2021-01-02 04:24:29 +00:00
|
|
|
#include "ZFile.h"
|
2021-03-20 16:02:12 +00:00
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
2021-04-30 21:23:22 +00:00
|
|
|
#include <unordered_set>
|
2021-03-20 16:02:12 +00:00
|
|
|
#include "Directory.h"
|
|
|
|
#include "File.h"
|
|
|
|
#include "Globals.h"
|
|
|
|
#include "HighLevel/HLModelIntermediette.h"
|
2021-04-30 21:23:22 +00:00
|
|
|
#include "OutputFormatter.h"
|
2021-03-20 16:02:12 +00:00
|
|
|
#include "Path.h"
|
|
|
|
#include "ZAnimation.h"
|
|
|
|
#include "ZArray.h"
|
2021-04-30 21:23:22 +00:00
|
|
|
#include "ZBackground.h"
|
2021-01-02 04:24:29 +00:00
|
|
|
#include "ZBlob.h"
|
2021-03-20 16:02:12 +00:00
|
|
|
#include "ZCollision.h"
|
|
|
|
#include "ZCutscene.h"
|
2021-01-02 04:24:29 +00:00
|
|
|
#include "ZDisplayList.h"
|
2021-03-14 15:40:25 +00:00
|
|
|
#include "ZLimb.h"
|
2021-04-30 21:23:22 +00:00
|
|
|
#include "ZMtx.h"
|
2021-03-20 16:02:12 +00:00
|
|
|
#include "ZRoom/ZRoom.h"
|
2021-01-09 00:38:28 +00:00
|
|
|
#include "ZScalar.h"
|
2021-03-20 16:02:12 +00:00
|
|
|
#include "ZSkeleton.h"
|
|
|
|
#include "ZSymbol.h"
|
|
|
|
#include "ZTexture.h"
|
2021-01-09 00:38:28 +00:00
|
|
|
#include "ZVector.h"
|
2021-01-22 21:25:08 +00:00
|
|
|
#include "ZVtx.h"
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
using namespace tinyxml2;
|
|
|
|
|
|
|
|
ZFile::ZFile()
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
resources = std::vector<ZResource*>();
|
2021-01-02 04:24:29 +00:00
|
|
|
basePath = "";
|
|
|
|
outputPath = Directory::GetCurrentDirectory();
|
2021-05-30 15:09:59 +00:00
|
|
|
declarations = std::map<uint32_t, Declaration*>();
|
2021-01-02 04:24:29 +00:00
|
|
|
defines = "";
|
|
|
|
baseAddress = 0;
|
|
|
|
rangeStart = 0x000000000;
|
|
|
|
rangeEnd = 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
ZFile::ZFile(const fs::path& nOutPath, std::string nName) : ZFile()
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
|
|
|
outputPath = nOutPath;
|
|
|
|
name = nName;
|
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
ZFile::ZFile(ZFileMode mode, tinyxml2::XMLElement* reader, const fs::path& nBasePath,
|
|
|
|
const fs::path& nOutPath, std::string filename, const fs::path& nXmlFilePath,
|
|
|
|
bool placeholderMode)
|
2021-03-20 16:02:12 +00:00
|
|
|
: ZFile()
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
xmlFilePath = nXmlFilePath;
|
2021-01-02 04:24:29 +00:00
|
|
|
if (nBasePath == "")
|
|
|
|
basePath = Directory::GetCurrentDirectory();
|
|
|
|
else
|
|
|
|
basePath = nBasePath;
|
|
|
|
|
|
|
|
if (nOutPath == "")
|
|
|
|
outputPath = Directory::GetCurrentDirectory();
|
|
|
|
else
|
|
|
|
outputPath = nOutPath;
|
|
|
|
|
2021-01-22 21:25:08 +00:00
|
|
|
ParseXML(mode, reader, filename, placeholderMode);
|
2021-05-30 15:09:59 +00:00
|
|
|
DeclareResourceSubReferences();
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-01-09 00:38:28 +00:00
|
|
|
ZFile::~ZFile()
|
|
|
|
{
|
|
|
|
for (ZResource* res : resources)
|
2021-04-30 21:23:22 +00:00
|
|
|
{
|
2021-01-09 00:38:28 +00:00
|
|
|
delete res;
|
2021-04-30 21:23:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (auto d : declarations)
|
|
|
|
{
|
|
|
|
delete d.second;
|
|
|
|
}
|
2021-01-09 00:38:28 +00:00
|
|
|
}
|
|
|
|
|
2021-01-22 21:25:08 +00:00
|
|
|
void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, bool placeholderMode)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-01-22 21:25:08 +00:00
|
|
|
if (filename == "")
|
|
|
|
name = reader->Attribute("Name");
|
|
|
|
else
|
|
|
|
name = filename;
|
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
// TODO: This should be a variable on the ZFile, but it is a large change in order to force all
|
|
|
|
// ZResource types to have a parent ZFile.
|
2021-01-25 00:36:40 +00:00
|
|
|
const char* gameStr = reader->Attribute("Game");
|
|
|
|
if (reader->Attribute("Game") != nullptr)
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
if (std::string(gameStr) == "MM")
|
2021-01-25 00:36:40 +00:00
|
|
|
Globals::Instance->game = ZGame::MM_RETAIL;
|
2021-05-30 15:09:59 +00:00
|
|
|
else if (std::string(gameStr) == "SW97" || std::string(gameStr) == "OOTSW97")
|
2021-01-25 00:36:40 +00:00
|
|
|
Globals::Instance->game = ZGame::OOT_SW97;
|
2021-05-30 15:09:59 +00:00
|
|
|
else if (std::string(gameStr) == "OOT")
|
2021-04-30 21:23:22 +00:00
|
|
|
Globals::Instance->game = ZGame::OOT_RETAIL;
|
2021-01-25 00:36:40 +00:00
|
|
|
else
|
2021-04-30 21:23:22 +00:00
|
|
|
throw std::runtime_error(
|
|
|
|
StringHelper::Sprintf("Error: Game type %s not supported.", gameStr));
|
2021-01-25 00:36:40 +00:00
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (reader->Attribute("BaseAddress") != nullptr)
|
|
|
|
baseAddress = StringHelper::StrToL(reader->Attribute("BaseAddress"), 16);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (reader->Attribute("RangeStart") != nullptr)
|
|
|
|
rangeStart = StringHelper::StrToL(reader->Attribute("RangeStart"), 16);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (reader->Attribute("RangeEnd") != nullptr)
|
|
|
|
rangeEnd = StringHelper::StrToL(reader->Attribute("RangeEnd"), 16);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
// 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()));
|
|
|
|
*/
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (reader->Attribute("Segment") != nullptr)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
segment = StringHelper::StrToL(reader->Attribute("Segment"), 10);
|
|
|
|
Globals::Instance->AddSegment(segment, this);
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string folderName = (basePath / Path::GetFileNameWithoutExtension(name)).string();
|
2021-03-20 16:02:12 +00:00
|
|
|
|
2021-01-02 04:24:29 +00:00
|
|
|
if (mode == ZFileMode::Extract)
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
if (!File::Exists((basePath / name).string()))
|
2021-04-30 21:23:22 +00:00
|
|
|
throw std::runtime_error(
|
|
|
|
StringHelper::Sprintf("Error! File %s does not exist.", (basePath / name).c_str()));
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
rawData = File::ReadAllBytes((basePath / name).string());
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
std::unordered_set<std::string> nameSet;
|
|
|
|
std::unordered_set<std::string> outNameSet;
|
|
|
|
std::unordered_set<std::string> offsetSet;
|
|
|
|
|
|
|
|
auto nodeMap = *GetNodeMap();
|
|
|
|
uint32_t rawDataIndex = 0;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
for (XMLElement* child = reader->FirstChildElement(); child != nullptr;
|
2021-03-20 16:02:12 +00:00
|
|
|
child = child->NextSiblingElement())
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
const char* nameXml = child->Attribute("Name");
|
|
|
|
const char* outNameXml = child->Attribute("OutName");
|
|
|
|
const char* offsetXml = child->Attribute("Offset");
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
|
2021-04-30 21:23:22 +00:00
|
|
|
printf("%s: 0x%06X\n", nameXml, rawDataIndex);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
// Check for repeated attributes.
|
|
|
|
if (offsetXml != nullptr)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
rawDataIndex = strtol(StringHelper::Split(offsetXml, "0x")[1].c_str(), NULL, 16);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (offsetSet.find(offsetXml) != offsetSet.end())
|
2021-03-20 16:02:12 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
throw std::runtime_error(StringHelper::Sprintf(
|
|
|
|
"ZFile::ParseXML: Error in '%s'.\n\t Repeated 'Offset' attribute: %s \n",
|
|
|
|
name.c_str(), offsetXml));
|
2021-03-20 16:02:12 +00:00
|
|
|
}
|
2021-04-30 21:23:22 +00:00
|
|
|
offsetSet.insert(offsetXml);
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
2021-05-30 15:09:59 +00:00
|
|
|
if (outNameXml != nullptr)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
if (outNameSet.find(outNameXml) != outNameSet.end())
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
throw std::runtime_error(StringHelper::Sprintf(
|
|
|
|
"ZFile::ParseXML: Error in '%s'.\n\t Repeated 'OutName' attribute: %s \n",
|
|
|
|
name.c_str(), outNameXml));
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
2021-04-30 21:23:22 +00:00
|
|
|
outNameSet.insert(outNameXml);
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
2021-05-30 15:09:59 +00:00
|
|
|
if (nameXml != nullptr)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
if (nameSet.find(nameXml) != nameSet.end())
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
throw std::runtime_error(StringHelper::Sprintf(
|
|
|
|
"ZFile::ParseXML: Error in '%s'.\n\t Repeated 'Name' attribute: %s \n",
|
|
|
|
name.c_str(), nameXml));
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
2021-04-30 21:23:22 +00:00
|
|
|
nameSet.insert(nameXml);
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string nodeName = std::string(child->Name());
|
2021-01-09 00:38:28 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (nodeMap.find(nodeName) != nodeMap.end())
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
ZResource* nRes = nodeMap[nodeName](this);
|
2021-01-09 00:38:28 +00:00
|
|
|
|
|
|
|
if (mode == ZFileMode::Extract)
|
2021-05-30 15:09:59 +00:00
|
|
|
nRes->ExtractFromXML(child, rawData, rawDataIndex);
|
2021-01-22 21:25:08 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
auto resType = nRes->GetResourceType();
|
|
|
|
if (resType == ZResourceType::Texture)
|
|
|
|
AddTextureResource(rawDataIndex, static_cast<ZTexture*>(nRes));
|
|
|
|
else
|
|
|
|
resources.push_back(nRes);
|
2021-01-18 21:04:04 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
rawDataIndex += nRes->GetRawDataSize();
|
2021-01-18 21:04:04 +00:00
|
|
|
}
|
2021-05-30 15:09:59 +00:00
|
|
|
else if (std::string(child->Name()) == "File")
|
2021-01-22 21:25:08 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
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()));
|
2021-01-22 21:25:08 +00:00
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
else
|
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
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()));
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
void ZFile::DeclareResourceSubReferences()
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < resources.size(); i++)
|
|
|
|
{
|
|
|
|
resources.at(i)->DeclareReferences(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
void ZFile::BuildSourceFile(fs::path outputDir)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string folderName = Path::GetFileNameWithoutExtension(outputPath.string());
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (!Directory::Exists(outputPath.string()))
|
|
|
|
Directory::CreateDirectory(outputPath.string());
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
GenerateSourceFiles(outputDir);
|
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
std::string ZFile::GetVarName(uint32_t address)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
for (std::pair<uint32_t, Declaration*> pair : declarations)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
|
|
|
if (pair.first == address)
|
|
|
|
return pair.second->varName;
|
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string ZFile::GetName() const
|
2021-01-22 21:25:08 +00:00
|
|
|
{
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
const fs::path& ZFile::GetXmlFilePath() const
|
|
|
|
{
|
|
|
|
return xmlFilePath;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<uint8_t>& ZFile::GetRawData() const
|
|
|
|
{
|
|
|
|
return rawData;
|
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
void ZFile::ExtractResources(fs::path outputDir)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string folderName = Path::GetFileNameWithoutExtension(outputPath.string());
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (!Directory::Exists(outputPath.string()))
|
|
|
|
Directory::CreateDirectory(outputPath.string());
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (!Directory::Exists(Globals::Instance->sourceOutputPath.string()))
|
|
|
|
Directory::CreateDirectory(Globals::Instance->sourceOutputPath.string());
|
2021-04-30 21:23:22 +00:00
|
|
|
|
2021-01-02 04:24:29 +00:00
|
|
|
for (ZResource* res : resources)
|
|
|
|
res->PreGenSourceFiles();
|
|
|
|
|
|
|
|
if (Globals::Instance->genSourceFile)
|
|
|
|
GenerateSourceFiles(outputDir);
|
|
|
|
|
|
|
|
for (ZResource* res : resources)
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
|
2021-01-09 00:38:28 +00:00
|
|
|
printf("Saving resource %s\n", res->GetName().c_str());
|
2021-03-20 16:02:12 +00:00
|
|
|
|
2021-01-02 04:24:29 +00:00
|
|
|
res->Save(outputPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Globals::Instance->testMode)
|
|
|
|
GenerateHLIntermediette();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ZFile::AddResource(ZResource* res)
|
|
|
|
{
|
|
|
|
resources.push_back(res);
|
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
ZResource* ZFile::FindResource(uint32_t rawDataIndex)
|
|
|
|
{
|
|
|
|
for (ZResource* res : resources)
|
|
|
|
{
|
|
|
|
if (res->GetRawDataIndex() == rawDataIndex)
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<ZResource*> ZFile::GetResourcesOfType(ZResourceType resType)
|
|
|
|
{
|
|
|
|
std::vector<ZResource*> resList;
|
|
|
|
|
|
|
|
for (ZResource* res : resources)
|
|
|
|
{
|
|
|
|
if (res->GetResourceType() == resType)
|
|
|
|
resList.push_back(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
return resList;
|
|
|
|
}
|
|
|
|
|
|
|
|
Declaration* ZFile::AddDeclaration(uint32_t address, DeclarationAlignment alignment, size_t size,
|
2021-03-20 16:02:12 +00:00
|
|
|
std::string varType, std::string varName, std::string body)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
assert(GETSEGNUM(address) == 0);
|
2021-01-02 04:24:29 +00:00
|
|
|
AddDeclarationDebugChecks(address);
|
|
|
|
|
|
|
|
Declaration* decl = new Declaration(alignment, size, varType, varName, false, body);
|
|
|
|
declarations[address] = decl;
|
|
|
|
return decl;
|
|
|
|
}
|
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
Declaration* ZFile::AddDeclaration(uint32_t address, DeclarationAlignment alignment,
|
2021-05-30 15:09:59 +00:00
|
|
|
DeclarationPadding padding, size_t size, std::string varType,
|
|
|
|
std::string varName, std::string body)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
assert(GETSEGNUM(address) == 0);
|
2021-01-02 04:24:29 +00:00
|
|
|
AddDeclarationDebugChecks(address);
|
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
declarations[address] =
|
|
|
|
new Declaration(alignment, padding, size, varType, varName, false, body);
|
2021-01-18 21:04:04 +00:00
|
|
|
return declarations[address];
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
Declaration* ZFile::AddDeclarationArray(uint32_t address, DeclarationAlignment alignment,
|
2021-04-30 21:23:22 +00:00
|
|
|
size_t size, std::string varType, std::string varName,
|
|
|
|
size_t arrayItemCnt, std::string body)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
assert(GETSEGNUM(address) == 0);
|
2021-01-02 04:24:29 +00:00
|
|
|
AddDeclarationDebugChecks(address);
|
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
declarations[address] =
|
|
|
|
new Declaration(alignment, size, varType, varName, true, arrayItemCnt, body);
|
2021-01-18 21:04:04 +00:00
|
|
|
return declarations[address];
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
Declaration* ZFile::AddDeclarationArray(uint32_t address, DeclarationAlignment alignment,
|
2021-04-30 21:23:22 +00:00
|
|
|
size_t size, std::string varType, std::string varName,
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string arrayItemCntStr, std::string body)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
assert(GETSEGNUM(address) == 0);
|
|
|
|
AddDeclarationDebugChecks(address);
|
|
|
|
|
|
|
|
declarations[address] =
|
|
|
|
new Declaration(alignment, size, varType, varName, true, arrayItemCntStr, body);
|
|
|
|
return declarations[address];
|
|
|
|
}
|
2021-04-30 21:23:22 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
Declaration* ZFile::AddDeclarationArray(uint32_t address, DeclarationAlignment alignment,
|
|
|
|
size_t size, std::string varType, std::string varName,
|
|
|
|
size_t arrayItemCnt, std::string body, bool isExternal)
|
|
|
|
{
|
|
|
|
assert(GETSEGNUM(address) == 0);
|
2021-04-30 21:23:22 +00:00
|
|
|
AddDeclarationDebugChecks(address);
|
|
|
|
|
|
|
|
declarations[address] =
|
|
|
|
new Declaration(alignment, size, varType, varName, true, arrayItemCnt, body, isExternal);
|
|
|
|
return declarations[address];
|
|
|
|
}
|
|
|
|
|
|
|
|
Declaration* ZFile::AddDeclarationArray(uint32_t address, DeclarationAlignment alignment,
|
2021-05-30 15:09:59 +00:00
|
|
|
DeclarationPadding padding, size_t size,
|
|
|
|
std::string varType, std::string varName,
|
|
|
|
size_t arrayItemCnt, std::string body)
|
2021-04-30 21:23:22 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
assert(GETSEGNUM(address) == 0);
|
2021-01-02 04:24:29 +00:00
|
|
|
AddDeclarationDebugChecks(address);
|
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
declarations[address] =
|
|
|
|
new Declaration(alignment, padding, size, varType, varName, true, arrayItemCnt, body);
|
2021-01-18 21:04:04 +00:00
|
|
|
return declarations[address];
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-01-18 21:04:04 +00:00
|
|
|
Declaration* ZFile::AddDeclarationPlaceholder(uint32_t address)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
assert(GETSEGNUM(address) == 0);
|
2021-01-02 04:24:29 +00:00
|
|
|
AddDeclarationDebugChecks(address);
|
2021-05-30 15:09:59 +00:00
|
|
|
Declaration* decl;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
if (declarations.find(address) == declarations.end())
|
2021-05-30 15:09:59 +00:00
|
|
|
{
|
|
|
|
decl = new Declaration(DeclarationAlignment::None, 0, "", "", false, "");
|
|
|
|
decl->isPlaceholder = true;
|
|
|
|
declarations[address] = decl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
decl = declarations[address];
|
2021-01-18 21:04:04 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
return decl;
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
Declaration* ZFile::AddDeclarationPlaceholder(uint32_t address, std::string varName)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
assert(GETSEGNUM(address) == 0);
|
2021-01-02 04:24:29 +00:00
|
|
|
AddDeclarationDebugChecks(address);
|
2021-05-30 15:09:59 +00:00
|
|
|
Declaration* decl;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
if (declarations.find(address) == declarations.end())
|
2021-05-30 15:09:59 +00:00
|
|
|
{
|
|
|
|
decl = new Declaration(DeclarationAlignment::None, 0, "", varName, false, "");
|
|
|
|
decl->isPlaceholder = true;
|
|
|
|
declarations[address] = decl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
decl = declarations[address];
|
2021-01-18 21:04:04 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
return decl;
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
Declaration* ZFile::AddDeclarationInclude(uint32_t address, std::string includePath, size_t size,
|
|
|
|
std::string varType, std::string varName)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
assert(GETSEGNUM(address) == 0);
|
2021-01-02 04:24:29 +00:00
|
|
|
AddDeclarationDebugChecks(address);
|
|
|
|
|
|
|
|
if (declarations.find(address) == declarations.end())
|
|
|
|
declarations[address] = new Declaration(includePath, size, varType, varName);
|
2021-01-18 21:04:04 +00:00
|
|
|
|
|
|
|
return declarations[address];
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
Declaration* ZFile::AddDeclarationIncludeArray(uint32_t address, std::string includePath,
|
2021-04-30 21:23:22 +00:00
|
|
|
size_t size, std::string varType,
|
|
|
|
std::string varName, size_t arrayItemCnt)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
assert(GETSEGNUM(address) == 0);
|
2021-01-02 04:24:29 +00:00
|
|
|
AddDeclarationDebugChecks(address);
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (StringHelper::StartsWith(includePath, "assets/extracted/"))
|
|
|
|
includePath = "assets/" + StringHelper::Split(includePath, "assets/extracted/")[1];
|
|
|
|
if (StringHelper::StartsWith(includePath, "assets/custom/"))
|
|
|
|
includePath = "assets/" + StringHelper::Split(includePath, "assets/custom/")[1];
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
auto declCheck = declarations.find(address);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (declCheck != declarations.end())
|
|
|
|
{
|
|
|
|
declCheck->second->includePath = includePath;
|
|
|
|
declCheck->second->varType = varType;
|
|
|
|
declCheck->second->varName = varName;
|
|
|
|
declCheck->second->size = size;
|
|
|
|
declCheck->second->isArray = true;
|
|
|
|
declCheck->second->arrayItemCnt = arrayItemCnt;
|
|
|
|
|
|
|
|
return declCheck->second;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Declaration* decl = new Declaration(includePath, size, varType, varName);
|
|
|
|
|
|
|
|
decl->isArray = true;
|
|
|
|
decl->arrayItemCnt = arrayItemCnt;
|
|
|
|
|
|
|
|
declarations[address] = decl;
|
|
|
|
return declarations[address];
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ZFile::AddDeclarationDebugChecks(uint32_t address)
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
assert(GETSEGNUM(address) == 0);
|
2021-01-02 04:24:29 +00:00
|
|
|
#ifdef _DEBUG
|
2021-04-30 21:23:22 +00:00
|
|
|
if (address == 0x0000)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
int32_t bp = 0;
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string ZFile::GetDeclarationName(uint32_t address) const
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
return GetDeclarationName(address,
|
|
|
|
"ERROR_COULD_NOT_FIND_DECLARATION"); // Note: For now that default
|
|
|
|
// message is just for testing
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string ZFile::GetDeclarationName(uint32_t address, std::string defaultResult) const
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
Declaration* decl = GetDeclaration(address);
|
|
|
|
if (decl != nullptr)
|
|
|
|
return decl->varName;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
return defaultResult;
|
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string ZFile::GetDeclarationPtrName(segptr_t segAddress) const
|
|
|
|
{
|
|
|
|
if (segAddress == 0)
|
|
|
|
return "NULL";
|
|
|
|
|
|
|
|
Declaration* decl = GetDeclaration(Seg2Filespace(segAddress, baseAddress));
|
|
|
|
|
|
|
|
if (!Globals::Instance->HasSegment(GETSEGNUM(segAddress)) || decl == nullptr)
|
|
|
|
return StringHelper::Sprintf("0x%08X", segAddress);
|
|
|
|
|
|
|
|
if (!decl->isArray)
|
|
|
|
return "&" + decl->varName;
|
|
|
|
|
|
|
|
return decl->varName;
|
|
|
|
}
|
|
|
|
|
|
|
|
Declaration* ZFile::GetDeclaration(uint32_t address) const
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
|
|
|
if (declarations.find(address) != declarations.end())
|
2021-05-30 15:09:59 +00:00
|
|
|
return declarations.at(address);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
Declaration* ZFile::GetDeclarationRanged(uint32_t address) const
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
|
|
|
for (const auto decl : declarations)
|
|
|
|
{
|
2021-01-18 21:04:04 +00:00
|
|
|
if (address >= decl.first && address < decl.first + decl.second->size)
|
2021-01-02 04:24:29 +00:00
|
|
|
return decl.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
uint32_t ZFile::GetDeclarationRangedAddress(uint32_t address) const
|
2021-01-18 21:04:04 +00:00
|
|
|
{
|
|
|
|
for (const auto decl : declarations)
|
|
|
|
{
|
|
|
|
if (address >= decl.first && address < decl.first + decl.second->size)
|
|
|
|
return decl.first;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0xFFFFFFFF;
|
|
|
|
}
|
|
|
|
|
2021-01-02 04:24:29 +00:00
|
|
|
bool ZFile::HasDeclaration(uint32_t address)
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
return declarations.find(address) != declarations.end();
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
void ZFile::GenerateSourceFiles(fs::path outputDir)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
std::string sourceOutput = "";
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
sourceOutput += "#include \"ultra64.h\"\n";
|
|
|
|
sourceOutput += "#include \"z64.h\"\n";
|
|
|
|
sourceOutput += "#include \"macros.h\"\n";
|
|
|
|
sourceOutput += GetHeaderInclude();
|
|
|
|
|
|
|
|
GeneratePlaceholderDeclarations();
|
|
|
|
|
|
|
|
// Generate Code
|
2021-05-30 15:09:59 +00:00
|
|
|
for (size_t i = 0; i < resources.size(); i++)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
ZResource* res = resources.at(i);
|
|
|
|
std::string resSrc = res->GetSourceOutputCode(name);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
if (res->IsExternalResource())
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string path = Path::GetFileNameWithoutExtension(res->GetName()).c_str();
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string assetOutDir =
|
|
|
|
(outputDir / Path::GetFileNameWithoutExtension(res->GetOutName())).string();
|
|
|
|
std::string declType = res->GetSourceTypeName();
|
2021-04-30 21:23:22 +00:00
|
|
|
|
|
|
|
std::string incStr = StringHelper::Sprintf("%s.%s.inc", assetOutDir.c_str(),
|
|
|
|
res->GetExternalExtension().c_str());
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (res->GetResourceType() == ZResourceType::Texture)
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
ZTexture* tex = static_cast<ZTexture*>(res);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
if (!Globals::Instance->cfg.texturePool.empty())
|
2021-04-30 21:23:22 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
tex->CalcHash();
|
|
|
|
|
|
|
|
// 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";
|
|
|
|
}
|
2021-04-30 21:23:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
incStr += ".c";
|
|
|
|
}
|
|
|
|
else if (res->GetResourceType() == ZResourceType::Blob ||
|
|
|
|
res->GetResourceType() == ZResourceType::Background)
|
|
|
|
{
|
|
|
|
incStr += ".c";
|
|
|
|
}
|
2021-03-20 16:02:12 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
AddDeclarationIncludeArray(res->GetRawDataIndex(), incStr, res->GetRawDataSize(),
|
|
|
|
declType, res->GetName(), 0);
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sourceOutput += resSrc;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resSrc != "" && !res->IsExternalResource())
|
|
|
|
sourceOutput += "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
sourceOutput += ProcessDeclarations();
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string outPath =
|
|
|
|
(Globals::Instance->sourceOutputPath / (Path::GetFileNameWithoutExtension(name) + ".c"))
|
|
|
|
.string();
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
OutputFormatter formatter;
|
|
|
|
formatter.Write(sourceOutput);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
File::WriteAllText(outPath, formatter.GetOutput());
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
GenerateSourceHeaderFiles();
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
void ZFile::GenerateSourceHeaderFiles()
|
|
|
|
{
|
|
|
|
OutputFormatter formatter;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
for (ZResource* res : resources)
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string resSrc = res->GetSourceOutputHeader("");
|
2021-04-30 21:23:22 +00:00
|
|
|
formatter.Write(resSrc);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
if (resSrc != "")
|
2021-04-30 21:23:22 +00:00
|
|
|
formatter.Write("\n");
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
formatter.Write(ProcessExterns());
|
|
|
|
|
|
|
|
fs::path headerFilename =
|
|
|
|
Globals::Instance->sourceOutputPath / (Path::GetFileNameWithoutExtension(name) + ".h");
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
File::WriteAllText(headerFilename.string(), formatter.GetOutput());
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ZFile::GenerateHLIntermediette()
|
|
|
|
{
|
|
|
|
// This is kinda hacky but it gets the job done for now...
|
|
|
|
HLModelIntermediette* mdl = new HLModelIntermediette();
|
|
|
|
|
|
|
|
for (ZResource* res : resources)
|
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
if (res->GetResourceType() == ZResourceType::DisplayList ||
|
|
|
|
res->GetResourceType() == ZResourceType::Skeleton)
|
2021-01-02 04:24:29 +00:00
|
|
|
res->GenerateHLIntermediette(*mdl);
|
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
// std::string test = mdl->ToOBJFile();
|
|
|
|
// std::string test2 = mdl->ToAssimpFile();
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string ZFile::GetHeaderInclude()
|
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
return StringHelper::Sprintf("#include \"%s\"\n\n",
|
|
|
|
(Path::GetFileNameWithoutExtension(name) + ".h").c_str());
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ZFile::GeneratePlaceholderDeclarations()
|
|
|
|
{
|
|
|
|
// Generate placeholder declarations
|
|
|
|
for (ZResource* res : resources)
|
|
|
|
{
|
|
|
|
if (GetDeclaration(res->GetRawDataIndex()) == nullptr)
|
|
|
|
AddDeclarationPlaceholder(res->GetRawDataIndex(), res->GetName());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
void ZFile::AddTextureResource(uint32_t offset, ZTexture* tex)
|
|
|
|
{
|
|
|
|
for (auto res : resources)
|
|
|
|
assert(res->GetRawDataIndex() != offset);
|
|
|
|
|
|
|
|
resources.push_back(tex);
|
|
|
|
texturesResources[offset] = tex;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZTexture* ZFile::GetTextureResource(uint32_t offset) const
|
|
|
|
{
|
|
|
|
auto tex = texturesResources.find(offset);
|
|
|
|
if (tex != texturesResources.end())
|
|
|
|
return tex->second;
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
std::map<std::string, ZResourceFactoryFunc*>* ZFile::GetNodeMap()
|
|
|
|
{
|
|
|
|
static std::map<std::string, ZResourceFactoryFunc*> nodeMap;
|
|
|
|
return &nodeMap;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ZFile::RegisterNode(std::string nodeName, ZResourceFactoryFunc* nodeFunc)
|
|
|
|
{
|
|
|
|
std::map<std::string, ZResourceFactoryFunc*>* nodeMap = GetNodeMap();
|
|
|
|
(*nodeMap)[nodeName] = nodeFunc;
|
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string ZFile::ProcessDeclarations()
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string output = "";
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
if (declarations.size() == 0)
|
|
|
|
return output;
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
defines += ProcessTextureIntersections(name);
|
|
|
|
|
2021-01-02 04:24:29 +00:00
|
|
|
// Account for padding/alignment
|
2021-03-20 16:02:12 +00:00
|
|
|
uint32_t lastAddr = 0;
|
|
|
|
uint32_t lastSize = 0;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
// printf("RANGE START: 0x%06X - RANGE END: 0x%06X\n", rangeStart, rangeEnd);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-01-18 21:04:04 +00:00
|
|
|
// Optimization: See if there are any arrays side by side that can be merged...
|
2021-05-30 15:09:59 +00:00
|
|
|
std::vector<std::pair<int32_t, Declaration*>> declarationKeys(declarations.begin(),
|
|
|
|
declarations.end());
|
2021-01-18 21:04:04 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::pair<int32_t, Declaration*> lastItem = declarationKeys.at(0);
|
2021-04-30 21:23:22 +00:00
|
|
|
|
|
|
|
for (size_t i = 1; i < declarationKeys.size(); i++)
|
2021-01-18 21:04:04 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
std::pair<int32_t, Declaration*> curItem = declarationKeys[i];
|
2021-04-30 21:23:22 +00:00
|
|
|
|
|
|
|
if (curItem.second->isArray && lastItem.second->isArray)
|
|
|
|
{
|
|
|
|
if (curItem.second->varType == lastItem.second->varType)
|
|
|
|
{
|
|
|
|
// TEST: For now just do Vtx declarations...
|
|
|
|
if (lastItem.second->varType == "static Vtx")
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lastItem = curItem;
|
2021-01-18 21:04:04 +00:00
|
|
|
}
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
for (std::pair<uint32_t, Declaration*> item : declarations)
|
2021-04-30 21:23:22 +00:00
|
|
|
ProcessDeclarationText(item.second);
|
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
for (std::pair<uint32_t, Declaration*> item : declarations)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
while (item.second->size % 4 != 0)
|
|
|
|
item.second->size++;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
if (lastAddr != 0)
|
|
|
|
{
|
|
|
|
if (item.second->alignment == DeclarationAlignment::Align16)
|
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
// int32_t lastAddrSizeTest = declarations[lastAddr]->size;
|
|
|
|
int32_t curPtr = lastAddr + declarations[lastAddr]->size;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
while (curPtr % 4 != 0)
|
|
|
|
{
|
|
|
|
declarations[lastAddr]->size++;
|
2021-03-20 16:02:12 +00:00
|
|
|
// item.second->size++;
|
2021-01-02 04:24:29 +00:00
|
|
|
curPtr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*while (curPtr % 16 != 0)
|
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
char buffer[2048];
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
sprintf(buffer, "static u32 align%02X = 0;\n", curPtr);
|
|
|
|
item.second->text = buffer + item.second->text;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
declarations[lastAddr]->size += 4;
|
|
|
|
curPtr += 4;
|
2021-01-02 04:24:29 +00:00
|
|
|
}*/
|
|
|
|
}
|
|
|
|
else if (item.second->alignment == DeclarationAlignment::Align8)
|
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
int32_t curPtr = lastAddr + declarations[lastAddr]->size;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
while (curPtr % 4 != 0)
|
|
|
|
{
|
|
|
|
declarations[lastAddr]->size++;
|
2021-03-20 16:02:12 +00:00
|
|
|
// item.second->size++;
|
2021-01-02 04:24:29 +00:00
|
|
|
curPtr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (curPtr % 8 != 0)
|
|
|
|
{
|
|
|
|
char buffer[2048];
|
|
|
|
|
|
|
|
sprintf(buffer, "static u32 align%02X = 0;\n", curPtr);
|
2021-03-20 16:02:12 +00:00
|
|
|
item.second->preText = buffer + item.second->preText;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
declarations[lastAddr]->size += 4;
|
2021-03-20 16:02:12 +00:00
|
|
|
// item.second->size += 4;
|
2021-01-02 04:24:29 +00:00
|
|
|
curPtr += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (item.second->padding == DeclarationPadding::Pad16)
|
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
int32_t curPtr = item.first + item.second->size;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
while (curPtr % 4 != 0)
|
|
|
|
{
|
|
|
|
item.second->size++;
|
|
|
|
curPtr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (curPtr % 16 != 0)
|
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
item.second->postText += StringHelper::Sprintf("static u32 pad%02X = 0;\n", curPtr);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
|
|
|
item.second->size += 4;
|
|
|
|
curPtr += 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
lastAddr = item.first;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle unaccounted data
|
|
|
|
lastAddr = 0;
|
2021-01-09 00:38:28 +00:00
|
|
|
lastSize = 0;
|
2021-04-30 21:23:22 +00:00
|
|
|
std::vector<uint32_t> declsAddresses;
|
|
|
|
for (const auto& item : declarations)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
declsAddresses.push_back(item.first);
|
|
|
|
}
|
|
|
|
declsAddresses.push_back(rawData.size());
|
|
|
|
|
|
|
|
for (uint32_t currentAddress : declsAddresses)
|
|
|
|
{
|
|
|
|
if (currentAddress >= rangeEnd)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
break;
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (currentAddress < rangeStart)
|
|
|
|
{
|
|
|
|
lastAddr = currentAddress;
|
|
|
|
continue;
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (currentAddress != lastAddr && declarations.find(lastAddr) != declarations.end())
|
|
|
|
{
|
|
|
|
Declaration* lastDecl = declarations.at(lastAddr);
|
|
|
|
lastSize = lastDecl->size;
|
|
|
|
|
|
|
|
if (lastAddr + lastSize > currentAddress)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
Declaration* currentDecl = declarations.at(currentAddress);
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
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());
|
|
|
|
}
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
uint32_t unaccountedAddress = lastAddr + lastSize;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (unaccountedAddress != currentAddress && lastAddr >= rangeStart &&
|
|
|
|
unaccountedAddress < rangeEnd)
|
|
|
|
{
|
|
|
|
int diff = currentAddress - unaccountedAddress;
|
|
|
|
bool nonZeroUnaccounted = false;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string src = " ";
|
2021-04-30 21:23:22 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < diff; i++)
|
|
|
|
{
|
|
|
|
uint8_t val = rawData.at(unaccountedAddress + i);
|
|
|
|
src += StringHelper::Sprintf("0x%02X, ", val);
|
|
|
|
if (val != 0x00)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
nonZeroUnaccounted = true;
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if ((i % 16 == 15) && (i != (diff - 1)))
|
|
|
|
src += "\n ";
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (declarations.find(unaccountedAddress) == declarations.end())
|
|
|
|
{
|
|
|
|
if (diff > 0)
|
|
|
|
{
|
|
|
|
std::string unaccountedPrefix = "unaccounted";
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (diff < 16 && !nonZeroUnaccounted)
|
|
|
|
unaccountedPrefix = "possiblePadding";
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
Declaration* decl = AddDeclarationArray(
|
|
|
|
unaccountedAddress, DeclarationAlignment::None, diff, "static u8",
|
|
|
|
StringHelper::Sprintf("%s_%06X", unaccountedPrefix.c_str(),
|
|
|
|
unaccountedAddress),
|
|
|
|
diff, src);
|
|
|
|
decl->isUnaccounted = true;
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
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%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 address '0x%06X'.\n"
|
|
|
|
"\t Block size: '0x%X'.\n",
|
|
|
|
xmlFilePath.c_str(), name.c_str(), unaccountedAddress, diff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
}
|
2021-04-30 21:23:22 +00:00
|
|
|
|
|
|
|
lastAddr = currentAddress;
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Go through include declarations
|
2021-01-09 00:38:28 +00:00
|
|
|
// First, handle the prototypes (static only for now)
|
2021-04-30 21:23:22 +00:00
|
|
|
int32_t protoCnt = 0;
|
2021-05-30 15:09:59 +00:00
|
|
|
for (std::pair<uint32_t, Declaration*> item : declarations)
|
2021-01-09 00:38:28 +00:00
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
if (StringHelper::StartsWith(item.second->varType, "static ") &&
|
|
|
|
!item.second->isUnaccounted)
|
2021-01-09 00:38:28 +00:00
|
|
|
{
|
|
|
|
if (item.second->isArray)
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
if (item.second->arrayItemCntStr != "")
|
|
|
|
{
|
|
|
|
output += StringHelper::Sprintf("%s %s[%s];\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str(),
|
|
|
|
item.second->arrayItemCntStr.c_str());
|
|
|
|
}
|
|
|
|
else if (item.second->arrayItemCnt == 0)
|
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
output += StringHelper::Sprintf("%s %s[];\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str());
|
2021-05-30 15:09:59 +00:00
|
|
|
}
|
2021-01-09 00:38:28 +00:00
|
|
|
else
|
2021-05-30 15:09:59 +00:00
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
output += StringHelper::Sprintf("%s %s[%i];\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str(),
|
|
|
|
item.second->arrayItemCnt);
|
2021-05-30 15:09:59 +00:00
|
|
|
}
|
2021-01-09 00:38:28 +00:00
|
|
|
}
|
|
|
|
else
|
2021-03-20 16:02:12 +00:00
|
|
|
output += StringHelper::Sprintf("%s %s;\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str());
|
2021-01-09 00:38:28 +00:00
|
|
|
|
|
|
|
protoCnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (protoCnt > 0)
|
|
|
|
output += "\n";
|
|
|
|
|
|
|
|
// Next, output the actual declarations
|
2021-05-30 15:09:59 +00:00
|
|
|
for (std::pair<uint32_t, Declaration*> item : declarations)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
if (item.first < rangeStart || item.first >= rangeEnd)
|
|
|
|
{
|
2021-03-14 15:40:25 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-01-02 04:24:29 +00:00
|
|
|
if (item.second->includePath != "")
|
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
if (item.second->isExternal)
|
|
|
|
{
|
|
|
|
// HACK
|
|
|
|
std::string extType = "";
|
|
|
|
|
|
|
|
if (item.second->varType == "Gfx")
|
|
|
|
extType = "dlist";
|
|
|
|
else if (item.second->varType == "Vtx" || item.second->varType == "static Vtx")
|
|
|
|
extType = "vtx";
|
|
|
|
|
|
|
|
auto filepath = Globals::Instance->outputPath / item.second->varName;
|
|
|
|
File::WriteAllText(
|
|
|
|
StringHelper::Sprintf("%s.%s.inc", filepath.c_str(), extType.c_str()),
|
|
|
|
item.second->text);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do not asm_process vertex arrays. They have no practical use being overridden.
|
|
|
|
// if (item.second->varType == "Vtx" || item.second->varType == "static Vtx")
|
|
|
|
if (item.second->varType != "u64" && item.second->varType != "static u64" &&
|
|
|
|
item.second->varType != "u8" && item.second->varType != "static u8")
|
|
|
|
{
|
|
|
|
output += StringHelper::Sprintf(
|
|
|
|
"%s %s[] = {\n #include \"%s\"\n};\n\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str(),
|
|
|
|
StringHelper::Replace(item.second->includePath, "assets/", "../assets/")
|
|
|
|
.c_str());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
if (item.second->arrayItemCntStr != "")
|
|
|
|
output += StringHelper::Sprintf(
|
|
|
|
"%s %s[%s] = {\n #include \"%s\"\n};\n\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str(), item.second->arrayItemCntStr.c_str(),
|
|
|
|
item.second->includePath.c_str());
|
|
|
|
else
|
|
|
|
output += StringHelper::Sprintf(
|
|
|
|
"%s %s[] = {\n #include \"%s\"\n};\n\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str(), item.second->includePath.c_str());
|
2021-04-30 21:23:22 +00:00
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
else if (item.second->varType != "")
|
|
|
|
{
|
|
|
|
if (item.second->preText != "")
|
|
|
|
output += item.second->preText + "\n";
|
|
|
|
|
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
if (item.second->isArray)
|
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
if (item.second->arrayItemCntStr != "")
|
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
output += StringHelper::Sprintf(
|
2021-05-30 15:09:59 +00:00
|
|
|
"%s %s[%s];\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str(), item.second->arrayItemCntStr.c_str());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (item.second->arrayItemCnt == 0)
|
|
|
|
output +=
|
|
|
|
StringHelper::Sprintf("%s %s[] = {\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str());
|
|
|
|
else
|
|
|
|
output += StringHelper::Sprintf(
|
|
|
|
"%s %s[%i] = {\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str(), item.second->arrayItemCnt);
|
|
|
|
}
|
2021-04-30 21:23:22 +00:00
|
|
|
|
|
|
|
output += item.second->text + "\n";
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
else
|
2021-04-30 21:23:22 +00:00
|
|
|
{
|
|
|
|
output += StringHelper::Sprintf("%s %s = { ", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str());
|
|
|
|
output += item.second->text;
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-04-30 21:23:22 +00:00
|
|
|
if (output.back() == '\n')
|
|
|
|
output += "};";
|
|
|
|
else
|
|
|
|
output += " };";
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
output += " " + item.second->rightText + "\n\n";
|
2021-03-20 16:02:12 +00:00
|
|
|
|
2021-01-02 04:24:29 +00:00
|
|
|
if (item.second->postText != "")
|
|
|
|
output += item.second->postText + "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
output += "\n";
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
|
2021-01-18 21:04:04 +00:00
|
|
|
void ZFile::ProcessDeclarationText(Declaration* decl)
|
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
size_t refIndex = 0;
|
2021-01-18 21:04:04 +00:00
|
|
|
|
|
|
|
if (decl->references.size() > 0)
|
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
for (size_t i = 0; i < decl->text.size() - 1; i++)
|
2021-01-18 21:04:04 +00:00
|
|
|
{
|
|
|
|
char c = decl->text[i];
|
|
|
|
char c2 = decl->text[i + 1];
|
|
|
|
|
|
|
|
if (c == '@' && c2 == 'r')
|
|
|
|
{
|
2021-01-25 00:36:40 +00:00
|
|
|
if (refIndex >= decl->references.size())
|
|
|
|
break;
|
|
|
|
|
2021-01-18 21:04:04 +00:00
|
|
|
Declaration* refDecl = GetDeclarationRanged(decl->references[refIndex]);
|
|
|
|
uint32_t refDeclAddr = GetDeclarationRangedAddress(decl->references[refIndex]);
|
|
|
|
|
|
|
|
if (refDecl != nullptr)
|
|
|
|
{
|
|
|
|
if (refDecl->isArray)
|
|
|
|
{
|
2021-01-25 00:36:40 +00:00
|
|
|
if (refDecl->arrayItemCnt != 0)
|
|
|
|
{
|
2021-04-30 21:23:22 +00:00
|
|
|
int32_t itemSize = refDecl->size / refDecl->arrayItemCnt;
|
|
|
|
int32_t itemIndex =
|
|
|
|
(decl->references[refIndex] - refDeclAddr) / itemSize;
|
2021-01-25 00:36:40 +00:00
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
decl->text.replace(i, 2,
|
|
|
|
StringHelper::Sprintf(
|
|
|
|
"&%s[%i]", refDecl->varName.c_str(), itemIndex));
|
2021-01-25 00:36:40 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
decl->text.replace(i, 2,
|
|
|
|
StringHelper::Sprintf("ERROR ARRAYITEMCNT = 0"));
|
2021-01-25 00:36:40 +00:00
|
|
|
}
|
2021-01-18 21:04:04 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
decl->text.replace(i, 2, refDecl->varName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
decl->text.replace(i, 2, "ERROR");
|
|
|
|
|
|
|
|
refIndex++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string ZFile::ProcessExterns()
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-05-30 15:09:59 +00:00
|
|
|
std::string output = "";
|
2021-01-02 04:24:29 +00:00
|
|
|
|
2021-05-30 15:09:59 +00:00
|
|
|
for (std::pair<uint32_t, Declaration*> item : declarations)
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
2021-03-20 16:02:12 +00:00
|
|
|
if (item.first < rangeStart || item.first >= rangeEnd)
|
|
|
|
{
|
2021-03-14 15:40:25 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-03-20 16:02:12 +00:00
|
|
|
if (!StringHelper::StartsWith(item.second->varType, "static ") &&
|
|
|
|
item.second->varType != "") // && item.second->includePath == "")
|
2021-01-02 04:24:29 +00:00
|
|
|
{
|
|
|
|
if (item.second->isArray)
|
|
|
|
{
|
|
|
|
if (item.second->arrayItemCnt == 0)
|
2021-03-20 16:02:12 +00:00
|
|
|
output +=
|
|
|
|
StringHelper::Sprintf("extern %s %s[];\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str());
|
2021-01-02 04:24:29 +00:00
|
|
|
else
|
2021-03-20 16:02:12 +00:00
|
|
|
output += StringHelper::Sprintf(
|
|
|
|
"extern %s %s[%i];\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str(), item.second->arrayItemCnt);
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
else
|
2021-03-20 16:02:12 +00:00
|
|
|
output += StringHelper::Sprintf("extern %s %s;\n", item.second->varType.c_str(),
|
|
|
|
item.second->varName.c_str());
|
2021-01-02 04:24:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
output += "\n";
|
|
|
|
|
|
|
|
output += defines;
|
|
|
|
|
|
|
|
return output;
|
2021-05-30 15:09:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string ZFile::ProcessTextureIntersections(std::string prefix)
|
|
|
|
{
|
|
|
|
if (texturesResources.empty())
|
|
|
|
return "";
|
|
|
|
|
|
|
|
std::string defines = "";
|
|
|
|
std::vector<std::pair<uint32_t, ZTexture*>> texturesSorted(texturesResources.begin(),
|
|
|
|
texturesResources.end());
|
|
|
|
|
|
|
|
for (size_t i = 0; i < texturesSorted.size() - 1; i++)
|
|
|
|
{
|
|
|
|
uint32_t currentOffset = texturesSorted[i].first;
|
|
|
|
uint32_t nextOffset = texturesSorted[i + 1].first;
|
|
|
|
auto& currentTex = texturesResources.at(currentOffset);
|
|
|
|
int texSize = currentTex->GetRawDataSize();
|
|
|
|
|
|
|
|
if (currentTex->WasDeclaredInXml())
|
|
|
|
{
|
|
|
|
// We believe the user is right.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((currentOffset + texSize) > nextOffset)
|
|
|
|
{
|
|
|
|
uint32_t offsetDiff = nextOffset - currentOffset;
|
|
|
|
if (currentTex->isPalette)
|
|
|
|
{
|
|
|
|
// Shrink palette so it doesn't overlap
|
|
|
|
currentTex->SetDimensions(offsetDiff / currentTex->GetPixelMultiplyer(), 1);
|
|
|
|
declarations.at(currentOffset)->size = currentTex->GetRawDataSize();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::string texName = GetDeclarationPtrName(currentOffset);
|
|
|
|
std::string texNextName;
|
|
|
|
|
|
|
|
Declaration* nextDecl = GetDeclaration(nextOffset);
|
|
|
|
if (nextDecl == nullptr)
|
|
|
|
texNextName = texturesResources.at(nextOffset)->GetName();
|
|
|
|
else
|
|
|
|
texNextName = nextDecl->varName;
|
|
|
|
|
|
|
|
defines += StringHelper::Sprintf("#define %s ((u32)%s + 0x%06X)\n",
|
|
|
|
texNextName.c_str(), texName.c_str(), offsetDiff);
|
|
|
|
|
|
|
|
declarations.erase(nextOffset);
|
|
|
|
texturesResources.erase(nextOffset);
|
|
|
|
texturesSorted.erase(texturesSorted.begin() + i + 1);
|
|
|
|
|
|
|
|
i--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return defines;
|
|
|
|
}
|