diff --git a/tools/ZAPD/.gitrepo b/tools/ZAPD/.gitrepo index 04b472ce2d..be24b438e2 100644 --- a/tools/ZAPD/.gitrepo +++ b/tools/ZAPD/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/zeldaret/ZAPD.git branch = master - commit = 4f7b8393ec8a3abd59649c2ba669e951fb61f3d2 - parent = efb9badbf211c5d5065c1b25b58f0e0fe2d17ec4 + commit = a3363333d809e8089a55efc3ea32eaea9ddb8d8c + parent = 1cf11907fa8d636babba2df854850035f04bd4fc method = merge cmdver = 0.4.3 diff --git a/tools/ZAPD/ExporterTest/ExporterTest.vcxproj b/tools/ZAPD/ExporterTest/ExporterTest.vcxproj index a709a35091..839d451023 100644 --- a/tools/ZAPD/ExporterTest/ExporterTest.vcxproj +++ b/tools/ZAPD/ExporterTest/ExporterTest.vcxproj @@ -79,7 +79,7 @@ true - $(SolutionDir)\ZAPD\;$(SolutionDir)ZAPDUtils;$(SolutionDir)lib\tinyxml2;$(SolutionDir)lib\libgfxd;$(SolutionDir)lib\elfio;$(SolutionDir)lib\stb;$(ProjectDir);$(IncludePath) + $(ProjectDir)..\ZAPD\;$(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath) false @@ -120,6 +120,7 @@ true stdcpp17 stdc11 + MultiThreadedDebug Console @@ -156,4 +157,4 @@ - + \ No newline at end of file diff --git a/tools/ZAPD/ExporterTest/Main.cpp b/tools/ZAPD/ExporterTest/Main.cpp index 4f683a1ba3..07fdbeeced 100644 --- a/tools/ZAPD/ExporterTest/Main.cpp +++ b/tools/ZAPD/ExporterTest/Main.cpp @@ -1,7 +1,7 @@ -#include -#include -#include -#include +#include "CollisionExporter.h" +#include "Globals.h" +#include "RoomExporter.h" +#include "TextureExporter.h" enum class ExporterFileMode { diff --git a/tools/ZAPD/ExporterTest/RoomExporter.cpp b/tools/ZAPD/ExporterTest/RoomExporter.cpp index c4a6844fb5..6c5552d8f8 100644 --- a/tools/ZAPD/ExporterTest/RoomExporter.cpp +++ b/tools/ZAPD/ExporterTest/RoomExporter.cpp @@ -1,24 +1,24 @@ #include "RoomExporter.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "CollisionExporter.h" +#include "Utils/BinaryWriter.h" +#include "Utils/File.h" +#include "Utils/MemoryStream.h" +#include "ZRoom/Commands/SetCameraSettings.h" +#include "ZRoom/Commands/SetCollisionHeader.h" +#include "ZRoom/Commands/SetCsCamera.h" +#include "ZRoom/Commands/SetEchoSettings.h" +#include "ZRoom/Commands/SetEntranceList.h" +#include "ZRoom/Commands/SetLightingSettings.h" +#include "ZRoom/Commands/SetMesh.h" +#include "ZRoom/Commands/SetRoomBehavior.h" +#include "ZRoom/Commands/SetRoomList.h" +#include "ZRoom/Commands/SetSkyboxModifier.h" +#include "ZRoom/Commands/SetSkyboxSettings.h" +#include "ZRoom/Commands/SetSoundSettings.h" +#include "ZRoom/Commands/SetSpecialObjects.h" +#include "ZRoom/Commands/SetStartPositionList.h" +#include "ZRoom/Commands/SetTimeSettings.h" +#include "ZRoom/Commands/SetWind.h" void ExporterExample_Room::Save(ZResource* res, fs::path outPath, BinaryWriter* writer) { diff --git a/tools/ZAPD/ExporterTest/TextureExporter.h b/tools/ZAPD/ExporterTest/TextureExporter.h index ffe6001dca..41c4e79be2 100644 --- a/tools/ZAPD/ExporterTest/TextureExporter.h +++ b/tools/ZAPD/ExporterTest/TextureExporter.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "Utils/BinaryWriter.h" #include "ZResource.h" #include "ZTexture.h" diff --git a/tools/ZAPD/Jenkinsfile b/tools/ZAPD/Jenkinsfile index 051e5f9982..a12f30a253 100644 --- a/tools/ZAPD/Jenkinsfile +++ b/tools/ZAPD/Jenkinsfile @@ -22,13 +22,13 @@ pipeline { } } - stage('Checkout mm') { - steps{ - dir('mm') { - git url: 'https://github.com/zeldaret/mm.git' - } - } - } + // stage('Checkout mm') { + // steps{ + // dir('mm') { + // git url: 'https://github.com/zeldaret/mm.git' + // } + // } + // } } } @@ -51,20 +51,20 @@ pipeline { } } - stage('Setup MM') { - steps { - dir('mm') { - sh 'cp /usr/local/etc/roms/mm.us.rev1.z64 baserom.mm.us.rev1.z64' + // stage('Setup MM') { + // steps { + // dir('mm') { + // sh 'cp /usr/local/etc/roms/mm.us.rev1.z64 baserom.mm.us.rev1.z64' - // Identical to `make setup` except for copying our newer ZAPD.out into mm - sh 'make -C tools' - sh 'cp ../ZAPD.out tools/ZAPD/' - sh 'python3 tools/fixbaserom.py' - sh 'python3 tools/extract_baserom.py' - sh 'python3 extract_assets.py -t 4' - } - } - } + // // Identical to `make setup` except for copying our newer ZAPD.out into mm + // sh 'make -C tools' + // sh 'cp ../ZAPD.out tools/ZAPD/' + // sh 'python3 tools/fixbaserom.py' + // sh 'python3 tools/extract_baserom.py' + // sh 'python3 extract_assets.py -t 4' + // } + // } + // } } } @@ -78,14 +78,14 @@ pipeline { } } } - stage('Build mm') { - steps { - dir('mm') { - sh 'make -j disasm' - sh 'make -j all' - } - } - } + // stage('Build mm') { + // steps { + // dir('mm') { + // sh 'make -j disasm' + // sh 'make -j all' + // } + // } + // } } } } diff --git a/tools/ZAPD/README.md b/tools/ZAPD/README.md index e2764b6277..e2821bc28a 100644 --- a/tools/ZAPD/README.md +++ b/tools/ZAPD/README.md @@ -109,11 +109,51 @@ ZAPD also accepts the following list of extra parameters: - Could be useful for looking at raw data or testing. - Can be used only in `e` or `bsf` modes. - `-tm MODE`: Test Mode (enables certain experimental features). To enable it, set `MODE` to `1`. -- `-wno` / `--warn-no-offsets` : Enable warnings for nodes that dont have offsets specified. Takes priority over `-eno`/ `--error-no-offsets`. -- `-eno` / `--error-no-offsets` : Enable errors for nodes that dont have offsets specified. - `-se` / `--set-exporter` : Sets which exporter to use. -- `--gcc-compat` : Enables GCC compatible mode. Slower. +- `--gcc-compat` : Enables GCC compatibly mode. Slower. - `-s` / `--static` : Mark every asset as `static`. - This behaviour can be overridden per asset using `Static=` in the respective XML node. +- `-W...`: warning flags, see below Additionally, you can pass the flag `--version` to see the current ZAPD version. If that flag is passed, ZAPD will ignore any other parameter passed. + +### Warning flags + +ZAPD contains a variety of warning types, with similar syntax to GCC or Clang's compiler warnings. Warnings can have three levels: + +- Off (does not display anything) +- Warn (print a warning but continue processing) +- Err (behave like an error, i.e. print and throw an exception to crash ZAPD when occurs) + +Each warning type uses one of these by default, but can be modified with flags, similarly to GCC or Clang: + +- `-Wfoo` enables warnings of type `foo` +- `-Wno-foo` disables warnings of type `foo` +- `-Werror=foo` escalates `foo` to behave like an error +- `-Weverything` enables all warnings (they may be turned off using `-Wno-` flags afterwards) +- `-Werror` escalates all enabled warnings to errors + +All warning types currently implemented, with their default levels: + +| Warning type | Default level | Description | +| --------------------------- | ------------- | ------------------------------------------------------------------------ | +| `-Wdeprecated` | Warn | Deprecated features | +| `-Whardcoded-pointer` | Warn | ZAPD lacks the info to make a symbol, so must output a hardcoded pointer | +| `-Wintersection` | Warn | Two assets intersect | +| `-Winvalid-attribute-value` | Err | Attribute declared in XML is wrong | +| `-Winvalid-extracted-data` | Err | Extracted data does not have correct form | +| `-Winvalid-jpeg` | Err | JPEG file does not conform to the game's format requirements | +| `-Winvalid-png` | Err | Issues arising when processing PNG data | +| `-Winvalid-xml` | Err | XML has syntax errors | +| `-Wmissing-attribute` | Warn | Required attribute missing in XML tag | +| `-Wmissing-offsets` | Warn | Offset attribute missing in XML tag | +| `-Wmissing-segment` | Warn | Segment not given in File tag in XML | +| `-Wnot-implemented` | Warn | ZAPD does not currently support this feature | +| `-Wunaccounted` | Off | Large blocks of unaccounted | +| `-Wunknown-attribute` | Warn | Unknown attribute in XML entry tag | + +There are also errors that do not have a type, and cannot be disabled. + +For example, here we have invoked ZAPD in the usual way to extract using a (rather badly-written) XML, but escalating `-Wintersection` to an error: + +![ZAPD warnings example](docs/zapd_warning_example.png?raw=true) diff --git a/tools/ZAPD/ZAPD/Declaration.cpp b/tools/ZAPD/ZAPD/Declaration.cpp index d2a86ffcc5..be06b0bea7 100644 --- a/tools/ZAPD/ZAPD/Declaration.cpp +++ b/tools/ZAPD/ZAPD/Declaration.cpp @@ -92,20 +92,20 @@ std::string Declaration::GetNormalDeclarationStr() const if (isArray) { - if (arrayItemCntStr != "") + if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt)) { output += StringHelper::Sprintf("%s %s[%s];\n", varType.c_str(), varName.c_str(), arrayItemCntStr.c_str()); } - else if (arrayItemCnt == 0) - { - output += StringHelper::Sprintf("%s %s[] = {\n", varType.c_str(), varName.c_str()); - } - else + else if (arrayItemCnt != 0 && (IsStatic() || forceArrayCnt)) { output += StringHelper::Sprintf("%s %s[%i] = {\n", varType.c_str(), varName.c_str(), arrayItemCnt); } + else + { + output += StringHelper::Sprintf("%s %s[] = {\n", varType.c_str(), varName.c_str()); + } output += text + "\n"; } @@ -145,16 +145,16 @@ std::string Declaration::GetExternalDeclarationStr() const output += "static "; } - if (arrayItemCntStr != "") + if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt)) + output += StringHelper::Sprintf("%s %s[%s] = ", varType.c_str(), varName.c_str(), + arrayItemCntStr.c_str()); + else if (arrayItemCnt != 0 && (IsStatic() || forceArrayCnt)) output += - StringHelper::Sprintf("%s %s[%s] = {\n#include \"%s\"\n};", varType.c_str(), - varName.c_str(), arrayItemCntStr.c_str(), includePath.c_str()); - else if (arrayItemCnt != 0) - output += StringHelper::Sprintf("%s %s[%i] = {\n#include \"%s\"\n};", varType.c_str(), - varName.c_str(), arrayItemCnt, includePath.c_str()); + StringHelper::Sprintf("%s %s[%i] = ", varType.c_str(), varName.c_str(), arrayItemCnt); else - output += StringHelper::Sprintf("%s %s[] = {\n#include \"%s\"\n};", varType.c_str(), - varName.c_str(), includePath.c_str()); + output += StringHelper::Sprintf("%s %s[] = ", varType.c_str(), varName.c_str()); + + output += StringHelper::Sprintf("{\n#include \"%s\"\n};", includePath.c_str()); if (rightText != "") output += " " + rightText + ""; @@ -178,14 +178,16 @@ std::string Declaration::GetExternStr() const if (isArray) { - if (arrayItemCntStr != "") + if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt)) { return StringHelper::Sprintf("extern %s %s[%s];\n", varType.c_str(), varName.c_str(), arrayItemCntStr.c_str()); } - else if (arrayItemCnt != 0) + else if (arrayItemCnt != 0 && (IsStatic() || forceArrayCnt)) + { return StringHelper::Sprintf("extern %s %s[%i];\n", varType.c_str(), varName.c_str(), arrayItemCnt); + } else return StringHelper::Sprintf("extern %s %s[];\n", varType.c_str(), varName.c_str()); } diff --git a/tools/ZAPD/ZAPD/Declaration.h b/tools/ZAPD/ZAPD/Declaration.h index 138524a4c2..b7bb0d30d2 100644 --- a/tools/ZAPD/ZAPD/Declaration.h +++ b/tools/ZAPD/ZAPD/Declaration.h @@ -38,10 +38,12 @@ public: std::string varType; std::string varName; std::string includePath; + bool isExternal = false; bool isArray = false; + bool forceArrayCnt = false; size_t arrayItemCnt = 0; - std::string arrayItemCntStr; + std::string arrayItemCntStr = ""; std::vector references; bool isUnaccounted = false; bool isPlaceholder = false; diff --git a/tools/ZAPD/ZAPD/GameConfig.cpp b/tools/ZAPD/ZAPD/GameConfig.cpp index f197493a4a..ae29ba28fa 100644 --- a/tools/ZAPD/ZAPD/GameConfig.cpp +++ b/tools/ZAPD/ZAPD/GameConfig.cpp @@ -25,7 +25,7 @@ GameConfig::~GameConfig() void GameConfig::ReadTexturePool(const fs::path& texturePoolXmlPath) { tinyxml2::XMLDocument doc; - tinyxml2::XMLError eResult = doc.LoadFile(texturePoolXmlPath.c_str()); + tinyxml2::XMLError eResult = doc.LoadFile(texturePoolXmlPath.string().c_str()); if (eResult != tinyxml2::XML_SUCCESS) { @@ -155,7 +155,7 @@ void GameConfig::ReadConfigFile(const fs::path& argConfigFilePath) {"ExternalFile", &GameConfig::ConfigFunc_ExternalFile}, }; - configFilePath = argConfigFilePath; + configFilePath = argConfigFilePath.string(); tinyxml2::XMLDocument doc; tinyxml2::XMLError eResult = doc.LoadFile(configFilePath.c_str()); diff --git a/tools/ZAPD/ZAPD/Globals.cpp b/tools/ZAPD/ZAPD/Globals.cpp index 036e4a5cbf..528a09d256 100644 --- a/tools/ZAPD/ZAPD/Globals.cpp +++ b/tools/ZAPD/ZAPD/Globals.cpp @@ -3,8 +3,9 @@ #include #include -#include -#include +#include "Utils/File.h" +#include "Utils/Path.h" +#include "WarningHandler.h" #include "tinyxml2.h" Globals* Globals::Instance; diff --git a/tools/ZAPD/ZAPD/Globals.h b/tools/ZAPD/ZAPD/Globals.h index 265f1af241..19e193f123 100644 --- a/tools/ZAPD/ZAPD/Globals.h +++ b/tools/ZAPD/ZAPD/Globals.h @@ -20,6 +20,7 @@ typedef bool (*ExporterSetFuncBool)(ZFileMode fileMode); typedef void (*ExporterSetFuncVoid)(int argc, char* argv[], int& i); typedef void (*ExporterSetFuncVoid2)(const std::string& buildMode, ZFileMode& fileMode); typedef void (*ExporterSetFuncVoid3)(); +typedef void (*ExporterSetResSave)(ZResource* res, BinaryWriter& writer); class ExporterSet { @@ -34,6 +35,7 @@ public: ExporterSetFunc endFileFunc = nullptr; ExporterSetFuncVoid3 beginXMLFunc = nullptr; ExporterSetFuncVoid3 endXMLFunc = nullptr; + ExporterSetResSave resSaveFunc = nullptr; }; class Globals @@ -53,9 +55,6 @@ public: TextureType texType; ZGame game; GameConfig cfg; - bool warnUnaccounted = false; - bool warnNoOffset = false; - bool errorNoOffset = false; bool verboseUnaccounted = false; bool gccCompat = false; bool forceStatic = false; diff --git a/tools/ZAPD/ZAPD/ImageBackend.cpp b/tools/ZAPD/ZAPD/ImageBackend.cpp index 137e326c33..8accb6b4e1 100644 --- a/tools/ZAPD/ZAPD/ImageBackend.cpp +++ b/tools/ZAPD/ZAPD/ImageBackend.cpp @@ -6,6 +6,7 @@ #include #include "Utils/StringHelper.h" +#include "WarningHandler.h" /* ImageBackend */ @@ -20,19 +21,28 @@ void ImageBackend::ReadPng(const char* filename) FILE* fp = fopen(filename, "rb"); if (fp == nullptr) - throw std::runtime_error(StringHelper::Sprintf( - "ImageBackend::ReadPng: Error.\n\t Couldn't open file '%s'.", filename)); + { + std::string errorHeader = StringHelper::Sprintf("could not open file '%s'", filename); + HANDLE_ERROR(WarningType::InvalidPNG, errorHeader, ""); + } png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if (!png) - throw std::runtime_error("ImageBackend::ReadPng: Error.\n\t Couldn't create png struct."); + if (png == nullptr) + { + HANDLE_ERROR(WarningType::InvalidPNG, "could not create png struct", ""); + } png_infop info = png_create_info_struct(png); - if (!info) - throw std::runtime_error("ImageBackend::ReadPng: Error.\n\t Couldn't create png info."); + if (info == nullptr) + { + HANDLE_ERROR(WarningType::InvalidPNG, "could not create png info", ""); + } if (setjmp(png_jmpbuf(png))) - throw std::runtime_error("ImageBackend::ReadPng: Error.\n\t setjmp(png_jmpbuf(png))."); + { + // TODO: better warning explanation + HANDLE_ERROR(WarningType::InvalidPNG, "setjmp(png_jmpbuf(png))", ""); + } png_init_io(png, fp); @@ -145,20 +155,30 @@ void ImageBackend::WritePng(const char* filename) assert(hasImageData); FILE* fp = fopen(filename, "wb"); - if (!fp) - throw std::runtime_error(StringHelper::Sprintf( - "ImageBackend::WritePng: Error.\n\t Couldn't open file '%s' in write mode.", filename)); + if (fp == nullptr) + { + std::string errorHeader = + StringHelper::Sprintf("could not open file '%s' in write mode", filename); + HANDLE_ERROR(WarningType::InvalidPNG, errorHeader, ""); + } png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if (!png) - throw std::runtime_error("ImageBackend::WritePng: Error.\n\t Couldn't create png struct."); + if (png == nullptr) + { + HANDLE_ERROR(WarningType::InvalidPNG, "could not create png struct", ""); + } png_infop info = png_create_info_struct(png); - if (!info) - throw std::runtime_error("ImageBackend::WritePng: Error.\n\t Couldn't create png info."); + if (info == nullptr) + { + HANDLE_ERROR(WarningType::InvalidPNG, "could not create png info", ""); + } if (setjmp(png_jmpbuf(png))) - throw std::runtime_error("ImageBackend::WritePng: Error.\n\t setjmp(png_jmpbuf(png))."); + { + // TODO: better warning description + HANDLE_ERROR(WarningType::InvalidPNG, "setjmp(png_jmpbuf(png))", ""); + } png_init_io(png, fp); @@ -441,7 +461,7 @@ double ImageBackend::GetBytesPerPixel() const return 1 * bitDepth / 8; default: - throw std::invalid_argument("ImageBackend::GetBytesPerPixel():\n\t Invalid color type."); + HANDLE_ERROR(WarningType::InvalidPNG, "invalid color type", ""); } } diff --git a/tools/ZAPD/ZAPD/Main.cpp b/tools/ZAPD/ZAPD/Main.cpp index 298ca02629..fd2ed06dc0 100644 --- a/tools/ZAPD/ZAPD/Main.cpp +++ b/tools/ZAPD/ZAPD/Main.cpp @@ -1,8 +1,9 @@ -#include -#include -#include #include "Globals.h" #include "Overlays/ZOverlay.h" +#include "Utils/Directory.h" +#include "Utils/File.h" +#include "Utils/Path.h" +#include "WarningHandler.h" #include "ZAnimation.h" #include "ZBackground.h" #include "ZBlob.h" @@ -12,10 +13,10 @@ #if !defined(_MSC_VER) && !defined(__CYGWIN__) #include #include +#include #include // for __cxa_demangle #include // for dladdr #include -#include #include #endif @@ -47,6 +48,7 @@ void ErrorHandler(int sig) const char* crashEasterEgg[] = { "\tYou've met with a terrible fate, haven't you?", "\tSEA BEARS FOAM. SLEEP BEARS DREAMS. \n\tBOTH END IN THE SAME WAY: CRASSSH!", + "ZAPD has fallen and cannot get up." }; srand(time(nullptr)); @@ -97,6 +99,9 @@ int main(int argc, char* argv[]) return 1; } + Globals* g = new Globals(); + WarningHandler::Init(argc, argv); + for (int i = 1; i < argc; i++) { if (!strcmp(argv[i], "--version")) @@ -109,12 +114,12 @@ int main(int argc, char* argv[]) printf("Congratulations!\n"); printf("You just found the (unimplemented and undocumented) ZAPD's help message.\n"); printf("Feel free to implement it if you want :D\n"); + + WarningHandler::PrintHelp(); return 0; } } - Globals* g = new Globals; - // Parse other "commands" for (int32_t i = 2; i < argc; i++) { @@ -186,26 +191,15 @@ int main(int argc, char* argv[]) signal(SIGSEGV, ErrorHandler); signal(SIGABRT, ErrorHandler); #else - fprintf(stderr, - "Warning: Tried to set error handler, but this build lacks support for one.\n"); + HANDLE_WARNING(WarningType::Always, + "tried to set error handler, but this ZAPD build lacks support for one", + ""); #endif } else if (arg == "-v") // Verbose { Globals::Instance->verbosity = static_cast(strtol(argv[++i], NULL, 16)); } - else if (arg == "-wu" || arg == "--warn-unaccounted") // Warn unaccounted - { - Globals::Instance->warnUnaccounted = true; - } - else if (arg == "-wno" || arg == "--warn-no-offset") - { - Globals::Instance->warnNoOffset = true; - } - else if (arg == "-eno" || arg == "--error-no-offset") - { - Globals::Instance->errorNoOffset = true; - } else if (arg == "-vu" || arg == "--verbose-unaccounted") // Verbose unaccounted { Globals::Instance->verboseUnaccounted = true; @@ -262,6 +256,11 @@ int main(int argc, char* argv[]) if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO) printf("ZAPD: Zelda Asset Processor For Decomp: %s\n", gBuildHash); + if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG) + { + WarningHandler::PrintWarningsDebugInfo(); + } + // TODO: switch if (fileMode == ZFileMode::Extract || fileMode == ZFileMode::BuildSourceFile) { @@ -334,7 +333,9 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path if (eResult != tinyxml2::XML_SUCCESS) { - fprintf(stderr, "Invalid xml file: '%s'\n", xmlFilePath.c_str()); + // TODO: use XMLDocument::ErrorIDToName to get more specific error messages here + HANDLE_ERROR(WarningType::InvalidXML, + StringHelper::Sprintf("invalid XML file: '%s'", xmlFilePath.c_str()), ""); return false; } @@ -342,7 +343,9 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path if (root == nullptr) { - fprintf(stderr, "Missing Root tag in xml file: '%s'\n", xmlFilePath.c_str()); + HANDLE_WARNING( + WarningType::InvalidXML, + StringHelper::Sprintf("missing Root tag in xml file: '%s'", xmlFilePath.c_str()), ""); return false; } @@ -392,10 +395,11 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path } else { - throw std::runtime_error(StringHelper::Sprintf( - "Parse: Fatal error in '%s'.\n\t A resource was found outside of " - "a File element: '%s'\n", - xmlFilePath.c_str(), child->Name())); + std::string errorHeader = + StringHelper::Sprintf("when parsing file '%s'", xmlFilePath.c_str()); + std::string errorBody = StringHelper::Sprintf( + "Found a resource outside a File element: '%s'", child->Name()); + HANDLE_ERROR(WarningType::InvalidXML, errorHeader, errorBody); } } diff --git a/tools/ZAPD/ZAPD/NuGet/libpng.static.txt b/tools/ZAPD/ZAPD/NuGet/libpng.static.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tools/ZAPD/ZAPD/Overlays/ZOverlay.cpp b/tools/ZAPD/ZAPD/Overlays/ZOverlay.cpp index a842a7e7d9..510de19aba 100644 --- a/tools/ZAPD/ZAPD/Overlays/ZOverlay.cpp +++ b/tools/ZAPD/ZAPD/Overlays/ZOverlay.cpp @@ -1,13 +1,13 @@ #include "ZOverlay.h" -#include +#include #include - -#include -#include -#include -#include #include "Globals.h" +#include "Utils/Directory.h" +#include "Utils/File.h" +#include "Utils/Path.h" +#include "Utils/StringHelper.h" +#include "WarningHandler.h" using namespace ELFIO; @@ -90,7 +90,7 @@ ZOverlay* ZOverlay::FromBuild(fs::path buildPath, fs::path cfgFolderPath) std::vector readers; for (size_t i = 1; i < cfgLines.size(); i++) { - std::string elfPath = buildPath / (cfgLines[i].substr(0, cfgLines[i].size() - 2) + ".o"); + std::string elfPath = (buildPath / (cfgLines[i].substr(0, cfgLines[i].size() - 2) + ".o")).string(); elfio* reader = new elfio(); if (!reader->load(elfPath)) @@ -128,7 +128,9 @@ ZOverlay* ZOverlay::FromBuild(fs::path buildPath, fs::path cfgFolderPath) SectionType sectionType = GetSectionTypeFromStr(pSec->get_name()); if (sectionType == SectionType::ERROR) - fprintf(stderr, "WARNING: One of the section types returned ERROR\n"); + { + HANDLE_WARNING(WarningType::Always, "one of the section types returned ERROR", ""); + } relocation_section_accessor relocs(*curReader, pSec); for (Elf_Xword j = 0; j < relocs.get_entries_num(); j++) diff --git a/tools/ZAPD/ZAPD/WarningHandler.cpp b/tools/ZAPD/ZAPD/WarningHandler.cpp new file mode 100644 index 0000000000..29f8352a71 --- /dev/null +++ b/tools/ZAPD/ZAPD/WarningHandler.cpp @@ -0,0 +1,443 @@ +/** + * ZAPD Warning- and Error-handling system + * ======================================= + * + * This provides a common standard way to write ZAPD warnings/errors, which should be used for all + * such. It will pretty-print them in a uniform way, with styles defined in the header. + * + * Warnings/errors should be constructed using the macros given in the header; there are now plenty + * of examples in the codebase of how to do this. Their purposes are noted above each category in + * the header. Each warning has a type, one of the ones in warningStringToInitMap, or + * WarningType::Always, which is used for warnings that cannot be disabled and do not display a + * type. + * + * Currently there are three levels of alert a warning can have: + * - Off (does not display anything) + * - Warn (print a warning but continue processing) + * - Err (behave like an error, i.e. print and throw an exception to crash ZAPD when occurs) + * + * Flag use: + * - -Wfoo enables warnings of type foo + * - -Wno-foo disables warnings of type foo + * - -Werror=foo escalates foo to behave like an error + * - -Weverything enables all warnings + * - -Werror escalates all enabled warnings to errors + * + * Errors do not have types, and will always throw an exception; they cannot be disabled. + * + * Format + * === + * Each printed warning/error contains the same three sections: + * - Preamble: automatically generated; the content varies depending on category. It will print the + * file and function that the warning is from, and information about the files being processed + * or extracted. + * - Header: begins with 'warning: ' or 'error:', should contain essential information about the + * warning/error, ends with the warning type if applicable. Printed with emphasis to make it + * stand out. Does not start with a capital letter or end with a '.' + * - Body (optional): indented, should contain further diagnostic information useful for identifying + * and fixing the warning/error. Can be a sentence with captialisation and '.' on the end. + * + * Please think of what the end user will find most useful when writing the header and body, and try + * to keep it brief without sacrificing important information! Also remember that if the user is + * only looking at stderr, they will normally have no other context. + * + * Warning vs error + * === + * The principle that we have operated on so far is + * - issue a warning if ZAPD will still be able to produce a valid, compilable C file that will + * match + * - if this cannot happen, use an error. + * but at the end of the day, it is up to the programmer's discretion what it should be possible to + * disable. + * + * Documentation + * === + * Remember that all warnings also need to be documented in the README.md. The help is generated + * automatically. + */ +#include "WarningHandler.h" + +#include +#include "Globals.h" +#include "Utils/StringHelper.h" + +typedef struct +{ + WarningType type; + WarningLevel defaultLevel; + std::string description; +} WarningInfoInit; + +typedef struct +{ + WarningLevel level; + std::string name; + std::string description; +} WarningInfo; + +/** + * Master list of all default warning types and features + * + * To add a warning type, fill in a new row of this map. Think carefully about what its default + * level should be, and try and make the description both brief and informative: it is used in the + * help message, so again, think about what the end user needs to know. + */ +// clang-format off +static const std::unordered_map warningStringToInitMap = { + {"deprecated", {WarningType::Deprecated, +#ifdef DEPRECATION_ON + WarningLevel::Warn, +#else + WarningLevel::Off, +#endif + "Deprecated features"}}, + {"unaccounted", {WarningType::Unaccounted, WarningLevel::Off, "Large blocks of unaccounted"}}, + {"missing-offsets", {WarningType::MissingOffsets, WarningLevel::Warn, "Offset attribute missing in XML tag"}}, + {"intersection", {WarningType::Intersection, WarningLevel::Warn, "Two assets intersect"}}, + {"missing-attribute", {WarningType::MissingAttribute, WarningLevel::Warn, "Required attribute missing in XML tag"}}, + {"invalid-attribute-value", {WarningType::InvalidAttributeValue, WarningLevel::Err, "Attribute declared in XML is wrong"}}, + {"unknown-attribute", {WarningType::UnknownAttribute, WarningLevel::Warn, "Unknown attribute in XML entry tag"}}, + {"invalid-xml", {WarningType::InvalidXML, WarningLevel::Err, "XML has syntax errors"}}, + {"invalid-jpeg", {WarningType::InvalidJPEG, WarningLevel::Err, "JPEG file does not conform to the game's format requirements"}}, + {"invalid-png", {WarningType::InvalidPNG, WarningLevel::Err, "Issues arising when processing PNG data"}}, + {"invalid-extracted-data", {WarningType::InvalidExtractedData, WarningLevel::Err, "Extracted data does not have correct form"}}, + {"missing-segment", {WarningType::MissingSegment, WarningLevel::Warn, "Segment not given in File tag in XML"}}, + {"hardcoded-pointer", {WarningType::HardcodedPointer, WarningLevel::Warn, "ZAPD lacks the info to make a symbol, so must output a hardcoded pointer"}}, + {"not-implemented", {WarningType::NotImplemented, WarningLevel::Warn, "ZAPD does not currently support this feature"}}, +}; + +/** + * Map constructed at runtime to contain the warning features as set by the user using -W flags. + */ +static std::unordered_map warningTypeToInfoMap; + +void WarningHandler::ConstructTypeToInfoMap() { + for (auto& entry : warningStringToInitMap) { + warningTypeToInfoMap[entry.second.type] = {entry.second.defaultLevel, entry.first, entry.second.description}; + } + warningTypeToInfoMap[WarningType::Always] = {WarningLevel::Warn, "always", "you shouldn't be reading this"}; + assert(warningTypeToInfoMap.size() == static_cast(WarningType::Max)); +} + +/** + * Initialises the main warning type map and reads flags passed to set each warning type's level. + */ +void WarningHandler::Init(int argc, char* argv[]) { + ConstructTypeToInfoMap(); + + bool werror = false; + for (int i = 1; i < argc; i++) { + // If it doesn't start with "-W" skip it. + if (argv[i][0] != '-' || argv[i][1] != 'W' || argv[i][2] == '\0') { + continue; + } + + WarningLevel warningTypeOn = WarningLevel::Warn; + size_t startingIndex = 2; + + // "-Wno-" + if (argv[i][2] == 'n' && argv[i][3] == 'o' && argv[i][4] == '-' && argv[i][5] != '\0') { + warningTypeOn = WarningLevel::Off; + startingIndex = 5; + } + + // Read starting after the "-W" or "-Wno-" + std::string_view currentArgv = &argv[i][startingIndex]; + + if (currentArgv == "error") { + werror = warningTypeOn != WarningLevel::Off; + } else if (currentArgv == "everything") { + for (auto& it: warningTypeToInfoMap) { + if (it.second.level <= WarningLevel::Warn) { + it.second.level = warningTypeOn; + } + } + } else { + // "-Werror=" / "-Wno-error=" parser + if (currentArgv.rfind("error=", 0) == 0) { + // Read starting after the "error=" part + currentArgv = &argv[i][startingIndex + 6]; + warningTypeOn = warningTypeOn != WarningLevel::Off ? WarningLevel::Err : WarningLevel::Warn; + } + + auto it = warningStringToInitMap.find(std::string(currentArgv)); + if (it != warningStringToInitMap.end()) { + warningTypeToInfoMap[it->second.type].level = warningTypeOn; + } + else { + HANDLE_WARNING(WarningType::Always, StringHelper::Sprintf("unknown warning flag '%s'", argv[i]), ""); + } + } + } + + if (werror) { + for (auto& it: warningTypeToInfoMap) { + if (it.second.level >= WarningLevel::Warn) { + it.second.level = WarningLevel::Err; + } + } + } +} + +bool WarningHandler::IsWarningEnabled(WarningType warnType) { + assert(static_cast(warnType) >= 0 && warnType < WarningType::Max); + + return warningTypeToInfoMap.at(warnType).level != WarningLevel::Off; +} + +bool WarningHandler::WasElevatedToError(WarningType warnType) { + assert(static_cast(warnType) >= 0 && warnType < WarningType::Max); + + if (!IsWarningEnabled(warnType)) { + return false; + } + + return warningTypeToInfoMap.at(warnType).level >= WarningLevel::Err; +} + +/** + * Print file/line/function info for debugging + */ +void WarningHandler::FunctionPreamble(const char* filename, int32_t line, const char* function) { + if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG) { + fprintf(stderr, "%s:%i: in function %s:\n", filename, line, function); + } +} + +/** + * Print the information about the file(s) being processed (XML for extraction, png etc. for building) + */ +void WarningHandler::ProcessedFilePreamble() { + if (Globals::Instance->inputPath != "") { + fprintf(stderr, "When processing file %s: ", Globals::Instance->inputPath.c_str()); + } +} + +/** + * Print information about the binary file being extracted + */ +void WarningHandler::ExtractedFilePreamble(const ZFile *parent, const ZResource* res, const uint32_t offset) { + fprintf(stderr, "in input binary file %s, ", parent->GetName().c_str()); + if (res != nullptr) { + fprintf(stderr, "resource '%s' at ", res->GetName().c_str()); + } + fprintf(stderr, "offset 0x%06X: \n\t", offset); +} + +/** + * Construct the rest of the message, after warning:/error. The message is filled in one character at a time, with indents added after newlines + */ +std::string WarningHandler::ConstructMessage(std::string message, const std::string& header, const std::string& body) { + message.reserve(message.size() + header.size() + body.size() + 10 * (sizeof(HANG_INDT) - 1)); + message += StringHelper::Sprintf(HILITE("%s"), header.c_str()); + message += "\n"; + + if (body == "") { + return message; + } + + message += HANG_INDT; + for (const char* ptr = body.c_str(); *ptr != '\0'; ptr++) { + message += *ptr; + if (*ptr == '\n') { + message += HANG_INDT; + } + } + message += "\n"; + + return message; +} + +/* Error module functions */ + +void WarningHandler::PrintErrorAndThrow(const std::string& header, const std::string& body) { + std::string errorMsg = ERR_FMT("error: "); + throw std::runtime_error(ConstructMessage(errorMsg, header, body)); +} + +/* Error types, to be used via the macros */ + +void WarningHandler::ErrorType(WarningType warnType, const std::string& header, const std::string& body) { + std::string headerMsg = header; + + for (const auto& iter: warningStringToInitMap) { + if (iter.second.type == warnType) { + headerMsg += StringHelper::Sprintf(" [%s]", iter.first.c_str()); + } + } + + PrintErrorAndThrow(headerMsg, body); +} + +void WarningHandler::Error_Plain(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) { + FunctionPreamble(filename, line, function); + + ErrorType(warnType, header, body); +} + +void WarningHandler::Error_Process(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) { + FunctionPreamble(filename, line, function); + ProcessedFilePreamble(); + + ErrorType(warnType, header, body); +} + +void WarningHandler::Error_Resource(const char* filename, int32_t line, const char* function, WarningType warnType, const ZFile *parent, const ZResource* res, const uint32_t offset, const std::string& header, const std::string& body) { + assert(parent != nullptr); + + FunctionPreamble(filename, line, function); + ProcessedFilePreamble(); + ExtractedFilePreamble(parent, res, offset); + + ErrorType(warnType, header, body); +} + +/* Warning module functions */ + +void WarningHandler::PrintWarningBody(const std::string& header, const std::string& body) { + std::string errorMsg = WARN_FMT("warning: "); + fprintf(stderr, "%s", ConstructMessage(errorMsg, header, body).c_str()); +} + +void WarningHandler::WarningTypeAndChooseEscalate(WarningType warnType, const std::string& header, const std::string& body) { + std::string headerMsg = header; + + for (const auto& iter: warningStringToInitMap) { + if (iter.second.type == warnType) { + headerMsg += StringHelper::Sprintf(" [-W%s]", iter.first.c_str()); + } + } + + if (WasElevatedToError(warnType)) { + PrintErrorAndThrow(headerMsg, body); + } else { + PrintWarningBody(headerMsg, body); + } +} + + +/* Warning types, to be used via the macros */ + +void WarningHandler::Warning_Plain(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) { + if (!IsWarningEnabled(warnType)) { + return; + } + + FunctionPreamble(filename, line, function); + + WarningTypeAndChooseEscalate(warnType, header, body); +} + +void WarningHandler::Warning_Process(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) { + if (!IsWarningEnabled(warnType)) { + return; + } + + FunctionPreamble(filename, line, function); + ProcessedFilePreamble(); + + WarningTypeAndChooseEscalate(warnType, header, body); +} + +void WarningHandler::Warning_Resource(const char* filename, int32_t line, const char* function, WarningType warnType, const ZFile *parent, const ZResource* res, const uint32_t offset, const std::string& header, const std::string& body) { + assert(parent != nullptr); + + if (!IsWarningEnabled(warnType)) { + return; + } + + FunctionPreamble(filename, line, function); + ProcessedFilePreamble(); + ExtractedFilePreamble(parent, res, offset); + + WarningTypeAndChooseEscalate(warnType, header, body); +} + + +/* Help-related functions */ + +#include + +/** + * Print each warning name, default status, and description using the init map + */ +void WarningHandler::PrintHelp() { + std::set sortedKeys; + WarningInfoInit warningInfo; + uint32_t columnWidth = 25; + std::string dt; + + // Sort keys through the magic of `set`, to print in alphabetical order + for (auto& it : warningStringToInitMap) { + sortedKeys.insert(it.first); + } + + printf("\nWarning types ( * means enabled by default)\n"); + for (auto& key : sortedKeys) { + warningInfo = warningStringToInitMap.at(key); + if (warningInfo.defaultLevel <= WarningLevel::Warn) { + dt = "-W"; + dt += key; + if (warningInfo.defaultLevel == WarningLevel::Warn) { + dt += " *"; + } + printf(HELP_DT_INDT "%-*s", columnWidth, dt.c_str()); + + if (dt.length() + 2 > columnWidth) { + printf("\n" HELP_DT_INDT "%-*s", columnWidth, ""); + } + printf("%s\n", warningInfo.description.c_str()); + } + } + + printf("\nDefault errors\n"); + for (auto& key : sortedKeys) { + if (warningInfo.defaultLevel > WarningLevel::Warn) { + dt = "-W"; + dt += key; + printf(HELP_DT_INDT "%-*s", columnWidth, dt.c_str()); + + if (dt.length() + 2 > columnWidth) { + printf("\n" HELP_DT_INDT "%*s", columnWidth, ""); + } + printf("%s\n", warningInfo.description.c_str()); + } + } + + printf("\n"); + printf("Other\n" HELP_DT_INDT "-Weverything will enable all existing warnings.\n" HELP_DT_INDT "-Werror will promote all warnings to errors.\n"); + + printf("\n"); + printf("Warnings can be disabled using -Wno-... instead of -W...; -Weverything will override any -Wno-... flags passed before it.\n"); +} + +/** + * Print which warnings are currently enabled + */ +void WarningHandler::PrintWarningsDebugInfo() +{ + std::string dt; + + printf("Warnings status:\n"); + for (auto& it: warningTypeToInfoMap) { + dt = it.second.name; + dt += ": "; + + printf(HELP_DT_INDT "%-25s", dt.c_str()); + switch (it.second.level) + { + case WarningLevel::Off: + printf(VT_FGCOL(LIGHTGRAY) "Off" VT_RST); + break; + case WarningLevel::Warn: + printf(VT_FGCOL(YELLOW) "Warn" VT_RST); + break; + case WarningLevel::Err: + printf(VT_FGCOL(RED) "Err" VT_RST); + break; + + } + printf("\n"); + } + printf("\n"); +} diff --git a/tools/ZAPD/ZAPD/WarningHandler.h b/tools/ZAPD/ZAPD/WarningHandler.h new file mode 100644 index 0000000000..bb0360a813 --- /dev/null +++ b/tools/ZAPD/ZAPD/WarningHandler.h @@ -0,0 +1,145 @@ +#pragma once + +#include +#include +#include +#include + +#include "Utils/vt.h" +#include "ZFile.h" + +#ifdef _MSC_VER +#define __PRETTY_FUNCTION__ __FUNCSIG__ +#elif not defined(__GNUC__) +#define __PRETTY_FUNCTION__ __func__ +#endif + +// ======================================= +/* Formatting macros */ + +// TODO: move this somewhere else so it can be used by other help +#define HELP_DT_INDT " " + +/* Macros for formatting warnings/errors */ +#define VT_HILITE VT_BOLD_FGCOL(WHITE) +#define VT_WARN VT_BOLD_FGCOL(PURPLE) +#define VT_ERR VT_BOLD_FGCOL(RED) + +#define HILITE(string) (VT_HILITE string VT_RST) +#define WARN_FMT(string) (VT_WARN string VT_RST) +#define ERR_FMT(string) (VT_ERR string VT_RST) + +// Maybe make WARN_LF instead +// Currently 8 spaces +#define WARN_INDT " " +// Currently 16 spaces +#define HANG_INDT " " + +// ======================================= +/* Warning and error macros */ +// TODO: better names + +// General-purpose, plain style (only prints function,file,line in the preamble) +#define HANDLE_ERROR(warningType, header, body) \ + WarningHandler::Error_Plain(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, body) +#define HANDLE_WARNING(warningType, header, body) \ + WarningHandler::Warning_Plain(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, \ + body) + +// For processing XMLs or textures/blobs (preamble contains function,file,line; processed file) +#define HANDLE_ERROR_PROCESS(warningType, header, body) \ + WarningHandler::Error_Process(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, \ + body) +#define HANDLE_WARNING_PROCESS(warningType, header, body) \ + WarningHandler::Warning_Process(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, \ + body) + +// For ZResource-related stuff (preamble contains function,file,line; processed file; extracted file +// and offset) +#define HANDLE_ERROR_RESOURCE(warningType, parent, resource, offset, header, body) \ + WarningHandler::Error_Resource(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, parent, \ + resource, offset, header, body) +#define HANDLE_WARNING_RESOURCE(warningType, parent, resource, offset, header, body) \ + WarningHandler::Warning_Resource(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, parent, \ + resource, offset, header, body) + +// ======================================= + +enum class WarningType +{ + Always, // Warnings of this type are always printed, cannot be disabled. + Deprecated, + Unaccounted, + MissingOffsets, + Intersection, + MissingAttribute, + InvalidAttributeValue, + UnknownAttribute, + InvalidXML, + InvalidJPEG, + InvalidPNG, + InvalidExtractedData, + MissingSegment, + HardcodedPointer, + NotImplemented, + Max, +}; + +enum class WarningLevel +{ + Off, + Warn, + Err, +}; + +class WarningHandler +{ +public: + static void ConstructTypeToInfoMap(); + + static void Init(int argc, char* argv[]); + + static bool IsWarningEnabled(WarningType warnType); + static bool WasElevatedToError(WarningType warnType); + + static void FunctionPreamble(const char* filename, int32_t line, const char* function); + static void ProcessedFilePreamble(); + static void ExtractedFilePreamble(const ZFile* parent, const ZResource* res, + const uint32_t offset); + static std::string ConstructMessage(std::string message, const std::string& header, + const std::string& body); + + [[noreturn]] static void PrintErrorAndThrow(const std::string& header, const std::string& body); + static void PrintWarningBody(const std::string& header, const std::string& body); + + [[noreturn]] static void ErrorType(WarningType warnType, const std::string& header, + const std::string& body); + [[noreturn]] static void Error_Plain(const char* filename, int32_t line, const char* function, + WarningType warnType, const std::string& header, + const std::string& body); + [[noreturn]] static void Error_Process(const char* filename, int32_t line, const char* function, + WarningType warnType, const std::string& header, + const std::string& body); + [[noreturn]] static void Error_Resource(const char* filename, int32_t line, + const char* function, WarningType warnType, + const ZFile* parent, const ZResource* res, + const uint32_t offset, const std::string& header, + const std::string& body); + + static void WarningTypeAndChooseEscalate(WarningType warnType, const std::string& header, + const std::string& body); + + static void Warning_Plain(const char* filename, int32_t line, const char* function, + WarningType warnType, const std::string& header, + const std::string& body); + static void Warning_Process(const char* filename, int32_t line, const char* function, + WarningType warnType, const std::string& header, + const std::string& body); + static void Warning_Resource(const char* filename, int32_t line, const char* function, + WarningType warnType, const ZFile* parent, const ZResource* res, + const uint32_t offset, const std::string& header, + const std::string& body); + + static void PrintHelp(); + static void PrintWarningsDebugInfo(); +}; diff --git a/tools/ZAPD/ZAPD/ZAPD.vcxproj b/tools/ZAPD/ZAPD/ZAPD.vcxproj index c74d28cbec..431abb73b9 100644 --- a/tools/ZAPD/ZAPD/ZAPD.vcxproj +++ b/tools/ZAPD/ZAPD/ZAPD.vcxproj @@ -1,5 +1,6 @@ + Debug @@ -71,8 +72,8 @@ - $(SolutionDir)lib\libgfxd;$(SolutionDir)x64\Debug;$(SolutionDir)packages\libpng.1.6.28.1\build\native\lib\x64\v140\dynamic\Debug;$(LibraryPath) - $(SolutionDir)ZAPDUtils;$(SolutionDir)lib\tinyxml2;$(SolutionDir)lib\libgfxd;$(SolutionDir)lib\elfio;$(SolutionDir)lib\stb;$(ProjectDir);$(IncludePath) + $(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(LibraryPath) + $(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath) $(IncludePath) @@ -105,13 +106,16 @@ _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) EnableFastChecks stdc11 + MultiThreadedDebug true - libpng16.lib;ZAPDUtils.lib;/WHOLEARCHIVE:ExporterExample.lib;%(AdditionalDependencies) + ZAPDUtils.lib;/WHOLEARCHIVE:ExporterExample.lib;%(AdditionalDependencies) + false cd .. +mkdir build\ZAPD python3 ZAPD/genbuildinfo.py @@ -146,6 +150,7 @@ python3 ZAPD/genbuildinfo.py + @@ -153,19 +158,22 @@ python3 ZAPD/genbuildinfo.py - + + + + @@ -213,6 +221,7 @@ python3 ZAPD/genbuildinfo.py + @@ -237,10 +246,13 @@ python3 ZAPD/genbuildinfo.py + + + @@ -253,6 +265,7 @@ python3 ZAPD/genbuildinfo.py + @@ -294,6 +307,7 @@ python3 ZAPD/genbuildinfo.py + @@ -301,24 +315,29 @@ python3 ZAPD/genbuildinfo.py true + + - - + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + + + \ No newline at end of file diff --git a/tools/ZAPD/ZAPD/ZAPD.vcxproj.filters b/tools/ZAPD/ZAPD/ZAPD.vcxproj.filters index 2d3050ed42..b8a7daaacf 100644 --- a/tools/ZAPD/ZAPD/ZAPD.vcxproj.filters +++ b/tools/ZAPD/ZAPD/ZAPD.vcxproj.filters @@ -49,6 +49,15 @@ {85600275-99fe-491d-8189-bcc3dc1a8903} + + {ba9990b0-1082-48bb-874c-6108534b5455} + + + {ce9d91b0-ba20-4296-bc2d-8630965bb392} + + + {730beb67-6d59-4849-9d9b-702c4a565fc0} + @@ -135,9 +144,6 @@ Source Files\Z64\ZRoom\Commands - - Source Files\Libraries - Source Files\Z64 @@ -258,6 +264,24 @@ Source Files\Z64 + + Source Files + + + Source Files\Z64 + + + Source Files\Z64 + + + Source Files + + + Source Files\Z64 + + + Source Files + @@ -497,11 +521,32 @@ Header Files\Z64 + + Header Files + + + Header Files\Z64 + + + Header Files\Z64 + + + Header Files\Z64 + + + Header Files + Resource Files + + any\any + + + NuGet + diff --git a/tools/ZAPD/ZAPD/ZAnimation.cpp b/tools/ZAPD/ZAPD/ZAnimation.cpp index 9242f657a8..adb0ae7c9a 100644 --- a/tools/ZAPD/ZAPD/ZAnimation.cpp +++ b/tools/ZAPD/ZAPD/ZAnimation.cpp @@ -6,6 +6,7 @@ #include "Utils/BitConverter.h" #include "Utils/File.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZFile.h" REGISTER_ZFILENODE(Animation, ZNormalAnimation); @@ -218,11 +219,9 @@ void ZCurveAnimation::ParseXML(tinyxml2::XMLElement* reader) std::string skelOffsetXml = registeredAttributes.at("SkelOffset").value; if (skelOffsetXml == "") { - throw std::runtime_error( - StringHelper::Sprintf("ZCurveAnimation::ParseXML: Fatal error in '%s'.\n" - "\t Missing 'SkelOffset' attribute in ZCurveAnimation.\n" - "\t You need to provide the offset of the curve skeleton.", - name.c_str())); + HANDLE_ERROR_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex, + "missing 'SkelOffset' attribute in ", + "You need to provide the offset of the curve skeleton."); } skelOffset = StringHelper::StrToL(skelOffsetXml, 0); } diff --git a/tools/ZAPD/ZAPD/ZAnimation.h b/tools/ZAPD/ZAPD/ZAnimation.h index e5b69d3ef8..2c04b4ff81 100644 --- a/tools/ZAPD/ZAPD/ZAnimation.h +++ b/tools/ZAPD/ZAPD/ZAnimation.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include "Vec3s.h" diff --git a/tools/ZAPD/ZAPD/ZArray.cpp b/tools/ZAPD/ZAPD/ZArray.cpp index b1ba3a6693..ebfb13ee74 100644 --- a/tools/ZAPD/ZAPD/ZArray.cpp +++ b/tools/ZAPD/ZAPD/ZArray.cpp @@ -4,6 +4,7 @@ #include "Globals.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZFile.h" REGISTER_ZFILENODE(Array, ZArray); @@ -25,13 +26,18 @@ void ZArray::ParseXML(tinyxml2::XMLElement* reader) ZResource::ParseXML(reader); arrayCnt = reader->IntAttribute("Count", 0); - // TODO: do a better check. - assert(arrayCnt > 0); + if (arrayCnt <= 0) + { + HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + "invalid value found for 'Count' attribute", ""); + } tinyxml2::XMLElement* child = reader->FirstChildElement(); if (child == nullptr) - throw std::runtime_error( - StringHelper::Sprintf("Error! Array needs at least one sub-element.\n")); + { + HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex, + " needs one sub-element", ""); + } childName = child->Name(); @@ -42,9 +48,10 @@ void ZArray::ParseXML(tinyxml2::XMLElement* reader) ZResource* res = nodeMap->at(childName)(parent); if (!res->DoesSupportArray()) { - throw std::runtime_error(StringHelper::Sprintf( - "Error! Resource %s does not support being wrapped in an array!\n", - childName.c_str())); + std::string errorHeader = StringHelper::Sprintf( + "resource <%s> does not support being wrapped in an ", childName.c_str()); + HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex, errorHeader, + ""); } res->parent = parent; res->SetInnerNode(true); @@ -87,7 +94,7 @@ Declaration* ZArray::DeclareVar(const std::string& prefix, const std::string& bo std::string ZArray::GetBodySourceCode() const { - std::string output; + std::string output = ""; for (size_t i = 0; i < arrayCnt; i++) { diff --git a/tools/ZAPD/ZAPD/ZArray.h b/tools/ZAPD/ZAPD/ZArray.h index 46a04d7329..b78a8edfd8 100644 --- a/tools/ZAPD/ZAPD/ZArray.h +++ b/tools/ZAPD/ZAPD/ZArray.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include "ZResource.h" diff --git a/tools/ZAPD/ZAPD/ZBackground.cpp b/tools/ZAPD/ZAPD/ZBackground.cpp index 4125f239f3..0ed1eb7471 100644 --- a/tools/ZAPD/ZAPD/ZBackground.cpp +++ b/tools/ZAPD/ZAPD/ZBackground.cpp @@ -5,6 +5,7 @@ #include "Utils/File.h" #include "Utils/Path.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZFile.h" REGISTER_ZFILENODE(Background, ZBackground); @@ -63,52 +64,46 @@ void ZBackground::CheckValidJpeg(const std::string& filepath) uint32_t jpegMarker = BitConverter::ToUInt32BE(data, 0); if (jpegMarker != JPEG_MARKER) { - fprintf(stderr, - "ZBackground::CheckValidJpeg: Warning.\n" - "\t Missing jpeg marker at the beginning of file: '%s'.\n" - "\t The game will skip this jpeg.\n", - filename.c_str()); + HANDLE_WARNING_PROCESS( + WarningType::InvalidJPEG, + StringHelper::Sprintf("missing jpeg marker at beginning of file: '%s'", + filename.c_str()), + "The game will skip this jpeg."); } if (data.at(6) != 'J' || data.at(7) != 'F' || data.at(8) != 'I' || data.at(9) != 'F' || data.at(10) != '\0') { std::string jfifIdentifier(data.begin() + 6, data.begin() + 6 + 5); - fprintf(stderr, - "ZBackground::CheckValidJpeg: Warning.\n" - "\t Missing 'JFIF' identifier. File: '%s'.\n" - "\t This image may be corrupted or not be a jpeg iamge.\n" - "\t The identifier found was '%s'.\n", - filename.c_str(), jfifIdentifier.c_str()); + HANDLE_WARNING_PROCESS( + WarningType::InvalidJPEG, "missing 'JFIF' identifier", + StringHelper::Sprintf( + "This image may be corrupted, or not a jpeg. The identifier found was: '%s'", + jfifIdentifier.c_str())); } uint8_t majorVersion = data.at(11); uint8_t minorVersion = data.at(12); if (majorVersion != 0x01 || minorVersion != 0x01) { - fprintf(stderr, - "ZBackground::CheckValidJpeg: Warning.\n" - "\t Wrong JFIF version '%i.%02i'. File: '%s'.\n" - "\t The expected version is '1.01'. The game may not be able to decode this image " - "properly.\n", - majorVersion, minorVersion, filename.c_str()); + HANDLE_WARNING_PROCESS( + WarningType::InvalidJPEG, + StringHelper::Sprintf("wrong JFIF version '%i.%02i'", majorVersion, minorVersion), + "The expected version is '1.01'. The game may be unable to decode this image " + "correctly."); } if (BitConverter::ToUInt16BE(data, 20) != MARKER_DQT) { // This may happen when creating a custom image with Exif, XMP, thumbnail, progressive, etc. // enabled. - fprintf(stderr, - "ZBackground::CheckValidJpeg: Warning.\n" - "\t There seems to be extra data before the image data in file: '%s'.\n" - "\t The game may not be able to decode this image properly.\n", - filename.c_str()); + HANDLE_WARNING_PROCESS(WarningType::InvalidJPEG, + "there seems to be extra data before the image data in this file", + "The game may not be able to decode this image correctly."); } if (data.size() > GetRawDataSize()) { - fprintf(stderr, - "ZBackground::CheckValidJpeg: Warning.\n" - "\t The image is bigger than the screen buffer. File: '%s'.\n" - "\t Image size: %zu bytes.\n" - "\t Screen buffer size: %zu bytes.\n", - filename.c_str(), data.size(), GetRawDataSize()); + HANDLE_WARNING_PROCESS( + WarningType::InvalidJPEG, "the image is bigger than the screen buffer", + StringHelper::Sprintf("Image size: %zu bytes\nScreen buffer size: %zu bytes", + data.size(), GetRawDataSize())); } } @@ -138,6 +133,7 @@ Declaration* ZBackground::DeclareVar(const std::string& prefix, Declaration* decl = parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(), GetSourceTypeName(), auxName, 0); decl->arrayItemCntStr = "SCREEN_WIDTH * SCREEN_HEIGHT / 4"; + decl->forceArrayCnt = true; decl->staticConf = staticConf; return decl; } diff --git a/tools/ZAPD/ZAPD/ZBlob.cpp b/tools/ZAPD/ZAPD/ZBlob.cpp index c1f0788206..6812bfaee9 100644 --- a/tools/ZAPD/ZAPD/ZBlob.cpp +++ b/tools/ZAPD/ZAPD/ZBlob.cpp @@ -83,11 +83,6 @@ std::string ZBlob::GetBodySourceCode() const return sourceOutput; } -std::string ZBlob::GetSourceOutputHeader([[maybe_unused]] const std::string& prefix) -{ - return StringHelper::Sprintf("extern u8 %s[];\n", name.c_str()); -} - void ZBlob::Save(const fs::path& outFolder) { File::WriteAllBytes((outFolder / (name + ".bin")).string(), blobData); diff --git a/tools/ZAPD/ZAPD/ZBlob.h b/tools/ZAPD/ZAPD/ZBlob.h index 86623b5119..d7a7feff12 100644 --- a/tools/ZAPD/ZAPD/ZBlob.h +++ b/tools/ZAPD/ZAPD/ZBlob.h @@ -16,7 +16,6 @@ public: Declaration* DeclareVar(const std::string& prefix, const std::string& bodyStr) override; std::string GetBodySourceCode() const override; - std::string GetSourceOutputHeader(const std::string& prefix) override; void Save(const fs::path& outFolder) override; bool IsExternalResource() const override; diff --git a/tools/ZAPD/ZAPD/ZCollision.cpp b/tools/ZAPD/ZAPD/ZCollision.cpp index f9c0bf7d62..1dfa46b1dd 100644 --- a/tools/ZAPD/ZAPD/ZCollision.cpp +++ b/tools/ZAPD/ZAPD/ZCollision.cpp @@ -88,7 +88,7 @@ void ZCollisionHeader::ParseRawData() void ZCollisionHeader::DeclareReferences(const std::string& prefix) { - std::string declaration; + std::string declaration = ""; std::string auxName = name; if (name == "") @@ -174,7 +174,7 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix) std::string ZCollisionHeader::GetBodySourceCode() const { - std::string declaration; + std::string declaration = ""; declaration += "\n"; diff --git a/tools/ZAPD/ZAPD/ZCutscene.cpp b/tools/ZAPD/ZAPD/ZCutscene.cpp index 237481079f..ba8fe89638 100644 --- a/tools/ZAPD/ZAPD/ZCutscene.cpp +++ b/tools/ZAPD/ZAPD/ZCutscene.cpp @@ -2,6 +2,7 @@ #include "Utils/BitConverter.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZResource.h" REGISTER_ZFILENODE(Cutscene, ZCutscene); @@ -87,7 +88,7 @@ CutsceneCommandSceneTransFX::~CutsceneCommandSceneTransFX() std::string ZCutscene::GetBodySourceCode() const { - std::string output; + std::string output = ""; uint32_t curPtr = 0; output += StringHelper::Sprintf(" CS_BEGIN_CUTSCENE(%i, %i),\n", commands.size(), endFrame); @@ -225,8 +226,9 @@ void ZCutscene::ParseRawData() cmd = new CutsceneCommandEnd(rawData, currentPtr); break; case CutsceneCommands::Error: - fprintf(stderr, "Cutscene command error %d %s %d\n", (int32_t)cmdID, __FILE__, - __LINE__); + HANDLE_WARNING_RESOURCE(WarningType::NotImplemented, parent, this, rawDataIndex, + StringHelper::Sprintf("cutscene command error %d", cmdID), + ""); break; } @@ -404,7 +406,9 @@ CutsceneCommands ZCutscene::GetCommandFromID(int32_t id) return CutsceneCommands::Unknown; } - fprintf(stderr, "WARNING: Could not identify cutscene command ID 0x%04X\n", id); + HANDLE_WARNING_RESOURCE( + WarningType::NotImplemented, parent, this, rawDataIndex, + StringHelper::Sprintf("could not identify cutscene command. ID 0x%04X", id), ""); return CutsceneCommands::Error; } diff --git a/tools/ZAPD/ZAPD/ZCutscene.h b/tools/ZAPD/ZAPD/ZCutscene.h index cbb6a78b02..8e901e3075 100644 --- a/tools/ZAPD/ZAPD/ZCutscene.h +++ b/tools/ZAPD/ZAPD/ZCutscene.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include "ZFile.h" diff --git a/tools/ZAPD/ZAPD/ZCutsceneMM.h b/tools/ZAPD/ZAPD/ZCutsceneMM.h index 41b7de37f3..44b108d6c1 100644 --- a/tools/ZAPD/ZAPD/ZCutsceneMM.h +++ b/tools/ZAPD/ZAPD/ZCutsceneMM.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include "ZCutscene.h" diff --git a/tools/ZAPD/ZAPD/ZDisplayList.cpp b/tools/ZAPD/ZAPD/ZDisplayList.cpp index 63c5684228..869b563d96 100644 --- a/tools/ZAPD/ZAPD/ZDisplayList.cpp +++ b/tools/ZAPD/ZAPD/ZDisplayList.cpp @@ -11,6 +11,7 @@ #include "Utils/File.h" #include "Utils/Path.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "gfxd.h" REGISTER_ZFILENODE(DList, ZDisplayList); @@ -445,11 +446,12 @@ int32_t ZDisplayList::GetDListLength(const std::vector& rawData, uint32 { if (ptr >= rawDataSize) { - throw std::runtime_error(StringHelper::Sprintf( - "%s: Fatal error.\n" - "\t End of file found when trying to find the end of the " - "DisplayList at offset: '0x%X'.\n", - "Raw data size: 0x%zX.\n", __PRETTY_FUNCTION__, rawDataIndex, rawDataSize)); + std::string errorHeader = + StringHelper::Sprintf("reached end of file when trying to find the end of the " + "DisplayList starting at offset 0x%X", + rawDataIndex); + std::string errorBody = StringHelper::Sprintf("Raw data size: 0x%zX.", rawDataSize); + HANDLE_ERROR_PROCESS(WarningType::Always, errorHeader, errorBody); } uint8_t opcode = rawData.at(ptr); @@ -1522,11 +1524,6 @@ void ZDisplayList::Opcode_G_ENDDL([[maybe_unused]] const std::string& prefix, ch TextureGenCheck(); } -std::string ZDisplayList::GetSourceOutputHeader([[maybe_unused]] const std::string& prefix) -{ - return ""; -} - static int32_t GfxdCallback_FormatSingleEntry() { ZDisplayList* self = static_cast(gfxd_udata_get()); @@ -1737,7 +1734,7 @@ static int32_t GfxdCallback_Matrix(uint32_t seg) return 1; } -std::string ZDisplayList::GetSourceOutputCode(const std::string& prefix) +void ZDisplayList::DeclareReferences(const std::string& prefix) { std::string sourceOutput; @@ -1750,7 +1747,7 @@ std::string ZDisplayList::GetSourceOutputCode(const std::string& prefix) if (vertices.size() > 0) { std::vector>> verticesSorted(vertices.begin(), - vertices.end()); + vertices.end()); for (size_t i = 0; i < verticesSorted.size() - 1; i++) { @@ -1775,15 +1772,13 @@ std::string ZDisplayList::GetSourceOutputCode(const std::string& prefix) // Generate Vertex Declarations for (auto& item : vertices) { - std::string declaration; + std::string declaration = ""; offset_t curAddr = item.first; auto& firstVtx = item.second.at(0); for (auto vtx : item.second) - { declaration += StringHelper::Sprintf("\t%s,\n", vtx.GetBodySourceCode().c_str()); - } Declaration* decl = parent->AddDeclarationArray( curAddr, firstVtx.GetDeclarationAlignment(), @@ -1800,7 +1795,7 @@ std::string ZDisplayList::GetSourceOutputCode(const std::string& prefix) if (vertices.size() > 0) { std::vector>> verticesSorted(vertices.begin(), - vertices.end()); + vertices.end()); for (size_t i = 0; i < verticesSorted.size() - 1; i++) { @@ -1863,11 +1858,6 @@ std::string ZDisplayList::GetSourceOutputCode(const std::string& prefix) } } } - - if (parent != nullptr) - return ""; - - return sourceOutput; } std::string ZDisplayList::ProcessLegacy(const std::string& prefix) diff --git a/tools/ZAPD/ZAPD/ZDisplayList.h b/tools/ZAPD/ZAPD/ZDisplayList.h index d538666750..96808315dc 100644 --- a/tools/ZAPD/ZAPD/ZDisplayList.h +++ b/tools/ZAPD/ZAPD/ZDisplayList.h @@ -363,8 +363,7 @@ public: size_t GetRawDataSize() const override; DeclarationAlignment GetDeclarationAlignment() const override; - std::string GetSourceOutputHeader(const std::string& prefix) override; - std::string GetSourceOutputCode(const std::string& prefix) override; + void DeclareReferences(const std::string& prefix) override; std::string ProcessLegacy(const std::string& prefix); std::string ProcessGfxDis(const std::string& prefix); diff --git a/tools/ZAPD/ZAPD/ZFile.cpp b/tools/ZAPD/ZAPD/ZFile.cpp index 7cbfeba886..77387fc72c 100644 --- a/tools/ZAPD/ZAPD/ZFile.cpp +++ b/tools/ZAPD/ZAPD/ZFile.cpp @@ -13,6 +13,7 @@ #include "Utils/MemoryStream.h" #include "Utils/Path.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZAnimation.h" #include "ZArray.h" #include "ZBackground.h" @@ -73,19 +74,13 @@ ZFile::ZFile(ZFileMode nMode, tinyxml2::XMLElement* reader, const fs::path& nBas ZFile::~ZFile() { for (ZResource* res : resources) - { delete res; - } for (auto d : declarations) - { delete d.second; - } for (auto sym : symbolResources) - { delete sym.second; - } } void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) @@ -114,8 +109,11 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) else if (std::string_view(gameStr) == "OOT") Globals::Instance->game = ZGame::OOT_RETAIL; else - throw std::runtime_error( - StringHelper::Sprintf("Error: Game type %s not supported.", gameStr)); + { + std::string errorHeader = + StringHelper::Sprintf("'Game' type '%s' is not supported.", gameStr); + HANDLE_ERROR_PROCESS(WarningType::InvalidAttributeValue, errorHeader, ""); + } } if (reader->Attribute("BaseAddress") != nullptr) @@ -128,16 +126,22 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) rangeEnd = StringHelper::StrToL(reader->Attribute("RangeEnd"), 16); if (rangeStart > rangeEnd) - throw std::runtime_error("Error: RangeStart must be before than RangeEnd."); + HANDLE_ERROR_PROCESS( + WarningType::Always, + StringHelper::Sprintf("'RangeStart' 0x%06X must be before 'RangeEnd' 0x%06X", + rangeStart, rangeEnd), + ""); const char* segmentXml = reader->Attribute("Segment"); if (segmentXml != nullptr) { if (!StringHelper::HasOnlyDigits(segmentXml)) { - throw std::runtime_error(StringHelper::Sprintf( - "error: Invalid segment value '%s': must be a decimal between 0 and 15 inclusive", - segmentXml)); + HANDLE_ERROR_PROCESS(WarningType::Always, + StringHelper::Sprintf("error: Invalid segment value '%s': must be " + "a decimal between 0 and 15 inclusive", + segmentXml), + ""); } segment = StringHelper::StrToL(segmentXml, 10); @@ -146,16 +150,19 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) if (segment == 128) { #ifdef DEPRECATION_ON - fprintf(stderr, "warning: segment 128 is deprecated.\n\tRemove " - "'Segment=\"128\"' from the xml to use virtual addresses\n"); + HANDLE_WARNING_PROCESS( + WarningType::Always, "warning: segment 128 is deprecated.", + "Remove 'Segment=\"128\"' from the xml to use virtual addresses\n"); #endif } else { - throw std::runtime_error( + HANDLE_ERROR_PROCESS( + WarningType::Always, StringHelper::Sprintf("error: invalid segment value '%s': must be a decimal " "number between 0 and 15 inclusive", - segmentXml)); + segmentXml), + ""); } } } @@ -176,18 +183,16 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) if (mode == ZFileMode::Extract || mode == ZFileMode::ExternalFile) { if (!File::Exists((basePath / name).string())) - throw std::runtime_error( - StringHelper::Sprintf("Error! File %s does not exist.", (basePath / name).c_str())); + { + std::string errorHeader = StringHelper::Sprintf("binary file '%s' does not exist.", + (basePath / name).c_str()); + HANDLE_ERROR_PROCESS(WarningType::Always, errorHeader, ""); + } rawData = File::ReadAllBytes((basePath / name).string()); - /* - * TODO: In OoT repo ovl_Boss_Sst has a wrong RangeEnd (0xAD40 instead of 0xAD70), - * so uncommenting the following produces wrong behavior. - * If somebody fixes that in OoT repo, uncomment this. I'm too tired of fixing XMLs. - */ - // if (reader->Attribute("RangeEnd") == nullptr) - // rangeEnd = rawData.size(); + if (reader->Attribute("RangeEnd") == nullptr) + rangeEnd = rawData.size(); } std::unordered_set nameSet; @@ -211,20 +216,17 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) if (offsetSet.find(offsetXml) != offsetSet.end()) { - throw std::runtime_error(StringHelper::Sprintf( - "ZFile::ParseXML: Error in '%s'.\n\t Repeated 'Offset' attribute: %s \n", - name.c_str(), offsetXml)); + std::string errorHeader = + StringHelper::Sprintf("repeated 'Offset' attribute: %s", offsetXml); + HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, ""); } offsetSet.insert(offsetXml); } - else if (Globals::Instance->warnNoOffset) + else { - fprintf(stderr, "Warning No offset specified for: %s", nameXml); - } - else if (Globals::Instance->errorNoOffset) - { - throw std::runtime_error( - StringHelper::Sprintf("Error no offset specified for %s", nameXml)); + HANDLE_WARNING_RESOURCE(WarningType::MissingOffsets, this, nullptr, rawDataIndex, + StringHelper::Sprintf("no offset specified for %s.", nameXml), + ""); } if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO) @@ -234,9 +236,9 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) { if (outNameSet.find(outNameXml) != outNameSet.end()) { - throw std::runtime_error(StringHelper::Sprintf( - "ZFile::ParseXML: Error in '%s'.\n\t Repeated 'OutName' attribute: %s \n", - name.c_str(), outNameXml)); + std::string errorHeader = + StringHelper::Sprintf("repeated 'OutName' attribute: %s", outNameXml); + HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, ""); } outNameSet.insert(outNameXml); } @@ -244,9 +246,9 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) { if (nameSet.find(nameXml) != nameSet.end()) { - throw std::runtime_error(StringHelper::Sprintf( - "ZFile::ParseXML: Error in '%s'.\n\t Repeated 'Name' attribute: %s \n", - name.c_str(), nameXml)); + std::string errorHeader = + StringHelper::Sprintf("repeated 'Name' attribute: %s", nameXml); + HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, ""); } nameSet.insert(nameXml); } @@ -279,16 +281,14 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename) } else if (std::string_view(child->Name()) == "File") { - throw std::runtime_error(StringHelper::Sprintf( - "ZFile::ParseXML: Error in '%s'.\n\t Can't declare a File inside a File.\n", - name.c_str())); + std::string errorHeader = "Can't declare a inside a "; + HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, ""); } else { - throw std::runtime_error( - StringHelper::Sprintf("ZFile::ParseXML: Error in '%s'.\n\t Unknown element found " - "inside a File element: '%s'.\n", - name.c_str(), nodeName.c_str())); + std::string errorHeader = StringHelper::Sprintf( + "Unknown element found inside a element: %s", nodeName.c_str()); + HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, ""); } } } @@ -307,7 +307,7 @@ void ZFile::BuildSourceFile() return; if (!Directory::Exists(outputPath)) - Directory::CreateDirectory(outputPath); + Directory::CreateDirectory(outputPath.string()); GenerateSourceFiles(); } @@ -317,6 +317,11 @@ std::string ZFile::GetName() const return name; } +std::string ZFile::GetOutName() const +{ + return outName.string(); +} + ZFileMode ZFile::GetMode() const { return mode; @@ -338,10 +343,10 @@ void ZFile::ExtractResources() return; if (!Directory::Exists(outputPath)) - Directory::CreateDirectory(outputPath); + Directory::CreateDirectory(outputPath.string()); if (!Directory::Exists(GetSourceOutputFolderPath())) - Directory::CreateDirectory(GetSourceOutputFolderPath()); + Directory::CreateDirectory(GetSourceOutputFolderPath().string()); for (size_t i = 0; i < resources.size(); i++) resources[i]->ParseRawDataLate(); @@ -351,8 +356,8 @@ void ZFile::ExtractResources() if (Globals::Instance->genSourceFile) GenerateSourceFiles(); - MemoryStream* memStream = new MemoryStream(); - BinaryWriter writer = BinaryWriter(memStream); + auto memStreamFile = std::shared_ptr(new MemoryStream()); + BinaryWriter writerFile = BinaryWriter(memStreamFile); ExporterSet* exporterSet = Globals::Instance->GetExporterSet(); @@ -361,6 +366,9 @@ void ZFile::ExtractResources() for (ZResource* res : resources) { + auto memStreamRes = std::shared_ptr(new MemoryStream()); + BinaryWriter writerRes = BinaryWriter(memStreamRes); + if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO) printf("Saving resource %s\n", res->GetName().c_str()); @@ -369,18 +377,24 @@ void ZFile::ExtractResources() // Check if we have an exporter "registered" for this resource type ZResourceExporter* exporter = Globals::Instance->GetExporter(res->GetResourceType()); if (exporter != nullptr) - exporter->Save(res, Globals::Instance->outputPath.string(), &writer); + { + //exporter->Save(res, Globals::Instance->outputPath.string(), &writerFile); + exporter->Save(res, Globals::Instance->outputPath.string(), &writerRes); + } + + if (exporterSet != nullptr && exporterSet->resSaveFunc != nullptr) + exporterSet->resSaveFunc(res, writerRes); } - if (memStream->GetLength() > 0) + if (memStreamFile->GetLength() > 0) { File::WriteAllBytes(StringHelper::Sprintf("%s%s.bin", Globals::Instance->outputPath.string().c_str(), GetName().c_str()), - memStream->ToVector()); + memStreamFile->ToVector()); } - writer.Close(); + writerFile.Close(); if (exporterSet != nullptr && exporterSet->endFileFunc != nullptr) exporterSet->endFileFunc(this); @@ -1070,8 +1084,6 @@ std::string ZFile::ProcessDeclarations() } } - output += "\n"; - return output; } @@ -1234,11 +1246,12 @@ bool ZFile::HandleUnaccountedAddress(uint32_t currentAddress, uint32_t lastAddr, { Declaration* currentDecl = declarations.at(currentAddress); - fprintf(stderr, - "WARNING: Intersection detected from 0x%06X:0x%06X (%s), conflicts with " - "0x%06X (%s)\n", - lastAddr, lastAddr + lastSize, lastDecl->varName.c_str(), currentAddress, - currentDecl->varName.c_str()); + std::string intersectionInfo = StringHelper::Sprintf( + "Resource from 0x%06X:0x%06X (%s) conflicts with 0x%06X (%s).", lastAddr, + lastAddr + lastSize, lastDecl->varName.c_str(), currentAddress, + currentDecl->varName.c_str()); + HANDLE_WARNING_RESOURCE(WarningType::Intersection, this, nullptr, currentAddress, + "intersection detected", intersectionInfo); } } @@ -1309,25 +1322,17 @@ bool ZFile::HandleUnaccountedAddress(uint32_t currentAddress, uint32_t lastAddr, diff, src); decl->isUnaccounted = true; - if (Globals::Instance->warnUnaccounted) + if (nonZeroUnaccounted) { - if (nonZeroUnaccounted) - { - fprintf(stderr, - "Warning in file: %s (%s)\n" - "\t A non-zero unaccounted block was found at offset '0x%06X'.\n" - "\t Block size: '0x%X'.\n", - xmlFilePath.c_str(), name.c_str(), unaccountedAddress, diff); - } - else if (diff >= 16) - { - fprintf(stderr, - "Warning in file: %s (%s)\n" - "\t A big (size>=0x10) zero-only unaccounted block was found " - "at offset '0x%06X'.\n" - "\t Block size: '0x%X'.\n", - xmlFilePath.c_str(), name.c_str(), unaccountedAddress, diff); - } + HANDLE_WARNING_RESOURCE(WarningType::Unaccounted, this, nullptr, unaccountedAddress, + "a non-zero unaccounted block was found", + StringHelper::Sprintf("Block size: '0x%X'", diff)); + } + else if (diff >= 16) + { + HANDLE_WARNING_RESOURCE(WarningType::Unaccounted, this, nullptr, unaccountedAddress, + "a big (size>=0x10) zero-only unaccounted block was found", + StringHelper::Sprintf("Block size: '0x%X'", diff)); } } } diff --git a/tools/ZAPD/ZAPD/ZFile.h b/tools/ZAPD/ZAPD/ZFile.h index 9de6950e4a..7918d5f595 100644 --- a/tools/ZAPD/ZAPD/ZFile.h +++ b/tools/ZAPD/ZAPD/ZFile.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include @@ -46,6 +45,7 @@ public: ~ZFile(); std::string GetName() const; + std::string GetOutName() const; ZFileMode GetMode() const; const fs::path& GetXmlFilePath() const; const std::vector& GetRawData() const; diff --git a/tools/ZAPD/ZAPD/ZLimb.cpp b/tools/ZAPD/ZAPD/ZLimb.cpp index 77c66871fe..a47615d6c6 100644 --- a/tools/ZAPD/ZAPD/ZLimb.cpp +++ b/tools/ZAPD/ZAPD/ZLimb.cpp @@ -4,7 +4,7 @@ #include "Globals.h" #include "Utils/BitConverter.h" -#include "Utils/StringHelper.h" +#include "WarningHandler.h" REGISTER_ZFILENODE(Limb, ZLimb); @@ -37,17 +37,15 @@ void ZLimb::ParseXML(tinyxml2::XMLElement* reader) if (limbType == "") { - throw std::runtime_error(StringHelper::Sprintf("ZLimb::ParseXML: Error in '%s'.\n" - "\t Missing 'LimbType' attribute in xml.\n", - name.c_str())); + HANDLE_ERROR_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex, + "missing 'LimbType' attribute in ", ""); } type = GetTypeByAttributeName(limbType); if (type == ZLimbType::Invalid) { - throw std::runtime_error(StringHelper::Sprintf("ZLimb::ParseXML: Error in '%s'.\n" - "\t Invalid 'LimbType' found: '%s'.\n", - name.c_str(), limbType.c_str())); + HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + "invalid value found for 'LimbType' attribute", ""); } } @@ -109,8 +107,12 @@ void ZLimb::ParseRawData() } break; - default: - throw std::runtime_error("Invalid ZLimb type"); + case ZLimbType::Curve: + case ZLimbType::Legacy: + break; + + case ZLimbType::Invalid: + assert(!"whoops"); break; } } diff --git a/tools/ZAPD/ZAPD/ZPath.cpp b/tools/ZAPD/ZAPD/ZPath.cpp index 4a95c5b91e..e19513db34 100644 --- a/tools/ZAPD/ZAPD/ZPath.cpp +++ b/tools/ZAPD/ZAPD/ZPath.cpp @@ -3,6 +3,7 @@ #include "Globals.h" #include "Utils/BitConverter.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZFile.h" REGISTER_ZFILENODE(Path, ZPath); @@ -20,10 +21,12 @@ void ZPath::ParseXML(tinyxml2::XMLElement* reader) numPaths = StringHelper::StrToL(registeredAttributes.at("NumPaths").value); if (numPaths < 1) - throw std::runtime_error( - StringHelper::Sprintf("ZPath::ParseXML: Fatal error in '%s'.\n" - "\t Invalid value for attribute 'NumPaths': '%i'\n", - name.c_str(), numPaths)); + { + HANDLE_ERROR_RESOURCE( + WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + StringHelper::Sprintf("invalid value '%d' found for 'NumPaths' attribute", numPaths), + "Should be at least '1'"); + } } void ZPath::ParseRawData() @@ -144,7 +147,7 @@ void PathwayEntry::DeclareReferences(const std::string& prefix) if (addressFound) return; - std::string declaration; + std::string declaration = ""; size_t index = 0; for (const auto& point : points) diff --git a/tools/ZAPD/ZAPD/ZResource.cpp b/tools/ZAPD/ZAPD/ZResource.cpp index cb811f4c3b..2dfe6d5eaa 100644 --- a/tools/ZAPD/ZAPD/ZResource.cpp +++ b/tools/ZAPD/ZAPD/ZResource.cpp @@ -4,6 +4,7 @@ #include #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZFile.h" ZResource::ZResource(ZFile* nParent) @@ -85,29 +86,33 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader) } if (!attrDeclared) - fprintf(stderr, - "ZResource::ParseXML: Warning while parsing '%s'.\n" - "\t Unexpected '%s' attribute in resource '%s'.\n", - parent->GetName().c_str(), attrName.c_str(), reader->Name()); + { + HANDLE_WARNING_RESOURCE( + WarningType::UnknownAttribute, parent, this, rawDataIndex, + StringHelper::Sprintf("unexpected '%s' attribute in resource <%s>", + attrName.c_str(), reader->Name()), + ""); + } attrs = attrs->Next(); } if (!canHaveInner && !reader->NoChildren()) { - throw std::runtime_error( - StringHelper::Sprintf("ZResource::ParseXML: Fatal error in '%s'.\n" - "\t Resource '%s' with inner element/child detected.\n", - name.c_str(), reader->Name())); + std::string errorHeader = StringHelper::Sprintf( + "resource '%s' with inner element/child detected", reader->Name()); + HANDLE_ERROR_PROCESS(WarningType::InvalidXML, errorHeader, ""); } for (const auto& attr : registeredAttributes) { if (attr.second.isRequired && attr.second.value == "") - throw std::runtime_error(StringHelper::Sprintf( - "ZResource::ParseXML: Fatal error while parsing '%s'.\n" - "\t Missing required attribute '%s' in resource '%s'.\n" - "\t Aborting...", - parent->GetName().c_str(), attr.first.c_str(), reader->Name())); + { + std::string headerMsg = + StringHelper::Sprintf("missing required attribute '%s' in resource <%s>", + attr.first.c_str(), reader->Name()); + HANDLE_ERROR_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex, + headerMsg, ""); + } } name = registeredAttributes.at("Name").value; @@ -118,10 +123,8 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader) { if (!std::regex_match(name, r)) { - throw std::domain_error( - StringHelper::Sprintf("ZResource::ParseXML: Fatal error in '%s'.\n" - "\t Resource with invalid 'Name' attribute.\n", - name.c_str())); + HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, + rawDataIndex, "invalid value found for 'Name' attribute", ""); } } @@ -146,7 +149,9 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader) } else { - throw std::runtime_error("Invalid value for 'Static' attribute."); + HANDLE_ERROR_RESOURCE( + WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + StringHelper::Sprintf("invalid value '%s' for 'Static' attribute", staticConf), ""); } declaredInXml = true; @@ -253,18 +258,21 @@ std::string ZResource::GetDefaultName(const std::string& prefix) const rawDataIndex); } -std::string ZResource::GetSourceOutputCode([[maybe_unused]] const std::string& prefix) +void ZResource::GetSourceOutputCode([[maybe_unused]] const std::string& prefix) { std::string bodyStr = GetBodySourceCode(); - Declaration* decl = parent->GetDeclaration(rawDataIndex); - if (decl == nullptr || decl->isPlaceholder) - decl = DeclareVar(prefix, bodyStr); - else - decl->text = bodyStr; - decl->staticConf = staticConf; + if (bodyStr != "ERROR") + { + Declaration* decl = parent->GetDeclaration(rawDataIndex); - return ""; + if (decl == nullptr || decl->isPlaceholder) + decl = DeclareVar(prefix, bodyStr); + else + decl->text = bodyStr; + + decl->staticConf = staticConf; + } } std::string ZResource::GetSourceOutputHeader([[maybe_unused]] const std::string& prefix) @@ -312,13 +320,13 @@ offset_t Seg2Filespace(segptr_t segmentedAddress, uint32_t parentBaseAddress) uint32_t parentBaseOffset = GETSEGOFFSET(parentBaseAddress); if (parentBaseOffset > currentPtr) { - throw std::runtime_error( - StringHelper::Sprintf("\nSeg2Filespace: Segmented address is smaller than " - "'BaseAddress'. Maybe your 'BaseAddress' is wrong?\n" - "\t SegmentedAddress: 0x%08X\n" - "\t BaseAddress: 0x%08X\n", - segmentedAddress, parentBaseAddress)); + HANDLE_ERROR(WarningType::Always, + StringHelper::Sprintf( + "resource address 0x%08X is smaller than 'BaseAddress' 0x%08X", + segmentedAddress, parentBaseAddress), + "Maybe your 'BaseAddress' is wrong?"); } + currentPtr -= parentBaseOffset; } diff --git a/tools/ZAPD/ZAPD/ZResource.h b/tools/ZAPD/ZAPD/ZResource.h index ff35786fac..4dad398955 100644 --- a/tools/ZAPD/ZAPD/ZResource.h +++ b/tools/ZAPD/ZAPD/ZResource.h @@ -1,16 +1,15 @@ #pragma once -#include +#include #include #include -#include #include #include #include "Declaration.h" +#include "Utils/BinaryWriter.h" +#include "Utils/Directory.h" #include "tinyxml2.h" -#include - #define SEGMENT_SCENE 2 #define SEGMENT_ROOM 3 #define SEGMENT_KEEP 4 @@ -113,7 +112,7 @@ public: */ [[nodiscard]] virtual std::string GetDefaultName(const std::string& prefix) const; - virtual std::string GetSourceOutputCode(const std::string& prefix); + virtual void GetSourceOutputCode(const std::string& prefix); virtual std::string GetSourceOutputHeader(const std::string& prefix); virtual void CalcHash(); /** diff --git a/tools/ZAPD/ZAPD/ZRoom/Commands/SetMesh.cpp b/tools/ZAPD/ZAPD/ZRoom/Commands/SetMesh.cpp index d1c8abd5c5..69668c49c1 100644 --- a/tools/ZAPD/ZAPD/ZRoom/Commands/SetMesh.cpp +++ b/tools/ZAPD/ZAPD/ZRoom/Commands/SetMesh.cpp @@ -1,8 +1,10 @@ #include "SetMesh.h" -#include -#include + +#include "Globals.h" #include "Utils/BitConverter.h" +#include "Utils/Path.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZBackground.h" #include "ZFile.h" #include "ZRoom/ZRoom.h" @@ -34,9 +36,8 @@ void SetMesh::ParseRawData() break; default: - throw std::runtime_error(StringHelper::Sprintf("Error in SetMesh::ParseRawData\n" - "\t Unknown meshHeaderType: %i\n", - meshHeaderType)); + HANDLE_ERROR(WarningType::InvalidExtractedData, + StringHelper::Sprintf("unknown meshHeaderType: %i", meshHeaderType), ""); } polyType->ParseRawData(); @@ -53,11 +54,9 @@ void SetMesh::DeclareReferences(const std::string& prefix) void GenDListDeclarations(ZRoom* zRoom, ZFile* parent, ZDisplayList* dList) { if (dList == nullptr) - { return; - } - std::string sourceOutput = dList->GetSourceOutputCode(zRoom->GetName()); + dList->DeclareReferences(zRoom->GetName()); for (ZDisplayList* otherDList : dList->otherDLists) GenDListDeclarations(zRoom, parent, otherDList); @@ -143,21 +142,17 @@ std::string PolygonDlist::GetBodySourceCode() const return bodyStr; } -std::string PolygonDlist::GetSourceOutputCode(const std::string& prefix) +void PolygonDlist::GetSourceOutputCode(const std::string& prefix) { std::string bodyStr = StringHelper::Sprintf("\n\t%s\n", GetBodySourceCode().c_str()); Declaration* decl = parent->GetDeclaration(rawDataIndex); - if (decl == nullptr) - { - DeclareVar(prefix, bodyStr); - } - else - { - decl->text = bodyStr; - } - return ""; + if (decl == nullptr) + DeclareVar(prefix, bodyStr); + else + decl->text = bodyStr; + } std::string PolygonDlist::GetSourceTypeName() const @@ -472,8 +467,8 @@ void PolygonType1::DeclareReferences(const std::string& prefix) break; default: - throw std::runtime_error(StringHelper::Sprintf( - "Error in PolygonType1::PolygonType1\n\t Unknown format: %i\n", format)); + HANDLE_ERROR(WarningType::InvalidExtractedData, + StringHelper::Sprintf("unknown format: %i", format), ""); break; } } @@ -582,9 +577,11 @@ void PolygonType2::DeclareReferences(const std::string& prefix) polyDListName = StringHelper::Sprintf("%s%s_%06X", prefix.c_str(), polyDlistType.c_str(), GETSEGOFFSET(start)); - parent->AddDeclarationArray(GETSEGOFFSET(start), DeclarationAlignment::Align4, - polyDLists.size() * polyDLists.at(0).GetRawDataSize(), - polyDlistType, polyDListName, polyDLists.size(), declaration); + Declaration* decl = parent->AddDeclarationArray( + GETSEGOFFSET(start), DeclarationAlignment::Align4, + polyDLists.size() * polyDLists.at(0).GetRawDataSize(), polyDlistType, polyDListName, + polyDLists.size(), declaration); + decl->forceArrayCnt = true; } parent->AddDeclaration(GETSEGOFFSET(end), DeclarationAlignment::Align4, 4, "s32", diff --git a/tools/ZAPD/ZAPD/ZRoom/Commands/SetMesh.h b/tools/ZAPD/ZAPD/ZRoom/Commands/SetMesh.h index 566711a9a7..9d9037417b 100644 --- a/tools/ZAPD/ZAPD/ZRoom/Commands/SetMesh.h +++ b/tools/ZAPD/ZAPD/ZRoom/Commands/SetMesh.h @@ -28,7 +28,7 @@ public: std::string GetBodySourceCode() const override; - std::string GetSourceOutputCode(const std::string& prefix) override; + void GetSourceOutputCode(const std::string& prefix) override; std::string GetSourceTypeName() const override; ZResourceType GetResourceType() const override; diff --git a/tools/ZAPD/ZAPD/ZRoom/Commands/SetRoomList.cpp b/tools/ZAPD/ZAPD/ZRoom/Commands/SetRoomList.cpp index 43c3968221..7027fa1f98 100644 --- a/tools/ZAPD/ZAPD/ZRoom/Commands/SetRoomList.cpp +++ b/tools/ZAPD/ZAPD/ZRoom/Commands/SetRoomList.cpp @@ -115,11 +115,9 @@ std::string RomFile::GetBodySourceCode() const return declaration; } -std::string RomFile::GetSourceOutputCode(const std::string& prefix) +void RomFile::GetSourceOutputCode(const std::string& prefix) { DeclareVar(prefix, GetBodySourceCode()); - - return ""; } std::string RomFile::GetSourceTypeName() const diff --git a/tools/ZAPD/ZAPD/ZRoom/Commands/SetRoomList.h b/tools/ZAPD/ZAPD/ZRoom/Commands/SetRoomList.h index 4fb2ced176..2ae48b68df 100644 --- a/tools/ZAPD/ZAPD/ZRoom/Commands/SetRoomList.h +++ b/tools/ZAPD/ZAPD/ZRoom/Commands/SetRoomList.h @@ -24,7 +24,7 @@ public: Declaration* DeclareVar(const std::string& prefix, const std::string& body) override; std::string GetBodySourceCode() const override; - std::string GetSourceOutputCode(const std::string& prefix) override; + void GetSourceOutputCode(const std::string& prefix) override; std::string GetSourceTypeName() const override; virtual ZResourceType GetResourceType() const override; diff --git a/tools/ZAPD/ZAPD/ZRoom/ZRoom.cpp b/tools/ZAPD/ZAPD/ZRoom/ZRoom.cpp index edc0cad029..c7e60d3592 100644 --- a/tools/ZAPD/ZAPD/ZRoom/ZRoom.cpp +++ b/tools/ZAPD/ZAPD/ZRoom/ZRoom.cpp @@ -40,6 +40,7 @@ #include "Utils/File.h" #include "Utils/Path.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZBlob.h" #include "ZCutscene.h" #include "ZFile.h" @@ -123,10 +124,12 @@ void ZRoom::ParseXML(tinyxml2::XMLElement* reader) { hackMode = std::string(reader->Attribute("HackMode")); if (hackMode != "syotes_room") - throw std::runtime_error( - StringHelper::Sprintf("ZRoom::ParseXML: Fatal error in '%s'.\n" - "\t Invalid value for attribute 'HackMode': '%s'\n", - name.c_str(), hackMode.c_str())); + { + std::string headerError = StringHelper::Sprintf( + "invalid value found for 'HackMode' attribute: '%s'", hackMode.c_str()); + HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + headerError, ""); + } } } @@ -392,14 +395,10 @@ size_t ZRoom::GetCommandSizeFromNeighbor(ZRoomCommand* cmd) return 0; } -std::string ZRoom::GetSourceOutputCode([[maybe_unused]] const std::string& prefix) +void ZRoom::GetSourceOutputCode([[maybe_unused]] const std::string& prefix) { - if (hackMode == "syotes_room") - return ""; - - DeclareVar(prefix, GetBodySourceCode()); - - return ""; + if (hackMode != "syotes_room") + DeclareVar(prefix, GetBodySourceCode()); } size_t ZRoom::GetRawDataSize() const diff --git a/tools/ZAPD/ZAPD/ZRoom/ZRoom.h b/tools/ZAPD/ZAPD/ZRoom/ZRoom.h index 0993a9d302..e837ec70ac 100644 --- a/tools/ZAPD/ZAPD/ZRoom/ZRoom.h +++ b/tools/ZAPD/ZAPD/ZRoom/ZRoom.h @@ -34,7 +34,7 @@ public: Declaration* DeclareVar(const std::string& prefix, const std::string& body) override; std::string GetBodySourceCode() const override; - std::string GetSourceOutputCode(const std::string& prefix) override; + void GetSourceOutputCode(const std::string& prefix) override; std::string GetDefaultName(const std::string& prefix) const override; size_t GetDeclarationSizeFromNeighbor(uint32_t declarationAddress); diff --git a/tools/ZAPD/ZAPD/ZScalar.cpp b/tools/ZAPD/ZAPD/ZScalar.cpp index 062fb0e079..7e4be4d57f 100644 --- a/tools/ZAPD/ZAPD/ZScalar.cpp +++ b/tools/ZAPD/ZAPD/ZScalar.cpp @@ -4,6 +4,7 @@ #include "Utils/BitConverter.h" #include "Utils/File.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZFile.h" REGISTER_ZFILENODE(Scalar, ZScalar); @@ -207,8 +208,8 @@ void ZScalar::ParseRawData() scalarData.f64 = BitConverter::ToDoubleBE(rawData, rawDataIndex); break; case ZScalarType::ZSCALAR_NONE: - fprintf(stderr, "Warning in ZScalar: Invalid type. %d %s %d\n", (int32_t)scalarType, - __FILE__, __LINE__); + HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + "invalid value found for 'Type' attribute", "Defaulting to ''"); break; } } diff --git a/tools/ZAPD/ZAPD/ZScalar.h b/tools/ZAPD/ZAPD/ZScalar.h index d269995cca..8f98f261d7 100644 --- a/tools/ZAPD/ZAPD/ZScalar.h +++ b/tools/ZAPD/ZAPD/ZScalar.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include "ZResource.h" diff --git a/tools/ZAPD/ZAPD/ZSkeleton.cpp b/tools/ZAPD/ZAPD/ZSkeleton.cpp index 84f00c8187..1a2f93ff7b 100644 --- a/tools/ZAPD/ZAPD/ZSkeleton.cpp +++ b/tools/ZAPD/ZAPD/ZSkeleton.cpp @@ -5,6 +5,7 @@ #include "Globals.h" #include "Utils/BitConverter.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" REGISTER_ZFILENODE(Skeleton, ZSkeleton); REGISTER_ZFILENODE(LimbTable, ZLimbTable); @@ -27,18 +28,19 @@ void ZSkeleton::ParseXML(tinyxml2::XMLElement* reader) type = ZSkeletonType::Curve; else if (skelTypeXml != "Normal") { - throw std::runtime_error(StringHelper::Sprintf("ZSkeleton::ParseXML: Error in '%s'.\n" - "\t Invalid Type found: '%s'.\n", - name.c_str(), skelTypeXml.c_str())); + HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + "invalid value found for 'Type' attribute", ""); } std::string limbTypeXml = registeredAttributes.at("LimbType").value; limbType = ZLimb::GetTypeByAttributeName(limbTypeXml); if (limbType == ZLimbType::Invalid) { - throw std::runtime_error(StringHelper::Sprintf("ZSkeleton::ParseXML: Error in '%s'.\n" - "\t Invalid LimbType found: '%s'.\n", - name.c_str(), limbTypeXml.c_str())); + HANDLE_ERROR_RESOURCE( + WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + StringHelper::Sprintf("invalid value '%s' found for 'LimbType' attribute", + limbTypeXml.c_str()), + "Defaulting to 'Standard'."); } } @@ -170,11 +172,9 @@ void ZLimbTable::ParseXML(tinyxml2::XMLElement* reader) limbType = ZLimb::GetTypeByAttributeName(limbTypeXml); if (limbType == ZLimbType::Invalid) { - fprintf(stderr, - "ZLimbTable::ParseXML: Warning in '%s'.\n" - "\t Invalid LimbType found: '%s'.\n" - "\t Defaulting to 'Standard'.\n", - name.c_str(), limbTypeXml.c_str()); + HANDLE_WARNING_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + "invalid value found for 'LimbType' attribute.", + "Defaulting to 'Standard'."); limbType = ZLimbType::Standard; } diff --git a/tools/ZAPD/ZAPD/ZSymbol.cpp b/tools/ZAPD/ZAPD/ZSymbol.cpp index b24c3de4b0..eabfc2faae 100644 --- a/tools/ZAPD/ZAPD/ZSymbol.cpp +++ b/tools/ZAPD/ZAPD/ZSymbol.cpp @@ -1,6 +1,7 @@ #include "ZSymbol.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZFile.h" REGISTER_ZFILENODE(Symbol, ZSymbol); @@ -20,11 +21,8 @@ void ZSymbol::ParseXML(tinyxml2::XMLElement* reader) if (typeXml == "") { - fprintf(stderr, - "ZSymbol::ParseXML: Warning in '%s'.\n" - "\t Missing 'Type' attribute in xml.\n" - "\t Defaulting to 'void*'.\n", - name.c_str()); + HANDLE_WARNING_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex, + "missing 'Type' attribute in ", "Defaulting to 'void*'."); type = "void*"; } else @@ -35,11 +33,8 @@ void ZSymbol::ParseXML(tinyxml2::XMLElement* reader) std::string typeSizeXml = registeredAttributes.at("TypeSize").value; if (typeSizeXml == "") { - fprintf(stderr, - "ZSymbol::ParseXML: Warning in '%s'.\n" - "\t Missing 'TypeSize' attribute in xml.\n" - "\t Defaulting to '4'.\n", - name.c_str()); + HANDLE_WARNING_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex, + "missing 'TypeSize' attribute in ", "Defaulting to '4'."); typeSize = 4; // Size of a word. } else @@ -58,7 +53,9 @@ void ZSymbol::ParseXML(tinyxml2::XMLElement* reader) if (registeredAttributes.at("Static").value == "On") { - fprintf(stderr, "A can't be marked as static.\n\t Disabling static\n"); + HANDLE_WARNING_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + "a cannot be marked as static", + "Disabling static for this resource."); } staticConf = StaticConfig::Off; } diff --git a/tools/ZAPD/ZAPD/ZTexture.cpp b/tools/ZAPD/ZAPD/ZTexture.cpp index 33ee54d1bc..7bd31438b4 100644 --- a/tools/ZAPD/ZAPD/ZTexture.cpp +++ b/tools/ZAPD/ZAPD/ZTexture.cpp @@ -8,6 +8,7 @@ #include "Utils/Directory.h" #include "Utils/File.h" #include "Utils/Path.h" +#include "WarningHandler.h" REGISTER_ZFILENODE(Texture, ZTexture); @@ -57,17 +58,17 @@ void ZTexture::ParseXML(tinyxml2::XMLElement* reader) if (!StringHelper::HasOnlyDigits(widthXml)) { - throw std::runtime_error( - StringHelper::Sprintf("ZTexture::ParseXML: Error in %s\n" - "\t Value of 'Width' attribute has non-decimal digits: '%s'.\n", - name.c_str(), widthXml.c_str())); + std::string errorHeader = StringHelper::Sprintf( + "value of 'Width' attribute has non-decimal digits: '%s'", widthXml.c_str()); + HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + errorHeader, ""); } if (!StringHelper::HasOnlyDigits(heightXml)) { - throw std::runtime_error( - StringHelper::Sprintf("ZTexture::ParseXML: Error in %s\n" - "\t Value of 'Height' attribute has non-decimal digits: '%s'.\n", - name.c_str(), heightXml.c_str())); + std::string errorHeader = StringHelper::Sprintf( + "value of 'Height' attribute has non-decimal digits: '%s'", heightXml.c_str()); + HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + errorHeader, ""); } width = StringHelper::StrToL(widthXml); @@ -77,7 +78,10 @@ void ZTexture::ParseXML(tinyxml2::XMLElement* reader) format = GetTextureTypeFromString(formatStr); if (format == TextureType::Error) - throw std::runtime_error("Format " + formatStr + " is not supported!"); + { + HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + "invalid value found for 'Format' attribute", ""); + } const auto& tlutOffsetAttr = registeredAttributes.at("TlutOffset"); if (tlutOffsetAttr.wasSet) @@ -90,10 +94,9 @@ void ZTexture::ParseXML(tinyxml2::XMLElement* reader) break; default: - throw std::runtime_error(StringHelper::Sprintf( - "ZTexture::ParseXML: Error in %s\n" - "\t 'TlutOffset' declared in non color-indexed (ci4 or ci8) texture.\n", - name.c_str())); + HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex, + "'TlutOffset' declared in non color-indexed (ci4 or ci8) texture", + ""); break; } } @@ -102,10 +105,10 @@ void ZTexture::ParseXML(tinyxml2::XMLElement* reader) void ZTexture::ParseRawData() { if (rawDataIndex % 8 != 0) - fprintf(stderr, - "ZTexture::ParseXML: Warning in '%s'.\n" - "\t This texture is not 64-bit aligned.\n", - name.c_str()); + { + HANDLE_WARNING_RESOURCE(WarningType::NotImplemented, parent, this, rawDataIndex, + "this texture is not 64-bit aligned", ""); + } switch (format) { @@ -136,8 +139,11 @@ void ZTexture::ParseRawData() case TextureType::Palette8bpp: PrepareBitmapPalette8(); break; - default: - throw std::runtime_error("Format is not supported!"); + case TextureType::Error: + HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex, + StringHelper::Sprintf("Invalid texture format", format), ""); + assert(!"TODO"); + break; } } @@ -375,8 +381,9 @@ void ZTexture::PrepareRawDataFromFile(const fs::path& pngFilePath) case TextureType::Palette8bpp: PrepareRawDataPalette8(pngFilePath); break; - default: - throw std::runtime_error("Format is not supported!"); + case TextureType::Error: + HANDLE_ERROR_PROCESS(WarningType::InvalidPNG, "Input PNG file has invalid format type", ""); + break; } } @@ -860,13 +867,9 @@ TextureType ZTexture::GetTextureTypeFromString(const std::string& str) else if (str == "rgb5a1") { texType = TextureType::RGBA16bpp; -#ifdef DEPRECATION_ON - fprintf(stderr, "ZTexture::GetTextureTypeFromString: Deprecation warning.\n" - "\t The texture format 'rgb5a1' is currently deprecated, and will be " - "removed in a future " - "version.\n" - "\t Use the format 'rgba16' instead.\n"); -#endif + HANDLE_WARNING(WarningType::Deprecated, + "the texture format 'rgb5a1' is currently deprecated", + "It will be removed in a future version. Use the format 'rgba16' instead."); } else if (str == "i4") texType = TextureType::Grayscale4bpp; @@ -883,7 +886,9 @@ TextureType ZTexture::GetTextureTypeFromString(const std::string& str) else if (str == "ci8") texType = TextureType::Palette8bpp; else - fprintf(stderr, "Encountered Unknown Texture format %s \n", str.c_str()); + // TODO: handle this case in a more coherent way + HANDLE_WARNING(WarningType::InvalidAttributeValue, + "invalid value found for 'Type' attribute", "Defaulting to ''."); return texType; } diff --git a/tools/ZAPD/ZAPD/ZTextureAnimation.cpp b/tools/ZAPD/ZAPD/ZTextureAnimation.cpp index 4332fcf1e5..698054fa87 100644 --- a/tools/ZAPD/ZAPD/ZTextureAnimation.cpp +++ b/tools/ZAPD/ZAPD/ZTextureAnimation.cpp @@ -2,8 +2,8 @@ * File: ZTextureAnimation.cpp * ZResources defined: ZTextureAnimation, ZTextureAnimationParams (XML declaration not supported for * the latter) - * Purpose: extracting texture animating structures from asset files Note: data type is exclusive to - * Majora's Mask + * Purpose: extracting texture animating structures from asset files + * Note: data type is exclusive to Majora's Mask * * Structure of data: * A texture animation consists of a main array of data of the form @@ -82,6 +82,7 @@ #include "Globals.h" #include "Utils/BitConverter.h" +#include "WarningHandler.h" #include "ZFile.h" #include "ZResource.h" #include "tinyxml2.h" @@ -115,7 +116,7 @@ void ZTextureAnimationParams::ExtractFromBinary(uint32_t nRawDataIndex) ParseRawData(); } -// Implemented by TextureScrollingParams only[ +// Implemented by TextureScrollingParams only void ZTextureAnimationParams::ExtractFromBinary([[maybe_unused]] uint32_t nRawDataIndex, [[maybe_unused]] int count) { @@ -217,19 +218,8 @@ void TextureColorChangingParams::ParseRawData() ((type == TextureAnimationParamsType::ColorChange) ? animLength : colorListCount); if (listLength == 0) - throw std::runtime_error(StringHelper::Sprintf( - "When processing file %s: in input binary file %s, offset 0x%06X:" - "\n\t" - "\033[97m" - "TextureColorChangingParams::ParseRawData:" - "\033[0m" - "\033[91m" - " error: " - "\033[0m" - "\033[97m" - "color list length cannot be 0\n" - "\033[0m", - Globals::Instance->inputPath.c_str(), parent->GetName().c_str(), rawDataIndex)); + HANDLE_ERROR_RESOURCE(WarningType::Always, parent, this, rawDataIndex, + "color list length cannot be 0", ""); primColorListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 4); envColorListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8); @@ -378,20 +368,8 @@ void TextureCyclingParams::ParseRawData() cycleLength = BitConverter::ToUInt16BE(rawData, rawDataIndex); if (cycleLength == 0) - throw std::runtime_error( - StringHelper::Sprintf("When processing file %s: in input binary file %s, offset 0x%06X:" - "\n\t" - "\033[97m" - "TextureCyclingParams::ParseRawData:" - "\033[0m" - "\033[91m" - " error: " - "\033[0m" - "\033[97m" - "cycleLength cannot be 0\n" - "\033[0m", - Globals::Instance->inputPath.c_str(), parent->GetName().c_str(), - Seg2Filespace(rawDataIndex, 0))); + HANDLE_ERROR_RESOURCE(WarningType::Always, parent, this, rawDataIndex, + "cycle length cannot be 0", ""); textureListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 4); textureIndexListAddress = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8); @@ -454,21 +432,12 @@ void TextureCyclingParams::DeclareReferences([[maybe_unused]] const std::string& { comment = " // Raw pointer, declare texture in XML to use proper symbol"; - fprintf(stderr, - "When processing file %s: in input binary file %s, offset 0x%06X:" - "\n\t" - "\033[97m" - "TextureCyclingParams::DeclareReferences:" - "\033[0m" - "\033[95m" - " warning: " - "\033[0m" - "\033[97m" - "TexCycle declared here points to unknown texture at address %s. " - "Please declare the texture in the XML to use the proper symbol.\n" - "\033[0m", - Globals::Instance->inputPath.c_str(), parent->GetName().c_str(), - Seg2Filespace(textureListAddress, parent->baseAddress), texName.c_str()); + auto msgHeader = StringHelper::Sprintf( + "TexCycle texture array declared here points to unknown texture at address %s", + texName.c_str()); + HANDLE_WARNING_RESOURCE( + WarningType::HardcodedPointer, parent, this, rawDataIndex, msgHeader, + "Please declare the texture in the XML to use the proper symbol."); } texturesBodyStr += StringHelper::Sprintf("\t%s,%s\n", texName.c_str(), comment.c_str()); } @@ -546,22 +515,14 @@ void ZTextureAnimation::ParseRawData() if ((type < 0) || (type > 6)) { - throw std::runtime_error(StringHelper::Sprintf( - "When processing file %s: in input binary file %s, offset 0x%06X:" - "\n\t" - "\033[97m" - "ZTextureAnimation::ParseRawData:" - "\033[0m" - "\033[91m" - " error: " - "\033[0m" - "\033[97m" - "unknown TextureAnimationParams type 0x%02X in TextureAnimation: entry reads\n\t{ " - "0x%02X, 0x%02X, 0x%08X }\n(type should be between " - "0x00 and 0x06)\n" - "\033[0m", - Globals::Instance->inputPath.c_str(), parent->GetName().c_str(), rawDataIndex, type, - currentEntry.segment, type, currentEntry.paramsPtr)); + HANDLE_ERROR_RESOURCE( + WarningType::Always, parent, this, rawDataIndex, + StringHelper::Sprintf( + "unknown TextureAnimationParams type 0x%02X in TextureAnimation", type), + StringHelper::Sprintf( + "Entry reads { 0x%02X, 0x%02X, 0x%08X } , but type should be " + "between 0x00 and 0x06 inclusive.", + currentEntry.segment, type, currentEntry.paramsPtr)); } if (currentEntry.segment <= 0) @@ -589,13 +550,24 @@ void ZTextureAnimation::DeclareReferences(const std::string& prefix) if (!parent->HasDeclaration(paramsOffset)) { ZTextureAnimationParams* params; - int count = 2; + int count; switch (entry.type) { case TextureAnimationParamsType::SingleScroll: - count = 1; - [[fallthrough]]; - case TextureAnimationParamsType::DualScroll: + if (true) + { + count = 1; + // The else now allows SingleScroll to fall through to params = ... without + // touching the code in the else block + } + else + { + // The contents of this block can only be run by jumping into it with the + // case label + [[fallthrough]]; + case TextureAnimationParamsType::DualScroll: + count = 2; + } params = new TextureScrollingParams(parent); params->ExtractFromBinary(paramsOffset, count); break; @@ -614,22 +586,12 @@ void ZTextureAnimation::DeclareReferences(const std::string& prefix) break; case TextureAnimationParamsType::Empty: - fprintf(stderr, - "When processing file %s: in input binary file %s: offset 0x%06X:" - "\n\t" - "\033[97m" - "ZTextureAnimation::DeclareReferences:" - "\033[0m" - "\033[95m" - " warning: " - "\033[0m" - "\033[97m" - "TextureAnimationParams entry has empty type (6), but params pointer " - "is not NULL. Params read\n\t\t" - "{ 0x%02X, 0x%02X, 0x%08X }\n" - "\033[0m", - Globals::Instance->inputPath.c_str(), parent->GetName().c_str(), - rawDataIndex, entry.segment, (int)entry.type, entry.paramsPtr); + HANDLE_WARNING_RESOURCE( + WarningType::InvalidExtractedData, parent, this, rawDataIndex, + "TextureAnimationParams entry has empty type (6), but params pointer is " + "not NULL", + StringHelper::Sprintf("Params read { 0x%02X, 0x%02X, 0x%08X } .", + entry.segment, (int)entry.type, entry.paramsPtr)); return; default: // Because GCC is worried this could happen diff --git a/tools/ZAPD/ZAPD/ZVector.cpp b/tools/ZAPD/ZAPD/ZVector.cpp index c940b0b0de..a5a059e354 100644 --- a/tools/ZAPD/ZAPD/ZVector.cpp +++ b/tools/ZAPD/ZAPD/ZVector.cpp @@ -6,6 +6,7 @@ #include "Utils/BitConverter.h" #include "Utils/File.h" #include "Utils/StringHelper.h" +#include "WarningHandler.h" #include "ZFile.h" REGISTER_ZFILENODE(Vector, ZVector); @@ -86,20 +87,18 @@ std::string ZVector::GetSourceTypeName() const return "Vec3i"; else { - std::string output = StringHelper::Sprintf( - "Encountered unsupported vector type: %d dimensions, %s type", dimensions, + std::string msgHeader = StringHelper::Sprintf( + "encountered unsupported vector type: %d dimensions, %s type", dimensions, ZScalar::MapScalarTypeToOutputType(scalarType).c_str()); - if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG) - printf("%s\n", output.c_str()); - - throw std::runtime_error(output); + HANDLE_ERROR_RESOURCE(WarningType::NotImplemented, parent, this, rawDataIndex, msgHeader, + ""); } } std::string ZVector::GetBodySourceCode() const { - std::string body; + std::string body = ""; for (size_t i = 0; i < scalars.size(); i++) { diff --git a/tools/ZAPD/ZAPD/ZVector.h b/tools/ZAPD/ZAPD/ZVector.h index d1a738968d..a50d3e8083 100644 --- a/tools/ZAPD/ZAPD/ZVector.h +++ b/tools/ZAPD/ZAPD/ZVector.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include "ZResource.h" diff --git a/tools/ZAPD/ZAPD/ZVtx.h b/tools/ZAPD/ZAPD/ZVtx.h index 018a1d4a9a..511048791d 100644 --- a/tools/ZAPD/ZAPD/ZVtx.h +++ b/tools/ZAPD/ZAPD/ZVtx.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include "ZResource.h" diff --git a/tools/ZAPD/ZAPD/any/any/zlib.static.txt b/tools/ZAPD/ZAPD/any/any/zlib.static.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tools/ZAPD/ZAPD/packages.config b/tools/ZAPD/ZAPD/packages.config index a7f2abbd29..c387aaed70 100644 --- a/tools/ZAPD/ZAPD/packages.config +++ b/tools/ZAPD/ZAPD/packages.config @@ -1,8 +1,9 @@  - - + + + \ No newline at end of file diff --git a/tools/ZAPD/ZAPDUtils/Color3b.h b/tools/ZAPD/ZAPDUtils/Color3b.h index 7e59f6b7f7..507c099f52 100644 --- a/tools/ZAPD/ZAPDUtils/Color3b.h +++ b/tools/ZAPD/ZAPDUtils/Color3b.h @@ -1,6 +1,6 @@ #pragma once -#include +#include struct Color3b { diff --git a/tools/ZAPD/ZAPDUtils/StrHash.h b/tools/ZAPD/ZAPDUtils/StrHash.h index 68d22b9cd6..c611bdddad 100644 --- a/tools/ZAPD/ZAPDUtils/StrHash.h +++ b/tools/ZAPD/ZAPDUtils/StrHash.h @@ -1,8 +1,8 @@ #pragma once -#include -#include -#include +#include +#include +#include typedef uint32_t strhash; diff --git a/tools/ZAPD/ZAPDUtils/Utils/BinaryReader.cpp b/tools/ZAPD/ZAPDUtils/Utils/BinaryReader.cpp index a4cf782294..35412781cc 100644 --- a/tools/ZAPD/ZAPDUtils/Utils/BinaryReader.cpp +++ b/tools/ZAPD/ZAPDUtils/Utils/BinaryReader.cpp @@ -1,5 +1,5 @@ #include "BinaryReader.h" -#include +#include #include #include "Stream.h" @@ -89,7 +89,7 @@ float BinaryReader::ReadSingle() stream->Read((char*)&result, sizeof(float)); - if (isnan(result)) + if (std::isnan(result)) throw std::runtime_error("BinaryReader::ReadSingle(): Error reading stream"); return result; @@ -100,7 +100,7 @@ double BinaryReader::ReadDouble() double result = NAN; stream->Read((char*)&result, sizeof(double)); - if (isnan(result)) + if (std::isnan(result)) throw std::runtime_error("BinaryReader::ReadDouble(): Error reading stream"); return result; diff --git a/tools/ZAPD/ZAPDUtils/Utils/BitConverter.h b/tools/ZAPD/ZAPDUtils/Utils/BitConverter.h index 5cca35b319..e672b97c23 100644 --- a/tools/ZAPD/ZAPDUtils/Utils/BitConverter.h +++ b/tools/ZAPD/ZAPDUtils/Utils/BitConverter.h @@ -1,7 +1,7 @@ #pragma once +#include #include -#include #include class BitConverter diff --git a/tools/ZAPD/ZAPDUtils/Utils/File.h b/tools/ZAPD/ZAPDUtils/Utils/File.h index e3f8880cb6..084152f794 100644 --- a/tools/ZAPD/ZAPDUtils/Utils/File.h +++ b/tools/ZAPD/ZAPDUtils/Utils/File.h @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include #include #include #include "Directory.h" diff --git a/tools/ZAPD/ZAPDUtils/Utils/MemoryStream.cpp b/tools/ZAPD/ZAPDUtils/Utils/MemoryStream.cpp index 6c27399d6c..6e85c59a04 100644 --- a/tools/ZAPD/ZAPDUtils/Utils/MemoryStream.cpp +++ b/tools/ZAPD/ZAPDUtils/Utils/MemoryStream.cpp @@ -1,5 +1,5 @@ #include "MemoryStream.h" -#include +#include #ifndef _MSC_VER #define memcpy_s(dest, destSize, source, sourceSize) memcpy(dest, source, destSize) diff --git a/tools/ZAPD/ZAPDUtils/Utils/Path.h b/tools/ZAPD/ZAPDUtils/Utils/Path.h index 496a0ae13c..0f7ef27431 100644 --- a/tools/ZAPD/ZAPDUtils/Utils/Path.h +++ b/tools/ZAPD/ZAPDUtils/Utils/Path.h @@ -18,13 +18,13 @@ public: static std::string GetFileName(const fs::path& input) { // https://en.cppreference.com/w/cpp/filesystem/path/filename - return input.filename(); + return input.filename().string(); }; static std::string GetFileNameWithoutExtension(const fs::path& input) { // https://en.cppreference.com/w/cpp/filesystem/path/stem - return input.stem(); + return input.stem().string(); }; static std::string GetFileNameExtension(const std::string& input) diff --git a/tools/ZAPD/ZAPDUtils/Utils/Stream.h b/tools/ZAPD/ZAPDUtils/Utils/Stream.h index 060e23cd27..e73a9a70d0 100644 --- a/tools/ZAPD/ZAPDUtils/Utils/Stream.h +++ b/tools/ZAPD/ZAPDUtils/Utils/Stream.h @@ -1,7 +1,7 @@ #pragma once +#include #include -#include enum class SeekOffsetType { diff --git a/tools/ZAPD/ZAPDUtils/Utils/StringHelper.h b/tools/ZAPD/ZAPDUtils/Utils/StringHelper.h index 74607ce3a2..0b0d676429 100644 --- a/tools/ZAPD/ZAPDUtils/Utils/StringHelper.h +++ b/tools/ZAPD/ZAPDUtils/Utils/StringHelper.h @@ -1,18 +1,12 @@ #pragma once #include +#include #include #include -#include #include #include -#ifdef _MSC_VER -#define __PRETTY_FUNCTION__ __FUNCSIG__ -#elif not defined(__GNUC__) -#define __PRETTY_FUNCTION__ __func__ -#endif - class StringHelper { public: @@ -111,4 +105,10 @@ public: { return std::all_of(str.begin(), str.end(), ::isdigit); } + + static bool IEquals(const std::string& a, const std::string& b) + { + return std::equal(a.begin(), a.end(), b.begin(), b.end(), + [](char a, char b) { return tolower(a) == tolower(b); }); + } }; diff --git a/tools/ZAPD/ZAPDUtils/Utils/vt.h b/tools/ZAPD/ZAPDUtils/Utils/vt.h new file mode 100644 index 0000000000..23f424442b --- /dev/null +++ b/tools/ZAPD/ZAPDUtils/Utils/vt.h @@ -0,0 +1,45 @@ +#ifndef VT_H +#define VT_H + +// clang-format off +#define VT_COLOR_BLACK 0 +#define VT_COLOR_RED 1 +#define VT_COLOR_GREEN 2 +#define VT_COLOR_YELLOW 3 +#define VT_COLOR_BLUE 4 +#define VT_COLOR_PURPLE 5 +#define VT_COLOR_CYAN 6 +#define VT_COLOR_WHITE 7 +#define VT_COLOR_LIGHTGRAY 8 +#define VT_COLOR_DARKGRAY 9 + +#define VT_COLOR_FOREGROUND 3 +#define VT_COLOR_BACKGROUND 4 +// clang-format on + +#define VT_COLOR_EXPAND0(type, color) #type #color +#define VT_COLOR_EXPAND1(type, color) VT_COLOR_EXPAND0(type, color) +#define VT_COLOR(type, color) VT_COLOR_EXPAND1(VT_COLOR_##type, VT_COLOR_##color) + +#define VT_ESC "\x1b" +#define VT_CSI "[" +#define VT_CUP(x, y) VT_ESC VT_CSI y ";" x "H" +#define VT_ED(n) VT_ESC VT_CSI #n "J" +#define VT_SGR(n) VT_ESC VT_CSI n "m" + +// Add more macros if necessary +#define VT_COL(back, fore) VT_SGR(VT_COLOR(BACKGROUND, back) ";" VT_COLOR(FOREGROUND, fore)) +#define VT_FGCOL(color) VT_SGR(VT_COLOR(FOREGROUND, color)) +#define VT_BGCOL(color) VT_SGR(VT_COLOR(BACKGROUND, color)) + +// Bold +#define VT_BOLD "1" + +// Bold color support +#define VT_BOLD_FGCOL(color) VT_SGR(VT_BOLD ";" VT_COLOR(FOREGROUND, color)) +#define VT_BOLD_BGCOL(color) VT_SGR(VT_BOLD ";" VT_COLOR(BACKGROUND, color)) + +#define VT_RST VT_SGR("") +#define VT_CLS VT_ED(2) + +#endif diff --git a/tools/ZAPD/ZAPDUtils/Vec2f.h b/tools/ZAPD/ZAPDUtils/Vec2f.h index 9d4beeb465..73e9259a89 100644 --- a/tools/ZAPD/ZAPDUtils/Vec2f.h +++ b/tools/ZAPD/ZAPDUtils/Vec2f.h @@ -1,6 +1,6 @@ #pragma once -#include +#include struct Vec2f { diff --git a/tools/ZAPD/ZAPDUtils/Vec3f.h b/tools/ZAPD/ZAPDUtils/Vec3f.h index 4bfbb3c254..d6e9c5568f 100644 --- a/tools/ZAPD/ZAPDUtils/Vec3f.h +++ b/tools/ZAPD/ZAPDUtils/Vec3f.h @@ -1,6 +1,6 @@ #pragma once -#include +#include struct Vec3f { diff --git a/tools/ZAPD/ZAPDUtils/Vec3s.h b/tools/ZAPD/ZAPDUtils/Vec3s.h index 23e4673b84..05816eddb5 100644 --- a/tools/ZAPD/ZAPDUtils/Vec3s.h +++ b/tools/ZAPD/ZAPDUtils/Vec3s.h @@ -1,6 +1,6 @@ #pragma once -#include +#include struct Vec3s { diff --git a/tools/ZAPD/ZAPDUtils/ZAPDUtils.vcxproj b/tools/ZAPD/ZAPDUtils/ZAPDUtils.vcxproj index 803cdb5f01..0a09666e03 100644 --- a/tools/ZAPD/ZAPDUtils/ZAPDUtils.vcxproj +++ b/tools/ZAPD/ZAPDUtils/ZAPDUtils.vcxproj @@ -43,7 +43,7 @@ StaticLibrary true v142 - Unicode + MultiByte Application @@ -116,6 +116,8 @@ true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true + MultiThreadedDebug + Default Console @@ -155,6 +157,7 @@ + diff --git a/tools/ZAPD/ZAPDUtils/ZAPDUtils.vcxproj.filters b/tools/ZAPD/ZAPDUtils/ZAPDUtils.vcxproj.filters index 48117c845f..4765ad5d45 100644 --- a/tools/ZAPD/ZAPDUtils/ZAPDUtils.vcxproj.filters +++ b/tools/ZAPD/ZAPDUtils/ZAPDUtils.vcxproj.filters @@ -19,6 +19,9 @@ {e047919d-7186-49ca-b115-e48fbb5c8743} + + {3de9dd46-0dfd-4d48-9f20-9f24e5b80fe0} + @@ -74,5 +77,8 @@ Source Files\Utils + + Source Files\Libraries + \ No newline at end of file diff --git a/tools/ZAPD/docs/zapd_warning_example.png b/tools/ZAPD/docs/zapd_warning_example.png new file mode 100644 index 0000000000..a001c64d6a Binary files /dev/null and b/tools/ZAPD/docs/zapd_warning_example.png differ