diff --git a/tools/Makefile b/tools/Makefile index 42d9935b..3bc54e2e 100755 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,6 +1,7 @@ CC := gcc CXX := g++ CFLAGS := -I . -Wall -Wextra -Wno-unused-parameter -pedantic -std=c99 -O2 -s +CXXFLAGS := --std=c++17 -lstdc++fs -lcrypto -lssl -lpthread LDFLAGS := -lm PROGRAMS := n64crc CXX_PROGRAMS := dkr_assets_tool @@ -37,12 +38,12 @@ dkr_assets_tool_OBJ_FILES := $(foreach file,$(dkr_assets_tool_C_FILES),$(BUILD_D DUMMY != mkdir -p $(sort $(dir $(dkr_assets_tool_OBJ_FILES))) $(BUILD_DIR)/%.o: %.c - $(CXX) -c $^ -o $@ --std=c++17 -lstdc++fs -lcrypto -lssl -lpthread $(LDFLAGS) + $(CXX) -c $^ -o $@ $(CXXFLAGS) $(LDFLAGS) $(BUILD_DIR)/%.o: %.cpp - $(CXX) -c $< -o $@ --std=c++17 -lstdc++fs -lcrypto -lssl -lpthread $(LDFLAGS) + $(CXX) -c $< -o $@ $(CXXFLAGS) $(LDFLAGS) dkr_assets_tool: $(dkr_assets_tool_OBJ_FILES) - $(CXX) $^ -o $@ --std=c++17 -lstdc++fs -lcrypto -lssl -lpthread $(LDFLAGS) + $(CXX) $^ -o $@ $(CXXFLAGS) $(LDFLAGS) .PHONY: all clean distclean default 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 b1abb6b6..58cf8b8a 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 @@ -13,26 +13,26 @@ BuildGameText::BuildGameText(std::string srcPath, std::string dstPath) { // TODO: Figure this out! - /* + std::string textType = get_string_from_json(srcPath, "text-type"); if(textType == "Dialog") { - build_dialog(out, inputJSON); + // This is temporary until the game text format is figured out + int numRawBytes = get_array_length_from_json(srcPath, "raw"); + + for(int i = 0; i < numRawBytes; i++) { + out.push_back(get_int_from_json(srcPath, "raw", i)); + } + //build_dialog(out, srcPath); } else { - build_textbox(out, inputJSON); + build_textbox(out, srcPath); } - */ - // This is temporary until the game text format is figured out - int numRawBytes = get_array_length_from_json(srcPath, "raw"); - - for(int i = 0; i < numRawBytes; i++) { - out.push_back(get_int_from_json(srcPath, "raw", i)); - } - + while(out.size() % 8 != 0) { out.push_back(0); // Make sure the data is 8-byte aligned. } + write_binary_file(out, dstPath); } @@ -41,7 +41,7 @@ BuildGameText::~BuildGameText() { } /* -void BuildGameText::build_dialog(std::vector &out, json::JSON inputJSON) { +void BuildGameText::build_dialog(std::vector &out, std::string &srcPath) { int numberOfLines = GET_ARRAY_LENGTH("lines"); for(int i = 0; i < numberOfLines; i++) { if(inputJSON["lines"][i].JSONType() == json::JSON::Class::String) { @@ -68,6 +68,7 @@ void BuildGameText::build_dialog(std::vector &out, json::JSON inputJSON //} } } +*/ void write_basic_command(std::vector &out, uint8_t cmdId, uint8_t value) { out.push_back(cmdId); @@ -82,10 +83,10 @@ void write_basic_command_4_args(std::vector &out, uint8_t cmdId, uint8_ out.push_back(d); } -void BuildGameText::build_textbox(std::vector &out, json::JSON inputJSON) { - int numberOfPages = GET_ARRAY_LENGTH("pages"); +void BuildGameText::build_textbox(std::vector &out, std::string &srcPath) { + int numberOfPages = get_array_length_from_json(srcPath, "pages"); for(int page = 0; page < numberOfPages; page++) { - int numberOfCommandsInPage = GET_ARRAY_LENGTH("pages", page); + int numberOfCommandsInPage = get_array_length_from_json(srcPath, "pages", page); for(int cmd = 0; cmd < numberOfCommandsInPage; cmd++) { std::string cmdType = get_string_from_json(srcPath, "pages", page, cmd, "command"); if(cmdType == "Text") { @@ -107,7 +108,7 @@ void BuildGameText::build_textbox(std::vector &out, json::JSON inputJSO get_int_from_json(srcPath, "pages", page, cmd, "value", "alpha") ); } else if(cmdType == "SetAlignment") { - write_basic_command(out, 6, get_string_from_json(srcPath, "pages", page, cmd, "value") == "ALIGN_CENTER" ? 0 : 4); + write_basic_command(out, 6, get_string_from_json(srcPath, "pages", page, cmd, "value") == "Center" ? 0 : 4); } else if(cmdType == "Unknown") { write_basic_command(out, 7, get_int_from_json(srcPath, "pages", page, cmd, "value")); } else if(cmdType == "AddVerticalSpacing") { @@ -117,7 +118,7 @@ void BuildGameText::build_textbox(std::vector &out, json::JSON inputJSO } else if(cmdType == "SetTimer") { write_basic_command(out, 10, get_int_from_json(srcPath, "pages", page, cmd, "value")); } else if(cmdType == "AllowUserInput") { - write_basic_command(out, 10, GET_BOOL("pages", page, cmd, "value") ? 1 : 0); + write_basic_command(out, 11, get_bool_from_json(srcPath, "pages", page, cmd, "value") ? 1 : 0); } } if(page < numberOfPages - 1) { @@ -125,4 +126,3 @@ void BuildGameText::build_textbox(std::vector &out, json::JSON inputJSO } } } -*/ diff --git a/tools/dkr_assets_tool_classes/builder/build_files/build_gametext.h b/tools/dkr_assets_tool_classes/builder/build_files/build_gametext.h index 64b47641..d8a3cbbb 100644 --- a/tools/dkr_assets_tool_classes/builder/build_files/build_gametext.h +++ b/tools/dkr_assets_tool_classes/builder/build_files/build_gametext.h @@ -8,7 +8,7 @@ public: ~BuildGameText(); private: /* - void build_dialog(std::vector &out, json::JSON &inputJSON); - void build_textbox(std::vector &out, json::JSON &inputJSON); + void build_dialog(std::vector &out, std::string &srcPath); */ + void build_textbox(std::vector &out, std::string &srcPath); }; diff --git a/tools/dkr_assets_tool_classes/common/util/enumHelper.cpp b/tools/dkr_assets_tool_classes/common/util/enumHelper.cpp index 9da21930..da01620c 100644 --- a/tools/dkr_assets_tool_classes/common/util/enumHelper.cpp +++ b/tools/dkr_assets_tool_classes/common/util/enumHelper.cpp @@ -123,30 +123,33 @@ void load_enums_cache() { } } +std::mutex enumsMutex; + void make_sure_enums_are_loaded() { - if(hasLoadedEnums) { - return; - } - std::string assetsFolderPath = get_asset_folder_path(); - ensure_that_path_exists("build/"); // Make sure build folder exists - if(path_exists(ENUMS_CACHE_PATH)) { - load_enums_cache(); - } else { - // Generate enums map - path_must_exist("include/enums.h"); - std::string enumsIncludeText = read_text_file("include/enums.h"); - std::regex enumRegex("enum ([^\\s{]+)\\s*[{]((?:.*\\n)*?)[}]"); - std::smatch sm; - std::string text = enumsIncludeText; - while (regex_search(text, sm, enumRegex)) { - std::string enumName = sm[1]; - std::string enumValuesText = sm[2]; - get_enum_values(enumName, enumValuesText); - text = sm.suffix(); + enumsMutex.lock(); + if(!hasLoadedEnums) { + std::string assetsFolderPath = get_asset_folder_path(); + ensure_that_path_exists("build/"); // Make sure build folder exists + if(path_exists(ENUMS_CACHE_PATH)) { + load_enums_cache(); + } else { + // Generate enums map + path_must_exist("include/enums.h"); + std::string enumsIncludeText = read_text_file("include/enums.h"); + std::regex enumRegex("enum ([^\\s{]+)\\s*[{]((?:.*\\n)*?)[}]"); + std::smatch sm; + std::string text = enumsIncludeText; + while (regex_search(text, sm, enumRegex)) { + std::string enumName = sm[1]; + std::string enumValuesText = sm[2]; + get_enum_values(enumName, enumValuesText); + text = sm.suffix(); + } + save_enums_cache(); } - save_enums_cache(); + hasLoadedEnums = true; } - hasLoadedEnums = true; + enumsMutex.unlock(); } std::string get_enum_string_from_value(std::string enumName, int value) { diff --git a/tools/dkr_assets_tool_classes/common/util/enumHelper.h b/tools/dkr_assets_tool_classes/common/util/enumHelper.h index 043aa88b..6e31cc41 100644 --- a/tools/dkr_assets_tool_classes/common/util/enumHelper.h +++ b/tools/dkr_assets_tool_classes/common/util/enumHelper.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "../../libs/calculator.hpp" diff --git a/tools/dkr_assets_tool_classes/common/util/fileHelper.cpp b/tools/dkr_assets_tool_classes/common/util/fileHelper.cpp index da7463c1..b72c57bd 100644 --- a/tools/dkr_assets_tool_classes/common/util/fileHelper.cpp +++ b/tools/dkr_assets_tool_classes/common/util/fileHelper.cpp @@ -64,8 +64,7 @@ bool path_exists(std::string path) { void path_must_exist(std::string path) { if(!fs::exists(path)) { - std::cout << "Error: Path \"" << path << "\" does not exist!" << std::endl; - throw 1; + display_error_and_abort("Error: Path \"", path, "\" does not exist!"); } } diff --git a/tools/dkr_assets_tool_classes/common/util/fileHelper.h b/tools/dkr_assets_tool_classes/common/util/fileHelper.h index 6021b2d0..68c9898b 100644 --- a/tools/dkr_assets_tool_classes/common/util/fileHelper.h +++ b/tools/dkr_assets_tool_classes/common/util/fileHelper.h @@ -12,6 +12,8 @@ #include namespace fs = std::filesystem; +#include "errorHelper.h" + bool is_asset_folder_path_defined(); void set_assets_folder_path(std::string path); std::string get_asset_folder_path(); diff --git a/tools/dkr_assets_tool_classes/common/util/jsonHelper.cpp b/tools/dkr_assets_tool_classes/common/util/jsonHelper.cpp index ee5075a9..35bdeed8 100644 --- a/tools/dkr_assets_tool_classes/common/util/jsonHelper.cpp +++ b/tools/dkr_assets_tool_classes/common/util/jsonHelper.cpp @@ -15,6 +15,7 @@ std::unordered_map jsonFileCache; json::JSON load_assets_json(std::string assetsFolder, std::string jsonName) { std::string jsonFilepath = assetsFolder + "/" + jsonName; + path_must_exist(jsonFilepath); return json::JSON::Load(read_text_file(jsonFilepath)); } @@ -25,25 +26,32 @@ void write_json(json::JSON &jsonData, std::string filename) { myfile.close(); } +std::mutex assetsJsonMutex; + void make_sure_assets_json_is_loaded() { - if(hasLoadedAssetsJson) { - return; + assetsJsonMutex.lock(); + if(!hasLoadedAssetsJson) { + if(!is_asset_folder_path_defined()) { + display_error_and_abort("assetsFolderPath not defined! Make sure set_assets_folder_path() is called somewhere!"); + } + std::string assetsJsonPath = get_asset_folder_path() + "/" + get_version() + "/" + ASSETS_FILENAME; + path_must_exist(assetsJsonPath); + std::string assetsJsonText = read_text_file(assetsJsonPath); + assetsJson = json::JSON::Load(assetsJsonText); + hasLoadedAssetsJson = true; } - if(!is_asset_folder_path_defined()) { - std::cout << "assetsFolderPath not defined! Make sure set_assets_folder_path() is called somewhere!" << std::endl; - throw 1; - } - std::string assetsJsonPath = get_asset_folder_path() + "/" + get_version() + "/" + ASSETS_FILENAME; - path_must_exist(assetsJsonPath); - std::string assetsJsonText = read_text_file(assetsJsonPath); - assetsJson = json::JSON::Load(assetsJsonText); - hasLoadedAssetsJson = true; + assetsJsonMutex.unlock(); } + +std::mutex sectionJsonMutex; + json::JSON *get_section_json(std::string sectionName) { make_sure_assets_json_is_loaded(); + sectionJsonMutex.lock(); std::string assetsFolderPath = get_asset_folder_path() + "/" + get_version(); if(sectionName == lastSectionName) { + sectionJsonMutex.unlock(); return lastSection; } else if(sectionCache.find(sectionName) == sectionCache.end()) { // section not found in cache, so it needs to be loaded/defined! @@ -51,13 +59,16 @@ json::JSON *get_section_json(std::string sectionName) { if(assetSection.JSONType() == json::JSON::Class::String) { std::string sectionJsonLocalPath = assetsJson["assets"]["sections"][sectionName].ToString(); make_lowercase(sectionJsonLocalPath); - sectionCache[sectionName] = json::JSON::Load(read_text_file(assetsFolderPath + "/" + sectionJsonLocalPath)); + std::string jsonPath = assetsFolderPath + "/" + sectionJsonLocalPath; + path_must_exist(jsonPath); + sectionCache[sectionName] = json::JSON::Load(read_text_file(jsonPath)); } else { sectionCache[sectionName] = assetSection; } } lastSectionName = sectionName; lastSection = §ionCache[sectionName]; + sectionJsonMutex.unlock(); return lastSection; } diff --git a/tools/dkr_assets_tool_classes/common/util/jsonHelper.h b/tools/dkr_assets_tool_classes/common/util/jsonHelper.h index a249c418..dcc86893 100644 --- a/tools/dkr_assets_tool_classes/common/util/jsonHelper.h +++ b/tools/dkr_assets_tool_classes/common/util/jsonHelper.h @@ -7,9 +7,12 @@ #include #include #include +#include + #include "../../libs/json.hpp" #include "fileHelper.h" +#include "errorHelper.h" void write_json(json::JSON &assetsJSON, std::string filename); json::JSON load_assets_json(std::string assetsFolder, std::string jsonName); diff --git a/tools/dkr_assets_tool_classes/extractor/config.cpp b/tools/dkr_assets_tool_classes/extractor/config.cpp index a0384fb4..8810b6dc 100644 --- a/tools/dkr_assets_tool_classes/extractor/config.cpp +++ b/tools/dkr_assets_tool_classes/extractor/config.cpp @@ -323,7 +323,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); @@ -363,7 +363,7 @@ void ExtractConfig::execute_extraction() { } }); } - } + //} } void ExtractConfig::extract() { 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 c9cfa906..384d6c7e 100644 --- a/tools/dkr_assets_tool_classes/extractor/extract/extract_gametext.cpp +++ b/tools/dkr_assets_tool_classes/extractor/extract/extract_gametext.cpp @@ -12,20 +12,17 @@ ExtractGameText::ExtractGameText(std::string key, std::vector data, std isDialog = (out["text-type"].ToString() == "Dialog"); } - // Uncomment this when the formats have been fully figured out. - /* if(isDialog) { - extract_dialog(data, data); + // Uncomment this when the formats have been fully figured out. + //extract_dialog(out, data); + // Remove this raw part when dialog has been figured out. + out["raw"] = json::Array(); + size_t dataLength = data.size(); + for(int i = 0; i < dataLength; i++) { + out["raw"].append(data[i]); + } } else { // Textbox - extract_textbox(data, data); - } - */ - - // This is temporary - out["raw"] = json::Array(); - size_t dataLength = data.size(); - for(int i = 0; i < dataLength; i++) { - out["raw"].append(data[i]); + extract_textbox(out, data); } write_json(out, outFilepath); @@ -123,7 +120,7 @@ void ExtractGameText::extract_textbox(json::JSON &out, std::vector &dat break; case 6: cmd["command"] = "SetAlignment"; - cmd["value"] = (data[offset++] == 0) ? "ALIGN_CENTER" : "ALIGN_LEFT"; + cmd["value"] = (data[offset++] == 0) ? "Center" : "Left"; break; case 7: cmd["command"] = "Unknown"; // Doesn't seem to do anything as far as I can tell. diff --git a/tools/dkr_assets_tool_classes/libs/json.hpp b/tools/dkr_assets_tool_classes/libs/json.hpp index 82208ee2..c5cd9a71 100644 --- a/tools/dkr_assets_tool_classes/libs/json.hpp +++ b/tools/dkr_assets_tool_classes/libs/json.hpp @@ -181,13 +181,19 @@ class JSON ~JSON() { switch( Type ) { case Class::Array: - delete Internal.List; + if(Internal.List != nullptr) { + delete Internal.List; + } break; case Class::Object: - delete Internal.Map; + if(Internal.Map != nullptr) { + delete Internal.Map; + } break; case Class::String: - delete Internal.String; + if(Internal.String != nullptr) { + delete Internal.String; + } break; default:; }