Update ZAPD subrepo (#1338)

* git subrepo pull --force tools/ZAPD

subrepo:
  subdir:   "tools/ZAPD"
  merged:   "cb0342425"
upstream:
  origin:   "https://github.com/zeldaret/ZAPD.git"
  branch:   "master"
  commit:   "cb0342425"
git-subrepo:
  version:  "0.4.6"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "110b9eb"

* git subrepo pull --force tools/ZAPD

subrepo:
  subdir:   "tools/ZAPD"
  merged:   "505024b33"
upstream:
  origin:   "https://github.com/zeldaret/ZAPD.git"
  branch:   "master"
  commit:   "505024b33"
git-subrepo:
  version:  "0.4.6"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "110b9eb"

* Disable Wno-hardcoded-pointer for `make assets`
This commit is contained in:
Tom Overton 2023-07-28 15:20:12 -07:00 committed by GitHub
parent 6f7d6cc47e
commit bbfbc4073e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1426 additions and 719 deletions

View File

@ -309,7 +309,7 @@ setup:
python3 tools/decompress_yars.py
assets:
python3 extract_assets.py -j $(N_THREADS)
python3 extract_assets.py -j $(N_THREADS) -Z Wno-hardcoded-pointer
## Assembly generation
disasm:

View File

@ -66,7 +66,7 @@ PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortIncludes: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements

View File

@ -6,7 +6,7 @@
[subrepo]
remote = https://github.com/zeldaret/ZAPD.git
branch = master
commit = 23929ec9373d28cb298daad4ad7cb468e09c0a46
parent = 2e487b5008c129031ab311a3a7bfd42adeb4916b
commit = 505024b33eb1fcd00e3e9bb71f1355fa2ae6e9cf
parent = 387d3597142ebdbebe1fbb99858ea831aa2752b4
method = merge
cmdver = 0.4.3
cmdver = 0.4.6

View File

@ -67,9 +67,9 @@ void ExporterExample_Collision::Save(ZResource* res, [[maybe_unused]] fs::path o
for (auto entry : col->camData->entries)
{
writer->Write(entry->cameraSType);
writer->Write(entry->numData);
writer->Write(entry->cameraPosDataSeg);
writer->Write(entry.cameraSType);
writer->Write(entry.numData);
writer->Write(entry.cameraPosDataSeg);
}
writer->Seek(oldOffset, SeekOffsetType::Start);

View File

@ -17,7 +17,7 @@ clean:
rm -rf build $(LIB)
format:
clang-format-11 -i $(CPP_FILES) $(H_FILES)
clang-format-14 -i $(CPP_FILES) $(H_FILES)
.PHONY: all clean format

View File

@ -106,7 +106,7 @@ clean:
rebuild: clean all
format:
clang-format-11 -i $(ZAPD_CPP_FILES) $(ZAPD_H_FILES)
clang-format-14 -i $(ZAPD_CPP_FILES) $(ZAPD_H_FILES)
$(MAKE) -C ZAPDUtils format
$(MAKE) -C ExporterTest format

View File

@ -139,22 +139,23 @@ Each warning type uses one of these by default, but can be modified with flags,
All warning types currently implemented, with their default levels:
| Warning type | Default level | Description |
| --------------------------- | ------------- | ------------------------------------------------------------------------ |
| `-Wdeprecated` | Warn | Deprecated features |
| `-Whardcoded-pointer` | Warn | ZAPD lacks the info to make a symbol, so must output a hardcoded pointer |
| `-Wintersection` | Warn | Two assets intersect |
| `-Winvalid-attribute-value` | Err | Attribute declared in XML is wrong |
| `-Winvalid-extracted-data` | Err | Extracted data does not have correct form |
| `-Winvalid-jpeg` | Err | JPEG file does not conform to the game's format requirements |
| `-Winvalid-png` | Err | Issues arising when processing PNG data |
| `-Winvalid-xml` | Err | XML has syntax errors |
| `-Wmissing-attribute` | Warn | Required attribute missing in XML tag |
| `-Wmissing-offsets` | Warn | Offset attribute missing in XML tag |
| `-Wmissing-segment` | Warn | Segment not given in File tag in XML |
| `-Wnot-implemented` | Warn | ZAPD does not currently support this feature |
| `-Wunaccounted` | Off | Large blocks of unaccounted |
| `-Wunknown-attribute` | Warn | Unknown attribute in XML entry tag |
| Warning type | Default level | Description |
| ----------------------------- | ------------- | ------------------------------------------------------------------------ |
| `-Wdeprecated` | Warn | Deprecated features |
| `-Whardcoded-generic-pointer` | Off | A generic segmented pointer must be produced |
| `-Whardcoded-pointer` | Warn | ZAPD lacks the info to make a symbol, so must output a hardcoded pointer |
| `-Wintersection` | Warn | Two assets intersect |
| `-Winvalid-attribute-value` | Err | Attribute declared in XML is wrong |
| `-Winvalid-extracted-data` | Err | Extracted data does not have correct form |
| `-Winvalid-jpeg` | Err | JPEG file does not conform to the game's format requirements |
| `-Winvalid-png` | Err | Issues arising when processing PNG data |
| `-Winvalid-xml` | Err | XML has syntax errors |
| `-Wmissing-attribute` | Warn | Required attribute missing in XML tag |
| `-Wmissing-offsets` | Warn | Offset attribute missing in XML tag |
| `-Wmissing-segment` | Warn | Segment not given in File tag in XML |
| `-Wnot-implemented` | Warn | ZAPD does not currently support this feature |
| `-Wunaccounted` | Off | Large blocks of unaccounted |
| `-Wunknown-attribute` | Warn | Unknown attribute in XML entry tag |
There are also errors that do not have a type, and cannot be disabled.

View File

@ -1,6 +1,6 @@
#pragma once
static uint32_t CRC32B(unsigned char* message, int32_t size)
static uint32_t CRC32B(const unsigned char* message, int32_t size)
{
int32_t byte, crc;
int32_t mask;

View File

@ -8,6 +8,7 @@
#endif
#include <array>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <ctime>

View File

@ -4,61 +4,79 @@
#include "Utils/StringHelper.h"
Declaration::Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nText)
const std::string& nBody)
{
address = nAddress;
alignment = nAlignment;
size = nSize;
text = nText;
declBody = nBody;
}
Declaration::Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nVarType, const std::string& nVarName, bool nIsArray,
const std::string& nText)
: Declaration(nAddress, nAlignment, nSize, nText)
Declaration* Declaration::Create(offset_t declAddr, DeclarationAlignment declAlign, size_t declSize,
const std::string& declType, const std::string& declName,
const std::string& declBody)
{
varType = nVarType;
varName = nVarName;
isArray = nIsArray;
Declaration* decl = new Declaration(declAddr, declAlign, declSize, declBody);
decl->declType = declType;
decl->declName = declName;
decl->declBody = declBody;
return decl;
}
Declaration::Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nVarType, const std::string& nVarName, bool nIsArray,
size_t nArrayItemCnt, const std::string& nText)
: Declaration(nAddress, nAlignment, nSize, nText)
Declaration* Declaration::CreateArray(offset_t declAddr, DeclarationAlignment declAlign,
size_t declSize, const std::string& declType,
const std::string& declName, const std::string& declBody,
size_t declArrayItemCnt, bool isDeclExternal)
{
varType = nVarType;
varName = nVarName;
isArray = nIsArray;
arrayItemCnt = nArrayItemCnt;
Declaration* decl = new Declaration(declAddr, declAlign, declSize, declBody);
decl->declName = declName;
decl->declType = declType;
decl->arrayItemCnt = declArrayItemCnt;
decl->isExternal = isDeclExternal;
decl->isArray = true;
return decl;
}
Declaration::Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nVarType, const std::string& nVarName, bool nIsArray,
const std::string& nArrayItemCntStr, const std::string& nText)
: Declaration(nAddress, nAlignment, nSize, nText)
Declaration* Declaration::CreateArray(offset_t declAddr, DeclarationAlignment declAlign,
size_t declSize, const std::string& declType,
const std::string& declName, const std::string& declBody,
const std::string& declArrayItemCntStr, bool isDeclExternal)
{
varType = nVarType;
varName = nVarName;
isArray = nIsArray;
arrayItemCntStr = nArrayItemCntStr;
Declaration* decl = new Declaration(declAddr, declAlign, declSize, declBody);
decl->declName = declName;
decl->declType = declType;
decl->arrayItemCntStr = declArrayItemCntStr;
decl->isExternal = isDeclExternal;
decl->isArray = true;
return decl;
}
Declaration::Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nVarType, const std::string& nVarName, bool nIsArray,
size_t nArrayItemCnt, const std::string& nText, bool nIsExternal)
: Declaration(nAddress, nAlignment, nSize, nVarType, nVarName, nIsArray, nArrayItemCnt, nText)
Declaration* Declaration::CreateInclude(offset_t declAddr, const std::string& includePath,
size_t declSize, const std::string& declType,
const std::string& declName, const std::string& defines)
{
isExternal = nIsExternal;
Declaration* decl = new Declaration(declAddr, DeclarationAlignment::Align4, declSize, "");
decl->includePath = includePath;
decl->declType = declType;
decl->declName = declName;
decl->defines = defines;
return decl;
}
Declaration::Declaration(offset_t nAddress, const std::string& nIncludePath, size_t nSize,
const std::string& nVarType, const std::string& nVarName)
: Declaration(nAddress, DeclarationAlignment::Align4, nSize, "")
Declaration* Declaration::CreatePlaceholder(offset_t declAddr, const std::string& declName)
{
includePath = nIncludePath;
varType = nVarType;
varName = nVarName;
Declaration* decl = new Declaration(declAddr, DeclarationAlignment::Align4, 0, "");
decl->declName = declName;
decl->isPlaceholder = true;
return decl;
}
bool Declaration::IsStatic() const
@ -82,9 +100,6 @@ std::string Declaration::GetNormalDeclarationStr() const
{
std::string output;
if (preText != "")
output += preText + "\n";
if (IsStatic())
{
output += "static ";
@ -92,27 +107,28 @@ std::string Declaration::GetNormalDeclarationStr() const
if (isArray)
{
if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt))
bool includeArraySize = (IsStatic() || forceArrayCnt);
if (includeArraySize)
{
output += StringHelper::Sprintf("%s %s[%s];\n", varType.c_str(), varName.c_str(),
arrayItemCntStr.c_str());
}
else if (arrayItemCnt != 0 && (IsStatic() || forceArrayCnt))
{
output += StringHelper::Sprintf("%s %s[%i] = {\n", varType.c_str(), varName.c_str(),
arrayItemCnt);
if (arrayItemCntStr != "")
output += StringHelper::Sprintf("%s %s[%s];\n", declType.c_str(), declName.c_str(),
arrayItemCntStr.c_str());
else
output += StringHelper::Sprintf("%s %s[%i] = {\n", declType.c_str(),
declName.c_str(), arrayItemCnt);
}
else
{
output += StringHelper::Sprintf("%s %s[] = {\n", varType.c_str(), varName.c_str());
output += StringHelper::Sprintf("%s %s[] = {\n", declType.c_str(), declName.c_str());
}
output += text + "\n";
output += declBody + "\n";
}
else
{
output += StringHelper::Sprintf("%s %s = { ", varType.c_str(), varName.c_str());
output += text;
output += StringHelper::Sprintf("%s %s = { ", declType.c_str(), declName.c_str());
output += declBody;
}
if (output.back() == '\n')
@ -120,14 +136,8 @@ std::string Declaration::GetNormalDeclarationStr() const
else
output += " };";
if (rightText != "")
output += " " + rightText + "";
output += "\n";
if (postText != "")
output += postText + "\n";
output += "\n";
return output;
@ -137,41 +147,34 @@ std::string Declaration::GetExternalDeclarationStr() const
{
std::string output;
if (preText != "")
output += preText + "\n";
if (IsStatic())
{
output += "static ";
bool includeArraySize = (IsStatic() || forceArrayCnt);
if (includeArraySize)
{
if (arrayItemCntStr != "")
output += StringHelper::Sprintf("%s %s[%s] = ", declType.c_str(), declName.c_str(),
arrayItemCntStr.c_str());
else
output += StringHelper::Sprintf("%s %s[%i] = ", declType.c_str(), declName.c_str(),
arrayItemCnt);
}
else
{
output += StringHelper::Sprintf("%s %s[] = ", declType.c_str(), declName.c_str());
}
if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt))
output += StringHelper::Sprintf("%s %s[%s] = ", varType.c_str(), varName.c_str(),
arrayItemCntStr.c_str());
else if (arrayItemCnt != 0 && (IsStatic() || forceArrayCnt))
output +=
StringHelper::Sprintf("%s %s[%i] = ", varType.c_str(), varName.c_str(), arrayItemCnt);
else
output += StringHelper::Sprintf("%s %s[] = ", varType.c_str(), varName.c_str());
output += StringHelper::Sprintf("{\n#include \"%s\"\n};", includePath.c_str());
if (rightText != "")
output += " " + rightText + "";
output += "\n";
if (postText != "")
output += postText + "\n";
output += "\n";
output += "\n\n";
return output;
}
std::string Declaration::GetExternStr() const
{
if (IsStatic() || varType == "" || isUnaccounted)
if (IsStatic() || declType == "" || isUnaccounted)
{
return "";
}
@ -180,19 +183,28 @@ std::string Declaration::GetExternStr() const
{
if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt))
{
return StringHelper::Sprintf("extern %s %s[%s];\n", varType.c_str(), varName.c_str(),
return StringHelper::Sprintf("extern %s %s[%s];\n", declType.c_str(), declName.c_str(),
arrayItemCntStr.c_str());
}
else if (arrayItemCnt != 0 && (IsStatic() || forceArrayCnt))
{
return StringHelper::Sprintf("extern %s %s[%i];\n", varType.c_str(), varName.c_str(),
return StringHelper::Sprintf("extern %s %s[%i];\n", declType.c_str(), declName.c_str(),
arrayItemCnt);
}
else
return StringHelper::Sprintf("extern %s %s[];\n", varType.c_str(), varName.c_str());
return StringHelper::Sprintf("extern %s %s[];\n", declType.c_str(), declName.c_str());
}
return StringHelper::Sprintf("extern %s %s;\n", varType.c_str(), varName.c_str());
return StringHelper::Sprintf("extern %s %s;\n", declType.c_str(), declName.c_str());
}
std::string Declaration::GetDefinesStr() const
{
if (IsStatic() || (declType == ""))
{
return "";
}
return StringHelper::Sprintf("%s", defines.c_str());
}
std::string Declaration::GetStaticForwardDeclarationStr() const
@ -210,15 +222,15 @@ std::string Declaration::GetStaticForwardDeclarationStr() const
if (arrayItemCntStr != "")
{
return StringHelper::Sprintf("static %s %s[%s];\n", varType.c_str(), varName.c_str(),
return StringHelper::Sprintf("static %s %s[%s];\n", declType.c_str(), declName.c_str(),
arrayItemCntStr.c_str());
}
else
{
return StringHelper::Sprintf("static %s %s[%i];\n", varType.c_str(), varName.c_str(),
return StringHelper::Sprintf("static %s %s[%i];\n", declType.c_str(), declName.c_str(),
arrayItemCnt);
}
}
return StringHelper::Sprintf("static %s %s;\n", varType.c_str(), varName.c_str());
return StringHelper::Sprintf("static %s %s;\n", declType.c_str(), declName.c_str());
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
@ -22,59 +23,160 @@ enum class StaticConfig
On
};
/// <summary>
/// A declaration is contains the C contents of a symbol for a file.
/// It contains at a minimum the address where the symbol would be in the binary file, alignment
/// settings, the size of the binary data, and the C code that makes it up. Optionally it can also
/// contain comments.
/// </summary>
class Declaration
{
public:
offset_t address;
DeclarationAlignment alignment;
size_t size;
std::string preText;
std::string text;
std::string rightText;
std::string postText;
std::string preComment;
std::string postComment;
std::string varType;
std::string varName;
std::string includePath;
// Where in the binary file (segment) will this C code end up being?
offset_t address = 0;
// How is this C code aligned?
DeclarationAlignment alignment = DeclarationAlignment::Align4;
// How many bytes will this C code take up in the resulting binary when compiled?
size_t size = 0;
// The C type of this declaration
std::string declType = "";
// The C variable name of this declaration
std::string declName = "";
// The body of the declaration containing the data.
// In "int j = 7;", "7" would be text.
std::string declBody = "";
// #define's to be included in the header
std::string defines = "";
std::string includePath = "";
// Is this declaration in an external file? (ie. a gameplay_keep reference being found in
// another file that wishes to use its data)
bool isExternal = false;
bool isArray = false;
// If true, will ensure that the arrays size is included in the declaration
bool forceArrayCnt = false;
// If this declaration is an array, how many items make it up?
size_t arrayItemCnt = 0;
// Overrides the brackets for the arrays size with a custom string
std::string arrayItemCntStr = "";
std::vector<segptr_t> references;
// If true, this declaration represents data inside the file which we do not understand it's
// purpose for. It will be outputted as just a byte array.
bool isUnaccounted = false;
// Is this declaration a placeholder that will be replaced later?
bool isPlaceholder = false;
// Does this declaration come straight from the XML?
// If false, this means that the declaration was created by ZAPD when it was parsing the
// resources.
bool declaredInXml = false;
StaticConfig staticConf = StaticConfig::Global;
Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nVarType, const std::string& nVarName, bool nIsArray,
const std::string& nText);
Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nVarType, const std::string& nVarName, bool nIsArray,
size_t nArrayItemCnt, const std::string& nText);
Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nVarType, const std::string& nVarName, bool nIsArray,
const std::string& nArrayItemCntStr, const std::string& nText);
Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nVarType, const std::string& nVarName, bool nIsArray,
size_t nArrayItemCnt, const std::string& nText, bool nIsExternal);
/// <summary>
/// Creates a regular declaration.
/// </summary>
/// <param name="declAddr">The address inside a binary file this declaration will be in when
/// compiled.</param> <param name="declAlign">The alignment of this declaration in the compiled
/// binary file.</param> <param name="declSize">The size of this declaration when it is compiled
/// to binary data.</param> <param name="declType">The C variable type this declaration will be
/// declared as.</param> <param name="declName">The C variable name this declaration will be
/// declared as.</param> <param name="declBody">The contents of the C variable
/// declaration.</param> <returns></returns>
static Declaration* Create(offset_t declAddr, DeclarationAlignment declAlign, size_t declSize,
const std::string& declType, const std::string& declName,
const std::string& declBody);
Declaration(offset_t nAddress, const std::string& nIncludePath, size_t nSize,
const std::string& nVarType, const std::string& nVarName);
/// <summary>
/// Creates an array declaration.
/// </summary>
/// <param name="declAddr">The address inside a binary file this declaration will be in when
/// compiled.</param> <param name="declAlign">The alignment of this declaration in the compiled
/// binary file.</param> <param name="declSize">The size of this declaration when it is compiled
/// to binary data.</param> <param name="declType">The C variable type this declaration will be
/// declared as.</param> <param name="declName">The C variable name this declaration will be
/// declared as.</param> <param name="declBody">The contents of the C variable
/// declaration.</param> <param name="declArrayItemCnt">The number of items in the
/// array.</param> <param name="isDeclExternal">(Optional) Is this declaration from another
/// segment?</param> <returns></returns>
static Declaration* CreateArray(offset_t declAddr, DeclarationAlignment declAlign,
size_t declSize, const std::string& declType,
const std::string& declName, const std::string& declBody,
size_t declArrayItemCnt = 0, bool isDeclExternal = false);
/// <summary>
/// Creates an array declaration who's size in the C code uses a custom string.
/// </summary>
/// <param name="declAddr">The address inside a binary file this declaration will be in when
/// compiled.</param> <param name="declAlign">The alignment of this declaration in the compiled
/// binary file.</param> <param name="declSize">The size of this declaration when it is compiled
/// to binary data.</param> <param name="declType">The C variable type this declaration will be
/// declared as.</param> <param name="declName">The C variable name this declaration will be
/// declared as.</param> <param name="declBody">The contents of the C variable
/// declaration.</param> <param name="declArrayItemCntStr">The string to be put in the C array's
/// size inbetween the brackets.</param> <param name="isDeclExternal">(Optional) Is this
/// declaration from another segment?</param> <returns></returns>
static Declaration* CreateArray(offset_t declAddr, DeclarationAlignment declAlign,
size_t declSize, const std::string& declType,
const std::string& declName, const std::string& declBody,
const std::string& declArrayItemCntStr,
bool isDeclExternal = false);
/// <summary>
/// Creates a declaration who's body uses a #include to include another file
/// </summary>
/// <param name="declAddr">The address inside a binary file this declaration will be in when
/// compiled.</param> <param name="includePath">The path to the file this declaration will be
/// #including.</param> <param name="declSize">The size of this declaration when it is compiled
/// to binary data.</param> <param name="declType">The C variable type this declaration will be
/// declared as.</param> <param name="declName">The C variable name this declaration will be
/// declared as.</param> <param name="defines">(Optional) Any #define's we want to have
/// outputted by this declaration.</param> <returns></returns>
static Declaration* CreateInclude(offset_t declAddr, const std::string& includePath,
size_t declSize, const std::string& declType,
const std::string& declName, const std::string& defines = "");
/// <summary>
/// Creates a placeholder declaration to be replaced later.
/// </summary>
/// <param name="declAddr">The address inside a binary file this declaration will be in when
/// compiled.</param> <param name="declName">The C variable name this declaration will be
/// declared as.</param> <returns></returns>
static Declaration* CreatePlaceholder(offset_t declAddr, const std::string& declName);
bool IsStatic() const;
// Returns the declaration as C code as it would be in the code file when the body contains the
// needed data
std::string GetNormalDeclarationStr() const;
// Returns the declaration as C code as it would be in the code file when the body #include's
// another file
std::string GetExternalDeclarationStr() const;
// Generates the extern for this item to be placed in header files.
std::string GetExternStr() const;
// Generates any #define's needed
std::string GetDefinesStr() const;
std::string GetStaticForwardDeclarationStr() const;
protected:
Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nText);
const std::string& nBody);
};

