summaryrefslogtreecommitdiff
path: root/ZAPD/ZFile.cpp
diff options
context:
space:
mode:
authorKenix3 <kenixwhisperwind@gmail.com>2020-12-30 19:25:06 -0500
committerGitHub <noreply@github.com>2020-12-30 19:25:06 -0500
commit27c17b20d38a72b7a8016852fa85311dcdc40f11 (patch)
treecc62e053f3ff368e1affbd809a34e2e99ce1c74a /ZAPD/ZFile.cpp
parentfd533747ddfa6645a53f6b1356b5b68d7f2f0bed (diff)
ZAP2 project renamed to ZAPD (#27)
Diffstat (limited to 'ZAPD/ZFile.cpp')
-rw-r--r--ZAPD/ZFile.cpp828
1 files changed, 828 insertions, 0 deletions
diff --git a/ZAPD/ZFile.cpp b/ZAPD/ZFile.cpp
new file mode 100644
index 0000000..0ee2b78
--- /dev/null
+++ b/ZAPD/ZFile.cpp
@@ -0,0 +1,828 @@
+#include "ZFile.h"
+#include "ZBlob.h"
+#include "ZDisplayList.h"
+#include "ZRoom/ZRoom.h"
+#include "ZTexture.h"
+#include "ZAnimation.h"
+#include "ZSkeleton.h"
+#include "Path.h"
+#include "File.h"
+#include "Directory.h"
+#include "Globals.h"
+#include "HighLevel/HLModelIntermediette.h"
+#include <algorithm>
+#include <cassert>
+
+using namespace tinyxml2;
+using namespace std;
+
+ZFile::ZFile()
+{
+ resources = vector<ZResource*>();
+ basePath = "";
+ outputPath = Directory::GetCurrentDirectory();
+ declarations = map<int32_t, Declaration*>();
+ defines = "";
+ baseAddress = 0;
+ rangeStart = 0x000000000;
+ rangeEnd = 0xFFFFFFFF;
+}
+
+ZFile::ZFile(string nOutPath, string nName) : ZFile()
+{
+ outputPath = nOutPath;
+ name = nName;
+}
+
+ZFile::ZFile(ZFileMode mode, XMLElement* reader, string nBasePath, string nOutPath, bool placeholderMode) : ZFile()
+{
+ if (nBasePath == "")
+ basePath = Directory::GetCurrentDirectory();
+ else
+ basePath = nBasePath;
+
+ if (nOutPath == "")
+ outputPath = Directory::GetCurrentDirectory();
+ else
+ outputPath = nOutPath;
+
+ ParseXML(mode, reader, placeholderMode);
+}
+
+void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, bool placeholderMode)
+{
+ name = reader->Attribute("Name");
+ int segment = -1;
+
+ if (reader->Attribute("BaseAddress") != NULL)
+ baseAddress = (uint32_t)strtoul(StringHelper::Split(reader->Attribute("BaseAddress"), "0x")[1].c_str(), NULL, 16);
+
+ if (reader->Attribute("RangeStart") != NULL)
+ rangeStart = (uint32_t)strtoul(StringHelper::Split(reader->Attribute("RangeStart"), "0x")[1].c_str(), NULL, 16);
+
+ if (reader->Attribute("RangeEnd") != NULL)
+ rangeEnd = (uint32_t)strtoul(StringHelper::Split(reader->Attribute("RangeEnd"), "0x")[1].c_str(), NULL, 16);
+
+ if (reader->Attribute("Segment") != NULL)
+ segment = strtol(reader->Attribute("Segment"), NULL, 10);
+
+ if (segment != -1)
+ {
+ //printf("Adding Segment %i\n", segment);
+ Globals::Instance->AddSegment(segment);
+ }
+
+ string folderName = basePath + "/" + Path::GetFileNameWithoutExtension(name);
+
+ if (mode == ZFileMode::Extract)
+ {
+ if (!File::Exists(basePath + "/" + name))
+ throw StringHelper::Sprintf("Error! File %s does not exist.", (basePath + "/" + name).c_str());
+
+ rawData = File::ReadAllBytes(basePath + "/" + name);
+ }
+
+ int rawDataIndex = 0;
+
+ for (XMLElement* child = reader->FirstChildElement(); child != NULL; child = child->NextSiblingElement())
+ {
+ if (child->Attribute("Offset") != NULL)
+ rawDataIndex = strtol(StringHelper::Split(child->Attribute("Offset"), "0x")[1].c_str(), NULL, 16);
+
+ printf("%s: %08X\n", child->Attribute("Name"), rawDataIndex);
+
+ if (string(child->Name()) == "Texture")
+ {
+ ZTexture* tex = nullptr;
+
+ if (mode == ZFileMode::Extract)
+ tex = ZTexture::ExtractFromXML(child, rawData, rawDataIndex, folderName);
+ else
+ tex = ZTexture::BuildFromXML(child, folderName, mode == ZFileMode::Build);
+
+ tex->SetRawDataIndex(rawDataIndex);
+
+ tex->parent = this;
+
+ resources.push_back(tex);
+ rawDataIndex += tex->GetRawDataSize();
+ }
+ else if (string(child->Name()) == "Blob")
+ {
+ ZBlob* blob = nullptr;
+
+ if (mode == ZFileMode::Extract)
+ blob = ZBlob::ExtractFromXML(child, rawData, rawDataIndex, folderName);
+ else
+ blob = ZBlob::BuildFromXML(child, folderName, mode == ZFileMode::Build);
+
+ blob->parent = this;
+
+ resources.push_back(blob);
+
+ rawDataIndex += blob->GetRawDataSize();
+ }
+ else if (string(child->Name()) == "DList")
+ {
+ ZResource* dList = nullptr;
+
+ if (mode == ZFileMode::Extract)
+ dList = ZDisplayList::ExtractFromXML(child, rawData, rawDataIndex, ZDisplayList::GetDListLength(rawData, rawDataIndex), folderName);
+ //else
+ //dList = ZDisplayList::BuildFromXML(child, folderName, mode == ZFileMode::Build);
+ else
+ dList = ZBlob::BuildFromXML(child, folderName, mode == ZFileMode::Build);
+
+ dList->parent = this;
+
+ resources.push_back(dList);
+
+ rawDataIndex += dList->GetRawDataSize();
+ }
+ else if (string(child->Name()) == "Scene" || string(child->Name()) == "Room")
+ {
+ ZRoom* room = nullptr;
+
+ if (mode == ZFileMode::Extract)
+ room = ZRoom::ExtractFromXML(child, rawData, rawDataIndex, folderName, this, Globals::Instance->lastScene);
+
+ if (string(child->Name()) == "Scene")
+ {
+ Globals::Instance->lastScene = room;
+
+ if (segment == -1)
+ segment = SEGMENT_SCENE;
+ }
+ else
+ {
+ if (segment == -1)
+ segment = SEGMENT_ROOM;
+ }
+
+ if (segment != -1)
+ Globals::Instance->AddSegment(segment);
+
+ resources.push_back(room);
+
+ rawDataIndex += room->GetRawDataSize();
+ }
+ else if (string(child->Name()) == "Animation")
+ {
+ ZAnimation* anim = nullptr;
+
+ if (mode == ZFileMode::Extract)
+ anim = ZAnimation::ExtractFromXML(child, rawData, rawDataIndex, folderName);
+
+ anim->parent = this;
+ resources.push_back(anim);
+
+ rawDataIndex += anim->GetRawDataSize();
+ }
+ else if (string(child->Name()) == "Skeleton")
+ {
+ ZSkeleton* skeleton = nullptr;
+
+ if (mode == ZFileMode::Extract)
+ skeleton = ZSkeleton::FromXML(child, rawData, rawDataIndex, folderName, this);
+
+ resources.push_back(skeleton);
+ rawDataIndex += skeleton->GetRawDataSize();
+ }
+ else if (string(child->Name()) == "Limb")
+ {
+ ZLimbStandard* limb = nullptr;
+
+ if (mode == ZFileMode::Extract)
+ limb = ZLimbStandard::FromXML(child, rawData, rawDataIndex, folderName, this);
+
+ resources.push_back(limb);
+
+ rawDataIndex += limb->GetRawDataSize();
+ }
+ else if (string(child->Name()) == "Symbol")
+ {
+ ZResource* res = nullptr;
+
+ if (mode == ZFileMode::Extract)
+ {
+ res = new ZResource();
+ res->SetName(child->Attribute("Name"));
+ res->SetRawDataIndex(rawDataIndex);
+ res->outputDeclaration = false;
+ }
+
+ resources.push_back(res);
+ }
+ else if (string(child->Name()) == "Vec3s")
+ {
+
+ }
+ else if (string(child->Name()) == "Vec3f")
+ {
+
+ }
+ else if (string(child->Name()) == "Vec3i")
+ {
+
+ }
+ else if (string(child->Name()) == "String")
+ {
+
+ }
+ else
+ {
+
+ }
+ }
+}
+
+void ZFile::BuildResources()
+{
+ cout << "Building resources " << name << "\n";
+
+ int size = 0;
+
+ for (ZResource* res : resources)
+ size += res->GetRawDataSize();
+
+ // Make sure size is 16 byte aligned
+ if (size % 16 != 0)
+ size = ((size / 16) + 1) * 16;
+
+ vector<uint8_t> file = vector<uint8_t>(size);
+ int fileIndex = 0;
+
+ for (ZResource* res : resources)
+ {
+ //Console.WriteLine("Building resource " + res.GetName());
+ memcpy(file.data() + fileIndex, res->GetRawData().data(), res->GetRawData().size());
+ //Array.Copy(res.GetRawData(), 0, file, fileIndex, res.GetRawData().Length);
+ fileIndex += res->GetRawData().size();
+ }
+
+ File::WriteAllBytes(basePath + "/" + name, file);
+}
+
+void ZFile::BuildSourceFile(string outputDir)
+{
+ string folderName = Path::GetFileNameWithoutExtension(outputPath);
+
+ if (!Directory::Exists(outputPath))
+ Directory::CreateDirectory(outputPath);
+
+ GenerateSourceFiles(outputDir);
+}
+
+std::string ZFile::GetVarName(int address)
+{
+ for (pair<int32_t, Declaration*> pair : declarations)
+ {
+ if (pair.first == address)
+ return pair.second->varName;
+ }
+
+ return "";
+}
+
+void ZFile::ExtractResources(string outputDir)
+{
+ string folderName = Path::GetFileNameWithoutExtension(outputPath);
+
+ //printf("DIR CHECK: %s\n", folderName.c_str());
+ //printf("OUT CHECK: %s\n", outputDir.c_str());
+
+ if (!Directory::Exists(outputPath))
+ Directory::CreateDirectory(outputPath);
+
+ for (ZResource* res : resources)
+ res->PreGenSourceFiles();
+
+ if (Globals::Instance->genSourceFile)
+ GenerateSourceFiles(outputDir);
+
+ for (ZResource* res : resources)
+ {
+ printf("Saving resource %s\n", res->GetName().c_str());
+ res->CalcHash(); // TEST
+ res->Save(outputPath);
+ }
+
+ if (Globals::Instance->testMode)
+ GenerateHLIntermediette();
+}
+
+void ZFile::AddResource(ZResource* res)
+{
+ resources.push_back(res);
+}
+
+Declaration* ZFile::AddDeclaration(uint32_t address, DeclarationAlignment alignment, uint32_t size, std::string varType, std::string varName, std::string body)
+{
+#if _DEBUG
+ if (declarations.find(address) != declarations.end())
+ {
+ int bp = 0;
+ }
+#endif
+
+ AddDeclarationDebugChecks(address);
+
+ Declaration* decl = new Declaration(alignment, size, varType, varName, false, body);
+ declarations[address] = decl;
+ return decl;
+}
+
+void ZFile::AddDeclaration(uint32_t address, DeclarationAlignment alignment, DeclarationPadding padding, uint32_t size, string varType, string varName, std::string body)
+{
+#if _DEBUG
+ if (declarations.find(address) != declarations.end())
+ {
+ int bp = 0;
+ }
+#endif
+
+ AddDeclarationDebugChecks(address);
+
+ declarations[address] = new Declaration(alignment, padding, size, varType, varName, false, body);
+}
+
+void ZFile::AddDeclarationArray(uint32_t address, DeclarationAlignment alignment, uint32_t size, std::string varType, std::string varName, int arrayItemCnt, std::string body)
+{
+#if _DEBUG
+ if (declarations.find(address) != declarations.end())
+ {
+ int bp = 0;
+ }
+#endif
+
+ AddDeclarationDebugChecks(address);
+
+ declarations[address] = new Declaration(alignment, size, varType, varName, true, arrayItemCnt, body);
+}
+
+
+void ZFile::AddDeclarationArray(uint32_t address, DeclarationAlignment alignment, DeclarationPadding padding, uint32_t size, string varType, string varName, int arrayItemCnt, std::string body)
+{
+#if _DEBUG
+ if (declarations.find(address) != declarations.end())
+ {
+ int bp = 0;
+ }
+#endif
+
+ AddDeclarationDebugChecks(address);
+
+ declarations[address] = new Declaration(alignment, padding, size, varType, varName, true, arrayItemCnt, body);
+}
+
+
+void ZFile::AddDeclarationPlaceholder(uint32_t address)
+{
+ AddDeclarationDebugChecks(address);
+
+ if (declarations.find(address) == declarations.end())
+ declarations[address] = new Declaration(DeclarationAlignment::None, 0, "", "", false, "");
+}
+
+void ZFile::AddDeclarationPlaceholder(uint32_t address, string varName)
+{
+ AddDeclarationDebugChecks(address);
+
+ if (declarations.find(address) == declarations.end())
+ declarations[address] = new Declaration(DeclarationAlignment::None, 0, "", varName, false, "");
+}
+
+void ZFile::AddDeclarationInclude(uint32_t address, string includePath, uint32_t size, string varType, string varName)
+{
+ AddDeclarationDebugChecks(address);
+
+ if (declarations.find(address) == declarations.end())
+ declarations[address] = new Declaration(includePath, size, varType, varName);
+}
+
+void ZFile::AddDeclarationIncludeArray(uint32_t address, std::string includePath, uint32_t size, std::string varType, std::string varName, int arrayItemCnt)
+{
+#if _DEBUG
+ if (declarations.find(address) != declarations.end())
+ {
+ int bp = 0;
+ }
+#endif
+
+ AddDeclarationDebugChecks(address);
+
+ Declaration* decl = new Declaration(includePath, size, varType, varName);
+
+ decl->isArray = true;
+ decl->arrayItemCnt = arrayItemCnt;
+
+ declarations[address] = decl;
+}
+
+void ZFile::AddDeclarationDebugChecks(uint32_t address)
+{
+#ifdef _DEBUG
+ if (address == 0xB888E0)
+ {
+ int bp = 0;
+ }
+#endif
+}
+
+std::string ZFile::GetDeclarationName(uint32_t address)
+{
+ return GetDeclarationName(address, "ERROR_COULD_NOT_FIND_DECLARATION"); // Note: For now that default message is just for testing
+}
+
+std::string ZFile::GetDeclarationName(uint32_t address, std::string defaultResult)
+{
+ if (declarations.find(address) != declarations.end())
+ return declarations[address]->varName;
+
+ return defaultResult;
+}
+
+Declaration* ZFile::GetDeclaration(uint32_t address)
+{
+ if (declarations.find(address) != declarations.end())
+ return declarations[address];
+
+ return nullptr;
+}
+
+Declaration* ZFile::GetDeclarationRanged(uint32_t address)
+{
+ for (const auto decl : declarations)
+ {
+ if (address >= decl.first && address <= decl.first + decl.second->size)
+ {
+ return decl.second;
+ }
+ }
+
+ return nullptr;
+}
+
+bool ZFile::HasDeclaration(uint32_t address)
+{
+ return (declarations.find(address) != declarations.end());
+}
+
+void ZFile::GenerateSourceFiles(string outputDir)
+{
+ sourceOutput = "";
+
+ sourceOutput += "#include <ultra64.h>\n";
+ sourceOutput += "#include <z64.h>\n";
+ sourceOutput += GetHeaderInclude();
+
+ GeneratePlaceholderDeclarations();
+
+ // Generate Code
+ for (ZResource* res : resources)
+ {
+ string resSrc = res->GetSourceOutputCode(name);
+
+ if (res->IsExternalResource())
+ {
+ //cout << "EXTERN\n";
+ string path = Path::GetFileNameWithoutExtension(res->GetName()).c_str();
+
+ while (StringHelper::EndsWith(outputDir, "/"))
+ outputDir = outputDir.substr(0, outputDir.length() - 1);
+
+ // HACK
+ string declType = "u64";
+
+ if (res->GetResourceType() != ZResourceType::Texture)
+ declType = "u8";
+
+ AddDeclarationIncludeArray(res->GetRawDataIndex(), StringHelper::Sprintf("%s/%s.%s.inc.c",
+ outputDir.c_str(), Path::GetFileNameWithoutExtension(res->GetOutName()).c_str(), res->GetExternalExtension().c_str()), res->GetRawDataSize(),
+ declType, res->GetName(), 0);
+
+
+ //File::WriteAllText("build/" + outputDir + "/" + Path::GetFileNameWithoutExtension(res->GetName()) + ".inc.c", resSrc);
+ }
+ else
+ {
+ //cout << "NOT EXTERN\n";
+ sourceOutput += resSrc;
+ }
+
+ if (resSrc != "" && !res->IsExternalResource())
+ sourceOutput += "\n";
+ }
+
+ sourceOutput += ProcessDeclarations();
+
+ while (StringHelper::EndsWith(outputDir, "/"))
+ outputDir = outputDir.substr(0, outputDir.length() - 1);
+
+ string buildPath = "build/" + outputDir + "/" + "basefile.txt";
+ string outPath = outputDir + "/" + Path::GetFileNameWithoutExtension(name) + ".c";
+ //printf("WRITING %s\n", buildPath.c_str());
+
+ //if (!Directory::Exists(Path::GetPath(outPath)))
+ //Directory::CreateDirectory(Path::GetPath(outPath));
+
+ //if (!Directory::Exists(Path::GetPath(buildPath)))
+ //Directory::CreateDirectory(Path::GetPath(buildPath));
+
+ File::WriteAllText(outPath, sourceOutput);
+ File::WriteAllText(buildPath, outPath);
+
+ // Generate Header
+ sourceOutput = "";
+
+ for (ZResource* res : resources)
+ {
+ string resSrc = res->GetSourceOutputHeader("");
+ sourceOutput += resSrc;
+
+ if (resSrc != "")
+ sourceOutput += "\n";
+ }
+
+ sourceOutput += ProcessExterns();
+
+ File::WriteAllText(outputDir + "/" + Path::GetFileNameWithoutExtension(name) + ".h", sourceOutput);
+}
+
+void ZFile::GenerateHLIntermediette()
+{
+ // This is kinda hacky but it gets the job done for now...
+ HLModelIntermediette* mdl = new HLModelIntermediette();
+
+ for (ZResource* res : resources)
+ {
+ if (typeid(ZDisplayList) == typeid(*res) || typeid(ZSkeleton) == typeid(*res))
+ res->GenerateHLIntermediette(*mdl);
+ }
+
+ std::string test = mdl->ToOBJFile();
+ std::string test2 = mdl->ToFBXFile();
+}
+
+std::string ZFile::GetHeaderInclude()
+{
+ return StringHelper::Sprintf("#include \"%s\"\n\n", (Path::GetFileNameWithoutExtension(name) + ".h").c_str());
+}
+
+void ZFile::GeneratePlaceholderDeclarations()
+{
+ // Generate placeholder declarations
+ for (ZResource* res : resources)
+ {
+ if (GetDeclaration(res->GetRawDataIndex()) == nullptr)
+ AddDeclarationPlaceholder(res->GetRawDataIndex(), res->GetName());
+ }
+}
+
+string ZFile::ProcessDeclarations()
+{
+ string output = "";
+
+ if (declarations.size() == 0)
+ return output;
+
+ auto declarationKeysSorted = vector<pair<int32_t, Declaration*>>(declarations.begin(), declarations.end());
+ sort(declarationKeysSorted.begin(), declarationKeysSorted.end(), [](const auto& lhs, const auto& rhs)
+ {
+ return lhs.first < rhs.first;
+ });
+
+ // Account for padding/alignment
+ int lastAddr = 0;
+
+ //printf("RANGE START: 0x%08X - RANGE END: 0x%08X\n", rangeStart, rangeEnd);
+
+ for (pair<int32_t, Declaration*> item : declarationKeysSorted)
+ {
+ while (declarations[item.first]->size % 4 != 0)
+ {
+ declarations[item.first]->size++;
+ }
+
+ if (lastAddr != 0)
+ {
+ if (item.second->alignment == DeclarationAlignment::Align16)
+ {
+ int lastAddrSizeTest = declarations[lastAddr]->size;
+ int curPtr = lastAddr + declarations[lastAddr]->size;
+
+ while (curPtr % 4 != 0)
+ {
+ declarations[lastAddr]->size++;
+ //declarations[item.first]->size++;
+ curPtr++;
+ }
+
+ /*while (curPtr % 16 != 0)
+ {
+ char buffer[2048];
+
+ sprintf(buffer, "static u32 align%02X = 0;\n", curPtr);
+ declarations[item.first]->text = buffer + declarations[item.first]->text;
+
+ declarations[lastAddr]->size += 4;
+ curPtr += 4;
+ }*/
+ }
+ else if (item.second->alignment == DeclarationAlignment::Align8)
+ {
+ int curPtr = lastAddr + declarations[lastAddr]->size;
+
+ while (curPtr % 4 != 0)
+ {
+ declarations[lastAddr]->size++;
+ //item.second->size++;
+ //declarations[item.first]->size++;
+ curPtr++;
+ }
+
+ while (curPtr % 8 != 0)
+ {
+ char buffer[2048];
+
+ sprintf(buffer, "static u32 align%02X = 0;\n", curPtr);
+ declarations[item.first]->preText = buffer + declarations[item.first]->preText;
+
+ declarations[lastAddr]->size += 4;
+ //item.second->size += 4;
+ //declarations[item.first]->size += 4;
+ curPtr += 4;
+ }
+ }
+ }
+
+ if (item.second->padding == DeclarationPadding::Pad16)
+ {
+ int curPtr = item.first + item.second->size;
+
+ while (curPtr % 4 != 0)
+ {
+ item.second->size++;
+ curPtr++;
+ }
+
+ while (curPtr % 16 != 0)
+ {
+ declarations[item.first]->postText += StringHelper::Sprintf("static u32 pad%02X = 0;\n", curPtr);
+
+ item.second->size += 4;
+ curPtr += 4;
+ }
+ }
+
+ lastAddr = item.first;
+ }
+
+ // Handle unaccounted data
+ lastAddr = 0;
+ for (pair<int32_t, Declaration*> item : declarationKeysSorted)
+ {
+ if (lastAddr != 0 && item.first >= rangeStart && item.first < rangeEnd)
+ {
+ if (lastAddr + declarations[lastAddr]->size > item.first)
+ {
+ // UH OH!
+ int bp = 0;
+ }
+
+ uint8_t* rawDataArr = rawData.data();
+
+ if (lastAddr + declarations[lastAddr]->size != item.first)
+ {
+ int diff = item.first - (lastAddr + declarations[lastAddr]->size);
+
+ string src = "\t";
+
+ for (int i = 0; i < diff; i++)
+ {
+ src += StringHelper::Sprintf("0x%02X, ", rawDataArr[lastAddr + declarations[lastAddr]->size + i]);
+
+ if (i % 16 == 15)
+ src += "\n\t";
+ }
+
+ if (declarations.find(lastAddr + declarations[lastAddr]->size) == declarations.end())
+ {
+ if (diff > 0)
+ {
+ AddDeclarationArray(lastAddr + declarations[lastAddr]->size, DeclarationAlignment::None, diff, "static u8", StringHelper::Sprintf("unaccounted%04X", lastAddr + declarations[lastAddr]->size),
+ diff, src);
+ }
+ }
+ }
+ }
+
+ lastAddr = item.first;
+ }
+
+ // TODO: THIS CONTAINS REDUNDANCIES. CLEAN THIS UP!
+ if (lastAddr + declarations[lastAddr]->size < rawData.size() && lastAddr + declarations[lastAddr]->size >= rangeStart && lastAddr + declarations[lastAddr]->size < rangeEnd)
+ {
+ int diff = (int)(rawData.size() - (lastAddr + declarations[lastAddr]->size));
+
+ string src = "\t";
+
+ for (int i = 0; i < diff; i++)
+ {
+ src += StringHelper::Sprintf("0x%02X, ", rawData[lastAddr + declarations[lastAddr]->size + i]);
+
+ if (i % 16 == 15)
+ src += "\n\t";
+ }
+
+ if (declarations.find(lastAddr + declarations[lastAddr]->size) == declarations.end())
+ {
+ if (diff > 0)
+ {
+ AddDeclarationArray(lastAddr + declarations[lastAddr]->size, DeclarationAlignment::None, diff, "static u8", StringHelper::Sprintf("unaccounted%04X", lastAddr + declarations[lastAddr]->size),
+ diff, src);
+ }
+ }
+ }
+
+ // Go through include declarations
+ declarationKeysSorted = vector<pair<int32_t, Declaration*>>(declarations.begin(), declarations.end());
+ sort(declarationKeysSorted.begin(), declarationKeysSorted.end(), [](const auto& lhs, const auto& rhs)
+ {
+ return lhs.first < rhs.first;
+ });
+
+ for (pair<int32_t, Declaration*> item : declarationKeysSorted)
+ {
+ if (item.second->includePath != "")
+ {
+ //output += StringHelper::Sprintf("#include \"%s\"\n", item.second->includePath.c_str());
+ output += StringHelper::Sprintf("%s %s[] = {\n#include \"%s\"\n};\n", item.second->varType.c_str(), item.second->varName.c_str(), item.second->includePath.c_str());
+ }
+ else if (item.second->varType != "")
+ {
+ if (item.second->preText != "")
+ output += item.second->preText + "\n";
+
+ if (item.second->isArray)
+ {
+ if (item.second->arrayItemCnt == 0)
+ output += StringHelper::Sprintf("%s %s[] = \n{\n", item.second->varType.c_str(), item.second->varName.c_str());
+ else
+ output += StringHelper::Sprintf("%s %s[%i] = \n{\n", item.second->varType.c_str(), item.second->varName.c_str(), item.second->arrayItemCnt);
+
+ output += item.second->text + "\n";
+ }
+ else
+ {
+ output += StringHelper::Sprintf("%s %s = {", item.second->varType.c_str(), item.second->varName.c_str());
+ output += item.second->text;
+ }
+
+
+ output += "};";
+ output += " " + item.second->rightText + "\n\n";
+
+ if (item.second->postText != "")
+ output += item.second->postText + "\n";
+ }
+ }
+
+ output += "\n";
+
+ return output;
+}
+
+
+string ZFile::ProcessExterns()
+{
+ string output = "";
+
+ auto declarationKeysSorted = vector<pair<int32_t, Declaration*>>(declarations.begin(), declarations.end());
+ sort(declarationKeysSorted.begin(), declarationKeysSorted.end(), [](const auto& lhs, const auto& rhs)
+ {
+ return lhs.first < rhs.first;
+ });
+
+ for (pair<int32_t, Declaration*> item : declarationKeysSorted)
+ {
+ if (!StringHelper::StartsWith(item.second->varType, "static ") && item.second->varType != "")// && item.second->includePath == "")
+ {
+ if (item.second->isArray)
+ {
+ if (item.second->arrayItemCnt == 0)
+ output += StringHelper::Sprintf("extern %s %s[];\n", item.second->varType.c_str(), item.second->varName.c_str());
+ else
+ output += StringHelper::Sprintf("extern %s %s[%i];\n", item.second->varType.c_str(), item.second->varName.c_str(), item.second->arrayItemCnt);
+ }
+ else
+ output += StringHelper::Sprintf("extern %s %s;\n", item.second->varType.c_str(), item.second->varName.c_str());
+ }
+ }
+
+ output += "\n";
+
+ output += defines;
+
+ return output;
+} \ No newline at end of file