diff --git a/extract-ver/us_1.0.config.json b/extract-ver/us_1.0.config.json index 04314545..f9b5cbbe 100755 --- a/extract-ver/us_1.0.config.json +++ b/extract-ver/us_1.0.config.json @@ -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 @@ } ] } -} \ No newline at end of file +} diff --git a/include/asset_enums.h b/include/asset_enums.h index 89ca0005..5a7e746a 100644 --- a/include/asset_enums.h +++ b/include/asset_enums.h @@ -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 { diff --git a/tools/dkr_assets_tool_classes/builder/build_files/build_fonts.cpp b/tools/dkr_assets_tool_classes/builder/build_files/build_fonts.cpp index 6a434c8b..8ff9c281 100644 --- a/tools/dkr_assets_tool_classes/builder/build_files/build_fonts.cpp +++ b/tools/dkr_assets_tool_classes/builder/build_files/build_fonts.cpp @@ -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 fontIds = get_array_from_section("ASSET_FONTS", "fonts-order"); + int numberOfFonts = fontIds.size(); + std::vector 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 &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 &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 &out, std::string srcPath, int offset, int font) { +void BuildFonts::write_ascii_char_nodes(std::vector &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 &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 &out, std::string srcPath, int offset, int font) { +void BuildFonts::write_custom_char_nodes(std::vector &out, std::string fontPath, int offset) { int index = 0; - std::vector order = get_array_from_json(srcPath, "fonts", font, "encoding", "order"); + std::vector 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) { diff --git a/tools/dkr_assets_tool_classes/builder/build_files/build_fonts.h b/tools/dkr_assets_tool_classes/builder/build_files/build_fonts.h index c7b83bd6..6b125770 100644 --- a/tools/dkr_assets_tool_classes/builder/build_files/build_fonts.h +++ b/tools/dkr_assets_tool_classes/builder/build_files/build_fonts.h @@ -8,6 +8,6 @@ public: BuildFonts(std::string srcPath, std::string dstPath); ~BuildFonts(); private: - void write_ascii_char_nodes(std::vector &out, std::string srcPath, int offset, int font); - void write_custom_char_nodes(std::vector &out, std::string srcPath, int offset, int font); + void write_ascii_char_nodes(std::vector &out, std::string srcPath, int offset); + void write_custom_char_nodes(std::vector &out, std::string srcPath, int offset); }; diff --git a/tools/dkr_assets_tool_classes/builder/build_files/build_gametext.cpp b/tools/dkr_assets_tool_classes/builder/build_files/build_gametext.cpp index 58cf8b8a..7dee46c8 100644 --- a/tools/dkr_assets_tool_classes/builder/build_files/build_gametext.cpp +++ b/tools/dkr_assets_tool_classes/builder/build_files/build_gametext.cpp @@ -92,7 +92,12 @@ void BuildGameText::build_textbox(std::vector &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"), diff --git a/tools/dkr_assets_tool_classes/common/util/jsonHelper.h b/tools/dkr_assets_tool_classes/common/util/jsonHelper.h index dcc86893..1ca9b3b2 100644 --- a/tools/dkr_assets_tool_classes/common/util/jsonHelper.h +++ b/tools/dkr_assets_tool_classes/common/util/jsonHelper.h @@ -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 +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 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 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 } - diff --git a/tools/dkr_assets_tool_classes/extractor/config.cpp b/tools/dkr_assets_tool_classes/extractor/config.cpp index 8810b6dc..cfb4105d 100644 --- a/tools/dkr_assets_tool_classes/extractor/config.cpp +++ b/tools/dkr_assets_tool_classes/extractor/config.cpp @@ -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() { diff --git a/tools/dkr_assets_tool_classes/extractor/extract/extract_fonts.cpp b/tools/dkr_assets_tool_classes/extractor/extract/extract_fonts.cpp index aa930275..367bdcdb 100644 --- a/tools/dkr_assets_tool_classes/extractor/extract/extract_fonts.cpp +++ b/tools/dkr_assets_tool_classes/extractor/extract/extract_fonts.cpp @@ -1,21 +1,29 @@ #include "extract_fonts.h" -ExtractFonts::ExtractFonts(std::string key, std::vector 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 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 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 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(); } diff --git a/tools/dkr_assets_tool_classes/extractor/extract/extract_fonts.h b/tools/dkr_assets_tool_classes/extractor/extract/extract_fonts.h index 59c3f77e..f05b4e1d 100644 --- a/tools/dkr_assets_tool_classes/extractor/extract/extract_fonts.h +++ b/tools/dkr_assets_tool_classes/extractor/extract/extract_fonts.h @@ -4,6 +4,6 @@ class ExtractFonts : Extract { public: - ExtractFonts(std::string key, std::vector data, std::string outFilepath, json::JSON &configJSON); + ExtractFonts(std::string key, std::vector data, std::string outFilepath, std::string folder, json::JSON &configJSON); ~ExtractFonts(); }; diff --git a/tools/dkr_assets_tool_classes/extractor/extract/extract_gametext.cpp b/tools/dkr_assets_tool_classes/extractor/extract/extract_gametext.cpp index 384d6c7e..c72ab283 100644 --- a/tools/dkr_assets_tool_classes/extractor/extract/extract_gametext.cpp +++ b/tools/dkr_assets_tool_classes/extractor/extract/extract_gametext.cpp @@ -100,7 +100,7 @@ void ExtractGameText::extract_textbox(json::JSON &out, std::vector &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"; diff --git a/tools/dkr_assets_tool_classes/make_asset_files/asset_enums_header.cpp b/tools/dkr_assets_tool_classes/make_asset_files/asset_enums_header.cpp index 550cf62e..0c1b8f00 100644 --- a/tools/dkr_assets_tool_classes/make_asset_files/asset_enums_header.cpp +++ b/tools/dkr_assets_tool_classes/make_asset_files/asset_enums_header.cpp @@ -23,9 +23,14 @@ AssetEnumsHeader::AssetEnumsHeader(std::string dstFolder) { std::vector 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 menuTextBuildIds = get_array_from_section(sectionName, "menu-text-build-ids"); write_order_section(out, sectionName + "_IDS", menuTextBuildIds); + } else if (sectionType == "Fonts") { + std::vector fonts = get_array_from_section(sectionName, "fonts-order"); + write_header_comment(out, sectionName); + write_order_section(out, sectionName, fonts); } } out << "#endif " << std::endl;