Skip to content

Commit

Permalink
ZAPD features to support OOT multiversion assets (#322)
Browse files Browse the repository at this point in the history
* Add ZAPD hack to deal with extracted/VERSION/ in include paths

* Add ZAPD flags to override virtual address / start offset / end offset

* make zapd addresses globals int64_t so they can store uint32_t addresses and -1

* Use CamelCase

---------

Co-authored-by: Dragorn421 <Dragorn421@users.noreply.github.com>
  • Loading branch information
cadmic and Dragorn421 authored Jun 22, 2024
1 parent b9f0bdd commit 0285e11
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 0 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ ZAPD also accepts the following list of extra parameters:
- `both`: `CS_FLOAT(0x42280000, 42.0f)`
- `hex-commented-left`: `/* 42.0f */ 0x42280000`
- `hex-commented-right`: `0x42280000 /* 42.0f */`
- `--base-address ADDRESS`: Override base virtual address for input files.
- `--start-offset OFFSET`: Override start offset for input files.
- `--end-offset OFFSET`: Override end offset for input files.
- `-W...`: warning flags, see below

Additionally, you can pass the flag `--version` to see the current ZAPD version. If that flag is passed, ZAPD will ignore any other parameter passed.
Expand Down
3 changes: 3 additions & 0 deletions ZAPD/Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class Globals
fs::path baseRomPath, inputPath, outputPath, sourceOutputPath, cfgPath;
TextureType texType;
CsFloatType floatType = CsFloatType::FloatOnly;
int64_t baseAddress = -1;
int64_t startOffset = -1;
int64_t endOffset = -1;
ZGame game;
GameConfig cfg;
bool verboseUnaccounted = false;
Expand Down
27 changes: 27 additions & 0 deletions ZAPD/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ void Arg_EnableGCCCompat(int& i, char* argv[]);
void Arg_ForceStatic(int& i, char* argv[]);
void Arg_ForceUnaccountedStatic(int& i, char* argv[]);
void Arg_CsFloatMode(int& i, char* argv[]);
void Arg_BaseAddress(int& i, char* argv[]);
void Arg_StartOffset(int& i, char* argv[]);
void Arg_EndOffset(int& i, char* argv[]);

int main(int argc, char* argv[]);

Expand Down Expand Up @@ -254,6 +257,9 @@ void ParseArgs(int& argc, char* argv[])
{"-us", &Arg_ForceUnaccountedStatic},
{"--unaccounted-static", &Arg_ForceUnaccountedStatic},
{"--cs-float", &Arg_CsFloatMode},
{"--base-address", &Arg_BaseAddress},
{"--start-offset", &Arg_StartOffset},
{"--end-offset", &Arg_EndOffset},
};

for (int32_t i = 2; i < argc; i++)
Expand Down Expand Up @@ -429,6 +435,27 @@ void Arg_CsFloatMode([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
}
}

uint32_t ParseU32Hex(char* str)
{
static_assert(sizeof(uint32_t) <= sizeof(unsigned long));
return (uint32_t)std::stoul(str, nullptr, 16);
}

void Arg_BaseAddress(int& i, char* argv[])
{
Globals::Instance->baseAddress = ParseU32Hex(argv[++i]);
}

void Arg_StartOffset(int& i, char* argv[])
{
Globals::Instance->startOffset = ParseU32Hex(argv[++i]);
}

void Arg_EndOffset(int& i, char* argv[])
{
Globals::Instance->endOffset = ParseU32Hex(argv[++i]);
}

int HandleExtract(ZFileMode fileMode, ExporterSet* exporterSet)
{
bool procFileModeSuccess = false;
Expand Down
18 changes: 18 additions & 0 deletions ZAPD/ZFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
if (reader->Attribute("BaseAddress") != nullptr)
baseAddress = StringHelper::StrToL(reader->Attribute("BaseAddress"), 16);

if (mode == ZFileMode::Extract && Globals::Instance->baseAddress != -1)
baseAddress = Globals::Instance->baseAddress;

if (reader->Attribute("RangeStart") != nullptr)
rangeStart = StringHelper::StrToL(reader->Attribute("RangeStart"), 16);

Expand Down Expand Up @@ -197,6 +200,9 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
}

rawData = File::ReadAllBytes((basePath / name).string());
if (mode == ZFileMode::Extract && Globals::Instance->startOffset != -1 && Globals::Instance->endOffset != -1)
rawData = std::vector<uint8_t>(rawData.begin() + Globals::Instance->startOffset,
rawData.begin() + Globals::Instance->endOffset);

if (reader->Attribute("RangeEnd") == nullptr)
rangeEnd = rawData.size();
Expand Down Expand Up @@ -585,6 +591,12 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in
includePath = "assets/" + StringHelper::Split(includePath, "assets/extracted/")[1];
if (StringHelper::StartsWith(includePath, "assets/custom/"))
includePath = "assets/" + StringHelper::Split(includePath, "assets/custom/")[1];
// Hack for OOT: don't prefix include paths with extracted/VERSION/
if (StringHelper::StartsWith(includePath, "extracted/")) {
std::vector<std::string> parts = StringHelper::Split(includePath, "/");
parts.erase(parts.begin(), parts.begin() + 2);
includePath = StringHelper::Join(parts, "/");
}

Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
Expand Down Expand Up @@ -621,6 +633,12 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in
includePath = "assets/" + StringHelper::Split(includePath, "assets/extracted/")[1];
if (StringHelper::StartsWith(includePath, "assets/custom/"))
includePath = "assets/" + StringHelper::Split(includePath, "assets/custom/")[1];
// Hack for OOT: don't prefix include paths with extracted/VERSION/
if (StringHelper::StartsWith(includePath, "extracted/")) {
std::vector<std::string> parts = StringHelper::Split(includePath, "/");
parts.erase(parts.begin(), parts.begin() + 2);
includePath = StringHelper::Join(parts, "/");
}

Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
Expand Down
15 changes: 15 additions & 0 deletions ZAPDUtils/Utils/StringHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ class StringHelper
return result;
}

static std::string Join(const std::vector<std::string> parts, const std::string& delimiter)
{
std::string result;

for (size_t i = 0; i < parts.size(); i++)
{
result += parts[i];

if (i != parts.size() - 1)
result += delimiter;
}

return result;
}

static std::string Strip(std::string s, const std::string& delimiter)
{
size_t pos = 0;
Expand Down

0 comments on commit 0285e11

Please sign in to comment.