summaryrefslogtreecommitdiff
path: root/ZAPD/ZFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ZAPD/ZFile.cpp')
-rw-r--r--ZAPD/ZFile.cpp225
1 files changed, 163 insertions, 62 deletions
diff --git a/ZAPD/ZFile.cpp b/ZAPD/ZFile.cpp
index b2a3996..bfb76eb 100644
--- a/ZAPD/ZFile.cpp
+++ b/ZAPD/ZFile.cpp
@@ -63,6 +63,7 @@ ZFile::ZFile(ZFileMode mode, tinyxml2::XMLElement* reader, const fs::path& nBase
outputPath = nOutPath;
ParseXML(mode, reader, filename, placeholderMode);
+ DeclareResourceSubReferences();
}
ZFile::~ZFile()
@@ -85,8 +86,6 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b
else
name = filename;
- int32_t segment = -1;
-
// 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.
const char* gameStr = reader->Attribute("Game");
@@ -103,24 +102,28 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b
StringHelper::Sprintf("Error: Game type %s not supported.", gameStr));
}
- if (reader->Attribute("BaseAddress") != NULL)
- baseAddress = (uint32_t)strtoul(
- StringHelper::Split(reader->Attribute("BaseAddress"), "0x")[1].c_str(), NULL, 16);
+ if (reader->Attribute("BaseAddress") != nullptr)
+ baseAddress = StringHelper::StrToL(reader->Attribute("BaseAddress"), 16);
- if (reader->Attribute("RangeStart") != NULL)
- rangeStart = (uint32_t)strtoul(
- StringHelper::Split(reader->Attribute("RangeStart"), "0x")[1].c_str(), NULL, 16);
+ if (reader->Attribute("RangeStart") != nullptr)
+ rangeStart = StringHelper::StrToL(reader->Attribute("RangeStart"), 16);
- if (reader->Attribute("RangeEnd") != NULL)
- rangeEnd = (uint32_t)strtoul(
- StringHelper::Split(reader->Attribute("RangeEnd"), "0x")[1].c_str(), NULL, 16);
+ if (reader->Attribute("RangeEnd") != nullptr)
+ rangeEnd = StringHelper::StrToL(reader->Attribute("RangeEnd"), 16);
- if (reader->Attribute("Segment") != NULL)
- segment = strtol(reader->Attribute("Segment"), NULL, 10);
+ // 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()));
+ */
- if (segment != -1)
+ if (reader->Attribute("Segment") != nullptr)
{
- Globals::Instance->AddSegment(segment);
+ segment = StringHelper::StrToL(reader->Attribute("Segment"), 10);
+ Globals::Instance->AddSegment(segment, this);
}
string folderName = (basePath / Path::GetFileNameWithoutExtension(name)).string();
@@ -151,7 +154,8 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b
if (Globals::Instance->verbosity >= VERBOSITY_INFO)
printf("%s: 0x%06X\n", nameXml, rawDataIndex);
- if (offsetXml != NULL)
+ // Check for repeated attributes.
+ if (offsetXml != nullptr)
{
rawDataIndex = strtol(StringHelper::Split(offsetXml, "0x")[1].c_str(), NULL, 16);
@@ -163,7 +167,7 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b
}
offsetSet.insert(offsetXml);
}
- if (outNameXml != NULL)
+ if (outNameXml != nullptr)
{
if (outNameSet.find(outNameXml) != outNameSet.end())
{
@@ -173,7 +177,7 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b
}
outNameSet.insert(outNameXml);
}
- if (nameXml != NULL)
+ if (nameXml != nullptr)
{
if (nameSet.find(nameXml) != nameSet.end())
{
@@ -194,27 +198,12 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b
if (mode == ZFileMode::Extract)
nRes->ExtractFromXML(child, rawData, rawDataIndex);
- // TODO: See if we can make this part of the ZRoom code...
- if (nRes->GetResourceType() == ZResourceType::Room)
- {
- if (nodeName == "Scene")
- {
- Globals::Instance->lastScene = (ZRoom*)nRes;
-
- if (segment == -1)
- segment = SEGMENT_SCENE;
- }
- else
- {
- if (segment == -1)
- segment = SEGMENT_ROOM;
- }
-
- if (segment != -1)
- Globals::Instance->AddSegment(segment);
- }
+ auto resType = nRes->GetResourceType();
+ if (resType == ZResourceType::Texture)
+ AddTextureResource(rawDataIndex, static_cast<ZTexture*>(nRes));
+ else
+ resources.push_back(nRes);
- resources.push_back(nRes);
rawDataIndex += nRes->GetRawDataSize();
}
else if (string(child->Name()) == "File")
@@ -233,6 +222,14 @@ void ZFile::ParseXML(ZFileMode mode, XMLElement* reader, std::string filename, b
}
}
+void ZFile::DeclareResourceSubReferences()
+{
+ for (size_t i = 0; i < resources.size(); i++)
+ {
+ resources.at(i)->DeclareReferences(name);
+ }
+}
+
void ZFile::BuildSourceFile(fs::path outputDir)
{
string folderName = Path::GetFileNameWithoutExtension(outputPath.string());
@@ -259,6 +256,16 @@ std::string ZFile::GetName()
return name;
}
+const fs::path& ZFile::GetXmlFilePath() const
+{
+ return xmlFilePath;
+}
+
+const std::vector<uint8_t>& ZFile::GetRawData() const
+{
+ return rawData;
+}
+
void ZFile::ExtractResources(fs::path outputDir)
{
string folderName = Path::GetFileNameWithoutExtension(outputPath.string());
@@ -280,8 +287,7 @@ void ZFile::ExtractResources(fs::path outputDir)
if (Globals::Instance->verbosity >= VERBOSITY_INFO)
printf("Saving resource %s\n", res->GetName().c_str());
- res->CalcHash();
- res->Save(outputPath.string());
+ res->Save(outputPath);
}
if (Globals::Instance->testMode)
@@ -460,30 +466,46 @@ void ZFile::AddDeclarationDebugChecks(uint32_t address)
#endif
}
-std::string ZFile::GetDeclarationName(uint32_t address)
+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
}
-std::string ZFile::GetDeclarationName(uint32_t address, std::string defaultResult)
+std::string ZFile::GetDeclarationName(uint32_t address, std::string defaultResult) const
{
if (declarations.find(address) != declarations.end())
- return declarations[address]->varName;
+ return declarations.at(address)->varName;
return defaultResult;
}
-Declaration* ZFile::GetDeclaration(uint32_t address)
+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
{
if (declarations.find(address) != declarations.end())
- return declarations[address];
+ return declarations.at(address);
return nullptr;
}
-Declaration* ZFile::GetDeclarationRanged(uint32_t address)
+Declaration* ZFile::GetDeclarationRanged(uint32_t address) const
{
for (const auto decl : declarations)
{
@@ -494,7 +516,7 @@ Declaration* ZFile::GetDeclarationRanged(uint32_t address)
return nullptr;
}
-uint32_t ZFile::GetDeclarationRangedAddress(uint32_t address)
+uint32_t ZFile::GetDeclarationRangedAddress(uint32_t address) const
{
for (const auto decl : declarations)
{
@@ -522,8 +544,9 @@ void ZFile::GenerateSourceFiles(fs::path outputDir)
GeneratePlaceholderDeclarations();
// Generate Code
- for (ZResource* res : resources)
+ for (size_t i = 0; i < resources.size(); i++)
{
+ ZResource* res = resources.at(i);
string resSrc = res->GetSourceOutputCode(name);
if (res->IsExternalResource())
@@ -539,16 +562,19 @@ void ZFile::GenerateSourceFiles(fs::path outputDir)
if (res->GetResourceType() == ZResourceType::Texture)
{
- ZTexture* tex = (ZTexture*)res;
-
- tex->CalcHash();
+ ZTexture* tex = static_cast<ZTexture*>(res);
- // TEXTURE POOL CHECK
- if (Globals::Instance->cfg.texturePool.find(tex->hash) !=
- Globals::Instance->cfg.texturePool.end())
+ if (!Globals::Instance->cfg.texturePool.empty())
{
- incStr = Globals::Instance->cfg.texturePool[tex->hash].path.string() + "." +
- res->GetExternalExtension() + ".inc";
+ 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";
+ }
}
incStr += ".c";
@@ -639,6 +665,24 @@ void ZFile::GeneratePlaceholderDeclarations()
}
}
+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;
+}
+
std::map<std::string, ZResourceFactoryFunc*>* ZFile::GetNodeMap()
{
static std::map<std::string, ZResourceFactoryFunc*> nodeMap;
@@ -658,6 +702,8 @@ string ZFile::ProcessDeclarations()
if (declarations.size() == 0)
return output;
+ defines += ProcessTextureIntersections(name);
+
// Account for padding/alignment
uint32_t lastAddr = 0;
uint32_t lastSize = 0;
@@ -665,12 +711,10 @@ string ZFile::ProcessDeclarations()
// printf("RANGE START: 0x%06X - RANGE END: 0x%06X\n", rangeStart, rangeEnd);
// Optimization: See if there are any arrays side by side that can be merged...
- auto declarationKeys =
- vector<pair<int32_t, Declaration*>>(declarations.begin(), declarations.end());
- sort(declarationKeys.begin(), declarationKeys.end(),
- [](const auto& lhs, const auto& rhs) { return lhs.first < rhs.first; });
+ std::vector<pair<int32_t, Declaration*>> declarationKeys(declarations.begin(),
+ declarations.end());
- pair<int32_t, Declaration*> lastItem = declarationKeys[0];
+ pair<int32_t, Declaration*> lastItem = declarationKeys.at(0);
for (size_t i = 1; i < declarationKeys.size(); i++)
{
@@ -1153,4 +1197,61 @@ string ZFile::ProcessExterns()
output += defines;
return output;
-} \ No newline at end of file
+}
+
+std::string ZFile::ProcessTextureIntersections(std::string prefix)
+{
+ if (texturesResources.empty())
+ return "";
+
+ std::string defines = "";
+ vector<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;
+}