View File

@ -0,0 +1,24 @@
#pragma once
typedef void (*ExporterSetFunc)(ZFile*);
typedef bool (*ExporterSetFuncBool)(ZFileMode fileMode);
typedef void (*ExporterSetFuncVoid)(int argc, char* argv[], int& i);
typedef void (*ExporterSetFuncVoid2)(const std::string& buildMode, ZFileMode& fileMode);
typedef void (*ExporterSetFuncVoid3)();
typedef void (*ExporterSetResSave)(ZResource* res, BinaryWriter& writer);
class ExporterSet
{
public:
~ExporterSet();
std::map<ZResourceType, ZResourceExporter*> exporters;
ExporterSetFuncVoid parseArgsFunc = nullptr;
ExporterSetFuncVoid2 parseFileModeFunc = nullptr;
ExporterSetFuncBool processFileModeFunc = nullptr;
ExporterSetFunc beginFileFunc = nullptr;
ExporterSetFunc endFileFunc = nullptr;
ExporterSetFuncVoid3 beginXMLFunc = nullptr;
ExporterSetFuncVoid3 endXMLFunc = nullptr;
ExporterSetResSave resSaveFunc = nullptr;
};

View File

@ -124,6 +124,7 @@ void GameConfig::ConfigFunc_BGConfig(const tinyxml2::XMLElement& element)
{
bgScreenWidth = element.IntAttribute("ScreenWidth", 320);
bgScreenHeight = element.IntAttribute("ScreenHeight", 240);
useScreenWidthHeightConstants = element.BoolAttribute("UseScreenWidthHeightConstants", true);
}
void GameConfig::ConfigFunc_ExternalXMLFolder(const tinyxml2::XMLElement& element)

View File

@ -37,6 +37,8 @@ public:
// ZBackground
uint32_t bgScreenWidth = 320, bgScreenHeight = 240;
bool useScreenWidthHeightConstants = true; // If true, ZBackground's will be declared with
// SCREEN_WIDTH * SCREEN_HEIGHT in the C file
// ExternalFile
fs::path externalXmlFolder;

View File

@ -83,9 +83,10 @@ ExporterSet* Globals::GetExporterSet()
}
bool Globals::GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile,
const std::string& expectedType, std::string& declName)
const std::string& expectedType, std::string& declName,
bool warnIfNotFound)
{
if (segAddress == 0)
if (segAddress == SEGMENTED_NULL)
{
declName = "NULL";
return true;
@ -160,14 +161,18 @@ bool Globals::GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile,
}
declName = StringHelper::Sprintf("0x%08X", segAddress);
if (warnIfNotFound)
{
WarnHardcodedPointer(segAddress, currentFile, nullptr, -1);
}
return false;
}
bool Globals::GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSize,
ZFile* currentFile, const std::string& expectedType,
std::string& declName)
std::string& declName, bool warnIfNotFound)
{
if (segAddress == 0)
if (segAddress == SEGMENTED_NULL)
{
declName = "NULL";
return true;
@ -197,9 +202,36 @@ bool Globals::GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSi
}
declName = StringHelper::Sprintf("0x%08X", segAddress);
if (warnIfNotFound)
{
WarnHardcodedPointer(segAddress, currentFile, nullptr, -1);
}
return false;
}
void Globals::WarnHardcodedPointer(segptr_t segAddress, ZFile* currentFile, ZResource* res,
offset_t currentOffset)
{
uint8_t segment = GETSEGNUM(segAddress);
if ((segment >= 2 && segment <= 6) || segment == 0x80)
{
std::string errorHeader = "A hardcoded pointer was found";
std::string errorBody = StringHelper::Sprintf("Pointer: 0x%08X", segAddress);
HANDLE_WARNING_RESOURCE(WarningType::HardcodedPointer, currentFile, res, currentOffset,
errorHeader, errorBody);
}
else
{
std::string errorHeader = "A general purpose hardcoded pointer was found";
std::string errorBody = StringHelper::Sprintf("Pointer: 0x%08X", segAddress);
HANDLE_WARNING_RESOURCE(WarningType::HardcodedGenericPointer, currentFile, res,
currentOffset, errorHeader, errorBody);
}
}
ExternalFile::ExternalFile(fs::path nXmlPath, fs::path nOutPath)
: xmlPath{nXmlPath}, outPath{nOutPath}
{

View File

@ -5,6 +5,7 @@
#include <vector>
#include "GameConfig.h"
#include "ZFile.h"
#include "ExporterSet.h"
class ZRoom;
@ -15,29 +16,6 @@ enum class VerbosityLevel
VERBOSITY_DEBUG
};
typedef void (*ExporterSetFunc)(ZFile*);
typedef bool (*ExporterSetFuncBool)(ZFileMode fileMode);
typedef void (*ExporterSetFuncVoid)(int argc, char* argv[], int& i);
typedef void (*ExporterSetFuncVoid2)(const std::string& buildMode, ZFileMode& fileMode);
typedef void (*ExporterSetFuncVoid3)();
typedef void (*ExporterSetResSave)(ZResource* res, BinaryWriter& writer);
class ExporterSet
{
public:
~ExporterSet();
std::map<ZResourceType, ZResourceExporter*> exporters;
ExporterSetFuncVoid parseArgsFunc = nullptr;
ExporterSetFuncVoid2 parseFileModeFunc = nullptr;
ExporterSetFuncBool processFileModeFunc = nullptr;
ExporterSetFunc beginFileFunc = nullptr;
ExporterSetFunc endFileFunc = nullptr;
ExporterSetFuncVoid3 beginXMLFunc = nullptr;
ExporterSetFuncVoid3 endXMLFunc = nullptr;
ExporterSetResSave resSaveFunc = nullptr;
};
class Globals
{
public:
@ -86,8 +64,14 @@ public:
* in which case `declName` will be set to the address formatted as a pointer.
*/
bool GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile,
const std::string& expectedType, std::string& declName);
const std::string& expectedType, std::string& declName,
bool warnIfNotFound = true);
bool GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSize, ZFile* currentFile,
const std::string& expectedType, std::string& declName);
const std::string& expectedType, std::string& declName,
bool warnIfNotFound = true);
// TODO: consider moving to another place
void WarnHardcodedPointer(segptr_t segAddress, ZFile* currentFile, ZResource* res,
offset_t currentOffset);
};

View File

