mirror of
https://github.com/izzy2lost/Diddy-Kong-Racing.git
synced 2026-06-19 01:16:26 -07:00
Split up fonts/fonts.json into different files so each font can have a string ID.
This commit is contained in:
@@ -965,7 +965,8 @@
|
||||
"build-id": "ASSET_FONTS",
|
||||
"type": "Fonts",
|
||||
"folder": "fonts",
|
||||
"filenames": ["fonts"]
|
||||
"filenames": ["fonts"],
|
||||
"font-names": [ "FunFont", "SmallFont", "BigFont", "SubtitleFont" ]
|
||||
},
|
||||
{
|
||||
"build-id": "ASSET_BINARY_45",
|
||||
@@ -1039,4 +1040,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4816,6 +4816,15 @@ typedef enum {
|
||||
ASSET_PARTICLE_BEHAVIORS_74
|
||||
} AssetParticleBehaviorsEnum;
|
||||
|
||||
/********** ASSET_FONTS **********/
|
||||
|
||||
typedef enum {
|
||||
ASSET_FONTS_FUNFONT,
|
||||
ASSET_FONTS_SMALLFONT,
|
||||
ASSET_FONTS_BIGFONT,
|
||||
ASSET_FONTS_SUBTITLEFONT
|
||||
} AssetFontsEnum;
|
||||
|
||||
/********** ASSET_TTGHOSTS **********/
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -11,7 +11,12 @@
|
||||
#define SIZEOF_CHAR_NODE 8
|
||||
|
||||
BuildFonts::BuildFonts(std::string srcPath, std::string dstPath) {
|
||||
int numberOfFonts = get_array_length_from_json(srcPath, "fonts");
|
||||
|
||||
std::string fontFolderPath = get_directory_from_full_path(srcPath);
|
||||
|
||||
std::vector<std::string> fontIds = get_array_from_section("ASSET_FONTS", "fonts-order");
|
||||
int numberOfFonts = fontIds.size();
|
||||
|
||||
std::vector<uint8_t> out(align16(SIZEOF_FONT * numberOfFonts + SIZEOF_FONTS_HEADER));
|
||||
|
||||
// Write header.
|
||||
@@ -19,21 +24,23 @@ BuildFonts::BuildFonts(std::string srcPath, std::string dstPath) {
|
||||
|
||||
// Write fonts.
|
||||
for(int font = 0; font < numberOfFonts; font++) {
|
||||
std::string fontPath = fontFolderPath + "/" + get_string_from_json(srcPath, "fonts", fontIds[font]);
|
||||
|
||||
int fontOffset = font * SIZEOF_FONT + SIZEOF_FONTS_HEADER;
|
||||
|
||||
insert_ascii(out, fontOffset, get_string_from_json(srcPath, "fonts", font, "name"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x20, get_int_from_json(srcPath, "fonts", font, "fixed-width"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x22, get_int_from_json(srcPath, "fonts", font, "y-offset"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x24, get_int_from_json(srcPath, "fonts", font, "special-character-width"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x26, get_int_from_json(srcPath, "fonts", font, "tab-width"));
|
||||
insert_ascii(out, fontOffset + 0x28, get_string_from_json(srcPath, "fonts", font, "unknown-text"));
|
||||
insert_ascii(out, fontOffset, get_string_from_json(fontPath, "name"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x20, get_int_from_json(fontPath, "fixed-width"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x22, get_int_from_json(fontPath, "y-offset"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x24, get_int_from_json(fontPath, "special-character-width"));
|
||||
write_big_endian_halfword(out, fontOffset + 0x26, get_int_from_json(fontPath, "tab-width"));
|
||||
insert_ascii(out, fontOffset + 0x28, get_string_from_json(fontPath, "unknown-text"));
|
||||
|
||||
int numberOfTextures = get_array_length_from_json(srcPath, "fonts", font, "textures");
|
||||
int numberOfTextures = get_array_length_from_json(fontPath, "textures");
|
||||
int texOffset = fontOffset + 0x40;
|
||||
int texIndex = 0;
|
||||
// Write texture ids.
|
||||
for(; texIndex < numberOfTextures; texIndex++) {
|
||||
write_big_endian_halfword(out, texOffset, get_tex_2d_index_from_build_id(get_string_from_json(srcPath, "fonts", font, "textures", texIndex)));
|
||||
write_big_endian_halfword(out, texOffset, get_tex_2d_index_from_build_id(get_string_from_json(fontPath, "textures", texIndex)));
|
||||
texOffset += 2;
|
||||
}
|
||||
// Fill rest of the space with -1.
|
||||
@@ -42,14 +49,14 @@ BuildFonts::BuildFonts(std::string srcPath, std::string dstPath) {
|
||||
texOffset += 2;
|
||||
}
|
||||
|
||||
std::string encoding = get_string_from_json(srcPath, "fonts", font, "encoding", "type");
|
||||
std::string encoding = get_string_from_json(fontPath, "encoding", "type");
|
||||
make_uppercase(encoding);
|
||||
|
||||
// Write character nodes
|
||||
if(encoding == "ASCII") {
|
||||
write_ascii_char_nodes(out, srcPath, fontOffset + 0x100, font);
|
||||
write_ascii_char_nodes(out, fontPath, fontOffset + 0x100);
|
||||
} else if(encoding == "CUSTOM") {
|
||||
write_custom_char_nodes(out, srcPath, fontOffset + 0x100, font);
|
||||
write_custom_char_nodes(out, fontPath, fontOffset + 0x100);
|
||||
} else {
|
||||
display_error_and_abort("Unsupported font encoding type: \"", encoding, "\"");
|
||||
}
|
||||
@@ -63,18 +70,18 @@ BuildFonts::~BuildFonts() {
|
||||
|
||||
}
|
||||
|
||||
void write_char_node(std::vector<uint8_t> &out, std::string srcPath, int nodeOffset, int font, std::string &chr) {
|
||||
out[nodeOffset] = get_int_from_json(srcPath, "fonts", font, "characters", chr, "tex-index");
|
||||
out[nodeOffset + 1] = get_int_from_json(srcPath, "fonts", font, "characters", chr, "char-width");
|
||||
out[nodeOffset + 2] = get_int_from_json(srcPath, "fonts", font, "characters", chr, "offset", 0); // X offset
|
||||
out[nodeOffset + 3] = get_int_from_json(srcPath, "fonts", font, "characters", chr, "offset", 1); // Y offset
|
||||
out[nodeOffset + 4] = get_int_from_json(srcPath, "fonts", font, "characters", chr, "uv", 0); // U coordinate
|
||||
out[nodeOffset + 5] = get_int_from_json(srcPath, "fonts", font, "characters", chr, "uv", 1); // V coordinate
|
||||
out[nodeOffset + 6] = get_int_from_json(srcPath, "fonts", font, "characters", chr, "tex-size", 0); // Width
|
||||
out[nodeOffset + 7] = get_int_from_json(srcPath, "fonts", font, "characters", chr, "tex-size", 1); // Height
|
||||
void write_char_node(std::vector<uint8_t> &out, std::string fontPath, int nodeOffset, std::string &chr) {
|
||||
out[nodeOffset] = get_int_from_json(fontPath, "characters", chr, "tex-index");
|
||||
out[nodeOffset + 1] = get_int_from_json(fontPath, "characters", chr, "char-width");
|
||||
out[nodeOffset + 2] = get_int_from_json(fontPath, "characters", chr, "offset", 0); // X offset
|
||||
out[nodeOffset + 3] = get_int_from_json(fontPath, "characters", chr, "offset", 1); // Y offset
|
||||
out[nodeOffset + 4] = get_int_from_json(fontPath, "characters", chr, "uv", 0); // U coordinate
|
||||
out[nodeOffset + 5] = get_int_from_json(fontPath, "characters", chr, "uv", 1); // V coordinate
|
||||
out[nodeOffset + 6] = get_int_from_json(fontPath, "characters", chr, "tex-size", 0); // Width
|
||||
out[nodeOffset + 7] = get_int_from_json(fontPath, "characters", chr, "tex-size", 1); // Height
|
||||
}
|
||||
|
||||
void BuildFonts::write_ascii_char_nodes(std::vector<uint8_t> &out, std::string srcPath, int offset, int font) {
|
||||
void BuildFonts::write_ascii_char_nodes(std::vector<uint8_t> &out, std::string fontPath, int offset) {
|
||||
for(int node = CHAR_NODE_START_OFFSET; node < CHAR_NODE_END_OFFSET; node++) {
|
||||
std::string chr;
|
||||
if(node == 127) {
|
||||
@@ -87,20 +94,20 @@ void BuildFonts::write_ascii_char_nodes(std::vector<uint8_t> &out, std::string s
|
||||
chr = (char)node;
|
||||
}
|
||||
int nodeOffset = offset + (node - CHAR_NODE_START_OFFSET) * SIZEOF_CHAR_NODE;
|
||||
write_char_node(out, srcPath, nodeOffset, font, chr);
|
||||
write_char_node(out, fontPath, nodeOffset, chr);
|
||||
}
|
||||
}
|
||||
|
||||
void BuildFonts::write_custom_char_nodes(std::vector<uint8_t> &out, std::string srcPath, int offset, int font) {
|
||||
void BuildFonts::write_custom_char_nodes(std::vector<uint8_t> &out, std::string fontPath, int offset) {
|
||||
int index = 0;
|
||||
std::vector<std::string> order = get_array_from_json(srcPath, "fonts", font, "encoding", "order");
|
||||
std::vector<std::string> order = get_array_from_json(fontPath, "encoding", "order");
|
||||
for(std::string &chr : order) {
|
||||
if(index >= NUMBER_OF_CHAR_NODES) {
|
||||
std::string fontName = get_string_from_json(srcPath, "fonts", font, "name");
|
||||
std::string fontName = get_string_from_json(fontPath, "name");
|
||||
display_error_and_abort("Too many character nodes in ", fontName, ". The limit is ", NUMBER_OF_CHAR_NODES);
|
||||
}
|
||||
int nodeOffset = offset + (index++ * SIZEOF_CHAR_NODE);
|
||||
write_char_node(out, srcPath, nodeOffset, font, chr);
|
||||
write_char_node(out, fontPath, nodeOffset, chr);
|
||||
}
|
||||
// Set the rest of the nodes to show nothing.
|
||||
while(index < NUMBER_OF_CHAR_NODES) {
|
||||
|
||||
@@ -8,6 +8,6 @@ public:
|
||||
BuildFonts(std::string srcPath, std::string dstPath);
|
||||
~BuildFonts();
|
||||
private:
|
||||
void write_ascii_char_nodes(std::vector<uint8_t> &out, std::string srcPath, int offset, int font);
|
||||
void write_custom_char_nodes(std::vector<uint8_t> &out, std::string srcPath, int offset, int font);
|
||||
void write_ascii_char_nodes(std::vector<uint8_t> &out, std::string srcPath, int offset);
|
||||
void write_custom_char_nodes(std::vector<uint8_t> &out, std::string srcPath, int offset);
|
||||
};
|
||||
|
||||
@@ -92,7 +92,12 @@ void BuildGameText::build_textbox(std::vector<uint8_t> &out, std::string &srcPat
|
||||
if(cmdType == "Text") {
|
||||
write_ascii(out, get_string_from_json(srcPath, "pages", page, cmd, "value"));
|
||||
} else if(cmdType == "SetFont") {
|
||||
write_basic_command(out, 3, get_int_from_json(srcPath, "pages", page, cmd, "value"));
|
||||
std::string fontId = get_string_from_json(srcPath, "pages", page, cmd, "value");
|
||||
int fontIndex = get_index_of_string_array_value_from_section("ASSET_FONTS", fontId, "fonts-order");
|
||||
if(fontIndex == -1) {
|
||||
display_error_and_abort("Could not find the font \"", fontId, "\" in the \"fonts-order\" array in asset_fonts.json.");
|
||||
}
|
||||
write_basic_command(out, 3, fontIndex);
|
||||
} else if(cmdType == "SetBorder") {
|
||||
write_basic_command_4_args(out, 4,
|
||||
get_int_from_json(srcPath, "pages", page, cmd, "value", "Left"),
|
||||
|
||||
@@ -127,6 +127,19 @@ inline int get_array_length_from_section(std::string sectionName, FirstKey const
|
||||
return json_get(*json, key, rest_keys...).length();
|
||||
}
|
||||
|
||||
template<typename FirstKey, typename ...RestKeys>
|
||||
inline int get_index_of_string_array_value_from_section(std::string sectionName, std::string value, FirstKey const& key, RestKeys const&... rest_keys) {
|
||||
json::JSON *json = get_section_json(sectionName);
|
||||
|
||||
std::vector<std::string> arr = get_array_from_section(sectionName, key, rest_keys...);
|
||||
for(int i = 0; i < arr.size(); i++) {
|
||||
if(arr[i] == value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1; // Value not found in array.
|
||||
}
|
||||
|
||||
template<typename FirstKey, typename ...RestKeys>
|
||||
inline bool section_has_key(std::string sectionName, FirstKey const& key, RestKeys const&... rest_keys) {
|
||||
json::JSON *json = get_section_json(sectionName);
|
||||
@@ -137,4 +150,3 @@ inline bool section_has_key(std::string sectionName, FirstKey const& key, RestKe
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -297,6 +297,18 @@ void ExtractConfig::extract_asset_sections(int &romOffset) {
|
||||
}
|
||||
sectionOut["filename"] = filename + get_extension_from_type(type);
|
||||
extractions.push_back(ExtractInfo(build_id, type, folder, filename, sectionsData[i]));
|
||||
|
||||
if(type == "Fonts") {
|
||||
//sectionOut["fonts"] = json::Object();
|
||||
sectionOut["fonts-order"] = json::Array();
|
||||
for(auto& fontName : section["font-names"].ArrayRange()) {
|
||||
std::string fontid = "ASSET_FONTS_" + fontName.ToString();
|
||||
make_uppercase(fontid);
|
||||
//sectionOut["fonts"][fontid] = fontName.ToString() + ".json";
|
||||
sectionOut["fonts-order"].append(fontid);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (type == "Table") {
|
||||
sectionOut["for"] = section["for"];
|
||||
}
|
||||
@@ -323,7 +335,7 @@ void write_vanilla_warning_file(std::string baseDirectory) {
|
||||
|
||||
void ExtractConfig::execute_extraction() {
|
||||
// These braces are important, because I want the ThreadPool to call its destructor by going out of scope.
|
||||
//{
|
||||
{
|
||||
ThreadPool pool(std::thread::hardware_concurrency());
|
||||
//ThreadPool pool(1);
|
||||
|
||||
@@ -352,7 +364,7 @@ void ExtractConfig::execute_extraction() {
|
||||
} else if(type == "Sprites") {
|
||||
ExtractSprite(key, data, outFilepath + ".json", configJSON);
|
||||
} else if(type == "Fonts") {
|
||||
ExtractFonts(key, data, outFilepath + ".json", configJSON);
|
||||
ExtractFonts(key, data, outFilepath + ".json", folder, configJSON);
|
||||
} else if(is_binary_type(type)) {
|
||||
ExtractBinary(key, data, outFilepath + ".bin");
|
||||
} else if(is_compressed_type(type)) {
|
||||
@@ -363,7 +375,7 @@ void ExtractConfig::execute_extraction() {
|
||||
}
|
||||
});
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtractConfig::extract() {
|
||||
|
||||
@@ -1,21 +1,29 @@
|
||||
#include "extract_fonts.h"
|
||||
|
||||
ExtractFonts::ExtractFonts(std::string key, std::vector<uint8_t> data, std::string outFilepath, json::JSON &configJSON)
|
||||
#define SECTION_TEXTURE_2D_INDEX 4
|
||||
#define SECTION_FONTS_INDEX 44
|
||||
|
||||
#define GAME_FONTS_FOLDERNAME "game_fonts"
|
||||
|
||||
ExtractFonts::ExtractFonts(std::string key, std::vector<uint8_t> data, std::string outFilepath, std::string folder, json::JSON &configJSON)
|
||||
: Extract(key, data, outFilepath) {
|
||||
json::JSON out = json::Object();
|
||||
|
||||
out["type"] = "Fonts";
|
||||
|
||||
out["fonts"] = json::Array();
|
||||
|
||||
//out["fonts-folder"] = GAME_FONTS_FOLDERNAME;
|
||||
create_directory(folder + "/" + GAME_FONTS_FOLDERNAME);
|
||||
out["fonts"] = json::Object();
|
||||
|
||||
int numberOfFonts = get_big_endian_word(data, 0);
|
||||
|
||||
for(int i = 0; i < numberOfFonts; i++) {
|
||||
int offset = (i * 0x400) + 4; // Offset in file for this font.
|
||||
|
||||
std::string fontName = get_ascii(data, offset);
|
||||
std::string fontId = "ASSET_FONTS_" + fontName;
|
||||
make_uppercase(fontId);
|
||||
|
||||
json::JSON font = json::Object();
|
||||
|
||||
font["name"] = get_ascii(data, offset);
|
||||
font["name"] = fontName;
|
||||
font["unknown-text"] = get_ascii(data, offset + 0x28);
|
||||
font["fixed-width"] = get_big_endian_halfword(data, offset + 0x20);
|
||||
font["y-offset"] = get_big_endian_halfword(data, offset + 0x22);
|
||||
@@ -27,7 +35,8 @@ ExtractFonts::ExtractFonts(std::string key, std::vector<uint8_t> data, std::stri
|
||||
int texOffset = offset + 0x40;
|
||||
int16_t texIndex = get_big_endian_halfword(data, texOffset);
|
||||
while(texIndex != -1) {
|
||||
font["textures"].append(configJSON["assets"]["sections"][4]["child-build-ids"][texIndex]);
|
||||
json::JSON textureId = configJSON["assets"]["sections"][SECTION_TEXTURE_2D_INDEX]["child-build-ids"][texIndex];
|
||||
font["textures"].append(textureId);
|
||||
texOffset += 2;
|
||||
texIndex = get_big_endian_halfword(data, texOffset);
|
||||
}
|
||||
@@ -63,10 +72,15 @@ ExtractFonts::ExtractFonts(std::string key, std::vector<uint8_t> data, std::stri
|
||||
|
||||
font["encoding"] = json::Object();
|
||||
font["encoding"]["type"] = "ASCII";
|
||||
|
||||
std::string fontJsonFilename = GAME_FONTS_FOLDERNAME;
|
||||
fontJsonFilename += "/" + fontName + ".json";
|
||||
|
||||
out["fonts"][fontId] = fontJsonFilename;
|
||||
|
||||
out["fonts"].append(font);
|
||||
write_json(font, folder + "/" + fontJsonFilename);
|
||||
}
|
||||
|
||||
out["type"] = "Fonts";
|
||||
write_json(out, outFilepath);
|
||||
print_extracted();
|
||||
}
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
|
||||
class ExtractFonts : Extract {
|
||||
public:
|
||||
ExtractFonts(std::string key, std::vector<uint8_t> data, std::string outFilepath, json::JSON &configJSON);
|
||||
ExtractFonts(std::string key, std::vector<uint8_t> data, std::string outFilepath, std::string folder, json::JSON &configJSON);
|
||||
~ExtractFonts();
|
||||
};
|
||||
|
||||
@@ -100,7 +100,7 @@ void ExtractGameText::extract_textbox(json::JSON &out, std::vector<uint8_t> &dat
|
||||
break;
|
||||
case 3:
|
||||
cmd["command"] = "SetFont";
|
||||
cmd["value"] = data[offset++];
|
||||
cmd["value"] = get_string_from_section("ASSET_FONTS", "fonts-order", data[offset++]);
|
||||
break;
|
||||
case 4:
|
||||
cmd["command"] = "SetBorder";
|
||||
|
||||
@@ -23,9 +23,14 @@ AssetEnumsHeader::AssetEnumsHeader(std::string dstFolder) {
|
||||
std::vector<std::string> sectionOrder = get_section_order(sectionName);
|
||||
write_order_section(out, sectionName, sectionOrder);
|
||||
}
|
||||
if(get_string_from_section(sectionName, "type") == "MenuText") {
|
||||
std::string sectionType = get_string_from_section(sectionName, "type");
|
||||
if(sectionType == "MenuText") {
|
||||
std::vector<std::string> menuTextBuildIds = get_array_from_section(sectionName, "menu-text-build-ids");
|
||||
write_order_section(out, sectionName + "_IDS", menuTextBuildIds);
|
||||
} else if (sectionType == "Fonts") {
|
||||
std::vector<std::string> fonts = get_array_from_section(sectionName, "fonts-order");
|
||||
write_header_comment(out, sectionName);
|
||||
write_order_section(out, sectionName, fonts);
|
||||
}
|
||||
}
|
||||
out << "#endif " << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user