summaryrefslogtreecommitdiff
path: root/ZAPD/ZFile.cpp
diff options
context:
space:
mode:
authorAnghelo Carvajal <angheloalf95@gmail.com>2021-10-16 18:55:56 -0300
committerGitHub <noreply@github.com>2021-10-16 17:55:56 -0400
commite7a8a48cf361a7591b88592eb3e333ddf8d3ab34 (patch)
tree4f63eac4c2136dd74e05593ea200b2c24c284a3f /ZAPD/ZFile.cpp
parent3e9ed72e202b1165152d42f7d160695f9f2f233a (diff)
`ExternalFile`: Expose other XML's declarations during extraction (#151)
* proof of concept * fix header include paths * GetDeclarationAlignment and others * this should fix this * minor * DeclareVar in ExtractFromXML * fix vtx intersections * Fix segmented vtxs * --version * zcollision changes * Use GetSegmentedPtrName a lot more * memory related stuff * minor style fixes and use the actual symbol for zlinkanimation instead of the hex address * Simplify lots of GetSourceOutputCode * ZSkeleton cleanup and other changes * Elevate unknown types in skeleton to errors * ZAnimation cleanup * Add ExternalFile to config * delete some code * Remove unused code * fix conflicts * format * remove redundant constructors * minor fixes * fix vtx warnings * extract every vtx as standalone files * format * uups * Bugfix: don't create extra blank files * Fix some Vtx warnings and remove "defaulting to normal" in skeleton error * Refactor ZLimb * Make each limb to look up in every file for dlists * Use GetSegmentedArrayIndexedName in VTX references in dlists * simplify simple condition * search by type * run format * Revert "search by type" This reverts commit a049bdfc94c4ab04613b354f466dee836a20508a. * Add range checks * uups * Always set rangeEnd * special case zsymbol * Revert "Revert "search by type"" This reverts commit 3f6e77c780bd30dc7000614304021a0940168316. * symbol fix and IsOffsetInFileRange * Bugfix and minor checks * run format * Don't extract data from external files * Fix extraction of overly big tluts * Minor changes * More minor fixes * Fix clang warnings * Remove unused parameter * Fix merge issues * Fix ZLimbTable::DeclareVar * Fix limbs not naming properly their DLists * Remove segment number check * Fix merge problems * Run formatter * Maybe fix? * path * empty commit * Fix a typo * Fix merge issues * Fix null ptr dereferencing * Fix merge issues and some clang warnings * Format * Fix not-matching * Format * Fix merge issues * Fix exporter * Last fixes I hope * Fix merge issues * format * fix * fix * I'm dumb * format * static fix * Whoops * fix asan * Fix? * fix * reduce artificial changes * reduce artificial changes 2 * reorder more stuff * format * fix borken thing * Remove redundant stuff in zfile * fix * Format * Fix conflict issues * format * cleanup header includes * format * Add error checks in for ExternalXMLFolder * format
Diffstat (limited to 'ZAPD/ZFile.cpp')
-rw-r--r--ZAPD/ZFile.cpp859
1 files changed, 488 insertions, 371 deletions
diff --git a/ZAPD/ZFile.cpp b/ZAPD/ZFile.cpp
index 2245168..e4bd771 100644
--- a/ZAPD/ZFile.cpp
+++ b/ZAPD/ZFile.cpp
@@ -40,13 +40,15 @@ ZFile::ZFile()
rangeEnd = 0xFFFFFFFF;
}
-ZFile::ZFile(const std::string& nName) : ZFile()
+ZFile::ZFile(const fs::path& nOutPath, const std::string& nName) : ZFile()
{
name = nName;
+ outName = nName;
+ outputPath = nOutPath;
}
-ZFile::ZFile(ZFileMode mode, tinyxml2::XMLElement* reader, const fs::path& nBasePath,
- const std::string& filename, const fs::path& nXmlFilePath, bool placeholderMode)
+ZFile::ZFile(ZFileMode nMode, tinyxml2::XMLElement* reader, const fs::path& nBasePath,
+ const fs::path& nOutPath, const std::string& filename, const fs::path& nXmlFilePath)
: ZFile()
{
xmlFilePath = nXmlFilePath;
@@ -55,8 +57,16 @@ ZFile::ZFile(ZFileMode mode, tinyxml2::XMLElement* reader, const fs::path& nBase
else
basePath = nBasePath;
- ParseXML(mode, reader, filename, placeholderMode);
- DeclareResourceSubReferences();
+ if (nOutPath == "")
+ outputPath = Directory::GetCurrentDirectory();
+ else
+ outputPath = nOutPath;
+
+ mode = nMode;
+
+ ParseXML(reader, filename);
+ if (mode != ZFileMode::ExternalFile)
+ DeclareResourceSubReferences();
}
ZFile::~ZFile()
@@ -70,11 +80,17 @@ ZFile::~ZFile()
{
delete d.second;
}
+
+ for (auto sym : symbolResources)
+ {
+ delete sym.second;
+ }
}
-void ZFile::ParseXML(ZFileMode mode, tinyxml2::XMLElement* reader, const std::string& filename,
- [[maybe_unused]] bool placeholderMode)
+void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
{
+ assert(mode != ZFileMode::Invalid);
+
if (filename == "")
name = reader->Attribute("Name");
else
@@ -113,14 +129,12 @@ void ZFile::ParseXML(ZFileMode mode, tinyxml2::XMLElement* reader, const std::st
if (rangeStart > rangeEnd)
throw std::runtime_error("Error: RangeStart must be before than RangeEnd.");
- // Commented until ZArray doesn't use a ZFile to parse it's contents anymore.
- /*
- if (reader->Attribute("Segment") == nullptr)
- throw std::runtime_error(StringHelper::Sprintf(
- "ZFile::ParseXML: Error in '%s'.\n"
- "\t Missing 'Segment' attribute in File node. \n",
- name.c_str()));
- */
+ // Not every XML may have a segment number, so this doesn't make much sense anymore.
+ // if (reader->Attribute("Segment") == nullptr)
+ // throw std::runtime_error(
+ // StringHelper::Sprintf("ZFile::ParseXML: Error in '%s'.\n"
+ // "\t Missing 'Segment' attribute in File node. \n",
+ // name.c_str()));
if (reader->Attribute("Segment") != nullptr)
{
@@ -128,13 +142,21 @@ void ZFile::ParseXML(ZFileMode mode, tinyxml2::XMLElement* reader, const std::st
Globals::Instance->AddSegment(segment, this);
}
- if (mode == ZFileMode::Extract)
+ 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()));
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();
}
std::unordered_set<std::string> nameSet;
@@ -151,9 +173,6 @@ void ZFile::ParseXML(ZFileMode mode, tinyxml2::XMLElement* reader, const std::st
const char* outNameXml = child->Attribute("OutName");
const char* offsetXml = child->Attribute("Offset");
- if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
- printf("%s: 0x%06X\n", nameXml, rawDataIndex);
-
// Check for repeated attributes.
if (offsetXml != nullptr)
{
@@ -176,6 +195,10 @@ void ZFile::ParseXML(ZFileMode mode, tinyxml2::XMLElement* reader, const std::st
throw std::runtime_error(
StringHelper::Sprintf("Error no offset specified for %s", nameXml));
}
+
+ if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
+ printf("%s: 0x%06X\n", nameXml, rawDataIndex);
+
if (outNameXml != nullptr)
{
if (outNameSet.find(outNameXml) != outNameSet.end())
@@ -203,14 +226,23 @@ void ZFile::ParseXML(ZFileMode mode, tinyxml2::XMLElement* reader, const std::st
{
ZResource* nRes = nodeMap[nodeName](this);
- if (mode == ZFileMode::Extract)
+ if (mode == ZFileMode::Extract || mode == ZFileMode::ExternalFile)
nRes->ExtractFromXML(child, rawDataIndex);
- auto resType = nRes->GetResourceType();
- if (resType == ZResourceType::Texture)
+ switch (nRes->GetResourceType())
+ {
+ case ZResourceType::Texture:
AddTextureResource(rawDataIndex, static_cast<ZTexture*>(nRes));
- else
- resources.push_back(nRes);
+ break;
+
+ case ZResourceType::Symbol:
+ AddSymbolResource(rawDataIndex, static_cast<ZSymbol*>(nRes));
+ break;
+
+ default:
+ AddResource(nRes);
+ break;
+ }
rawDataIndex += nRes->GetRawDataSize();
}
@@ -240,21 +272,13 @@ void ZFile::DeclareResourceSubReferences()
void ZFile::BuildSourceFile()
{
- if (!Directory::Exists(Globals::Instance->outputPath))
- Directory::CreateDirectory(Globals::Instance->outputPath.string());
-
- GenerateSourceFiles(Globals::Instance->outputPath);
-}
+ if (mode == ZFileMode::ExternalFile)
+ return;
-std::string ZFile::GetVarName(uint32_t address)
-{
- for (std::pair<uint32_t, Declaration*> pair : declarations)
- {
- if (pair.first == address)
- return pair.second->varName;
- }
+ if (!Directory::Exists(outputPath))
+ Directory::CreateDirectory(outputPath);
- return "";
+ GenerateSourceFiles();
}
std::string ZFile::GetName() const
@@ -262,6 +286,11 @@ std::string ZFile::GetName() const
return name;
}
+ZFileMode ZFile::GetMode() const
+{
+ return mode;
+}
+
const fs::path& ZFile::GetXmlFilePath() const
{
return xmlFilePath;
@@ -274,11 +303,14 @@ const std::vector<uint8_t>& ZFile::GetRawData() const
void ZFile::ExtractResources()
{
- if (!Directory::Exists(Globals::Instance->outputPath))
- Directory::CreateDirectory(Globals::Instance->outputPath.string());
+ if (mode == ZFileMode::ExternalFile)
+ return;
- if (!Directory::Exists(GetSourceOutputFolderPath().string()))
- Directory::CreateDirectory(GetSourceOutputFolderPath().string());
+ if (!Directory::Exists(outputPath))
+ Directory::CreateDirectory(outputPath);
+
+ if (!Directory::Exists(GetSourceOutputFolderPath()))
+ Directory::CreateDirectory(GetSourceOutputFolderPath());
for (size_t i = 0; i < resources.size(); i++)
resources[i]->ParseRawDataLate();
@@ -286,7 +318,7 @@ void ZFile::ExtractResources()
resources[i]->DeclareReferencesLate(name);
if (Globals::Instance->genSourceFile)
- GenerateSourceFiles(Globals::Instance->outputPath);
+ GenerateSourceFiles();
MemoryStream* memStream = new MemoryStream();
BinaryWriter writer = BinaryWriter(memStream);
@@ -301,12 +333,10 @@ void ZFile::ExtractResources()
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
printf("Saving resource %s\n", res->GetName().c_str());
- res->CalcHash();
- res->Save(Globals::Instance->outputPath.string());
+ res->Save(outputPath);
// 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);
}
@@ -358,13 +388,14 @@ Declaration* ZFile::AddDeclaration(offset_t address, DeclarationAlignment alignm
const std::string& varType, const std::string& varName,
const std::string& body)
{
- assert(GETSEGNUM(address) == 0);
- AddDeclarationDebugChecks(address);
+ bool validOffset = AddDeclarationChecks(address, varName);
+ if (!validOffset)
+ return nullptr;
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
- decl = new Declaration(alignment, size, varType, varName, false, body);
+ decl = new Declaration(address, alignment, size, varType, varName, false, body);
declarations[address] = decl;
}
else
@@ -383,13 +414,15 @@ Declaration* ZFile::AddDeclarationArray(offset_t address, DeclarationAlignment a
const std::string& varName, size_t arrayItemCnt,
const std::string& body)
{
- assert(GETSEGNUM(address) == 0);
- AddDeclarationDebugChecks(address);
+ bool validOffset = AddDeclarationChecks(address, varName);
+ if (!validOffset)
+ return nullptr;
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
- decl = new Declaration(alignment, size, varType, varName, true, arrayItemCnt, body);
+ decl =
+ new Declaration(address, alignment, size, varType, varName, true, arrayItemCnt, body);
declarations[address] = decl;
}
else
@@ -401,8 +434,7 @@ Declaration* ZFile::AddDeclarationArray(offset_t address, DeclarationAlignment a
decl->varType = varType;
decl->isArray = true;
decl->arrayItemCnt = arrayItemCnt;
- if (body != "" && decl->text == "")
- decl->text = body;
+ decl->text = body;
}
return decl;
@@ -413,13 +445,15 @@ Declaration* ZFile::AddDeclarationArray(offset_t address, DeclarationAlignment a
const std::string& varName,
const std::string& arrayItemCntStr, const std::string& body)
{
- assert(GETSEGNUM(address) == 0);
- AddDeclarationDebugChecks(address);
+ bool validOffset = AddDeclarationChecks(address, varName);
+ if (!validOffset)
+ return nullptr;
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
- decl = new Declaration(alignment, size, varType, varName, true, arrayItemCntStr, body);
+ decl = new Declaration(address, alignment, size, varType, varName, true, arrayItemCntStr,
+ body);
declarations[address] = decl;
}
else
@@ -435,33 +469,16 @@ Declaration* ZFile::AddDeclarationArray(offset_t address, DeclarationAlignment a
return decl;
}
-Declaration* ZFile::AddDeclarationPlaceholder(uint32_t address)
-{
- assert(GETSEGNUM(address) == 0);
- AddDeclarationDebugChecks(address);
- Declaration* decl;
-
- if (declarations.find(address) == declarations.end())
- {
- decl = new Declaration(DeclarationAlignment::Align4, 0, "", "", false, "");
- decl->isPlaceholder = true;
- declarations[address] = decl;
- }
- else
- decl = declarations[address];
-
- return decl;
-}
-
Declaration* ZFile::AddDeclarationPlaceholder(offset_t address, const std::string& varName)
{
- assert(GETSEGNUM(address) == 0);
- AddDeclarationDebugChecks(address);
- Declaration* decl;
+ bool validOffset = AddDeclarationChecks(address, varName);
+ if (!validOffset)
+ return nullptr;
+ Declaration* decl;
if (declarations.find(address) == declarations.end())
{
- decl = new Declaration(DeclarationAlignment::Align4, 0, "", varName, false, "");
+ decl = new Declaration(address, DeclarationAlignment::Align4, 0, "", varName, false, "");
decl->isPlaceholder = true;
declarations[address] = decl;
}
@@ -475,13 +492,14 @@ Declaration* ZFile::AddDeclarationInclude(offset_t address, const std::string& i
size_t size, const std::string& varType,
const std::string& varName)
{
- assert(GETSEGNUM(address) == 0);
- AddDeclarationDebugChecks(address);
+ bool validOffset = AddDeclarationChecks(address, varName);
+ if (!validOffset)
+ return nullptr;
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
- decl = new Declaration(includePath, size, varType, varName);
+ decl = new Declaration(address, includePath, size, varType, varName);
declarations[address] = decl;
}
else
@@ -498,8 +516,9 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in
size_t size, const std::string& varType,
const std::string& varName, size_t arrayItemCnt)
{
- assert(GETSEGNUM(address) == 0);
- AddDeclarationDebugChecks(address);
+ bool validOffset = AddDeclarationChecks(address, varName);
+ if (!validOffset)
+ return nullptr;
if (StringHelper::StartsWith(includePath, "assets/extracted/"))
includePath = "assets/" + StringHelper::Split(includePath, "assets/extracted/")[1];
@@ -509,7 +528,7 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
- decl = new Declaration(includePath, size, varType, varName);
+ decl = new Declaration(address, includePath, size, varType, varName);
decl->isArray = true;
decl->arrayItemCnt = arrayItemCnt;
@@ -528,47 +547,106 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in
return decl;
}
-void ZFile::AddDeclarationDebugChecks(uint32_t address)
+bool ZFile::AddDeclarationChecks(uint32_t address, const std::string& varName)
{
assert(GETSEGNUM(address) == 0);
-#ifdef _DEBUG
+ assert(varName != "");
+#ifdef DEVELOPMENT
if (address == 0x0000)
{
[[maybe_unused]] int32_t bp = 0;
}
#endif
-}
-std::string ZFile::GetDeclarationName(uint32_t address) const
-{
- return GetDeclarationName(address,
- "ERROR_COULD_NOT_FIND_DECLARATION"); // Note: For now that default
- // message is just for testing
+ if (!IsOffsetInFileRange(address))
+ {
+ fprintf(stderr,
+ "%s: Warning in %s\n"
+ "\t Tried to declare a variable outside of this file's range. Ignoring...\n"
+ "\t\t Variable's name: %s\n"
+ "\t\t Variable's offset: 0x%06X\n",
+ __PRETTY_FUNCTION__, name.c_str(), varName.c_str(), address);
+ return false;
+ }
+
+ return true;
}
-std::string ZFile::GetDeclarationName(uint32_t address, const std::string& defaultResult) const
+bool ZFile::GetDeclarationPtrName(segptr_t segAddress, const std::string& expectedType,
+ std::string& declName) const
{
- Declaration* decl = GetDeclaration(address);
- if (decl != nullptr)
- return decl->varName;
+ if (segAddress == 0)
+ {
+ declName = "NULL";
+ return true;
+ }
+
+ uint32_t offset = Seg2Filespace(segAddress, baseAddress);
+ Declaration* decl = GetDeclaration(offset);
+ if (GETSEGNUM(segAddress) != segment || decl == nullptr)
+ {
+ declName = StringHelper::Sprintf("0x%08X", segAddress);
+ return false;
+ }
- return defaultResult;
+ if (expectedType != "" && expectedType != "void*")
+ {
+ if (expectedType != decl->varType && "static " + expectedType != decl->varType)
+ {
+ declName = StringHelper::Sprintf("0x%08X", segAddress);
+ return false;
+ }
+ }
+
+ if (!decl->isArray)
+ declName = "&" + decl->varName;
+ else
+ declName = decl->varName;
+ return true;
}
-std::string ZFile::GetDeclarationPtrName(segptr_t segAddress) const
+bool ZFile::GetDeclarationArrayIndexedName(segptr_t segAddress, size_t elementSize,
+ const std::string& expectedType,
+ std::string& declName) const
{
if (segAddress == 0)
- return "NULL";
+ {
+ declName = "NULL";
+ return true;
+ }
- Declaration* decl = GetDeclaration(Seg2Filespace(segAddress, baseAddress));
+ uint32_t address = Seg2Filespace(segAddress, baseAddress);
+ Declaration* decl = GetDeclarationRanged(address);
+ if (GETSEGNUM(segAddress) != segment || decl == nullptr || !decl->isArray)
+ {
+ declName = StringHelper::Sprintf("0x%08X", segAddress);
+ return false;
+ }
- if (!Globals::Instance->HasSegment(GETSEGNUM(segAddress)) || decl == nullptr)
- return StringHelper::Sprintf("0x%08X", segAddress);
+ if (expectedType != "" && expectedType != "void*")
+ {
+ if (expectedType != decl->varType && "static " + expectedType != decl->varType)
+ {
+ declName = StringHelper::Sprintf("0x%08X", segAddress);
+ return false;
+ }
+ }
- if (!decl->isArray)
- return "&" + decl->varName;
+ if (decl->address == address)
+ {
+ declName = decl->varName;
+ return true;
+ }
+
+ if ((address - decl->address) % elementSize != 0 || !(address < decl->address + decl->size))
+ {
+ declName = StringHelper::Sprintf("0x%08X", segAddress);
+ return false;
+ }
- return decl->varName;
+ uint32_t index = (address - decl->address) / elementSize;
+ declName = StringHelper::Sprintf("&%s[%u]", decl->varName.c_str(), index);
+ return true;
}
Declaration* ZFile::GetDeclaration(uint32_t address) const
@@ -590,24 +668,13 @@ Declaration* ZFile::GetDeclarationRanged(uint32_t address) const
return nullptr;
}
-uint32_t ZFile::GetDeclarationRangedAddress(uint32_t address) const
-{
- for (const auto decl : declarations)
- {
- if (address >= decl.first && address < decl.first + decl.second->size)
- return decl.first;
- }
-
- return 0xFFFFFFFF;
-}
-
bool ZFile::HasDeclaration(uint32_t address)
{
assert(GETSEGNUM(address) == 0);
return declarations.find(address) != declarations.end();
}
-void ZFile::GenerateSourceFiles(fs::path outputDir)
+void ZFile::GenerateSourceFiles()
{
std::string sourceOutput;
@@ -616,60 +683,34 @@ void ZFile::GenerateSourceFiles(fs::path outputDir)
sourceOutput += "#include \"macros.h\"\n";
sourceOutput += GetHeaderInclude();
- GeneratePlaceholderDeclarations();
-
- // Generate Code
- for (size_t i = 0; i < resources.size(); i++)
+ bool hasZRoom = false;
+ for (const auto& res : resources)
{
- ZResource* res = resources.at(i);
- std::string resSrc = res->GetSourceOutputCode(name);
-
- if (res->IsExternalResource())
+ ZResourceType resType = res->GetResourceType();
+ if (resType == ZResourceType::Room || resType == ZResourceType::Scene ||
+ resType == ZResourceType::AltHeader)
{
- std::string path = Path::GetFileNameWithoutExtension(res->GetName()).c_str();
-
- std::string assetOutDir =
- (outputDir / Path::GetFileNameWithoutExtension(res->GetOutName())).string();
- std::string declType = res->GetSourceTypeName();
-
- std::string incStr = StringHelper::Sprintf("%s.%s.inc", assetOutDir.c_str(),
- res->GetExternalExtension().c_str());
-
- if (res->GetResourceType() == ZResourceType::Texture)
- {
- ZTexture* tex = static_cast<ZTexture*>(res);
+ hasZRoom = true;
+ break;
+ }
+ }
- if (!Globals::Instance->cfg.texturePool.empty())
- {
- tex->CalcHash();
+ if (hasZRoom)
+ {
+ sourceOutput += GetZRoomHeaderInclude();
+ }
- // TEXTURE POOL CHECK
- if (Globals::Instance->cfg.texturePool.find(tex->hash) !=
- Globals::Instance->cfg.texturePool.end())
- {
- incStr = Globals::Instance->cfg.texturePool[tex->hash].path.string() + "." +
- res->GetExternalExtension() + ".inc";
- }
- }
+ sourceOutput += GetExternalFileHeaderInclude();
- incStr += ".c";
- }
- else if (res->GetResourceType() == ZResourceType::Blob ||
- res->GetResourceType() == ZResourceType::Background)
- {
- incStr += ".c";
- }
+ sourceOutput += "\n";
- AddDeclarationIncludeArray(res->GetRawDataIndex(), incStr, res->GetRawDataSize(),
- declType, res->GetName(), 0);
- }
- else
- {
- sourceOutput += resSrc;
- }
+ GeneratePlaceholderDeclarations();
- if (resSrc != "" && !res->IsExternalResource())
- sourceOutput += "\n";
+ // Generate Code
+ for (size_t i = 0; i < resources.size(); i++)
+ {
+ ZResource* res = resources.at(i);
+ res->GetSourceOutputCode(name);
}
sourceOutput += ProcessDeclarations();
@@ -700,6 +741,11 @@ void ZFile::GenerateSourceHeaderFiles()
formatter.Write("\n");
}
+ for (auto& sym : symbolResources)
+ {
+ formatter.Write(sym.second->GetSourceOutputHeader(""));
+ }
+
formatter.Write(ProcessExterns());
fs::path headerFilename = GetSourceOutputFolderPath() / outName.stem().concat(".h");
@@ -710,10 +756,48 @@ void ZFile::GenerateSourceHeaderFiles()
File::WriteAllText(headerFilename, formatter.GetOutput());
}
-std::string ZFile::GetHeaderInclude()
+std::string ZFile::GetHeaderInclude() const
{
- return StringHelper::Sprintf("#include \"%s\"\n\n",
- (outName.parent_path() / outName.stem().concat(".h")).c_str());
+ std::string headers = StringHelper::Sprintf("#include \"%s.h\"\n",
+ (outName.parent_path() / outName.stem()).c_str());
+
+ return headers;
+}
+
+std::string ZFile::GetZRoomHeaderInclude() const
+{
+ std::string headers;
+ headers += "#include \"segment_symbols.h\"\n";
+ headers += "#include \"command_macros_base.h\"\n";
+ headers += "#include \"z64cutscene_commands.h\"\n";
+ headers += "#include \"variables.h\"\n";
+ return headers;
+}
+
+std::string ZFile::GetExternalFileHeaderInclude() const
+{
+ std::string externalFilesIncludes = "";
+
+ for (ZFile* externalFile : Globals::Instance->files)
+ {
+ if (externalFile != this)
+ {
+ fs::path outputFolderPath = externalFile->GetSourceOutputFolderPath();
+ if (outputFolderPath == this->GetSourceOutputFolderPath())
+ {
+ outputFolderPath = externalFile->outName.stem();
+ }
+ else
+ {
+ outputFolderPath /= externalFile->outName.stem();
+ }
+
+ externalFilesIncludes +=
+ StringHelper::Sprintf("#include \"%s.h\"\n", outputFolderPath.c_str());
+ }
+ }
+
+ return externalFilesIncludes;
}
void ZFile::GeneratePlaceholderDeclarations()
@@ -752,9 +836,52 @@ ZTexture* ZFile::GetTextureResource(uint32_t offset) const
return nullptr;
}
+void ZFile::AddSymbolResource(uint32_t offset, ZSymbol* sym)
+{
+ symbolResources[offset] = sym;
+}
+
+ZSymbol* ZFile::GetSymbolResource(uint32_t offset) const
+{
+ auto sym = symbolResources.find(offset);
+ if (sym != symbolResources.end())
+ return sym->second;
+
+ return nullptr;
+}
+
+ZSymbol* ZFile::GetSymbolResourceRanged(uint32_t offset) const
+{
+ for (const auto decl : symbolResources)
+ {
+ if (offset >= decl.first && offset < decl.first + decl.second->GetRawDataSize())
+ return decl.second;
+ }
+
+ return nullptr;
+}
+
fs::path ZFile::GetSourceOutputFolderPath() const
{
- return Globals::Instance->sourceOutputPath / outName.parent_path();
+ return outputPath / outName.parent_path();
+}
+
+bool ZFile::IsOffsetInFileRange(uint32_t offset) const
+{
+ if (!(offset < rawData.size()))
+ return false;
+
+ return rangeStart <= offset && offset < rangeEnd;
+}
+bool ZFile::IsSegmentedInFilespaceRange(segptr_t segAddress) const
+{
+ uint8_t segnum = GETSEGNUM(segAddress);
+ uint32_t offset = Seg2Filespace(segAddress, baseAddress);
+
+ if (segment != segnum)
+ return false;
+
+ return IsOffsetInFileRange(offset);
}
std::map<std::string, ZResourceFactoryFunc*>* ZFile::GetNodeMap()
@@ -780,7 +907,6 @@ std::string ZFile::ProcessDeclarations()
// Account for padding/alignment
uint32_t lastAddr = 0;
- uint32_t lastSize = 0;
// printf("RANGE START: 0x%06X - RANGE END: 0x%06X\n", rangeStart, rangeEnd);
@@ -798,21 +924,24 @@ std::string ZFile::ProcessDeclarations()
{
if (curItem.second->varType == lastItem.second->varType)
{
- // TEST: For now just do Vtx declarations...
- if (lastItem.second->varType == "static Vtx")
+ if (!curItem.second->declaredInXml && !lastItem.second->declaredInXml)
{
- int32_t sizeDiff = curItem.first - (lastItem.first + lastItem.second->size);
-
- // Make sure there isn't an unaccounted inbetween these two
- if (sizeDiff == 0)
+ // TEST: For now just do Vtx declarations...
+ if (lastItem.second->varType == "Vtx")
{
- lastItem.second->size += curItem.second->size;
- lastItem.second->arrayItemCnt += curItem.second->arrayItemCnt;
- lastItem.second->text += "\n" + curItem.second->text;
- declarations.erase(curItem.first);
- declarationKeys.erase(declarationKeys.begin() + i);
- i--;
- continue;
+ int32_t sizeDiff = curItem.first - (lastItem.first + lastItem.second->size);
+
+ // Make sure there isn't an unaccounted inbetween these two
+ if (sizeDiff == 0)
+ {
+ lastItem.second->size += curItem.second->size;
+ lastItem.second->arrayItemCnt += curItem.second->arrayItemCnt;
+ lastItem.second->text += "\n" + curItem.second->text;
+ declarations.erase(curItem.first);
+ declarationKeys.erase(declarationKeys.begin() + i);
+ i--;
+ continue;
+ }
}
}
}
@@ -833,26 +962,13 @@ std::string ZFile::ProcessDeclarations()
{
if (item.second->alignment == DeclarationAlignment::Align16)
{
- // int32_t lastAddrSizeTest = declarations[lastAddr]->size;
int32_t curPtr = lastAddr + declarations[lastAddr]->size;
while (curPtr % 4 != 0)
{
declarations[lastAddr]->size++;
- // item.second->size++;
curPtr++;
}
-
- /*while (curPtr % 16 != 0)
- {
- char buffer[2048];
-
- sprintf(buffer, "static u32 align%02X = 0;\n", curPtr);
- item.second->text = buffer + item.second->text;
-
- declarations[lastAddr]->size += 4;
- curPtr += 4;
- }*/
}
else if (item.second->alignment == DeclarationAlignment::Align8)
{
@@ -861,7 +977,6 @@ std::string ZFile::ProcessDeclarations()
while (curPtr % 4 != 0)
{
declarations[lastAddr]->size++;
- // item.second->size++;
curPtr++;
}
@@ -873,7 +988,6 @@ std::string ZFile::ProcessDeclarations()
item.second->preText = buffer + item.second->preText;
declarations[lastAddr]->size += 4;
- // item.second->size += 4;
curPtr += 4;
}
}
@@ -882,132 +996,7 @@ std::string ZFile::ProcessDeclarations()
lastAddr = item.first;
}
- // Handle unaccounted data
- lastAddr = 0;
- lastSize = 0;
- std::vector<uint32_t> declsAddresses;
- for (const auto& item : declarations)
- {
- declsAddresses.push_back(item.first);
- }
- declsAddresses.push_back(rawData.size());
-
- for (uint32_t currentAddress : declsAddresses)
- {
- if (currentAddress >= rangeEnd)
- {
- break;
- }
-
- if (currentAddress < rangeStart)
- {
- lastAddr = currentAddress;
- continue;
- }
-
- if (currentAddress != lastAddr && declarations.find(lastAddr) != declarations.end())
- {
- Declaration* lastDecl = declarations.at(lastAddr);
- lastSize = lastDecl->size;
-
- if (lastAddr + lastSize > currentAddress)
- {
- 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());
- }
- }
-
- size_t unaccountedAddress = lastAddr + lastSize;
-
- if (unaccountedAddress != currentAddress && lastAddr >= rangeStart &&
- unaccountedAddress < rangeEnd)
- {
- int diff = currentAddress - unaccountedAddress;
- bool nonZeroUnaccounted = false;
-
- std::string src = " ";
-
- for (int i = 0; i < diff; i++)
- {
- uint8_t val = rawData.at(unaccountedAddress + i);
- src += StringHelper::Sprintf("0x%02X, ", val);
- if (val != 0x00)
- {
- nonZeroUnaccounted = true;
- }
-
- if (Globals::Instance->verboseUnaccounted)
- {
- if ((i % 4 == 3))
- {
- src += StringHelper::Sprintf(" // 0x%06X", unaccountedAddress + i - 3);
- if (i != (diff - 1))
- {
- src += "\n\t";
- }
- }
- }
- else
- {
- if ((i % 16 == 15) && (i != (diff - 1)))
- src += "\n ";
- }
- }
-
- if (declarations.find(unaccountedAddress) == declarations.end())
- {
- if (diff > 0)
- {
- std::string unaccountedPrefix = "unaccounted";
-
- if (diff < 16 && !nonZeroUnaccounted)
- {
- unaccountedPrefix = "possiblePadding";
-
- // Strip unnecessary padding at the end of the file.
- if (unaccountedAddress + diff >= rawData.size())
- break;
- }
-
- Declaration* decl = AddDeclarationArray(
- unaccountedAddress, DeclarationAlignment::Align4, diff, "u8",
- StringHelper::Sprintf("%s_%s_%06X", name.c_str(), unaccountedPrefix.c_str(),
- unaccountedAddress),
- diff, src);
- decl->isUnaccounted = true;
-
- if (Globals::Instance->warnUnaccounted)
- {
- if (nonZeroUnaccounted)
- {
- fprintf(
- stderr,
- "Warning in file: %s (%s)\n"
- "\t A non-zero unaccounted block was found at address '0x%06zX'.\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 address '0x%06zX'.\n"
- "\t Block size: '0x%X'.\n",
- xmlFilePath.c_str(), name.c_str(), unaccountedAddress, diff);
- }
- }
- }
- }
- }
-
- lastAddr = currentAddress;
- }
+ HandleUnaccountedData();
// Go through include declarations
// First, handle the prototypes (static only for now)
@@ -1019,9 +1008,9 @@ std::string ZFile::ProcessDeclarations()
output += "\n";
// Next, output the actual declarations
- for (std::pair<uint32_t, Declaration*> item : declarations)
+ for (const auto& item : declarations)
{
- if (item.first < rangeStart || item.first >= rangeEnd)
+ if (!IsOffsetInFileRange(item.first))
continue;
if (item.second->includePath != "")
@@ -1033,10 +1022,10 @@ std::string ZFile::ProcessDeclarations()
if (item.second->varType == "Gfx")
extType = "dlist";
- else if (item.second->varType == "Vtx" || item.second->varType == "static Vtx")
+ else if (item.second->varType == "Vtx")
extType = "vtx";
- auto filepath = Globals::Instance->outputPath / item.second->varName;
+ auto filepath = outputPath / item.second->varName;
File::WriteAllText(
StringHelper::Sprintf("%s.%s.inc", filepath.c_str(), extType.c_str()),
item.second->text);
@@ -1059,51 +1048,25 @@ void ZFile::ProcessDeclarationText(Declaration* decl)
{
size_t refIndex = 0;
- if (decl->references.size() > 0)
- {
- for (size_t i = 0; i < decl->text.size() - 1; i++)
- {
- char c = decl->text[i];
- char c2 = decl->text[i + 1];
+ if (!(decl->references.size() > 0))
+ return;
- if (c == '@' && c2 == 'r')
- {
- if (refIndex >= decl->references.size())
- break;
-
- Declaration* refDecl = GetDeclarationRanged(decl->references[refIndex]);
- uint32_t refDeclAddr = GetDeclarationRangedAddress(decl->references[refIndex]);
+ for (size_t i = 0; i < decl->text.size() - 1; i++)
+ {
+ char c = decl->text[i];
+ char c2 = decl->text[i + 1];
- if (refDecl != nullptr)
- {
- if (refDecl->isArray)
- {
- if (refDecl->arrayItemCnt != 0)
- {
- int32_t itemSize = refDecl->size / refDecl->arrayItemCnt;
- int32_t itemIndex =
- (decl->references[refIndex] - refDeclAddr) / itemSize;
+ if (c == '@' && c2 == 'r')
+ {
+ std::string vtxName;
+ Globals::Instance->GetSegmentedArrayIndexedName(decl->references[refIndex], 0x10, this,
+ "Vtx", vtxName);
+ decl->text.replace(i, 2, vtxName);
- decl->text.replace(i, 2,
- StringHelper::Sprintf(
- "&%s[%i]", refDecl->varName.c_str(), itemIndex));
- }
- else
- {
- decl->text.replace(i, 2,
- StringHelper::Sprintf("ERROR ARRAYITEMCNT = 0"));
- }
- }
- else
- {
- decl->text.replace(i, 2, refDecl->varName);
- }
- }
- else
- decl->text.replace(i, 2, "ERROR");
+ refIndex++;
- refIndex++;
- }
+ if (refIndex >= decl->references.size())
+ break;
}
}
}
@@ -1112,9 +1075,9 @@ std::string ZFile::ProcessExterns()
{
std::string output;
- for (std::pair<uint32_t, Declaration*> item : declarations)
+ for (const auto& item : declarations)
{
- if (item.first < rangeStart || item.first >= rangeEnd)
+ if (!IsOffsetInFileRange(item.first))
{
continue;
}
@@ -1162,8 +1125,9 @@ std::string ZFile::ProcessTextureIntersections([[maybe_unused]] const std::strin
}
else
{
- std::string texName = GetDeclarationPtrName(currentOffset);
+ std::string texName;
std::string texNextName;
+ GetDeclarationPtrName(currentOffset, "", texName);
Declaration* nextDecl = GetDeclaration(nextOffset);
if (nextDecl == nullptr)
@@ -1174,6 +1138,7 @@ std::string ZFile::ProcessTextureIntersections([[maybe_unused]] const std::strin
defines += StringHelper::Sprintf("#define %s ((u32)%s + 0x%06X)\n",
texNextName.c_str(), texName.c_str(), offsetDiff);
+ delete declarations[nextOffset];
declarations.erase(nextOffset);
texturesResources.erase(nextOffset);
texturesSorted.erase(texturesSorted.begin() + i + 1);
@@ -1185,3 +1150,155 @@ std::string ZFile::ProcessTextureIntersections([[maybe_unused]] const std::strin
return defines;
}
+
+void ZFile::HandleUnaccountedData()
+{
+ uint32_t lastAddr = 0;
+ uint32_t lastSize = 0;
+ std::vector<uint32_t> declsAddresses;
+ for (const auto& item : declarations)
+ {
+ declsAddresses.push_back(item.first);
+ }
+
+ bool breakLoop = false;
+ for (uint32_t currentAddress : declsAddresses)
+ {
+ if (currentAddress >= rangeEnd)
+ {
+ breakLoop = true;
+ break;
+ }
+
+ if (currentAddress < rangeStart)
+ {
+ lastAddr = currentAddress;
+ continue;
+ }
+
+ breakLoop = HandleUnaccountedAddress(currentAddress, lastAddr, lastSize);
+ if (breakLoop)
+ break;
+
+ lastAddr = currentAddress;
+ }
+
+ if (!breakLoop)
+ {
+ // TODO: change rawData.size() to rangeEnd
+ // HandleUnaccountedAddress(rangeEnd, lastAddr, lastSize);
+ HandleUnaccountedAddress(rawData.size(), lastAddr, lastSize);
+ }
+}
+
+bool ZFile::HandleUnaccountedAddress(uint32_t currentAddress, uint32_t lastAddr, uint32_t& lastSize)
+{
+ if (currentAddress != lastAddr && declarations.find(lastAddr) != declarations.end())
+ {
+ Declaration* lastDecl = declarations.at(lastAddr);
+ lastSize = lastDecl->size;
+
+ if (lastAddr + lastSize > currentAddress)
+ {
+ 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());
+ }
+ }
+
+ uint32_t unaccountedAddress = lastAddr + lastSize;
+
+ if (unaccountedAddress != currentAddress && lastAddr >= rangeStart &&
+ unaccountedAddress < rangeEnd)
+ {
+ int diff = currentAddress - unaccountedAddress;
+ bool nonZeroUnaccounted = false;
+
+ std::string src = " ";
+
+ if (currentAddress > rawData.size())
+ {
+ throw std::runtime_error(StringHelper::Sprintf(
+ "ZFile::ProcessDeclarations(): Fatal error while processing XML '%s'.\n"
+ "\t Offset '0x%X' is outside of the limits of file '%s', which has a size of "
+ "'0x%X'.\n"
+ "\t Aborting...",
+ xmlFilePath.c_str(), currentAddress, name.c_str(), rawData.size()));
+ }
+
+ for (int i = 0; i < diff; i++)
+ {
+ uint8_t val = rawData.at(unaccountedAddress + i);
+ src += StringHelper::Sprintf("0x%02X, ", val);
+ if (val != 0x00)
+ {
+ nonZeroUnaccounted = true;
+ }
+
+ if (Globals::Instance->verboseUnaccounted)
+ {
+ if ((i % 4 == 3))
+ {
+ src += StringHelper::Sprintf(" // 0x%06X", unaccountedAddress + i - 3);
+ if (i != (diff - 1))
+ {
+ src += "\n\t";
+ }
+ }
+ }
+ else
+ {
+ if ((i % 16 == 15) && (i != (diff - 1)))
+ src += "\n ";
+ }
+ }
+
+ if (declarations.find(unaccountedAddress) == declarations.end() && diff > 0)
+ {
+ std::string unaccountedPrefix = "unaccounted";
+
+ if (diff < 16 && !nonZeroUnaccounted)
+ {
+ unaccountedPrefix = "possiblePadding";
+
+ // Strip unnecessary padding at the end of the file.
+ if (unaccountedAddress + diff >= rawData.size())
+ return true;
+ }
+
+ Declaration* decl = AddDeclarationArray(
+ unaccountedAddress, DeclarationAlignment::Align4, diff, "u8",
+ StringHelper::Sprintf("%s_%s_%06X", name.c_str(), unaccountedPrefix.c_str(),
+ unaccountedAddress),
+ diff, src);
+ decl->isUnaccounted = true;
+
+ if (Globals::Instance->warnUnaccounted)
+ {
+ 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);
+ }
+ }
+ }
+ }
+
+ return false;
+}