@ -9,24 +9,52 @@
#include "ZFile.h"
#include "ZTexture.h"
#include <functional>
#include "CrashHandler.h"
#include <string>
#include <string_view>
#include "tinyxml2.h"
using ArgFunc = void (*)(int&, char**);
void Arg_SetOutputPath(int& i, char* argv[]);
void Arg_SetInputPath(int& i, char* argv[]);
void Arg_SetBaseromPath(int& i, char* argv[]);
void Arg_SetSourceOutputPath(int& i, char* argv[]);
void Arg_GenerateSourceFile(int& i, char* argv[]);
void Arg_TestMode(int& i, char* argv[]);
void Arg_LegacyDList(int& i, char* argv[]);
void Arg_EnableProfiling(int& i, char* argv[]);
void Arg_UseExternalResources(int& i, char* argv[]);
void Arg_SetTextureType(int& i, char* argv[]);
void Arg_ReadConfigFile(int& i, char* argv[]);
void Arg_EnableErrorHandler(int& i, char* argv[]);
void Arg_SetVerbosity(int& i, char* argv[]);
void Arg_VerboseUnaccounted(int& i, char* argv[]);
void Arg_SetExporter(int& i, char* argv[]);
void Arg_EnableGCCCompat(int& i, char* argv[]);
void Arg_ForceStatic(int& i, char* argv[]);
void Arg_ForceUnaccountedStatic(int& i, char* argv[]);
int main(int argc, char* argv[]);
bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath,
ZFileMode fileMode);
void ParseArgs(int& argc, char* argv[]);
void BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const fs::path& outPath);
void BuildAssetBackground(const fs::path& imageFilePath, const fs::path& outPath);
void BuildAssetBlob(const fs::path& blobFilePath, const fs::path& outPath);
ZFileMode ParseFileMode(const std::string& buildMode, ExporterSet* exporterSet);
int HandleExtract(ZFileMode fileMode, ExporterSet* exporterSet);
extern const char gBuildHash[];
int main(int argc, char* argv[])
{
// Syntax: ZAPD.out [mode (btex/bovl/e)] (Arbritrary Number of Arguments)
int returnCode = 0;
if (argc < 2)
{
@ -55,112 +83,12 @@ int main(int argc, char* argv[])
}
}
// Parse other "commands"
for (int32_t i = 2; i < argc; i++)
{
std::string arg = argv[i];
if (arg == "-o" || arg == "--outputpath") // Set output path
{
Globals::Instance->outputPath = argv[++i];
if (Globals::Instance->sourceOutputPath == "")
Globals::Instance->sourceOutputPath = Globals::Instance->outputPath;
}
else if (arg == "-i" || arg == "--inputpath") // Set input path
{
Globals::Instance->inputPath = argv[++i];
}
else if (arg == "-b" || arg == "--baserompath") // Set baserom path
{
Globals::Instance->baseRomPath = argv[++i];
}
else if (arg == "-osf") // Set source output path
{
Globals::Instance->sourceOutputPath = argv[++i];
}
else if (arg == "-gsf") // Generate source file during extraction
{
Globals::Instance->genSourceFile = std::string_view(argv[++i]) == "1";
}
else if (arg == "-tm") // Test Mode (enables certain experimental features)
{
Globals::Instance->testMode = std::string_view(argv[++i]) == "1";
}
else if (arg == "-crc" ||
arg == "--output-crc") // Outputs a CRC file for each extracted texture.
{
Globals::Instance->testMode = std::string_view(argv[++i]) == "1";
}
else if (arg == "-ulzdl") // Use Legacy ZDisplay List
{
Globals::Instance->useLegacyZDList = std::string_view(argv[++i]) == "1";
}
else if (arg == "-profile") // Enable profiling
{
Globals::Instance->profile = std::string_view(argv[++i]) == "1";
}
else if (arg ==
"-uer") // Split resources into their individual components (enabled by default)
// TODO: We may wish to make this a part of the config file...
{
Globals::Instance->useExternalResources = std::string_view(argv[++i]) == "1";
}
else if (arg == "-tt") // Set texture type
{
Globals::Instance->texType = ZTexture::GetTextureTypeFromString(argv[++i]);
}
else if (arg == "-rconf") // Read Config File
{
Globals::Instance->cfg.ReadConfigFile(argv[++i]);
}
else if (arg == "-eh") // Enable Error Handler
{
CrashHandler_Init();
}
else if (arg == "-v") // Verbose
{
Globals::Instance->verbosity = static_cast<VerbosityLevel>(strtol(argv[++i], NULL, 16));
}
else if (arg == "-vu" || arg == "--verbose-unaccounted") // Verbose unaccounted
{
Globals::Instance->verboseUnaccounted = true;
}
else if (arg == "-se" || arg == "--set-exporter") // Set Current Exporter
{
Globals::Instance->currentExporter = argv[++i];
}
else if (arg == "--gcc-compat") // GCC compatibility
{
Globals::Instance->gccCompat = true;
}
else if (arg == "-s" || arg == "--static")
{
Globals::Instance->forceStatic = true;
}
else if (arg == "-us" || arg == "--unaccounted-static")
{
Globals::Instance->forceUnaccountedStatic = true;
}
}
ParseArgs(argc, argv);
// Parse File Mode
ExporterSet* exporterSet = Globals::Instance->GetExporterSet();
std::string buildMode = argv[1];
ZFileMode fileMode = ZFileMode::Invalid;
if (buildMode == "btex")
fileMode = ZFileMode::BuildTexture;
else if (buildMode == "bren")
fileMode = ZFileMode::BuildBackground;
else if (buildMode == "bsf")
fileMode = ZFileMode::BuildSourceFile;
else if (buildMode == "bblb")
fileMode = ZFileMode::BuildBlob;
else if (buildMode == "e")
fileMode = ZFileMode::Extract;
else if (exporterSet != nullptr && exporterSet->parseFileModeFunc != nullptr)
exporterSet->parseFileModeFunc(buildMode, fileMode);
ZFileMode fileMode = ParseFileMode(buildMode, exporterSet);
if (fileMode == ZFileMode::Invalid)
{
@ -170,7 +98,6 @@ int main(int argc, char* argv[])
// We've parsed through our commands once. If an exporter exists, it's been set by now.
// Now we'll parse through them again but pass them on to our exporter if one is available.
if (exporterSet != nullptr && exporterSet->parseArgsFunc != nullptr)
{
for (int32_t i = 2; i < argc; i++)
@ -181,62 +108,20 @@ int main(int argc, char* argv[])
printf("ZAPD: Zelda Asset Processor For Decomp: %s\n", gBuildHash);
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
{
WarningHandler::PrintWarningsDebugInfo();
}
// TODO: switch
if (fileMode == ZFileMode::Extract || fileMode == ZFileMode::BuildSourceFile)
{
bool procFileModeSuccess = false;
if (exporterSet != nullptr && exporterSet->processFileModeFunc != nullptr)
procFileModeSuccess = exporterSet->processFileModeFunc(fileMode);
if (!procFileModeSuccess)
{
bool parseSuccessful;
for (auto& extFile : Globals::Instance->cfg.externalFiles)
{
fs::path externalXmlFilePath =
Globals::Instance->cfg.externalXmlFolder / extFile.xmlPath;
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
{
printf("Parsing external file from config: '%s'\n",
externalXmlFilePath.c_str());
}
parseSuccessful = Parse(externalXmlFilePath, Globals::Instance->baseRomPath,
extFile.outPath, ZFileMode::ExternalFile);
if (!parseSuccessful)
return 1;
}
parseSuccessful = Parse(Globals::Instance->inputPath, Globals::Instance->baseRomPath,
Globals::Instance->outputPath, fileMode);
if (!parseSuccessful)
return 1;
}
}
returnCode = HandleExtract(fileMode, exporterSet);
else if (fileMode == ZFileMode::BuildTexture)
{
TextureType texType = Globals::Instance->texType;
BuildAssetTexture(Globals::Instance->inputPath, texType, Globals::Instance->outputPath);
}
BuildAssetTexture(Globals::Instance->inputPath, Globals::Instance->texType,
Globals::Instance->outputPath);
else if (fileMode == ZFileMode::BuildBackground)
{
BuildAssetBackground(Globals::Instance->inputPath, Globals::Instance->outputPath);
}
else if (fileMode == ZFileMode::BuildBlob)
{
BuildAssetBlob(Globals::Instance->inputPath, Globals::Instance->outputPath);
}
delete g;
return 0;
return returnCode;
}
bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath,
@ -339,6 +224,209 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path
return true;
}
void ParseArgs(int& argc, char* argv[])
{
static const std::unordered_map<std::string, ArgFunc> ArgFuncDictionary = {
{"-o", &Arg_SetOutputPath},
{"--outputpath", &Arg_SetOutputPath},
{"-i", &Arg_SetInputPath},
{"--inputpath", &Arg_SetInputPath},
{"-b", &Arg_SetBaseromPath},
{"--baserompath", &Arg_SetBaseromPath},
{"-osf", &Arg_SetSourceOutputPath},
{"-gsf", &Arg_GenerateSourceFile},
{"-tm", &Arg_TestMode},
{"-ulzdl", &Arg_LegacyDList},
{"-profile", &Arg_EnableProfiling},
{"-uer", &Arg_UseExternalResources},
{"-tt", &Arg_SetTextureType},
{"-rconf", &Arg_ReadConfigFile},
{"-eh", &Arg_EnableErrorHandler},
{"-v", &Arg_SetVerbosity},
{"-vu", &Arg_VerboseUnaccounted},
{"--verbose-unaccounted", &Arg_VerboseUnaccounted},
{"-se", &Arg_SetExporter},
{"--set-exporter", &Arg_SetExporter},
{"--gcc-compat", &Arg_EnableGCCCompat},
{"-s", &Arg_ForceStatic},
{"--static", &Arg_ForceStatic},
{"-us", &Arg_ForceUnaccountedStatic},
{"--unaccounted-static", &Arg_ForceUnaccountedStatic},
};
for (int32_t i = 2; i < argc; i++)
{
std::string arg = argv[i];
// Ignore warning args as they have already been parsed
if (arg.length() > 2 && arg[0] == '-' && arg[1] == 'W' && arg[2] != '\0')
{
continue;
}
auto it = ArgFuncDictionary.find(arg);
if (it == ArgFuncDictionary.end())
{
fprintf(stderr, "Unsupported argument: %s\n", arg.c_str());
continue;
}
std::invoke(it->second, i, argv);
}
}
ZFileMode ParseFileMode(const std::string& buildMode, ExporterSet* exporterSet)
{
ZFileMode fileMode = ZFileMode::Invalid;
if (buildMode == "btex")
fileMode = ZFileMode::BuildTexture;
else if (buildMode == "bren")
fileMode = ZFileMode::BuildBackground;
else if (buildMode == "bsf")
fileMode = ZFileMode::BuildSourceFile;
else if (buildMode == "bblb")
fileMode = ZFileMode::BuildBlob;
else if (buildMode == "e")
fileMode = ZFileMode::Extract;
else if (exporterSet != nullptr && exporterSet->parseFileModeFunc != nullptr)
exporterSet->parseFileModeFunc(buildMode, fileMode);
return fileMode;
}
void Arg_SetOutputPath(int& i, [[maybe_unused]] char* argv[])
{
Globals::Instance->outputPath = argv[++i];
if (Globals::Instance->sourceOutputPath == "")
Globals::Instance->sourceOutputPath = Globals::Instance->outputPath;
}
void Arg_SetInputPath(int& i, char* argv[])
{
Globals::Instance->inputPath = argv[++i];
}
void Arg_SetBaseromPath(int& i, char* argv[])
{
Globals::Instance->baseRomPath = argv[++i];
}
void Arg_SetSourceOutputPath(int& i, char* argv[])
{
Globals::Instance->sourceOutputPath = argv[++i];
}
void Arg_GenerateSourceFile(int& i, char* argv[])
{
// Generate source file during extraction
Globals::Instance->genSourceFile = std::string_view(argv[++i]) == "1";
}
void Arg_TestMode(int& i, char* argv[])
{
// Test Mode (enables certain experimental features)
Globals::Instance->testMode = std::string_view(argv[++i]) == "1";
}
void Arg_LegacyDList(int& i, char* argv[])
{
Globals::Instance->useLegacyZDList = std::string_view(argv[++i]) == "1";
}
void Arg_EnableProfiling(int& i, char* argv[])
{
Globals::Instance->profile = std::string_view(argv[++i]) == "1";
}
void Arg_UseExternalResources(int& i, char* argv[])
{
// Split resources into their individual components(enabled by default)
// TODO: We may wish to make this a part of the config file...
Globals::Instance->useExternalResources = std::string_view(argv[++i]) == "1";
}
void Arg_SetTextureType(int& i, char* argv[])
{
Globals::Instance->texType = ZTexture::GetTextureTypeFromString(argv[++i]);
}
void Arg_ReadConfigFile(int& i, char* argv[])
{
Globals::Instance->cfg.ReadConfigFile(argv[++i]);
}
void Arg_EnableErrorHandler([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
{
CrashHandler_Init();
}
void Arg_SetVerbosity(int& i, char* argv[])
{
Globals::Instance->verbosity = static_cast<VerbosityLevel>(strtol(argv[++i], NULL, 16));
}
void Arg_VerboseUnaccounted([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
{
Globals::Instance->verboseUnaccounted = true;
}
void Arg_SetExporter(int& i, char* argv[])
{
Globals::Instance->currentExporter = argv[++i];
}
void Arg_EnableGCCCompat([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
{
Globals::Instance->gccCompat = true;
}
void Arg_ForceStatic([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
{
Globals::Instance->forceStatic = true;
}
void Arg_ForceUnaccountedStatic([[maybe_unused]] int& i, [[maybe_unused]] char* argv[])
{
Globals::Instance->forceUnaccountedStatic = true;
}
int HandleExtract(ZFileMode fileMode, ExporterSet* exporterSet)
{
bool procFileModeSuccess = false;
if (exporterSet != nullptr && exporterSet->processFileModeFunc != nullptr)
procFileModeSuccess = exporterSet->processFileModeFunc(fileMode);
if (!procFileModeSuccess)
{
bool parseSuccessful;
for (auto& extFile : Globals::Instance->cfg.externalFiles)
{
fs::path externalXmlFilePath =
Globals::Instance->cfg.externalXmlFolder / extFile.xmlPath;
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
printf("Parsing external file from config: '%s'\n", externalXmlFilePath.c_str());
parseSuccessful = Parse(externalXmlFilePath, Globals::Instance->baseRomPath,
extFile.outPath, ZFileMode::ExternalFile);
if (!parseSuccessful)
return 1;
}
parseSuccessful = Parse(Globals::Instance->inputPath, Globals::Instance->baseRomPath,
Globals::Instance->outputPath, fileMode);
if (!parseSuccessful)
return 1;
}
return 0;
}
void BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const fs::path& outPath)
{
std::string name = outPath.stem().string();

View File

@ -165,7 +165,7 @@ void Struct_800A598C::DeclareReferences(const std::string& prefix)
res.GetSourceTypeName(), unk_8_Str, arrayItemCnt, entryStr);
}
else
decl->text = entryStr;
decl->declBody = entryStr;
}
if (unk_C != 0 && GETSEGNUM(unk_C) == parent->segment)
@ -195,7 +195,7 @@ void Struct_800A598C::DeclareReferences(const std::string& prefix)
res.GetSourceTypeName(), unk_C_Str, arrayItemCnt, entryStr);
}
else
decl->text = entryStr;
decl->declBody = entryStr;
}
}
@ -296,7 +296,7 @@ void Struct_800A5E28::DeclareReferences(const std::string& prefix)
res.GetSourceTypeName(), unk_4_Str, arrayItemCnt, entryStr);
}
else
decl->text = entryStr;
decl->declBody = entryStr;
}
if (unk_8 != SEGMENTED_NULL && GETSEGNUM(unk_8) == parent->segment)

View File

@ -1,5 +1,6 @@
#pragma once
#include <cstdint>
#include <map>
#include <string>
#include <vector>

View File

