2021-03-20 16:02:12 +00:00
|
|
|
#include "Globals.h"
|
2021-12-03 20:57:05 +00:00
|
|
|
#include "Utils/Directory.h"
|
|
|
|
#include "Utils/File.h"
|
|
|
|
#include "Utils/Path.h"
|
|
|
|
#include "WarningHandler.h"
|
2021-03-20 16:02:12 +00:00
|
|
|
#include "ZAnimation.h"
|
2021-04-30 21:23:22 +00:00
|
|
|
#include "ZBackground.h"
|
2021-03-20 16:02:12 +00:00
|
|
|
#include "ZBlob.h"
|
|
|
|
#include "ZFile.h"
|
|
|
|
#include "ZTexture.h"
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2023-10-25 01:36:10 +00:00
|
|
|
#include <functional>
|
2022-12-08 18:15:18 +00:00
|
|
|
#include "CrashHandler.h"
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
#include <string>
|
2021-10-17 11:32:09 +00:00
|
|
|
#include <string_view>
|
2021-01-02 04:24:29 +00:00
|
|
|
#include "tinyxml2.h"
|
|
|
|
|
2023-10-25 01:36:10 +00:00
|
|
|
using ArgFunc = void (*)(int&, char**);
|
|
|
|
|
|
|
|
void Arg_SetOutputPath(int& i, char* argv[]);
|
|
|
|
void Arg_SetInputPath(int& i, char* argv[]);
|
|
|
|
void Arg_SetBaseromPath(int& i, char* argv[]);
|
|
|
|
void Arg_SetSourceOutputPath(int& i, char* argv[]);
|
|
|
|
void Arg_GenerateSourceFile(int& i, char* argv[]);
|
|
|
|
void Arg_TestMode(int& i, char* argv[]);
|
|
|
|
void Arg_LegacyDList(int& i, char* argv[]);
|
|
|
|
void Arg_EnableProfiling(int& i, char* argv[]);
|
|
|
|
void Arg_UseExternalResources(int& i, char* argv[]);
|
|
|
|
void Arg_SetTextureType(int& i, char* argv[]);
|
|
|
|
void Arg_ReadConfigFile(int& i, char* argv[]);
|
|
|
|
void Arg_EnableErrorHandler(int& i, char* argv[]);
|
|
|
|
void Arg_SetVerbosity(int& i, char* argv[]);
|
|
|
|
void Arg_VerboseUnaccounted(int& i, char* argv[]);
|
|
|
|
void Arg_SetExporter(int& i, char* argv[]);
|
|
|
|
void Arg_EnableGCCCompat(int& i, char* argv[]);
|
|
|
|
void Arg_ForceStatic(int& i, char* argv[]);
|
|
|
|
void Arg_ForceUnaccountedStatic(int& i, char* argv[]);
|
2024-03-01 21:12:22 +00:00
|
|
|
void Arg_CsFloatMode(int& i, char* argv[]);
|
2024-06-24 13:22:39 +00:00
|
|
|
void Arg_BaseAddress(int& i, char* argv[]);
|
|
|
|
void Arg_StartOffset(int& i, char* argv[]);
|
|
|
|
void Arg_EndOffset(int& i, char* argv[]);
|
2023-10-25 01:36:10 +00:00
|
|
|
|
|
|
|
int main(int argc, char* argv[]);
|
|
|
|
|
2021-10-17 11:32:09 +00:00
|
|
|
bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath,
|
2024-06-24 13:22:39 +00:00
|
|
|
ZFileMode fileMode);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2023-10-25 01:36:10 +00:00
|
|
|
void ParseArgs(int& argc, char* argv[]);
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
void BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const fs::path& outPath);
|
|
|
|
void BuildAssetBackground(const fs::path& imageFilePath, const fs::path& outPath);
|
|
|
|
void BuildAssetBlob(const fs::path& blobFilePath, const fs::path& outPath);
|
2023-10-25 01:36:10 +00:00
|
|
|
ZFileMode ParseFileMode(const std::string& buildMode, ExporterSet* exporterSet);
|
|
|
|
int HandleExtract(ZFileMode fileMode, ExporterSet* exporterSet);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2022-12-08 18:15:18 +00:00
|
|
|
extern const char gBuildHash[];
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
2023-10-25 01:36:10 +00:00
|
|
|
int returnCode = 0;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
if (argc < 2)
|
|
|
|
{
|
2021-07-28 02:16:03 +00:00
|
|
|
printf("ZAPD.out (%s) [mode (btex/bovl/bsf/bblb/bmdlintr/bamnintr/e)] ...\n", gBuildHash);
|
2021-01-02 04:24:29 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-12-03 20:57:05 +00:00
|
|
|
Globals* g = new Globals();
|
|
|
|
WarningHandler::Init(argc, argv);
|
|
|
|
|
2021-07-28 02:16:03 +00:00
|
|
|
for (int i = 1; i < argc; i++)
|
|
|
|
{
|
|
|
|
if (!strcmp(argv[i], "--version"))
|
|
|
|
{
|
|
|
|
printf("ZAPD.out %s\n", gBuildHash);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h"))
|
|
|
|
{
|
|
|
|
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");
|
2021-12-03 20:57:05 +00:00
|
|
|
|
|
|
|
WarningHandler::PrintHelp();
|
2021-07-28 02:16:03 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-25 01:36:10 +00:00
|
|
|
ParseArgs(argc, argv);
|
2021-10-17 11:32:09 +00:00
|
|
|
|
|
|
|
// Parse File Mode
|
|
|
|
ExporterSet* exporterSet = Globals::Instance->GetExporterSet();
|
|
|
|
std::string buildMode = argv[1];
|
2023-10-25 01:36:10 +00:00
|
|
|
ZFileMode fileMode = ParseFileMode(buildMode, exporterSet);
|
2021-10-17 11:32:09 +00:00
|
|
|
|
|
|
|
if (fileMode == ZFileMode::Invalid)
|
|
|
|
{
|
|
|
|
printf("Error: Invalid file mode '%s'\n", buildMode.c_str());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We've parsed through our commands once. If an exporter exists, it's been set by now.
|
|
|
|
// Now we'll parse through them again but pass them on to our exporter if one is available.
|
|
|
|
if (exporterSet != nullptr && exporterSet->parseArgsFunc != nullptr)
|
|
|
|
{
|
|
|
|
for (int32_t i = 2; i < argc; i++)
|
|
|
|
exporterSet->parseArgsFunc(argc, argv, i);
|
2021-01-09 00:38:28 +00:00
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
|
2021-03-14 15:40:25 +00:00
|
|
|
printf("ZAPD: Zelda Asset Processor For Decomp: %s\n", gBuildHash);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-12-03 20:57:05 +00:00
|
|
|
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
|
|
|
|
WarningHandler::PrintWarningsDebugInfo();
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (fileMode == ZFileMode::Extract || fileMode == ZFileMode::BuildSourceFile)
|
2023-10-25 01:36:10 +00:00
|
|
|
returnCode = HandleExtract(fileMode, exporterSet);
|
2021-05-30 15:09:59 +00:00
|
|
|
else if (fileMode == ZFileMode::BuildTexture)
|
2023-10-25 01:36:10 +00:00
|
|
|
BuildAssetTexture(Globals::Instance->inputPath, Globals::Instance->texType,
|
2024-06-24 13:22:39 +00:00
|
|
|
Globals::Instance->outputPath);
|
2021-05-30 15:09:59 +00:00
|
|
|
else if (fileMode == ZFileMode::BuildBackground)
|
|
|
|
BuildAssetBackground(Globals::Instance->inputPath, Globals::Instance->outputPath);
|
|
|
|
else if (fileMode == ZFileMode::BuildBlob)
|
|
|
|
BuildAssetBlob(Globals::Instance->inputPath, Globals::Instance->outputPath);
|
2021-10-17 11:32:09 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
delete g;
|
2023-10-25 01:36:10 +00:00
|
|
|
return returnCode;
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-10-17 11:32:09 +00:00
|
|
|
bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath,
|
2024-06-24 13:22:39 +00:00
|
|
|
ZFileMode fileMode)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-10-17 11:32:09 +00:00
|
|
|
tinyxml2::XMLDocument doc;
|
|
|
|
tinyxml2::XMLError eResult = doc.LoadFile(xmlFilePath.string().c_str());
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
if (eResult != tinyxml2::XML_SUCCESS)
|
2021-03-20 16:02:12 +00:00
|
|
|
{
|
2021-12-03 20:57:05 +00:00
|
|
|
// TODO: use XMLDocument::ErrorIDToName to get more specific error messages here
|
|
|
|
HANDLE_ERROR(WarningType::InvalidXML,
|
2024-06-24 13:22:39 +00:00
|
|
|
StringHelper::Sprintf("invalid XML file: '%s'", xmlFilePath.c_str()), "");
|
2021-01-02 04:24:29 +00:00
|
|
|
return false;
|
2021-03-20 16:02:12 +00:00
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-10-17 11:32:09 +00:00
|
|
|
tinyxml2::XMLNode* root = doc.FirstChild();
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
if (root == nullptr)
|
2021-03-20 16:02:12 +00:00
|
|
|
{
|
2021-12-03 20:57:05 +00:00
|
|
|
HANDLE_WARNING(
|
|
|
|
WarningType::InvalidXML,
|
|
|
|
StringHelper::Sprintf("missing Root tag in xml file: '%s'", xmlFilePath.c_str()), "");
|
2021-01-02 04:24:29 +00:00
|
|
|
return false;
|
2021-03-20 16:02:12 +00:00
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-10-17 11:32:09 +00:00
|
|
|
for (tinyxml2::XMLElement* child = root->FirstChildElement(); child != NULL;
|
2024-06-24 13:22:39 +00:00
|
|
|
child = child->NextSiblingElement())
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-10-17 11:32:09 +00:00
|
|
|
if (std::string_view(child->Name()) == "File")
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-10-17 11:32:09 +00:00
|
|
|
ZFile* file = new ZFile(fileMode, child, basePath, outPath, "", xmlFilePath);
|
2021-01-02 04:24:29 +00:00
|
|
|
Globals::Instance->files.push_back(file);
|
2021-10-17 11:32:09 +00:00
|
|
|
if (fileMode == ZFileMode::ExternalFile)
|
|
|
|
{
|
|
|
|
Globals::Instance->externalFiles.push_back(file);
|
|
|
|
file->isExternalFile = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (std::string(child->Name()) == "ExternalFile")
|
|
|
|
{
|
|
|
|
const char* xmlPathValue = child->Attribute("XmlPath");
|
|
|
|
if (xmlPathValue == nullptr)
|
|
|
|
{
|
|
|
|
throw std::runtime_error(StringHelper::Sprintf(
|
|
|
|
"Parse: Fatal error in '%s'.\n"
|
|
|
|
"\t Missing 'XmlPath' attribute in `ExternalFile` element.\n",
|
|
|
|
xmlFilePath.c_str()));
|
|
|
|
}
|
|
|
|
const char* outPathValue = child->Attribute("OutPath");
|
|
|
|
if (outPathValue == nullptr)
|
|
|
|
{
|
|
|
|
throw std::runtime_error(StringHelper::Sprintf(
|
|
|
|
"Parse: Fatal error in '%s'.\n"
|
|
|
|
"\t Missing 'OutPath' attribute in `ExternalFile` element.\n",
|
|
|
|
xmlFilePath.c_str()));
|
|
|
|
}
|
|
|
|
|
|
|
|
fs::path externalXmlFilePath =
|
|
|
|
Globals::Instance->cfg.externalXmlFolder / fs::path(xmlPathValue);
|
|
|
|
fs::path externalOutFilePath = fs::path(outPathValue);
|
|
|
|
|
|
|
|
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
|
|
|
|
{
|
|
|
|
printf("Parsing external file: '%s'\n", externalXmlFilePath.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Recursion. What can go wrong?
|
|
|
|
Parse(externalXmlFilePath, basePath, externalOutFilePath, ZFileMode::ExternalFile);
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
2021-04-30 21:23:22 +00:00
|
|
|
else
|
|
|
|
{
|
2021-12-03 20:57:05 +00:00
|
|
|
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);
|
2021-04-30 21:23:22 +00:00
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-10-17 11:32:09 +00:00
|
|
|
if (fileMode != ZFileMode::ExternalFile)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-10-17 11:32:09 +00:00
|
|
|
ExporterSet* exporterSet = Globals::Instance->GetExporterSet();
|
|
|
|
|
|
|
|
if (exporterSet != nullptr && exporterSet->beginXMLFunc != nullptr)
|
|
|
|
exporterSet->beginXMLFunc();
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-10-17 11:32:09 +00:00
|
|
|
for (ZFile* file : Globals::Instance->files)
|
|
|
|
{
|
|
|
|
if (fileMode == ZFileMode::BuildSourceFile)
|
|
|
|
file->BuildSourceFile();
|
|
|
|
else
|
|
|
|
file->ExtractResources();
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-10-17 11:32:09 +00:00
|
|
|
if (exporterSet != nullptr && exporterSet->endXMLFunc != nullptr)
|
|
|
|
exporterSet->endXMLFunc();
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2023-10-25 01:36:10 +00:00
|
|
|
void ParseArgs(int& argc, char* argv[])
|
|
|
|
{
|
|
|
|
static const std::unordered_map<std::string, ArgFunc> ArgFuncDictionary = {
|
|
|
|
{"-o", &Arg_SetOutputPath},
|
|
|
|
{"--outputpath", &Arg_SetOutputPath},
|
|
|
|
{"-i", &Arg_SetInputPath},
|
|
|
|
{"--inputpath", &Arg_SetInputPath},
|
|
|
|
{"-b", &Arg_SetBaseromPath},
|
|
|
|
{"--baserompath", &Arg_SetBaseromPath},
|
|
|
|
{"-osf", &Arg_SetSourceOutputPath},
|
|
|
|
{"-gsf", &Arg_GenerateSourceFile},
|
|
|
|
{"-tm", &Arg_TestMode},
|
|
|
|
{"-ulzdl", &Arg_LegacyDList},
|
|
|
|
{"-profile", &Arg_EnableProfiling},
|
|
|
|
{"-uer", &Arg_UseExternalResources},
|
|
|
|
{"-tt", &Arg_SetTextureType},
|
|
|
|
{"-rconf", &Arg_ReadConfigFile},
|
|
|
|
{"-eh", &Arg_EnableErrorHandler},
|
|
|
|
{"-v", &Arg_SetVerbosity},
|
|
|
|
{"-vu", &Arg_VerboseUnaccounted},
|
|
|
|
{"--verbose-unaccounted", &Arg_VerboseUnaccounted},
|
|
|
|
{"-se", &Arg_SetExporter},
|
|
|
|
{"--set-exporter", &Arg_SetExporter},
|
|
|
|
{"--gcc-compat", &Arg_EnableGCCCompat},
|
|
|
|
{"-s", &Arg_ForceStatic},
|
|
|
|
{"--static", &Arg_ForceStatic},
|
|
|
|
{"-us", &Arg_ForceUnaccountedStatic},
|
|
|
|
{"--unaccounted-static", &Arg_ForceUnaccountedStatic},
|
2024-03-01 21:12:22 +00:00
|
|
|
{"--cs-float", &Arg_CsFloatMode},
|
2024-06-24 13:22:39 +00:00
|
|
|
{"--base-address", &Arg_BaseAddress},
|
|
|
|
{"--start-offset", &Arg_StartOffset},
|
|
|
|
{"--end-offset", &Arg_EndOffset},
|
2023-10-25 01:36:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
for (int32_t i = 2; i < argc; i++)
|
|
|
|
{
|
|
|
|
std::string arg = argv[i];
|
|
|
|
|
|
|
|
// Ignore warning args as they have already been parsed
|
|
|
|
if (arg.length() > 2 && arg[0] == '-' && arg[1] == 'W' && arg[2] != '\0')
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto it = ArgFuncDictionary.find(arg);
|
|
|
|
if (it == ArgFuncDictionary.end())
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Unsupported argument: %s\n", arg.c_str());
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::invoke(it->second, i, argv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ZFileMode ParseFileMode(const std::string& buildMode, ExporterSet* exporterSet)
|
|
|
|
{
|
|
|
|
ZFileMode fileMode = ZFileMode::Invalid;
|
|
|
|
|
|
|
|
if (buildMode == "btex")
|
|
|
|
fileMode = ZFileMode::BuildTexture;
|
|
|
|
else if (buildMode == "bren")
|
|
|
|
fileMode = ZFileMode::BuildBackground;
|
|
|
|
else if (buildMode == "bsf")
|
|
|
|
fileMode = ZFileMode::BuildSourceFile;
|
|
|
|
else if (buildMode == "bblb")
|
|
|
|
fileMode = ZFileMode::BuildBlob;
|
|
|
|
else if (buildMode == "e")
|
|
|
|
fileMode = ZFileMode::Extract;
|
|
|
|
else if (exporterSet != nullptr && exporterSet->parseFileModeFunc != nullptr)
|
|
|
|
exporterSet->parseFileModeFunc(buildMode, fileMode);
|
|
|
|
|
|
|
|
return fileMode;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_SetOutputPath(int& i, [[maybe_unused]] char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->outputPath = argv[++i];
|
|
|
|
|
|
|
|
if (Globals::Instance->sourceOutputPath == "")
|
|
|
|
Globals::Instance->sourceOutputPath = Globals::Instance->outputPath;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_SetInputPath(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->inputPath = argv[++i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_SetBaseromPath(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->baseRomPath = argv[++i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_SetSourceOutputPath(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->sourceOutputPath = argv[++i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_GenerateSourceFile(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
// Generate source file during extraction
|
|
|
|
Globals::Instance->genSourceFile = std::string_view(argv[++i]) == "1";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_TestMode(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
// Test Mode (enables certain experimental features)
|
|
|
|
Globals::Instance->testMode = std::string_view(argv[++i]) == "1";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_LegacyDList(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->useLegacyZDList = std::string_view(argv[++i]) == "1";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_EnableProfiling(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->profile = std::string_view(argv[++i]) == "1";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_UseExternalResources(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
// Split resources into their individual components(enabled by default)
|
|
|
|
// TODO: We may wish to make this a part of the config file...
|
|
|
|
Globals::Instance->useExternalResources = std::string_view(argv[++i]) == "1";
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_SetTextureType(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->texType = ZTexture::GetTextureTypeFromString(argv[++i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_ReadConfigFile(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->cfg.ReadConfigFile(argv[++i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_EnableErrorHandler([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
|
|
|
|
{
|
|
|
|
CrashHandler_Init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_SetVerbosity(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->verbosity = static_cast<VerbosityLevel>(strtol(argv[++i], NULL, 16));
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_VerboseUnaccounted([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->verboseUnaccounted = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_SetExporter(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->currentExporter = argv[++i];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_EnableGCCCompat([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->gccCompat = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_ForceStatic([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->forceStatic = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_ForceUnaccountedStatic([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->forceUnaccountedStatic = true;
|
|
|
|
}
|
|
|
|
|
2024-03-01 21:12:22 +00:00
|
|
|
void Arg_CsFloatMode([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
|
|
|
|
{
|
|
|
|
i++;
|
|
|
|
if (std::strcmp(argv[i], "hex") == 0)
|
|
|
|
{
|
|
|
|
Globals::Instance->floatType = CsFloatType::HexOnly;
|
|
|
|
}
|
|
|
|
else if (std::strcmp(argv[i], "float") == 0)
|
|
|
|
{
|
|
|
|
Globals::Instance->floatType = CsFloatType::FloatOnly;
|
|
|
|
}
|
|
|
|
else if (std::strcmp(argv[i], "both") == 0)
|
|
|
|
{
|
|
|
|
Globals::Instance->floatType = CsFloatType::HexAndFloat;
|
|
|
|
}
|
2024-06-24 13:22:39 +00:00
|
|
|
else if (std::strcmp(argv[i], "hex-commented-left") == 0)
|
|
|
|
{
|
|
|
|
Globals::Instance->floatType = CsFloatType::HexAndCommentedFloatLeft;
|
|
|
|
}
|
|
|
|
else if (std::strcmp(argv[i], "hex-commented-right") == 0)
|
|
|
|
{
|
|
|
|
Globals::Instance->floatType = CsFloatType::HexAndCommentedFloatRight;
|
|
|
|
}
|
2024-03-01 21:12:22 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
Globals::Instance->floatType = CsFloatType::FloatOnly;
|
|
|
|
HANDLE_WARNING(
|
|
|
|
WarningType::Always, "Invalid CS Float Type",
|
2024-06-24 13:22:39 +00:00
|
|
|
StringHelper::Sprintf("Invalid CS float type entered. Expected \"hex\", \"float\", "
|
|
|
|
"\"both\", \"hex-commented-left\" or \"hex-commented-right\". "
|
|
|
|
"Got %s.\n Defaulting to \"float\".",
|
|
|
|
argv[i]));
|
2024-03-01 21:12:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-06-24 13:22:39 +00:00
|
|
|
uint32_t ParseU32Hex(char* str)
|
|
|
|
{
|
|
|
|
static_assert(sizeof(uint32_t) <= sizeof(unsigned long));
|
|
|
|
return (uint32_t)std::stoul(str, nullptr, 16);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_BaseAddress(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->baseAddress = ParseU32Hex(argv[++i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_StartOffset(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->startOffset = ParseU32Hex(argv[++i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Arg_EndOffset(int& i, char* argv[])
|
|
|
|
{
|
|
|
|
Globals::Instance->endOffset = ParseU32Hex(argv[++i]);
|
|
|
|
}
|
|
|
|
|
2023-10-25 01:36:10 +00:00
|
|
|
int HandleExtract(ZFileMode fileMode, ExporterSet* exporterSet)
|
|
|
|
{
|
|
|
|
bool procFileModeSuccess = false;
|
|
|
|
|
|
|
|
if (exporterSet != nullptr && exporterSet->processFileModeFunc != nullptr)
|
|
|
|
procFileModeSuccess = exporterSet->processFileModeFunc(fileMode);
|
|
|
|
|
|
|
|
if (!procFileModeSuccess)
|
|
|
|
{
|
|
|
|
bool parseSuccessful;
|
|
|
|
|
|
|
|
for (auto& extFile : Globals::Instance->cfg.externalFiles)
|
|
|
|
{
|
|
|
|
fs::path externalXmlFilePath =
|
|
|
|
Globals::Instance->cfg.externalXmlFolder / extFile.xmlPath;
|
|
|
|
|
|
|
|
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
|
|
|
|
printf("Parsing external file from config: '%s'\n", externalXmlFilePath.c_str());
|
|
|
|
|
|
|
|
parseSuccessful = Parse(externalXmlFilePath, Globals::Instance->baseRomPath,
|
2024-06-24 13:22:39 +00:00
|
|
|
extFile.outPath, ZFileMode::ExternalFile);
|
2023-10-25 01:36:10 +00:00
|
|
|
|
|
|
|
if (!parseSuccessful)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
parseSuccessful = Parse(Globals::Instance->inputPath, Globals::Instance->baseRomPath,
|
2024-06-24 13:22:39 +00:00
|
|
|
Globals::Instance->outputPath, fileMode);
|
2023-10-25 01:36:10 +00:00
|
|
|
if (!parseSuccessful)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
void BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const fs::path& outPath)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string name = outPath.stem().string();
|
2021-04-30 21:23:22 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
ZTexture tex(nullptr);
|
2022-01-17 00:43:07 +00:00
|
|
|
|
|
|
|
if (name.find("u32") != std::string::npos)
|
|
|
|
tex.dWordAligned = false;
|
|
|
|
|
2021-10-17 11:32:09 +00:00
|
|
|
tex.FromPNG(pngFilePath.string(), texType);
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string cfgPath = StringHelper::Split(pngFilePath.string(), ".")[0] + ".cfg";
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
if (File::Exists(cfgPath))
|
|
|
|
name = File::ReadAllText(cfgPath);
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string src = tex.GetBodySourceCode();
|
2021-01-09 00:38:28 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
File::WriteAllText(outPath.string(), src);
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
void BuildAssetBackground(const fs::path& imageFilePath, const fs::path& outPath)
|
|
|
|
{
|
|
|
|
ZBackground background(nullptr);
|
2021-05-30 15:09:59 +00:00
|
|
|
background.ParseBinaryFile(imageFilePath.string(), false);
|
2021-04-30 21:23:22 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
File::WriteAllText(outPath.string(), background.GetBodySourceCode());
|
2021-04-30 21:23:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BuildAssetBlob(const fs::path& blobFilePath, const fs::path& outPath)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
ZBlob* blob = ZBlob::FromFile(blobFilePath.string());
|
|
|
|
std::string name = outPath.stem().string(); // filename without extension
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-10-17 11:32:09 +00:00
|
|
|
std::string src = blob->GetBodySourceCode();
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
File::WriteAllText(outPath.string(), src);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
delete blob;
|
|
|
|
}
|