@ -84,26 +84,27 @@ typedef struct
*/
// clang-format off
static const std::unordered_map<std::string, WarningInfoInit> warningStringToInitMap = {
{"deprecated", {WarningType::Deprecated,
{"deprecated", {WarningType::Deprecated,
#ifdef DEPRECATION_ON
WarningLevel::Warn,
#else
WarningLevel::Off,
#endif
"Deprecated features"}},
{"unaccounted", {WarningType::Unaccounted, WarningLevel::Off, "Large blocks of unaccounted"}},
{"missing-offsets", {WarningType::MissingOffsets, WarningLevel::Warn, "Offset attribute missing in XML tag"}},
{"intersection", {WarningType::Intersection, WarningLevel::Warn, "Two assets intersect"}},
{"missing-attribute", {WarningType::MissingAttribute, WarningLevel::Warn, "Required attribute missing in XML tag"}},
{"invalid-attribute-value", {WarningType::InvalidAttributeValue, WarningLevel::Err, "Attribute declared in XML is wrong"}},
{"unknown-attribute", {WarningType::UnknownAttribute, WarningLevel::Warn, "Unknown attribute in XML entry tag"}},
{"invalid-xml", {WarningType::InvalidXML, WarningLevel::Err, "XML has syntax errors"}},
{"invalid-jpeg", {WarningType::InvalidJPEG, WarningLevel::Err, "JPEG file does not conform to the game's format requirements"}},
{"invalid-png", {WarningType::InvalidPNG, WarningLevel::Err, "Issues arising when processing PNG data"}},
{"invalid-extracted-data", {WarningType::InvalidExtractedData, WarningLevel::Err, "Extracted data does not have correct form"}},
{"missing-segment", {WarningType::MissingSegment, WarningLevel::Warn, "Segment not given in File tag in XML"}},
{"hardcoded-pointer", {WarningType::HardcodedPointer, WarningLevel::Warn, "ZAPD lacks the info to make a symbol, so must output a hardcoded pointer"}},
{"not-implemented", {WarningType::NotImplemented, WarningLevel::Warn, "ZAPD does not currently support this feature"}},
{"unaccounted", {WarningType::Unaccounted, WarningLevel::Off, "Large blocks of unaccounted"}},
{"missing-offsets", {WarningType::MissingOffsets, WarningLevel::Warn, "Offset attribute missing in XML tag"}},
{"intersection", {WarningType::Intersection, WarningLevel::Warn, "Two assets intersect"}},
{"missing-attribute", {WarningType::MissingAttribute, WarningLevel::Warn, "Required attribute missing in XML tag"}},
{"invalid-attribute-value", {WarningType::InvalidAttributeValue, WarningLevel::Err, "Attribute declared in XML is wrong"}},
{"unknown-attribute", {WarningType::UnknownAttribute, WarningLevel::Warn, "Unknown attribute in XML entry tag"}},
{"invalid-xml", {WarningType::InvalidXML, WarningLevel::Err, "XML has syntax errors"}},
{"invalid-jpeg", {WarningType::InvalidJPEG, WarningLevel::Err, "JPEG file does not conform to the game's format requirements"}},
{"invalid-png", {WarningType::InvalidPNG, WarningLevel::Err, "Issues arising when processing PNG data"}},
{"invalid-extracted-data", {WarningType::InvalidExtractedData, WarningLevel::Err, "Extracted data does not have correct form"}},
{"missing-segment", {WarningType::MissingSegment, WarningLevel::Warn, "Segment not given in File tag in XML"}},
{"hardcoded-generic-pointer", {WarningType::HardcodedGenericPointer, WarningLevel::Off, "A generic segmented pointer must be produced"}},
{"hardcoded-pointer", {WarningType::HardcodedPointer, WarningLevel::Warn, "ZAPD lacks the info to make a symbol, so must output a hardcoded pointer"}},
{"not-implemented", {WarningType::NotImplemented, WarningLevel::Warn, "ZAPD does not currently support this feature"}},
};
/**
@ -229,7 +230,10 @@ void WarningHandler::ExtractedFilePreamble(const ZFile *parent, const ZResource*
if (res != nullptr) {
fprintf(stderr, "resource '%s' at ", res->GetName().c_str());
}
fprintf(stderr, "offset 0x%06X: \n\t", offset);
if (offset != static_cast<uint32_t>(-1)) {
fprintf(stderr, "offset 0x%06X:", offset);
}
fprintf(stderr, "\n\t");
}
/**

View File

@ -81,6 +81,7 @@ enum class WarningType
InvalidExtractedData,
MissingSegment,
HardcodedPointer,
HardcodedGenericPointer,
NotImplemented,
Max,
};

View File

@ -249,6 +249,7 @@ mkdir build\ZAPD
<ClCompile Include="ZTextureAnimation.cpp" />
<ClCompile Include="ZVector.cpp" />
<ClCompile Include="ZVtx.cpp" />
<ClCompile Include="ZWaterbox.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\lib\elfio\elfio\elfio.hpp" />
@ -272,6 +273,7 @@ mkdir build\ZAPD
<ClInclude Include="CrashHandler.h" />
<ClInclude Include="CRC32.h" />
<ClInclude Include="Declaration.h" />
<ClInclude Include="ExporterSet.h" />
<ClInclude Include="GameConfig.h" />
<ClInclude Include="Globals.h" />
<ClInclude Include="ImageBackend.h" />
@ -339,6 +341,7 @@ mkdir build\ZAPD
<ClInclude Include="ZTextureAnimation.h" />
<ClInclude Include="ZVector.h" />
<ClInclude Include="ZVtx.h" />
<ClInclude Include="ZWaterbox.h" />
</ItemGroup>
<ItemGroup>
<Text Include="..\SymbolMap_OoTMqDbg.txt">

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
@ -291,6 +291,12 @@
<ClCompile Include="ZSurfaceType.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZActorList.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZWaterbox.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ZRoom\ZRoom.h">
@ -554,6 +560,15 @@
<ClInclude Include="ZSurfaceType.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZActorList.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ExporterSet.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZWaterbox.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="..\SymbolMap_OoTMqDbg.txt">

View File

@ -300,7 +300,7 @@ void ZCurveAnimation::DeclareReferences(const std::string& prefix)
}
else
{
decl->text = entryStr;
decl->declBody = entryStr;
}
}
@ -331,7 +331,7 @@ void ZCurveAnimation::DeclareReferences(const std::string& prefix)
}
else
{
decl->text = entryStr;
decl->declBody = entryStr;
}
}
@ -359,7 +359,7 @@ void ZCurveAnimation::DeclareReferences(const std::string& prefix)
}
else
{
decl->text = entryStr;
decl->declBody = entryStr;
}
}
}

View File

@ -56,7 +56,7 @@ void ZArray::ParseXML(tinyxml2::XMLElement* reader)
}
res->parent = parent;
res->SetInnerNode(true);
res->ExtractFromXML(child, childIndex);
res->ExtractWithXML(child, childIndex);
childIndex += res->GetRawDataSize();
resList.push_back(res);
@ -75,11 +75,11 @@ Declaration* ZArray::DeclareVar(const std::string& prefix, const std::string& bo
if (res->IsExternalResource())
{
auto filepath = Globals::Instance->outputPath / name;
std::string includePath = StringHelper::Sprintf("%s.%s.inc", filepath.c_str(),
std::string includePath = StringHelper::Sprintf("%s.%s.inc", filepath.string().c_str(),
res->GetExternalExtension().c_str());
decl = parent->AddDeclarationIncludeArray(rawDataIndex, includePath, GetRawDataSize(),
GetSourceTypeName(), name, arrayCnt);
decl->text = bodyStr;
decl->declBody = bodyStr;
decl->isExternal = true;
}
else
@ -109,6 +109,7 @@ std::string ZArray::GetBodySourceCode() const
case ZResourceType::Vertex:
case ZResourceType::CollisionPoly:
case ZResourceType::SurfaceType:
case ZResourceType::Waterbox:
output += resList.at(i)->GetBodySourceCode();
break;

View File

@ -132,8 +132,13 @@ Declaration* ZBackground::DeclareVar(const std::string& prefix,
Declaration* decl = parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(),
GetSourceTypeName(), auxName, 0);
decl->arrayItemCntStr = "SCREEN_WIDTH * SCREEN_HEIGHT / 4";
decl->forceArrayCnt = true;
if (Globals::Instance->cfg.useScreenWidthHeightConstants)
{
decl->arrayItemCntStr = "SCREEN_WIDTH * SCREEN_HEIGHT / 4";
decl->forceArrayCnt = true;
}
decl->staticConf = staticConf;
return decl;
}

View File

@ -1,4 +1,5 @@
#include "ZCollision.h"
#include "ZWaterbox.h"
#include <cassert>
#include <cstdint>
@ -50,6 +51,7 @@ void ZCollisionHeader::ParseRawData()
vertices.reserve(numVerts);
polygons.reserve(numPolygons);
waterBoxes.reserve(numWaterBoxes);
offset_t currentPtr = vtxSegmentOffset;
@ -104,31 +106,48 @@ void ZCollisionHeader::ParseRawData()
// - WaterBoxes
// - CollisionHeader
offset_t upperCameraBoundary = polyTypeDefSegmentOffset;
if (upperCameraBoundary == 0)
if (upperCameraBoundary == SEGMENTED_NULL)
{
upperCameraBoundary = polySegmentOffset;
}
if (upperCameraBoundary == 0)
if (upperCameraBoundary == SEGMENTED_NULL)
{
upperCameraBoundary = vtxSegmentOffset;
}
if (upperCameraBoundary == 0)
if (upperCameraBoundary == SEGMENTED_NULL)
{
upperCameraBoundary = waterBoxSegmentOffset;
}
if (upperCameraBoundary == 0)
if (upperCameraBoundary == SEGMENTED_NULL)
{
upperCameraBoundary = rawDataIndex;
}
// Sharp Ocarina places the CamDataEntries above the list so we need to calculate the number
// of cameras differently.
if (upperCameraBoundary < camDataSegmentOffset)
{
offset_t offset = camDataSegmentOffset;
while (rawData[offset] == 0x00 && rawData[offset + 0x4] == 0x02)
{
offset += 0x08;
}
upperCameraBoundary = offset;
}
camData =
new CameraDataList(parent, name, rawData, camDataSegmentOffset, upperCameraBoundary);
}
for (uint16_t i = 0; i < numWaterBoxes; i++)
waterBoxes.push_back(WaterBoxHeader(
rawData,
waterBoxSegmentOffset + (i * (Globals::Instance->game == ZGame::OOT_SW97 ? 12 : 16))));
for (int32_t i = 0; i < numWaterBoxes; i++)
{
ZWaterbox waterbox(parent);
waterbox.SetRawDataIndex(waterBoxSegmentOffset +
(i * (Globals::Instance->game == ZGame::OOT_SW97 ? 12 : 16)));
waterbox.ParseRawData();
waterBoxes.emplace_back(waterbox);
}
}
void ZCollisionHeader::DeclareReferences(const std::string& prefix)
@ -149,9 +168,11 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix)
declaration += "\n";
}
parent->AddDeclarationArray(
waterBoxSegmentOffset, DeclarationAlignment::Align4, 16 * waterBoxes.size(), "WaterBox",
StringHelper::Sprintf("%sWaterBoxes", auxName.c_str()), waterBoxes.size(), declaration);
parent->AddDeclarationArray(waterBoxSegmentOffset, DeclarationAlignment::Align4,
waterBoxes[0].GetRawDataSize() * waterBoxes.size(),
waterBoxes[0].GetSourceTypeName().c_str(),
StringHelper::Sprintf("%sWaterBoxes", auxName.c_str()),
waterBoxes.size(), declaration);
}
if (polygons.size() > 0)
@ -219,11 +240,21 @@ std::string ZCollisionHeader::GetBodySourceCode() const
std::string vtxName;
Globals::Instance->GetSegmentedPtrName(vtxAddress, parent, "Vec3s", vtxName);
declaration += StringHelper::Sprintf("\t%i, %s,\n", numVerts, vtxName.c_str());
if (numVerts > 0)
declaration +=
StringHelper::Sprintf("\tARRAY_COUNT(%s), %s,\n", vtxName.c_str(), vtxName.c_str());
else
declaration += StringHelper::Sprintf("\t%i, %s,\n", numVerts, vtxName.c_str());
std::string polyName;
Globals::Instance->GetSegmentedPtrName(polyAddress, parent, "CollisionPoly", polyName);
declaration += StringHelper::Sprintf("\t%i, %s,\n", numPolygons, polyName.c_str());
if (numPolygons > 0)
declaration +=
StringHelper::Sprintf("\tARRAY_COUNT(%s), %s,\n", polyName.c_str(), polyName.c_str());
else
declaration += StringHelper::Sprintf("\t%i, %s,\n", numPolygons, polyName.c_str());
std::string surfaceName;
Globals::Instance->GetSegmentedPtrName(polyTypeDefAddress, parent, "SurfaceType", surfaceName);
@ -235,7 +266,12 @@ std::string ZCollisionHeader::GetBodySourceCode() const
std::string waterBoxName;
Globals::Instance->GetSegmentedPtrName(waterBoxAddress, parent, "WaterBox", waterBoxName);
declaration += StringHelper::Sprintf("\t%i, %s\n", numWaterBoxes, waterBoxName.c_str());
if (numWaterBoxes > 0)
declaration += StringHelper::Sprintf("\tARRAY_COUNT(%s), %s\n", waterBoxName.c_str(),
waterBoxName.c_str());
else
declaration += StringHelper::Sprintf("\t%i, %s\n", numWaterBoxes, waterBoxName.c_str());
return declaration;
}
@ -260,26 +296,6 @@ size_t ZCollisionHeader::GetRawDataSize() const
return 44;
}
WaterBoxHeader::WaterBoxHeader(const std::vector<uint8_t>& rawData, uint32_t rawDataIndex)
{
xMin = BitConverter::ToInt16BE(rawData, rawDataIndex + 0);
ySurface = BitConverter::ToInt16BE(rawData, rawDataIndex + 2);
zMin = BitConverter::ToInt16BE(rawData, rawDataIndex + 4);
xLength = BitConverter::ToInt16BE(rawData, rawDataIndex + 6);
zLength = BitConverter::ToInt16BE(rawData, rawDataIndex + 8);
if (Globals::Instance->game == ZGame::OOT_SW97)
properties = BitConverter::ToInt16BE(rawData, rawDataIndex + 10);
else
properties = BitConverter::ToInt32BE(rawData, rawDataIndex + 12);
}
std::string WaterBoxHeader::GetBodySourceCode() const
{
return StringHelper::Sprintf("%i, %i, %i, %i, %i, 0x%08X", xMin, ySurface, zMin, xLength,
zLength, properties);
}
CameraDataList::CameraDataList(ZFile* parent, const std::string& prefix,
const std::vector<uint8_t>& rawData, offset_t rawDataIndex,
offset_t upperCameraBoundary)
@ -291,46 +307,63 @@ CameraDataList::CameraDataList(ZFile* parent, const std::string& prefix,
assert(numElements < 10000);
offset_t cameraPosDataSeg = rawDataIndex;
uint32_t numDataTotal;
uint32_t cameraPosDataSegEnd = rawDataIndex;
bool isSharpOcarina = false;
for (size_t i = 0; i < numElements; i++)
{
CameraDataEntry* entry = new CameraDataEntry();
CameraDataEntry entry;
entry->cameraSType =
entry.cameraSType =
BitConverter::ToInt16BE(rawData, rawDataIndex + (entries.size() * 8) + 0);
entry->numData = BitConverter::ToInt16BE(rawData, rawDataIndex + (entries.size() * 8) + 2);
entry->cameraPosDataSeg =
entry.numData = BitConverter::ToInt16BE(rawData, rawDataIndex + (entries.size() * 8) + 2);
entry.cameraPosDataSeg =
BitConverter::ToInt32BE(rawData, rawDataIndex + (entries.size() * 8) + 4);
if (entry->cameraPosDataSeg != 0 && GETSEGNUM(entry->cameraPosDataSeg) != SEGMENT_SCENE)
if (entry.cameraPosDataSeg != 0 && GETSEGNUM(entry.cameraPosDataSeg) != SEGMENT_SCENE)
{
cameraPosDataSeg = rawDataIndex + (entries.size() * 8);
break;
}
if (entry->cameraPosDataSeg != 0 && cameraPosDataSeg > (entry->cameraPosDataSeg & 0xFFFFFF))
cameraPosDataSeg = (entry->cameraPosDataSeg & 0xFFFFFF);
if (rawDataIndex > GETSEGOFFSET(entry.cameraPosDataSeg))
{
if (entry.cameraPosDataSeg != 0 &&
cameraPosDataSeg > GETSEGOFFSET(entry.cameraPosDataSeg))
cameraPosDataSeg = GETSEGOFFSET(entry.cameraPosDataSeg);
}
else
{
// Sharp Ocarina will place the cam data after the list as opposed to the original maps
// which have it before.
isSharpOcarina = true;
cameraPosDataSeg = rawDataIndex + (numElements * 0x8);
if (cameraPosDataSegEnd < GETSEGOFFSET(entry.cameraPosDataSeg))
cameraPosDataSegEnd = GETSEGOFFSET(entry.cameraPosDataSeg);
}
entries.push_back(entry);
entries.emplace_back(entry);
}
// Setting cameraPosDataAddr to rawDataIndex give a pos list length of 0
uint32_t cameraPosDataOffset = cameraPosDataSeg & 0xFFFFFF;
uint32_t cameraPosDataOffset = GETSEGOFFSET(cameraPosDataSeg);
for (size_t i = 0; i < entries.size(); i++)
{
char camSegLine[2048];
if (entries[i]->cameraPosDataSeg != 0)
if (entries[i].cameraPosDataSeg != 0)
{
int32_t index =
((entries[i]->cameraPosDataSeg & 0x00FFFFFF) - cameraPosDataOffset) / 0x6;
sprintf(camSegLine, "&%sCamPosData[%i]", prefix.c_str(), index);
uint32_t index =
(GETSEGOFFSET(entries[i].cameraPosDataSeg) - cameraPosDataOffset) / 0x6;
snprintf(camSegLine, 2048, "&%sCamPosData[%i]", prefix.c_str(), index);
}
else
sprintf(camSegLine, "NULL");
snprintf(camSegLine, 2048, "NULL");
declaration +=
StringHelper::Sprintf(" { 0x%04X, %i, %s },", entries[i]->cameraSType,
entries[i]->numData, camSegLine, rawDataIndex + (i * 8));
StringHelper::Sprintf(" { 0x%04X, %i, %s },", entries[i].cameraSType,
entries[i].numData, camSegLine, rawDataIndex + (i * 8));
if (i < entries.size() - 1)
declaration += "\n";
@ -341,23 +374,26 @@ CameraDataList::CameraDataList(ZFile* parent, const std::string& prefix,
StringHelper::Sprintf("%sCamDataList", prefix.c_str(), rawDataIndex), entries.size(),
declaration);
uint32_t numDataTotal = (rawDataIndex - cameraPosDataOffset) / 0x6;
if (!isSharpOcarina)
numDataTotal = (rawDataIndex - cameraPosDataOffset) / 0x6;
else
numDataTotal = ((cameraPosDataSegEnd - cameraPosDataSeg) + 18) / 0x6;
if (numDataTotal > 0)
{
declaration.clear();
cameraPositionData.reserve(numDataTotal);
for (uint32_t i = 0; i < numDataTotal; i++)
{
CameraPositionData* data =
new CameraPositionData(rawData, cameraPosDataOffset + (i * 6));
cameraPositionData.push_back(data);
CameraPositionData data = CameraPositionData(rawData, cameraPosDataOffset + (i * 6));
declaration += StringHelper::Sprintf("\t{ %6i, %6i, %6i },", data->x, data->y, data->z);
declaration += StringHelper::Sprintf("\t{ %6i, %6i, %6i },", data.x, data.y, data.z);
cameraPositionData.emplace_back(data);
if (i + 1 < numDataTotal)
declaration += "\n";
}
int32_t cameraPosDataIndex = GETSEGOFFSET(cameraPosDataSeg);
uint32_t cameraPosDataIndex = GETSEGOFFSET(cameraPosDataSeg);
uint32_t entrySize = numDataTotal * 0x6;
parent->AddDeclarationArray(cameraPosDataIndex, DeclarationAlignment::Align4, entrySize,
"Vec3s", StringHelper::Sprintf("%sCamPosData", prefix.c_str()),
@ -367,11 +403,6 @@ CameraDataList::CameraDataList(ZFile* parent, const std::string& prefix,
CameraDataList::~CameraDataList()
{
for (auto entry : entries)
delete entry;
for (auto camPosData : cameraPositionData)
delete camPosData;
}
CameraPositionData::CameraPositionData(const std::vector<uint8_t>& rawData, uint32_t rawDataIndex)

View File

@ -6,23 +6,7 @@
#include "ZRoom/ZRoom.h"
#include "ZSurfaceType.h"
#include "ZVector.h"
class WaterBoxHeader
{
public:
WaterBoxHeader(const std::vector<uint8_t>& rawData, uint32_t rawDataIndex);
std::string GetBodySourceCode() const;
protected:
int16_t xMin;
int16_t ySurface;
int16_t zMin;
int16_t xLength;
int16_t zLength;
int16_t pad;
int32_t properties;
};
#include "ZWaterbox.h"
class CameraPositionData
{
@ -37,14 +21,14 @@ class CameraDataEntry
public:
int16_t cameraSType;
int16_t numData;
int32_t cameraPosDataSeg;
offset_t cameraPosDataSeg;
};
class CameraDataList
{
public:
std::vector<CameraDataEntry*> entries;
std::vector<CameraPositionData*> cameraPositionData;
std::vector<CameraDataEntry> entries;
std::vector<CameraPositionData> cameraPositionData;
CameraDataList(ZFile* parent, const std::string& prefix, const std::vector<uint8_t>& rawData,
offset_t rawDataIndex, offset_t upperCameraBoundary);
@ -72,7 +56,7 @@ public:
std::vector<ZVector> vertices;
std::vector<ZCollisionPoly> polygons;
std::vector<ZSurfaceType> polygonTypes;
std::vector<WaterBoxHeader> waterBoxes;
std::vector<ZWaterbox> waterBoxes;
CameraDataList* camData = nullptr;
ZCollisionHeader(ZFile* nParent);

View File

@ -231,6 +231,7 @@ CutsceneCommand* ZCutscene::GetCommandOoT(uint32_t id, offset_t currentPtr) cons
case 142:
case 62: // CutsceneCommands::SetActorAction9
case 143: // CutsceneCommands::SetActorAction10
case 74:
return new CutsceneCommand_ActorAction(rawData, currentPtr);
case 0x0B:
@ -249,7 +250,6 @@ CutsceneCommand* ZCutscene::GetCommandOoT(uint32_t id, offset_t currentPtr) cons
case 0x16:
case 0x70:
case 0x71:
case 0x4A:
return new CutsceneCommand_GenericCmd(rawData, currentPtr, cmdID);
}

View File

@ -40,7 +40,7 @@ ZDisplayList::~ZDisplayList()
}
// EXTRACT MODE
void ZDisplayList::ExtractFromXML(tinyxml2::XMLElement* reader, uint32_t nRawDataIndex)
void ZDisplayList::ExtractWithXML(tinyxml2::XMLElement* reader, uint32_t nRawDataIndex)
{
rawDataIndex = nRawDataIndex;
ParseXML(reader);
@ -708,7 +708,7 @@ void ZDisplayList::Opcode_G_DL(uint64_t data, const std::string& prefix, char* l
if (!Globals::Instance->HasSegment(segNum))
sprintf(line, "gsSPBranchList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
else if (dListDecl != nullptr)
sprintf(line, "gsSPBranchList(%s),", dListDecl->varName.c_str());
sprintf(line, "gsSPBranchList(%s),", dListDecl->declName.c_str());
else
sprintf(line, "gsSPBranchList(%sDlist0x%06" PRIX64 "),", prefix.c_str(),
GETSEGOFFSET(data));
@ -718,7 +718,7 @@ void ZDisplayList::Opcode_G_DL(uint64_t data, const std::string& prefix, char* l
if (!Globals::Instance->HasSegment(segNum))
sprintf(line, "gsSPDisplayList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
else if (dListDecl != nullptr)
sprintf(line, "gsSPDisplayList(%s),", dListDecl->varName.c_str());
sprintf(line, "gsSPDisplayList(%s),", dListDecl->declName.c_str());
else
sprintf(line, "gsSPDisplayList(%sDlist0x%06" PRIX64 "),", prefix.c_str(),
GETSEGOFFSET(data));
@ -958,7 +958,7 @@ void ZDisplayList::Opcode_G_SETTIMG(uint64_t data, const std::string& prefix, ch
}
if (texDecl != nullptr)
sprintf(texStr, "%s", texDecl->varName.c_str());
sprintf(texStr, "%s", texDecl->declName.c_str());
else if (data != 0 && Globals::Instance->HasSegment(segmentNumber))
sprintf(texStr, "%sTex_%06X", prefix.c_str(), texAddress);
else
@ -1642,7 +1642,14 @@ static int32_t GfxdCallback_Vtx(uint32_t seg, int32_t count)
vtxList.push_back(vtx);
currentPtr += 16;
}
self->vertices[vtxOffset] = vtxList;
bool keyAlreadyOccupied = self->vertices.find(vtxOffset) != self->vertices.end();
// In some cases a vtxList already exists at vtxOffset. Only override the existing list
// if the new one is bigger.
if (!keyAlreadyOccupied ||
(keyAlreadyOccupied && vtxList.size() > self->vertices[vtxOffset].size()))
self->vertices[vtxOffset] = vtxList;
}
}
@ -1708,17 +1715,26 @@ static int32_t GfxdCallback_DisplayList(uint32_t seg)
uint32_t dListSegNum = GETSEGNUM(seg);
std::string dListName = "";
bool addressFound = Globals::Instance->GetSegmentedPtrName(seg, self->parent, "Gfx", dListName);
bool addressFound =
Globals::Instance->GetSegmentedPtrName(seg, self->parent, "Gfx", dListName, false);
if (!addressFound && self->parent->segment == dListSegNum)
if (!addressFound)
{
ZDisplayList* newDList = new ZDisplayList(self->parent);
newDList->ExtractFromBinary(
dListOffset,
self->GetDListLength(self->parent->GetRawData(), dListOffset, self->dListType));
newDList->SetName(newDList->GetDefaultName(self->parent->GetName()));
self->otherDLists.push_back(newDList);
dListName = newDList->GetName();
if (self->parent->segment == dListSegNum)
{
ZDisplayList* newDList = new ZDisplayList(self->parent);
newDList->ExtractFromBinary(
dListOffset,
self->GetDListLength(self->parent->GetRawData(), dListOffset, self->dListType));
newDList->SetName(newDList->GetDefaultName(self->parent->GetName()));
self->otherDLists.push_back(newDList);
dListName = newDList->GetName();
}
else
{
Globals::Instance->WarnHardcodedPointer(seg, self->parent, self,
self->GetRawDataIndex());
}
}
gfxd_puts(dListName.c_str());
@ -1731,21 +1747,31 @@ static int32_t GfxdCallback_Matrix(uint32_t seg)
std::string mtxName;
ZDisplayList* self = static_cast<ZDisplayList*>(gfxd_udata_get());
bool addressFound = Globals::Instance->GetSegmentedPtrName(seg, self->parent, "Mtx", mtxName);
if (!addressFound && GETSEGNUM(seg) == self->parent->segment)
{
Declaration* decl =
self->parent->GetDeclaration(Seg2Filespace(seg, self->parent->baseAddress));
if (decl == nullptr)
{
ZMtx mtx(self->parent);
mtx.SetName(mtx.GetDefaultName(self->GetName()));
mtx.ExtractFromFile(Seg2Filespace(seg, self->parent->baseAddress));
mtx.DeclareVar(self->GetName(), "");
bool addressFound =
Globals::Instance->GetSegmentedPtrName(seg, self->parent, "Mtx", mtxName, false);
mtx.GetSourceOutputCode(self->GetName());
self->mtxList.push_back(mtx);
mtxName = "&" + mtx.GetName();
if (!addressFound)
{
if (GETSEGNUM(seg) == self->parent->segment)
{
Declaration* decl =
self->parent->GetDeclaration(Seg2Filespace(seg, self->parent->baseAddress));
if (decl == nullptr)
{
ZMtx mtx(self->parent);
mtx.SetName(mtx.GetDefaultName(self->GetName()));
mtx.ExtractFromFile(Seg2Filespace(seg, self->parent->baseAddress));
mtx.DeclareVar(self->GetName(), "");
mtx.GetSourceOutputCode(self->GetName());
self->mtxList.push_back(mtx);
mtxName = "&" + mtx.GetName();
}
}
else
{
Globals::Instance->WarnHardcodedPointer(seg, self->parent, self,
self->GetRawDataIndex());
}
}
@ -1870,7 +1896,8 @@ void ZDisplayList::DeclareReferences(const std::string& prefix)
vtxName = StringHelper::Sprintf("%sVtx_%06X", prefix.c_str(), vtxKeys[i]);
auto filepath = Globals::Instance->outputPath / vtxName;
std::string incStr = StringHelper::Sprintf("%s.%s.inc", filepath.c_str(), "vtx");
std::string incStr =
StringHelper::Sprintf("%s.%s.inc", filepath.string().c_str(), "vtx");
Declaration* vtxDecl = parent->AddDeclarationIncludeArray(
vtxKeys[i], incStr, item.size() * 16, "Vtx", vtxName, item.size());
@ -1954,9 +1981,46 @@ std::string ZDisplayList::ProcessGfxDis([[maybe_unused]] const std::string& pref
gfxd_execute(); // generate display list
sourceOutput += outputformatter.GetOutput(); // write formatted display list
MergeConnectingVertexLists();
return sourceOutput;
}
void ZDisplayList::MergeConnectingVertexLists()
{
if (vertices.size() > 0)
{
std::vector<std::pair<uint32_t, std::vector<ZVtx>>> vertexKeys(vertices.begin(),
vertices.end());
std::pair<uint32_t, std::vector<ZVtx>> lastItem = vertexKeys.at(0);
for (size_t i = 1; i < vertexKeys.size(); i++)
{
std::pair<uint32_t, std::vector<ZVtx>> curItem = vertexKeys[i];
size_t lastItemEnd = lastItem.first + (lastItem.second.size() * 16);
bool lastItemIntersects = lastItemEnd >= curItem.first;
if (lastItemIntersects)
{
int intersectedVtxStart = (lastItemEnd - curItem.first) / 16;
for (size_t j = intersectedVtxStart; j < curItem.second.size(); j++)
vertices[lastItem.first].push_back(curItem.second[j]);
vertices.erase(curItem.first);
vertexKeys.erase(vertexKeys.begin() + i);
lastItem.second = vertices[lastItem.first];
i--;
}
else
lastItem = curItem;
}
}
}
void ZDisplayList::TextureGenCheck()
{
if (TextureGenCheck(lastTexWidth, lastTexHeight, lastTexAddr, lastTexSeg, lastTexFmt,

View File

@ -346,7 +346,7 @@ public:
ZDisplayList(ZFile* nParent);
~ZDisplayList();
void ExtractFromXML(tinyxml2::XMLElement* reader, uint32_t nRawDataIndex) override;
void ExtractWithXML(tinyxml2::XMLElement* reader, uint32_t nRawDataIndex) override;
void ExtractFromBinary(uint32_t nRawDataIndex, int32_t rawDataSize);
void ParseRawData() override;
@ -367,6 +367,9 @@ public:
std::string ProcessLegacy(const std::string& prefix);
std::string ProcessGfxDis(const std::string& prefix);
// Combines vertex lists from the vertices map which touch or intersect
void MergeConnectingVertexLists();
bool IsExternalResource() const override;
std::string GetExternalExtension() const override;
std::string GetSourceTypeName() const override;

View File

@ -181,6 +181,12 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
}
}
const char* segmentDefines = reader->Attribute("Defines");
if (segmentDefines != NULL)
{
makeDefines = true;
}
if (mode == ZFileMode::Extract || mode == ZFileMode::ExternalFile)
{
if (!File::Exists((basePath / name).string()))
@ -213,14 +219,12 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
// Check for repeated attributes.
if (offsetXml != nullptr)
{
std::string offsetStr = StringHelper::Split(offsetXml, "0x")[1];
if (!StringHelper::HasOnlyHexDigits(offsetStr))
if (!StringHelper::IsValidOffset(std::string_view(offsetXml)))
{
HANDLE_ERROR(WarningType::InvalidXML,
StringHelper::Sprintf("Invalid offset %s entered", offsetStr.c_str()),
"");
StringHelper::Sprintf("Invalid offset %s entered", offsetXml), "");
}
rawDataIndex = strtol(offsetStr.c_str(), NULL, 16);
rawDataIndex = strtol(offsetXml, NULL, 16);
if (offsetSet.find(offsetXml) != offsetSet.end())
{
@ -268,7 +272,7 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
ZResource* nRes = nodeMap[nodeName](this);
if (mode == ZFileMode::Extract || mode == ZFileMode::ExternalFile)
nRes->ExtractFromXML(child, rawDataIndex);
nRes->ExtractWithXML(child, rawDataIndex);
switch (nRes->GetResourceType())
{
@ -442,24 +446,25 @@ Declaration* ZFile::AddDeclaration(offset_t address, DeclarationAlignment alignm
const std::string& varType, const std::string& varName,
const std::string& body)
{
bool validOffset = AddDeclarationChecks(address, varName);
bool validOffset = DeclarationSanityChecks(address, varName);
if (!validOffset)
return nullptr;
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
decl = new Declaration(address, alignment, size, varType, varName, false, body);
decl = Declaration::Create(address, alignment, size, varType, varName, body);
declarations[address] = decl;
}
else
{
decl->alignment = alignment;
decl->size = size;
decl->varType = varType;
decl->varName = varName;
decl->text = body;
decl->declType = varType;
decl->declName = varName;
decl->declBody = body;
}
return decl;
}
@ -468,27 +473,29 @@ Declaration* ZFile::AddDeclarationArray(offset_t address, DeclarationAlignment a
const std::string& varName, size_t arrayItemCnt,
const std::string& body)
{
bool validOffset = AddDeclarationChecks(address, varName);
bool validOffset = DeclarationSanityChecks(address, varName);
if (!validOffset)
return nullptr;
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
decl =
new Declaration(address, alignment, size, varType, varName, true, arrayItemCnt, body);
decl = Declaration::CreateArray(address, alignment, size, varType, varName, body,
arrayItemCnt);
declarations[address] = decl;
}
else
{
if (decl->isPlaceholder)
decl->varName = varName;
decl->declName = varName;
decl->alignment = alignment;
decl->size = size;
decl->varType = varType;
decl->declType = varType;
decl->isArray = true;
decl->arrayItemCnt = arrayItemCnt;
decl->text = body;
decl->declBody = body;
}
return decl;
@ -499,41 +506,41 @@ Declaration* ZFile::AddDeclarationArray(offset_t address, DeclarationAlignment a
const std::string& varName,
const std::string& arrayItemCntStr, const std::string& body)
{
bool validOffset = AddDeclarationChecks(address, varName);
bool validOffset = DeclarationSanityChecks(address, varName);
if (!validOffset)
return nullptr;
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
decl = new Declaration(address, alignment, size, varType, varName, true, arrayItemCntStr,
body);
decl = Declaration::CreateArray(address, alignment, size, varType, varName, body,
arrayItemCntStr);
declarations[address] = decl;
}
else
{
decl->alignment = alignment;
decl->size = size;
decl->varType = varType;
decl->varName = varName;
decl->declType = varType;
decl->declName = varName;
decl->isArray = true;
decl->arrayItemCntStr = arrayItemCntStr;
decl->text = body;
decl->declBody = body;
}
return decl;
}
Declaration* ZFile::AddDeclarationPlaceholder(offset_t address, const std::string& varName)
{
bool validOffset = AddDeclarationChecks(address, varName);
bool validOffset = DeclarationSanityChecks(address, varName);
if (!validOffset)
return nullptr;
Declaration* decl;
if (declarations.find(address) == declarations.end())
{
decl = new Declaration(address, DeclarationAlignment::Align4, 0, "", varName, false, "");
decl->isPlaceholder = true;
decl = Declaration::CreatePlaceholder(address, varName);
declarations[address] = decl;
}
else
@ -546,22 +553,22 @@ Declaration* ZFile::AddDeclarationInclude(offset_t address, const std::string& i
size_t size, const std::string& varType,
const std::string& varName)
{
bool validOffset = AddDeclarationChecks(address, varName);
bool validOffset = DeclarationSanityChecks(address, varName);
if (!validOffset)
return nullptr;
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
decl = new Declaration(address, includePath, size, varType, varName);
decl = Declaration::CreateInclude(address, includePath, size, varType, varName);
declarations[address] = decl;
}
else
{
decl->includePath = includePath;
decl->size = size;
decl->varType = varType;
decl->varName = varName;
decl->declType = varType;
decl->declName = varName;
}
return decl;
}
@ -570,7 +577,7 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in
size_t size, const std::string& varType,
const std::string& varName, size_t arrayItemCnt)
{
bool validOffset = AddDeclarationChecks(address, varName);
bool validOffset = DeclarationSanityChecks(address, varName);
if (!validOffset)
return nullptr;
@ -582,7 +589,7 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
decl = new Declaration(address, includePath, size, varType, varName);
decl = Declaration::CreateInclude(address, includePath, size, varType, varName);
decl->isArray = true;
decl->arrayItemCnt = arrayItemCnt;
@ -592,8 +599,8 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in
else
{
decl->includePath = includePath;
decl->varType = varType;
decl->varName = varName;
decl->declType = varType;
decl->declName = varName;
decl->size = size;
decl->isArray = true;
decl->arrayItemCnt = arrayItemCnt;
@ -601,7 +608,44 @@ Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& in
return decl;
}
bool ZFile::AddDeclarationChecks(uint32_t address, const std::string& varName)
Declaration* ZFile::AddDeclarationIncludeArray(offset_t address, std::string& includePath,
size_t size, const std::string& varType,
const std::string& varName,
const std::string& defines, size_t arrayItemCnt)
{
bool validOffset = DeclarationSanityChecks(address, varName);
if (!validOffset)
return nullptr;
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];
Declaration* decl = GetDeclaration(address);
if (decl == nullptr)
{
decl = Declaration::CreateInclude(address, includePath, size, varType, varName, defines);
decl->isArray = true;
decl->arrayItemCnt = arrayItemCnt;
declarations[address] = decl;
}
else
{
decl->includePath = includePath;
decl->declType = varType;
decl->declName = varName;
decl->defines = defines;
decl->size = size;
decl->isArray = true;
decl->arrayItemCnt = arrayItemCnt;
}
return decl;
}
bool ZFile::DeclarationSanityChecks(uint32_t address, const std::string& varName)
{
assert(GETSEGNUM(address) == 0);
assert(varName != "");
@ -645,7 +689,7 @@ bool ZFile::GetDeclarationPtrName(segptr_t segAddress, const std::string& expect
if (expectedType != "" && expectedType != "void*")
{
if (expectedType != decl->varType && "static " + expectedType != decl->varType)
if (expectedType != decl->declType && "static " + expectedType != decl->declType)
{
declName = StringHelper::Sprintf("0x%08X", segAddress);
return false;
@ -653,9 +697,9 @@ bool ZFile::GetDeclarationPtrName(segptr_t segAddress, const std::string& expect
}
if (!decl->isArray)
declName = "&" + decl->varName;
declName = "&" + decl->declName;
else
declName = decl->varName;
declName = decl->declName;
return true;
}
@ -679,7 +723,7 @@ bool ZFile::GetDeclarationArrayIndexedName(segptr_t segAddress, size_t elementSi
if (expectedType != "" && expectedType != "void*")
{
if (expectedType != decl->varType && "static " + expectedType != decl->varType)
if (expectedType != decl->declType && "static " + expectedType != decl->declType)
{
declName = StringHelper::Sprintf("0x%08X", segAddress);
return false;
@ -688,7 +732,7 @@ bool ZFile::GetDeclarationArrayIndexedName(segptr_t segAddress, size_t elementSi
if (decl->address == address)
{
declName = decl->varName;
declName = decl->declName;
return true;
}
@ -699,7 +743,7 @@ bool ZFile::GetDeclarationArrayIndexedName(segptr_t segAddress, size_t elementSi
}
uint32_t index = (address - decl->address) / elementSize;
declName = StringHelper::Sprintf("&%s[%u]", decl->varName.c_str(), index);
declName = StringHelper::Sprintf("&%s[%u]", decl->declName.c_str(), index);
return true;
}
@ -728,6 +772,20 @@ bool ZFile::HasDeclaration(offset_t address)
return declarations.find(address) != declarations.end();
}
size_t ZFile::GetDeclarationSizeFromNeighbor(uint32_t declarationAddress)
{
auto currentDecl = declarations.find(declarationAddress);
if (currentDecl == declarations.end())
return 0;
auto nextDecl = currentDecl;
std::advance(nextDecl, 1);
if (nextDecl == declarations.end())
return GetRawData().size() - currentDecl->first;
return nextDecl->first - currentDecl->first;
}
void ZFile::GenerateSourceFiles()
{
std::string sourceOutput;
@ -817,8 +875,8 @@ void ZFile::GenerateSourceHeaderFiles()
std::string ZFile::GetHeaderInclude() const
{
std::string headers = StringHelper::Sprintf("#include \"%s.h\"\n",
(outName.parent_path() / outName.stem()).c_str());
std::string headers = StringHelper::Sprintf(
"#include \"%s.h\"\n", (outName.parent_path() / outName.stem()).string().c_str());
return headers;
}
@ -843,16 +901,12 @@ std::string ZFile::GetExternalFileHeaderInclude() const
{
fs::path outputFolderPath = externalFile->GetSourceOutputFolderPath();
if (outputFolderPath == this->GetSourceOutputFolderPath())
{
outputFolderPath = externalFile->outName.stem();
}
else
{
outputFolderPath /= externalFile->outName.stem();
}
externalFilesIncludes +=
StringHelper::Sprintf("#include \"%s.h\"\n", outputFolderPath.c_str());
StringHelper::Sprintf("#include \"%s.h\"\n", outputFolderPath.string().c_str());
}
}
@ -967,46 +1021,7 @@ std::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...
std::vector<std::pair<int32_t, Declaration*>> declarationKeys(declarations.begin(),
declarations.end());
std::pair<int32_t, Declaration*> lastItem = declarationKeys.at(0);
for (size_t i = 1; i < declarationKeys.size(); i++)
{
std::pair<int32_t, Declaration*> curItem = declarationKeys[i];
if (curItem.second->isArray && lastItem.second->isArray)
{
if (curItem.second->varType == lastItem.second->varType)
{
if (!curItem.second->declaredInXml && !lastItem.second->declaredInXml)
{
// TEST: For now just do Vtx declarations...
if (lastItem.second->varType == "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);
delete curItem.second;
i--;
continue;
}
}
}
}
}
lastItem = curItem;
}
MergeNeighboringDeclarations();
for (std::pair<uint32_t, Declaration*> item : declarations)
ProcessDeclarationText(item.second);
@ -1041,20 +1056,20 @@ std::string ZFile::ProcessDeclarations()
// HACK
std::string extType;
if (item.second->varType == "Gfx")
if (item.second->declType == "Gfx")
extType = "dlist";
else if (item.second->varType == "Vtx")
else if (item.second->declType == "Vtx")
extType = "vtx";
auto filepath = outputPath / item.second->varName;
auto filepath = outputPath / item.second->declName;
File::WriteAllText(
StringHelper::Sprintf("%s.%s.inc", filepath.c_str(), extType.c_str()),
item.second->text);
StringHelper::Sprintf("%s.%s.inc", filepath.string().c_str(), extType.c_str()),
item.second->declBody);
}
output += item.second->GetExternalDeclarationStr();
}
else if (item.second->varType != "")
else if (item.second->declType != "")
{
output += item.second->GetNormalDeclarationStr();
}
@ -1063,6 +1078,50 @@ std::string ZFile::ProcessDeclarations()
return output;
}
void ZFile::MergeNeighboringDeclarations()
{
// Optimization: See if there are any arrays side by side that can be merged...
std::vector<std::pair<int32_t, Declaration*>> declarationKeys(declarations.begin(),
declarations.end());
std::pair<int32_t, Declaration*> lastItem = declarationKeys.at(0);
for (size_t i = 1; i < declarationKeys.size(); i++)
{
std::pair<int32_t, Declaration*> curItem = declarationKeys[i];
if (curItem.second->isArray && lastItem.second->isArray)
{
if (curItem.second->declType == lastItem.second->declType)
{
if (!curItem.second->declaredInXml && !lastItem.second->declaredInXml)
{
// TEST: For now just do Vtx declarations...
if (lastItem.second->declType == "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->declBody += "\n" + curItem.second->declBody;
declarations.erase(curItem.first);
declarationKeys.erase(declarationKeys.begin() + i);
delete curItem.second;
i--;
continue;
}
}
}
}
}
lastItem = curItem;
}
}
void ZFile::ProcessDeclarationText(Declaration* decl)
{
size_t refIndex = 0;
@ -1070,17 +1129,17 @@ void ZFile::ProcessDeclarationText(Declaration* decl)
if (!(decl->references.size() > 0))
return;
for (size_t i = 0; i < decl->text.size() - 1; i++)
for (size_t i = 0; i < decl->declBody.size() - 1; i++)
{
char c = decl->text[i];
char c2 = decl->text[i + 1];
char c = decl->declBody[i];
char c2 = decl->declBody[i + 1];
if (c == '@' && c2 == 'r')
{
std::string vtxName;
Globals::Instance->GetSegmentedArrayIndexedName(decl->references[refIndex], 0x10, this,
"Vtx", vtxName);
decl->text.replace(i, 2, vtxName);
decl->declBody.replace(i, 2, vtxName);
refIndex++;
@ -1092,7 +1151,8 @@ void ZFile::ProcessDeclarationText(Declaration* decl)
std::string ZFile::ProcessExterns()
{
std::string output;
std::string output = "";
bool hadDefines = true; // Previous declaration included defines.
for (const auto& item : declarations)
{
@ -1101,10 +1161,21 @@ std::string ZFile::ProcessExterns()
continue;
}
std::string itemDefines = item.second->GetDefinesStr();
// Add a newline above if previous has no defines and this one does.
if (!hadDefines && (itemDefines.length() > 0))
{
output.push_back('\n');
}
output += item.second->GetExternStr();
}
output += itemDefines;
output += "\n";
// Newline below if this one has defines.
if ((hadDefines = (itemDefines.length() > 0)))
{
output.push_back('\n');
}
}
output += defines;
@ -1153,7 +1224,7 @@ std::string ZFile::ProcessTextureIntersections([[maybe_unused]] const std::strin
if (nextDecl == nullptr)
texNextName = texturesResources.at(nextOffset)->GetName();
else
texNextName = nextDecl->varName;
texNextName = nextDecl->declName;
defines += StringHelper::Sprintf("#define %s ((u32)%s + 0x%06X)\n",
texNextName.c_str(), texName.c_str(), offsetDiff);
@ -1226,8 +1297,8 @@ bool ZFile::HandleUnaccountedAddress(offset_t currentAddress, offset_t lastAddr,
std::string intersectionInfo = StringHelper::Sprintf(
"Resource from 0x%06X:0x%06X (%s) conflicts with 0x%06X (%s).", lastAddr,
lastAddr + lastSize, lastDecl->varName.c_str(), currentAddress,
currentDecl->varName.c_str());
lastAddr + lastSize, lastDecl->declName.c_str(), currentAddress,
currentDecl->declName.c_str());
HANDLE_WARNING_RESOURCE(WarningType::Intersection, this, nullptr, currentAddress,
"intersection detected", intersectionInfo);
}

View File

@ -38,6 +38,8 @@ public:
uint32_t segment = 0x80;
uint32_t baseAddress, rangeStart, rangeEnd;
bool isExternalFile = false;
// Whether to make defines for texture dimensions, and possibly more in future
bool makeDefines = false;
ZFile(const fs::path& nOutPath, const std::string& nName);
ZFile(ZFileMode nMode, tinyxml2::XMLElement* reader, const fs::path& nBasePath,
@ -74,6 +76,9 @@ public:
Declaration* AddDeclarationIncludeArray(offset_t address, std::string& includePath, size_t size,
const std::string& varType, const std::string& varName,
size_t arrayItemCnt);
Declaration* AddDeclarationIncludeArray(offset_t address, std::string& includePath, size_t size,
const std::string& varType, const std::string& varName,
const std::string& defines, size_t arrayItemCnt);
bool GetDeclarationPtrName(segptr_t segAddress, const std::string& expectedType,
std::string& declName) const;
@ -84,6 +89,7 @@ public:
Declaration* GetDeclaration(offset_t address) const;
Declaration* GetDeclarationRanged(offset_t address) const;
bool HasDeclaration(offset_t address);
size_t GetDeclarationSizeFromNeighbor(uint32_t declarationAddress);
std::string GetHeaderInclude() const;
std::string GetZRoomHeaderInclude() const;
@ -126,8 +132,9 @@ protected:
void DeclareResourceSubReferences();
void GenerateSourceFiles();
void GenerateSourceHeaderFiles();
bool AddDeclarationChecks(uint32_t address, const std::string& varName);
bool DeclarationSanityChecks(uint32_t address, const std::string& varName);
std::string ProcessDeclarations();
void MergeNeighboringDeclarations();
void ProcessDeclarationText(Declaration* decl);
std::string ProcessExterns();

View File

@ -394,7 +394,7 @@ void ZLimb::DeclareDList(segptr_t dListSegmentedPtr, const std::string& prefix,
std::string dlistName;
bool declFound = Globals::Instance->GetSegmentedArrayIndexedName(dListSegmentedPtr, 8, parent,
"Gfx", dlistName);
"Gfx", dlistName, false);
if (declFound)
return;

View File

@ -6,7 +6,8 @@
#include "WarningHandler.h"
#include "ZFile.h"
REGISTER_ZFILENODE(Path, ZPath);
REGISTER_ZFILENODE(Path, ZPath); // Old name that is being kept for backwards compatability
REGISTER_ZFILENODE(PathList, ZPath); // New name that may be used in future XMLs
ZPath::ZPath(ZFile* nParent) : ZResource(nParent)
{
@ -144,8 +145,8 @@ void PathwayEntry::DeclareReferences(const std::string& prefix)
return;
std::string pointsName;
bool addressFound =
Globals::Instance->GetSegmentedPtrName(listSegmentAddress, parent, "Vec3s", pointsName);
bool addressFound = Globals::Instance->GetSegmentedPtrName(listSegmentAddress, parent, "Vec3s",
pointsName, false);
if (addressFound)
return;
@ -172,7 +173,7 @@ void PathwayEntry::DeclareReferences(const std::string& prefix)
points.size(), declaration);
}
else
decl->text = declaration;
decl->declBody = declaration;
}
std::string PathwayEntry::GetBodySourceCode() const
@ -185,7 +186,13 @@ std::string PathwayEntry::GetBodySourceCode() const
declaration +=
StringHelper::Sprintf("%i, %i, %i, %s", numPoints, unk1, unk2, listName.c_str());
else
declaration += StringHelper::Sprintf("%i, %s", numPoints, listName.c_str());
{
if (numPoints > 0)
declaration +=
StringHelper::Sprintf("ARRAY_COUNT(%s), %s", listName.c_str(), listName.c_str());
else
declaration += StringHelper::Sprintf("%i, %s", numPoints, listName.c_str());
}
return declaration;
}

View File

@ -32,7 +32,7 @@ void ZPlayerAnimationData::ParseRawData()
for (size_t i = 0; i < totalSize; i += 2)
{
limbRotData.push_back(BitConverter::ToUInt16BE(rawData, rawDataIndex + i));
limbRotData.push_back(BitConverter::ToInt16BE(rawData, rawDataIndex + i));
}
}
@ -55,14 +55,21 @@ std::string ZPlayerAnimationData::GetBodySourceCode() const
std::string declaration = "";
size_t index = 0;
for (const auto& entry : limbRotData)
for (const auto entry : limbRotData)
{
if (index % 8 == 0)
{
declaration += "\t";
}
declaration += StringHelper::Sprintf("0x%04X, ", entry);
if (entry < 0)
{
declaration += StringHelper::Sprintf("-0x%04X, ", -entry);
}
else
{
declaration += StringHelper::Sprintf("0x%04X, ", entry);
}
if ((index + 1) % 8 == 0)
{

View File

@ -9,7 +9,7 @@ class ZPlayerAnimationData : public ZResource
{
public:
int16_t frameCount = 0;
std::vector<uint16_t> limbRotData;
std::vector<int16_t> limbRotData;
ZPlayerAnimationData(ZFile* nParent);

View File

@ -24,7 +24,7 @@ ZResource::ZResource(ZFile* nParent)
RegisterOptionalAttribute("Static", "Global");
}
void ZResource::ExtractFromXML(tinyxml2::XMLElement* reader, offset_t nRawDataIndex)
void ZResource::ExtractWithXML(tinyxml2::XMLElement* reader, offset_t nRawDataIndex)
{
rawDataIndex = nRawDataIndex;
declaredInXml = true;
@ -274,7 +274,7 @@ void ZResource::GetSourceOutputCode([[maybe_unused]] const std::string& prefix)
if (decl == nullptr || decl->isPlaceholder)
decl = DeclareVar(prefix, bodyStr);
else
decl->text = bodyStr;
decl->declBody = bodyStr;
decl->staticConf = staticConf;
}

View File

@ -54,6 +54,7 @@ enum class ZResourceType
TextureAnimationParams,
Vector,
Vertex,
Waterbox,
};
class ResourceAttribute
@ -79,8 +80,18 @@ public:
ZResource(ZFile* nParent);
virtual ~ZResource() = default;
// Parsing from File
virtual void ExtractFromXML(tinyxml2::XMLElement* reader, offset_t nRawDataIndex);
/// <summary>
/// Extracts/Parsees data from binary file using an XML to provide the needed metadata.
/// </summary>
/// <param name="reader">XML Node we wish to parse from.</param>
/// <param name="nRawDataIndex">The offset within the binary file we are going to parse from as
/// indicated by the "Offset" parameter in the XML.</param>
virtual void ExtractWithXML(tinyxml2::XMLElement* reader, offset_t nRawDataIndex);
/// <summary>
/// Extracts/Parses the needed data straight from a binary without the use of an XML.
/// </summary>
/// <param name="nRawDataIndex">The offset within the binary file we wish to parse from.</param>
virtual void ExtractFromFile(offset_t nRawDataIndex);
// Misc

View File

@ -21,7 +21,7 @@ void SetAlternateHeaders::DeclareReferences([[maybe_unused]] const std::string&
void SetAlternateHeaders::ParseRawDataLate()
{
size_t numHeaders = zRoom->GetDeclarationSizeFromNeighbor(segmentOffset) / 4;
size_t numHeaders = zRoom->parent->GetDeclarationSizeFromNeighbor(segmentOffset) / 4;
headers.reserve(numHeaders);
for (uint32_t i = 0; i < numHeaders; i++)

View File

@ -24,7 +24,7 @@ void SetEntranceList::DeclareReferences([[maybe_unused]] const std::string& pref
void SetEntranceList::ParseRawDataLate()
{
// Parse Entrances and Generate Declaration
uint32_t numEntrances = zRoom->GetDeclarationSizeFromNeighbor(segmentOffset) / 2;
uint32_t numEntrances = zRoom->parent->GetDeclarationSizeFromNeighbor(segmentOffset) / 2;
uint32_t currentPtr = segmentOffset;
entrances.reserve(numEntrances);

View File

@ -24,7 +24,7 @@ void SetExitList::DeclareReferences([[maybe_unused]] const std::string& prefix)
void SetExitList::ParseRawDataLate()
{
// Parse Entrances and Generate Declaration
uint32_t numEntrances = zRoom->GetDeclarationSizeFromNeighbor(segmentOffset) / 2;
uint32_t numEntrances = zRoom->parent->GetDeclarationSizeFromNeighbor(segmentOffset) / 2;
uint32_t currentPtr = segmentOffset;
exits.reserve(numEntrances);

View File

@ -151,7 +151,7 @@ void PolygonDlist::GetSourceOutputCode(const std::string& prefix)
if (decl == nullptr)
DeclareVar(prefix, bodyStr);
else
decl->text = bodyStr;
decl->declBody = bodyStr;
}
std::string PolygonDlist::GetSourceTypeName() const
@ -371,7 +371,7 @@ void PolygonTypeBase::DeclareAndGenerateOutputCode(const std::string& prefix)
}
else
{
decl->text = bodyStr;
decl->declBody = bodyStr;
}
}

View File

@ -24,7 +24,7 @@ void SetPathways::ParseRawDataLate()
{
if (Globals::Instance->game == ZGame::MM_RETAIL)
{
auto numPaths = zRoom->GetDeclarationSizeFromNeighbor(segmentOffset) / 8;
auto numPaths = zRoom->parent->GetDeclarationSizeFromNeighbor(segmentOffset) / 8;
pathwayList.SetNumPaths(numPaths);
}

View File

@ -48,11 +48,12 @@ public:
static std::string GetEntranceName(uint16_t id)
{
if (ZNames::GetNumEntrances() == 0 || ZNames::GetNumSpecialEntrances() == 0)
return StringHelper::Sprintf("0x%04X", id);
return StringHelper::Sprintf("0x%04X", id);
if (id < ZNames::GetNumEntrances())
return Globals::Instance->cfg.entranceList[id];
else if ((id >= 0x7FF9 && id <= 0x7FFF) && !((id - 0x7FF9U) > GetNumSpecialEntrances())) // Special entrances
else if ((id >= 0x7FF9 && id <= 0x7FFF) &&
!((id - 0x7FF9U) > GetNumSpecialEntrances())) // Special entrances
return Globals::Instance->cfg.specialEntranceList[id - 0x7FF9];
else
return StringHelper::Sprintf("0x%04X", id);
@ -60,5 +61,8 @@ public:
static size_t GetNumActors() { return Globals::Instance->cfg.actorList.size(); }
static size_t GetNumEntrances() { return Globals::Instance->cfg.entranceList.size(); }
static size_t GetNumSpecialEntrances() { return Globals::Instance->cfg.specialEntranceList.size(); }
static size_t GetNumSpecialEntrances()
{
return Globals::Instance->cfg.specialEntranceList.size();
}
};

View File

@ -64,18 +64,14 @@ ZRoom::~ZRoom()
delete cmd;
}
void ZRoom::ExtractFromXML(tinyxml2::XMLElement* reader, uint32_t nRawDataIndex)
void ZRoom::ExtractWithXML(tinyxml2::XMLElement* reader, uint32_t nRawDataIndex)
{
ZResource::ExtractFromXML(reader, nRawDataIndex);
ZResource::ExtractWithXML(reader, nRawDataIndex);
if (hackMode == "syotes_room")
{
SyotesRoomHack();
}
SyotesRoomFix();
else
{
DeclareVar(name, "");
}
}
void ZRoom::ExtractFromBinary(uint32_t nRawDataIndex, ZResourceType parentType)
@ -338,7 +334,7 @@ std::string ZRoom::GetDefaultName(const std::string& prefix) const
* back to very early in the game's development. Since this room is a special case,
* declare automatically the data its contains whitout the need of a header.
*/
void ZRoom::SyotesRoomHack()
void ZRoom::SyotesRoomFix()
{
PolygonType2 poly(parent, 0, this);
@ -360,20 +356,6 @@ ZRoomCommand* ZRoom::FindCommandOfType(RoomCommand cmdType)
return nullptr;
}
size_t ZRoom::GetDeclarationSizeFromNeighbor(uint32_t declarationAddress)
{
auto currentDecl = parent->declarations.find(declarationAddress);
if (currentDecl == parent->declarations.end())
return 0;
auto nextDecl = currentDecl;
std::advance(nextDecl, 1);
if (nextDecl == parent->declarations.end())
return parent->GetRawData().size() - currentDecl->first;
return nextDecl->first - currentDecl->first;
}
size_t ZRoom::GetCommandSizeFromNeighbor(ZRoomCommand* cmd)
{
int32_t cmdIndex = -1;

View File

@ -22,7 +22,7 @@ public:
ZRoom(ZFile* nParent);
virtual ~ZRoom();
void ExtractFromXML(tinyxml2::XMLElement* reader, uint32_t nRawDataIndex) override;
void ExtractWithXML(tinyxml2::XMLElement* reader, uint32_t nRawDataIndex) override;
void ExtractFromBinary(uint32_t nRawDataIndex, ZResourceType parentType);
void ParseXML(tinyxml2::XMLElement* reader) override;
@ -37,7 +37,6 @@ public:
void GetSourceOutputCode(const std::string& prefix) override;
std::string GetDefaultName(const std::string& prefix) const override;
size_t GetDeclarationSizeFromNeighbor(uint32_t declarationAddress);
size_t GetCommandSizeFromNeighbor(ZRoomCommand* cmd);
ZRoomCommand* FindCommandOfType(RoomCommand cmdType);
@ -46,5 +45,5 @@ public:
ZResourceType GetResourceType() const override;
protected:
void SyotesRoomHack();
void SyotesRoomFix();
};

View File

@ -137,31 +137,31 @@ void ZTexture::ParseRawData()
switch (format)
{
case TextureType::RGBA16bpp:
PrepareBitmapRGBA16();
ConvertN64ToBitmap_RGBA16();
break;
case TextureType::RGBA32bpp:
PrepareBitmapRGBA32();
ConvertN64ToBitmap_RGBA32();
break;
case TextureType::Grayscale4bpp:
PrepareBitmapGrayscale4();
ConvertN64ToBitmap_Grayscale4();
break;
case TextureType::Grayscale8bpp:
PrepareBitmapGrayscale8();
ConvertN64ToBitmap_Grayscale8();
break;
case TextureType::GrayscaleAlpha4bpp:
PrepareBitmapGrayscaleAlpha4();
ConvertN64ToBitmap_GrayscaleAlpha4();
break;
case TextureType::GrayscaleAlpha8bpp:
PrepareBitmapGrayscaleAlpha8();
ConvertN64ToBitmap_GrayscaleAlpha8();
break;
case TextureType::GrayscaleAlpha16bpp:
PrepareBitmapGrayscaleAlpha16();
ConvertN64ToBitmap_GrayscaleAlpha16();
break;
case TextureType::Palette4bpp:
PrepareBitmapPalette4();
ConvertN64ToBitmap_Palette4();
break;
case TextureType::Palette8bpp:
PrepareBitmapPalette8();
ConvertN64ToBitmap_Palette8();
break;
case TextureType::Error:
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
@ -212,10 +212,10 @@ void ZTexture::ParseRawDataLate()
}
}
void ZTexture::PrepareBitmapRGBA16()
void ZTexture::ConvertN64ToBitmap_RGBA16()
{
textureData.InitEmptyRGBImage(width, height, true);
auto parentRawData = parent->GetRawData();
const auto& parentRawData = parent->GetRawData();
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x++)
@ -227,15 +227,16 @@ void ZTexture::PrepareBitmapRGBA16()
uint8_t b = (data & 0x003E) >> 1;
uint8_t alpha = data & 0x01;
textureData.SetRGBPixel(y, x, r * 8, g * 8, b * 8, alpha * 255);
textureData.SetRGBPixel(y, x, (r << 3) | (r >> 2), (g << 3) | (g >> 2),
(b << 3) | (b >> 2), alpha * 255);
}
}
}
void ZTexture::PrepareBitmapRGBA32()
void ZTexture::ConvertN64ToBitmap_RGBA32()
{
textureData.InitEmptyRGBImage(width, height, true);
auto parentRawData = parent->GetRawData();
const auto& parentRawData = parent->GetRawData();
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x++)
@ -251,10 +252,10 @@ void ZTexture::PrepareBitmapRGBA32()
}
}
void ZTexture::PrepareBitmapGrayscale4()
void ZTexture::ConvertN64ToBitmap_Grayscale4()
{
textureData.InitEmptyRGBImage(width, height, false);
auto parentRawData = parent->GetRawData();
const auto& parentRawData = parent->GetRawData();
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x += 2)
@ -269,16 +270,16 @@ void ZTexture::PrepareBitmapGrayscale4()
else
grayscale = (parentRawData.at(pos) & 0x0F) << 4;
textureData.SetGrayscalePixel(y, x + i, grayscale);
textureData.SetGrayscalePixel(y, x + i, (grayscale << 4) | grayscale);
}
}
}
}
void ZTexture::PrepareBitmapGrayscale8()
void ZTexture::ConvertN64ToBitmap_Grayscale8()
{
textureData.InitEmptyRGBImage(width, height, false);
auto parentRawData = parent->GetRawData();
const auto& parentRawData = parent->GetRawData();
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x++)
@ -290,10 +291,10 @@ void ZTexture::PrepareBitmapGrayscale8()
}
}
void ZTexture::PrepareBitmapGrayscaleAlpha4()
void ZTexture::ConvertN64ToBitmap_GrayscaleAlpha4()
{
textureData.InitEmptyRGBImage(width, height, true);
auto parentRawData = parent->GetRawData();
const auto& parentRawData = parent->GetRawData();
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x += 2)
@ -308,8 +309,9 @@ void ZTexture::PrepareBitmapGrayscaleAlpha4()
else
data = parentRawData.at(pos) & 0x0F;
uint8_t grayscale = ((data & 0x0E) >> 1) * 32;
uint8_t alpha = (data & 0x01) * 255;
uint8_t grayscale = data & 0b1110;
grayscale = (grayscale << 4) | (grayscale << 1) | (grayscale >> 2);
uint8_t alpha = (data & 0x01) ? 255 : 0;
textureData.SetGrayscalePixel(y, x + i, grayscale, alpha);
}
@ -317,27 +319,32 @@ void ZTexture::PrepareBitmapGrayscaleAlpha4()
}
}
void ZTexture::PrepareBitmapGrayscaleAlpha8()
void ZTexture::ConvertN64ToBitmap_GrayscaleAlpha8()
{
textureData.InitEmptyRGBImage(width, height, true);
auto parentRawData = parent->GetRawData();
const auto& parentRawData = parent->GetRawData();
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x++)
{
size_t pos = rawDataIndex + ((y * width) + x) * 1;
uint8_t grayscale = parentRawData.at(pos) & 0xF0;
uint8_t alpha = (parentRawData.at(pos) & 0x0F) << 4;
uint8_t pixel = parentRawData.at(pos);
uint8_t data = (pixel >> 4) & 0xF;
data = (data << 4) | data;
uint8_t grayscale = data;
uint8_t alpha = (pixel & 0xF);
alpha = (alpha << 4) | alpha;
textureData.SetGrayscalePixel(y, x, grayscale, alpha);
}
}
}
void ZTexture::PrepareBitmapGrayscaleAlpha16()
void ZTexture::ConvertN64ToBitmap_GrayscaleAlpha16()
{
textureData.InitEmptyRGBImage(width, height, true);
auto parentRawData = parent->GetRawData();
const auto& parentRawData = parent->GetRawData();
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x++)
@ -351,10 +358,10 @@ void ZTexture::PrepareBitmapGrayscaleAlpha16()
}
}
void ZTexture::PrepareBitmapPalette4()
void ZTexture::ConvertN64ToBitmap_Palette4()
{
textureData.InitEmptyPaletteImage(width, height);
auto parentRawData = parent->GetRawData();
const auto& parentRawData = parent->GetRawData();
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x += 2)
@ -375,10 +382,10 @@ void ZTexture::PrepareBitmapPalette4()
}
}
void ZTexture::PrepareBitmapPalette8()
void ZTexture::ConvertN64ToBitmap_Palette8()
{
textureData.InitEmptyPaletteImage(width, height);
auto parentRawData = parent->GetRawData();
const auto& parentRawData = parent->GetRawData();
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x++)
@ -428,31 +435,31 @@ void ZTexture::PrepareRawDataFromFile(const fs::path& pngFilePath)
switch (format)
{
case TextureType::RGBA16bpp:
PrepareRawDataRGBA16();
ConvertBitmapToN64_RGBA16();
break;
case TextureType::RGBA32bpp:
PrepareRawDataRGBA32();
ConvertBitmapToN64_RGBA32();
break;
case TextureType::Grayscale4bpp:
PrepareRawDataGrayscale4();
ConvertBitmapToN64_Grayscale4();
break;
case TextureType::Grayscale8bpp:
PrepareRawDataGrayscale8();
ConvertBitmapToN64_Grayscale8();
break;
case TextureType::GrayscaleAlpha4bpp:
PrepareRawDataGrayscaleAlpha4();
ConvertBitmapToN64_GrayscaleAlpha4();
break;
case TextureType::GrayscaleAlpha8bpp:
PrepareRawDataGrayscaleAlpha8();
ConvertBitmapToN64_GrayscaleAlpha8();
break;
case TextureType::GrayscaleAlpha16bpp:
PrepareRawDataGrayscaleAlpha16();
ConvertBitmapToN64_GrayscaleAlpha16();
break;
case TextureType::Palette4bpp:
PrepareRawDataPalette4();
ConvertBitmapToN64_Palette4();
break;
case TextureType::Palette8bpp:
PrepareRawDataPalette8();
ConvertBitmapToN64_Palette8();
break;
case TextureType::Error:
HANDLE_ERROR_PROCESS(WarningType::InvalidPNG, "Input PNG file has invalid format type", "");
@ -460,7 +467,7 @@ void ZTexture::PrepareRawDataFromFile(const fs::path& pngFilePath)
}
}
void ZTexture::PrepareRawDataRGBA16()
void ZTexture::ConvertBitmapToN64_RGBA16()
{
for (uint16_t y = 0; y < height; y++)
{
@ -469,13 +476,13 @@ void ZTexture::PrepareRawDataRGBA16()
size_t pos = ((y * width) + x) * 2;
RGBAPixel pixel = textureData.GetPixel(y, x);
uint8_t r = pixel.r / 8;
uint8_t g = pixel.g / 8;
uint8_t b = pixel.b / 8;
uint8_t r = pixel.r >> 3;
uint8_t g = pixel.g >> 3;
uint8_t b = pixel.b >> 3;
uint8_t alphaBit = pixel.a != 0;
uint16_t data = (r << 11) + (g << 6) + (b << 1) + alphaBit;
uint16_t data = (r << 11) | (g << 6) | (b << 1) | alphaBit;
textureDataRaw[pos + 0] = (data & 0xFF00) >> 8;
textureDataRaw[pos + 1] = (data & 0x00FF);
@ -483,7 +490,7 @@ void ZTexture::PrepareRawDataRGBA16()
}
}
void ZTexture::PrepareRawDataRGBA32()
void ZTexture::ConvertBitmapToN64_RGBA32()
{
for (uint16_t y = 0; y < height; y++)
{
@ -500,7 +507,7 @@ void ZTexture::PrepareRawDataRGBA32()
}
}
void ZTexture::PrepareRawDataGrayscale4()
void ZTexture::ConvertBitmapToN64_Grayscale4()
{
for (uint16_t y = 0; y < height; y++)
{
@ -515,7 +522,7 @@ void ZTexture::PrepareRawDataGrayscale4()
}
}
void ZTexture::PrepareRawDataGrayscale8()
void ZTexture::ConvertBitmapToN64_Grayscale8()
{
for (uint16_t y = 0; y < height; y++)
{
@ -528,7 +535,7 @@ void ZTexture::PrepareRawDataGrayscale8()
}
}
void ZTexture::PrepareRawDataGrayscaleAlpha4()
void ZTexture::ConvertBitmapToN64_GrayscaleAlpha4()
{
for (uint16_t y = 0; y < height; y++)
{
@ -544,9 +551,9 @@ void ZTexture::PrepareRawDataGrayscaleAlpha4()
uint8_t alphaBit = pixel.a != 0;
if (i == 0)
data |= (((cR / 32) << 1) + alphaBit) << 4;
data = (((cR >> 5) << 1) | alphaBit) << 4;
else
data |= ((cR / 32) << 1) + alphaBit;
data |= ((cR >> 5) << 1) | alphaBit;
}
textureDataRaw[pos] = data;
@ -554,7 +561,7 @@ void ZTexture::PrepareRawDataGrayscaleAlpha4()
}
}
void ZTexture::PrepareRawDataGrayscaleAlpha8()
void ZTexture::ConvertBitmapToN64_GrayscaleAlpha8()
{
for (uint16_t y = 0; y < height; y++)
{
@ -563,15 +570,15 @@ void ZTexture::PrepareRawDataGrayscaleAlpha8()
size_t pos = ((y * width) + x) * 1;
RGBAPixel pixel = textureData.GetPixel(y, x);
uint8_t r = pixel.r;
uint8_t a = pixel.a;
uint8_t r = (pixel.r >> 4) & 0xF;
uint8_t a = (pixel.a >> 4) & 0xF;
textureDataRaw[pos] = ((r / 16) << 4) + (a / 16);
textureDataRaw[pos] = (r << 4) | a;
}
}
}
void ZTexture::PrepareRawDataGrayscaleAlpha16()
void ZTexture::ConvertBitmapToN64_GrayscaleAlpha16()
{
for (uint16_t y = 0; y < height; y++)
{
@ -589,7 +596,7 @@ void ZTexture::PrepareRawDataGrayscaleAlpha16()
}
}
void ZTexture::PrepareRawDataPalette4()
void ZTexture::ConvertBitmapToN64_Palette4()
{
for (uint16_t y = 0; y < height; y++)
{
@ -605,7 +612,7 @@ void ZTexture::PrepareRawDataPalette4()
}
}
void ZTexture::PrepareRawDataPalette8()
void ZTexture::ConvertBitmapToN64_Palette8()
{
for (uint16_t y = 0; y < height; y++)
{
@ -770,10 +777,10 @@ Declaration* ZTexture::DeclareVar(const std::string& prefix,
auto filepath = Globals::Instance->outputPath / fs::path(auxOutName).stem();
if (dWordAligned)
incStr =
StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), GetExternalExtension().c_str());
incStr = StringHelper::Sprintf("%s.%s.inc.c", filepath.string().c_str(),
GetExternalExtension().c_str());
else
incStr = StringHelper::Sprintf("%s.u32.%s.inc.c", filepath.c_str(),
incStr = StringHelper::Sprintf("%s.u32.%s.inc.c", filepath.string().c_str(),
GetExternalExtension().c_str());
if (!Globals::Instance->cfg.texturePool.empty())
@ -785,18 +792,31 @@ Declaration* ZTexture::DeclareVar(const std::string& prefix,
if (poolEntry != Globals::Instance->cfg.texturePool.end())
{
if (dWordAligned)
incStr = StringHelper::Sprintf("%s.%s.inc.c", poolEntry->second.path.c_str(),
GetExternalExtension().c_str());
incStr =
StringHelper::Sprintf("%s.%s.inc.c", poolEntry->second.path.string().c_str(),
GetExternalExtension().c_str());
else
incStr = StringHelper::Sprintf("%s.u32.%s.inc.c", poolEntry->second.path.c_str(),
incStr = StringHelper::Sprintf("%s.u32.%s.inc.c",
poolEntry->second.path.string().c_str(),
GetExternalExtension().c_str());
}
}
size_t texSizeDivisor = (dWordAligned) ? 8 : 4;
Declaration* decl = parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(),
GetSourceTypeName(), auxName,
GetRawDataSize() / texSizeDivisor);
Declaration* decl;
if (parent->makeDefines)
{
decl = parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(),
GetSourceTypeName(), auxName, GetHeaderDefines(),
GetRawDataSize() / texSizeDivisor);
}
else
{
decl = parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(),
GetSourceTypeName(), auxName,
GetRawDataSize() / texSizeDivisor);
}
decl->staticConf = staticConf;
return decl;
}
@ -827,6 +847,17 @@ std::string ZTexture::GetBodySourceCode() const
return sourceOutput;
}
std::string ZTexture::GetHeaderDefines() const
{
std::string definePrefix = StringHelper::camelCaseTo_SCREAMING_SNAKE_CASE(name.c_str(), true);
std::string ret = StringHelper::Sprintf("#define %s_WIDTH %d\n", definePrefix.c_str(), width);
ret += StringHelper::Sprintf("#define %s_HEIGHT %d\n", definePrefix.c_str(), height);
ret += StringHelper::Sprintf("#define %s_SIZE 0x%zX\n", definePrefix.c_str(), GetRawDataSize());
return ret;
}
bool ZTexture::IsExternalResource() const
{
return true;
@ -844,7 +875,7 @@ std::string ZTexture::GetSourceTypeName() const
void ZTexture::CalcHash()
{
auto parentRawData = parent->GetRawData();
const auto& parentRawData = parent->GetRawData();
hash = CRC32B(parentRawData.data() + rawDataIndex, GetRawDataSize());
}

View File

@ -30,26 +30,28 @@ protected:
ZTexture* tlut = nullptr;
bool splitTlut;
void PrepareBitmapRGBA16();
void PrepareBitmapRGBA32();
void PrepareBitmapGrayscale8();
void PrepareBitmapGrayscaleAlpha8();
void PrepareBitmapGrayscale4();
void PrepareBitmapGrayscaleAlpha4();
void PrepareBitmapGrayscaleAlpha16();
void PrepareBitmapPalette4();
void PrepareBitmapPalette8();
// The following functions convert from N64 binary data to a bitmap to be saved to a PNG.
void ConvertN64ToBitmap_RGBA16();
void ConvertN64ToBitmap_RGBA32();
void ConvertN64ToBitmap_Grayscale8();
void ConvertN64ToBitmap_GrayscaleAlpha8();
void ConvertN64ToBitmap_Grayscale4();
void ConvertN64ToBitmap_GrayscaleAlpha4();
void ConvertN64ToBitmap_GrayscaleAlpha16();
void ConvertN64ToBitmap_Palette4();
void ConvertN64ToBitmap_Palette8();
// The following functions convert from a bitmap to N64 binary data.
void PrepareRawDataFromFile(const fs::path& inFolder);
void PrepareRawDataRGBA16();
void PrepareRawDataRGBA32();
void PrepareRawDataGrayscale4();
void PrepareRawDataGrayscale8();
void PrepareRawDataGrayscaleAlpha4();
void PrepareRawDataGrayscaleAlpha8();
void PrepareRawDataGrayscaleAlpha16();
void PrepareRawDataPalette4();
void PrepareRawDataPalette8();
void ConvertBitmapToN64_RGBA16();
void ConvertBitmapToN64_RGBA32();
void ConvertBitmapToN64_Grayscale4();
void ConvertBitmapToN64_Grayscale8();
void ConvertBitmapToN64_GrayscaleAlpha4();
void ConvertBitmapToN64_GrayscaleAlpha8();
void ConvertBitmapToN64_GrayscaleAlpha16();
void ConvertBitmapToN64_Palette4();
void ConvertBitmapToN64_Palette8();
public:
ZTexture(ZFile* nParent);
@ -68,9 +70,15 @@ public:
Declaration* DeclareVar(const std::string& prefix, const std::string& bodyStr) override;
std::string GetBodySourceCode() const override;
/// <summary>
/// Calculates the hash of this texture, for use with the texture pool.
/// </summary>
void CalcHash() override;
void Save(const fs::path& outFolder) override;
std::string GetHeaderDefines() const;
bool IsExternalResource() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
@ -83,10 +91,28 @@ public:
uint32_t GetWidth() const;
uint32_t GetHeight() const;
void SetDimensions(uint32_t nWidth, uint32_t nHeight);
/// <summary>
/// Returns how many bytes each pixel takes up.
/// </summary>
/// <returns></returns>
float GetPixelMultiplyer() const;
TextureType GetTextureType() const;
/// <summary>
/// Returns the path to the texture pool, taken from the config file.
/// </summary>
/// <param name="defaultValue"></param>
/// <returns></returns>
fs::path GetPoolOutPath(const fs::path& defaultValue);
/// <summary>
/// Returns if this texture uses a palette.
/// </summary>
/// <returns></returns>
bool IsColorIndexed() const;
void SetTlut(ZTexture* nTlut);
bool HasTlut() const;
void ParseRawDataLate() override;

View File

@ -0,0 +1,74 @@
#include "ZWaterbox.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
REGISTER_ZFILENODE(Waterbox, ZWaterbox);
ZWaterbox::ZWaterbox(ZFile* nParent) : ZResource(nParent)
{
}
ZWaterbox::~ZWaterbox()
{
}
void ZWaterbox::ParseRawData()
{
const auto& rawData = parent->GetRawData();
xMin = BitConverter::ToInt16BE(rawData, rawDataIndex + 0);
ySurface = BitConverter::ToInt16BE(rawData, rawDataIndex + 2);
zMin = BitConverter::ToInt16BE(rawData, rawDataIndex + 4);
xLength = BitConverter::ToInt16BE(rawData, rawDataIndex + 6);
zLength = BitConverter::ToInt16BE(rawData, rawDataIndex + 8);
if (Globals::Instance->game == ZGame::OOT_SW97)
properties = BitConverter::ToInt16BE(rawData, rawDataIndex + 10);
else
properties = BitConverter::ToInt32BE(rawData, rawDataIndex + 12);
}
void ZWaterbox::DeclareReferences(const std::string& prefix)
{
std::string declaration;
std::string auxName = name;
if (name == "")
auxName = GetDefaultName(prefix);
parent->AddDeclaration(rawDataIndex, DeclarationAlignment::Align4, GetRawDataSize(),
GetSourceTypeName(), name.c_str(), GetBodySourceCode());
}
std::string ZWaterbox::GetBodySourceCode() const
{
return StringHelper::Sprintf("%i, %i, %i, %i, %i, 0x%08X", xMin, ySurface, zMin, xLength,
zLength, properties);
}
std::string ZWaterbox::GetDefaultName(const std::string& prefix) const
{
return StringHelper::Sprintf("%sWaterBoxes_%06X", prefix.c_str(), rawDataIndex);
}
ZResourceType ZWaterbox::GetResourceType() const
{
return ZResourceType::Waterbox;
}
size_t ZWaterbox::GetRawDataSize() const
{
return 16;
}
std::string ZWaterbox::GetSourceTypeName() const
{
return "WaterBox";
}
bool ZWaterbox::DoesSupportArray() const
{
return true;
}

View File

@ -0,0 +1,30 @@
#pragma once
#include "ZFile.h"
#include "ZResource.h"
class ZWaterbox : public ZResource
{
public:
int16_t xMin;
int16_t ySurface;
int16_t zMin;
int16_t xLength;
int16_t zLength;
int32_t properties;
ZWaterbox(ZFile* nParent);
~ZWaterbox();
void ParseRawData() override;
void DeclareReferences(const std::string& prefix) override;
std::string GetBodySourceCode() const override;
std::string GetDefaultName(const std::string& prefix) const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
bool DoesSupportArray() const override;
size_t GetRawDataSize() const override;
};

View File

@ -10,7 +10,13 @@ parser.add_argument("--devel", action="store_true")
args = parser.parse_args()
with open("build/ZAPD/BuildInfo.cpp", "w+") as buildFile:
label = subprocess.check_output(["git", "describe", "--always"]).strip().decode("utf-8")
# Get commit hash from git
# If git fails due to a missing .git directory, a default label will be used instead.
try:
label = subprocess.check_output(["git", "describe", "--always"]).strip().decode("utf-8")
except:
label = "GIT_NOT_FOUND"
now = datetime.now()
if args.devel:
label += " ~ Development version"

View File

@ -17,7 +17,7 @@ clean:
rm -rf build $(LIB)
format:
clang-format-11 -i $(CPP_FILES) $(H_FILES)
clang-format-14 -i $(CPP_FILES) $(H_FILES)
.PHONY: all clean format

View File

@ -76,7 +76,7 @@ public:
fprintf(stderr, "\t Trying to read at offset: 0x%zX\n", offset);
}
return ((uint32_t)data.at(offset + 0) << 24) + ((uint32_t)data.at(offset + 1) << 16) +
((uint32_t)data.at(offset + 2) << 8) + (uint32_t)data.at(offset + 3);
((uint32_t)data.at(offset + 2) << 8) + (uint32_t)data.at(offset + 3);
}
static inline uint32_t ToUInt32BE(const std::vector<uint8_t>& data, size_t offset)
@ -89,7 +89,7 @@ public:
fprintf(stderr, "\t Trying to read at offset: 0x%zX\n", offset);
}
return ((uint32_t)data.at(offset + 0) << 24) + ((uint32_t)data.at(offset + 1) << 16) +
((uint32_t)data.at(offset + 2) << 8) + (uint32_t)data.at(offset + 3);
((uint32_t)data.at(offset + 2) << 8) + (uint32_t)data.at(offset + 3);
}
static inline int64_t ToInt64BE(const std::vector<uint8_t>& data, size_t offset)
@ -102,9 +102,9 @@ public:
fprintf(stderr, "\t Trying to read at offset: 0x%zX\n", offset);
}
return ((uint64_t)data.at(offset + 0) << 56) + ((uint64_t)data.at(offset + 1) << 48) +
((uint64_t)data.at(offset + 2) << 40) + ((uint64_t)data.at(offset + 3) << 32) +
((uint64_t)data.at(offset + 4) << 24) + ((uint64_t)data.at(offset + 5) << 16) +
((uint64_t)data.at(offset + 6) << 8) + ((uint64_t)data.at(offset + 7));
((uint64_t)data.at(offset + 2) << 40) + ((uint64_t)data.at(offset + 3) << 32) +
((uint64_t)data.at(offset + 4) << 24) + ((uint64_t)data.at(offset + 5) << 16) +
((uint64_t)data.at(offset + 6) << 8) + ((uint64_t)data.at(offset + 7));
}
static inline uint64_t ToUInt64BE(const std::vector<uint8_t>& data, size_t offset)
@ -117,9 +117,9 @@ public:
fprintf(stderr, "\t Trying to read at offset: 0x%zX\n", offset);
}
return ((uint64_t)data.at(offset + 0) << 56) + ((uint64_t)data.at(offset + 1) << 48) +
((uint64_t)data.at(offset + 2) << 40) + ((uint64_t)data.at(offset + 3) << 32) +
((uint64_t)data.at(offset + 4) << 24) + ((uint64_t)data.at(offset + 5) << 16) +
((uint64_t)data.at(offset + 6) << 8) + ((uint64_t)data.at(offset + 7));
((uint64_t)data.at(offset + 2) << 40) + ((uint64_t)data.at(offset + 3) << 32) +
((uint64_t)data.at(offset + 4) << 24) + ((uint64_t)data.at(offset + 5) << 16) +
((uint64_t)data.at(offset + 6) << 8) + ((uint64_t)data.at(offset + 7));
}
static inline float ToFloatBE(const std::vector<uint8_t>& data, size_t offset)
@ -133,8 +133,8 @@ public:
}
float value;
uint32_t floatData = ((uint32_t)data.at(offset + 0) << 24) +
((uint32_t)data.at(offset + 1) << 16) +
((uint32_t)data.at(offset + 2) << 8) + (uint32_t)data.at(offset + 3);
((uint32_t)data.at(offset + 1) << 16) +
((uint32_t)data.at(offset + 2) << 8) + (uint32_t)data.at(offset + 3);
static_assert(sizeof(uint32_t) == sizeof(float), "expected 32-bit float");
std::memcpy(&value, &floatData, sizeof(value));
return value;

View File

@ -1,8 +1,6 @@
#pragma once
#include <cstdio>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "Directory.h"
@ -26,6 +24,7 @@ public:
file.read(data, fileSize);
std::vector<uint8_t> result = std::vector<uint8_t>(data, data + fileSize);
delete[] data;
file.close();
return result;
};
@ -42,6 +41,7 @@ public:
file.read(data, fileSize);
std::string str = std::string((const char*)data);
delete[] data;
file.close();
return str;
};
@ -58,23 +58,27 @@ public:
{
std::ofstream file(filePath, std::ios::binary);
file.write((char*)data.data(), data.size());
file.close();
};
static void WriteAllBytes(const std::string& filePath, const std::vector<char>& data)
{
std::ofstream file(filePath, std::ios::binary);
file.write((char*)data.data(), data.size());
file.close();
};
static void WriteAllBytes(const std::string& filePath, const char* data, int dataSize)
{
std::ofstream file(filePath, std::ios::binary);
file.write((char*)data, dataSize);
file.close();
};
static void WriteAllText(const fs::path& filePath, const std::string& text)
{
std::ofstream file(filePath, std::ios::out);
file.write(text.c_str(), text.size());
file.close();
}
};

View File

@ -106,9 +106,35 @@ public:
return std::all_of(str.begin(), str.end(), ::isdigit);
}
static bool HasOnlyHexDigits(const std::string& str)
static bool IsValidHex(std::string_view str)
{
return std::all_of(str.begin(), str.end(), ::isxdigit);
if (str.length() < 3)
{
return false;
}
if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
{
return std::all_of(str.begin() + 2, str.end(), ::isxdigit);
}
return false;
}
static bool IsValidOffset(std::string_view str)
{
if (str.length() == 1)
{
// 0 is a valid offset
return isdigit(str[0]);
}
return IsValidHex(str);
}
static bool IsValidHex(const std::string& str)
{
return IsValidHex(std::string_view(str.c_str()));
}
static std::string ToUpper(const std::string& str)
@ -123,4 +149,66 @@ public:
return std::equal(a.begin(), a.end(), b.begin(), b.end(),
[](char a, char b) { return tolower(a) == tolower(b); });
}
/**
* Converts a std::string formatted in camelCase into one in SCREAMING_SNAKE_CASE. Since this
* will mostly be used on symbols that start with either 'g' or 's', an option is included to
* skip these.
*/
static std::string camelCaseTo_SCREAMING_SNAKE_CASE(const std::string& in, bool skipSP)
{
std::string out = "";
const char* ptr = in.c_str();
char ch = *ptr;
// Switch checks for 'g'/'s'/'\0', looks at next character if skipSP enabled and string is
// nonempty.
switch (ch)
{
case 'g':
case 's':
if (skipSP)
{
// Print it anyway if the next character is lowercase, e.g. "gameplay_keep_...".
if (!isupper(ptr[1]))
{
out.push_back(toupper(ch));
}
if ((ch = *++ptr) == '\0')
{
case '\0':
// This is reached either by the if or the case label, avoiding duplication.
return out;
}
}
[[fallthrough]];
default:
if (islower(ch))
{
out.push_back(toupper(ch));
}
else
{
out.push_back(ch);
}
break;
}
while ((ch = *++ptr) != '\0')
{
if (islower(ch))
{
out.push_back(toupper(ch));
}
else
{
if (isupper(ch) && !(isupper(ptr[1]) && isupper(ptr[-1])))
{
out.push_back('_');
}
out.push_back(ch);
}
}
return out;
}
};

View File

@ -118,6 +118,7 @@
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard_C>Default</LanguageStandard_C>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>