first commit

This commit is contained in:
root
2026-03-30 10:05:53 +00:00
commit 59f6583862
8465 changed files with 541514 additions and 0 deletions

84
ZAPDTR/.clang-format Normal file
View File

@@ -0,0 +1,84 @@
---
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false
ColumnLimit: 100
CommentPragmas: '^ (IWYU pragma:|NOLINT)'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ForEachMacros: [ ]
IncludeCategories:
- Regex: '^<[Ww]indows\.h>$'
Priority: 1
- Regex: '^<'
Priority: 2
- Regex: '^"'
Priority: 3
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Latest
TabWidth: 4
UseTab: AlignWithSpaces
...

83
ZAPDTR/.github/workflows/main.yml vendored Normal file
View File

@@ -0,0 +1,83 @@
name: Build ZAPD
on:
push:
pull_request:
branches:
- master
jobs:
build:
runs-on: self-hosted-runner
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Build ZAPD
run: make -j WERROR=1
- name: Checkout Repos
run: echo "Checkout Repos"
- name: Checkout oot
run: |
git clone https://github.com/zeldaret/oot.git
cd oot
git submodule update --init --recursive
- name: Checkout mm
run: |
git clone https://github.com/zeldaret/mm.git
cd mm
- name: Set up repos
run: echo "Set up repos"
- name: Setup OOT
run: |
cd oot
mkdir -p baseroms/gc-eu-mq-dbg
cp ~/baserom_original.z64 ./baseroms/gc-eu-mq-dbg/baserom.z64
make venv
make -C tools -j
cp ../ZAPD.out tools/ZAPD/
.venv/bin/python3 tools/decompress_baserom.py gc-eu-mq-dbg
.venv/bin/python3 extract_baserom.py
.venv/bin/python3 extract_assets.py -j 4
- name: Install Python dependencies
run: |
cd mm
python3 -m venv .mm-env
source .mm-env/bin/activate
python3 -m pip install -r requirements.txt
- name: Setup MM
run: |
cd mm
cp ~/baserom.mm.us.rev1.z64 ./baserom.mm.us.rev1.z64
make -C tools -j
cp ../ZAPD.out tools/ZAPD/
python3 tools/fixbaserom.py
python3 tools/extract_baserom.py
python3 tools/decompress_yars.py
python3 extract_assets.py -j $(nproc)
- name: Build Repos
run: echo "Build Repos"
- name: Build oot
run: |
cd oot
make venv
make -j
- name: Build mm
run: |
cd mm
make -j disasm
make -j
- name: Clean workspace
run: git clean -fdX

341
ZAPDTR/.gitignore vendored Normal file
View File

@@ -0,0 +1,341 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
*.out
*.o
*.d
lib/libgfxd/libgfxd.a
ExporterTest/ExporterTest.a
ZAPDUtils/ZAPDUtils.a
.vscode/
build/
ZAPDUtils/build/
ZAPD/BuildInfo.h

View File

@@ -0,0 +1,76 @@
#include "CollisionExporter.h"
void ExporterExample_Collision::Save(ZResource* res, [[maybe_unused]] const fs::path& outPath,
BinaryWriter* writer)
{
ZCollisionHeader* col = (ZCollisionHeader*)res;
writer->Write(col->absMinX);
writer->Write(col->absMinY);
writer->Write(col->absMinZ);
writer->Write(col->absMaxX);
writer->Write(col->absMaxY);
writer->Write(col->absMaxZ);
writer->Write(col->numVerts);
writer->Write(col->vtxAddress);
writer->Write(col->numPolygons);
writer->Write(col->polyAddress);
writer->Write(col->polyTypeDefAddress);
writer->Write(col->camDataAddress);
writer->Write(col->numWaterBoxes);
writer->Write(col->waterBoxAddress);
writer->Write(col->vtxSegmentOffset);
writer->Write(col->polySegmentOffset);
writer->Write(col->polyTypeDefSegmentOffset);
writer->Write(col->camDataSegmentOffset);
writer->Write(col->waterBoxSegmentOffset);
uint32_t oldOffset = writer->GetBaseAddress();
writer->Seek(col->vtxSegmentOffset, SeekOffsetType::Start);
for (uint16_t i = 0; i < col->vertices.size(); i++)
{
for (uint32_t j = 0; j < col->vertices[i].dimensions; j++)
{
writer->Write(col->vertices[i].scalars[j].scalarData.s16);
}
}
writer->Seek(col->polySegmentOffset, SeekOffsetType::Start);
for (uint16_t i = 0; i < col->polygons.size(); i++)
{
writer->Write(col->polygons[i].type);
writer->Write(col->polygons[i].vtxA);
writer->Write(col->polygons[i].vtxB);
writer->Write(col->polygons[i].vtxC);
writer->Write(col->polygons[i].normX);
writer->Write(col->polygons[i].normY);
writer->Write(col->polygons[i].normZ);
writer->Write(col->polygons[i].dist);
}
writer->Seek(col->polyTypeDefSegmentOffset, SeekOffsetType::Start);
for (const auto& poly : col->polygonTypes)
{
writer->Write(poly.data[0]);
writer->Write(poly.data[1]);
}
writer->Seek(col->camDataSegmentOffset, SeekOffsetType::Start);
for (auto entry : col->camData->entries)
{
writer->Write(entry->cameraSType);
writer->Write(entry->numData);
writer->Write(entry->cameraPosDataSeg);
}
writer->Seek(oldOffset, SeekOffsetType::Start);
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "ZCollision.h"
#include "ZResource.h"
class ExporterExample_Collision : public ZResourceExporter
{
public:
void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View File

@@ -0,0 +1,160 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{65608eb0-1a47-45ad-ab66-192fb64c762c}</ProjectGuid>
<RootNamespace>ExporterTest</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>ExporterExample</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(ProjectDir)..\ZAPD\;$(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="CollisionExporter.h" />
<ClInclude Include="TextureExporter.h" />
<ClInclude Include="RoomExporter.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="CollisionExporter.cpp" />
<ClCompile Include="TextureExporter.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="RoomExporter.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="TextureExporter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RoomExporter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CollisionExporter.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="TextureExporter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RoomExporter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CollisionExporter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,79 @@
#include "CollisionExporter.h"
#include "Globals.h"
#include "RoomExporter.h"
#include "TextureExporter.h"
enum class ExporterFileMode
{
ModeExample1 = (int)ZFileMode::Custom + 1,
ModeExample2 = (int)ZFileMode::Custom + 2,
ModeExample3 = (int)ZFileMode::Custom + 3,
};
static void ExporterParseFileMode(const std::string& buildMode, ZFileMode& fileMode)
{
if (buildMode == "me1")
fileMode = (ZFileMode)ExporterFileMode::ModeExample1;
else if (buildMode == "me2")
fileMode = (ZFileMode)ExporterFileMode::ModeExample2;
else if (buildMode == "me3")
fileMode = (ZFileMode)ExporterFileMode::ModeExample3;
}
static void ExporterParseArgs([[maybe_unused]] int argc, char* argv[], int& i)
{
std::string arg = argv[i];
if (arg == "--do-x")
{
}
else if (arg == "--do-y")
{
}
}
static bool ExporterProcessFileMode(ZFileMode fileMode)
{
// Do whatever work is associated with these custom file modes...
// Return true to indicate one of our own file modes is being processed
if (fileMode == (ZFileMode)ExporterFileMode::ModeExample1)
return true;
else if (fileMode == (ZFileMode)ExporterFileMode::ModeExample2)
return true;
else if (fileMode == (ZFileMode)ExporterFileMode::ModeExample3)
return true;
return false;
}
static void ExporterFileBegin(ZFile* file)
{
printf("ExporterFileBegin() called on ZFile %s.\n", file->GetName().c_str());
}
static void ExporterFileEnd(ZFile* file)
{
printf("ExporterFileEnd() called on ZFile %s.\n", file->GetName().c_str());
}
static void ImportExporters()
{
// In this example we set up a new exporter called "EXAMPLE".
// By running ZAPD with the argument -se EXAMPLE, we tell it that we want to use this exporter
// for our resources.
ExporterSet* exporterSet = new ExporterSet();
exporterSet->processFileModeFunc = ExporterProcessFileMode;
exporterSet->parseFileModeFunc = ExporterParseFileMode;
exporterSet->parseArgsFunc = ExporterParseArgs;
exporterSet->beginFileFunc = ExporterFileBegin;
exporterSet->endFileFunc = ExporterFileEnd;
exporterSet->exporters[ZResourceType::Texture] = new ExporterExample_Texture();
exporterSet->exporters[ZResourceType::Room] = new ExporterExample_Room();
exporterSet->exporters[ZResourceType::CollisionHeader] = new ExporterExample_Collision();
Globals::AddExporter("EXAMPLE", exporterSet);
}
// When ZAPD starts up, it will automatically call the below function, which in turn sets up our
// exporters.
REGISTER_EXPORTER(ImportExporters);

View File

@@ -0,0 +1,28 @@
# Only used for standalone compilation, usually inherits these from the main makefile
CXXFLAGS ?= -Wall -Wextra -O2 -g -std=c++17
SRC_DIRS := $(shell find . -type d -not -path "*build*")
CPP_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h))
O_FILES := $(foreach f,$(CPP_FILES:.cpp=.o),build/$f)
LIB := ExporterTest.a
# create build directories
$(shell mkdir -p $(foreach dir,$(SRC_DIRS),build/$(dir)))
all: $(LIB)
clean:
rm -rf build $(LIB)
format:
clang-format-11 -i $(CPP_FILES) $(H_FILES)
.PHONY: all clean format
build/%.o: %.cpp
$(CXX) $(CXXFLAGS) $(OPTFLAGS) -I ./ -I ../ZAPD -I ../ZAPDUtils -I ../lib/tinyxml2 -c $(OUTPUT_OPTION) $<
$(LIB): $(O_FILES)
$(AR) rcs $@ $^

View File

@@ -0,0 +1,372 @@
#include "RoomExporter.h"
#include "CollisionExporter.h"
#include "Utils/BinaryWriter.h"
#include <Utils/DiskFile.h>
#include "Utils/MemoryStream.h"
#include "ZRoom/Commands/SetCameraSettings.h"
#include "ZRoom/Commands/SetCollisionHeader.h"
#include "ZRoom/Commands/SetCsCamera.h"
#include "ZRoom/Commands/SetEchoSettings.h"
#include "ZRoom/Commands/SetEntranceList.h"
#include "ZRoom/Commands/SetLightingSettings.h"
#include "ZRoom/Commands/SetMesh.h"
#include "ZRoom/Commands/SetRoomBehavior.h"
#include "ZRoom/Commands/SetRoomList.h"
#include "ZRoom/Commands/SetSkyboxModifier.h"
#include "ZRoom/Commands/SetSkyboxSettings.h"
#include "ZRoom/Commands/SetSoundSettings.h"
#include "ZRoom/Commands/SetSpecialObjects.h"
#include "ZRoom/Commands/SetStartPositionList.h"
#include "ZRoom/Commands/SetTimeSettings.h"
#include "ZRoom/Commands/SetWind.h"
void ExporterExample_Room::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZRoom* room = dynamic_cast<ZRoom*>(res);
// MemoryStream* memStream = new MemoryStream();
// BinaryWriter* writer = new BinaryWriter(memStream);
for (size_t i = 0; i < room->commands.size() * 8; i++)
writer->Write((uint8_t)0);
for (size_t i = 0; i < room->commands.size(); i++)
{
ZRoomCommand* cmd = room->commands[i];
writer->Seek(i * 8, SeekOffsetType::Start);
writer->Write((uint8_t)cmd->cmdID);
switch (cmd->cmdID)
{
case RoomCommand::SetWind:
{
SetWind* cmdSetWind = (SetWind*)cmd;
writer->Write((uint8_t)0); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(cmdSetWind->windWest); // 0x04
writer->Write(cmdSetWind->windVertical); // 0x05
writer->Write(cmdSetWind->windSouth); // 0x06
writer->Write(cmdSetWind->clothFlappingStrength); // 0x07
}
break;
case RoomCommand::SetTimeSettings:
{
SetTimeSettings* cmdTime = (SetTimeSettings*)cmd;
writer->Write((uint8_t)0); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(cmdTime->hour); // 0x04
writer->Write(cmdTime->min); // 0x05
writer->Write(cmdTime->unk); // 0x06
writer->Write((uint8_t)0); // 0x07
}
break;
case RoomCommand::SetSkyboxModifier:
{
SetSkyboxModifier* cmdSkybox = (SetSkyboxModifier*)cmd;
writer->Write((uint8_t)0); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(cmdSkybox->disableSky); // 0x04
writer->Write(cmdSkybox->disableSunMoon); // 0x05
writer->Write((uint8_t)0); // 0x06
writer->Write((uint8_t)0); // 0x07
}
break;
case RoomCommand::SetEchoSettings:
{
SetEchoSettings* cmdEcho = (SetEchoSettings*)cmd;
writer->Write((uint8_t)0); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write((uint8_t)0); // 0x04
writer->Write((uint8_t)0); // 0x05
writer->Write((uint8_t)0); // 0x06
writer->Write((uint8_t)cmdEcho->echo); // 0x07
}
break;
case RoomCommand::SetSoundSettings:
{
SetSoundSettings* cmdSound = (SetSoundSettings*)cmd;
writer->Write((uint8_t)cmdSound->reverb); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write((uint8_t)0); // 0x04
writer->Write((uint8_t)0); // 0x05
writer->Write(cmdSound->nightTimeSFX); // 0x06
writer->Write(cmdSound->musicSequence); // 0x07
}
break;
case RoomCommand::SetSkyboxSettings:
{
SetSkyboxSettings* cmdSkybox = (SetSkyboxSettings*)cmd;
writer->Write((uint8_t)cmdSkybox->unk1); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write((uint8_t)cmdSkybox->skyboxNumber); // 0x04
writer->Write((uint8_t)cmdSkybox->cloudsType); // 0x05
writer->Write((uint8_t)cmdSkybox->isIndoors); // 0x06
}
break;
case RoomCommand::SetRoomBehavior:
{
SetRoomBehavior* cmdRoom = (SetRoomBehavior*)cmd;
writer->Write((uint8_t)cmdRoom->gameplayFlags); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(cmdRoom->gameplayFlags2); // 0x04
}
break;
case RoomCommand::SetCsCamera:
{
SetCsCamera* cmdCsCam = (SetCsCamera*)cmd;
writer->Write((uint8_t)cmdCsCam->cameras.size()); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(cmdCsCam->segmentOffset); // 0x04
}
break;
case RoomCommand::SetMesh:
{
SetMesh* cmdMesh = (SetMesh*)cmd;
int baseStreamEnd = writer->GetStream().get()->GetLength();
writer->Write((uint8_t)cmdMesh->data); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(baseStreamEnd); // 0x04
uint32_t oldOffset = writer->GetBaseAddress();
writer->Seek(baseStreamEnd, SeekOffsetType::Start);
// TODO: NOT DONE
writer->Write(cmdMesh->meshHeaderType);
if (cmdMesh->meshHeaderType == 0)
{
// writer->Write(cmdMesh->)
}
else if (cmdMesh->meshHeaderType == 1)
{
}
else if (cmdMesh->meshHeaderType == 2)
{
}
writer->Seek(oldOffset, SeekOffsetType::Start);
}
break;
case RoomCommand::SetCameraSettings:
{
SetCameraSettings* cmdCam = (SetCameraSettings*)cmd;
writer->Write((uint8_t)cmdCam->cameraMovement); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(cmdCam->mapHighlight); // 0x04
}
break;
case RoomCommand::SetLightingSettings:
{
SetLightingSettings* cmdLight = (SetLightingSettings*)cmd;
writer->Write((uint8_t)cmdLight->settings.size()); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(cmdLight->segmentOffset); // 0x04
uint32_t oldOffset = writer->GetBaseAddress();
writer->Seek(cmdLight->segmentOffset, SeekOffsetType::Start);
for (LightingSettings setting : cmdLight->settings)
{
writer->Write(setting.ambientClrR);
writer->Write(setting.ambientClrG);
writer->Write(setting.ambientClrB);
writer->Write(setting.diffuseClrA_R);
writer->Write(setting.diffuseClrA_G);
writer->Write(setting.diffuseClrA_B);
writer->Write(setting.diffuseDirA_X);
writer->Write(setting.diffuseDirA_Y);
writer->Write(setting.diffuseDirA_Z);
writer->Write(setting.diffuseClrB_R);
writer->Write(setting.diffuseClrB_G);
writer->Write(setting.diffuseClrB_B);
writer->Write(setting.diffuseDirB_X);
writer->Write(setting.diffuseDirB_Y);
writer->Write(setting.diffuseDirB_Z);
writer->Write(setting.fogClrR);
writer->Write(setting.fogClrG);
writer->Write(setting.fogClrB);
writer->Write(setting.unk);
writer->Write(setting.drawDistance);
}
writer->Seek(oldOffset, SeekOffsetType::Start);
}
break;
case RoomCommand::SetRoomList:
{
SetRoomList* cmdRoom = (SetRoomList*)cmd;
writer->Write((uint8_t)cmdRoom->romfile->rooms.size()); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
auto baseStreamEnd = writer->GetLength();
writer->Write(baseStreamEnd); // 0x04
uint32_t oldOffset = writer->GetBaseAddress();
writer->Seek(baseStreamEnd, SeekOffsetType::Start);
for (const auto& entry : cmdRoom->romfile->rooms)
{
writer->Write(entry.virtualAddressStart);
writer->Write(entry.virtualAddressEnd);
}
writer->Seek(oldOffset, SeekOffsetType::Start);
}
break;
case RoomCommand::SetCollisionHeader:
{
SetCollisionHeader* cmdCollHeader = (SetCollisionHeader*)cmd;
int streamEnd = writer->GetStream().get()->GetLength();
writer->Write((uint8_t)0); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(streamEnd); // 0x04
// TODO: NOT DONE
uint32_t oldOffset = writer->GetBaseAddress();
writer->Seek(streamEnd, SeekOffsetType::Start);
ExporterExample_Collision colExp = ExporterExample_Collision();
colExp.Save(cmdCollHeader->collisionHeader, outPath, writer);
writer->Seek(oldOffset, SeekOffsetType::Start);
}
break;
case RoomCommand::SetEntranceList:
{
SetEntranceList* cmdEntrance = (SetEntranceList*)cmd;
uint32_t baseStreamEnd = writer->GetStream().get()->GetLength();
writer->Write((uint8_t)0); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(baseStreamEnd); // 0x04
uint32_t oldOffset = writer->GetBaseAddress();
writer->Seek(baseStreamEnd, SeekOffsetType::Start);
for (EntranceEntry entry : cmdEntrance->entrances)
{
writer->Write((uint8_t)entry.startPositionIndex);
writer->Write((uint8_t)entry.roomToLoad);
}
writer->Seek(oldOffset, SeekOffsetType::Start);
}
break;
case RoomCommand::SetSpecialObjects:
{
SetSpecialObjects* cmdSpecObj = (SetSpecialObjects*)cmd;
writer->Write((uint8_t)cmdSpecObj->elfMessage); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write((uint8_t)0); // 0x04
writer->Write((uint8_t)0); // 0x05
writer->Write((uint16_t)cmdSpecObj->globalObject); // 0x06
}
break;
case RoomCommand::SetStartPositionList:
{
SetStartPositionList* cmdStartPos = (SetStartPositionList*)cmd;
uint32_t baseStreamEnd = writer->GetStream().get()->GetLength();
writer->Write((uint8_t)cmdStartPos->actors.size()); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write(baseStreamEnd); // 0x04
uint32_t oldOffset = writer->GetBaseAddress();
writer->Seek(baseStreamEnd, SeekOffsetType::Start);
for (ActorSpawnEntry entry : cmdStartPos->actors)
{
writer->Write(entry.actorNum);
writer->Write(entry.posX);
writer->Write(entry.posY);
writer->Write(entry.posZ);
writer->Write(entry.rotX);
writer->Write(entry.rotY);
writer->Write(entry.rotZ);
writer->Write(entry.params);
}
writer->Seek(oldOffset, SeekOffsetType::Start);
}
break;
case RoomCommand::EndMarker:
{
writer->Write((uint8_t)0); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write((uint8_t)0); // 0x04
writer->Write((uint8_t)0); // 0x05
writer->Write((uint8_t)0); // 0x06
writer->Write((uint8_t)0); // 0x07
}
break;
default:
printf("UNIMPLEMENTED COMMAND: %i\n", (int)cmd->cmdID);
writer->Write((uint8_t)0); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write((uint8_t)0); // 0x04
writer->Write((uint8_t)0); // 0x05
writer->Write((uint8_t)0); // 0x06
writer->Write((uint8_t)0); // 0x07
break;
}
}
// writer->Close();
// DiskFile::WriteAllBytes(StringHelper::Sprintf("%s", res->GetName().c_str()),
// memStream->ToVector());
}

View File

@@ -0,0 +1,10 @@
#pragma once
#include "ZResource.h"
#include "ZRoom/ZRoom.h"
class ExporterExample_Room : public ZResourceExporter
{
public:
void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View File

@@ -0,0 +1,14 @@
#include "TextureExporter.h"
#include "../ZAPD/ZFile.h"
void ExporterExample_Texture::Save(ZResource* res, [[maybe_unused]] const fs::path& outPath,
BinaryWriter* writer)
{
ZTexture* tex = (ZTexture*)res;
auto data = tex->parent->GetRawData();
for (offset_t i = tex->GetRawDataIndex(); i < tex->GetRawDataIndex() + tex->GetRawDataSize();
i++)
writer->Write(data[i]);
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include "Utils/BinaryWriter.h"
#include "ZResource.h"
#include "ZTexture.h"
class ExporterExample_Texture : public ZResourceExporter
{
public:
void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

21
ZAPDTR/LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Zelda Reverse Engineering Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

134
ZAPDTR/Makefile Normal file
View File

@@ -0,0 +1,134 @@
# use variables in submakes
export
OPTIMIZATION_ON ?= 1
ASAN ?= 0
DEPRECATION_ON ?= 1
DEBUG ?= 0
COPYCHECK_ARGS ?=
LLD ?= 0
WERROR ?= 0
# Use clang++ if available, else use g++
ifeq ($(shell command -v clang++ >/dev/null 2>&1; echo $$?),0)
CXX := clang++
else
CXX := g++
endif
INC := -I ZAPD -I lib/libgfxd -I lib/tinyxml2 -I ZAPDUtils
CXXFLAGS := -fpic -std=c++17 -Wall -Wextra -fno-omit-frame-pointer
OPTFLAGS :=
ifneq ($(DEBUG),0)
OPTIMIZATION_ON = 0
CXXFLAGS += -g3 -DDEVELOPMENT -D_DEBUG
COPYCHECK_ARGS += --devel
DEPRECATION_ON = 0
endif
ifneq ($(WERROR),0)
CXXFLAGS += -Werror
endif
ifeq ($(OPTIMIZATION_ON),0)
OPTFLAGS := -O0
else
OPTFLAGS := -O2
endif
ifneq ($(ASAN),0)
CXXFLAGS += -fsanitize=address -fsanitize=pointer-compare -fsanitize=pointer-subtract -fsanitize=undefined
endif
ifneq ($(DEPRECATION_ON),0)
CXXFLAGS += -DDEPRECATION_ON
endif
# CXXFLAGS += -DTEXTURE_DEBUG
LDFLAGS := -lm -ldl -lpng
# Use LLD if available. Set LLD=0 to not use it
ifeq ($(shell command -v ld.lld >/dev/null 2>&1; echo $$?),0)
LLD := 1
endif
ifneq ($(LLD),0)
LDFLAGS += -fuse-ld=lld
endif
UNAME := $(shell uname)
UNAMEM := $(shell uname -m)
ifneq ($(UNAME), Darwin)
LDFLAGS += -Wl,-export-dynamic -lstdc++fs
EXPORTERS := -Wl,--whole-archive ExporterTest/ExporterTest.a -Wl,--no-whole-archive
else
EXPORTERS := -Wl,-force_load ExporterTest/ExporterTest.a
ifeq ($(UNAMEM),arm64)
ifeq ($(shell brew list libpng > /dev/null 2>&1; echo $$?),0)
LDFLAGS += -L $(shell brew --prefix)/lib
INC += -I $(shell brew --prefix)/include
else
$(error Please install libpng via Homebrew)
endif
endif
endif
ZAPD_SRC_DIRS := $(shell find ZAPD -type d)
SRC_DIRS = $(ZAPD_SRC_DIRS) lib/tinyxml2
ZAPD_CPP_FILES := $(foreach dir,$(ZAPD_SRC_DIRS),$(wildcard $(dir)/*.cpp))
ZAPD_H_FILES := $(foreach dir,$(ZAPD_SRC_DIRS),$(wildcard $(dir)/*.h))
CPP_FILES += $(ZAPD_CPP_FILES) lib/tinyxml2/tinyxml2.cpp
O_FILES := $(foreach f,$(CPP_FILES:.cpp=.o),build/$f)
O_FILES += build/ZAPD/BuildInfo.o
# create build directories
$(shell mkdir -p $(foreach dir,$(SRC_DIRS),build/$(dir)))
# Main targets
all: ZAPD.out copycheck
build/ZAPD/BuildInfo.o:
python3 ZAPD/genbuildinfo.py $(COPYCHECK_ARGS)
$(CXX) $(CXXFLAGS) $(OPTFLAGS) $(INC) -c $(OUTPUT_OPTION) build/ZAPD/BuildInfo.cpp
copycheck: ZAPD.out
python3 copycheck.py
clean:
rm -rf build ZAPD.out
$(MAKE) -C lib/libgfxd clean
$(MAKE) -C ZAPDUtils clean
$(MAKE) -C ExporterTest clean
rebuild: clean all
format:
clang-format-11 -i $(ZAPD_CPP_FILES) $(ZAPD_H_FILES)
$(MAKE) -C ZAPDUtils format
$(MAKE) -C ExporterTest format
.PHONY: all build/ZAPD/BuildInfo.o copycheck clean rebuild format
build/%.o: %.cpp
$(CXX) $(CXXFLAGS) $(OPTFLAGS) $(INC) -c $(OUTPUT_OPTION) $<
# Submakes
lib/libgfxd/libgfxd.a:
$(MAKE) -C lib/libgfxd
.PHONY: ExporterTest
ExporterTest:
$(MAKE) -C ExporterTest
.PHONY: ZAPDUtils
ZAPDUtils:
$(MAKE) -C ZAPDUtils
# Linking
ZAPD.out: $(O_FILES) lib/libgfxd/libgfxd.a ExporterTest ZAPDUtils
$(CXX) $(CXXFLAGS) $(O_FILES) lib/libgfxd/libgfxd.a ZAPDUtils/ZAPDUtils.a $(EXPORTERS) $(LDFLAGS) $(OUTPUT_OPTION)

163
ZAPDTR/README.md Normal file
View File

@@ -0,0 +1,163 @@
# ZAPD: Zelda Asset Processor for Decomp
## Compiling
### Dependencies
ZAPD needs a compiler with C++17 support.
ZAPD has the following library dependencies:
- `libpng`
In a Debian/Ubuntu based environment, those could be installed with the following command:
```bash
sudo apt install libpng-dev
```
On a Mac, you will need to install libpng with Homebrew or MacPorts; we currently only support Homebrew. You can run
```bash
brew install libpng
```
to install it via Homebrew.
### Building
#### Linux / *nix
ZAPD uses the clasic `Makefile` approach. To build just run `make` (or even better `make -j` for faster compilations).
You can configure a bit your ZAPD build with the following options:
- `OPTIMIZATION_ON`: If set to `0` optimizations will be disabled (compile with `-O0`). Any other value compiles with `-O2`. Defaults to `1`.
- `ASAN`: If it is set to a non-zero then ZAPD will be compiled with Address Sanitizer enabled (`-fsanitize=address`). Defaults to `0`.
- `DEPRECATION_ON`: If it is set to a zero then deprecation warnings will be disabled. Defaults to `1`.
- `DEBUG`: If non-zero, ZAPD will be compiled in _development mode_. This implies the following:
- Debugging symbols enabled (`-g3`). They are disabled by default.
- `OPTIMIZATION_ON=0`: Disables optimizations (`-O0`).
- `DEPRECATION_ON=0`: Disables deprecation warnings.
- `LLD=1`: builds with the LLVM linker `ld.lld` instead of the system default.
As an example, if you want to build ZAPD with optimizations disabled and use the address sanitizer, you could use the following command:
```bash
make -j OPTIMIZATION_ON=0 ASAN=1
```
#### Windows
This repository contains `vcxproj` files for compiling under Visual Studio environments. See `ZAPD/ZAPD.vcxproj`.
## Invoking ZAPD
ZAPD needs a _File parsing mode_ to be passed as first parameter. The options are:
- `e`: "Extraction" mode.
- In this mode, ZAPD expects a XML file as input, a folder as ouput and a path to the baserom files.
- ZAPD will read the XML and use it as a guide to extract the contents of the specified asset file from the baserom folder.
- For more info of the format of those XMLs, see the [ZAPD extraction XML reference](docs/zapd_extraction_xml_reference.md).
- `bsf`: "Build source file" mode.
- This is an experimental mode.
- It was going to be used to let you have XMLs that aren't just for extraction. Might get used, might not. Still need to experiment on that.
- `btex`: "Build texture" mode.
- In this mode, ZAPD expects a PNG file as input, a filename as ouput and a texture type parameter (`-tt`).
- ZAPD will try to convert the given PNG into the contents of a `uint64_t` C array.
- `bren`: "Build (render) background" mode.
- In this mode, ZAPD expects a JPG file as input and a filename as ouput.
- ZAPD will try to convert the given JPG into the contents of a `uint64_t` C array.
- `blb`: "Build blob" mode.
- In this mode, ZAPD expects a BIN file as input and a filename as ouput.
- ZAPD will try to convert the given BIN into the contents of a `uint8_t` C array.
ZAPD also accepts the following list of extra parameters:
- `-i PATH` / `--inputpath PATH`: Set input path.
- `-o PATH` / `--outputpath PATH`: Set output path.
- `-b PATH` / `--baserompath`: Set baserom path.
- Can be used only in `e` or `bsf` modes.
- `-osf PATH`: Set source output path. This is the path where the `.c` and `.h` files will be extracted to. If omitted, it will use the value passed to `--outputpath` parameter.
- `-gsf MODE`: Generate source file during extraction. If `MODE` is `1`, C source files will be generated.
- Can be used only in `e` mode.
- `-crc` / `--output-crc`: Outputs a CRC file for each extracted texture.
- Can be used only in `e` or `bsf` modes.
- `-ulzdl MODE`: Use "Legacy ZDisplayList" instead of `libgfxd`. Set `MODE` to `1` to enable it.
- Can be used only in `e` or `bsf` modes.
- `-profile MODE`: Enable profiling. Set `MODE` to `1` to enable it.
- `-uer MODE`: Split resources into their individual components (enabled by default). Set `MODE` to non-`1` to disable it.
- `-tt TYPE`: Set texture type.
- Can be used only in mode `btex`.
- Valid values:
- `rgba32`
- `rgb5a1`
- `i4`
- `i8`
- `ia4`
- `ia8`
- `ia16`
- `ci4`
- `ci8`
- `-rconf PATH` Read Config File.
- `-eh`: Enable error handler.
- Only available in non-Windows environments.
- `-v MODE`: Enable verbosity. Currently there are 3 possible values:
- `0`: Default. Completely silent (except for warnings and errors).
- `1`: Information.
- `2` (and higher): Debug.
- `-wu` / `--warn-unaccounted`: Enable warnings for each unaccounted block of data found.
- Can be used only in `e` or `bsf` modes.
- `-vu` / `--verbose-unaccounted`: Changes how unaccounteds are outputted. Max 4 bytes per line (a word) and add a comment with the offset of each of those lines.
- Could be useful for looking at raw data or testing.
- Can be used only in `e` or `bsf` modes.
- `-tm MODE`: Test Mode (enables certain experimental features). To enable it, set `MODE` to `1`.
- `-se` / `--set-exporter` : Sets which exporter to use.
- `--gcc-compat` : Enables GCC compatibly mode. Slower.
- `-us` / `--unaccounted-static` : Mark unaccounted data as `static`
- `-s` / `--static` : Mark every asset as `static`.
- This behaviour can be overridden per asset using `Static=` in the respective XML node.
- `-W...`: warning flags, see below
Additionally, you can pass the flag `--version` to see the current ZAPD version. If that flag is passed, ZAPD will ignore any other parameter passed.
### Warning flags
ZAPD contains a variety of warning types, with similar syntax to GCC or Clang's compiler warnings. Warnings can have three levels:
- Off (does not display anything)
- Warn (print a warning but continue processing)
- Err (behave like an error, i.e. print and throw an exception to crash ZAPD when occurs)
Each warning type uses one of these by default, but can be modified with flags, similarly to GCC or Clang:
- `-Wfoo` enables warnings of type `foo`
- `-Wno-foo` disables warnings of type `foo`
- `-Werror=foo` escalates `foo` to behave like an error
- `-Weverything` enables all warnings (they may be turned off using `-Wno-` flags afterwards)
- `-Werror` escalates all enabled warnings to errors
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 |
There are also errors that do not have a type, and cannot be disabled.
For example, here we have invoked ZAPD in the usual way to extract using a (rather badly-written) XML, but escalating `-Wintersection` to an error:
![ZAPD warnings example](docs/zapd_warning_example.png?raw=true)

521
ZAPDTR/ZAPD/CMakeLists.txt Normal file
View File

@@ -0,0 +1,521 @@
set(PROJECT_NAME ZAPDLib)
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
#set(CMAKE_C_STANDARD 11 CACHE STRING "The C standard to use")
set(CMAKE_C_STANDARD 11)
################################################################################
# Source groups
################################################################################
set(Header_Files
"../lib/tinyxml2/tinyxml2.h"
"CRC32.h"
"Declaration.h"
"FileWorker.h"
"GameConfig.h"
"Globals.h"
"ImageBackend.h"
"OutputFormatter.h"
"WarningHandler.h"
"CrashHandler.h"
)
source_group("Header Files" FILES ${Header_Files})
set(Header_Files__Libraries
"ctpl_stl.h"
)
source_group("Header Files\\Libraries" FILES ${Header_Files__Libraries})
set(Header_Files__Libraries__libgfxd
"../lib/libgfxd/gbi.h"
"../lib/libgfxd/gfxd.h"
"../lib/libgfxd/priv.h"
)
source_group("Header Files\\Libraries\\libgfxd" FILES ${Header_Files__Libraries__libgfxd})
set(Header_Files__Yaz0
"yaz0/readwrite.h"
"yaz0/yaz0.h"
)
source_group("Header Files\\Yaz0" FILES ${Header_Files__Yaz0})
set(Header_Files__Z64
"OtherStructs/SkinLimbStructs.h"
"OtherStructs/CutsceneMM_Commands.h"
"OtherStructs/Cutscene_Commands.h"
"ZAnimation.h"
"ZActorList.h"
"ZArray.h"
"ZAudio.h"
"ZBackground.h"
"ZBlob.h"
"ZCollision.h"
"ZCollisionPoly.h"
"ZCutscene.h"
"ZDisplayList.h"
"ZFile.h"
"ZLimb.h"
"ZMtx.h"
"ZPath.h"
"ZPlayerAnimationData.h"
"ZResource.h"
"ZRom.h"
"ZScalar.h"
"ZSkeleton.h"
"ZSurfaceType.h"
"ZString.h"
"ZSymbol.h"
"ZText.h"
"ZTexture.h"
"ZTextureAnimation.h"
"ZVector.h"
"ZVtx.h"
)
source_group("Header Files\\Z64" FILES ${Header_Files__Z64})
set(Header_Files__Z64__ZRoom
"ZRoom/ZRoom.h"
"ZRoom/ZRoomCommand.h"
)
source_group("Header Files\\Z64\\ZRoom" FILES ${Header_Files__Z64__ZRoom})
set(Header_Files__Z64__ZRoom__Commands
"ZRoom/Commands/EndMarker.h"
"ZRoom/Commands/SetActorCutsceneList.h"
"ZRoom/Commands/SetActorList.h"
"ZRoom/Commands/SetAlternateHeaders.h"
"ZRoom/Commands/SetAnimatedMaterialList.h"
"ZRoom/Commands/SetCameraSettings.h"
"ZRoom/Commands/SetCollisionHeader.h"
"ZRoom/Commands/SetCsCamera.h"
"ZRoom/Commands/SetCutscenes.h"
"ZRoom/Commands/SetEchoSettings.h"
"ZRoom/Commands/SetEntranceList.h"
"ZRoom/Commands/SetExitList.h"
"ZRoom/Commands/SetLightingSettings.h"
"ZRoom/Commands/SetLightList.h"
"ZRoom/Commands/SetMesh.h"
"ZRoom/Commands/SetMinimapChests.h"
"ZRoom/Commands/SetMinimapList.h"
"ZRoom/Commands/SetObjectList.h"
"ZRoom/Commands/SetPathways.h"
"ZRoom/Commands/SetRoomBehavior.h"
"ZRoom/Commands/SetRoomList.h"
"ZRoom/Commands/SetSkyboxModifier.h"
"ZRoom/Commands/SetSkyboxSettings.h"
"ZRoom/Commands/SetSoundSettings.h"
"ZRoom/Commands/SetSpecialObjects.h"
"ZRoom/Commands/SetStartPositionList.h"
"ZRoom/Commands/SetTimeSettings.h"
"ZRoom/Commands/SetTransitionActorList.h"
"ZRoom/Commands/SetWind.h"
"ZRoom/Commands/SetWorldMapVisited.h"
"ZRoom/Commands/Unused09.h"
"ZRoom/Commands/Unused1D.h"
"ZRoom/Commands/ZRoomCommandUnk.h"
)
source_group("Header Files\\Z64\\ZRoom\\Commands" FILES ${Header_Files__Z64__ZRoom__Commands})
set(Resource_Files
"../../OTRExporter/CFG/SymbolMap_OoTMqDbg.txt"
)
source_group("Resource Files" FILES ${Resource_Files})
set(Source_Files
"CrashHandler.cpp"
"Declaration.cpp"
"FileWorker.cpp"
"GameConfig.cpp"
"Globals.cpp"
"ImageBackend.cpp"
"Main.cpp"
"OutputFormatter.cpp"
"WarningHandler.cpp"
)
source_group("Source Files" FILES ${Source_Files})
set(Source_Files__Libraries__libgfxd
"../lib/libgfxd/gfxd.c"
"../lib/libgfxd/uc.c"
"../lib/libgfxd/uc_f3dex2.c"
)
source_group("Source Files\\Libraries\\libgfxd" FILES ${Source_Files__Libraries__libgfxd})
set(Source_Files__Yaz0
"yaz0/yaz0.cpp"
)
source_group("Source Files\\Yaz0" FILES ${Source_Files__Yaz0})
set(Source_Files__Z64
"OtherStructs/SkinLimbStructs.cpp"
"OtherStructs/CutsceneMM_Commands.cpp"
"OtherStructs/Cutscene_Commands.cpp"
"ZAnimation.cpp"
"ZActorList.cpp"
"ZArray.cpp"
"ZAudio.cpp"
"ZAudioDecode.cpp"
"ZBackground.cpp"
"ZBlob.cpp"
"ZCollision.cpp"
"ZCollisionPoly.cpp"
"ZCutscene.cpp"
"ZDisplayList.cpp"
"ZFile.cpp"
"ZLimb.cpp"
"ZMtx.cpp"
"ZPath.cpp"
"ZPlayerAnimationData.cpp"
"ZResource.cpp"
"ZRom.cpp"
"ZScalar.cpp"
"ZSkeleton.cpp"
"ZSurfaceType.cpp"
"ZString.cpp"
"ZSymbol.cpp"
"ZText.cpp"
"ZTexture.cpp"
"ZTextureAnimation.cpp"
"ZVector.cpp"
"ZVtx.cpp"
)
source_group("Source Files\\Z64" FILES ${Source_Files__Z64})
set(Source_Files__Z64__ZRoom
"ZRoom/ZRoom.cpp"
"ZRoom/ZRoomCommand.cpp"
)
source_group("Source Files\\Z64\\ZRoom" FILES ${Source_Files__Z64__ZRoom})
set(Source_Files__Z64__ZRoom__Commands
"ZRoom/Commands/EndMarker.cpp"
"ZRoom/Commands/SetActorCutsceneList.cpp"
"ZRoom/Commands/SetActorList.cpp"
"ZRoom/Commands/SetAlternateHeaders.cpp"
"ZRoom/Commands/SetAnimatedMaterialList.cpp"
"ZRoom/Commands/SetCameraSettings.cpp"
"ZRoom/Commands/SetCollisionHeader.cpp"
"ZRoom/Commands/SetCsCamera.cpp"
"ZRoom/Commands/SetCutscenes.cpp"
"ZRoom/Commands/SetEchoSettings.cpp"
"ZRoom/Commands/SetEntranceList.cpp"
"ZRoom/Commands/SetExitList.cpp"
"ZRoom/Commands/SetLightingSettings.cpp"
"ZRoom/Commands/SetLightList.cpp"
"ZRoom/Commands/SetMesh.cpp"
"ZRoom/Commands/SetMinimapChests.cpp"
"ZRoom/Commands/SetMinimapList.cpp"
"ZRoom/Commands/SetObjectList.cpp"
"ZRoom/Commands/SetPathways.cpp"
"ZRoom/Commands/SetRoomBehavior.cpp"
"ZRoom/Commands/SetRoomList.cpp"
"ZRoom/Commands/SetSkyboxModifier.cpp"
"ZRoom/Commands/SetSkyboxSettings.cpp"
"ZRoom/Commands/SetSoundSettings.cpp"
"ZRoom/Commands/SetSpecialObjects.cpp"
"ZRoom/Commands/SetStartPositionList.cpp"
"ZRoom/Commands/SetTimeSettings.cpp"
"ZRoom/Commands/SetTransitionActorList.cpp"
"ZRoom/Commands/SetWind.cpp"
"ZRoom/Commands/SetWorldMapVisited.cpp"
"ZRoom/Commands/Unused09.cpp"
"ZRoom/Commands/Unused1D.cpp"
"ZRoom/Commands/ZRoomCommandUnk.cpp"
)
source_group("Source Files\\Z64\\ZRoom\\Commands" FILES ${Source_Files__Z64__ZRoom__Commands})
file(GLOB Source_Files__Utils RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "Utils/*.c" "Utils/*.cpp")
source_group("Source Files\\Utils" FILES ${Source_Files__Utils})
file(GLOB Header_Files__Utils RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "Utils/*.h")
source_group("Header Files\\Utils" FILES ${Header_Files__Utils})
set(ALL_FILES
${Header_Files}
${Header_Files__Libraries}
${Header_Files__Libraries__libgfxd}
${Header_Files__Yaz0}
${Header_Files__Z64}
${Header_Files__Z64__ZRoom}
${Header_Files__Z64__ZRoom__Commands}
${Header_Files__Utils}
${Resource_Files}
${Source_Files}
${Source_Files__Libraries__libgfxd}
${Source_Files__Yaz0}
${Source_Files__Z64}
${Source_Files__Z64__ZRoom}
${Source_Files__Z64__ZRoom__Commands}
${Source_Files__Utils}
${any__any}
)
################################################################################
# Target
################################################################################
add_library(${PROJECT_NAME} STATIC ${ALL_FILES})
add_executable(ZAPD ExecutableMain.cpp)
target_link_libraries(ZAPD ${PROJECT_NAME})
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
use_props(${PROJECT_NAME} "${CMAKE_CONFIGURATION_TYPES}" "${DEFAULT_CXX_PROPS}")
use_props(ZAPD "${CMAKE_CONFIGURATION_TYPES}" "${DEFAULT_CXX_PROPS}")
endif()
################################################################################
# Includes for CMake from *.props
################################################################################
set(ROOT_NAMESPACE ZAPD)
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
set_target_properties(${PROJECT_NAME} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE "TRUE"
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
set_target_properties(${PROJECT_NAME} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE "TRUE"
)
endif()
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin")
set_target_properties(ZAPD PROPERTIES
OUTPUT_NAME "ZAPD.out"
)
endif()
################################################################################
# MSVC runtime library
################################################################################
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
foreach(ZTarget ${PROJECT_NAME} ZAPD)
get_property(MSVC_RUNTIME_LIBRARY_DEFAULT TARGET ${ZTarget} PROPERTY MSVC_RUNTIME_LIBRARY)
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
string(CONCAT "MSVC_RUNTIME_LIBRARY_STR"
$<$<CONFIG:Debug>:
MultiThreadedDebug
>
$<$<CONFIG:Release>:
MultiThreaded
>
$<$<NOT:$<OR:$<CONFIG:Debug>,$<CONFIG:Release>>>:${MSVC_RUNTIME_LIBRARY_DEFAULT}>
)
endif()
set_target_properties(${ZTarget} PROPERTIES MSVC_RUNTIME_LIBRARY ${MSVC_RUNTIME_LIBRARY_STR})
endforeach()
endif()
################################################################################
# Compile definitions
################################################################################
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_compile_definitions(${PROJECT_NAME} PRIVATE
"_CRT_SECURE_NO_WARNINGS;"
"_MBCS"
STORMLIB_NO_AUTO_LINK
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
target_compile_definitions(${PROJECT_NAME} PRIVATE
"$<$<CONFIG:Debug>:"
"_CRT_SECURE_NO_WARNINGS"
">"
"_MBCS"
STORMLIB_NO_AUTO_LINK
)
endif()
endif()
################################################################################
# Compile and link options
################################################################################
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(CMAKE_FIND_FRAMEWORK LAST)
endif()
################################################################################
# Find/download PNG for Android
################################################################################
if (CMAKE_SYSTEM_NAME STREQUAL "Android")
find_package(PNG QUIET)
if (NOT ${PNG_FOUND})
include(FetchContent)
FetchContent_Declare(
png
GIT_REPOSITORY https://github.com/glennrp/libpng.git
GIT_TAG v1.6.37
OVERRIDE_FIND_PACKAGE
)
message("PNG not found. Downloading now...")
FetchContent_MakeAvailable(png)
message("PNG downloaded to " ${FETCHCONTENT_BASE_DIR}/png-src)
set (PNG_PNG_INCLUDE_DIR ${png_BINARY_DIR} ${png_SOURCE_DIR})
endif()
endif()
find_package(PNG REQUIRED)
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/src/resource
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/include
${CMAKE_CURRENT_SOURCE_DIR}/../../ZAPDTR/lib/libgfxd
${PNG_PNG_INCLUDE_DIR}/
.
)
if(MSVC)
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>:
/Od;
/RTC1
>
$<$<CONFIG:Release>:
/Oi;
/Gy
>
/permissive-;
/sdl;
/W3;
${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT};
${DEFAULT_CXX_EXCEPTION_HANDLING}
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>:
/Od
>
$<$<CONFIG:Release>:
/O2;
/Oi;
/Gy
>
/permissive-;
/sdl;
/W3;
${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT};
${DEFAULT_CXX_EXCEPTION_HANDLING}
)
endif()
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_link_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>:
/PROFILE
>
$<$<CONFIG:Release>:
/OPT:REF;
/OPT:ICF
>
/DEBUG:FULL
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
target_link_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Debug>:
/PROFILE
>
$<$<CONFIG:Release>:
/OPT:REF;
/OPT:ICF
>
/DEBUG:FULL
)
endif()
endif()
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang")
target_compile_options(${PROJECT_NAME} PUBLIC
-Wall -Wextra -Wno-error
-Wno-unused-parameter
-Wno-unused-function
-Wno-unused-variable
-Wno-missing-field-initializers
-Wno-parentheses
-Wno-narrowing
$<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion>
-pthread
)
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
target_link_options(${PROJECT_NAME} PUBLIC
-pthread
)
else()
target_link_options(${PROJECT_NAME} PUBLIC
-pthread
-Wl,-export-dynamic
)
endif()
endif()
################################################################################
# Dependencies
################################################################################
add_dependencies(${PROJECT_NAME}
OTRExporter
libultraship
)
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(ADDITIONAL_LIBRARY_DEPENDENCIES
"-WHOLEARCHIVE:$<TARGET_LINKER_FILE_DIR:OTRExporter>/$<TARGET_LINKER_FILE_NAME:OTRExporter>"
"libultraship;"
storm
PNG::PNG
)
endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
set(ADDITIONAL_LIBRARY_DEPENDENCIES
-Wl,-force_load $<TARGET_LINKER_FILE_DIR:OTRExporter>/$<TARGET_LINKER_FILE_NAME:OTRExporter>
"libultraship;"
PNG::PNG
${CMAKE_DL_LIBS}
Threads::Threads
)
elseif(CMAKE_SYSTEM_NAME STREQUAL "NintendoSwitch")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
set(ADDITIONAL_LIBRARY_DEPENDENCIES
-Wl,--whole-archive $<TARGET_LINKER_FILE_DIR:OTRExporter>/$<TARGET_LINKER_FILE_NAME:OTRExporter> -Wl,--no-whole-archive
"libultraship;"
PNG::PNG
Threads::Threads
)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
set(ADDITIONAL_LIBRARY_DEPENDENCIES
-Wl,--whole-archive $<TARGET_LINKER_FILE_DIR:OTRExporter>/$<TARGET_LINKER_FILE_NAME:OTRExporter> -Wl,--no-whole-archive
"libultraship;"
png
Threads::Threads
)
elseif(CMAKE_SYSTEM_NAME STREQUAL "CafeOS")
set(ADDITIONAL_LIBRARY_DEPENDENCIES
"libultraship;"
PNG::PNG
)
else()
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
set(ADDITIONAL_LIBRARY_DEPENDENCIES
-Wl,--whole-archive $<TARGET_LINKER_FILE_DIR:OTRExporter>/$<TARGET_LINKER_FILE_NAME:OTRExporter> -Wl,--no-whole-archive
"libultraship;"
PNG::PNG
${CMAKE_DL_LIBS}
Threads::Threads
)
endif()
if(CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
add_library(pathconf OBJECT pathconf.c)
target_link_libraries(${PROJECT_NAME} PUBLIC "${ADDITIONAL_LIBRARY_DEPENDENCIES}" $<TARGET_OBJECTS:pathconf> )
else()
target_link_libraries(${PROJECT_NAME} PUBLIC "${ADDITIONAL_LIBRARY_DEPENDENCIES}")
endif()

23
ZAPDTR/ZAPD/CRC32.h Normal file
View File

@@ -0,0 +1,23 @@
#pragma once
static uint32_t CRC32B(const unsigned char* message, int32_t size)
{
int32_t byte, crc;
int32_t mask;
crc = 0xFFFFFFFF;
for (int32_t i = 0; i < size; i++)
{
byte = message[i];
crc = crc ^ byte;
for (int32_t j = 7; j >= 0; j--)
{
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
}
return ~(uint32_t)(crc);
}

View File

@@ -0,0 +1,205 @@
#include "CrashHandler.h"
#include "Utils/StringHelper.h"
#if __has_include(<unistd.h>) && !defined(__ANDROID__)
#define HAS_POSIX 1
#else
#define HAS_POSIX 0
#endif
#include <array>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#if HAS_POSIX == 1
#include <csignal>
#include <cxxabi.h> // for __cxa_demangle
#include <dlfcn.h> // for dladdr
#include <execinfo.h>
#include <unistd.h>
#elif defined(_MSC_VER)
#include <Windows.h>
#include <DbgHelp.h>
#include <inttypes.h>
#pragma comment(lib, "Dbghelp.lib")
#endif
// Feel free to add more crash messages.
static std::array<const char* const, 14> crashEasterEgg = {
"\tYou've met with a terrible fate, haven't you?",
"\tSEA BEARS FOAM. SLEEP BEARS DREAMS. \n\tBOTH END IN THE SAME WAY: CRASSSH!",
"\tZAPD has fallen and cannot get up.",
"\tIT'S A SECRET TO EVERYBODY. \n\tBut it shouldn't be, you'd better ask about it!",
"\tI AM ERROR.",
"\tGRUMBLE,GRUMBLE...",
"\tDODONGO DISLIKES SMOKE \n\tAnd ZAPD dislikes whatever you fed it.",
"\tMay the way of the Hero lead \n\tto the debugger.",
"\tTHE WIND FISH SLUMBERS LONG... \n\tTHE HERO'S LIFE GONE... ",
"\tSEA BEARS FOAM, SLEEP BEARS DREAMS. \n\tBOTH END IN THE SAME WAY CRASSSH!",
"\tYou've met with a terrible fate, haven't you?",
"\tMaster, I calculate a 100% probability that ZAPD has crashed. \n\tAdditionally, the "
"batteries in your Wii Remote are nearly depleted.",
"\t CONGRATURATIONS! \n"
"\tAll Pages are displayed.\n"
"\t THANK YOU! \n"
"\t You are great debugger!",
"\tRCP is HUNG UP!!\n"
"\tOh! MY GOD!!",
};
#if HAS_POSIX == 1
void ErrorHandler(int sig)
{
std::array<void*, 4096> arr;
constexpr size_t nMaxFrames = arr.size();
size_t size = backtrace(arr.data(), nMaxFrames);
char** symbols = backtrace_symbols(arr.data(), nMaxFrames);
fprintf(stderr, "\nZAPD crashed. (Signal: %i)\n", sig);
srand(time(nullptr));
auto easterIndex = rand() % crashEasterEgg.size();
fprintf(stderr, "\n%s\n\n", crashEasterEgg[easterIndex]);
fprintf(stderr, "Traceback:\n");
for (size_t i = 1; i < size; i++)
{
Dl_info info;
uint32_t gotAddress = dladdr(arr[i], &info);
std::string functionName(symbols[i]);
if (gotAddress != 0 && info.dli_sname != nullptr)
{
int32_t status;
char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status);
const char* nameFound = info.dli_sname;
if (status == 0)
{
nameFound = demangled;
}
functionName = StringHelper::Sprintf("%s (+0x%X)", nameFound,
(char*)arr[i] - (char*)info.dli_saddr);
free(demangled);
}
fprintf(stderr, "%-3zd %s\n", i, functionName.c_str());
}
fprintf(stderr, "\n");
free(symbols);
exit(1);
}
#elif defined(_MSC_VER)
void printStack(CONTEXT* ctx)
{
BOOL result;
HANDLE process;
HANDLE thread;
HMODULE hModule;
ULONG frame;
DWORD64 displacement;
DWORD disp;
srand(time(nullptr));
auto easterIndex = rand() % crashEasterEgg.size();
fprintf(stderr, "\n%s\n\n", crashEasterEgg[easterIndex]);
#if defined(_M_AMD64)
STACKFRAME64 stack;
memset(&stack, 0, sizeof(STACKFRAME64));
#else
STACKFRAME stack;
memset(&stack, 0, sizeof(STACKFRAME));
#endif
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME + sizeof(TCHAR)];
char module[512];
PSYMBOL_INFO symbol = (PSYMBOL_INFO)buffer;
CONTEXT ctx2;
memcpy(&ctx2, ctx, sizeof(CONTEXT));
process = GetCurrentProcess();
thread = GetCurrentThread();
SymInitialize(process, nullptr, TRUE);
constexpr DWORD machineType =
#if defined(_M_AMD64)
IMAGE_FILE_MACHINE_AMD64;
#else
IMAGE_FILE_MACHINE_I386;
#endif
displacement = 0;
for (frame = 0;; frame++)
{
result = StackWalk(machineType, process, thread, &stack, &ctx2, nullptr,
SymFunctionTableAccess, SymGetModuleBase, nullptr);
if (!result)
{
break;
}
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME;
SymFromAddr(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbol);
#if defined(_M_AMD64)
IMAGEHLP_LINE64 line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
#else
IMAGEHLP_LINE line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE);
#endif
if (SymGetLineFromAddr(process, stack.AddrPC.Offset, &disp, &line))
{
fprintf(stderr, "%u\t %s in %s: line: %lu: \n", frame, symbol->Name, line.FileName,
line.LineNumber);
}
else
{
fprintf(stderr, "%u\tat % s\n", frame, symbol->Name);
hModule = nullptr;
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)(stack.AddrPC.Offset), &hModule);
if (hModule != nullptr)
{
GetModuleFileNameA(hModule, module, 512 - 1);
}
fprintf(stderr, "%u\tIn %s\n", frame, module);
}
}
}
LONG seh_filter(_EXCEPTION_POINTERS* ex)
{
fprintf(stderr, "EXCEPTION 0x%x occured\n", ex->ExceptionRecord->ExceptionCode);
printStack(ex->ContextRecord);
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
void CrashHandler_Init()
{
#if HAS_POSIX == 1
signal(SIGSEGV, ErrorHandler);
signal(SIGABRT, ErrorHandler);
#elif defined(_MSC_VER)
SetUnhandledExceptionFilter(seh_filter);
#elif !defined(__ANDROID__)
HANDLE_WARNING(WarningType::Always,
"tried to set error handler, but this ZAPD build lacks support for one", "");
#endif
}

View File

@@ -0,0 +1,6 @@
#ifndef CRASH_HANDLER_H
#define CRASH_HANDLER_H
void CrashHandler_Init();
#endif

236
ZAPDTR/ZAPD/Declaration.cpp Normal file
View File

@@ -0,0 +1,236 @@
#include "Declaration.h"
#include "Globals.h"
#include "ZVtx.h"
#include "Utils/StringHelper.h"
Declaration::Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nText)
{
address = nAddress;
alignment = nAlignment;
size = nSize;
text = nText;
}
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)
{
varType = nVarType;
varName = nVarName;
isArray = nIsArray;
}
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)
{
varType = nVarType;
varName = nVarName;
isArray = nIsArray;
arrayItemCnt = nArrayItemCnt;
}
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)
{
varType = nVarType;
varName = nVarName;
isArray = nIsArray;
arrayItemCntStr = nArrayItemCntStr;
}
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)
{
isExternal = nIsExternal;
}
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, "")
{
includePath = nIncludePath;
varType = nVarType;
varName = nVarName;
}
Declaration::~Declaration()
{
//for (auto item : vertexHack)
//delete item;
}
bool Declaration::IsStatic() const
{
switch (staticConf)
{
case StaticConfig::Off:
return false;
case StaticConfig::Global:
return Globals::Instance->forceStatic;
case StaticConfig::On:
return true;
}
return false;
}
std::string Declaration::GetNormalDeclarationStr() const
{
std::string output;
if (preText != "")
output += preText + "\n";
if (IsStatic())
{
output += "static ";
}
if (isArray)
{
if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt))
{
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);
}
else
{
output += StringHelper::Sprintf("%s %s[] = {\n", varType.c_str(), varName.c_str());
}
output += text + "\n";
}
else
{
output += StringHelper::Sprintf("%s %s = { ", varType.c_str(), varName.c_str());
output += text;
}
if (output.back() == '\n')
output += "};";
else
output += " };";
if (rightText != "")
output += " " + rightText + "";
output += "\n";
if (postText != "")
output += postText + "\n";
output += "\n";
return output;
}
std::string Declaration::GetExternalDeclarationStr() const
{
std::string output;
if (preText != "")
output += preText + "\n";
if (IsStatic())
{
output += "static ";
}
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";
return output;
}
std::string Declaration::GetExternStr() const
{
if (IsStatic() || varType == "" || isUnaccounted)
{
return "";
}
if (Globals::Instance->otrMode) /* && (varType == "Gfx" || varType == "u64" || varType == "AnimationHeader" || varType == "LinkAnimationHeader" ||
varType == "StandardLimb" || varType == "JointIndex" || varType == "Vtx" || varType == "FlexSkeletonHeader" || varType == "SkeletonHeader") ||
varType == "CollisionHeader") */
return "";
if (isArray)
{
if (arrayItemCntStr != "" && (IsStatic() || forceArrayCnt))
{
return StringHelper::Sprintf("extern %s %s[%s];\n", varType.c_str(), varName.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(),
arrayItemCnt);
}
else
return StringHelper::Sprintf("extern %s %s[];\n", varType.c_str(), varName.c_str());
}
return StringHelper::Sprintf("extern %s %s;\n", varType.c_str(), varName.c_str());
}
std::string Declaration::GetStaticForwardDeclarationStr() const
{
if (!IsStatic() || isUnaccounted)
return "";
if (isArray)
{
if (arrayItemCntStr == "" && arrayItemCnt == 0)
{
// Forward declaring static arrays without specifying the size is not allowed.
return "";
}
if (arrayItemCntStr != "")
{
return StringHelper::Sprintf("static %s %s[%s];\n", varType.c_str(), varName.c_str(),
arrayItemCntStr.c_str());
}
else
{
return StringHelper::Sprintf("static %s %s[%i];\n", varType.c_str(), varName.c_str(),
arrayItemCnt);
}
}
return StringHelper::Sprintf("static %s %s;\n", varType.c_str(), varName.c_str());
}

87
ZAPDTR/ZAPD/Declaration.h Normal file
View File

@@ -0,0 +1,87 @@
#pragma once
#include <string>
#include <vector>
#include <cstdint>
// TODO: should we drop the `_t` suffix because of UNIX compliance?
typedef uint32_t segptr_t;
typedef uint32_t offset_t;
#define SEGMENTED_NULL ((segptr_t)0)
enum class DeclarationAlignment
{
Align4,
Align8
};
enum class StaticConfig
{
Off,
Global,
On
};
class ZVtx;
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;
std::vector<ZVtx*> vertexHack;
bool isExternal = false;
bool isArray = false;
bool forceArrayCnt = false;
size_t arrayItemCnt = 0;
std::string arrayItemCntStr = "";
std::vector<segptr_t> references;
bool isUnaccounted = false;
bool isPlaceholder = false;
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);
Declaration(offset_t nAddress, const std::string& nIncludePath, size_t nSize,
const std::string& nVarType, const std::string& nVarName);
~Declaration();
bool IsStatic() const;
std::string GetNormalDeclarationStr() const;
std::string GetExternalDeclarationStr() const;
std::string GetExternStr() const;
std::string GetStaticForwardDeclarationStr() const;
protected:
Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
const std::string& nText);
};

View File

@@ -0,0 +1,5 @@
extern "C" int zapd_main(int argc, char* argv[]);
int main(int argc, char* argv[]) {
return zapd_main(argc, argv);
}

27
ZAPDTR/ZAPD/ExporterSet.h Normal file
View File

@@ -0,0 +1,27 @@
#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 (*ExporterSetFuncVoid4)(tinyxml2::XMLElement* reader);
typedef void (*ExporterSetResSave)(ZResource* res, BinaryWriter& writer);
//processCompilableFunc
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;
ExporterSetFuncVoid3 endProgramFunc = nullptr;
ExporterSetFuncVoid4 processCompilableFunc = nullptr;
};

View File

15
ZAPDTR/ZAPD/FileWorker.h Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
#include <map>
#include <string>
#include <vector>
#include "ZFile.h"
class FileWorker
{
public:
std::vector<ZFile*> files;
std::vector<ZFile*> externalFiles;
std::vector<int32_t> segments;
std::map<int32_t, std::vector<ZFile*>> segmentRefFiles;
};

207
ZAPDTR/ZAPD/GameConfig.cpp Normal file
View File

@@ -0,0 +1,207 @@
#include "GameConfig.h"
#include <functional>
#include <string_view>
#include <unordered_map>
#include "Utils/Directory.h"
#include <Utils/DiskFile.h>
#include "Utils/Path.h"
#include "ZFile.h"
#include "tinyxml2.h"
using ConfigFunc = void (GameConfig::*)(const tinyxml2::XMLElement&);
GameConfig::~GameConfig()
{
for (auto& declPair : segmentRefFiles)
{
for (auto& file : declPair.second)
{
delete file;
}
}
}
void GameConfig::ReadTexturePool(const fs::path& texturePoolXmlPath)
{
tinyxml2::XMLDocument doc;
tinyxml2::XMLError eResult = doc.LoadFile(texturePoolXmlPath.string().c_str());
if (eResult != tinyxml2::XML_SUCCESS)
{
fprintf(stderr, "Warning: Unable to read texture pool XML with error code %i\n", eResult);
return;
}
tinyxml2::XMLNode* root = doc.FirstChild();
if (root == nullptr)
return;
for (tinyxml2::XMLElement* child = root->FirstChildElement(); child != nullptr;
child = child->NextSiblingElement())
{
if (std::string_view(child->Name()) == "Texture")
{
std::string crcStr = child->Attribute("CRC");
fs::path texPath = child->Attribute("Path");
std::string texName;
uint32_t crc = strtoul(crcStr.c_str(), nullptr, 16);
texturePool[crc].path = texPath;
}
}
}
void GameConfig::GenSymbolMap(const fs::path& symbolMapPath)
{
auto symbolLines = DiskFile::ReadAllLines(symbolMapPath);
for (std::string& symbolLine : symbolLines)
{
auto split = StringHelper::Split(symbolLine, " ");
uint32_t addr = strtoul(split[0].c_str(), nullptr, 16);
std::string symbolName = split[1];
symbolMap[addr] = std::move(symbolName);
}
}
void GameConfig::ConfigFunc_SymbolMap(const tinyxml2::XMLElement& element)
{
std::string fileName = element.Attribute("File");
GenSymbolMap(Path::GetDirectoryName(configFilePath) / fileName);
}
void GameConfig::ConfigFunc_ActorList(const tinyxml2::XMLElement& element)
{
std::string fileName = element.Attribute("File");
std::vector<std::string> lines =
DiskFile::ReadAllLines(Path::GetDirectoryName(configFilePath) / fileName);
for (auto& line : lines)
actorList.emplace_back(std::move(line));
}
void GameConfig::ConfigFunc_ObjectList(const tinyxml2::XMLElement& element)
{
std::string fileName = element.Attribute("File");
std::vector<std::string> lines =
DiskFile::ReadAllLines(Path::GetDirectoryName(configFilePath) / fileName);
for (auto& line : lines)
objectList.emplace_back(std::move(line));
}
void GameConfig::ConfigFunc_EntranceList(const tinyxml2::XMLElement& element)
{
std::string fileName = element.Attribute("File");
std::vector<std::string> lines =
DiskFile::ReadAllLines(Path::GetDirectoryName(configFilePath) / fileName);
for (auto& line : lines)
entranceList.emplace_back(std::move(line));
}
void GameConfig::ConfigFunc_specialEntranceList(const tinyxml2::XMLElement& element)
{
std::string fileName = element.Attribute("File");
std::vector<std::string> lines =
DiskFile::ReadAllLines(Path::GetDirectoryName(configFilePath) / fileName);
for (auto& line : lines)
specialEntranceList.emplace_back(std::move(line));
}
void GameConfig::ConfigFunc_TexturePool(const tinyxml2::XMLElement& element)
{
std::string fileName = element.Attribute("File");
ReadTexturePool(Path::GetDirectoryName(configFilePath) / fileName);
}
void GameConfig::ConfigFunc_BGConfig(const tinyxml2::XMLElement& element)
{
bgScreenWidth = element.IntAttribute("ScreenWidth", 320);
bgScreenHeight = element.IntAttribute("ScreenHeight", 240);
}
void GameConfig::ConfigFunc_ExternalXMLFolder(const tinyxml2::XMLElement& element)
{
const char* pathValue = element.Attribute("Path");
if (pathValue == nullptr)
{
throw std::runtime_error(
StringHelper::Sprintf("Parse: Fatal error in configuration file.\n"
"\t Missing 'Path' attribute in `ExternalXMLFolder` element.\n"));
}
if (externalXmlFolder != "")
{
throw std::runtime_error(StringHelper::Sprintf("Parse: Fatal error in configuration file.\n"
"\t `ExternalXMLFolder` is duplicated.\n"));
}
externalXmlFolder = pathValue;
}
void GameConfig::ConfigFunc_ExternalFile(const tinyxml2::XMLElement& element)
{
const char* xmlPathValue = element.Attribute("XmlPath");
if (xmlPathValue == nullptr)
{
throw std::runtime_error(
StringHelper::Sprintf("Parse: Fatal error in configuration file.\n"
"\t Missing 'XmlPath' attribute in `ExternalFile` element.\n"));
}
const char* outPathValue = element.Attribute("OutPath");
if (outPathValue == nullptr)
{
throw std::runtime_error(
StringHelper::Sprintf("Parse: Fatal error in configuration file.\n"
"\t Missing 'OutPath' attribute in `ExternalFile` element.\n"));
}
externalFiles.push_back(ExternalFile(fs::path(xmlPathValue), fs::path(outPathValue)));
}
void GameConfig::ReadConfigFile(const fs::path& argConfigFilePath)
{
static const std::unordered_map<std::string, ConfigFunc> ConfigFuncDictionary = {
{"SymbolMap", &GameConfig::ConfigFunc_SymbolMap},
{"ActorList", &GameConfig::ConfigFunc_ActorList},
{"ObjectList", &GameConfig::ConfigFunc_ObjectList},
{"EntranceList", &GameConfig::ConfigFunc_EntranceList},
{"SpecialEntranceList", &GameConfig::ConfigFunc_specialEntranceList},
{"TexturePool", &GameConfig::ConfigFunc_TexturePool},
{"BGConfig", &GameConfig::ConfigFunc_BGConfig},
{"ExternalXMLFolder", &GameConfig::ConfigFunc_ExternalXMLFolder},
{"ExternalFile", &GameConfig::ConfigFunc_ExternalFile},
};
configFilePath = argConfigFilePath.string();
tinyxml2::XMLDocument doc;
tinyxml2::XMLError eResult = doc.LoadFile(configFilePath.c_str());
if (eResult != tinyxml2::XML_SUCCESS)
{
throw std::runtime_error("Error: Unable to read config file.");
}
tinyxml2::XMLNode* root = doc.FirstChild();
if (root == nullptr)
return;
for (tinyxml2::XMLElement* child = root->FirstChildElement(); child != nullptr;
child = child->NextSiblingElement())
{
auto it = ConfigFuncDictionary.find(child->Name());
if (it == ConfigFuncDictionary.end())
{
fprintf(stderr, "Unsupported configuration variable: %s\n", child->Name());
continue;
}
std::invoke(it->second, *this, *child);
}
}

62
ZAPDTR/ZAPD/GameConfig.h Normal file
View File

@@ -0,0 +1,62 @@
#pragma once
#include <cstdint>
#include <map>
#include <string>
#include <vector>
#include "Utils/Directory.h"
#include "tinyxml2.h"
struct TexturePoolEntry
{
fs::path path = ""; // Path to Shared Texture
};
class ExternalFile
{
public:
fs::path xmlPath, outPath;
ExternalFile(fs::path nXmlPath, fs::path nOutPath);
};
class ZFile;
class GameConfig
{
public:
std::string configFilePath;
std::map<int32_t, std::vector<ZFile*>> segmentRefFiles;
std::map<uint32_t, std::string> symbolMap;
std::vector<std::string> actorList;
std::vector<std::string> objectList;
std::vector<std::string> entranceList;
std::vector<std::string> specialEntranceList;
std::map<uint32_t, TexturePoolEntry> texturePool; // Key = CRC
// ZBackground
uint32_t bgScreenWidth = 320, bgScreenHeight = 240;
// ExternalFile
fs::path externalXmlFolder;
std::vector<ExternalFile> externalFiles;
GameConfig() = default;
~GameConfig();
void ReadTexturePool(const fs::path& texturePoolXmlPath);
void GenSymbolMap(const fs::path& symbolMapPath);
void ConfigFunc_SymbolMap(const tinyxml2::XMLElement& element);
void ConfigFunc_ActorList(const tinyxml2::XMLElement& element);
void ConfigFunc_ObjectList(const tinyxml2::XMLElement& element);
void ConfigFunc_EntranceList(const tinyxml2::XMLElement& element);
void ConfigFunc_specialEntranceList(const tinyxml2::XMLElement& element);
void ConfigFunc_TexturePool(const tinyxml2::XMLElement& element);
void ConfigFunc_BGConfig(const tinyxml2::XMLElement& element);
void ConfigFunc_ExternalXMLFolder(const tinyxml2::XMLElement& element);
void ConfigFunc_ExternalFile(const tinyxml2::XMLElement& element);
void ReadConfigFile(const fs::path& configFilePath);
};

325
ZAPDTR/ZAPD/Globals.cpp Normal file
View File

@@ -0,0 +1,325 @@
#include "Globals.h"
#include <algorithm>
#include <string_view>
#include <Utils/DiskFile.h>
#include "Utils/Path.h"
#include "WarningHandler.h"
#include "tinyxml2.h"
Globals* Globals::Instance;
Globals::Globals()
{
Instance = this;
game = ZGame::OOT_RETAIL;
genSourceFile = true;
testMode = false;
profile = false;
useLegacyZDList = false;
useExternalResources = true;
singleThreaded = true;
verbosity = VerbosityLevel::VERBOSITY_SILENT;
outputPath = Directory::GetCurrentDirectory();
}
Globals::~Globals()
{
for (const auto& w : workerData)
{
delete w.second;
}
if (rom != nullptr)
{
delete rom;
}
}
void Globals::AddSegment(int32_t segment, ZFile* file, int workerID)
{
if (!Globals::Instance->singleThreaded)
{
auto worker = workerData[workerID];
if (std::find(worker->segments.begin(), worker->segments.end(), segment) ==
worker->segments.end())
worker->segments.push_back(segment);
if (worker->segmentRefFiles.find(segment) == worker->segmentRefFiles.end())
worker->segmentRefFiles[segment] = std::vector<ZFile*>();
worker->segmentRefFiles[segment].push_back(file);
}
else
{
if (std::find(segments.begin(), segments.end(), segment) == segments.end())
segments.push_back(segment);
if (cfg.segmentRefFiles.find(segment) == cfg.segmentRefFiles.end())
cfg.segmentRefFiles[segment] = std::vector<ZFile*>();
cfg.segmentRefFiles[segment].push_back(file);
}
}
bool Globals::HasSegment(int32_t segment, int workerID)
{
if (!Globals::Instance->singleThreaded)
return std::find(workerData[workerID]->segments.begin(),
workerData[workerID]->segments.end(), segment) != workerData[workerID]->segments.end();
else
return std::find(segments.begin(), segments.end(), segment) != segments.end();
}
ZFile* Globals::GetSegment(int32_t segment, int workerID)
{
if (!Globals::Instance->singleThreaded)
{
if (HasSegment(segment, workerID))
{
int idx = std::find(workerData[workerID]->segments.begin(),
workerData[workerID]->segments.end(), segment) -
workerData[workerID]->segments.begin();
return workerData[workerID]->files[idx];
}
else
return nullptr;
}
else
{
if (HasSegment(segment, workerID))
{
int idx = std::find(segments.begin(), segments.end(), segment) - segments.begin();
return files[idx];
}
else
return nullptr;
}
}
std::map<int32_t, std::vector<ZFile*>> Globals::GetSegmentRefFiles(int workerID)
{
if (!Globals::Instance->singleThreaded)
return workerData[workerID]->segmentRefFiles;
else
return cfg.segmentRefFiles;
}
void Globals::AddFile(ZFile* file, int workerID)
{
if (singleThreaded)
files.push_back(file);
else
workerData[workerID]->files.push_back(file);
}
void Globals::AddExternalFile(ZFile* file, int workerID)
{
if (singleThreaded)
externalFiles.push_back(file);
else
workerData[workerID]->externalFiles.push_back(file);
}
void Globals::BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const fs::path& outPath)
{
std::string name = outPath.stem().string();
ZTexture tex(nullptr);
if (name.find("u32") != std::string::npos)
tex.dWordAligned = false;
tex.FromPNG(pngFilePath.string(), texType);
std::string cfgPath = StringHelper::Split(pngFilePath.string(), ".")[0] + ".cfg";
if (DiskFile::Exists(cfgPath))
name = DiskFile::ReadAllText(cfgPath);
std::string src = tex.GetBodySourceCode();
DiskFile::WriteAllBytes(outPath.string(), src.c_str(), src.size());
}
std::map<std::string, ExporterSet*>& Globals::GetExporterMap()
{
static std::map<std::string, ExporterSet*> exporters;
return exporters;
}
void Globals::AddExporter(std::string exporterName, ExporterSet* exporterSet)
{
auto& exporters = GetExporterMap();
exporters[exporterName] = exporterSet;
}
ZResourceExporter* Globals::GetExporter(ZResourceType resType)
{
auto& exporters = GetExporterMap();
if (currentExporter != "" && exporters[currentExporter]->exporters.find(resType) !=
exporters[currentExporter]->exporters.end())
return exporters[currentExporter]->exporters[resType];
else
return nullptr;
}
ExporterSet* Globals::GetExporterSet()
{
auto& exporters = GetExporterMap();
if (currentExporter != "")
return exporters[currentExporter];
else
return nullptr;
}
std::vector<uint8_t> Globals::GetBaseromFile(std::string fileName)
{
if (fileMode == ZFileMode::ExtractDirectory)
{
if (StringHelper::Contains(fileName, "baserom/"))
fileName = StringHelper::Split(fileName, "baserom/")[1];
return rom->GetFile(fileName);
}
else
return DiskFile::ReadAllBytes(fileName);
}
bool Globals::GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile,
const std::string& expectedType, std::string& declName, int workerID)
{
if (segAddress == 0)
{
declName = "NULL";
return true;
}
uint8_t segment = GETSEGNUM(segAddress);
uint32_t offset = Seg2Filespace(segAddress, currentFile->baseAddress);
ZSymbol* sym;
sym = currentFile->GetSymbolResource(offset);
if (sym != nullptr)
{
if (expectedType == "" || expectedType == sym->GetSourceTypeName())
{
declName = sym->GetName();
return true;
}
}
sym = currentFile->GetSymbolResource(segAddress);
if (sym != nullptr)
{
if (expectedType == "" || expectedType == sym->GetSourceTypeName())
{
declName = sym->GetName();
return true;
}
}
if (currentFile->IsSegmentedInFilespaceRange(segAddress))
{
if (currentFile->GetDeclarationPtrName(segAddress, expectedType, declName))
return true;
}
else if (HasSegment(segment, workerID))
{
// OTRTODO: Multithreading
auto segs = GetSegmentRefFiles(workerID);
for (auto file : segs[segment])
{
offset = Seg2Filespace(segAddress, file->baseAddress);
sym = file->GetSymbolResource(offset);
if (sym != nullptr)
{
if (expectedType == "" || expectedType == sym->GetSourceTypeName())
{
declName = sym->GetName();
return true;
}
}
sym = file->GetSymbolResource(segAddress);
if (sym != nullptr)
{
if (expectedType == "" || expectedType == sym->GetSourceTypeName())
{
declName = sym->GetName();
return true;
}
}
if (file->IsSegmentedInFilespaceRange(segAddress))
{
if (file->GetDeclarationPtrName(segAddress, expectedType, declName))
return true;
}
}
}
const auto& symbolFromMap = Globals::Instance->cfg.symbolMap.find(segAddress);
if (symbolFromMap != Globals::Instance->cfg.symbolMap.end())
{
declName = "&" + symbolFromMap->second;
return true;
}
declName = StringHelper::Sprintf("0x%08X", segAddress);
return false;
}
bool Globals::GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSize,
ZFile* currentFile, const std::string& expectedType,
std::string& declName, int workerID)
{
if (segAddress == 0)
{
declName = "NULL";
return true;
}
uint8_t segment = GETSEGNUM(segAddress);
if (currentFile->IsSegmentedInFilespaceRange(segAddress))
{
bool addressFound = currentFile->GetDeclarationArrayIndexedName(segAddress, elementSize,
expectedType, declName);
if (addressFound)
return true;
}
else if (HasSegment(segment, workerID))
{
// OTRTODO: Multithreading
auto segs = GetSegmentRefFiles(workerID);
for (auto file : segs[segment])
{
if (file->IsSegmentedInFilespaceRange(segAddress))
{
bool addressFound = file->GetDeclarationArrayIndexedName(segAddress, elementSize,
expectedType, declName);
if (addressFound)
return true;
}
}
}
declName = StringHelper::Sprintf("0x%08X", segAddress);
return false;
}
ExternalFile::ExternalFile(fs::path nXmlPath, fs::path nOutPath)
: xmlPath{nXmlPath}, outPath{nOutPath}
{
}
ExporterSet::~ExporterSet()
{
for (auto& it : exporters)
{
delete it.second;
}
}

113
ZAPDTR/ZAPD/Globals.h Normal file
View File

@@ -0,0 +1,113 @@
#pragma once
#include <map>
#include <string>
#include <vector>
#include "GameConfig.h"
#include "ZFile.h"
#include <ZRom.h>
#include <FileWorker.h>
class ZRoom;
enum class VerbosityLevel
{
VERBOSITY_SILENT,
VERBOSITY_INFO,
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 (*ExporterSetFuncVoid4)(tinyxml2::XMLElement* reader);
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;
ExporterSetFuncVoid3 endProgramFunc = nullptr;
ExporterSetFuncVoid4 processCompilableFunc = nullptr;
};
class Globals
{
public:
static Globals* Instance;
bool genSourceFile; // Used for extraction
bool useExternalResources;
bool testMode; // Enables certain experimental features
bool outputCrc = false;
bool profile; // Measure performance of certain operations
bool useLegacyZDList;
bool singleThreaded;
VerbosityLevel verbosity; // ZAPD outputs additional information
ZFileMode fileMode = ZFileMode::Invalid;
fs::path baseRomPath, inputPath, outputPath, sourceOutputPath, cfgPath, fileListPath;
TextureType texType;
ZGame game;
GameConfig cfg;
bool verboseUnaccounted = false;
bool gccCompat = false;
bool forceStatic = false;
bool forceUnaccountedStatic = false;
bool otrMode = true;
bool buildRawTexture = false;
bool onlyGenCustomOtr = false;
ZRom* rom = nullptr;
std::vector<ZFile*> files;
std::vector<ZFile*> externalFiles;
std::vector<int32_t> segments;
std::map<int, FileWorker*> workerData;
std::string currentExporter;
static std::map<std::string, ExporterSet*>& GetExporterMap();
static void AddExporter(std::string exporterName, ExporterSet* exporterSet);
Globals();
~Globals();
void AddSegment(int32_t segment, ZFile* file, int workerID);
bool HasSegment(int32_t segment, int workerID);
ZFile* GetSegment(int32_t segment, int workerID);
std::map<int32_t, std::vector<ZFile*>> GetSegmentRefFiles(int workerID);
void AddFile(ZFile* file, int workerID);
void AddExternalFile(ZFile* file, int workerID);
void BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const fs::path& outPath);
ZResourceExporter* GetExporter(ZResourceType resType);
ExporterSet* GetExporterSet();
std::vector<uint8_t> GetBaseromFile(std::string fileName);
/**
* Search in every file (and the symbol map) for the `segAddress` passed as parameter.
* If the segment of `currentFile` is the same segment of `segAddress`, then that file will be
* used only, otherwise, the search will be performed in every other file.
* The name of that variable will be stored in the `declName` parameter.
* Returns `true` if the address is found. `false` otherwise,
* 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, int workerID);
bool GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSize, ZFile* currentFile,
const std::string& expectedType, std::string& declName, int workerID);
};

View File

@@ -0,0 +1,506 @@
#include "ImageBackend.h"
#include <cassert>
#include <cstdlib>
#include <png.h>
#include <stdexcept>
#include "Utils/StringHelper.h"
#include "WarningHandler.h"
/* ImageBackend */
ImageBackend::~ImageBackend()
{
FreeImageData();
}
void ImageBackend::ReadPng(const char* filename)
{
FreeImageData();
FILE* fp = fopen(filename, "rb");
if (fp == nullptr)
{
std::string errorHeader = StringHelper::Sprintf("could not open file '%s'", filename);
HANDLE_ERROR(WarningType::InvalidPNG, errorHeader, "");
}
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (png == nullptr)
{
HANDLE_ERROR(WarningType::InvalidPNG, "could not create png struct", "");
}
png_infop info = png_create_info_struct(png);
if (info == nullptr)
{
HANDLE_ERROR(WarningType::InvalidPNG, "could not create png info", "");
}
if (setjmp(png_jmpbuf(png)))
{
// TODO: better warning explanation
HANDLE_ERROR(WarningType::InvalidPNG, "setjmp(png_jmpbuf(png))", "");
}
png_init_io(png, fp);
png_read_info(png, info);
width = png_get_image_width(png, info);
height = png_get_image_height(png, info);
colorType = png_get_color_type(png, info);
bitDepth = png_get_bit_depth(png, info);
#ifdef TEXTURE_DEBUG
printf("Width: %u\n", width);
printf("Height: %u\n", height);
printf("ColorType: ");
switch (colorType)
{
case PNG_COLOR_TYPE_RGBA:
printf("PNG_COLOR_TYPE_RGBA\n");
break;
case PNG_COLOR_TYPE_RGB:
printf("PNG_COLOR_TYPE_RGB\n");
break;
case PNG_COLOR_TYPE_PALETTE:
printf("PNG_COLOR_TYPE_PALETTE\n");
break;
default:
printf("%u\n", colorType);
break;
}
printf("BitDepth: %u\n", bitDepth);
printf("\n");
#endif
// Read any color_type into 8bit depth, RGBA format.
// See http://www.libpng.org/pub/png/libpng-manual.txt
if (bitDepth == 16)
png_set_strip_16(png);
if (colorType == PNG_COLOR_TYPE_PALETTE)
{
// png_set_palette_to_rgb(png);
isColorIndexed = true;
}
// PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
if (colorType == PNG_COLOR_TYPE_GRAY && bitDepth < 8)
png_set_expand_gray_1_2_4_to_8(png);
/*if (png_get_valid(png, info, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png);*/
// These color_type don't have an alpha channel then fill it with 0xff.
/*if(*color_type == PNG_COLOR_TYPE_RGB ||
*color_type == PNG_COLOR_TYPE_GRAY ||
*color_type == PNG_COLOR_TYPE_PALETTE)
png_set_filler(png, 0xFF, PNG_FILLER_AFTER);*/
if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png);
png_read_update_info(png, info);
size_t rowBytes = png_get_rowbytes(png, info);
pixelMatrix = (uint8_t**)malloc(sizeof(uint8_t*) * height);
for (size_t y = 0; y < height; y++)
{
pixelMatrix[y] = (uint8_t*)malloc(rowBytes);
}
png_read_image(png, pixelMatrix);
#ifdef TEXTURE_DEBUG
printf("rowBytes: %zu\n", rowBytes);
size_t bytePerPixel = GetBytesPerPixel();
printf("imgData\n");
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width; x++)
{
for (size_t z = 0; z < bytePerPixel; z++)
{
printf("%02X ", pixelMatrix[y][x * bytePerPixel + z]);
}
printf(" ");
}
printf("\n");
}
printf("\n");
#endif
fclose(fp);
png_destroy_read_struct(&png, &info, nullptr);
hasImageData = true;
}
void ImageBackend::ReadPng(const fs::path& filename)
{
ReadPng(filename.string().c_str());
}
void ImageBackend::WritePng(const char* filename)
{
assert(hasImageData);
FILE* fp = fopen(filename, "wb");
if (fp == nullptr)
{
std::string errorHeader =
StringHelper::Sprintf("could not open file '%s' in write mode", filename);
HANDLE_ERROR(WarningType::InvalidPNG, errorHeader, "");
}
png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
if (png == nullptr)
{
HANDLE_ERROR(WarningType::InvalidPNG, "could not create png struct", "");
}
png_infop info = png_create_info_struct(png);
if (info == nullptr)
{
HANDLE_ERROR(WarningType::InvalidPNG, "could not create png info", "");
}
if (setjmp(png_jmpbuf(png)))
{
// TODO: better warning description
HANDLE_ERROR(WarningType::InvalidPNG, "setjmp(png_jmpbuf(png))", "");
}
png_init_io(png, fp);
png_set_IHDR(png, info, width, height,
bitDepth, // 8,
colorType, // PNG_COLOR_TYPE_RGBA,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
if (isColorIndexed)
{
png_set_PLTE(png, info, static_cast<png_color*>(colorPalette), paletteSize);
#ifdef TEXTURE_DEBUG
printf("palette\n");
png_color* aux = (png_color*)colorPalette;
for (size_t y = 0; y < paletteSize; y++)
{
printf("#%02X%02X%02X ", aux[y].red, aux[y].green, aux[y].blue);
if ((y + 1) % 8 == 0)
printf("\n");
}
printf("\n");
#endif
png_set_tRNS(png, info, alphaPalette, paletteSize, nullptr);
}
png_write_info(png, info);
// To remove the alpha channel for PNG_COLOR_TYPE_RGB format,
// Use png_set_filler().
// png_set_filler(png, 0, PNG_FILLER_AFTER);
#ifdef TEXTURE_DEBUG
size_t bytePerPixel = GetBytesPerPixel();
printf("imgData\n");
for (size_t y = 0; y < height; y++)
{
for (size_t x = 0; x < width * bytePerPixel; x++)
{
printf("%02X ", pixelMatrix[y][x]);
}
printf("\n");
}
printf("\n");
#endif
png_write_image(png, pixelMatrix);
png_write_end(png, nullptr);
fclose(fp);
png_destroy_write_struct(&png, &info);
}
void ImageBackend::WritePng(const fs::path& filename)
{
// Note: The .string() is necessary for MSVC, due to the implementation of std::filesystem
// differing from GCC. Do not remove!
WritePng(filename.string().c_str());
}
void ImageBackend::SetTextureData(const std::vector<std::vector<RGBAPixel>>& texData,
uint32_t nWidth, uint32_t nHeight, uint8_t nColorType,
uint8_t nBitDepth)
{
FreeImageData();
width = nWidth;
height = nHeight;
colorType = nColorType;
bitDepth = nBitDepth;
size_t bytePerPixel = GetBytesPerPixel();
pixelMatrix = static_cast<uint8_t**>(malloc(sizeof(uint8_t*) * height));
for (size_t y = 0; y < height; y++)
{
pixelMatrix[y] = static_cast<uint8_t*>(malloc(sizeof(uint8_t*) * width * bytePerPixel));
for (size_t x = 0; x < width; x++)
{
pixelMatrix[y][x * bytePerPixel + 0] = texData.at(y).at(x).r;
pixelMatrix[y][x * bytePerPixel + 1] = texData.at(y).at(x).g;
pixelMatrix[y][x * bytePerPixel + 2] = texData.at(y).at(x).b;
if (colorType == PNG_COLOR_TYPE_RGBA)
pixelMatrix[y][x * bytePerPixel + 3] = texData.at(y).at(x).a;
}
}
hasImageData = true;
}
void ImageBackend::InitEmptyRGBImage(uint32_t nWidth, uint32_t nHeight, bool alpha)
{
FreeImageData();
width = nWidth;
height = nHeight;
colorType = PNG_COLOR_TYPE_RGB;
if (alpha)
colorType = PNG_COLOR_TYPE_RGBA;
bitDepth = 8; // nBitDepth;
size_t bytePerPixel = GetBytesPerPixel();
pixelMatrix = static_cast<uint8_t**>(malloc(sizeof(uint8_t*) * height));
for (size_t y = 0; y < height; y++)
{
pixelMatrix[y] = static_cast<uint8_t*>(calloc(width * bytePerPixel, sizeof(uint8_t*)));
}
hasImageData = true;
}
void ImageBackend::InitEmptyPaletteImage(uint32_t nWidth, uint32_t nHeight)
{
FreeImageData();
width = nWidth;
height = nHeight;
colorType = PNG_COLOR_TYPE_PALETTE;
bitDepth = 8;
size_t bytePerPixel = GetBytesPerPixel();
pixelMatrix = (uint8_t**)malloc(sizeof(uint8_t*) * height);
for (size_t y = 0; y < height; y++)
{
pixelMatrix[y] = static_cast<uint8_t*>(calloc(width * bytePerPixel, sizeof(uint8_t*)));
}
colorPalette = calloc(paletteSize, sizeof(png_color));
alphaPalette = static_cast<uint8_t*>(calloc(paletteSize, sizeof(uint8_t)));
hasImageData = true;
isColorIndexed = true;
}
RGBAPixel ImageBackend::GetPixel(size_t y, size_t x) const
{
assert(y < height);
assert(x < width);
assert(!isColorIndexed);
RGBAPixel pixel;
size_t bytePerPixel = GetBytesPerPixel();
pixel.r = pixelMatrix[y][x * bytePerPixel + 0];
pixel.g = pixelMatrix[y][x * bytePerPixel + 1];
pixel.b = pixelMatrix[y][x * bytePerPixel + 2];
if (colorType == PNG_COLOR_TYPE_RGBA)
pixel.a = pixelMatrix[y][x * bytePerPixel + 3];
return pixel;
}
uint8_t ImageBackend::GetIndexedPixel(size_t y, size_t x) const
{
assert(y < height);
assert(x < width);
assert(isColorIndexed);
return pixelMatrix[y][x];
}
void ImageBackend::SetRGBPixel(size_t y, size_t x, uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA)
{
assert(hasImageData);
assert(y < height);
assert(x < width);
size_t bytePerPixel = GetBytesPerPixel();
pixelMatrix[y][x * bytePerPixel + 0] = nR;
pixelMatrix[y][x * bytePerPixel + 1] = nG;
pixelMatrix[y][x * bytePerPixel + 2] = nB;
if (colorType == PNG_COLOR_TYPE_RGBA)
pixelMatrix[y][x * bytePerPixel + 3] = nA;
}
void ImageBackend::SetGrayscalePixel(size_t y, size_t x, uint8_t grayscale, uint8_t alpha)
{
assert(hasImageData);
assert(y < height);
assert(x < width);
size_t bytePerPixel = GetBytesPerPixel();
pixelMatrix[y][x * bytePerPixel + 0] = grayscale;
pixelMatrix[y][x * bytePerPixel + 1] = grayscale;
pixelMatrix[y][x * bytePerPixel + 2] = grayscale;
if (colorType == PNG_COLOR_TYPE_RGBA)
pixelMatrix[y][x * bytePerPixel + 3] = alpha;
}
void ImageBackend::SetIndexedPixel(size_t y, size_t x, uint8_t index, uint8_t grayscale)
{
assert(hasImageData);
assert(y < height);
assert(x < width);
size_t bytePerPixel = GetBytesPerPixel();
pixelMatrix[y][x * bytePerPixel + 0] = index;
assert(index < paletteSize);
png_color* pal = static_cast<png_color*>(colorPalette);
pal[index].red = grayscale;
pal[index].green = grayscale;
pal[index].blue = grayscale;
alphaPalette[index] = 255;
}
void ImageBackend::SetPaletteIndex(size_t index, uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA)
{
assert(isColorIndexed);
assert(index < paletteSize);
png_color* pal = static_cast<png_color*>(colorPalette);
pal[index].red = nR;
pal[index].green = nG;
pal[index].blue = nB;
alphaPalette[index] = nA;
}
void ImageBackend::SetPalette(const ImageBackend& pal, uint32_t offset)
{
assert(isColorIndexed);
size_t bytePerPixel = pal.GetBytesPerPixel();
for (size_t y = 0; y < pal.height; y++)
{
for (size_t x = 0; x < pal.width; x++)
{
size_t index = y * pal.width + x;
if (index >= paletteSize)
{
/*
* Some TLUTs are bigger than 256 colors.
* For those cases, we will only take the first 256
* to colorize this CI texture.
*/
return;
}
uint8_t r = pal.pixelMatrix[y][x * bytePerPixel + 0];
uint8_t g = pal.pixelMatrix[y][x * bytePerPixel + 1];
uint8_t b = pal.pixelMatrix[y][x * bytePerPixel + 2];
uint8_t a = pal.pixelMatrix[y][x * bytePerPixel + 3];
SetPaletteIndex(index + offset, r, g, b, a);
}
}
}
uint32_t ImageBackend::GetWidth() const
{
return width;
}
uint32_t ImageBackend::GetHeight() const
{
return height;
}
uint8_t ImageBackend::GetColorType() const
{
return colorType;
}
uint8_t ImageBackend::GetBitDepth() const
{
return bitDepth;
}
double ImageBackend::GetBytesPerPixel() const
{
switch (colorType)
{
case PNG_COLOR_TYPE_RGBA:
return 4 * bitDepth / 8;
case PNG_COLOR_TYPE_RGB:
return 3 * bitDepth / 8;
case PNG_COLOR_TYPE_PALETTE:
return 1 * bitDepth / 8;
default:
HANDLE_ERROR(WarningType::InvalidPNG, "invalid color type", "");
}
}
void ImageBackend::FreeImageData()
{
if (hasImageData)
{
for (size_t y = 0; y < height; y++)
free(pixelMatrix[y]);
free(pixelMatrix);
pixelMatrix = nullptr;
}
if (isColorIndexed)
{
free(colorPalette);
free(alphaPalette);
colorPalette = nullptr;
alphaPalette = nullptr;
isColorIndexed = false;
}
hasImageData = false;
}
/* RGBAPixel */
void RGBAPixel::SetRGBA(uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA)
{
r = nR;
g = nG;
b = nB;
a = nA;
}
void RGBAPixel::SetGrayscale(uint8_t grayscale, uint8_t alpha)
{
r = grayscale;
g = grayscale;
b = grayscale;
a = alpha;
}

View File

@@ -0,0 +1,72 @@
#pragma once
#include <cstdint>
#include <vector>
#include "Utils/Directory.h"
class RGBAPixel
{
public:
RGBAPixel() = default;
void SetRGBA(uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA);
void SetGrayscale(uint8_t grayscale, uint8_t alpha = 0);
uint8_t r = 0;
uint8_t g = 0;
uint8_t b = 0;
uint8_t a = 0;
};
class ImageBackend
{
public:
ImageBackend() = default;
~ImageBackend();
void ReadPng(const char* filename);
void ReadPng(const fs::path& filename);
void WritePng(const char* filename);
void WritePng(const fs::path& filename);
void SetTextureData(const std::vector<std::vector<RGBAPixel>>& texData, uint32_t nWidth,
uint32_t nHeight, uint8_t nColorType, uint8_t nBitDepth);
void InitEmptyRGBImage(uint32_t nWidth, uint32_t nHeight, bool alpha);
void InitEmptyPaletteImage(uint32_t nWidth, uint32_t nHeight);
RGBAPixel GetPixel(size_t y, size_t x) const;
uint8_t GetIndexedPixel(size_t y, size_t x) const;
void SetRGBPixel(size_t y, size_t x, uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA = 0);
void SetGrayscalePixel(size_t y, size_t x, uint8_t grayscale, uint8_t alpha = 0);
void SetIndexedPixel(size_t y, size_t x, uint8_t index, uint8_t grayscale);
void SetIndexedPixel(size_t y, size_t x, uint8_t index, RGBAPixel pixel);
void SetPaletteIndex(size_t index, uint8_t nR, uint8_t nG, uint8_t nB, uint8_t nA);
void SetPalette(const ImageBackend& pal, uint32_t offset = 0);
uint32_t GetWidth() const;
uint32_t GetHeight() const;
uint8_t GetColorType() const;
uint8_t GetBitDepth() const;
protected:
uint8_t** pixelMatrix = nullptr; // height * [width * bytePerPixel]
void* colorPalette = nullptr;
uint8_t* alphaPalette = nullptr;
size_t paletteSize = 16 * 16;
uint32_t width = 0;
uint32_t height = 0;
uint8_t colorType = 0;
uint8_t bitDepth = 0;
bool hasImageData = false;
bool isColorIndexed = false;
double GetBytesPerPixel() const;
void FreeImageData();
};

596
ZAPDTR/ZAPD/Main.cpp Normal file
View File

@@ -0,0 +1,596 @@
#include "Globals.h"
#include "Utils/Directory.h"
#include <Utils/DiskFile.h>
#include "Utils/Path.h"
#include "WarningHandler.h"
#include "ZAnimation.h"
ZNormalAnimation nAnim(nullptr);
ZCurveAnimation cAnim(nullptr);
ZLinkAnimation lAnim(nullptr);
ZLegacyAnimation lAnim2(nullptr);
#include "ZArray.h"
ZArray arr(nullptr);
#include "ZAudio.h"
ZAudio audio(nullptr);
#include "ZBackground.h"
ZBackground back(nullptr);
#include "ZBlob.h"
ZBlob blob(nullptr);
#include "ZCollision.h"
ZCollisionHeader colHeader(nullptr);
#include "ZCutscene.h"
ZCutscene cs(nullptr);
#include "ZLimb.h"
ZLimb limb(nullptr);
#include "ZMtx.h"
ZMtx mtx(nullptr);
#include "ZPath.h"
ZPath path(nullptr);
#include "ZPlayerAnimationData.h"
ZPlayerAnimationData pAnimData(nullptr);
#include "ZScalar.h"
ZScalar scalar(nullptr);
#include "ZSkeleton.h"
ZLimbTable limbTbl(nullptr);
ZSkeleton skel(nullptr);
#include "ZString.h"
ZString str(nullptr);
#include "ZSymbol.h"
ZSymbol sym(nullptr);
#include "ZText.h"
ZText txt(nullptr);
#include "ZTexture.h"
ZTexture tex(nullptr);
#include "ZVector.h"
ZVector vec(nullptr);
#include "ZVtx.h"
ZVtx vtx(nullptr);
#include "ZRoom/ZRoom.h"
ZRoom room(nullptr);
#include "ZFile.h"
#include "ZTexture.h"
#include "CrashHandler.h"
#include <string>
#include <string_view>
#include "tinyxml2.h"
#include <ctpl_stl.h>
//extern const char gBuildHash[];
const char gBuildHash[] = "";
bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath,
ZFileMode fileMode, int workerID);
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);
int ExtractFunc(int workerID, int fileListSize, std::string fileListItem, ZFileMode fileMode);
volatile int numWorkersLeft = 0;
extern void ImportExporters();
extern "C" int zapd_main(int argc, char* argv[])
{
// Syntax: ZAPD.out [mode (btex/bovl/e)] (Arbritrary Number of Arguments)
if (argc < 2)
{
printf("ZAPD.out (%s) [mode (btex/bovl/bsf/bblb/bmdlintr/bamnintr/e)] ...\n", gBuildHash);
return 1;
}
Globals* g = new Globals();
WarningHandler::Init(argc, argv);
for (int i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "--version"))
{
printf("ZAPD.out %s\n", gBuildHash);
return 0;
}
else if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h"))
{
printf("Congratulations!\n");
printf("You just found the (unimplemented and undocumented) ZAPD's help message.\n");
printf("Feel free to implement it if you want :D\n");
WarningHandler::PrintHelp();
return 0;
}
}
// 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 == "-fl") // Set baserom filelist path
{
Globals::Instance->fileListPath = 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
{
ImportExporters();
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;
}
else if (arg == "-brt" || arg == "--build-raw-texture")
{
Globals::Instance->buildRawTexture = true;
}
else if (arg == "--norom")
{
Globals::Instance->onlyGenCustomOtr = true;
}
}
// Parse File Mode
ExporterSet* exporterSet = Globals::Instance->GetExporterSet();
// 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++) {
exporterSet->parseArgsFunc(argc, argv, i);
}
}
if (Globals::Instance->onlyGenCustomOtr) {
if (exporterSet != nullptr) {
exporterSet->endProgramFunc();
} else {
printf("Error: No exporter set, unable to make custom otr.\n");
}
delete g;
return 0;
}
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 (buildMode == "ed")
fileMode = ZFileMode::ExtractDirectory;
else if (exporterSet != nullptr && exporterSet->parseFileModeFunc != nullptr)
exporterSet->parseFileModeFunc(buildMode, fileMode);
if (fileMode == ZFileMode::Invalid)
{
printf("Error: Invalid file mode '%s'\n", buildMode.c_str());
return 1;
}
Globals::Instance->fileMode = fileMode;
if (fileMode == ZFileMode::ExtractDirectory)
Globals::Instance->rom = new ZRom(Globals::Instance->baseRomPath.string());
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
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 || fileMode == ZFileMode::ExtractDirectory)
{
bool procFileModeSuccess = false;
if (exporterSet != nullptr && exporterSet->processFileModeFunc != nullptr)
procFileModeSuccess = exporterSet->processFileModeFunc(fileMode);
if (!procFileModeSuccess)
{
if (fileMode == ZFileMode::ExtractDirectory)
{
std::vector<std::string> fileList =
Directory::ListFiles(Globals::Instance->inputPath.string());
const int num_threads = std::thread::hardware_concurrency();
ctpl::thread_pool pool(num_threads > 1 ? num_threads / 2 : 1);
bool parseSuccessful;
auto start = std::chrono::steady_clock::now();
int fileListSize = fileList.size();
Globals::Instance->singleThreaded = false;
for (int i = 0; i < fileListSize; i++)
Globals::Instance->workerData[i] = new FileWorker();
numWorkersLeft = fileListSize;
for (int i = 0; i < fileListSize; i++)
{
if (Globals::Instance->singleThreaded)
{
ExtractFunc(i, fileList.size(), fileList[i], fileMode);
}
else
{
std::string fileListItem = fileList[i];
pool.push([i, fileListSize, fileListItem, fileMode](int) {
ExtractFunc(i, fileListSize, fileListItem, fileMode);
});
}
}
if (!Globals::Instance->singleThreaded)
{
while (true)
{
if (numWorkersLeft <= 0)
break;
std::this_thread::sleep_for(std::chrono::milliseconds(250));
}
}
auto end = std::chrono::steady_clock::now();
auto diff =
std::chrono::duration_cast<std::chrono::seconds>(end - start).count();
printf("Generated OTR File Data in %i seconds\n", diff);
}
else
{
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, 0);
if (!parseSuccessful)
return 1;
}
parseSuccessful =
Parse(Globals::Instance->inputPath, Globals::Instance->baseRomPath,
Globals::Instance->outputPath, fileMode, 0);
if (!parseSuccessful)
return 1;
}
}
}
else if (fileMode == ZFileMode::BuildTexture)
{
TextureType texType = Globals::Instance->texType;
BuildAssetTexture(Globals::Instance->inputPath, 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);
}
if (exporterSet != nullptr && exporterSet->endProgramFunc != nullptr)
exporterSet->endProgramFunc();
end:
delete exporterSet;
//Globals::Instance->GetExporterSet() = nullptr; //TODO NULL this out. Compiler complains about lvalue assignment.
delete g;
return 0;
}
int ExtractFunc(int workerID, int fileListSize, std::string fileListItem, ZFileMode fileMode)
{
bool parseSuccessful;
printf("(%i / %i): %s\n", (workerID + 1), fileListSize, fileListItem.c_str());
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, workerID);
if (!parseSuccessful)
return 1;
}
parseSuccessful = Parse(fileListItem, Globals::Instance->baseRomPath,
Globals::Instance->outputPath, fileMode, workerID);
if (!parseSuccessful)
return 1;
if (Globals::Instance->singleThreaded)
{
for (int i = 0; i < Globals::Instance->files.size(); i++)
{
delete Globals::Instance->files[i];
Globals::Instance->files.erase(Globals::Instance->files.begin() + i);
i--;
}
Globals::Instance->externalFiles.clear();
Globals::Instance->segments.clear();
Globals::Instance->cfg.segmentRefFiles.clear();
}
else
{
for (int i = 0; i < Globals::Instance->workerData[workerID]->files.size(); i++)
{
delete Globals::Instance->workerData[workerID]->files[i];
Globals::Instance->workerData[workerID]->files.erase(
Globals::Instance->workerData[workerID]->files.begin() +
i);
i--;
}
Globals::Instance->workerData[workerID]->externalFiles.clear();
Globals::Instance->workerData[workerID]->segments.clear();
Globals::Instance->workerData[workerID]->segmentRefFiles.clear();
numWorkersLeft--;
}
return 0;
}
bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath,
ZFileMode fileMode, int workerID)
{
tinyxml2::XMLDocument doc;
tinyxml2::XMLError eResult = doc.LoadFile(xmlFilePath.string().c_str());
if (eResult != tinyxml2::XML_SUCCESS)
{
// TODO: use XMLDocument::ErrorIDToName to get more specific error messages here
HANDLE_ERROR(WarningType::InvalidXML,
StringHelper::Sprintf("invalid XML file: '%s'", xmlFilePath.c_str()), "");
return false;
}
tinyxml2::XMLNode* root = doc.FirstChild();
if (root == nullptr)
{
HANDLE_WARNING(
WarningType::InvalidXML,
StringHelper::Sprintf("missing Root tag in xml file: '%s'", xmlFilePath.c_str()), "");
return false;
}
for (tinyxml2::XMLElement* child = root->FirstChildElement(); child != NULL;
child = child->NextSiblingElement())
{
if (std::string_view(child->Name()) == "File")
{
ZFile* file = new ZFile(fileMode, child, basePath, outPath, "", xmlFilePath, workerID);
Globals::Instance->AddFile(file, workerID);
if (fileMode == ZFileMode::ExternalFile)
{
Globals::Instance->AddExternalFile(file, workerID);
file->isExternalFile = true;
}
}
else if (std::string(child->Name()) == "ExternalFile")
{
const char* xmlPathValue = child->Attribute("XmlPath");
if (xmlPathValue == nullptr)
{
throw std::runtime_error(StringHelper::Sprintf(
"Parse: Fatal error in '%s'.\n"
"\t Missing 'XmlPath' attribute in `ExternalFile` element.\n",
xmlFilePath.c_str()));
}
const char* outPathValue = child->Attribute("OutPath");
if (outPathValue == nullptr)
{
throw std::runtime_error(StringHelper::Sprintf(
"Parse: Fatal error in '%s'.\n"
"\t Missing 'OutPath' attribute in `ExternalFile` element.\n",
xmlFilePath.c_str()));
}
fs::path externalXmlFilePath =
Globals::Instance->cfg.externalXmlFolder / fs::path(xmlPathValue);
fs::path externalOutFilePath = fs::path(outPathValue);
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
{
printf("Parsing external file: '%s'\n", externalXmlFilePath.c_str());
}
// Recursion. What can go wrong?
Parse(externalXmlFilePath, basePath, externalOutFilePath, ZFileMode::ExternalFile, workerID);
}
else
{
std::string errorHeader =
StringHelper::Sprintf("when parsing file '%s'", xmlFilePath.c_str());
std::string errorBody = StringHelper::Sprintf(
"Found a resource outside a File element: '%s'", child->Name());
HANDLE_ERROR(WarningType::InvalidXML, errorHeader, errorBody);
}
}
if (fileMode != ZFileMode::ExternalFile)
{
ExporterSet* exporterSet = Globals::Instance->GetExporterSet();
if (exporterSet != nullptr && exporterSet->beginXMLFunc != nullptr)
exporterSet->beginXMLFunc();
std::vector<ZFile*> files;
if (Globals::Instance->singleThreaded)
files = Globals::Instance->files;
else
files = Globals::Instance->workerData[workerID]->files;
for (ZFile* file : files)
{
if (fileMode == ZFileMode::BuildSourceFile)
file->BuildSourceFile();
else
file->ExtractResources();
}
if (exporterSet != nullptr && exporterSet->endXMLFunc != nullptr)
exporterSet->endXMLFunc();
}
return true;
}
void BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const fs::path& outPath)
{
return Globals::Instance->BuildAssetTexture(pngFilePath, texType, outPath);
}
void BuildAssetBackground(const fs::path& imageFilePath, const fs::path& outPath)
{
ZBackground background(nullptr);
background.ParseBinaryFile(imageFilePath.string(), false);
DiskFile::WriteAllText(outPath.string(), background.GetBodySourceCode());
}
void BuildAssetBlob(const fs::path& blobFilePath, const fs::path& outPath)
{
ZBlob* blob = ZBlob::FromFile(blobFilePath.string());
std::string name = outPath.stem().string(); // filename without extension
std::string src = blob->GetBodySourceCode();
DiskFile::WriteAllText(outPath.string(), src);
delete blob;
}

View File

View File

@@ -0,0 +1,213 @@
#include "CutsceneMM_Commands.h"
#include <cassert>
#include <unordered_map>
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
// Specific for command lists where each entry has size 8 bytes
const std::unordered_map<CutsceneMMCommands, CsCommandListDescriptor> csCommandsDescMM = {
{CutsceneMMCommands::CS_CMD_MISC, {"CS_MISC", "(0x%02X, %i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_SET_LIGHTING, {"CS_LIGHTING", "(0x%02X, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_SCENE_TRANS_FX, {"CS_SCENE_TRANS_FX", "(%i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_MOTIONBLUR, {"CS_MOTIONBLUR", "(%i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_GIVETATL, {"CS_GIVETATL", "(%i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_PLAYSEQ, {"CS_PLAYSEQ", "(0x%04X, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_130, {"CS_SCENE_UNK_130", "(0x%04X, %i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_131, {"CS_SCENE_UNK_131", "(0x%04X, %i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_132, {"CS_SCENE_UNK_132", "(%i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_STOPSEQ, {"CS_STOPSEQ", "(0x%04X, %i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_PLAYAMBIENCE, {"CS_PLAYAMBIENCE", "(0x%04X, %i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_FADEAMBIENCE, {"CS_FADEAMBIENCE", "(0x%04X, %i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_TERMINATOR, {"CS_TERMINATOR", "(%i, %i, %i)"}},
{CutsceneMMCommands::CS_CMD_CHOOSE_CREDITS_SCENES,
{"CS_CHOOSE_CREDITS_SCENES", "(%i, %i, %i)"}},
};
CutsceneSubCommandEntry_GenericMMCmd::CutsceneSubCommandEntry_GenericMMCmd(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex, CutsceneMMCommands cmdId)
: CutsceneSubCommandEntry(rawData, rawDataIndex), commandId(cmdId)
{
}
std::string CutsceneSubCommandEntry_GenericMMCmd::GetBodySourceCode() const
{
const auto& element = csCommandsDescMM.find(commandId);
std::string entryFmt = "CS_UNK_DATA(0x%02X, %i, %i, %i)";
if (element != csCommandsDescMM.end())
{
entryFmt = element->second.cmdMacro;
entryFmt += element->second.args;
}
return StringHelper::Sprintf(entryFmt.c_str(), base, startFrame, endFrame, pad);
}
CutsceneMMCommand_GenericCmd::CutsceneMMCommand_GenericCmd(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex,
CutsceneMMCommands cmdId)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
commandID = static_cast<uint32_t>(cmdId);
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneSubCommandEntry_GenericMMCmd(rawData, rawDataIndex, cmdId);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneMMCommand_GenericCmd::GetCommandMacro() const
{
const auto& element = csCommandsDescMM.find(static_cast<CutsceneMMCommands>(commandID));
if (element != csCommandsDescMM.end())
{
return StringHelper::Sprintf("%s_LIST(%i)", element->second.cmdMacro, numEntries);
}
return StringHelper::Sprintf("CS_UNK_DATA_LIST(0x%X, %i)", commandID, numEntries);
}
CutsceneSubCommandEntry_Camera::CutsceneSubCommandEntry_Camera(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
}
std::string CutsceneSubCommandEntry_Camera::GetBodySourceCode() const
{
return StringHelper::Sprintf("CMD_HH(0x%04X, 0x%04X)", base, startFrame);
}
size_t CutsceneSubCommandEntry_Camera::GetRawSize() const
{
return 0x04;
}
CutsceneMMCommand_Camera::CutsceneMMCommand_Camera(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries / 4; i++)
{
auto* entry = new CutsceneSubCommandEntry_Camera(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneMMCommand_Camera::GetCommandMacro() const
{
return StringHelper::Sprintf("CS_CAMERA_LIST(%i)", numEntries);
}
CutsceneSubCommandEntry_FadeScreen::CutsceneSubCommandEntry_FadeScreen(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
unk_06 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x06);
unk_07 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x07);
unk_08 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x08);
unk_09 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x09);
unk_0A = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x0A);
unk_0B = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x0B);
}
std::string CutsceneSubCommandEntry_FadeScreen::GetBodySourceCode() const
{
return StringHelper::Sprintf("CS_FADESCREEN(0x%02X, %i, %i, %i, %i, %i)", base, startFrame,
endFrame, unk_06, unk_07, unk_08);
}
size_t CutsceneSubCommandEntry_FadeScreen::GetRawSize() const
{
return 0x0C;
}
CutsceneMMCommand_FadeScreen::CutsceneMMCommand_FadeScreen(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneSubCommandEntry_FadeScreen(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneMMCommand_FadeScreen::GetCommandMacro() const
{
return StringHelper::Sprintf("CS_FADESCREEN_LIST(%i)", numEntries);
}
CutsceneSubCommandEntry_FadeSeq::CutsceneSubCommandEntry_FadeSeq(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
unk_08 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8);
}
std::string CutsceneSubCommandEntry_FadeSeq::GetBodySourceCode() const
{
return StringHelper::Sprintf("CS_FADESEQ(%i, %i, %i)", base, startFrame, endFrame);
}
size_t CutsceneSubCommandEntry_FadeSeq::GetRawSize() const
{
return 0x0C;
}
CutsceneMMCommand_FadeSeq::CutsceneMMCommand_FadeSeq(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneSubCommandEntry_FadeSeq(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneMMCommand_FadeSeq::GetCommandMacro() const
{
return StringHelper::Sprintf("CS_FADESEQ_LIST(%i)", numEntries);
}
CutsceneSubCommandEntry_NonImplemented::CutsceneSubCommandEntry_NonImplemented(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
}
CutsceneMMCommand_NonImplemented::CutsceneMMCommand_NonImplemented(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneSubCommandEntry_NonImplemented(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}

View File

@@ -0,0 +1,140 @@
#pragma once
#include "Cutscene_Commands.h"
enum class CutsceneMMCommands
{
/* 0x00A */ CS_CMD_TEXTBOX = 0xA,
/* 0x05A */ CS_CMD_CAMERA = 0x5A,
/* 0x096 */ CS_CMD_MISC = 0x96,
/* 0x097 */ CS_CMD_SET_LIGHTING,
/* 0x098 */ CS_CMD_SCENE_TRANS_FX,
/* 0x099 */ CS_CMD_MOTIONBLUR,
/* 0x09A */ CS_CMD_GIVETATL,
/* 0x09B */ CS_CMD_FADESCREEN,
/* 0x09C */ CS_CMD_FADESEQ,
/* 0x09D */ CS_CMD_SETTIME,
/* 0x0C8 */ CS_CMD_SET_PLAYER_ACTION = 0xC8,
/* 0x0FA */ CS_CMD_UNK_FA = 0xFA,
/* 0x0FE */ CS_CMD_UNK_FE = 0xFE,
/* 0x0FF */ CS_CMD_UNK_FF,
/* 0x100 */ CS_CMD_UNK_100,
/* 0x101 */ CS_CMD_UNK_101,
/* 0x102 */ CS_CMD_UNK_102,
/* 0x103 */ CS_CMD_UNK_103,
/* 0x104 */ CS_CMD_UNK_104,
/* 0x105 */ CS_CMD_UNK_105,
/* 0x108 */ CS_CMD_UNK_108 = 0x108,
/* 0x109 */ CS_CMD_UNK_109,
/* 0x12C */ CS_CMD_PLAYSEQ = 0x12C,
/* 0x12D */ CS_CMD_UNK_12D,
/* 0x130 */ CS_CMD_130 = 0x130,
/* 0x131 */ CS_CMD_131 = 0x131,
/* 0x132 */ CS_CMD_132 = 0x132,
/* 0x133 */ CS_CMD_STOPSEQ,
/* 0x134 */ CS_CMD_PLAYAMBIENCE,
/* 0x135 */ CS_CMD_FADEAMBIENCE,
/* 0x15E */ CS_CMD_TERMINATOR = 0x15E,
/* 0x15F */ CS_CMD_CHOOSE_CREDITS_SCENES,
/* 0x190 */ CS_CMD_RUMBLE = 0x190,
};
class CutsceneSubCommandEntry_GenericMMCmd : public CutsceneSubCommandEntry
{
public:
CutsceneMMCommands commandId;
CutsceneSubCommandEntry_GenericMMCmd(const std::vector<uint8_t>& rawData, offset_t rawDataIndex,
CutsceneMMCommands cmdId);
std::string GetBodySourceCode() const override;
};
class CutsceneMMCommand_GenericCmd : public CutsceneCommand
{
public:
CutsceneMMCommand_GenericCmd(const std::vector<uint8_t>& rawData, offset_t rawDataIndex,
CutsceneMMCommands cmdId);
std::string GetCommandMacro() const override;
};
// TODO: MM cutscene camera command is implemented as a placeholder until we better understand how
// it works
class CutsceneSubCommandEntry_Camera : public CutsceneSubCommandEntry
{
public:
uint32_t unk_08;
CutsceneSubCommandEntry_Camera(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneMMCommand_Camera : public CutsceneCommand
{
public:
CutsceneMMCommand_Camera(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};
class CutsceneSubCommandEntry_FadeScreen : public CutsceneSubCommandEntry
{
public:
uint8_t unk_06;
uint8_t unk_07;
uint8_t unk_08;
uint8_t unk_09;
uint8_t unk_0A;
uint8_t unk_0B;
CutsceneSubCommandEntry_FadeScreen(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneMMCommand_FadeScreen : public CutsceneCommand
{
public:
CutsceneMMCommand_FadeScreen(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};
class CutsceneSubCommandEntry_FadeSeq : public CutsceneSubCommandEntry
{
public:
uint32_t unk_08;
CutsceneSubCommandEntry_FadeSeq(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneMMCommand_FadeSeq : public CutsceneCommand
{
public:
CutsceneMMCommand_FadeSeq(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};
class CutsceneSubCommandEntry_NonImplemented : public CutsceneSubCommandEntry
{
public:
CutsceneSubCommandEntry_NonImplemented(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex);
};
class CutsceneMMCommand_NonImplemented : public CutsceneCommand
{
public:
CutsceneMMCommand_NonImplemented(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
};

View File

@@ -0,0 +1,458 @@
#include "CutsceneOoT_Commands.h"
#include <cassert>
#include <unordered_map>
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
/**** GENERIC ****/
// Specific for command lists where each entry has size 0x30 bytes
const std::unordered_map<CutsceneOoT_CommandType, CsCommandListDescriptor> csCommandsDesc = {
{CutsceneOoT_CommandType::CS_CMD_MISC,
{"CS_MISC", "(%s, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}},
{CutsceneOoT_CommandType::CS_CMD_LIGHT_SETTING,
{"CS_LIGHT_SETTING", "(0x%02X, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}},
{CutsceneOoT_CommandType::CS_CMD_START_SEQ,
{"CS_START_SEQ", "(%s, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}},
{CutsceneOoT_CommandType::CS_CMD_STOP_SEQ,
{"CS_STOP_SEQ", "(%s, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}},
{CutsceneOoT_CommandType::CS_CMD_FADE_OUT_SEQ,
{"CS_FADE_OUT_SEQ", "(%s, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}},
};
CutsceneOoTSubCommandEntry_GenericCmd::CutsceneOoTSubCommandEntry_GenericCmd(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex, CutsceneOoT_CommandType cmdId)
: CutsceneSubCommandEntry(rawData, rawDataIndex), commandId(cmdId)
{
word0 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x0);
word1 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x4);
unused1 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x8);
unused2 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0xC);
unused3 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x10);
unused4 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x14);
unused5 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x18);
unused6 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x1C);
unused7 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x20);
unused8 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x24);
unused9 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x28);
unused10 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x2C);
}
std::string CutsceneOoTSubCommandEntry_GenericCmd::GetBodySourceCode() const
{
EnumData* enumData = &Globals::Instance->cfg.enumData;
const auto& element = csCommandsDesc.find(commandId);
if (element != csCommandsDesc.end())
{
bool isIndexInMisc = enumData->miscType.find(base) != enumData->miscType.end();
bool isIndexInFade =
enumData->fadeOutSeqPlayer.find(base) != enumData->fadeOutSeqPlayer.end();
bool isIndexInSeqId = enumData->seqId.find(base - 1) != enumData->seqId.end();
std::string entryFmt = element->second.cmdMacro;
std::string firstArg;
entryFmt += element->second.args;
if (commandId == CutsceneOoT_CommandType::CS_CMD_MISC && isIndexInMisc)
firstArg = enumData->miscType[base];
else if (commandId == CutsceneOoT_CommandType::CS_CMD_FADE_OUT_SEQ && isIndexInFade)
firstArg = enumData->fadeOutSeqPlayer[base];
else if (commandId == CutsceneOoT_CommandType::CS_CMD_START_SEQ && isIndexInSeqId)
firstArg = enumData->seqId[base - 1];
else if (commandId == CutsceneOoT_CommandType::CS_CMD_STOP_SEQ && isIndexInSeqId)
firstArg = enumData->seqId[base - 1];
else
{
return StringHelper::Sprintf(entryFmt.c_str(), base - 1, startFrame, endFrame, pad,
unused1, unused2, unused3, unused4, unused5, unused6,
unused7, unused8, unused9, unused10);
}
}
return StringHelper::Sprintf("CS_UNK_DATA(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, "
"0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X)",
word0, word1, unused1, unused2, unused3, unused4, unused5, unused6,
unused7, unused8, unused9, unused10);
}
size_t CutsceneOoTSubCommandEntry_GenericCmd::GetRawSize() const
{
return 0x30;
}
CutsceneOoTCommand_GenericCmd::CutsceneOoTCommand_GenericCmd(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex,
CutsceneOoT_CommandType cmdId)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
commandID = static_cast<uint32_t>(cmdId);
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneOoTSubCommandEntry_GenericCmd(rawData, rawDataIndex, cmdId);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneOoTCommand_GenericCmd::GetCommandMacro() const
{
const auto& element = csCommandsDesc.find(static_cast<CutsceneOoT_CommandType>(commandID));
if (element != csCommandsDesc.end())
{
return StringHelper::Sprintf("%s_LIST(%i)", element->second.cmdMacro, numEntries);
}
return StringHelper::Sprintf("CS_UNK_DATA_LIST(0x%X, %i)", commandID, numEntries);
}
/**** CAMERA ****/
CutsceneOoTCommand_CameraPoint::CutsceneOoTCommand_CameraPoint(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
continueFlag = BitConverter::ToInt8BE(rawData, rawDataIndex + 0);
cameraRoll = BitConverter::ToInt8BE(rawData, rawDataIndex + 1);
nextPointFrame = BitConverter::ToInt16BE(rawData, rawDataIndex + 2);
viewAngle = BitConverter::ToFloatBE(rawData, rawDataIndex + 4);
posX = BitConverter::ToInt16BE(rawData, rawDataIndex + 8);
posY = BitConverter::ToInt16BE(rawData, rawDataIndex + 10);
posZ = BitConverter::ToInt16BE(rawData, rawDataIndex + 12);
unused = BitConverter::ToInt16BE(rawData, rawDataIndex + 14);
}
std::string CutsceneOoTCommand_CameraPoint::GetBodySourceCode() const
{
std::string continueMacro = "CS_CAM_CONTINUE";
if (continueFlag != 0)
continueMacro = "CS_CAM_STOP";
return StringHelper::Sprintf("CS_CAM_POINT(%s, 0x%02X, %i, %ff, %i, %i, %i, 0x%04X)",
continueMacro.c_str(), cameraRoll, nextPointFrame, viewAngle, posX,
posY, posZ, unused);
}
size_t CutsceneOoTCommand_CameraPoint::GetRawSize() const
{
return 0x10;
}
CutsceneOoTCommand_GenericCameraCmd::CutsceneOoTCommand_GenericCameraCmd(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
base = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
startFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
endFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 4);
unused = BitConverter::ToUInt16BE(rawData, rawDataIndex + 6);
bool shouldContinue = true;
uint32_t currentPtr = rawDataIndex + 8;
while (shouldContinue)
{
CutsceneOoTCommand_CameraPoint* camPoint =
new CutsceneOoTCommand_CameraPoint(rawData, currentPtr);
entries.push_back(camPoint);
if (camPoint->continueFlag == -1)
shouldContinue = false;
currentPtr += camPoint->GetRawSize();
}
}
std::string CutsceneOoTCommand_GenericCameraCmd::GetCommandMacro() const
{
std::string result;
const char* listStr;
if (commandID == (uint32_t)CutsceneOoT_CommandType::CS_CMD_CAM_AT_SPLINE)
{
listStr = "CS_CAM_AT_SPLINE";
}
else if (commandID == (uint32_t)CutsceneOoT_CommandType::CS_CMD_CAM_AT_SPLINE_REL_TO_PLAYER)
{
listStr = "CS_CAM_AT_SPLINE_REL_TO_PLAYER";
}
else if (commandID == (uint32_t)CutsceneOoT_CommandType::CS_CMD_CAM_EYE_SPLINE_REL_TO_PLAYER)
{
listStr = "CS_CAM_EYE_SPLINE_REL_TO_PLAYER";
}
else
{
listStr = "CS_CAM_EYE_SPLINE";
}
result += StringHelper::Sprintf("%s(%i, %i)", listStr, startFrame, endFrame);
return result;
}
size_t CutsceneOoTCommand_GenericCameraCmd::GetCommandSize() const
{
return 0x0C + entries.at(0)->GetRawSize() * entries.size();
}
/**** RUMBLE ****/
CutsceneOoTSubCommandEntry_Rumble::CutsceneOoTSubCommandEntry_Rumble(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
sourceStrength = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x06);
duration = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x07);
decreaseRate = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x08);
unk_09 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x09);
unk_0A = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x0A);
}
std::string CutsceneOoTSubCommandEntry_Rumble::GetBodySourceCode() const
{
// Note: the first argument is unused
return StringHelper::Sprintf("CS_RUMBLE_CONTROLLER(%i, %i, %i, %i, %i, %i, 0x%02X, 0x%02X)",
base, startFrame, endFrame, sourceStrength, duration, decreaseRate,
unk_09, unk_0A);
}
size_t CutsceneOoTSubCommandEntry_Rumble::GetRawSize() const
{
return 0x0C;
}
CutsceneOoTCommand_Rumble::CutsceneOoTCommand_Rumble(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneOoTSubCommandEntry_Rumble(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneOoTCommand_Rumble::GetCommandMacro() const
{
return StringHelper::Sprintf("CS_RUMBLE_CONTROLLER_LIST(%i)", numEntries);
}
/**** TEXT ****/
CutsceneOoTSubCommandEntry_Text::CutsceneOoTSubCommandEntry_Text(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
type = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x6);
textId1 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x8);
textId2 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0xA);
}
std::string CutsceneOoTSubCommandEntry_Text::GetBodySourceCode() const
{
EnumData* enumData = &Globals::Instance->cfg.enumData;
if (type == 0xFFFF)
{
return StringHelper::Sprintf("CS_TEXT_NONE(%i, %i)", startFrame, endFrame);
}
if (type == 2 &&
enumData->ocarinaSongActionId.find(base) != enumData->ocarinaSongActionId.end())
{
return StringHelper::Sprintf("CS_TEXT_OCARINA_ACTION(%s, %i, %i, 0x%X)",
enumData->ocarinaSongActionId[base].c_str(), startFrame,
endFrame, textId1);
}
if (enumData->textType.find(type) != enumData->textType.end())
{
return StringHelper::Sprintf("CS_TEXT(0x%X, %i, %i, %s, 0x%X, 0x%X)", base, startFrame,
endFrame, enumData->textType[type].c_str(), textId1, textId2);
}
return StringHelper::Sprintf("CS_TEXT(0x%X, %i, %i, %i, 0x%X, 0x%X)", base, startFrame,
endFrame, type, textId1, textId2);
}
size_t CutsceneOoTSubCommandEntry_Text::GetRawSize() const
{
return 0x0C;
}
CutsceneOoTCommand_Text::CutsceneOoTCommand_Text(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneOoTSubCommandEntry_Text(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneOoTCommand_Text::GetCommandMacro() const
{
return StringHelper::Sprintf("CS_TEXT_LIST(%i)", numEntries);
}
/**** ACTOR CUE ****/
CutsceneOoTSubCommandEntry_ActorCue::CutsceneOoTSubCommandEntry_ActorCue(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
rotX = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x6);
rotY = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x8);
rotZ = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0xA);
startPosX = BitConverter::ToInt32BE(rawData, rawDataIndex + 0xC);
startPosY = BitConverter::ToInt32BE(rawData, rawDataIndex + 0x10);
startPosZ = BitConverter::ToInt32BE(rawData, rawDataIndex + 0x14);
endPosX = BitConverter::ToInt32BE(rawData, rawDataIndex + 0x18);
endPosY = BitConverter::ToInt32BE(rawData, rawDataIndex + 0x1C);
endPosZ = BitConverter::ToInt32BE(rawData, rawDataIndex + 0x20);
normalX = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x24);
normalY = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x28);
normalZ = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x2C);
}
std::string CutsceneOoTSubCommandEntry_ActorCue::GetBodySourceCode() const
{
EnumData* enumData = &Globals::Instance->cfg.enumData;
if (static_cast<CutsceneOoT_CommandType>(commandID) ==
CutsceneOoT_CommandType::CS_CMD_PLAYER_CUE)
{
return StringHelper::Sprintf("CS_PLAYER_CUE(%s, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, "
"%i, %i, %i, %i, %.8ef, %.8ef, %.8ef)",
enumData->playerCueId[base].c_str(), startFrame, endFrame,
rotX, rotY, rotZ, startPosX, startPosY, startPosZ, endPosX,
endPosY, endPosZ, normalX, normalY, normalZ);
}
else
{
return StringHelper::Sprintf("CS_ACTOR_CUE(%i, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, "
"%i, %i, %i, %i, %.8ef, %.8ef, %.8ef)",
base, startFrame, endFrame, rotX, rotY, rotZ, startPosX,
startPosY, startPosZ, endPosX, endPosY, endPosZ, normalX,
normalY, normalZ);
}
}
size_t CutsceneOoTSubCommandEntry_ActorCue::GetRawSize() const
{
return 0x30;
}
CutsceneOoTCommand_ActorCue::CutsceneOoTCommand_ActorCue(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneOoTSubCommandEntry_ActorCue(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneOoTCommand_ActorCue::GetCommandMacro() const
{
EnumData* enumData = &Globals::Instance->cfg.enumData;
if (static_cast<CutsceneOoT_CommandType>(commandID) ==
CutsceneOoT_CommandType::CS_CMD_PLAYER_CUE)
{
return StringHelper::Sprintf("CS_PLAYER_CUE_LIST(%i)", entries.size());
}
if (enumData->cutsceneCmd.find(commandID) != enumData->cutsceneCmd.end())
{
return StringHelper::Sprintf("CS_ACTOR_CUE_LIST(%s, %i)",
enumData->cutsceneCmd[commandID].c_str(), entries.size());
}
return StringHelper::Sprintf("CS_ACTOR_CUE_LIST(0x%04X, %i)", commandID, entries.size());
}
/**** DESTINATION ****/
CutsceneOoTCommand_Destination::CutsceneOoTCommand_Destination(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
base = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
startFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
endFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 4);
unknown = BitConverter::ToUInt16BE(rawData, rawDataIndex + 6); // endFrame duplicate
}
std::string CutsceneOoTCommand_Destination::GenerateSourceCode() const
{
EnumData* enumData = &Globals::Instance->cfg.enumData;
if (enumData->destination.find(base) != enumData->destination.end())
{
return StringHelper::Sprintf("CS_DESTINATION(%s, %i, %i),\n",
enumData->destination[base].c_str(), startFrame, endFrame);
}
return StringHelper::Sprintf("CS_DESTINATION(%i, %i, %i),\n", base, startFrame, endFrame);
}
size_t CutsceneOoTCommand_Destination::GetCommandSize() const
{
return 0x10;
}
/**** TRANSITION ****/
CutsceneOoTCommand_Transition::CutsceneOoTCommand_Transition(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
base = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
startFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
endFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 4);
}
std::string CutsceneOoTCommand_Transition::GenerateSourceCode() const
{
EnumData* enumData = &Globals::Instance->cfg.enumData;
if (enumData->transitionType.find(base) != enumData->transitionType.end())
{
return StringHelper::Sprintf("CS_TRANSITION(%s, %i, %i),\n",
enumData->transitionType[base].c_str(), startFrame, endFrame);
}
return StringHelper::Sprintf("CS_TRANSITION(%i, %i, %i),\n", base, startFrame, endFrame);
}
size_t CutsceneOoTCommand_Transition::GetCommandSize() const
{
return 0x10;
}

View File

@@ -0,0 +1,314 @@
#pragma once
#include "Cutscene_Common.h"
// https://github.com/zeldaret/oot/blob/7235af2249843fb68740111b70089bad827a4730/include/z64cutscene.h#L35-L165
enum class CutsceneOoT_CommandType
{
CS_CMD_CAM_EYE_SPLINE = 0x01,
CS_CMD_CAM_AT_SPLINE,
CS_CMD_MISC,
CS_CMD_LIGHT_SETTING,
CS_CMD_CAM_EYE_SPLINE_REL_TO_PLAYER,
CS_CMD_CAM_AT_SPLINE_REL_TO_PLAYER,
CS_CMD_CAM_EYE,
CS_CMD_CAM_AT,
CS_CMD_RUMBLE_CONTROLLER,
CS_CMD_PLAYER_CUE,
CS_CMD_UNIMPLEMENTED_B,
CS_CMD_UNIMPLEMENTED_D = 0x0D,
CS_CMD_ACTOR_CUE_1_0,
CS_CMD_ACTOR_CUE_0_0,
CS_CMD_ACTOR_CUE_1_1,
CS_CMD_ACTOR_CUE_0_1,
CS_CMD_ACTOR_CUE_0_2,
CS_CMD_TEXT,
CS_CMD_UNIMPLEMENTED_15 = 0x15,
CS_CMD_UNIMPLEMENTED_16,
CS_CMD_ACTOR_CUE_0_3,
CS_CMD_ACTOR_CUE_1_2,
CS_CMD_ACTOR_CUE_2_0,
CS_CMD_UNIMPLEMENTED_1B = 0x1B,
CS_CMD_UNIMPLEMENTED_1C,
CS_CMD_ACTOR_CUE_3_0,
CS_CMD_ACTOR_CUE_4_0,
CS_CMD_ACTOR_CUE_6_0,
CS_CMD_UNIMPLEMENTED_20,
CS_CMD_UNIMPLEMENTED_21,
CS_CMD_ACTOR_CUE_0_4,
CS_CMD_ACTOR_CUE_1_3,
CS_CMD_ACTOR_CUE_2_1,
CS_CMD_ACTOR_CUE_3_1,
CS_CMD_ACTOR_CUE_4_1,
CS_CMD_ACTOR_CUE_0_5,
CS_CMD_ACTOR_CUE_1_4,
CS_CMD_ACTOR_CUE_2_2,
CS_CMD_ACTOR_CUE_3_2,
CS_CMD_ACTOR_CUE_4_2,
CS_CMD_ACTOR_CUE_5_0,
CS_CMD_TRANSITION,
CS_CMD_ACTOR_CUE_0_6,
CS_CMD_ACTOR_CUE_4_3,
CS_CMD_ACTOR_CUE_1_5,
CS_CMD_ACTOR_CUE_7_0,
CS_CMD_ACTOR_CUE_2_3,
CS_CMD_ACTOR_CUE_3_3,
CS_CMD_ACTOR_CUE_6_1,
CS_CMD_ACTOR_CUE_3_4,
CS_CMD_ACTOR_CUE_4_4,
CS_CMD_ACTOR_CUE_5_1,
CS_CMD_ACTOR_CUE_6_2 = 0x39,
CS_CMD_ACTOR_CUE_6_3,
CS_CMD_UNIMPLEMENTED_3B,
CS_CMD_ACTOR_CUE_7_1,
CS_CMD_UNIMPLEMENTED_3D,
CS_CMD_ACTOR_CUE_8_0,
CS_CMD_ACTOR_CUE_3_5,
CS_CMD_ACTOR_CUE_1_6,
CS_CMD_ACTOR_CUE_3_6,
CS_CMD_ACTOR_CUE_3_7,
CS_CMD_ACTOR_CUE_2_4,
CS_CMD_ACTOR_CUE_1_7,
CS_CMD_ACTOR_CUE_2_5,
CS_CMD_ACTOR_CUE_1_8,
CS_CMD_UNIMPLEMENTED_47,
CS_CMD_ACTOR_CUE_2_6,
CS_CMD_UNIMPLEMENTED_49,
CS_CMD_ACTOR_CUE_2_7,
CS_CMD_ACTOR_CUE_3_8,
CS_CMD_ACTOR_CUE_0_7,
CS_CMD_ACTOR_CUE_5_2,
CS_CMD_ACTOR_CUE_1_9,
CS_CMD_ACTOR_CUE_4_5,
CS_CMD_ACTOR_CUE_1_10,
CS_CMD_ACTOR_CUE_2_8,
CS_CMD_ACTOR_CUE_3_9,
CS_CMD_ACTOR_CUE_4_6,
CS_CMD_ACTOR_CUE_5_3,
CS_CMD_ACTOR_CUE_0_8,
CS_CMD_START_SEQ,
CS_CMD_STOP_SEQ,
CS_CMD_ACTOR_CUE_6_4,
CS_CMD_ACTOR_CUE_7_2,
CS_CMD_ACTOR_CUE_5_4,
CS_CMD_ACTOR_CUE_0_9 = 0x5D,
CS_CMD_ACTOR_CUE_1_11,
CS_CMD_ACTOR_CUE_0_10 = 0x69,
CS_CMD_ACTOR_CUE_2_9,
CS_CMD_ACTOR_CUE_0_11,
CS_CMD_ACTOR_CUE_3_10,
CS_CMD_UNIMPLEMENTED_6D,
CS_CMD_ACTOR_CUE_0_12,
CS_CMD_ACTOR_CUE_7_3,
CS_CMD_UNIMPLEMENTED_70,
CS_CMD_UNIMPLEMENTED_71,
CS_CMD_ACTOR_CUE_7_4,
CS_CMD_ACTOR_CUE_6_5,
CS_CMD_ACTOR_CUE_1_12,
CS_CMD_ACTOR_CUE_2_10,
CS_CMD_ACTOR_CUE_1_13,
CS_CMD_ACTOR_CUE_0_13,
CS_CMD_ACTOR_CUE_1_14,
CS_CMD_ACTOR_CUE_2_11,
CS_CMD_ACTOR_CUE_0_14 = 0x7B,
CS_CMD_FADE_OUT_SEQ,
CS_CMD_ACTOR_CUE_1_15,
CS_CMD_ACTOR_CUE_2_12,
CS_CMD_ACTOR_CUE_3_11,
CS_CMD_ACTOR_CUE_4_7,
CS_CMD_ACTOR_CUE_5_5,
CS_CMD_ACTOR_CUE_6_6,
CS_CMD_ACTOR_CUE_1_16,
CS_CMD_ACTOR_CUE_2_13,
CS_CMD_ACTOR_CUE_3_12,
CS_CMD_ACTOR_CUE_7_5,
CS_CMD_ACTOR_CUE_4_8,
CS_CMD_ACTOR_CUE_5_6,
CS_CMD_ACTOR_CUE_6_7,
CS_CMD_ACTOR_CUE_0_15,
CS_CMD_ACTOR_CUE_0_16,
CS_CMD_TIME,
CS_CMD_ACTOR_CUE_1_17,
CS_CMD_ACTOR_CUE_7_6,
CS_CMD_ACTOR_CUE_9_0,
CS_CMD_ACTOR_CUE_0_17,
CS_CMD_DESTINATION = 0x03E8,
CS_CMD_END = 0xFFFF
};
/**** GENERIC ****/
class CutsceneOoTSubCommandEntry_GenericCmd : public CutsceneSubCommandEntry
{
public:
CutsceneOoT_CommandType commandId;
uint32_t word0 = 0;
uint32_t word1 = 0;
uint32_t unused1 = 0;
uint32_t unused2 = 0;
uint32_t unused3 = 0;
uint32_t unused4 = 0;
uint32_t unused5 = 0;
uint32_t unused6 = 0;
uint32_t unused7 = 0;
uint32_t unused8 = 0;
uint32_t unused9 = 0;
uint32_t unused10 = 0;
CutsceneOoTSubCommandEntry_GenericCmd(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex, CutsceneOoT_CommandType cmdId);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneOoTCommand_GenericCmd : public CutsceneCommand
{
public:
CutsceneOoTCommand_GenericCmd(const std::vector<uint8_t>& rawData, offset_t rawDataIndex,
CutsceneOoT_CommandType cmdId);
std::string GetCommandMacro() const override;
};
/**** CAMERA ****/
class CutsceneOoTCommand_CameraPoint : public CutsceneSubCommandEntry
{
public:
int8_t continueFlag;
int8_t cameraRoll;
int16_t nextPointFrame;
float viewAngle;
int16_t posX, posY, posZ;
int16_t unused;
CutsceneOoTCommand_CameraPoint(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneOoTCommand_GenericCameraCmd : public CutsceneCommand
{
public:
uint16_t base;
uint16_t startFrame;
uint16_t endFrame;
uint16_t unused;
CutsceneOoTCommand_GenericCameraCmd(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
size_t GetCommandSize() const override;
};
/**** TRANSITION ****/
class CutsceneOoTCommand_Transition : public CutsceneCommand
{
public:
uint16_t base;
uint16_t startFrame;
uint16_t endFrame;
CutsceneOoTCommand_Transition(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GenerateSourceCode() const override;
size_t GetCommandSize() const override;
};
/**** RUMBLE ****/
class CutsceneOoTSubCommandEntry_Rumble : public CutsceneSubCommandEntry
{
public:
uint8_t sourceStrength;
uint8_t duration;
uint8_t decreaseRate;
uint8_t unk_09;
uint8_t unk_0A;
CutsceneOoTSubCommandEntry_Rumble(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneOoTCommand_Rumble : public CutsceneCommand
{
public:
CutsceneOoTCommand_Rumble(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};
/**** TEXT ****/
class CutsceneOoTSubCommandEntry_Text : public CutsceneSubCommandEntry
{
public:
uint16_t type;
uint16_t textId1;
uint16_t textId2;
CutsceneOoTSubCommandEntry_Text(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneOoTCommand_Text : public CutsceneCommand
{
public:
CutsceneOoTCommand_Text(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};
/**** ACTOR CUE ****/
class CutsceneOoTSubCommandEntry_ActorCue : public CutsceneSubCommandEntry
{
public:
uint16_t rotX, rotY, rotZ;
int32_t startPosX, startPosY, startPosZ;
int32_t endPosX, endPosY, endPosZ;
float normalX, normalY, normalZ;
CutsceneOoTSubCommandEntry_ActorCue(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneOoTCommand_ActorCue : public CutsceneCommand
{
public:
CutsceneOoTCommand_ActorCue(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};
/**** DESTINATION ****/
class CutsceneOoTCommand_Destination : public CutsceneCommand
{
public:
uint16_t base;
uint16_t startFrame;
uint16_t endFrame;
uint16_t unknown;
CutsceneOoTCommand_Destination(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GenerateSourceCode() const override;
size_t GetCommandSize() const override;
};

View File

@@ -0,0 +1,596 @@
#include "Cutscene_Commands.h"
#include <cassert>
#include <unordered_map>
#include "CutsceneMM_Commands.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
/* CutsceneSubCommandEntry */
CutsceneSubCommandEntry::CutsceneSubCommandEntry(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
{
base = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
startFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
endFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 4);
pad = BitConverter::ToUInt16BE(rawData, rawDataIndex + 6);
}
std::string CutsceneSubCommandEntry::GetBodySourceCode() const
{
return StringHelper::Sprintf("CMD_HH(0x%04X, 0x%04X), CMD_HH(0x%04X, 0x%04X)", base, startFrame,
endFrame, pad);
}
size_t CutsceneSubCommandEntry::GetRawSize() const
{
return 0x08;
}
/* CutsceneCommand */
CutsceneCommand::CutsceneCommand(const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
{
numEntries = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0);
}
CutsceneCommand::~CutsceneCommand()
{
for (auto& entry : entries)
{
delete entry;
}
}
std::string CutsceneCommand::GetCommandMacro() const
{
return StringHelper::Sprintf("CMD_W(0x%08X), CMD_W(0x%08X)", commandID, numEntries);
}
std::string CutsceneCommand::GenerateSourceCode() const
{
std::string result;
result += GetCommandMacro();
result += ",\n";
for (auto& entry : entries)
{
result += " ";
result += entry->GetBodySourceCode();
result += ",\n";
}
return result;
}
size_t CutsceneCommand::GetCommandSize() const
{
size_t size = 0;
if (entries.size() > 0)
{
size = entries.at(0)->GetRawSize() * entries.size();
}
else
{
size = 0x08 * numEntries;
}
return 0x08 + size;
}
void CutsceneCommand::SetCommandID(uint32_t nCommandID)
{
commandID = nCommandID;
for (auto& entry : entries)
{
entry->commandID = commandID;
}
}
// Specific for command lists where each entry has size 0x30 bytes
const std::unordered_map<CutsceneCommands, CsCommandListDescriptor> csCommandsDesc = {
{CutsceneCommands::Misc,
{"CS_MISC", "(0x%04X, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}},
{CutsceneCommands::SetLighting,
{"CS_LIGHTING", "(0x%02X, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}},
{CutsceneCommands::PlayBGM, {"CS_PLAY_BGM", "(%i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}},
{CutsceneCommands::StopBGM, {"CS_STOP_BGM", "(%i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}},
{CutsceneCommands::FadeBGM, {"CS_FADE_BGM", "(%i, %i, %i, %i, %i, %i, %i, %i, %i, %i, %i)"}},
};
CutsceneSubCommandEntry_GenericCmd::CutsceneSubCommandEntry_GenericCmd(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex, CutsceneCommands cmdId)
: CutsceneSubCommandEntry(rawData, rawDataIndex), commandId(cmdId)
{
word0 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x0);
word1 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x4);
unused1 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x8);
unused2 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0xC);
unused3 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x10);
unused4 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x14);
unused5 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x18);
unused6 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x1C);
unused7 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x20);
unused8 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x24);
unused9 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x28);
unused10 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x2C);
}
std::string CutsceneSubCommandEntry_GenericCmd::GetBodySourceCode() const
{
const auto& element = csCommandsDesc.find(commandId);
if (element != csCommandsDesc.end())
{
std::string entryFmt = element->second.cmdMacro;
entryFmt += element->second.args;
return StringHelper::Sprintf(entryFmt.c_str(), base, startFrame, endFrame, pad, unused1,
unused2, unused3, unused4, unused5, unused6, unused7, unused8,
unused9, unused10);
}
return StringHelper::Sprintf("CS_UNK_DATA(0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, "
"0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X)",
word0, word1, unused1, unused2, unused3, unused4, unused5, unused6,
unused7, unused8, unused9, unused10);
}
size_t CutsceneSubCommandEntry_GenericCmd::GetRawSize() const
{
return 0x30;
}
CutsceneCommand_GenericCmd::CutsceneCommand_GenericCmd(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex,
CutsceneCommands cmdId)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
commandID = static_cast<uint32_t>(cmdId);
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneSubCommandEntry_GenericCmd(rawData, rawDataIndex, cmdId);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneCommand_GenericCmd::GetCommandMacro() const
{
const auto& element = csCommandsDesc.find(static_cast<CutsceneCommands>(commandID));
if (element != csCommandsDesc.end())
{
return StringHelper::Sprintf("%s_LIST(%i)", element->second.cmdMacro, numEntries);
}
return StringHelper::Sprintf("CS_UNK_DATA_LIST(0x%X, %i)", commandID, numEntries);
}
CutsceneCameraPoint::CutsceneCameraPoint(const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
continueFlag = BitConverter::ToInt8BE(rawData, rawDataIndex + 0);
cameraRoll = BitConverter::ToInt8BE(rawData, rawDataIndex + 1);
nextPointFrame = BitConverter::ToInt16BE(rawData, rawDataIndex + 2);
viewAngle = BitConverter::ToFloatBE(rawData, rawDataIndex + 4);
posX = BitConverter::ToInt16BE(rawData, rawDataIndex + 8);
posY = BitConverter::ToInt16BE(rawData, rawDataIndex + 10);
posZ = BitConverter::ToInt16BE(rawData, rawDataIndex + 12);
unused = BitConverter::ToInt16BE(rawData, rawDataIndex + 14);
}
std::string CutsceneCameraPoint::GetBodySourceCode() const
{
std::string result = "";
if (commandID == (int32_t)CutsceneCommands::SetCameraFocus)
{
result += "CS_CAM_FOCUS_POINT";
}
else if (commandID == (int32_t)CutsceneCommands::SetCameraFocusLink)
{
result += "CS_CAM_FOCUS_POINT_PLAYER";
}
else if (commandID == (int32_t)CutsceneCommands::SetCameraPosLink)
{
result += "CS_CAM_POS_PLAYER";
}
else
{
result += "CS_CAM_POS";
}
std::string continueMacro = "CS_CMD_CONTINUE";
if (continueFlag != 0)
continueMacro = "CS_CMD_STOP";
result +=
StringHelper::Sprintf("(%s, 0x%02X, %i, %ff, %i, %i, %i, 0x%04X)", continueMacro.c_str(),
cameraRoll, nextPointFrame, viewAngle, posX, posY, posZ, unused);
return result;
}
size_t CutsceneCameraPoint::GetRawSize() const
{
return 0x10;
}
CutsceneCommandSetCameraPos::CutsceneCommandSetCameraPos(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
base = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
startFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
endFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 4);
unused = BitConverter::ToUInt16BE(rawData, rawDataIndex + 6);
bool shouldContinue = true;
uint32_t currentPtr = rawDataIndex + 8;
while (shouldContinue)
{
CutsceneCameraPoint* camPoint = new CutsceneCameraPoint(rawData, currentPtr);
entries.push_back(camPoint);
if (camPoint->continueFlag == -1)
shouldContinue = false;
currentPtr += camPoint->GetRawSize();
}
}
std::string CutsceneCommandSetCameraPos::GetCommandMacro() const
{
std::string result;
std::string listStr;
if (commandID == (int32_t)CutsceneCommands::SetCameraFocus)
{
listStr = "CS_CAM_FOCUS_POINT_LIST";
}
else if (commandID == (int32_t)CutsceneCommands::SetCameraFocusLink)
{
listStr = "CS_CAM_FOCUS_POINT_PLAYER_LIST";
}
else if (commandID == (int32_t)CutsceneCommands::SetCameraPosLink)
{
listStr = "CS_CAM_POS_PLAYER_LIST";
}
else
{
listStr = "CS_CAM_POS_LIST";
}
result += StringHelper::Sprintf("%s(%i, %i)", listStr.c_str(), startFrame, endFrame);
return result;
}
size_t CutsceneCommandSetCameraPos::GetCommandSize() const
{
return 0x0C + entries.at(0)->GetRawSize() * entries.size();
}
CutsceneSubCommandEntry_Rumble::CutsceneSubCommandEntry_Rumble(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
unk_06 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x06);
unk_07 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x07);
unk_08 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x08);
unk_09 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x09);
unk_0A = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x0A);
unk_0B = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x0B);
}
std::string CutsceneSubCommandEntry_Rumble::GetBodySourceCode() const
{
if (Globals::Instance->game == ZGame::MM_RETAIL)
{
return StringHelper::Sprintf("CS_RUMBLE(%i, %i, %i, 0x%02X, 0x%02X, 0x%02X)", base,
startFrame, endFrame, unk_06, unk_07, unk_08);
}
return StringHelper::Sprintf("CS_CMD_09(%i, %i, %i, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X)",
base, startFrame, endFrame, unk_06, unk_07, unk_08, unk_09, unk_0A,
unk_0B);
}
size_t CutsceneSubCommandEntry_Rumble::GetRawSize() const
{
return 0x0C;
}
CutsceneCommand_Rumble::CutsceneCommand_Rumble(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneSubCommandEntry_Rumble(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneCommand_Rumble::GetCommandMacro() const
{
if (Globals::Instance->game == ZGame::MM_RETAIL)
{
return StringHelper::Sprintf("CS_RUMBLE_LIST(%i)", numEntries);
}
return StringHelper::Sprintf("CS_CMD_09_LIST(%i)", numEntries);
}
CutsceneSubCommandEntry_SetTime::CutsceneSubCommandEntry_SetTime(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
hour = BitConverter::ToUInt8BE(rawData, rawDataIndex + 6);
minute = BitConverter::ToUInt8BE(rawData, rawDataIndex + 7);
unk_08 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8);
}
std::string CutsceneSubCommandEntry_SetTime::GetBodySourceCode() const
{
return StringHelper::Sprintf("CS_TIME(%i, %i, %i, %i, %i, %i)", base, startFrame, endFrame,
hour, minute, unk_08);
}
size_t CutsceneSubCommandEntry_SetTime::GetRawSize() const
{
return 0x0C;
}
CutsceneCommand_SetTime::CutsceneCommand_SetTime(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneSubCommandEntry_SetTime(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneCommand_SetTime::GetCommandMacro() const
{
return StringHelper::Sprintf("CS_TIME_LIST(%i)", numEntries);
}
CutsceneSubCommandEntry_TextBox::CutsceneSubCommandEntry_TextBox(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
type = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x6);
textId1 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x8);
textId2 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0xA);
}
std::string CutsceneSubCommandEntry_TextBox::GetBodySourceCode() const
{
if (type == 0xFFFF)
{
return StringHelper::Sprintf("CS_TEXT_NONE(%i, %i)", startFrame, endFrame);
}
if (type == 2)
{
return StringHelper::Sprintf("CS_TEXT_LEARN_SONG(%i, %i, %i, 0x%X)", base, startFrame,
endFrame, textId1);
}
if (Globals::Instance->game == ZGame::MM_RETAIL)
{
switch (type)
{
case 0:
return StringHelper::Sprintf("CS_TEXT_DEFAULT(0x%X, %i, %i, 0x%X, 0x%X)", base,
startFrame, endFrame, textId1, textId2);
case 1:
return StringHelper::Sprintf("CS_TEXT_TYPE_1(0x%X, %i, %i, 0x%X, 0x%X)", base,
startFrame, endFrame, textId1, textId2);
case 3:
return StringHelper::Sprintf("CS_TEXT_TYPE_3(0x%X, %i, %i, 0x%X, 0x%X)", base,
startFrame, endFrame, textId1, textId2);
case 4:
return StringHelper::Sprintf("CS_TEXT_BOSSES_REMAINS(0x%X, %i, %i, 0x%X)", base,
startFrame, endFrame, textId1);
case 5:
return StringHelper::Sprintf("CS_TEXT_ALL_NORMAL_MASKS(0x%X, %i, %i, 0x%X)", base,
startFrame, endFrame, textId1);
}
}
return StringHelper::Sprintf("CS_TEXT_DISPLAY_TEXTBOX(0x%X, %i, %i, %i, 0x%X, 0x%X)", base,
startFrame, endFrame, type, textId1, textId2);
}
size_t CutsceneSubCommandEntry_TextBox::GetRawSize() const
{
return 0x0C;
}
CutsceneCommand_TextBox::CutsceneCommand_TextBox(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneSubCommandEntry_TextBox(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneCommand_TextBox::GetCommandMacro() const
{
return StringHelper::Sprintf("CS_TEXT_LIST(%i)", numEntries);
}
CutsceneSubCommandEntry_ActorAction::CutsceneSubCommandEntry_ActorAction(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
rotX = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x6);
rotY = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x8);
rotZ = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0xA);
startPosX = BitConverter::ToInt32BE(rawData, rawDataIndex + 0xC);
startPosY = BitConverter::ToInt32BE(rawData, rawDataIndex + 0x10);
startPosZ = BitConverter::ToInt32BE(rawData, rawDataIndex + 0x14);
endPosX = BitConverter::ToInt32BE(rawData, rawDataIndex + 0x18);
endPosY = BitConverter::ToInt32BE(rawData, rawDataIndex + 0x1C);
endPosZ = BitConverter::ToInt32BE(rawData, rawDataIndex + 0x20);
normalX = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x24);
normalY = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x28);
normalZ = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x2C);
}
std::string CutsceneSubCommandEntry_ActorAction::GetBodySourceCode() const
{
std::string result;
if (Globals::Instance->game == ZGame::MM_RETAIL)
{
if (static_cast<CutsceneMMCommands>(commandID) ==
CutsceneMMCommands::CS_CMD_SET_PLAYER_ACTION)
{
result = "CS_PLAYER_ACTION";
}
else
{
result = "CS_ACTOR_ACTION";
}
}
else
{
if (static_cast<CutsceneCommands>(commandID) == CutsceneCommands::SetPlayerAction)
{
result = "CS_PLAYER_ACTION";
}
else
{
result = "CS_NPC_ACTION";
}
}
result +=
StringHelper::Sprintf("(%i, %i, %i, 0x%04X, 0x%04X, 0x%04X, %i, %i, "
"%i, %i, %i, %i, %.11ef, %.11ef, %.11ef)",
base, startFrame, endFrame, rotX, rotY, rotZ, startPosX, startPosY,
startPosZ, endPosX, endPosY, endPosZ, normalX, normalY, normalZ);
return result;
}
size_t CutsceneSubCommandEntry_ActorAction::GetRawSize() const
{
return 0x30;
}
CutsceneCommand_ActorAction::CutsceneCommand_ActorAction(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneSubCommandEntry_ActorAction(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneCommand_ActorAction::GetCommandMacro() const
{
if (Globals::Instance->game == ZGame::MM_RETAIL)
{
if (static_cast<CutsceneMMCommands>(commandID) ==
CutsceneMMCommands::CS_CMD_SET_PLAYER_ACTION)
{
return StringHelper::Sprintf("CS_PLAYER_ACTION_LIST(%i)", numEntries);
}
return StringHelper::Sprintf("CS_ACTOR_ACTION_LIST(0x%03X, %i)", commandID, numEntries);
}
if (static_cast<CutsceneCommands>(commandID) == CutsceneCommands::SetPlayerAction)
{
return StringHelper::Sprintf("CS_PLAYER_ACTION_LIST(%i)", entries.size());
}
return StringHelper::Sprintf("CS_NPC_ACTION_LIST(0x%03X, %i)", commandID, entries.size());
}
CutsceneCommand_Terminator::CutsceneCommand_Terminator(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
base = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
startFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
endFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 4);
unknown = BitConverter::ToUInt16BE(rawData, rawDataIndex + 6); // endFrame duplicate
}
std::string CutsceneCommand_Terminator::GenerateSourceCode() const
{
std::string result;
result += StringHelper::Sprintf("CS_TERMINATOR(%i, %i, %i),\n", base, startFrame, endFrame);
return result;
}
size_t CutsceneCommand_Terminator::GetCommandSize() const
{
return 0x10;
}
CutsceneCommandSceneTransFX::CutsceneCommandSceneTransFX(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
base = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
startFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
endFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 4);
}
std::string CutsceneCommandSceneTransFX::GenerateSourceCode() const
{
return StringHelper::Sprintf("CS_SCENE_TRANS_FX(%i, %i, %i),\n", base, startFrame, endFrame);
}
size_t CutsceneCommandSceneTransFX::GetCommandSize() const
{
return 0x10;
}

View File

@@ -0,0 +1,267 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "Declaration.h"
enum class CutsceneCommands
{
SetCameraPos = 0x0001,
SetCameraFocus = 0x0002,
Misc = 0x0003,
SetLighting = 0x0004,
SetCameraPosLink = 0x0005,
SetCameraFocusLink = 0x0006,
Cmd07 = 0x0007,
Cmd08 = 0x0008,
Cmd09 = 0x0009, // Rumble
Textbox = 0x0013,
SetPlayerAction = 0x000A,
SetActorAction1 = 0x000F,
SetActorAction2 = 0x000E,
SetActorAction3 = 0x0019,
SetActorAction4 = 0x001D,
SetActorAction5 = 0x001E,
SetActorAction6 = 0x002C,
SetActorAction7 = 0x001F,
SetActorAction8 = 0x0031,
SetActorAction9 = 0x003E,
SetActorAction10 = 0x008F,
SetSceneTransFX = 0x002D,
PlayBGM = 0x0056,
StopBGM = 0x0057,
FadeBGM = 0x007C,
SetTime = 0x008C,
Terminator = 0x03E8,
};
typedef struct CsCommandListDescriptor
{
const char* cmdMacro;
const char* args;
} CsCommandListDescriptor;
class CutsceneSubCommandEntry
{
public:
uint16_t base;
uint16_t startFrame;
uint16_t endFrame;
uint16_t pad;
uint32_t commandID;
CutsceneSubCommandEntry(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
virtual ~CutsceneSubCommandEntry() = default;
virtual std::string GetBodySourceCode() const;
virtual size_t GetRawSize() const;
};
class CutsceneCommand
{
public:
uint32_t commandID;
uint32_t commandIndex;
uint32_t numEntries;
std::vector<CutsceneSubCommandEntry*> entries;
CutsceneCommand(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
virtual ~CutsceneCommand();
virtual std::string GetCommandMacro() const;
virtual std::string GenerateSourceCode() const;
virtual size_t GetCommandSize() const;
virtual void SetCommandID(uint32_t nCommandID);
};
class CutsceneSubCommandEntry_GenericCmd : public CutsceneSubCommandEntry
{
public:
CutsceneCommands commandId;
uint32_t word0 = 0;
uint32_t word1 = 0;
uint32_t unused1 = 0;
uint32_t unused2 = 0;
uint32_t unused3 = 0;
uint32_t unused4 = 0;
uint32_t unused5 = 0;
uint32_t unused6 = 0;
uint32_t unused7 = 0;
uint32_t unused8 = 0;
uint32_t unused9 = 0;
uint32_t unused10 = 0;
CutsceneSubCommandEntry_GenericCmd(const std::vector<uint8_t>& rawData, offset_t rawDataIndex,
CutsceneCommands cmdId);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneCommand_GenericCmd : public CutsceneCommand
{
public:
CutsceneCommand_GenericCmd(const std::vector<uint8_t>& rawData, offset_t rawDataIndex,
CutsceneCommands cmdId);
std::string GetCommandMacro() const override;
};
class CutsceneCameraPoint : public CutsceneSubCommandEntry
{
public:
int8_t continueFlag;
int8_t cameraRoll;
int16_t nextPointFrame;
float viewAngle;
int16_t posX, posY, posZ;
int16_t unused;
CutsceneCameraPoint(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneCommandSetCameraPos : public CutsceneCommand
{
public:
uint16_t base;
uint16_t startFrame;
uint16_t endFrame;
uint16_t unused;
CutsceneCommandSetCameraPos(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
size_t GetCommandSize() const override;
};
class CutsceneCommandSceneTransFX : public CutsceneCommand
{
public:
uint16_t base;
uint16_t startFrame;
uint16_t endFrame;
CutsceneCommandSceneTransFX(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GenerateSourceCode() const override;
size_t GetCommandSize() const override;
};
class CutsceneSubCommandEntry_Rumble : public CutsceneSubCommandEntry
{
public:
uint8_t unk_06;
uint8_t unk_07;
uint8_t unk_08;
uint8_t unk_09;
uint8_t unk_0A;
uint8_t unk_0B;
CutsceneSubCommandEntry_Rumble(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneCommand_Rumble : public CutsceneCommand
{
public:
CutsceneCommand_Rumble(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};
class CutsceneSubCommandEntry_SetTime : public CutsceneSubCommandEntry
{
public:
uint8_t hour;
uint8_t minute;
uint32_t unk_08;
CutsceneSubCommandEntry_SetTime(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneCommand_SetTime : public CutsceneCommand
{
public:
CutsceneCommand_SetTime(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};
class CutsceneSubCommandEntry_TextBox : public CutsceneSubCommandEntry
{
public:
uint16_t type;
uint16_t textId1;
uint16_t textId2;
CutsceneSubCommandEntry_TextBox(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneCommand_TextBox : public CutsceneCommand
{
public:
CutsceneCommand_TextBox(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};
class CutsceneSubCommandEntry_ActorAction : public CutsceneSubCommandEntry
{
public:
uint16_t rotX, rotY, rotZ;
int32_t startPosX, startPosY, startPosZ;
int32_t endPosX, endPosY, endPosZ;
float normalX, normalY, normalZ;
CutsceneSubCommandEntry_ActorAction(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneCommand_ActorAction : public CutsceneCommand
{
public:
CutsceneCommand_ActorAction(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};
class CutsceneCommand_Terminator : public CutsceneCommand
{
public:
uint16_t base;
uint16_t startFrame;
uint16_t endFrame;
uint16_t unknown;
CutsceneCommand_Terminator(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GenerateSourceCode() const override;
size_t GetCommandSize() const override;
};

View File

@@ -0,0 +1,128 @@
#include "Cutscene_Common.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
/* CutsceneSubCommandEntry */
CutsceneSubCommandEntry::CutsceneSubCommandEntry(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
{
base = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
startFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
endFrame = BitConverter::ToUInt16BE(rawData, rawDataIndex + 4);
pad = BitConverter::ToUInt16BE(rawData, rawDataIndex + 6);
}
std::string CutsceneSubCommandEntry::GetBodySourceCode() const
{
return StringHelper::Sprintf("CMD_HH(0x%04X, 0x%04X), CMD_HH(0x%04X, 0x%04X)", base, startFrame,
endFrame, pad);
}
size_t CutsceneSubCommandEntry::GetRawSize() const
{
return 0x08;
}
/* CutsceneCommand */
CutsceneCommand::CutsceneCommand(const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
{
numEntries = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0);
}
CutsceneCommand::~CutsceneCommand()
{
for (auto entry : entries)
{
delete entry;
}
}
std::string CutsceneCommand::GetCommandMacro() const
{
return StringHelper::Sprintf("CMD_W(0x%08X), CMD_W(0x%08X)", commandID, numEntries);
}
std::string CutsceneCommand::GenerateSourceCode() const
{
std::string result;
result += GetCommandMacro();
result += ",\n";
for (auto& entry : entries)
{
result += " ";
result += entry->GetBodySourceCode();
result += ",\n";
}
return result;
}
size_t CutsceneCommand::GetCommandSize() const
{
size_t size = 0;
if (entries.size() > 0)
{
size = entries.at(0)->GetRawSize() * entries.size();
}
else
{
size = 0x08 * numEntries;
}
return 0x08 + size;
}
void CutsceneCommand::SetCommandID(uint32_t nCommandID)
{
commandID = nCommandID;
for (auto& entry : entries)
{
entry->commandID = commandID;
}
}
/*** TIME ****/
CutsceneSubCommandEntry_SetTime::CutsceneSubCommandEntry_SetTime(
const std::vector<uint8_t>& rawData, offset_t rawDataIndex)
: CutsceneSubCommandEntry(rawData, rawDataIndex)
{
hour = BitConverter::ToUInt8BE(rawData, rawDataIndex + 6);
minute = BitConverter::ToUInt8BE(rawData, rawDataIndex + 7);
}
std::string CutsceneSubCommandEntry_SetTime::GetBodySourceCode() const
{
// Note: Both OoT and MM have the first argument unused
return StringHelper::Sprintf("CS_TIME(%i, %i, %i, %i, %i)", base, startFrame, endFrame, hour,
minute);
}
size_t CutsceneSubCommandEntry_SetTime::GetRawSize() const
{
return 0x0C;
}
CutsceneCommand_Time::CutsceneCommand_Time(const std::vector<uint8_t>& rawData,
offset_t rawDataIndex)
: CutsceneCommand(rawData, rawDataIndex)
{
rawDataIndex += 4;
entries.reserve(numEntries);
for (size_t i = 0; i < numEntries; i++)
{
auto* entry = new CutsceneSubCommandEntry_SetTime(rawData, rawDataIndex);
entries.push_back(entry);
rawDataIndex += entry->GetRawSize();
}
}
std::string CutsceneCommand_Time::GetCommandMacro() const
{
return StringHelper::Sprintf("CS_TIME_LIST(%i)", numEntries);
}

View File

@@ -0,0 +1,72 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "Declaration.h"
typedef struct CsCommandListDescriptor
{
const char* cmdMacro;
const char* args;
} CsCommandListDescriptor;
class CutsceneSubCommandEntry
{
public:
uint16_t base;
uint16_t startFrame;
uint16_t endFrame;
uint16_t pad;
uint32_t commandID;
CutsceneSubCommandEntry(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
virtual ~CutsceneSubCommandEntry() = default;
virtual std::string GetBodySourceCode() const;
virtual size_t GetRawSize() const;
};
class CutsceneCommand
{
public:
uint32_t commandID;
uint32_t commandIndex;
uint32_t numEntries;
std::vector<CutsceneSubCommandEntry*> entries;
CutsceneCommand(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
virtual ~CutsceneCommand();
virtual std::string GetCommandMacro() const;
virtual std::string GenerateSourceCode() const;
virtual size_t GetCommandSize() const;
virtual void SetCommandID(uint32_t nCommandID);
};
/**** TIME ****/
class CutsceneSubCommandEntry_SetTime : public CutsceneSubCommandEntry
{
public:
uint8_t hour;
uint8_t minute;
CutsceneSubCommandEntry_SetTime(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetBodySourceCode() const override;
size_t GetRawSize() const override;
};
class CutsceneCommand_Time : public CutsceneCommand
{
public:
CutsceneCommand_Time(const std::vector<uint8_t>& rawData, offset_t rawDataIndex);
std::string GetCommandMacro() const override;
};

View File

@@ -0,0 +1,352 @@
#include "SkinLimbStructs.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
#include "ZDisplayList.h"
#include "ZFile.h"
/* Struct_800A57C0 */
Struct_800A57C0::Struct_800A57C0(ZFile* nParent) : ZResource(nParent)
{
}
void Struct_800A57C0::ParseRawData()
{
const auto& rawData = parent->GetRawData();
unk_0 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x00);
unk_2 = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x02);
unk_4 = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x04);
unk_6 = BitConverter::ToInt8BE(rawData, rawDataIndex + 0x06);
unk_7 = BitConverter::ToInt8BE(rawData, rawDataIndex + 0x07);
unk_8 = BitConverter::ToInt8BE(rawData, rawDataIndex + 0x08);
unk_9 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x09);
}
std::string Struct_800A57C0::GetBodySourceCode() const
{
return StringHelper::Sprintf("0x%02X, %i, %i, %i, %i, %i, 0x%02X", unk_0, unk_2, unk_4, unk_6,
unk_7, unk_8, unk_9);
}
std::string Struct_800A57C0::GetSourceTypeName() const
{
return "Struct_800A57C0";
}
ZResourceType Struct_800A57C0::GetResourceType() const
{
// TODO
return ZResourceType::Error;
}
size_t Struct_800A57C0::GetRawDataSize() const
{
return 0x0A;
}
/* Struct_800A598C_2 */
Struct_800A598C_2::Struct_800A598C_2(ZFile* nParent) : ZResource(nParent)
{
}
void Struct_800A598C_2::ParseRawData()
{
const auto& rawData = parent->GetRawData();
unk_0 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x00);
x = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x02);
y = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x04);
z = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x06);
unk_8 = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x08);
}
std::string Struct_800A598C_2::GetBodySourceCode() const
{
return StringHelper::Sprintf("0x%02X, %i, %i, %i, 0x%02X", unk_0, x, y, z, unk_8);
}
std::string Struct_800A598C_2::GetSourceTypeName() const
{
return "Struct_800A598C_2";
}
ZResourceType Struct_800A598C_2::GetResourceType() const
{
// TODO
return ZResourceType::Error;
}
size_t Struct_800A598C_2::GetRawDataSize() const
{
return 0x0A;
}
/* Struct_800A598C */
Struct_800A598C::Struct_800A598C(ZFile* nParent) : ZResource(nParent)
{
}
void Struct_800A598C::ParseRawData()
{
const auto& rawData = parent->GetRawData();
unk_0 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x00);
unk_2 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x02);
unk_4 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x04);
unk_8 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x08);
unk_C = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x0C);
if (unk_8 != 0 && GETSEGNUM(unk_8) == parent->segment)
{
uint32_t unk_8_Offset = Seg2Filespace(unk_8, parent->baseAddress);
unk_8_arr.reserve(unk_0);
for (size_t i = 0; i < unk_0; i++)
{
Struct_800A57C0 unk8_data(parent);
unk8_data.ExtractFromFile(unk_8_Offset);
unk_8_arr.push_back(unk8_data);
unk_8_Offset += unk8_data.GetRawDataSize();
}
}
if (unk_C != 0 && GETSEGNUM(unk_8) == parent->segment)
{
uint32_t unk_C_Offset = Seg2Filespace(unk_C, parent->baseAddress);
unk_C_arr.reserve(unk_2);
for (size_t i = 0; i < unk_2; i++)
{
Struct_800A598C_2 unkC_data(parent);
unkC_data.ExtractFromFile(unk_C_Offset);
unk_C_arr.push_back(unkC_data);
unk_C_Offset += unkC_data.GetRawDataSize();
}
}
}
void Struct_800A598C::DeclareReferences(const std::string& prefix)
{
std::string varPrefix = prefix;
if (name != "")
varPrefix = name;
if (unk_8 != 0 && GETSEGNUM(unk_8) == parent->segment)
{
const auto& res = unk_8_arr.at(0);
std::string unk_8_Str = res.GetDefaultName(varPrefix);
size_t arrayItemCnt = unk_8_arr.size();
std::string entryStr = "";
for (size_t i = 0; i < arrayItemCnt; i++)
{
auto& child = unk_8_arr[i];
child.DeclareReferences(varPrefix);
entryStr += StringHelper::Sprintf("\t{ %s },", child.GetBodySourceCode().c_str());
if (i < arrayItemCnt - 1)
entryStr += "\n";
}
uint32_t unk_8_Offset = Seg2Filespace(unk_8, parent->baseAddress);
Declaration* decl = parent->GetDeclaration(unk_8_Offset);
if (decl == nullptr)
{
parent->AddDeclarationArray(unk_8_Offset, res.GetDeclarationAlignment(),
arrayItemCnt * res.GetRawDataSize(),
res.GetSourceTypeName(), unk_8_Str, arrayItemCnt, entryStr);
}
else
decl->text = entryStr;
}
if (unk_C != 0 && GETSEGNUM(unk_C) == parent->segment)
{
const auto& res = unk_C_arr.at(0);
std::string unk_C_Str = res.GetDefaultName(varPrefix);
size_t arrayItemCnt = unk_C_arr.size();
std::string entryStr = "";
for (size_t i = 0; i < arrayItemCnt; i++)
{
auto& child = unk_C_arr[i];
child.DeclareReferences(varPrefix);
entryStr += StringHelper::Sprintf("\t{ %s },", child.GetBodySourceCode().c_str());
if (i < arrayItemCnt - 1)
entryStr += "\n";
}
uint32_t unk_C_Offset = Seg2Filespace(unk_C, parent->baseAddress);
Declaration* decl = parent->GetDeclaration(unk_C_Offset);
if (decl == nullptr)
{
parent->AddDeclarationArray(unk_C_Offset, res.GetDeclarationAlignment(),
arrayItemCnt * res.GetRawDataSize(),
res.GetSourceTypeName(), unk_C_Str, arrayItemCnt, entryStr);
}
else
decl->text = entryStr;
}
}
std::string Struct_800A598C::GetBodySourceCode() const
{
std::string unk_8_Str;
std::string unk_C_Str;
Globals::Instance->GetSegmentedPtrName(unk_8, parent, "Struct_800A57C0", unk_8_Str,
parent->workerID);
Globals::Instance->GetSegmentedPtrName(unk_C, parent, "Struct_800A598C_2", unk_C_Str,
parent->workerID);
std::string entryStr = StringHelper::Sprintf("\n\t\tARRAY_COUNTU(%s), ARRAY_COUNTU(%s),\n",
unk_8_Str.c_str(), unk_C_Str.c_str());
entryStr +=
StringHelper::Sprintf("\t\t%i, %s, %s\n\t", unk_4, unk_8_Str.c_str(), unk_C_Str.c_str());
return entryStr;
}
std::string Struct_800A598C::GetSourceTypeName() const
{
return "Struct_800A598C";
}
ZResourceType Struct_800A598C::GetResourceType() const
{
// TODO
return ZResourceType::Error;
}
size_t Struct_800A598C::GetRawDataSize() const
{
return 0x10;
}
/* Struct_800A5E28 */
Struct_800A5E28::Struct_800A5E28(ZFile* nParent) : ZResource(nParent)
{
}
void Struct_800A5E28::ParseRawData()
{
const auto& rawData = parent->GetRawData();
unk_0 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x00);
unk_2 = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x02);
unk_4 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x04);
unk_8 = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x08);
if (unk_4 != 0 && GETSEGNUM(unk_4) == parent->segment)
{
uint32_t unk_4_Offset = Seg2Filespace(unk_4, parent->baseAddress);
unk_4_arr.reserve(unk_2);
for (size_t i = 0; i < unk_2; i++)
{
Struct_800A598C unk_4_data(parent);
unk_4_data.ExtractFromFile(unk_4_Offset);
unk_4_arr.push_back(unk_4_data);
unk_4_Offset += unk_4_data.GetRawDataSize();
}
}
}
void Struct_800A5E28::DeclareReferences(const std::string& prefix)
{
std::string varPrefix = prefix;
if (name != "")
varPrefix = name;
ZResource::DeclareReferences(varPrefix);
if (unk_4 != SEGMENTED_NULL && GETSEGNUM(unk_4) == parent->segment)
{
const auto& res = unk_4_arr.at(0);
std::string unk_4_Str = res.GetDefaultName(varPrefix);
size_t arrayItemCnt = unk_4_arr.size();
std::string entryStr = "";
for (size_t i = 0; i < arrayItemCnt; i++)
{
auto& child = unk_4_arr[i];
child.DeclareReferences(varPrefix);
entryStr += StringHelper::Sprintf("\t{ %s },", child.GetBodySourceCode().c_str());
if (i < arrayItemCnt - 1)
entryStr += "\n";
}
uint32_t unk_4_Offset = Seg2Filespace(unk_4, parent->baseAddress);
Declaration* decl = parent->GetDeclaration(unk_4_Offset);
if (decl == nullptr)
{
parent->AddDeclarationArray(unk_4_Offset, res.GetDeclarationAlignment(),
arrayItemCnt * res.GetRawDataSize(),
res.GetSourceTypeName(), unk_4_Str, arrayItemCnt, entryStr);
}
else
decl->text = entryStr;
}
if (unk_8 != SEGMENTED_NULL && GETSEGNUM(unk_8) == parent->segment)
{
uint32_t unk_8_Offset = Seg2Filespace(unk_8, parent->baseAddress);
int32_t dlistLength = ZDisplayList::GetDListLength(
parent->GetRawData(), unk_8_Offset,
Globals::Instance->game == ZGame::OOT_SW97 ? DListType::F3DEX : DListType::F3DZEX);
unk_8_dlist = new ZDisplayList(parent);
unk_8_dlist->ExtractFromBinary(unk_8_Offset, dlistLength);
std::string dListStr =
StringHelper::Sprintf("%sSkinLimbDL_%06X", varPrefix.c_str(), unk_8_Offset);
unk_8_dlist->SetName(dListStr);
unk_8_dlist->DeclareVar(varPrefix, "");
unk_8_dlist->DeclareReferences(varPrefix);
parent->AddResource(unk_8_dlist);
}
}
std::string Struct_800A5E28::GetBodySourceCode() const
{
std::string unk_4_Str;
std::string unk_8_Str;
Globals::Instance->GetSegmentedPtrName(unk_4, parent, "Struct_800A598C", unk_4_Str,
parent->workerID);
Globals::Instance->GetSegmentedPtrName(unk_8, parent, "Gfx", unk_8_Str, parent->workerID);
std::string entryStr = "\n";
entryStr += StringHelper::Sprintf("\t%i, ARRAY_COUNTU(%s),\n", unk_0, unk_4_Str.c_str());
entryStr += StringHelper::Sprintf("\t%s, %s\n", unk_4_Str.c_str(), unk_8_Str.c_str());
return entryStr;
}
std::string Struct_800A5E28::GetSourceTypeName() const
{
return "Struct_800A5E28";
}
ZResourceType Struct_800A5E28::GetResourceType() const
{
// TODO
return ZResourceType::Error;
}
size_t Struct_800A5E28::GetRawDataSize() const
{
return 0x0C;
}

View File

@@ -0,0 +1,114 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "ZResource.h"
#include "ZDisplayList.h"
// TODO: check if more types exists
enum class ZLimbSkinType
{
SkinType_0, // Segment = 0
SkinType_4 = 4, // Segment = segmented address // Struct_800A5E28
SkinType_5 = 5, // Segment = 0
SkinType_DList = 11, // Segment = DList address
};
class Struct_800A57C0 : public ZResource
{
public:
Struct_800A57C0(ZFile* nParent);
void ParseRawData() override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
public:
uint16_t unk_0;
int16_t unk_2;
int16_t unk_4;
int8_t unk_6;
int8_t unk_7;
int8_t unk_8;
uint8_t unk_9;
};
class Struct_800A598C_2 : public ZResource
{
public:
Struct_800A598C_2(ZFile* nParent);
void ParseRawData() override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
public:
uint8_t unk_0;
int16_t x;
int16_t y;
int16_t z;
uint8_t unk_8;
};
class Struct_800A598C : public ZResource
{
public:
Struct_800A598C(ZFile* nParent);
void ParseRawData() override;
void DeclareReferences(const std::string& prefix) override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
public:
uint16_t unk_0; // Length of unk_8
uint16_t unk_2; // Length of unk_C
uint16_t unk_4; // 0 or 1 // Used as an index for unk_C
segptr_t unk_8; // Struct_800A57C0*
segptr_t unk_C; // Struct_800A598C_2*
std::vector<Struct_800A57C0> unk_8_arr;
std::vector<Struct_800A598C_2> unk_C_arr;
};
class Struct_800A5E28 : public ZResource
{
public:
Struct_800A5E28(ZFile* nParent);
void ParseRawData() override;
void DeclareReferences(const std::string& prefix) override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
public:
uint16_t unk_0; // Vtx count
uint16_t unk_2; // Length of unk_4
segptr_t unk_4; // Struct_800A598C*
segptr_t unk_8; // Gfx*
std::vector<Struct_800A598C> unk_4_arr;
ZDisplayList* unk_8_dlist = nullptr;
};

View File

@@ -0,0 +1,123 @@
#include "OutputFormatter.h"
#include <Globals.h>
void OutputFormatter::Flush()
{
//if (!Globals::Instance->otrMode) // OTRTODO: MULTITHREADING
{
if (col > lineLimit && !Globals::Instance->otrMode)
{
str.append(1, '\n');
str.append(currentIndent, ' ');
uint32_t newCol = currentIndent + (wordP - word);
for (uint32_t i = 0; i < wordNests; i++)
nestIndent[nest - i] -= col - newCol;
col = newCol;
}
else
{
str.append(space, spaceP - space);
}
spaceP = space;
str.append(word, wordP - word);
wordP = word;
wordNests = 0;
}
}
int OutputFormatter::Write(const char* buf, int count)
{
// OTRTODO
//if (!Globals::Instance->singleThreaded)
//return 0;
for (int i = 0; i < count; i++)
{
char c = buf[i];
if (c == ' ' || c == '\t' || c == '\n')
{
if (wordP - word != 0)
{
Flush();
}
if (c == '\n')
{
col = 0;
*spaceP++ = c;
}
else if (c == '\t')
{
int n = tabSize - (col % tabSize);
col += n;
for (int j = 0; j < n; j++)
*spaceP++ = ' ';
}
else
{
col++;
*spaceP++ = c;
}
currentIndent = nestIndent[nest];
}
else
{
col++;
if (c == '(')
{
nest++;
nestIndent[nest] = col;
wordNests++;
}
else if (c == ')')
{
if (nest > 0)
nest--;
if (wordNests > 0)
wordNests--;
}
*wordP++ = c;
}
}
return count;
}
int OutputFormatter::Write(const std::string& buf)
{
return Write(buf.data(), buf.size());
}
thread_local OutputFormatter* OutputFormatter::Instance;
int OutputFormatter::WriteStatic(const char* buf, int count)
{
return Instance->Write(buf, count);
}
int (*OutputFormatter::StaticWriter())(const char* buf, int count)
{
Instance = this;
return &WriteStatic;
}
OutputFormatter::OutputFormatter(uint32_t tabSize, uint32_t indentation, uint32_t lineLimit)
: tabSize{tabSize}, lineLimit{lineLimit}, col{0}, nest{0}, nestIndent{indentation},
currentIndent{indentation}, wordNests(0), wordP{word}, spaceP{space}
{
}
std::string OutputFormatter::GetOutput()
{
Flush();
return std::move(str);
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include <map>
#include <string>
#include <vector>
#include <cstdint>
class OutputFormatter
{
private:
const uint32_t tabSize;
const uint32_t lineLimit;
uint32_t col;
uint32_t nest;
uint32_t nestIndent[8];
uint32_t currentIndent;
uint32_t wordNests;
char word[128];
char space[128];
char* wordP;
char* spaceP;
std::string str;
void Flush();
static thread_local OutputFormatter* Instance;
static int WriteStatic(const char* buf, int count);
public:
OutputFormatter(uint32_t tabSize = 4, uint32_t indentation = 4, uint32_t lineLimit = 120);
int (*StaticWriter())(const char* buf, int count); // Must be `int` due to libgfxd
int Write(const char* buf, int count);
int Write(const std::string& buf);
std::string GetOutput();
};

View File

@@ -0,0 +1,354 @@
#if 0
#include "ZOverlay.h"
#include <cassert>
#include <unordered_set>
#include "Globals.h"
#include "Utils/Directory.h"
#include <Utils/DiskFile.h>
#include "Utils/Path.h"
#include "Utils/StringHelper.h"
#include "WarningHandler.h"
using namespace ELFIO;
const char* RelocationEntry::GetSectionName() const
{
switch (sectionType)
{
case SectionType::Text:
return ".text";
case SectionType::Data:
return ".data";
case SectionType::RoData:
return ".rodata";
case SectionType::Bss:
return ".bss";
case SectionType::ERROR:
return ".ERROR";
}
assert(!"Oh no :c");
}
const char* RelocationEntry::GetRelocTypeName() const
{
switch (relocationType)
{
case RelocationType::R_MIPS_32:
return "R_MIPS_32";
case RelocationType::R_MIPS_26:
return "R_MIPS_26";
case RelocationType::R_MIPS_HI16:
return "R_MIPS_HI16";
case RelocationType::R_MIPS_LO16:
return "R_MIPS_LO16";
}
assert(!"Oh no :c");
}
ZOverlay::ZOverlay()
{
name = "";
entries = std::vector<RelocationEntry*>();
}
ZOverlay::ZOverlay(const std::string& nName) : ZOverlay()
{
name = nName;
}
ZOverlay::~ZOverlay()
{
for (auto entry : entries)
if (entry)
delete entry;
entries.clear();
}
static const std::unordered_set<std::string> sRelSections = {
".rel.text",
".rel.data",
".rel.rodata",
};
static const std::unordered_set<std::string> sSections = {
".text", ".data", ".symtab", ".rodata", ".rodata.str1.4", ".rodata.cst4", ".rodata.cst8",
};
ZOverlay* ZOverlay::FromBuild(fs::path buildPath, fs::path cfgFolderPath)
{
std::string cfgText = DiskFile::ReadAllText(cfgFolderPath / "overlay.cfg");
std::vector<std::string> cfgLines = StringHelper::Split(cfgText, "\n");
ZOverlay* ovl = new ZOverlay(StringHelper::Strip(cfgLines[0], "\r"));
ovl->cfgLines = cfgLines;
int32_t sectionOffs[5] = {0};
std::vector<RelocationEntry*> textRelocs;
std::vector<RelocationEntry*> dataRelocs;
std::vector<RelocationEntry*> rodataRelocs;
// get the elf files
std::vector<elfio*> readers;
for (size_t i = 1; i < cfgLines.size(); i++)
{
std::string elfPath =
(buildPath / (cfgLines[i].substr(0, cfgLines[i].size() - 2) + ".o")).string();
elfio* reader = new elfio();
if (!reader->load(elfPath))
{
// not all files were compiled
for (auto r : readers)
delete r;
readers.clear();
delete ovl;
return nullptr;
}
readers.push_back(reader);
}
for (size_t curReaderId = 0; curReaderId < readers.size(); curReaderId++)
{
auto& curReader = readers[curReaderId];
Elf_Half sec_num = curReader->sections.size();
for (int32_t i = 0; i < sec_num; i++)
{
section* pSec = curReader->sections[i];
if (pSec->get_type() != SHT_REL ||
sRelSections.find(pSec->get_name()) == sRelSections.end())
{
continue;
}
symbol_section_accessor currentSymbols(*curReader,
curReader->sections[(Elf_Half)pSec->get_link()]);
SectionType sectionType = GetSectionTypeFromStr(pSec->get_name());
if (sectionType == SectionType::ERROR)
{
HANDLE_WARNING(WarningType::Always, "one of the section types returned ERROR", "");
}
relocation_section_accessor relocs(*curReader, pSec);
for (Elf_Xword j = 0; j < relocs.get_entries_num(); j++)
{
Elf64_Addr offset = 0;
Elf_Word symbol = 0;
Elf_Word type = 0;
{
Elf_Sxword addend = 0;
relocs.get_entry(j, offset, symbol, type, addend);
}
std::string curSymName;
Elf_Half curSymShndx = SHN_UNDEF;
{
Elf64_Addr value;
Elf_Xword size;
unsigned char bind;
unsigned char type;
unsigned char other;
currentSymbols.get_symbol(symbol, curSymName, value, size, bind, type,
curSymShndx, other);
}
// check symbols outside the elf but within the overlay
if (curSymShndx == SHN_UNDEF)
{
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
{
printf("Symbol '%s' doesn't exist in current .o file (%s). Searching...\n",
curSymName.c_str(), cfgLines[curReaderId + 1].c_str());
}
for (size_t readerId = 0; readerId < readers.size(); readerId++)
{
auto& reader = readers[readerId];
if (curSymShndx != SHN_UNDEF)
break;
if (reader == curReader)
continue;
auto sectionData = reader->sections[(Elf_Half)pSec->get_link()];
curSymShndx =
ovl->FindSymbolInSection(curSymName, sectionData, *reader, readerId);
if (curSymShndx != SHN_UNDEF)
break;
if (Globals::Instance->gccCompat)
{
// Symbol wasn't found, try checking every section
Elf_Half sec_num = reader->sections.size();
for (int32_t otherSectionIdx = 0; otherSectionIdx < sec_num;
otherSectionIdx++)
{
if (curSymShndx != SHN_UNDEF)
{
break;
}
auto sectionDataIter = reader->sections[otherSectionIdx];
curSymShndx = ovl->FindSymbolInSection(curSymName, sectionDataIter,
*reader, readerId);
}
}
}
}
if (curSymShndx != SHN_UNDEF)
{
RelocationType typeConverted = (RelocationType)type;
offset += sectionOffs[static_cast<size_t>(sectionType)];
RelocationEntry* reloc =
new RelocationEntry(sectionType, typeConverted, offset);
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
{
printf(".word 0x%08X # %s %s 0x%04X\n", reloc->CalcRelocationWord(),
reloc->GetSectionName(), reloc->GetRelocTypeName(), reloc->offset);
}
// this is to keep the correct reloc entry order
if (sectionType == SectionType::Text)
textRelocs.push_back(reloc);
if (sectionType == SectionType::Data)
dataRelocs.push_back(reloc);
if (sectionType == SectionType::RoData)
rodataRelocs.push_back(reloc);
}
}
}
// increase section offsets
for (int32_t i = 0; i < sec_num; i++)
{
section* pSec = curReader->sections[i];
if (pSec->get_type() == SHT_PROGBITS &&
sSections.find(pSec->get_name()) != sSections.end())
{
SectionType sectionType = GetSectionTypeFromStr(pSec->get_name());
sectionOffs[static_cast<size_t>(sectionType)] += pSec->get_size();
}
}
}
ovl->entries.reserve(textRelocs.size() + dataRelocs.size() + rodataRelocs.size());
ovl->entries.insert(ovl->entries.end(), textRelocs.begin(), textRelocs.end());
ovl->entries.insert(ovl->entries.end(), dataRelocs.begin(), dataRelocs.end());
ovl->entries.insert(ovl->entries.end(), rodataRelocs.begin(), rodataRelocs.end());
for (auto r : readers)
delete r;
readers.clear();
return ovl;
}
std::string ZOverlay::GetSourceOutputCode([[maybe_unused]] const std::string& prefix)
{
std::string output;
output += ".section .ovl\n";
output += StringHelper::Sprintf("# %sOverlayInfo\n", name.c_str());
output += StringHelper::Sprintf(".word _%sSegmentTextSize\n", name.c_str());
output += StringHelper::Sprintf(".word _%sSegmentDataSize\n", name.c_str());
output += StringHelper::Sprintf(".word _%sSegmentRoDataSize\n", name.c_str());
output += StringHelper::Sprintf(".word _%sSegmentBssSize\n", name.c_str());
output += "\n";
output += StringHelper::Sprintf(".word %i # reloc_count\n", entries.size());
for (size_t i = 0; i < entries.size(); i++)
{
RelocationEntry* reloc = entries[i];
output += StringHelper::Sprintf(".word 0x%08X # %s %s 0x%04X\n",
reloc->CalcRelocationWord(), reloc->GetSectionName(),
reloc->GetRelocTypeName(), reloc->offset);
}
size_t offset = (entries.size() * 4) + 20;
while (offset % 16 != 12)
{
output += ".word 0\n";
offset += 4;
}
output += "\n";
output +=
StringHelper::Sprintf(".word 0x%08X # %sOverlayInfoOffset\n", offset + 4, name.c_str());
return output;
}
SectionType ZOverlay::GetSectionTypeFromStr(const std::string& sectionName)
{
if (sectionName == ".rel.text" || sectionName == ".text")
return SectionType::Text;
else if (sectionName == ".rel.data" || sectionName == ".data")
return SectionType::Data;
else if (sectionName == ".rel.rodata" || sectionName == ".rodata" ||
sectionName == ".rodata.str1.4" || sectionName == ".rodata.cst4")
return SectionType::RoData;
else if (sectionName == ".rel.bss" || sectionName == ".bss")
return SectionType::Bss;
return SectionType::ERROR;
}
ELFIO::Elf_Half ZOverlay::FindSymbolInSection(const std::string& curSymName,
ELFIO::section* sectionData, ELFIO::elfio& reader,
size_t readerId)
{
if (sectionData == nullptr)
return SHN_UNDEF;
auto sectionDataName = sectionData->get_name();
if (sSections.find(sectionDataName) == sSections.end())
return SHN_UNDEF;
#ifdef DEVELOPMENT
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
{
printf("\t File '%s' section: %s \n", cfgLines[readerId + 1].c_str(),
sectionDataName.c_str());
}
#endif
symbol_section_accessor symbols(reader, sectionData);
Elf_Xword symbolNum = symbols.get_symbols_num();
for (Elf_Xword symIdx = 0; symIdx < symbolNum; symIdx++)
{
Elf_Half shndx = SHN_UNDEF;
Elf64_Addr value;
std::string name;
Elf_Xword size;
unsigned char bind;
unsigned char type;
unsigned char other;
symbols.get_symbol(symIdx, name, value, size, bind, type, shndx, other);
if (name == curSymName)
{
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
{
printf("\t Symbol '%s' found in '%s' '%s' \n", curSymName.c_str(),
cfgLines[readerId + 1].c_str(), sectionDataName.c_str());
}
return shndx;
}
}
return SHN_UNDEF;
}
#endif

View File

@@ -0,0 +1,78 @@
#pragma once
#if 0
#include "Utils/Directory.h"
#include "ZResource.h"
#include "elfio/elfio.hpp"
#include "tinyxml2.h"
enum class SectionType
{
Text = 1,
Data = 2,
RoData = 3,
Bss = 4,
ERROR = 255
};
enum class RelocationType
{
R_MIPS_32 = 2,
R_MIPS_26 = 4,
R_MIPS_HI16 = 5,
R_MIPS_LO16 = 6,
};
class RelocationEntry
{
public:
SectionType sectionType;
RelocationType relocationType;
int32_t offset;
RelocationEntry(SectionType nSecType, RelocationType nRelType, int32_t nOffset)
{
sectionType = nSecType;
relocationType = nRelType;
offset = nOffset;
}
uint32_t CalcRelocationWord()
{
uint32_t relocationWord = 0;
relocationWord |= static_cast<uint32_t>(sectionType) << 30;
relocationWord |= static_cast<uint32_t>(relocationType) << 24;
relocationWord |= offset;
return relocationWord;
}
const char* GetSectionName() const;
const char* GetRelocTypeName() const;
};
class ZOverlay
{
public:
std::string name;
ZOverlay(const std::string& nName);
~ZOverlay();
static ZOverlay* FromBuild(fs::path buildPath, fs::path cfgFolderPath);
std::string GetSourceOutputCode(const std::string& prefix);
private:
std::vector<RelocationEntry*> entries;
std::vector<std::string> cfgLines;
ZOverlay();
static SectionType GetSectionTypeFromStr(const std::string& sectionName);
// static std::string GetOverlayNameFromElf(ELFIO::elfio& reader);
ELFIO::Elf_Half FindSymbolInSection(const std::string& curSymName, ELFIO::section* sectionData,
ELFIO::elfio& reader, size_t readerId);
};
#endif

View File

@@ -0,0 +1,178 @@
#include "BinaryReader.h"
#include <cmath>
#include <stdexcept>
#include "Stream.h"
BinaryReader::BinaryReader(Stream* nStream)
{
stream.reset(nStream);
}
BinaryReader::BinaryReader(std::shared_ptr<Stream> nStream)
{
stream = nStream;
}
void BinaryReader::Close()
{
stream->Close();
}
void BinaryReader::SetEndianness(Endianness endianness)
{
this->endianness = endianness;
}
Endianness BinaryReader::GetEndianness() const
{
return endianness;
}
void BinaryReader::Seek(uint32_t offset, SeekOffsetType seekType)
{
stream->Seek(offset, seekType);
}
uint32_t BinaryReader::GetBaseAddress()
{
return stream->GetBaseAddress();
}
void BinaryReader::Read(int32_t length)
{
stream->Read(length);
}
void BinaryReader::Read(char* buffer, int32_t length)
{
stream->Read(buffer, length);
}
char BinaryReader::ReadChar()
{
return (char)stream->ReadByte();
}
int8_t BinaryReader::ReadByte()
{
return stream->ReadByte();
}
uint8_t BinaryReader::ReadUByte()
{
return (uint8_t)stream->ReadByte();
}
int16_t BinaryReader::ReadInt16()
{
int16_t result = 0;
stream->Read((char*)&result, sizeof(int16_t));
if (endianness != Endianness::Native)
result = BSWAP16(result);
return result;
}
int32_t BinaryReader::ReadInt32()
{
int32_t result = 0;
stream->Read((char*)&result, sizeof(int32_t));
if (endianness != Endianness::Native)
result = BSWAP32(result);
return result;
}
uint16_t BinaryReader::ReadUInt16()
{
uint16_t result = 0;
stream->Read((char*)&result, sizeof(uint16_t));
if (endianness != Endianness::Native)
result = BSWAP16(result);
return result;
}
uint32_t BinaryReader::ReadUInt32()
{
uint32_t result = 0;
stream->Read((char*)&result, sizeof(uint32_t));
if (endianness != Endianness::Native)
result = BSWAP32(result);
return result;
}
uint64_t BinaryReader::ReadUInt64()
{
uint64_t result = 0;
stream->Read((char*)&result, sizeof(uint64_t));
if (endianness != Endianness::Native)
result = BSWAP64(result);
return result;
}
float BinaryReader::ReadSingle()
{
float result = NAN;
stream->Read((char*)&result, sizeof(float));
if (endianness != Endianness::Native)
{
float tmp;
char* dst = (char*)&tmp;
char* src = (char*)&result;
dst[3] = src[0]; dst[2] = src[1]; dst[1] = src[2]; dst[0] = src[3];
result = tmp;
}
if (std::isnan(result))
throw std::runtime_error("BinaryReader::ReadSingle(): Error reading stream");
return result;
}
double BinaryReader::ReadDouble()
{
double result = NAN;
stream->Read((char*)&result, sizeof(double));
if (endianness != Endianness::Native)
{
double tmp;
char* dst = (char*)&tmp;
char* src = (char*)&result;
dst[7] = src[0]; dst[6] = src[1]; dst[5] = src[2]; dst[4] = src[3];
dst[3] = src[4]; dst[2] = src[5]; dst[1] = src[6]; dst[0] = src[7];
result = tmp;
}
if (std::isnan(result))
throw std::runtime_error("BinaryReader::ReadDouble(): Error reading stream");
return result;
}
std::string BinaryReader::ReadString()
{
std::string res;
int numChars = ReadInt32();
for (int i = 0; i < numChars; i++)
res += ReadChar();
return res;
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include <array>
#include <memory>
#include <string>
#include <vector>
#include "BitConverter.h"
#include "Stream.h"
class BinaryReader
{
public:
BinaryReader(Stream* nStream);
BinaryReader(std::shared_ptr<Stream> nStream);
void Close();
void SetEndianness(Endianness endianness);
Endianness GetEndianness() const;
void Seek(uint32_t offset, SeekOffsetType seekType);
uint32_t GetBaseAddress();
void Read(int32_t length);
void Read(char* buffer, int32_t length);
char ReadChar();
int8_t ReadByte();
int16_t ReadInt16();
int32_t ReadInt32();
uint8_t ReadUByte();
uint16_t ReadUInt16();
uint32_t ReadUInt32();
uint64_t ReadUInt64();
float ReadSingle();
double ReadDouble();
std::string ReadString();
protected:
std::shared_ptr<Stream> stream;
Endianness endianness = Endianness::Native;
};

View File

@@ -0,0 +1,148 @@
#include "BinaryWriter.h"
BinaryWriter::BinaryWriter(Stream* nStream)
{
stream.reset(nStream);
}
BinaryWriter::BinaryWriter(std::shared_ptr<Stream> nStream)
{
stream = nStream;
}
void BinaryWriter::SetEndianness(Endianness endianness)
{
this->endianness = endianness;
}
void BinaryWriter::Close()
{
stream->Close();
}
std::shared_ptr<Stream> BinaryWriter::GetStream()
{
return stream;
}
uint64_t BinaryWriter::GetBaseAddress()
{
return stream->GetBaseAddress();
}
uint64_t BinaryWriter::GetLength()
{
return stream->GetLength();
}
void BinaryWriter::Seek(int32_t offset, SeekOffsetType seekType)
{
stream->Seek(offset, seekType);
}
void BinaryWriter::Write(int8_t value)
{
stream->Write((char*)&value, sizeof(int8_t));
}
void BinaryWriter::Write(uint8_t value)
{
stream->Write((char*)&value, sizeof(uint8_t));
}
void BinaryWriter::Write(int16_t value)
{
if (endianness != Endianness::Native)
value = BSWAP16(value);
stream->Write((char*)&value, sizeof(int16_t));
}
void BinaryWriter::Write(uint16_t value)
{
if (endianness != Endianness::Native)
value = BSWAP16(value);
stream->Write((char*)&value, sizeof(uint16_t));
}
void BinaryWriter::Write(int32_t value)
{
if (endianness != Endianness::Native)
value = BSWAP32(value);
stream->Write((char*)&value, sizeof(int32_t));
}
void BinaryWriter::Write(int32_t valueA, int32_t valueB)
{
Write(valueA);
Write(valueB);
}
void BinaryWriter::Write(uint32_t value)
{
if (endianness != Endianness::Native)
value = BSWAP32(value);
stream->Write((char*)&value, sizeof(uint32_t));
}
void BinaryWriter::Write(int64_t value)
{
if (endianness != Endianness::Native)
value = BSWAP64(value);
stream->Write((char*)&value, sizeof(int64_t));
}
void BinaryWriter::Write(uint64_t value)
{
if (endianness != Endianness::Native)
value = BSWAP64(value);
stream->Write((char*)&value, sizeof(uint64_t));
}
void BinaryWriter::Write(float value)
{
if (endianness != Endianness::Native)
{
float tmp;
char* dst = (char*)&tmp;
char* src = (char*)&value;
dst[3] = src[0]; dst[2] = src[1]; dst[1] = src[2]; dst[0] = src[3];
value = tmp;
}
stream->Write((char*)&value, sizeof(float));
}
void BinaryWriter::Write(double value)
{
if (endianness != Endianness::Native)
{
double tmp;
char* dst = (char*)&tmp;
char* src = (char*)&value;
dst[7] = src[0]; dst[6] = src[1]; dst[5] = src[2]; dst[4] = src[3];
dst[3] = src[4]; dst[2] = src[5]; dst[1] = src[6]; dst[0] = src[7];
value = tmp;
}
stream->Write((char*)&value, sizeof(double));
}
void BinaryWriter::Write(const std::string& str)
{
int strLen = str.size();
Write(strLen);
for (char c : str)
stream->WriteByte(c);
}
void BinaryWriter::Write(char* srcBuffer, size_t length)
{
stream->Write(srcBuffer, length);
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include <array>
#include <memory>
#include <string>
#include <vector>
#include "BitConverter.h"
#include "Stream.h"
class BinaryWriter
{
public:
BinaryWriter(Stream* nStream);
BinaryWriter(std::shared_ptr<Stream> nStream);
void SetEndianness(Endianness endianness);
std::shared_ptr<Stream> GetStream();
uint64_t GetBaseAddress();
uint64_t GetLength();
void Seek(int32_t offset, SeekOffsetType seekType);
void Close();
void Write(int8_t value);
void Write(uint8_t value);
void Write(int16_t value);
void Write(uint16_t value);
void Write(int32_t value);
void Write(int32_t valueA, int32_t valueB);
void Write(uint32_t value);
void Write(int64_t value);
void Write(uint64_t value);
void Write(float value);
void Write(double value);
void Write(const std::string& str);
void Write(char* srcBuffer, size_t length);
protected:
std::shared_ptr<Stream> stream;
Endianness endianness = Endianness::Native;
};

View File

@@ -0,0 +1,209 @@
#pragma once
#include <cstdint>
#include <limits>
#include <vector>
#include <cstring>
#ifdef _MSC_VER
#define BSWAP16 _byteswap_ushort
#define BSWAP32 _byteswap_ulong
#define BSWAP64 _byteswap_uint64
#else
#define BSWAP16 __builtin_bswap16
#define BSWAP32 __builtin_bswap32
#define BSWAP64 __builtin_bswap64
#endif
enum class Endianness
{
Little = 0,
Big = 1,
#if (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) || defined(__BIG_ENDIAN__)
Native = Big,
#else
Native = Little,
#endif
};
class BitConverter
{
public:
static inline int8_t ToInt8BE(const uint8_t* data, int32_t offset)
{
return (uint8_t)data[offset + 0];
}
static inline int8_t ToInt8BE(const std::vector<uint8_t>& data, int32_t offset)
{
return (uint8_t)data[offset + 0];
}
static inline uint8_t ToUInt8BE(const uint8_t* data, int32_t offset)
{
return (uint8_t)data[offset + 0];
}
static inline uint8_t ToUInt8BE(const std::vector<uint8_t>& data, int32_t offset)
{
return (uint8_t)data[offset + 0];
}
static inline int16_t ToInt16BE(const uint8_t* data, int32_t offset)
{
return ((uint16_t)data[offset + 0] << 8) + (uint16_t)data[offset + 1];
}
static inline int16_t ToInt16BE(const std::vector<uint8_t>& data, int32_t offset)
{
return ((uint16_t)data[offset + 0] << 8) + (uint16_t)data[offset + 1];
}
static inline uint16_t ToUInt16BE(const uint8_t* data, int32_t offset)
{
return ((uint16_t)data[offset + 0] << 8) + (uint16_t)data[offset + 1];
}
static inline uint16_t ToUInt16BE(const std::vector<uint8_t>& data, int32_t offset)
{
return ((uint16_t)data[offset + 0] << 8) + (uint16_t)data[offset + 1];
}
static inline int32_t ToInt32BE(const uint8_t* data, int32_t offset)
{
return ((uint32_t)data[offset + 0] << 24) + ((uint32_t)data[offset + 1] << 16) +
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
}
static inline int32_t ToInt32BE(const std::vector<uint8_t>& data, int32_t offset)
{
return ((uint32_t)data[offset + 0] << 24) + ((uint32_t)data[offset + 1] << 16) +
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
}
static inline uint32_t ToUInt32BE(const uint8_t* data, int32_t offset)
{
return ((uint32_t)data[offset + 0] << 24) + ((uint32_t)data[offset + 1] << 16) +
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
}
static inline uint32_t ToUInt32BE(const std::vector<uint8_t>& data, int32_t offset)
{
return ((uint32_t)data[offset + 0] << 24) + ((uint32_t)data[offset + 1] << 16) +
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
}
static inline int64_t ToInt64BE(const uint8_t* data, int32_t offset)
{
return ((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
}
static inline int64_t ToInt64BE(const std::vector<uint8_t>& data, int32_t offset)
{
return ((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
}
static inline uint64_t ToUInt64BE(const uint8_t* data, int32_t offset)
{
return ((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
}
static inline uint64_t ToUInt64BE(const std::vector<uint8_t>& data, int32_t offset)
{
return ((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
}
static inline float ToFloatBE(const uint8_t* data, int32_t offset)
{
float value;
uint32_t floatData = ((uint32_t)data[offset + 0] << 24) +
((uint32_t)data[offset + 1] << 16) +
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
static_assert(sizeof(uint32_t) == sizeof(float), "expected 32-bit float");
std::memcpy(&value, &floatData, sizeof(value));
return value;
}
static inline float ToFloatBE(const std::vector<uint8_t>& data, int32_t offset)
{
float value;
uint32_t floatData = ((uint32_t)data[offset + 0] << 24) +
((uint32_t)data[offset + 1] << 16) +
((uint32_t)data[offset + 2] << 8) + (uint32_t)data[offset + 3];
static_assert(sizeof(uint32_t) == sizeof(float), "expected 32-bit float");
std::memcpy(&value, &floatData, sizeof(value));
return value;
}
static inline double ToDoubleBE(const uint8_t* data, int32_t offset)
{
double value;
uint64_t floatData =
((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
static_assert(sizeof(uint64_t) == sizeof(double), "expected 64-bit double");
// Checks if the float format on the platform the ZAPD binary is running on supports the
// same float format as the object file.
static_assert(std::numeric_limits<float>::is_iec559,
"expected IEC559 floats on host machine");
std::memcpy(&value, &floatData, sizeof(value));
return value;
}
static inline double ToDoubleBE(const std::vector<uint8_t>& data, int32_t offset)
{
double value;
uint64_t floatData =
((uint64_t)data[offset + 0] << 56) + ((uint64_t)data[offset + 1] << 48) +
((uint64_t)data[offset + 2] << 40) + ((uint64_t)data[offset + 3] << 32) +
((uint64_t)data[offset + 4] << 24) + ((uint64_t)data[offset + 5] << 16) +
((uint64_t)data[offset + 6] << 8) + ((uint64_t)data[offset + 7]);
static_assert(sizeof(uint64_t) == sizeof(double), "expected 64-bit double");
// Checks if the float format on the platform the ZAPD binary is running on supports the
// same float format as the object file.
static_assert(std::numeric_limits<double>::is_iec559,
"expected IEC559 doubles on host machine");
std::memcpy(&value, &floatData, sizeof(value));
return value;
}
// Rewrites the rom data in-place to be in BigEndian/z64 format
static inline void RomToBigEndian(uint8_t* rom, size_t romSize) {
if (romSize <= 0) {
return;
}
// Use the first byte to determine byte order
uint8_t firstByte = rom[0];
switch (firstByte) {
case 0x37: // v64
for (size_t pos = 0; pos < (romSize / 2); pos++) {
((uint16_t*)rom)[pos] = ToUInt16BE(rom, pos * 2);
}
break;
case 0x40: // n64
for (size_t pos = 0; pos < (romSize / 4); pos++) {
((uint32_t*)rom)[pos] = ToUInt32BE(rom, pos * 4);
}
break;
case 0x80: // z64
break; // Already BE, no need to swap
}
}
};

View File

@@ -0,0 +1,60 @@
#pragma once
#include <string>
#include <vector>
#include "StringHelper.h"
#include <iostream>
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
#undef GetCurrentDirectory
#undef CreateDirectory
class Directory
{
public:
#ifndef PATH_HACK
static std::string GetCurrentDirectory() { return fs::current_path().string(); }
#endif
static bool Exists(const fs::path& path) { return fs::exists(path); }
// Stupid hack because of Windows.h
static void MakeDirectory(const std::string& path)
{
CreateDirectory(path);
}
static void CreateDirectory(const std::string& path)
{
try
{
fs::create_directories(path);
}
catch (...)
{
}
}
static std::vector<std::string> ListFiles(const std::string& dir)
{
std::vector<std::string> lst;
if (Exists(dir))
{
for (auto& p : fs::recursive_directory_iterator(dir))
{
if (!p.is_directory())
lst.push_back(p.path().generic_string());
}
}
return lst;
}
};

View File

@@ -0,0 +1,91 @@
#pragma once
#include <cstdio>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "Path.h"
#include "Utils/StringHelper.h"
#include "Utils/Directory.h"
class DiskFile
{
public:
static bool Exists(const fs::path& filePath)
{
std::ifstream file(filePath, std::ios::in | std::ios::binary | std::ios::ate);
return file.good();
}
static std::vector<uint8_t> ReadAllBytes(const fs::path& filePath)
{
std::ifstream file(filePath, std::ios::in | std::ios::binary | std::ios::ate);
if (!file)
return std::vector<uint8_t>();
int32_t fileSize = (int32_t)file.tellg();
file.seekg(0);
char* data = new char[fileSize];
file.read(data, fileSize);
std::vector<uint8_t> result = std::vector<uint8_t>(data, data + fileSize);
delete[] data;
return result;
};
static std::string ReadAllText(const fs::path& filePath)
{
std::ifstream file(filePath, std::ios::in | std::ios::binary | std::ios::ate);
int32_t fileSize = (int32_t)file.tellg();
file.seekg(0);
char* data = new char[fileSize + 1];
memset(data, 0, fileSize + 1);
file.read(data, fileSize);
std::string str = std::string((const char*)data);
delete[] data;
return str;
};
static std::vector<std::string> ReadAllLines(const fs::path& filePath)
{
std::string text = ReadAllText(filePath);
std::vector<std::string> lines = StringHelper::Split(text, "\n");
return lines;
};
static void WriteAllBytes(const fs::path& filePath, const std::vector<uint8_t>& data)
{
std::ofstream file(filePath, std::ios::binary);
file.write((char*)data.data(), data.size());
};
static void WriteAllBytes(const std::string& filePath, const std::vector<char>& data)
{
if (!Directory::Exists(Path::GetDirectoryName(filePath))) {
Directory::MakeDirectory(Path::GetDirectoryName(filePath).string());
}
std::ofstream file(filePath, std::ios::binary);
file.write((char*)data.data(), data.size());
};
static void WriteAllBytes(const std::string& filePath, const char* data, int dataSize)
{
std::ofstream file(filePath, std::ios::binary);
file.write((char*)data, dataSize);
};
static void WriteAllText(const fs::path& filePath, const std::string& text)
{
if (!Directory::Exists(Path::GetDirectoryName(filePath))) {
Directory::MakeDirectory(Path::GetDirectoryName(filePath).string());
}
std::ofstream file(filePath, std::ios::out);
file.write(text.c_str(), text.size());
}
};

View File

@@ -0,0 +1,97 @@
#include "MemoryStream.h"
#include <cstring>
#ifndef _MSC_VER
#define memcpy_s(dest, destSize, source, sourceSize) memcpy(dest, source, destSize)
#endif
MemoryStream::MemoryStream()
{
buffer = std::vector<char>();
//buffer.reserve(1024 * 16);
bufferSize = 0;
baseAddress = 0;
}
MemoryStream::MemoryStream(char* nBuffer, size_t nBufferSize) : MemoryStream()
{
buffer = std::vector<char>(nBuffer, nBuffer + nBufferSize);
bufferSize = nBufferSize;
baseAddress = 0;
}
MemoryStream::~MemoryStream()
{
}
uint64_t MemoryStream::GetLength()
{
return buffer.size();
}
void MemoryStream::Seek(int32_t offset, SeekOffsetType seekType)
{
if (seekType == SeekOffsetType::Start)
baseAddress = offset;
else if (seekType == SeekOffsetType::Current)
baseAddress += offset;
else if (seekType == SeekOffsetType::End)
baseAddress = bufferSize - 1 - offset;
}
std::unique_ptr<char[]> MemoryStream::Read(size_t length)
{
std::unique_ptr<char[]> result = std::make_unique<char[]>(length);
memcpy_s(result.get(), length, &buffer[baseAddress], length);
baseAddress += length;
return result;
}
void MemoryStream::Read(const char* dest, size_t length)
{
memcpy_s((void*)dest, length, &buffer[baseAddress], length);
baseAddress += length;
}
int8_t MemoryStream::ReadByte()
{
return buffer[baseAddress++];
}
void MemoryStream::Write(char* srcBuffer, size_t length)
{
if (baseAddress + length >= buffer.size())
{
buffer.resize(baseAddress + length);
bufferSize += length;
}
memcpy_s(&buffer[baseAddress], length, srcBuffer, length);
baseAddress += length;
}
void MemoryStream::WriteByte(int8_t value)
{
if (baseAddress >= buffer.size())
{
buffer.resize(baseAddress + 1);
bufferSize = baseAddress;
}
buffer[baseAddress++] = value;
}
std::vector<char> MemoryStream::ToVector()
{
return buffer;
}
void MemoryStream::Flush()
{
}
void MemoryStream::Close()
{
}

View File

@@ -0,0 +1,33 @@
#pragma once
#include <memory>
#include <vector>
#include "Stream.h"
class MemoryStream : public Stream
{
public:
MemoryStream();
MemoryStream(char* nBuffer, size_t nBufferSize);
~MemoryStream();
uint64_t GetLength() override;
void Seek(int32_t offset, SeekOffsetType seekType) override;
std::unique_ptr<char[]> Read(size_t length) override;
void Read(const char* dest, size_t length) override;
int8_t ReadByte() override;
void Write(char* srcBuffer, size_t length) override;
void WriteByte(int8_t value) override;
std::vector<char> ToVector();
void Flush() override;
void Close() override;
protected:
std::vector<char> buffer;
std::size_t bufferSize;
};

50
ZAPDTR/ZAPD/Utils/Path.h Normal file
View File

@@ -0,0 +1,50 @@
#pragma once
#include <iostream>
#include <string>
#include "Utils/StringHelper.h"
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#else
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#endif
class Path
{
public:
static std::string GetFileName(const fs::path& input)
{
// https://en.cppreference.com/w/cpp/filesystem/path/filename
return input.filename().string();
};
static std::string GetFileNameWithoutExtension(const fs::path& input)
{
// https://en.cppreference.com/w/cpp/filesystem/path/stem
return input.stem().string();
};
static std::string GetFileNameExtension(const std::string& input)
{
return input.substr(input.find_last_of("."), input.length());
};
static fs::path GetPath(const std::string& input)
{
std::vector<std::string> split = StringHelper::Split(input, "/");
fs::path output;
for (std::string str : split)
{
if (str.find_last_of(".") == std::string::npos)
output /= str;
}
return output;
};
static fs::path GetDirectoryName(const fs::path& path) { return path.parent_path(); };
};

View File

@@ -0,0 +1,34 @@
#pragma once
#include <cstdint>
#include <memory>
enum class SeekOffsetType
{
Start,
Current,
End
};
class Stream
{
public:
virtual ~Stream() = default;
virtual uint64_t GetLength() = 0;
uint64_t GetBaseAddress() { return baseAddress; }
virtual void Seek(int32_t offset, SeekOffsetType seekType) = 0;
virtual std::unique_ptr<char[]> Read(size_t length) = 0;
virtual void Read(const char* dest, size_t length) = 0;
virtual int8_t ReadByte() = 0;
virtual void Write(char* destBuffer, size_t length) = 0;
virtual void WriteByte(int8_t value) = 0;
virtual void Flush() = 0;
virtual void Close() = 0;
protected:
uint64_t baseAddress;
};

View File

@@ -0,0 +1,191 @@
#include "StringHelper.h"
#if (_MSC_VER)
#pragma optimize("2", on)
#define _CRT_SECURE_NO_WARNINGS
#endif
#ifndef _MSC_VER
#define vsprintf_s vsprintf
#endif
std::vector<std::string> StringHelper::Split(std::string s, const std::string& delimiter)
{
size_t pos_start = 0, pos_end, delim_len = delimiter.length();
std::string token;
std::vector<std::string> res;
while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) {
token = s.substr(pos_start, pos_end - pos_start);
pos_start = pos_end + delim_len;
res.push_back(token);
}
res.push_back(s.substr(pos_start));
return res;
}
std::vector<std::string_view> StringHelper::Split(std::string_view s, const std::string& delimiter)
{
size_t pos_start = 0, pos_end, delim_len = delimiter.length();
std::string_view token;
std::vector<std::string_view> res;
while ((pos_end = s.find(delimiter, pos_start)) != std::string_view::npos)
{
token = s.substr(pos_start, pos_end - pos_start);
pos_start = pos_end + delim_len;
res.push_back(token);
}
res.push_back(s.substr(pos_start));
return res;
}
std::string StringHelper::Strip(std::string s, const std::string& delimiter)
{
size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos)
{
token = s.substr(0, pos);
s.erase(pos, pos + delimiter.length());
}
return s;
}
std::string StringHelper::Replace(std::string str, const std::string& from,
const std::string& to)
{
size_t start_pos = str.find(from);
while (start_pos != std::string::npos)
{
str.replace(start_pos, from.length(), to);
start_pos = str.find(from);
}
return str;
}
void StringHelper::ReplaceOriginal(std::string& str, const std::string& from, const std::string& to)
{
size_t start_pos = str.find(from);
while (start_pos != std::string::npos)
{
str.replace(start_pos, from.length(), to);
start_pos = str.find(from);
}
}
bool StringHelper::StartsWith(const std::string& s, const std::string& input)
{
#if __cplusplus >= 202002L
return s.starts_with(input.c_str());
#else
return s.rfind(input, 0) == 0;
#endif
}
bool StringHelper::Contains(const std::string& s, const std::string& input)
{
return s.find(input) != std::string::npos;
}
bool StringHelper::EndsWith(const std::string& s, const std::string& input)
{
size_t inputLen = strlen(input.c_str());
return s.rfind(input) == (s.size() - inputLen);
}
std::string StringHelper::Sprintf(const char* format, ...)
{
char buffer[32768];
// char buffer[2048];
std::string output;
va_list va;
va_start(va, format);
vsprintf_s(buffer, format, va);
va_end(va);
output = buffer;
return output;
}
std::string StringHelper::Implode(std::vector<std::string>& elements,
const char* const separator)
{
return "";
// return std::accumulate(std::begin(elements), std::end(elements), std::string(),
//[separator](std::string& ss, std::string& s) {
// return ss.empty() ? s : ss + separator + s;
//});
}
int64_t StringHelper::StrToL(const std::string& str, int32_t base)
{
return std::strtoull(str.c_str(), nullptr, base);
}
std::string StringHelper::BoolStr(bool b)
{
return b ? "true" : "false";
}
bool StringHelper::HasOnlyDigits(const std::string& str)
{
return std::all_of(str.begin(), str.end(), ::isdigit);
}
// Validate a hex string based on the c89 standard
// https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html#Integer-Constants
bool StringHelper::IsValidHex(std::string_view str)
{
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;
}
bool StringHelper::IsValidHex(const std::string& str)
{
return IsValidHex(std::string_view(str.c_str()));
}
bool StringHelper::IsValidOffset(std::string_view str)
{
if (str.length() == 1)
{
// 0 is a valid offset
return isdigit(str[0]);
}
return IsValidHex(str);
}
bool StringHelper::IsValidOffset(const std::string& str)
{
if (str.length() == 1)
{
// 0 is a valid offset
return isdigit(str[0]);
}
return IsValidHex(str);
}
bool StringHelper::IEquals(const std::string& a, const std::string& b)
{
return std::equal(a.begin(), a.end(), b.begin(), b.end(),
[](char a, char b) { return tolower(a) == tolower(b); });
}

View File

@@ -0,0 +1,33 @@
#pragma once
#include <algorithm>
#include <cstdarg>
#include <cstring>
#include <numeric>
#include <string>
#include <string_view>
#include <vector>
#include <cstdint>
class StringHelper
{
public:
static std::vector<std::string> Split(std::string s, const std::string& delimiter);
static std::vector<std::string_view> Split(std::string_view s, const std::string& delimiter);
static std::string Strip(std::string s, const std::string& delimiter);
static std::string Replace(std::string str, const std::string& from, const std::string& to);
static void ReplaceOriginal(std::string& str, const std::string& from, const std::string& to);
static bool StartsWith(const std::string& s, const std::string& input);
static bool Contains(const std::string& s, const std::string& input);
static bool EndsWith(const std::string& s, const std::string& input);
static std::string Sprintf(const char* format, ...);
static std::string Implode(std::vector<std::string>& elements, const char* const separator);
static int64_t StrToL(const std::string& str, int32_t base = 10);
static std::string BoolStr(bool b);
static bool HasOnlyDigits(const std::string& str);
static bool IsValidHex(std::string_view str);
static bool IsValidHex(const std::string& str);
static bool IsValidOffset(std::string_view str);
static bool IsValidOffset(const std::string& str);
static bool IEquals(const std::string& a, const std::string& b);
};

45
ZAPDTR/ZAPD/Utils/vt.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef VT_H
#define VT_H
// clang-format off
#define VT_COLOR_BLACK 0
#define VT_COLOR_RED 1
#define VT_COLOR_GREEN 2
#define VT_COLOR_YELLOW 3
#define VT_COLOR_BLUE 4
#define VT_COLOR_PURPLE 5
#define VT_COLOR_CYAN 6
#define VT_COLOR_WHITE 7
#define VT_COLOR_LIGHTGRAY 8
#define VT_COLOR_DARKGRAY 9
#define VT_COLOR_FOREGROUND 3
#define VT_COLOR_BACKGROUND 4
// clang-format on
#define VT_COLOR_EXPAND0(type, color) #type #color
#define VT_COLOR_EXPAND1(type, color) VT_COLOR_EXPAND0(type, color)
#define VT_COLOR(type, color) VT_COLOR_EXPAND1(VT_COLOR_##type, VT_COLOR_##color)
#define VT_ESC "\x1b"
#define VT_CSI "["
#define VT_CUP(x, y) VT_ESC VT_CSI y ";" x "H"
#define VT_ED(n) VT_ESC VT_CSI #n "J"
#define VT_SGR(n) VT_ESC VT_CSI n "m"
// Add more macros if necessary
#define VT_COL(back, fore) VT_SGR(VT_COLOR(BACKGROUND, back) ";" VT_COLOR(FOREGROUND, fore))
#define VT_FGCOL(color) VT_SGR(VT_COLOR(FOREGROUND, color))
#define VT_BGCOL(color) VT_SGR(VT_COLOR(BACKGROUND, color))
// Bold
#define VT_BOLD "1"
// Bold color support
#define VT_BOLD_FGCOL(color) VT_SGR(VT_BOLD ";" VT_COLOR(FOREGROUND, color))
#define VT_BOLD_BGCOL(color) VT_SGR(VT_BOLD ";" VT_COLOR(BACKGROUND, color))
#define VT_RST VT_SGR("")
#define VT_CLS VT_ED(2)
#endif

View File

@@ -0,0 +1,451 @@
/**
* ZAPD Warning- and Error-handling system
* =======================================
*
* This provides a common standard way to write ZAPD warnings/errors, which should be used for all
* such. It will pretty-print them in a uniform way, with styles defined in the header.
*
* Warnings/errors should be constructed using the macros given in the header; there are now plenty
* of examples in the codebase of how to do this. Their purposes are noted above each category in
* the header. Each warning has a type, one of the ones in warningStringToInitMap, or
* WarningType::Always, which is used for warnings that cannot be disabled and do not display a
* type.
*
* Currently there are three levels of alert a warning can have:
* - Off (does not display anything)
* - Warn (print a warning but continue processing)
* - Err (behave like an error, i.e. print and throw an exception to crash ZAPD when occurs)
*
* Flag use:
* - -Wfoo enables warnings of type foo
* - -Wno-foo disables warnings of type foo
* - -Werror=foo escalates foo to behave like an error
* - -Weverything enables all warnings
* - -Werror escalates all enabled warnings to errors
*
* Errors do not have types, and will always throw an exception; they cannot be disabled.
*
* Format
* ===
* Each printed warning/error contains the same three sections:
* - Preamble: automatically generated; the content varies depending on category. It will print the
* file and function that the warning is from, and information about the files being processed
* or extracted.
* - Header: begins with 'warning: ' or 'error:', should contain essential information about the
* warning/error, ends with the warning type if applicable. Printed with emphasis to make it
* stand out. Does not start with a capital letter or end with a '.'
* - Body (optional): indented, should contain further diagnostic information useful for identifying
* and fixing the warning/error. Can be a sentence with captialisation and '.' on the end.
*
* Please think of what the end user will find most useful when writing the header and body, and try
* to keep it brief without sacrificing important information! Also remember that if the user is
* only looking at stderr, they will normally have no other context.
*
* Warning vs error
* ===
* The principle that we have operated on so far is
* - issue a warning if ZAPD will still be able to produce a valid, compilable C file that will
* match
* - if this cannot happen, use an error.
* but at the end of the day, it is up to the programmer's discretion what it should be possible to
* disable.
*
* Documentation
* ===
* Remember that all warnings also need to be documented in the README.md. The help is generated
* automatically.
*/
#include "WarningHandler.h"
#include <cassert>
#include "Globals.h"
#include "Utils/StringHelper.h"
typedef struct
{
WarningType type;
WarningLevel defaultLevel;
std::string description;
} WarningInfoInit;
typedef struct
{
WarningLevel level;
std::string name;
std::string description;
} WarningInfo;
/**
* Master list of all default warning types and features
*
* To add a warning type, fill in a new row of this map. Think carefully about what its default
* level should be, and try and make the description both brief and informative: it is used in the
* help message, so again, think about what the end user needs to know.
*/
// clang-format off
static const std::unordered_map<std::string, WarningInfoInit> warningStringToInitMap = {
{"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"}},
};
/**
* Map constructed at runtime to contain the warning features as set by the user using -W flags.
*/
static std::unordered_map<WarningType, WarningInfo> warningTypeToInfoMap;
void WarningHandler::ConstructTypeToInfoMap() {
for (auto& entry : warningStringToInitMap) {
warningTypeToInfoMap[entry.second.type] = {entry.second.defaultLevel, entry.first, entry.second.description};
}
warningTypeToInfoMap[WarningType::Always] = {WarningLevel::Warn, "always", "you shouldn't be reading this"};
assert(warningTypeToInfoMap.size() == static_cast<size_t>(WarningType::Max));
}
/**
* Initialises the main warning type map and reads flags passed to set each warning type's level.
*/
void WarningHandler::Init(int argc, char* argv[]) {
ConstructTypeToInfoMap();
bool werror = false;
for (int i = 1; i < argc; i++) {
// If it doesn't start with "-W" skip it.
if (argv[i][0] != '-' || argv[i][1] != 'W' || argv[i][2] == '\0') {
continue;
}
WarningLevel warningTypeOn = WarningLevel::Warn;
size_t startingIndex = 2;
// "-Wno-"
if (argv[i][2] == 'n' && argv[i][3] == 'o' && argv[i][4] == '-' && argv[i][5] != '\0') {
warningTypeOn = WarningLevel::Off;
startingIndex = 5;
}
// Read starting after the "-W" or "-Wno-"
std::string_view currentArgv = &argv[i][startingIndex];
if (currentArgv == "error") {
werror = warningTypeOn != WarningLevel::Off;
} else if (currentArgv == "everything") {
for (auto& it: warningTypeToInfoMap) {
if (it.second.level <= WarningLevel::Warn) {
it.second.level = warningTypeOn;
}
}
} else {
// "-Werror=" / "-Wno-error=" parser
if (currentArgv.rfind("error=", 0) == 0) {
// Read starting after the "error=" part
currentArgv = &argv[i][startingIndex + 6];
warningTypeOn = warningTypeOn != WarningLevel::Off ? WarningLevel::Err : WarningLevel::Warn;
}
auto it = warningStringToInitMap.find(std::string(currentArgv));
if (it != warningStringToInitMap.end()) {
warningTypeToInfoMap[it->second.type].level = warningTypeOn;
}
else {
HANDLE_WARNING(WarningType::Always, StringHelper::Sprintf("unknown warning flag '%s'", argv[i]), "");
}
}
}
if (werror) {
for (auto& it: warningTypeToInfoMap) {
if (it.second.level >= WarningLevel::Warn) {
it.second.level = WarningLevel::Err;
}
}
}
}
bool WarningHandler::IsWarningEnabled(WarningType warnType) {
assert(static_cast<size_t>(warnType) >= 0 && warnType < WarningType::Max);
return warningTypeToInfoMap.at(warnType).level != WarningLevel::Off;
}
bool WarningHandler::WasElevatedToError(WarningType warnType) {
assert(static_cast<size_t>(warnType) >= 0 && warnType < WarningType::Max);
if (!IsWarningEnabled(warnType)) {
return false;
}
return warningTypeToInfoMap.at(warnType).level >= WarningLevel::Err;
}
/**
* Print file/line/function info for debugging
*/
void WarningHandler::FunctionPreamble(const char* filename, int32_t line, const char* function) {
bool forcePrint = false;
#ifdef DEVELOPMENT
forcePrint = true;
#endif
fprintf(stderr, "\n");
if (forcePrint || Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG) {
fprintf(stderr, "%s:%i: in function <%s>:\n", filename, line, function);
}
}
/**
* Print the information about the file(s) being processed (XML for extraction, png etc. for building)
*/
void WarningHandler::ProcessedFilePreamble() {
if (Globals::Instance->inputPath != "") {
fprintf(stderr, "When processing file %s: ", Globals::Instance->inputPath.c_str());
}
}
/**
* Print information about the binary file being extracted
*/
void WarningHandler::ExtractedFilePreamble(const ZFile *parent, const ZResource* res, const uint32_t offset) {
fprintf(stderr, "in input binary file %s, ", parent->GetName().c_str());
if (res != nullptr) {
fprintf(stderr, "resource '%s' at ", res->GetName().c_str());
}
fprintf(stderr, "offset 0x%06X: \n\t", offset);
}
/**
* Construct the rest of the message, after warning:/error. The message is filled in one character at a time, with indents added after newlines
*/
std::string WarningHandler::ConstructMessage(std::string message, const std::string& header, const std::string& body) {
message.reserve(message.size() + header.size() + body.size() + 10 * (sizeof(HANG_INDT) - 1));
message += StringHelper::Sprintf(HILITE("%s"), header.c_str());
message += "\n";
if (body == "") {
return message;
}
message += HANG_INDT;
for (const char* ptr = body.c_str(); *ptr != '\0'; ptr++) {
message += *ptr;
if (*ptr == '\n') {
message += HANG_INDT;
}
}
message += "\n";
return message;
}
/* Error module functions */
void WarningHandler::PrintErrorAndThrow(const std::string& header, const std::string& body) {
std::string errorMsg = ERR_FMT("error: ");
throw std::runtime_error(ConstructMessage(errorMsg, header, body));
}
/* Error types, to be used via the macros */
void WarningHandler::ErrorType(WarningType warnType, const std::string& header, const std::string& body) {
std::string headerMsg = header;
for (const auto& iter: warningStringToInitMap) {
if (iter.second.type == warnType) {
headerMsg += StringHelper::Sprintf(" [%s]", iter.first.c_str());
}
}
PrintErrorAndThrow(headerMsg, body);
}
void WarningHandler::Error_Plain(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) {
FunctionPreamble(filename, line, function);
ErrorType(warnType, header, body);
}
void WarningHandler::Error_Process(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) {
FunctionPreamble(filename, line, function);
ProcessedFilePreamble();
ErrorType(warnType, header, body);
}
void WarningHandler::Error_Resource(const char* filename, int32_t line, const char* function, WarningType warnType, const ZFile *parent, const ZResource* res, const uint32_t offset, const std::string& header, const std::string& body) {
assert(parent != nullptr);
FunctionPreamble(filename, line, function);
ProcessedFilePreamble();
ExtractedFilePreamble(parent, res, offset);
ErrorType(warnType, header, body);
}
/* Warning module functions */
void WarningHandler::PrintWarningBody(const std::string& header, const std::string& body) {
std::string errorMsg = WARN_FMT("warning: ");
fprintf(stderr, "%s", ConstructMessage(errorMsg, header, body).c_str());
}
void WarningHandler::WarningTypeAndChooseEscalate(WarningType warnType, const std::string& header, const std::string& body) {
std::string headerMsg = header;
for (const auto& iter: warningStringToInitMap) {
if (iter.second.type == warnType) {
headerMsg += StringHelper::Sprintf(" [-W%s]", iter.first.c_str());
}
}
if (WasElevatedToError(warnType)) {
PrintErrorAndThrow(headerMsg, body);
} else {
PrintWarningBody(headerMsg, body);
}
}
/* Warning types, to be used via the macros */
void WarningHandler::Warning_Plain(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) {
if (!IsWarningEnabled(warnType)) {
return;
}
FunctionPreamble(filename, line, function);
WarningTypeAndChooseEscalate(warnType, header, body);
}
void WarningHandler::Warning_Process(const char* filename, int32_t line, const char* function, WarningType warnType, const std::string& header, const std::string& body) {
if (!IsWarningEnabled(warnType)) {
return;
}
FunctionPreamble(filename, line, function);
ProcessedFilePreamble();
WarningTypeAndChooseEscalate(warnType, header, body);
}
void WarningHandler::Warning_Resource(const char* filename, int32_t line, const char* function, WarningType warnType, const ZFile *parent, const ZResource* res, const uint32_t offset, const std::string& header, const std::string& body) {
assert(parent != nullptr);
if (!IsWarningEnabled(warnType)) {
return;
}
FunctionPreamble(filename, line, function);
ProcessedFilePreamble();
ExtractedFilePreamble(parent, res, offset);
WarningTypeAndChooseEscalate(warnType, header, body);
}
/* Help-related functions */
#include <set>
/**
* Print each warning name, default status, and description using the init map
*/
void WarningHandler::PrintHelp() {
std::set<std::string> sortedKeys;
WarningInfoInit warningInfo;
uint32_t columnWidth = 25;
std::string dt;
// Sort keys through the magic of `set`, to print in alphabetical order
for (auto& it : warningStringToInitMap) {
sortedKeys.insert(it.first);
}
printf("\nWarning types ( * means enabled by default)\n");
for (auto& key : sortedKeys) {
warningInfo = warningStringToInitMap.at(key);
if (warningInfo.defaultLevel <= WarningLevel::Warn) {
dt = "-W";
dt += key;
if (warningInfo.defaultLevel == WarningLevel::Warn) {
dt += " *";
}
printf(HELP_DT_INDT "%-*s", columnWidth, dt.c_str());
if (dt.length() + 2 > columnWidth) {
printf("\n" HELP_DT_INDT "%-*s", columnWidth, "");
}
printf("%s\n", warningInfo.description.c_str());
}
}
printf("\nDefault errors\n");
for (auto& key : sortedKeys) {
if (warningInfo.defaultLevel > WarningLevel::Warn) {
dt = "-W";
dt += key;
printf(HELP_DT_INDT "%-*s", columnWidth, dt.c_str());
if (dt.length() + 2 > columnWidth) {
printf("\n" HELP_DT_INDT "%*s", columnWidth, "");
}
printf("%s\n", warningInfo.description.c_str());
}
}
printf("\n");
printf("Other\n" HELP_DT_INDT "-Weverything will enable all existing warnings.\n" HELP_DT_INDT "-Werror will promote all warnings to errors.\n");
printf("\n");
printf("Warnings can be disabled using -Wno-... instead of -W...; -Weverything will override any -Wno-... flags passed before it.\n");
}
/**
* Print which warnings are currently enabled
*/
void WarningHandler::PrintWarningsDebugInfo()
{
std::string dt;
printf("Warnings status:\n");
for (auto& it: warningTypeToInfoMap) {
dt = it.second.name;
dt += ": ";
printf(HELP_DT_INDT "%-25s", dt.c_str());
switch (it.second.level)
{
case WarningLevel::Off:
printf(VT_FGCOL(LIGHTGRAY) "Off" VT_RST);
break;
case WarningLevel::Warn:
printf(VT_FGCOL(YELLOW) "Warn" VT_RST);
break;
case WarningLevel::Err:
printf(VT_FGCOL(RED) "Err" VT_RST);
break;
}
printf("\n");
}
printf("\n");
}

View File

@@ -0,0 +1,145 @@
#pragma once
#include <array>
#include <string>
#include <string_view>
#include <unordered_map>
#include "Utils/vt.h"
#include "ZFile.h"
#ifdef _MSC_VER
#define __PRETTY_FUNCTION__ __FUNCSIG__
#elif not defined(__GNUC__)
#define __PRETTY_FUNCTION__ __func__
#endif
// =======================================
/* Formatting macros */
// TODO: move this somewhere else so it can be used by other help
#define HELP_DT_INDT " "
/* Macros for formatting warnings/errors */
#define VT_HILITE VT_BOLD_FGCOL(WHITE)
#define VT_WARN VT_BOLD_FGCOL(PURPLE)
#define VT_ERR VT_BOLD_FGCOL(RED)
#define HILITE(string) (VT_HILITE string VT_RST)
#define WARN_FMT(string) (VT_WARN string VT_RST)
#define ERR_FMT(string) (VT_ERR string VT_RST)
// Maybe make WARN_LF instead
// Currently 8 spaces
#define WARN_INDT " "
// Currently 16 spaces
#define HANG_INDT " "
// =======================================
/* Warning and error macros */
// TODO: better names
// General-purpose, plain style (only prints function,file,line in the preamble)
#define HANDLE_ERROR(warningType, header, body) \
WarningHandler::Error_Plain(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, body)
#define HANDLE_WARNING(warningType, header, body) \
WarningHandler::Warning_Plain(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, \
body)
// For processing XMLs or textures/blobs (preamble contains function,file,line; processed file)
#define HANDLE_ERROR_PROCESS(warningType, header, body) \
WarningHandler::Error_Process(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, \
body)
#define HANDLE_WARNING_PROCESS(warningType, header, body) \
WarningHandler::Warning_Process(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, header, \
body)
// For ZResource-related stuff (preamble contains function,file,line; processed file; extracted file
// and offset)
#define HANDLE_ERROR_RESOURCE(warningType, parent, resource, offset, header, body) \
WarningHandler::Error_Resource(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, parent, \
resource, offset, header, body)
#define HANDLE_WARNING_RESOURCE(warningType, parent, resource, offset, header, body) \
WarningHandler::Warning_Resource(__FILE__, __LINE__, __PRETTY_FUNCTION__, warningType, parent, \
resource, offset, header, body)
// =======================================
enum class WarningType
{
Always, // Warnings of this type are always printed, cannot be disabled.
Deprecated,
Unaccounted,
MissingOffsets,
Intersection,
MissingAttribute,
InvalidAttributeValue,
UnknownAttribute,
InvalidXML,
InvalidJPEG,
InvalidPNG,
InvalidExtractedData,
MissingSegment,
HardcodedPointer,
NotImplemented,
Max,
};
enum class WarningLevel
{
Off,
Warn,
Err,
};
class WarningHandler
{
public:
static void ConstructTypeToInfoMap();
static void Init(int argc, char* argv[]);
static bool IsWarningEnabled(WarningType warnType);
static bool WasElevatedToError(WarningType warnType);
static void FunctionPreamble(const char* filename, int32_t line, const char* function);
static void ProcessedFilePreamble();
static void ExtractedFilePreamble(const ZFile* parent, const ZResource* res,
const uint32_t offset);
static std::string ConstructMessage(std::string message, const std::string& header,
const std::string& body);
[[noreturn]] static void PrintErrorAndThrow(const std::string& header, const std::string& body);
static void PrintWarningBody(const std::string& header, const std::string& body);
[[noreturn]] static void ErrorType(WarningType warnType, const std::string& header,
const std::string& body);
[[noreturn]] static void Error_Plain(const char* filename, int32_t line, const char* function,
WarningType warnType, const std::string& header,
const std::string& body);
[[noreturn]] static void Error_Process(const char* filename, int32_t line, const char* function,
WarningType warnType, const std::string& header,
const std::string& body);
[[noreturn]] static void Error_Resource(const char* filename, int32_t line,
const char* function, WarningType warnType,
const ZFile* parent, const ZResource* res,
const uint32_t offset, const std::string& header,
const std::string& body);
static void WarningTypeAndChooseEscalate(WarningType warnType, const std::string& header,
const std::string& body);
static void Warning_Plain(const char* filename, int32_t line, const char* function,
WarningType warnType, const std::string& header,
const std::string& body);
static void Warning_Process(const char* filename, int32_t line, const char* function,
WarningType warnType, const std::string& header,
const std::string& body);
static void Warning_Resource(const char* filename, int32_t line, const char* function,
WarningType warnType, const ZFile* parent, const ZResource* res,
const uint32_t offset, const std::string& header,
const std::string& body);
static void PrintHelp();
static void PrintWarningsDebugInfo();
};

372
ZAPDTR/ZAPD/ZAPD.vcxproj Normal file
View File

@@ -0,0 +1,372 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.props" Condition="Exists('..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{B53F9E5B-0A58-4BAE-9AFE-856C8CBB8D36}</ProjectGuid>
<RootNamespace>ZAPD</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>ZAPD</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>$(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(LibraryPath)</LibraryPath>
<IncludePath>$(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(SolutionDir)ZAPD\lib\tinyxml2;$(SolutionDir)ZAPD\lib\libgfxd;$(SolutionDir)ZAPD\lib\elfio;$(SolutionDir)ZAPD\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath>
<LibraryPath>$(SolutionDir)ZAPD\lib\libgfxd;$(SolutionDir)x64\Debug;$(SolutionDir)packages\libpng.1.6.28.1\build\native\lib\x64\v140\dynamic\Debug;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<Profile>true</Profile>
<SubSystem>Console</SubSystem>
</Link>
<PreBuildEvent>
<Command>cd ..
mkdir build\ZAPD
python ZAPD/genbuildinfo.py</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<Profile>true</Profile>
<AdditionalDependencies>ZAPDUtils.lib;/WHOLEARCHIVE:ExporterExample.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<SubSystem>Console</SubSystem>
</Link>
<PreBuildEvent>
<Command>cd ..
mkdir build\ZAPD
python ZAPD/genbuildinfo.py</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PreBuildEvent>
<Command>cd ..
mkdir build\ZAPD
python ZAPD/genbuildinfo.py</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
<PreBuildEvent>
<Command>cd ..
mkdir build\ZAPD
python ZAPD/genbuildinfo.py</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\build\ZAPD\BuildInfo.cpp" />
<ClCompile Include="..\lib\libgfxd\gfxd.c" />
<ClCompile Include="..\lib\libgfxd\uc.c" />
<ClCompile Include="..\lib\libgfxd\uc_f3d.c" />
<ClCompile Include="..\lib\libgfxd\uc_f3db.c" />
<ClCompile Include="..\lib\libgfxd\uc_f3dex.c" />
<ClCompile Include="..\lib\libgfxd\uc_f3dex2.c" />
<ClCompile Include="..\lib\libgfxd\uc_f3dexb.c" />
<ClCompile Include="CrashHandler.cpp" />
<ClCompile Include="Declaration.cpp" />
<ClCompile Include="GameConfig.cpp" />
<ClCompile Include="Globals.cpp" />
<ClCompile Include="ImageBackend.cpp" />
<ClCompile Include="Main.cpp" />
<ClCompile Include="OtherStructs\CutsceneMM_Commands.cpp" />
<ClCompile Include="OtherStructs\Cutscene_Commands.cpp" />
<ClCompile Include="OtherStructs\SkinLimbStructs.cpp" />
<ClCompile Include="OutputFormatter.cpp" />
<ClCompile Include="WarningHandler.cpp" />
<ClCompile Include="ZActorList.cpp" />
<ClCompile Include="ZArray.cpp" />
<ClCompile Include="ZBackground.cpp" />
<ClCompile Include="ZCollisionPoly.cpp" />
<ClCompile Include="ZLimb.cpp" />
<ClCompile Include="ZMtx.cpp" />
<ClCompile Include="ZPath.cpp" />
<ClCompile Include="ZPlayerAnimationData.cpp" />
<ClCompile Include="ZRoom\Commands\SetActorCutsceneList.cpp" />
<ClCompile Include="ZRoom\Commands\SetAnimatedMaterialList.cpp" />
<ClCompile Include="ZRoom\Commands\SetCsCamera.cpp" />
<ClCompile Include="ZRoom\Commands\SetMinimapChests.cpp" />
<ClCompile Include="ZRoom\Commands\SetMinimapList.cpp" />
<ClCompile Include="ZRoom\Commands\SetWorldMapVisited.cpp" />
<ClCompile Include="ZRoom\Commands\Unused1D.cpp" />
<ClCompile Include="ZScalar.cpp" />
<ClCompile Include="ZAnimation.cpp" />
<ClCompile Include="ZBlob.cpp" />
<ClCompile Include="ZCollision.cpp" />
<ClCompile Include="ZCutscene.cpp" />
<ClCompile Include="ZDisplayList.cpp" />
<ClCompile Include="ZFile.cpp" />
<ClCompile Include="ZSkeleton.cpp" />
<ClCompile Include="ZResource.cpp" />
<ClCompile Include="ZRoom\Commands\EndMarker.cpp" />
<ClCompile Include="ZRoom\Commands\SetActorList.cpp" />
<ClCompile Include="ZRoom\Commands\SetAlternateHeaders.cpp" />
<ClCompile Include="ZRoom\Commands\SetCameraSettings.cpp" />
<ClCompile Include="ZRoom\Commands\SetCollisionHeader.cpp" />
<ClCompile Include="ZRoom\Commands\SetCutscenes.cpp" />
<ClCompile Include="ZRoom\Commands\SetEchoSettings.cpp" />
<ClCompile Include="ZRoom\Commands\SetEntranceList.cpp" />
<ClCompile Include="ZRoom\Commands\SetExitList.cpp" />
<ClCompile Include="ZRoom\Commands\SetLightingSettings.cpp" />
<ClCompile Include="ZRoom\Commands\SetLightList.cpp" />
<ClCompile Include="ZRoom\Commands\SetMesh.cpp" />
<ClCompile Include="ZRoom\Commands\SetObjectList.cpp" />
<ClCompile Include="ZRoom\Commands\SetPathways.cpp" />
<ClCompile Include="ZRoom\Commands\SetRoomBehavior.cpp" />
<ClCompile Include="ZRoom\Commands\SetRoomList.cpp" />
<ClCompile Include="ZRoom\Commands\SetSkyboxModifier.cpp" />
<ClCompile Include="ZRoom\Commands\SetSkyboxSettings.cpp" />
<ClCompile Include="ZRoom\Commands\SetSoundSettings.cpp" />
<ClCompile Include="ZRoom\Commands\SetSpecialObjects.cpp" />
<ClCompile Include="ZRoom\Commands\SetStartPositionList.cpp" />
<ClCompile Include="ZRoom\Commands\SetTimeSettings.cpp" />
<ClCompile Include="ZRoom\Commands\SetTransitionActorList.cpp" />
<ClCompile Include="ZRoom\Commands\SetWind.cpp" />
<ClCompile Include="ZRoom\Commands\Unused09.cpp" />
<ClCompile Include="ZRoom\Commands\ZRoomCommandUnk.cpp" />
<ClCompile Include="ZRoom\ZRoom.cpp" />
<ClCompile Include="ZRoom\ZRoomCommand.cpp" />
<ClCompile Include="ZString.cpp" />
<ClCompile Include="ZSurfaceType.cpp" />
<ClCompile Include="ZSymbol.cpp" />
<ClCompile Include="ZTexture.cpp" />
<ClCompile Include="ZTextureAnimation.cpp" />
<ClCompile Include="ZVector.cpp" />
<ClCompile Include="ZVtx.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\lib\elfio\elfio\elfio.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elfio_dump.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elfio_dynamic.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elfio_header.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elfio_note.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elfio_relocation.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elfio_section.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elfio_segment.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elfio_strings.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elfio_symbols.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elfio_utils.hpp" />
<ClInclude Include="..\lib\elfio\elfio\elf_types.hpp" />
<ClInclude Include="..\lib\libgfxd\gbi.h" />
<ClInclude Include="..\lib\libgfxd\gfxd.h" />
<ClInclude Include="..\lib\libgfxd\priv.h" />
<ClInclude Include="..\lib\stb\stb_image.h" />
<ClInclude Include="..\lib\stb\stb_image_write.h" />
<ClInclude Include="..\lib\stb\tinyxml2.h" />
<ClInclude Include="CrashHandler.h" />
<ClInclude Include="CRC32.h" />
<ClInclude Include="Declaration.h" />
<ClInclude Include="GameConfig.h" />
<ClInclude Include="Globals.h" />
<ClInclude Include="ImageBackend.h" />
<ClInclude Include="OtherStructs\CutsceneMM_Commands.h" />
<ClInclude Include="OtherStructs\Cutscene_Commands.h" />
<ClInclude Include="OtherStructs\SkinLimbStructs.h" />
<ClInclude Include="OutputFormatter.h" />
<ClInclude Include="WarningHandler.h" />
<ClInclude Include="ZActorList.h" />
<ClInclude Include="ZAnimation.h" />
<ClInclude Include="ZArray.h" />
<ClInclude Include="ZBackground.h" />
<ClInclude Include="ZBlob.h" />
<ClInclude Include="ZCollision.h" />
<ClInclude Include="ZCollisionPoly.h" />
<ClInclude Include="ZCutscene.h" />
<ClInclude Include="ZDisplayList.h" />
<ClInclude Include="ZFile.h" />
<ClInclude Include="ZLimb.h" />
<ClInclude Include="ZMtx.h" />
<ClInclude Include="ZPath.h" />
<ClInclude Include="ZPlayerAnimationData.h" />
<ClInclude Include="ZRoom\Commands\SetActorCutsceneList.h" />
<ClInclude Include="ZRoom\Commands\SetAnimatedMaterialList.h" />
<ClInclude Include="ZRoom\Commands\SetCsCamera.h" />
<ClInclude Include="ZRoom\Commands\SetMinimapChests.h" />
<ClInclude Include="ZRoom\Commands\SetMinimapList.h" />
<ClInclude Include="ZRoom\Commands\SetWorldMapVisited.h" />
<ClInclude Include="ZRoom\Commands\Unused1D.h" />
<ClInclude Include="ZScalar.h" />
<ClInclude Include="ZSkeleton.h" />
<ClInclude Include="ZResource.h" />
<ClInclude Include="ZRoom\Commands\EndMarker.h" />
<ClInclude Include="ZRoom\Commands\SetActorList.h" />
<ClInclude Include="ZRoom\Commands\SetAlternateHeaders.h" />
<ClInclude Include="ZRoom\Commands\SetCameraSettings.h" />
<ClInclude Include="ZRoom\Commands\SetCollisionHeader.h" />
<ClInclude Include="ZRoom\Commands\SetCutscenes.h" />
<ClInclude Include="ZRoom\Commands\SetEchoSettings.h" />
<ClInclude Include="ZRoom\Commands\SetEntranceList.h" />
<ClInclude Include="ZRoom\Commands\SetExitList.h" />
<ClInclude Include="ZRoom\Commands\SetLightingSettings.h" />
<ClInclude Include="ZRoom\Commands\SetLightList.h" />
<ClInclude Include="ZRoom\Commands\SetMesh.h" />
<ClInclude Include="ZRoom\Commands\SetObjectList.h" />
<ClInclude Include="ZRoom\Commands\SetPathways.h" />
<ClInclude Include="ZRoom\Commands\SetRoomBehavior.h" />
<ClInclude Include="ZRoom\Commands\SetRoomList.h" />
<ClInclude Include="ZRoom\Commands\SetSkyboxModifier.h" />
<ClInclude Include="ZRoom\Commands\SetSkyboxSettings.h" />
<ClInclude Include="ZRoom\Commands\SetSoundSettings.h" />
<ClInclude Include="ZRoom\Commands\SetSpecialObjects.h" />
<ClInclude Include="ZRoom\Commands\SetStartPositionList.h" />
<ClInclude Include="ZRoom\Commands\SetTimeSettings.h" />
<ClInclude Include="ZRoom\Commands\SetTransitionActorList.h" />
<ClInclude Include="ZRoom\Commands\SetWind.h" />
<ClInclude Include="ZRoom\Commands\Unused09.h" />
<ClInclude Include="ZRoom\Commands\ZRoomCommandUnk.h" />
<ClInclude Include="ZRoom\ZRoom.h" />
<ClInclude Include="ZRoom\ZRoomCommand.h" />
<ClInclude Include="ZString.h" />
<ClInclude Include="ZSurfaceType.h" />
<ClInclude Include="ZSymbol.h" />
<ClInclude Include="ZTexture.h" />
<ClInclude Include="ZTextureAnimation.h" />
<ClInclude Include="ZVector.h" />
<ClInclude Include="ZVtx.h" />
</ItemGroup>
<ItemGroup>
<Text Include="..\SymbolMap_OoTMqDbg.txt">
<DeploymentContent>true</DeploymentContent>
</Text>
<Text Include="any\any\zlib.static.txt" />
<Text Include="NuGet\libpng.static.txt" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets" Condition="Exists('..\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets')" />
<Import Project="..\packages\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.targets" Condition="Exists('..\packages\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.targets')" />
<Import Project="..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.targets" Condition="Exists('..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.targets')" />
<Import Project="..\packages\zlib.static.1.2.5\build\native\zlib.static.targets" Condition="Exists('..\packages\zlib.static.1.2.5\build\native\zlib.static.targets')" />
<Import Project="..\packages\libpng.static.1.6.37\build\native\libpng.static.targets" Condition="Exists('..\packages\libpng.static.1.6.37\build\native\libpng.static.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets'))" />
<Error Condition="!Exists('..\packages\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v140.windesktop.msvcstl.dyn.rt-dyn.targets'))" />
<Error Condition="!Exists('..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.props'))" />
<Error Condition="!Exists('..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\YY.NuGet.Import.Helper.1.0.0.4\build\native\YY.NuGet.Import.Helper.targets'))" />
<Error Condition="!Exists('..\packages\zlib.static.1.2.5\build\native\zlib.static.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\zlib.static.1.2.5\build\native\zlib.static.targets'))" />
<Error Condition="!Exists('..\packages\libpng.static.1.6.37\build\native\libpng.static.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\libpng.static.1.6.37\build\native\libpng.static.targets'))" />
</Target>
</Project>

View File

@@ -0,0 +1,572 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Source Files\Libraries">
<UniqueIdentifier>{02148456-5068-4613-8478-f10addc58e70}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Libraries">
<UniqueIdentifier>{bcab3136-95ba-4839-833c-43d78ad6e335}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Libraries\elfio">
<UniqueIdentifier>{dc06ed84-f6fe-4277-80f3-d62bd5cdbb98}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Z64">
<UniqueIdentifier>{6049c045-bc38-4221-b29e-ca6d4d8af4aa}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Z64\ZRoom">
<UniqueIdentifier>{490e3a08-047b-48d3-ab53-3a860a3b92aa}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Z64\ZRoom\Commands">
<UniqueIdentifier>{26c06845-8e8e-4b79-ad18-07c4f9c0f801}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Z64">
<UniqueIdentifier>{d45c420d-2378-47ac-92c5-80db9475c195}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Z64\ZRoom">
<UniqueIdentifier>{03cc56a2-e0e8-4167-80a0-98fb900a959a}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Z64\ZRoom\Commands">
<UniqueIdentifier>{73db0879-6df8-4f6a-8cc2-a1f836e9e796}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Libraries\fbx">
<UniqueIdentifier>{be9a5be0-ec6a-4200-8e39-bb58c7da7aa8}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Libraries\libgfxd">
<UniqueIdentifier>{7ee79d97-c6a8-4e82-93ef-37981f4d7838}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Libraries\libgfxd">
<UniqueIdentifier>{85600275-99fe-491d-8189-bcc3dc1a8903}</UniqueIdentifier>
</Filter>
<Filter Include="any">
<UniqueIdentifier>{ba9990b0-1082-48bb-874c-6108534b5455}</UniqueIdentifier>
</Filter>
<Filter Include="any\any">
<UniqueIdentifier>{ce9d91b0-ba20-4296-bc2d-8630965bb392}</UniqueIdentifier>
</Filter>
<Filter Include="NuGet">
<UniqueIdentifier>{730beb67-6d59-4849-9d9b-702c4a565fc0}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZRoom\ZRoom.cpp">
<Filter>Source Files\Z64\ZRoom</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetEchoSettings.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\ZRoomCommand.cpp">
<Filter>Source Files\Z64\ZRoom</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetSoundSettings.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetWind.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetTimeSettings.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetSpecialObjects.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetRoomBehavior.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetSkyboxSettings.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetCameraSettings.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetSkyboxModifier.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetActorList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetEntranceList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetStartPositionList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="Globals.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetAlternateHeaders.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetExitList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\EndMarker.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetCollisionHeader.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetRoomList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetObjectList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetMesh.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\Unused09.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetLightingSettings.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetTransitionActorList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetPathways.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetCutscenes.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZAnimation.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZBlob.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZCutscene.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZDisplayList.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZFile.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZResource.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZTexture.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZSkeleton.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetLightList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\ZRoomCommandUnk.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZCollision.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZScalar.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZVector.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZArray.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZVtx.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZLimb.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="OutputFormatter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZSymbol.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="..\lib\libgfxd\gfxd.c">
<Filter>Source Files\Libraries\libgfxd</Filter>
</ClCompile>
<ClCompile Include="..\lib\libgfxd\uc.c">
<Filter>Source Files\Libraries\libgfxd</Filter>
</ClCompile>
<ClCompile Include="..\lib\libgfxd\uc_f3d.c">
<Filter>Source Files\Libraries\libgfxd</Filter>
</ClCompile>
<ClCompile Include="..\lib\libgfxd\uc_f3db.c">
<Filter>Source Files\Libraries\libgfxd</Filter>
</ClCompile>
<ClCompile Include="..\lib\libgfxd\uc_f3dex.c">
<Filter>Source Files\Libraries\libgfxd</Filter>
</ClCompile>
<ClCompile Include="..\lib\libgfxd\uc_f3dex2.c">
<Filter>Source Files\Libraries\libgfxd</Filter>
</ClCompile>
<ClCompile Include="..\lib\libgfxd\uc_f3dexb.c">
<Filter>Source Files\Libraries\libgfxd</Filter>
</ClCompile>
<ClCompile Include="ZMtx.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetWorldMapVisited.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\Unused1D.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetActorCutsceneList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetCsCamera.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetMinimapChests.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetMinimapList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZBackground.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="ZRoom\Commands\SetAnimatedMaterialList.cpp">
<Filter>Source Files\Z64\ZRoom\Commands</Filter>
</ClCompile>
<ClCompile Include="ZPath.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="Declaration.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ImageBackend.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZString.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="GameConfig.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZTextureAnimation.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="OtherStructs\SkinLimbStructs.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="..\build\ZAPD\BuildInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZPlayerAnimationData.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="WarningHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZCollisionPoly.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="OtherStructs\Cutscene_Commands.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="OtherStructs\CutsceneMM_Commands.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="CrashHandler.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZSurfaceType.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="ZRoom\ZRoom.h">
<Filter>Header Files\Z64\ZRoom</Filter>
</ClInclude>
<ClInclude Include="ZRoom\ZRoomCommand.h">
<Filter>Header Files\Z64\ZRoom</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetEchoSettings.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetSoundSettings.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetWind.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetTimeSettings.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetSpecialObjects.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetRoomBehavior.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetSkyboxSettings.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetCameraSettings.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetSkyboxModifier.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetActorList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetEntranceList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetStartPositionList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elf_types.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio_dump.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio_dynamic.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio_header.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio_note.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio_relocation.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio_section.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio_segment.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio_strings.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio_symbols.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="..\lib\elfio\elfio\elfio_utils.hpp">
<Filter>Header Files\Libraries\elfio</Filter>
</ClInclude>
<ClInclude Include="Globals.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetAlternateHeaders.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetExitList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\EndMarker.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetCollisionHeader.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetRoomList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetObjectList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetMesh.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\Unused09.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetLightingSettings.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetTransitionActorList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetPathways.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetCutscenes.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="..\lib\stb\stb_image.h">
<Filter>Header Files\Libraries</Filter>
</ClInclude>
<ClInclude Include="..\lib\stb\stb_image_write.h">
<Filter>Header Files\Libraries</Filter>
</ClInclude>
<ClInclude Include="ZTexture.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZAnimation.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZBlob.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZCutscene.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZDisplayList.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZFile.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZResource.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZSkeleton.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetLightList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\ZRoomCommandUnk.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZCollision.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZScalar.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZVector.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="..\lib\stb\tinyxml2.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZArray.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZVtx.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="CRC32.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZLimb.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="OutputFormatter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZSymbol.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="..\lib\libgfxd\gbi.h">
<Filter>Header Files\Libraries\libgfxd</Filter>
</ClInclude>
<ClInclude Include="..\lib\libgfxd\gfxd.h">
<Filter>Header Files\Libraries\libgfxd</Filter>
</ClInclude>
<ClInclude Include="..\lib\libgfxd\priv.h">
<Filter>Header Files\Libraries\libgfxd</Filter>
</ClInclude>
<ClInclude Include="ZMtx.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetWorldMapVisited.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetActorCutsceneList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\Unused1D.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetCsCamera.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetMinimapChests.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetMinimapList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ZBackground.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZRoom\Commands\SetAnimatedMaterialList.h">
<Filter>Header Files\Z64\ZRoom\Commands</Filter>
</ClInclude>
<ClInclude Include="ImageBackend.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZPath.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="Declaration.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZString.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="GameConfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZTextureAnimation.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="OtherStructs\SkinLimbStructs.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="ZPlayerAnimationData.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="WarningHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZCollisionPoly.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="OtherStructs\Cutscene_Commands.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="OtherStructs\CutsceneMM_Commands.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="CrashHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZSurfaceType.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="..\SymbolMap_OoTMqDbg.txt">
<Filter>Resource Files</Filter>
</Text>
<Text Include="any\any\zlib.static.txt">
<Filter>any\any</Filter>
</Text>
<Text Include="NuGet\libpng.static.txt">
<Filter>NuGet</Filter>
</Text>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
</Project>

194
ZAPDTR/ZAPD/ZActorList.cpp Normal file
View File

@@ -0,0 +1,194 @@
#include "ZActorList.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "WarningHandler.h"
#include "ZFile.h"
#include "ZRoom/ZNames.h"
REGISTER_ZFILENODE(ActorList, ZActorList);
ZActorList::ZActorList(ZFile* nParent) : ZResource(nParent)
{
RegisterRequiredAttribute("Count");
}
void ZActorList::ExtractFromBinary(uint32_t nRawDataIndex, uint8_t nNumActors)
{
rawDataIndex = nRawDataIndex;
numActors = nNumActors;
// Don't parse raw data of external files
if (parent->GetMode() == ZFileMode::ExternalFile)
return;
ParseRawData();
}
void ZActorList::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
numActors = StringHelper::StrToL(registeredAttributes.at("Count").value);
if (numActors < 1)
{
HANDLE_ERROR_RESOURCE(
WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
StringHelper::Sprintf("invalid value '%d' found for 'NumPaths' attribute", numActors),
"Should be at least '1'");
}
}
void ZActorList::ParseRawData()
{
ZResource::ParseRawData();
offset_t currentPtr = rawDataIndex;
size_t largestlength = 0;
for (size_t i = 0; i < numActors; i++)
{
ActorSpawnEntry entry(parent->GetRawData(), currentPtr);
currentPtr += entry.GetRawDataSize();
actors.push_back(entry);
size_t actorNameLength = ZNames::GetActorName(entry.GetActorId()).size();
if (actorNameLength > largestlength)
largestlength = actorNameLength;
}
for (auto& entry : actors)
{
entry.SetLargestActorName(largestlength);
}
}
Declaration* ZActorList::DeclareVar(const std::string& prefix, const std::string& bodyStr)
{
std::string auxName = name;
if (name == "")
auxName = GetDefaultName(prefix);
Declaration* decl =
parent->AddDeclarationArray(rawDataIndex, GetDeclarationAlignment(), GetRawDataSize(),
GetSourceTypeName(), name, GetActorListArraySize(), bodyStr);
decl->staticConf = staticConf;
return decl;
}
std::string ZActorList::GetBodySourceCode() const
{
std::string declaration;
size_t index = 0;
for (auto& entry : actors)
{
declaration += StringHelper::Sprintf("\t{ %s },", entry.GetBodySourceCode().c_str());
if (index < actors.size() - 1)
declaration += "\n";
index++;
}
return declaration;
}
std::string ZActorList::GetSourceTypeName() const
{
return actors.front().GetSourceTypeName();
}
ZResourceType ZActorList::GetResourceType() const
{
return ZResourceType::ActorList;
}
size_t ZActorList::GetRawDataSize() const
{
return actors.size() * actors.front().GetRawDataSize();
}
size_t ZActorList::GetActorListArraySize() const
{
size_t actorCount = 0;
// Doing an else-if here so we only do the loop when the game is SW97.
// Actor 0x22 is removed from SW97, so we need to ensure that we don't increment the actor count
// for it.
if (Globals::Instance->game == ZGame::OOT_SW97)
{
actorCount = 0;
for (const auto& entry : actors)
if (entry.GetActorId() != 0x22)
actorCount++;
}
else
{
actorCount = actors.size();
}
return actorCount;
}
/* ActorSpawnEntry */
ActorSpawnEntry::ActorSpawnEntry(const std::vector<uint8_t>& rawData, uint32_t rawDataIndex)
{
actorNum = BitConverter::ToInt16BE(rawData, rawDataIndex + 0);
posX = BitConverter::ToInt16BE(rawData, rawDataIndex + 2);
posY = BitConverter::ToInt16BE(rawData, rawDataIndex + 4);
posZ = BitConverter::ToInt16BE(rawData, rawDataIndex + 6);
rotX = BitConverter::ToUInt16BE(rawData, rawDataIndex + 8);
rotY = BitConverter::ToUInt16BE(rawData, rawDataIndex + 10);
rotZ = BitConverter::ToUInt16BE(rawData, rawDataIndex + 12);
params = BitConverter::ToInt16BE(rawData, rawDataIndex + 14);
}
std::string ActorSpawnEntry::GetBodySourceCode() const
{
std::string body;
std::string actorNameFmt = StringHelper::Sprintf("%%-%zus ", largestActorName + 1);
body =
StringHelper::Sprintf(actorNameFmt.c_str(), (ZNames::GetActorName(actorNum) + ",").c_str());
body += StringHelper::Sprintf("{ %6i, %6i, %6i }, ", posX, posY, posZ);
if (Globals::Instance->game == ZGame::MM_RETAIL)
body += StringHelper::Sprintf("{ SPAWN_ROT_FLAGS(%#5hX, 0x%04X)"
", SPAWN_ROT_FLAGS(%#5hX, 0x%04X)"
", SPAWN_ROT_FLAGS(%#5hX, 0x%04X) }, ",
(rotX >> 7) & 0b111111111, rotX & 0b1111111,
(rotY >> 7) & 0b111111111, rotY & 0b1111111,
(rotZ >> 7) & 0b111111111, rotZ & 0b1111111);
else
body += StringHelper::Sprintf("{ %#6hX, %#6hX, %#6hX }, ", rotX, rotY, rotZ);
body += StringHelper::Sprintf("0x%04X", params);
return body;
}
std::string ActorSpawnEntry::GetSourceTypeName() const
{
return "ActorEntry";
}
size_t ActorSpawnEntry::GetRawDataSize() const
{
return 16;
}
uint16_t ActorSpawnEntry::GetActorId() const
{
return actorNum;
}
void ActorSpawnEntry::SetLargestActorName(size_t nameSize)
{
largestActorName = nameSize;
}

52
ZAPDTR/ZAPD/ZActorList.h Normal file
View File

@@ -0,0 +1,52 @@
#pragma once
#include "ZResource.h"
class ActorSpawnEntry
{
public:
uint16_t actorNum;
int16_t posX;
int16_t posY;
int16_t posZ;
uint16_t rotX;
uint16_t rotY;
uint16_t rotZ;
uint16_t params;
size_t largestActorName = 16;
ActorSpawnEntry(const std::vector<uint8_t>& rawData, uint32_t rawDataIndex);
std::string GetBodySourceCode() const;
std::string GetSourceTypeName() const;
size_t GetRawDataSize() const;
uint16_t GetActorId() const;
void SetLargestActorName(size_t nameSize);
};
class ZActorList : public ZResource
{
public:
std::vector<ActorSpawnEntry> actors;
uint32_t numActors = 0;
ZActorList(ZFile* nParent);
void ExtractFromBinary(offset_t nRawDataIndex, uint8_t nNumActors);
void ParseXML(tinyxml2::XMLElement* reader) override;
void ParseRawData() override;
Declaration* DeclareVar(const std::string& prefix, const std::string& bodyStr) override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
protected:
size_t GetActorListArraySize() const;
};

580
ZAPDTR/ZAPD/ZAnimation.cpp Normal file
View File

@@ -0,0 +1,580 @@
#include "ZAnimation.h"
#include <utility>
#include "Globals.h"
#include "Utils/BitConverter.h"
#include <Utils/DiskFile.h>
#include "Utils/StringHelper.h"
#include "WarningHandler.h"
#include "ZFile.h"
REGISTER_ZFILENODE(Animation, ZNormalAnimation);
REGISTER_ZFILENODE(PlayerAnimation, ZLinkAnimation);
REGISTER_ZFILENODE(CurveAnimation, ZCurveAnimation);
REGISTER_ZFILENODE(LegacyAnimation, ZLegacyAnimation);
ZAnimation::ZAnimation(ZFile* nParent) : ZResource(nParent)
{
frameCount = 0;
genOTRDef = true;
}
void ZAnimation::ParseRawData()
{
ZResource::ParseRawData();
frameCount = BitConverter::ToInt16BE(parent->GetRawData(), rawDataIndex + 0);
}
/*
std::string ZAnimation::GetSourceOutputHeader(const std::string& prefix)
{
if (Globals::Instance->otrMode)
{
std::string str = "";
str += StringHelper::Sprintf("#define %s \"__OTR__%s/%s\"", name.c_str(), parent->GetOutName().c_str(), name.c_str());
return str;
}
else
return ZResource::GetSourceOutputHeader(prefix);
}
*/
ZResourceType ZAnimation::GetResourceType() const
{
return ZResourceType::Animation;
}
/* ZNormalAnimation */
ZNormalAnimation::ZNormalAnimation(ZFile* nParent) : ZAnimation(nParent)
{
}
size_t ZNormalAnimation::GetRawDataSize() const
{
return 16;
}
std::string ZNormalAnimation::GetSourceTypeName() const
{
return "AnimationHeader";
}
void ZNormalAnimation::ParseRawData()
{
ZAnimation::ParseRawData();
auto& data = parent->GetRawData();
rotationValuesSeg = BitConverter::ToInt32BE(data, rawDataIndex + 4);
rotationIndicesSeg = BitConverter::ToInt32BE(data, rawDataIndex + 8);
limit = BitConverter::ToInt16BE(data, rawDataIndex + 12);
rotationValuesOffset = Seg2Filespace(rotationValuesSeg, parent->baseAddress);
rotationIndicesOffset = Seg2Filespace(rotationIndicesSeg, parent->baseAddress);
uint32_t currentPtr = rotationValuesOffset;
// Read the Rotation Values
for (uint32_t i = 0; i < ((rotationIndicesOffset - rotationValuesOffset) / 2); i++)
{
rotationValues.push_back(BitConverter::ToInt16BE(data, currentPtr));
currentPtr += 2;
}
currentPtr = rotationIndicesOffset;
// Read the Rotation Indices
for (uint32_t i = 0; i < ((rawDataIndex - rotationIndicesOffset) / 6); i++)
{
rotationIndices.push_back(RotationIndex(BitConverter::ToInt16BE(data, currentPtr),
BitConverter::ToInt16BE(data, currentPtr + 2),
BitConverter::ToInt16BE(data, currentPtr + 4)));
currentPtr += 6;
}
}
void ZNormalAnimation::DeclareReferences(const std::string& prefix)
{
std::string defaultPrefix = prefix.c_str();
if (name != "")
defaultPrefix = name;
// replace g prefix with s for local variables
if (defaultPrefix.at(0) == 'g')
defaultPrefix.replace(0, 1, "s");
std::string indicesStr = "";
std::string valuesStr = " ";
const uint8_t lineLength = 14;
const uint8_t offset = 0;
if (!Globals::Instance->otrMode)
{
for (size_t i = 0; i < rotationValues.size(); i++)
{
valuesStr += StringHelper::Sprintf("0x%04X, ", rotationValues[i]);
if ((i - offset + 1) % lineLength == 0)
valuesStr += "\n ";
}
}
parent->AddDeclarationArray(rotationValuesOffset, DeclarationAlignment::Align4,
rotationValues.size() * 2, "s16",
StringHelper::Sprintf("%sFrameData", defaultPrefix.c_str()),
rotationValues.size(), valuesStr);
if (!Globals::Instance->otrMode)
{
for (size_t i = 0; i < rotationIndices.size(); i++)
{
indicesStr +=
StringHelper::Sprintf(" { 0x%04X, 0x%04X, 0x%04X },", rotationIndices[i].x,
rotationIndices[i].y, rotationIndices[i].z);
if (i != (rotationIndices.size() - 1))
indicesStr += "\n";
}
}
parent->AddDeclarationArray(rotationIndicesOffset, DeclarationAlignment::Align4,
rotationIndices.size() * 6, "JointIndex",
StringHelper::Sprintf("%sJointIndices", defaultPrefix.c_str()),
rotationIndices.size(), indicesStr);
}
std::string ZNormalAnimation::GetBodySourceCode() const
{
std::string frameDataName;
Globals::Instance->GetSegmentedPtrName(rotationValuesSeg, parent, "s16", frameDataName,
parent->workerID);
std::string jointIndicesName;
Globals::Instance->GetSegmentedPtrName(rotationIndicesSeg, parent, "JointIndex",
jointIndicesName, parent->workerID);
std::string headerStr =
StringHelper::Sprintf("\n\t{ %i }, %s,\n", frameCount, frameDataName.c_str());
headerStr += StringHelper::Sprintf("\t%s, %i\n", jointIndicesName.c_str(), limit);
return headerStr;
}
/* ZLinkAnimation */
ZLinkAnimation::ZLinkAnimation(ZFile* nParent) : ZAnimation(nParent)
{
segmentAddress = 0;
}
size_t ZLinkAnimation::GetRawDataSize() const
{
return 8;
}
std::string ZLinkAnimation::GetSourceTypeName() const
{
return "LinkAnimationHeader";
}
void ZLinkAnimation::ParseRawData()
{
ZAnimation::ParseRawData();
const auto& rawData = parent->GetRawData();
segmentAddress = BitConverter::ToInt32BE(rawData, rawDataIndex + 4);
}
std::string ZLinkAnimation::GetBodySourceCode() const
{
std::string segSymbol;
Globals::Instance->GetSegmentedPtrName(segmentAddress, parent, "", segSymbol, parent->workerID);
return StringHelper::Sprintf("\n\t{ %i }, %s\n", frameCount, segSymbol.c_str());
}
/* ZCurveAnimation */
TransformData::TransformData(ZFile* parent, const std::vector<uint8_t>& rawData,
uint32_t fileOffset)
: parent(parent)
{
unk_00 = BitConverter::ToUInt16BE(rawData, fileOffset + 0);
unk_02 = BitConverter::ToUInt16BE(rawData, fileOffset + 2);
unk_04 = BitConverter::ToInt16BE(rawData, fileOffset + 4);
unk_06 = BitConverter::ToInt16BE(rawData, fileOffset + 6);
unk_08 = BitConverter::ToFloatBE(rawData, fileOffset + 8);
}
TransformData::TransformData(ZFile* parent, const std::vector<uint8_t>& rawData,
uint32_t fileOffset, size_t index)
: TransformData(parent, rawData, fileOffset + index * GetRawDataSize())
{
}
std::string TransformData::GetBody([[maybe_unused]] const std::string& prefix) const
{
return StringHelper::Sprintf("0x%04X, 0x%04X, %i, %i, %ff", unk_00, unk_02, unk_04, unk_06,
unk_08);
}
size_t TransformData::GetRawDataSize() const
{
return 0x0C;
}
std::string TransformData::GetSourceTypeName()
{
return "TransformData";
}
ZCurveAnimation::ZCurveAnimation(ZFile* nParent) : ZAnimation(nParent)
{
RegisterOptionalAttribute("SkelOffset");
}
void ZCurveAnimation::ParseXML(tinyxml2::XMLElement* reader)
{
ZAnimation::ParseXML(reader);
std::string skelOffsetXml = registeredAttributes.at("SkelOffset").value;
if (skelOffsetXml == "")
{
HANDLE_ERROR_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex,
"missing 'SkelOffset' attribute in <ZCurveAnimation>",
"You need to provide the offset of the curve skeleton.");
}
skelOffset = StringHelper::StrToL(skelOffsetXml, 0);
}
void ZCurveAnimation::ParseRawData()
{
ZAnimation::ParseRawData();
const auto& rawData = parent->GetRawData();
refIndex = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0);
transformData = BitConverter::ToUInt32BE(rawData, rawDataIndex + 4);
copyValues = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8);
unk_0C = BitConverter::ToInt16BE(rawData, rawDataIndex + 12);
unk_10 = BitConverter::ToInt16BE(rawData, rawDataIndex + 14);
uint32_t limbCountAddress = Seg2Filespace(skelOffset, parent->baseAddress) + 4;
limbCount = BitConverter::ToUInt8BE(rawData, limbCountAddress);
size_t transformDataSize = 0;
size_t copyValuesSize = 0;
if (refIndex != 0)
{
uint32_t refIndexOffset = Seg2Filespace(refIndex, parent->baseAddress);
for (size_t i = 0; i < 3 * 3 * limbCount; i++)
{
uint8_t ref = BitConverter::ToUInt8BE(rawData, refIndexOffset + i);
if (ref == 0)
copyValuesSize++;
else
transformDataSize += ref;
refIndexArr.emplace_back(ref);
}
}
if (transformData != 0)
{
uint32_t transformDataOffset = Seg2Filespace(transformData, parent->baseAddress);
for (size_t i = 0; i < transformDataSize; i++)
transformDataArr.emplace_back(parent, rawData, transformDataOffset, i);
}
if (copyValues != 0)
{
uint32_t copyValuesOffset = Seg2Filespace(copyValues, parent->baseAddress);
for (size_t i = 0; i < copyValuesSize; i++)
copyValuesArr.emplace_back(BitConverter::ToInt16BE(rawData, copyValuesOffset + i * 2));
}
}
void ZCurveAnimation::DeclareReferences(const std::string& prefix)
{
if (refIndex != 0)
{
uint32_t refIndexOffset = Seg2Filespace(refIndex, parent->baseAddress);
std::string refIndexStr =
StringHelper::Sprintf("%sCurveAnime_%s_%06X", prefix.c_str(), "Ref", refIndexOffset);
std::string entryStr = " ";
uint16_t arrayItemCnt = refIndexArr.size();
size_t i = 0;
for (auto& child : refIndexArr)
{
entryStr += StringHelper::Sprintf("0x%02X, %s", child, (i++ % 8 == 7) ? "\n " : "");
}
Declaration* decl = parent->GetDeclaration(refIndexOffset);
if (decl == nullptr)
{
parent->AddDeclarationArray(refIndexOffset, DeclarationAlignment::Align4,
arrayItemCnt * 1, "u8", refIndexStr, arrayItemCnt,
entryStr);
}
else
{
decl->text = entryStr;
}
}
if (transformData != 0)
{
uint32_t transformDataOffset = Seg2Filespace(transformData, parent->baseAddress);
std::string transformDataStr = StringHelper::Sprintf(
"%sCurveAnime_%s_%06X", prefix.c_str(),
transformDataArr.at(0).GetSourceTypeName().c_str(), transformDataOffset);
std::string entryStr;
uint16_t arrayItemCnt = transformDataArr.size();
size_t i = 0;
for (auto& child : transformDataArr)
{
entryStr += StringHelper::Sprintf(" { %s },%s", child.GetBody(prefix).c_str(),
(++i < arrayItemCnt) ? "\n" : "");
}
Declaration* decl = parent->GetDeclaration(transformDataOffset);
if (decl == nullptr)
{
parent->AddDeclarationArray(transformDataOffset, DeclarationAlignment::Align4,
arrayItemCnt * transformDataArr.at(0).GetRawDataSize(),
transformDataArr.at(0).GetSourceTypeName(),
transformDataStr, arrayItemCnt, entryStr);
}
else
{
decl->text = entryStr;
}
}
if (copyValues != 0)
{
uint32_t copyValuesOffset = Seg2Filespace(copyValues, parent->baseAddress);
std::string copyValuesStr =
StringHelper::Sprintf("%sCurveAnime_%s_%06X", prefix.c_str(), "Copy", copyValuesOffset);
std::string entryStr = " ";
uint16_t arrayItemCnt = copyValuesArr.size();
size_t i = 0;
for (auto& child : copyValuesArr)
{
entryStr += StringHelper::Sprintf("% 6i, %s", child, (i++ % 8 == 7) ? "\n " : "");
}
Declaration* decl = parent->GetDeclaration(copyValuesOffset);
if (decl == nullptr)
{
parent->AddDeclarationArray(copyValuesOffset, DeclarationAlignment::Align4,
arrayItemCnt * 2, "s16", copyValuesStr, arrayItemCnt,
entryStr);
}
else
{
decl->text = entryStr;
}
}
}
std::string ZCurveAnimation::GetBodySourceCode() const
{
std::string refIndexStr;
Globals::Instance->GetSegmentedPtrName(refIndex, parent, "u8", refIndexStr, parent->workerID);
std::string transformDataStr;
Globals::Instance->GetSegmentedPtrName(transformData, parent, "TransformData",
transformDataStr, parent->workerID);
std::string copyValuesStr;
Globals::Instance->GetSegmentedPtrName(copyValues, parent, "s16", copyValuesStr,
parent->workerID);
return StringHelper::Sprintf("\n\t%s,\n\t%s,\n\t%s,\n\t%i, %i\n", refIndexStr.c_str(),
transformDataStr.c_str(), copyValuesStr.c_str(), unk_0C, unk_10);
}
size_t ZCurveAnimation::GetRawDataSize() const
{
return 0x10;
}
DeclarationAlignment ZCurveAnimation::GetDeclarationAlignment() const
{
return DeclarationAlignment::Align4;
}
std::string ZCurveAnimation::GetSourceTypeName() const
{
return "TransformUpdateIndex";
}
/* ZLegacyAnimation */
ZLegacyAnimation::ZLegacyAnimation(ZFile* nParent) : ZAnimation(nParent)
{
}
void ZLegacyAnimation::ParseRawData()
{
ZAnimation::ParseRawData();
const auto& rawData = parent->GetRawData();
limbCount = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x02);
frameData = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x04);
jointKey = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x08);
if (GETSEGNUM(frameData) == parent->segment && GETSEGNUM(jointKey) == parent->segment)
{
uint32_t frameDataOffset = Seg2Filespace(frameData, parent->baseAddress);
uint32_t jointKeyOffset = Seg2Filespace(jointKey, parent->baseAddress);
uint32_t ptr = frameDataOffset;
for (size_t i = 0; i < (jointKeyOffset - frameDataOffset) / 2; i++)
{
frameDataArray.push_back(BitConverter::ToUInt16BE(rawData, ptr));
ptr += 2;
}
ptr = jointKeyOffset;
for (int32_t i = 0; i < limbCount + 1; i++)
{
JointKey key(parent);
key.ExtractFromFile(ptr);
jointKeyArray.push_back(key);
ptr += key.GetRawDataSize();
}
}
}
void ZLegacyAnimation::DeclareReferences(const std::string& prefix)
{
std::string varPrefix = prefix;
if (name != "")
varPrefix = name;
ZAnimation::DeclareReferences(varPrefix);
if (!frameDataArray.empty())
{
uint32_t frameDataOffset = Seg2Filespace(frameData, parent->baseAddress);
if (GETSEGNUM(frameData) == parent->segment && !parent->HasDeclaration(frameDataOffset))
{
std::string frameDataBody = "\t";
for (size_t i = 0; i < frameDataArray.size(); i++)
{
frameDataBody += StringHelper::Sprintf("0x%04X, ", frameDataArray[i]);
if (i % 8 == 7 && i + 1 < frameDataArray.size())
frameDataBody += "\n\t";
}
std::string frameDataName = StringHelper::Sprintf("%sFrameData", varPrefix.c_str());
parent->AddDeclarationArray(frameDataOffset, DeclarationAlignment::Align4,
frameDataArray.size() * 2, "s16", frameDataName,
frameDataArray.size(), frameDataBody);
}
}
if (!jointKeyArray.empty())
{
uint32_t jointKeyOffset = Seg2Filespace(jointKey, parent->baseAddress);
if (GETSEGNUM(jointKey) == parent->segment && !parent->HasDeclaration(jointKeyOffset))
{
const auto res = jointKeyArray.at(0);
std::string jointKeyBody;
for (size_t i = 0; i < jointKeyArray.size(); i++)
{
jointKeyBody += StringHelper::Sprintf("\t{ %s },",
jointKeyArray[i].GetBodySourceCode().c_str());
if (i + 1 < jointKeyArray.size())
jointKeyBody += "\n";
}
std::string jointKeyName = StringHelper::Sprintf("%sJointKey", varPrefix.c_str());
parent->AddDeclarationArray(jointKeyOffset, DeclarationAlignment::Align4,
jointKeyArray.size() * res.GetRawDataSize(),
res.GetSourceTypeName(), jointKeyName, jointKeyArray.size(),
jointKeyBody);
}
}
}
std::string ZLegacyAnimation::GetBodySourceCode() const
{
std::string body = "\n";
std::string frameDataName;
std::string jointKeyName;
Globals::Instance->GetSegmentedPtrName(frameData, parent, "s16", frameDataName,
parent->workerID);
Globals::Instance->GetSegmentedPtrName(jointKey, parent, "JointKey", jointKeyName,
parent->workerID);
body += StringHelper::Sprintf("\t%i, %i,\n", frameCount, limbCount);
body += StringHelper::Sprintf("\t%s,\n", frameDataName.c_str());
body += StringHelper::Sprintf("\t%s\n", jointKeyName.c_str());
return body;
}
std::string ZLegacyAnimation::GetSourceTypeName() const
{
return "LegacyAnimationHeader";
}
size_t ZLegacyAnimation::GetRawDataSize() const
{
return 0x0C;
}
JointKey::JointKey(ZFile* nParent) : ZResource(nParent)
{
}
void JointKey::ParseRawData()
{
ZResource::ParseRawData();
const auto& rawData = parent->GetRawData();
xMax = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x00);
x = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x02);
yMax = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x04);
y = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x06);
zMax = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x08);
z = BitConverter::ToInt16BE(rawData, rawDataIndex + 0x0A);
}
std::string JointKey::GetBodySourceCode() const
{
return StringHelper::Sprintf("%6i, %6i, %6i, %6i, %6i, %6i", xMax, x, yMax, y, zMax, z);
}
std::string JointKey::GetSourceTypeName() const
{
return "JointKey";
}
ZResourceType JointKey::GetResourceType() const
{
// TODO
return ZResourceType::Error;
}
size_t JointKey::GetRawDataSize() const
{
return 0x0C;
}

179
ZAPDTR/ZAPD/ZAnimation.h Normal file
View File

@@ -0,0 +1,179 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "ZResource.h"
#include "ZSkeleton.h"
#include "tinyxml2.h"
struct RotationIndex
{
// uint16_t transX, transY, transZ;
uint16_t x, y, z;
RotationIndex(uint16_t nX, uint16_t nY, uint16_t nZ) : x(nX), y(nY), z(nZ) {}
};
class ZAnimation : public ZResource
{
public:
int16_t frameCount;
ZAnimation(ZFile* nParent);
//std::string GetSourceOutputHeader(const std::string& prefix) override;
ZResourceType GetResourceType() const override;
protected:
void ParseRawData() override;
};
class ZNormalAnimation : public ZAnimation
{
public:
std::vector<uint16_t> rotationValues;
std::vector<RotationIndex> rotationIndices;
segptr_t rotationValuesSeg = 0;
segptr_t rotationIndicesSeg = 0;
offset_t rotationValuesOffset = 0;
offset_t rotationIndicesOffset = 0;
int16_t limit = 0;
ZNormalAnimation(ZFile* nParent);
void DeclareReferences(const std::string& prefix) override;
std::string GetBodySourceCode() const override;
size_t GetRawDataSize() const override;
std::string GetSourceTypeName() const override;
void ParseRawData() override;
};
class ZLinkAnimation : public ZAnimation
{
public:
segptr_t segmentAddress;
ZLinkAnimation(ZFile* nParent);
std::string GetBodySourceCode() const override;
size_t GetRawDataSize() const override;
std::string GetSourceTypeName() const override;
void ParseRawData() override;
};
class TransformData
{
public:
ZFile* parent;
///* 0x0000 */ u16 unk_00; // appears to be flags
uint16_t unk_00;
///* 0x0002 */ s16 unk_02;
int16_t unk_02;
///* 0x0004 */ s16 unk_04;
int16_t unk_04;
///* 0x0006 */ s16 unk_06;
int16_t unk_06;
///* 0x0008 */ f32 unk_08;
float unk_08;
public:
TransformData() = default;
TransformData(ZFile* parent, const std::vector<uint8_t>& rawData, uint32_t fileOffset);
TransformData(ZFile* parent, const std::vector<uint8_t>& rawData, uint32_t fileOffset,
size_t index);
[[nodiscard]] std::string GetBody(const std::string& prefix) const;
size_t GetRawDataSize() const;
std::string GetSourceTypeName();
};
class ZCurveAnimation : public ZAnimation
{
public:
segptr_t skelOffset = 0;
///* 0x0000 */ u8* refIndex;
segptr_t refIndex = 0;
///* 0x0004 */ TransformData* transformData;
segptr_t transformData = 0;
///* 0x0008 */ s16* copyValues;
segptr_t copyValues = 0;
///* 0x000C */ s16 unk_0C;
int16_t unk_0C;
///* 0x000E */ s16 unk_10;
int16_t unk_10;
uint8_t limbCount = 0;
std::vector<uint8_t> refIndexArr;
std::vector<TransformData> transformDataArr;
std::vector<int16_t> copyValuesArr;
public:
ZCurveAnimation(ZFile* nParent);
void ParseXML(tinyxml2::XMLElement* reader) override;
void ParseRawData() override;
void DeclareReferences(const std::string& prefix) override;
std::string GetBodySourceCode() const override;
size_t GetRawDataSize() const override;
DeclarationAlignment GetDeclarationAlignment() const override;
std::string GetSourceTypeName() const override;
};
// TransformUpdateIndex
/* ZLegacyAnimation */
class JointKey : public ZResource
{
public:
JointKey(ZFile* nParent);
void ParseRawData() override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
protected:
int16_t xMax, x;
int16_t yMax, y;
int16_t zMax, z;
};
class ZLegacyAnimation : public ZAnimation
{
public:
ZLegacyAnimation(ZFile* nParent);
void ParseRawData() override;
void DeclareReferences(const std::string& prefix) override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
size_t GetRawDataSize() const override;
protected:
int16_t limbCount;
segptr_t frameData; // s16*
segptr_t jointKey; // JointKey*
std::vector<uint16_t> frameDataArray;
std::vector<JointKey> jointKeyArray;
};

153
ZAPDTR/ZAPD/ZArray.cpp Normal file
View File

@@ -0,0 +1,153 @@
#include "ZArray.h"
#include <cassert>
#include "Globals.h"
#include "Utils/StringHelper.h"
#include "WarningHandler.h"
#include "ZFile.h"
REGISTER_ZFILENODE(Array, ZArray);
ZArray::ZArray(ZFile* nParent) : ZResource(nParent)
{
canHaveInner = true;
genOTRDef = true;
RegisterRequiredAttribute("Count");
}
ZArray::~ZArray()
{
for (auto res : resList)
delete res;
}
void ZArray::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
arrayCnt = reader->IntAttribute("Count", 0);
if (arrayCnt <= 0)
{
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
"invalid value found for 'Count' attribute", "");
}
tinyxml2::XMLElement* child = reader->FirstChildElement();
if (child == nullptr)
{
HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex,
"<Array> needs one sub-element", "");
}
childName = child->Name();
auto nodeMap = ZFile::GetNodeMap();
size_t childIndex = rawDataIndex;
resList.reserve(arrayCnt);
for (size_t i = 0; i < arrayCnt; i++)
{
ZResource* res = nodeMap->at(childName)(parent);
if (!res->DoesSupportArray())
{
std::string errorHeader = StringHelper::Sprintf(
"resource <%s> does not support being wrapped in an <Array>", childName.c_str());
HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex, errorHeader,
"");
}
res->parent = parent;
res->SetInnerNode(true);
res->ExtractFromXML(child, childIndex);
childIndex += res->GetRawDataSize();
resList.push_back(res);
}
}
Declaration* ZArray::DeclareVar(const std::string& prefix, const std::string& bodyStr)
{
std::string auxName = name;
if (name == "")
auxName = GetDefaultName(prefix);
ZResource* res = resList.at(0);
Declaration* decl;
if (res->IsExternalResource())
{
auto filepath = Globals::Instance->outputPath / name;
std::string includePath = StringHelper::Sprintf("%s.%s.inc", filepath.c_str(),
res->GetExternalExtension().c_str());
decl = parent->AddDeclarationIncludeArray(rawDataIndex, includePath, GetRawDataSize(),
GetSourceTypeName(), name, arrayCnt);
decl->text = bodyStr;
decl->isExternal = true;
}
else
{
decl =
parent->AddDeclarationArray(rawDataIndex, GetDeclarationAlignment(), GetRawDataSize(),
GetSourceTypeName(), name, arrayCnt, bodyStr);
}
decl->staticConf = staticConf;
return decl;
}
std::string ZArray::GetBodySourceCode() const
{
std::string output;
for (size_t i = 0; i < arrayCnt; i++)
{
const auto& res = resList[i];
output += "\t";
switch (res->GetResourceType())
{
case ZResourceType::Pointer:
case ZResourceType::Scalar:
case ZResourceType::Vertex:
case ZResourceType::CollisionPoly:
case ZResourceType::SurfaceType:
output += resList.at(i)->GetBodySourceCode();
break;
default:
output += StringHelper::Sprintf("{ %s }", resList.at(i)->GetBodySourceCode().c_str());
break;
}
if (i < arrayCnt - 1 || res->IsExternalResource())
output += ",\n";
}
return output;
}
size_t ZArray::GetRawDataSize() const
{
size_t size = 0;
for (const auto res : resList)
size += res->GetRawDataSize();
return size;
}
std::string ZArray::GetSourceTypeName() const
{
return resList.at(0)->GetSourceTypeName();
}
ZResourceType ZArray::GetResourceType() const
{
return ZResourceType::Array;
}
DeclarationAlignment ZArray::GetDeclarationAlignment() const
{
if (resList.size() == 0)
{
return DeclarationAlignment::Align4;
}
return resList.at(0)->GetDeclarationAlignment();
}

31
ZAPDTR/ZAPD/ZArray.h Normal file
View File

@@ -0,0 +1,31 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "ZResource.h"
#include "tinyxml2.h"
class ZArray : public ZResource
{
public:
ZArray(ZFile* nParent);
~ZArray();
void ParseXML(tinyxml2::XMLElement* reader) override;
Declaration* DeclareVar(const std::string& prefix, const std::string& bodyStr) override;
std::string GetBodySourceCode() const override;
size_t GetRawDataSize() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
DeclarationAlignment GetDeclarationAlignment() const override;
size_t arrayCnt;
std::vector<ZResource*> resList;
protected:
std::string childName;
};

415
ZAPDTR/ZAPD/ZAudio.cpp Normal file
View File

@@ -0,0 +1,415 @@
#include "ZAudio.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include <Utils/DiskFile.h>
#include "Utils/Path.h"
#include "Utils/StringHelper.h"
#include "ZFile.h"
REGISTER_ZFILENODE(Audio, ZAudio);
ZAudio::ZAudio(ZFile* nParent) : ZResource(nParent)
{
RegisterRequiredAttribute("SoundFontTableOffset");
RegisterRequiredAttribute("SequenceTableOffset");
RegisterRequiredAttribute("SampleBankTableOffset");
RegisterRequiredAttribute("SequenceFontTableOffset");
}
void ZAudio::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
auto t = reader->Name();
auto child = reader->FirstChildElement();
while (child != nullptr)
{
if (std::string(child->Value()) == "Sequences")
{
auto seqChild = child->FirstChildElement();
while (seqChild != nullptr)
{
if (std::string(seqChild->Value()) == "Sequence")
{
seqNames.push_back(seqChild->Attribute("Name"));
}
seqChild = seqChild->NextSiblingElement();
}
}
if (std::string(child->Value()) == "Samples")
{
int bankId = child->IntAttribute("Bank", 0);
auto sampChild = child->FirstChildElement();
while (sampChild != nullptr)
{
if (std::string(sampChild->Value()) == "Sample")
{
auto atStr = sampChild->FirstChildElement()->Attribute("At");
auto loopStr = sampChild->FirstChildElement()->Attribute("LoopOffset");
uint32_t loopOffset = 0xFFFFFFFF;
uint32_t atOffset = StringHelper::StrToL(atStr, 16);
if (loopStr != NULL)
{
loopOffset = StringHelper::StrToL(loopStr, 16);
specialLoopSamples[loopOffset] = atOffset;
}
sampleOffsets[bankId][loopOffset][atOffset] = sampChild->Attribute("Name");
}
sampChild = sampChild->NextSiblingElement();
}
}
if (std::string(child->Value()) == "Soundfont")
{
auto name = child->Attribute("Name");
auto index = child->IntAttribute("Index", 0);
soundFontNames[index] = name;
}
child = child->NextSiblingElement();
}
}
void ZAudio::DecodeADPCMSample(SampleEntry* sample)
{
int16_t buffer[1024 * 128];
int16_t* out = &buffer[0];
}
std::vector<AdsrEnvelope*> ZAudio::ParseEnvelopeData(std::vector<uint8_t> audioBank, std::vector<uint8_t> audioTable, int envelopeOffset, int baseOffset)
{
std::vector<AdsrEnvelope*> result;
while (true)
{
AdsrEnvelope* env = new AdsrEnvelope();
env->delay = BitConverter::ToInt16BE(audioBank, envelopeOffset + 0);
env->arg = BitConverter::ToInt16BE(audioBank, envelopeOffset + 2);
envelopeOffset += 4;
result.push_back(env);
if (env->delay < 0)
break;
}
return result;
}
SoundFontEntry* ZAudio::ParseSoundFontEntry(std::vector<uint8_t> audioBank,
std::vector<uint8_t> audioTable,
AudioTableEntry audioSampleBankEntry, int bankIndex,
int soundFontOffset,
int baseOffset)
{
SoundFontEntry* soundFont = new SoundFontEntry();
soundFont->sampleEntry = ParseSampleEntry(
audioBank, audioTable, audioSampleBankEntry, bankIndex,
BitConverter::ToInt32BE(audioBank, soundFontOffset + 0) + baseOffset, baseOffset);
soundFont->tuning = BitConverter::ToFloatBE(audioBank, soundFontOffset + 4);
return soundFont;
}
SampleEntry* ZAudio::ParseSampleEntry(std::vector<uint8_t> audioBank,
std::vector<uint8_t> audioTable,
AudioTableEntry audioSampleBankEntry, int bankIndex,
int sampleOffset,
int baseOffset)
{
int sampleDataOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 4) + audioSampleBankEntry.ptr;
if (samples.find(sampleOffset) == samples.end())
{
SampleEntry* sample = new SampleEntry();
sample->bankId = bankIndex;
int sampleSize = BitConverter::ToInt32BE(audioBank, sampleOffset + 0) & 0x00FFFFFF;
int loopOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 8) + baseOffset;
int bookOffset = BitConverter::ToInt32BE(audioBank, sampleOffset + 12) + baseOffset;
char* sampleData = (char*)malloc(sampleSize);
memcpy(sampleData, audioTable.data() + sampleDataOffset, sampleSize);
sample->data = std::vector<uint8_t>(sampleSize);
memcpy(sample->data.data(), sampleData, sampleSize);
uint32_t origField = (BitConverter::ToUInt32BE(audioBank, sampleOffset + 0));
sample->codec = (origField >> 28) & 0x0F;
sample->medium = (origField >> 24) & 0x03;
sample->unk_bit26 = (origField >> 22) & 0x01;
sample->unk_bit25 = (origField >> 21) & 0x01;
sample->loop.start = BitConverter::ToInt32BE(audioBank, loopOffset + 0);
sample->loop.end = BitConverter::ToInt32BE(audioBank, loopOffset + 4);
sample->loop.count = BitConverter::ToInt32BE(audioBank, loopOffset + 8);
if (sample->loop.count != 0)
{
for (int i = 0; i < 16; i++)
{
int16_t state = BitConverter::ToInt16BE(audioBank, loopOffset + 16 + (i * 2));
sample->loop.states.push_back(state);
}
}
sample->book.order = BitConverter::ToInt32BE(audioBank, bookOffset + 0);
sample->book.npredictors = BitConverter::ToInt32BE(audioBank, bookOffset + 4);
for (int i = 0; i < sample->book.npredictors * sample->book.order * 8; i++)
{
sample->book.books.push_back(
BitConverter::ToInt16BE(audioBank, bookOffset + 8 + (i * 2)));
}
sample->sampleDataOffset = sampleDataOffset;
if (specialLoopSamples.find(loopOffset) != specialLoopSamples.end())
sample->sampleLoopOffset = loopOffset;
sample->fileName = StringHelper::Sprintf("audio/samples/sample_%08X", sampleOffset);
samples[sampleOffset] = sample;
return sample;
}
else
{
return samples[sampleOffset];
}
}
std::vector<AudioTableEntry> ZAudio::ParseAudioTable(std::vector<uint8_t> codeData, int baseOffset)
{
std::vector<AudioTableEntry> entries;
int numEntries = BitConverter::ToInt16BE(codeData, baseOffset + 0);
int romAddr = BitConverter::ToInt16BE(codeData, baseOffset + 4);
int currentOffset = baseOffset + 16;
for (int i = 0; i < numEntries; i++)
{
AudioTableEntry entry;
entry.ptr = BitConverter::ToInt32BE(codeData, currentOffset + 0);
entry.size = BitConverter::ToInt32BE(codeData, currentOffset + 4);
entry.medium = codeData[currentOffset + 8];
entry.cachePolicy = codeData[currentOffset + 9];
entry.data1 = BitConverter::ToInt16BE(codeData, currentOffset + 10);
entry.data2 = BitConverter::ToInt16BE(codeData, currentOffset + 12);
entry.data3 = BitConverter::ToInt16BE(codeData, currentOffset + 14);
entries.push_back(entry);
currentOffset += 16;
}
return entries;
}
void ZAudio::ParseSoundFont(std::vector<uint8_t> codeData, std::vector<uint8_t> audioTable,
std::vector<AudioTableEntry> audioSampleBank,
AudioTableEntry& entry)
{
int ptr = entry.ptr;
int size = entry.size;
int sampleBankId1 = (entry.data1 >> 8) & 0xFF;
int sampleBankId2 = (entry.data1) & 0xFF;
int numInstruments = (entry.data2 >> 8) & 0xFF;
int numDrums = entry.data2 & 0xFF;
int numSfx = entry.data3;
int currentOffset = BitConverter::ToInt32BE(codeData, ptr) + ptr;
for (int i = 0; i < numDrums; i++)
{
DrumEntry drum;
int samplePtr = BitConverter::ToInt32BE(codeData, currentOffset);
if (samplePtr != 0)
{
samplePtr += ptr;
drum.sample = ParseSampleEntry(codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1,
BitConverter::ToInt32BE(codeData, samplePtr + 4) + ptr, ptr);
drum.releaseRate = codeData[samplePtr + 0];
drum.pan = codeData[samplePtr + 1];
drum.loaded = codeData[samplePtr + 2];
drum.tuning = BitConverter::ToFloatBE(codeData, samplePtr + 8);
drum.env = ParseEnvelopeData(codeData, audioTable, BitConverter::ToInt32BE(codeData, samplePtr + 12) + ptr, ptr);
}
entry.drums.push_back(drum);
currentOffset += 4;
}
currentOffset = BitConverter::ToInt32BE(codeData, ptr + 4) + ptr;
for (int i = 0; i < numSfx; i++)
{
SoundFontEntry* sfx;
sfx = ParseSoundFontEntry(codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1,
currentOffset, ptr);
entry.soundEffects.push_back(sfx);
currentOffset += 8;
}
for (int i = 0; i < numInstruments; i++)
{
InstrumentEntry instrument;
currentOffset = BitConverter::ToInt32BE(codeData, ptr + 8 + (i * 4));
instrument.isValidInstrument = currentOffset != 0;
if (currentOffset != 0)
{
currentOffset += ptr;
instrument.loaded = codeData[currentOffset + 0];
instrument.normalRangeLo = codeData[currentOffset + 1];
instrument.normalRangeHi = codeData[currentOffset + 2];
instrument.releaseRate = codeData[currentOffset + 3];
instrument.env = ParseEnvelopeData(codeData, audioTable, BitConverter::ToInt32BE(codeData, currentOffset + 4) + ptr, ptr);
if (BitConverter::ToInt32BE(codeData, currentOffset + 8) != 0)
instrument.lowNotesSound = ParseSoundFontEntry(
codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset + 8, ptr);
if (BitConverter::ToInt32BE(codeData, currentOffset + 16) != 0)
instrument.normalNotesSound = ParseSoundFontEntry(
codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset + 16, ptr);
if (BitConverter::ToInt32BE(codeData, currentOffset + 24) != 0 &&
instrument.normalRangeHi != 0x7F)
instrument.highNotesSound = ParseSoundFontEntry(
codeData, audioTable, audioSampleBank[sampleBankId1], sampleBankId1, currentOffset + 24, ptr);
}
entry.instruments.push_back(instrument);
}
}
void ZAudio::ParseRawData()
{
ZResource::ParseRawData();
std::vector<uint8_t> codeData;
std::vector<uint8_t> audioTableData;
std::vector<uint8_t> audioBankData;
std::vector<uint8_t> audioSeqData;
if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
codeData = Globals::Instance->GetBaseromFile("code");
else
codeData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "code");
if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
audioTableData = Globals::Instance->GetBaseromFile("Audiotable");
else
audioTableData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiotable");
if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
audioBankData = Globals::Instance->GetBaseromFile("Audiobank");
else
audioBankData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "Audiobank");
if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
audioSeqData = Globals::Instance->GetBaseromFile("Audioseq");
else
audioSeqData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() +
"Audioseq");
// TABLE PARSING
// MQ DBG ROM
//int gSoundFontTableOffset = 0x138270;
//int gSequenceTableOffset = 0x1386A0;
//int gSampleBankTableOffset = 0x138D90;
//int gSequenceFontTableOffset = 0x1384E0;
// NTSC 1.0
//int gSoundFontTableOffset = 0x1026A0;
//int gSequenceTableOffset = 0x102AD0;
//int gSampleBankTableOffset = 0x1031C0;
//int gSequenceFontTableOffset = 0x102910;
int gSoundFontTableOffset = StringHelper::StrToL(registeredAttributes.at("SoundFontTableOffset").value, 16);
int gSequenceTableOffset = StringHelper::StrToL(registeredAttributes.at("SequenceTableOffset").value, 16);
int gSampleBankTableOffset = StringHelper::StrToL(registeredAttributes.at("SampleBankTableOffset").value, 16);
int gSequenceFontTableOffset = StringHelper::StrToL(registeredAttributes.at("SequenceFontTableOffset").value, 16);
soundFontTable = ParseAudioTable(codeData, gSoundFontTableOffset);
sequenceTable = ParseAudioTable(codeData, gSequenceTableOffset);
sampleBankTable = ParseAudioTable(codeData, gSampleBankTableOffset);
// SEQEUNCE FONT TABLE PARSING
for (int i = 0; i < sequenceTable.size(); i++)
{
uint16_t idx = BitConverter::ToUInt16BE(codeData, gSequenceFontTableOffset + (i * 2));
uint8_t numFonts = codeData[gSequenceFontTableOffset + (idx++)];
std::vector<uint32_t> fontIds;
for (int j = 0; j < numFonts; j++)
{
uint8_t fontId = codeData[gSequenceFontTableOffset + (idx++)];
fontIds.push_back(fontId);
}
fontIndices.push_back(fontIds);
}
// SAMPLE/FONT PARSING
for (int i = 0; i < soundFontTable.size(); i++)
{
ParseSoundFont(audioBankData, audioTableData, sampleBankTable, soundFontTable[i]);
}
// SEQUENCE PARSING
for (int i = 0; i < sequenceTable.size(); i++)
{
int seqDestIdx = i;
if (sequenceTable[i].size == 0)
seqDestIdx = sequenceTable[i].ptr;
std::vector<char> seqVec = std::vector<char>(sequenceTable[seqDestIdx].size);
memcpy(seqVec.data(), audioSeqData.data() + sequenceTable[seqDestIdx].ptr,
sequenceTable[seqDestIdx].size);
sequences.push_back(seqVec);
}
}
std::string ZAudio::GetSourceTypeName() const
{
return "u8";
}
size_t ZAudio::GetRawDataSize() const
{
return 1;
}
ZResourceType ZAudio::GetResourceType() const
{
return ZResourceType::Audio;
}

134
ZAPDTR/ZAPD/ZAudio.h Normal file
View File

@@ -0,0 +1,134 @@
#pragma once
#include "ZResource.h"
#include "tinyxml2.h"
struct AdsrEnvelope
{
int16_t delay;
int16_t arg;
};
struct AdpcmBook
{
/* 0x00 */ int32_t order;
/* 0x04 */ int32_t npredictors;
/* 0x08 */ std::vector<int16_t> books; // size 8 * order * npredictors. 8-byte aligned
};
struct AdpcmLoop
{
/* 0x00 */ uint32_t start;
/* 0x04 */ uint32_t end;
/* 0x08 */ uint32_t count;
/* 0x10 */ std::vector<int16_t> states;
};
struct SampleEntry
{
std::string fileName;
uint8_t bankId;
uint32_t sampleDataOffset;
uint32_t sampleLoopOffset = 0xFFFFFFFF;
uint8_t codec;
uint8_t medium;
uint8_t unk_bit26;
uint8_t unk_bit25;
std::vector<uint8_t> data;
AdpcmLoop loop;
AdpcmBook book;
};
struct SoundFontEntry
{
SampleEntry* sampleEntry = nullptr;
float tuning;
};
struct DrumEntry
{
uint8_t releaseRate;
uint8_t pan;
uint8_t loaded;
uint32_t offset;
float tuning;
std::vector<AdsrEnvelope*> env;
SampleEntry* sample = nullptr;
};
struct InstrumentEntry
{
bool isValidInstrument;
uint8_t loaded;
uint8_t normalRangeLo;
uint8_t normalRangeHi;
uint8_t releaseRate;
std::vector<AdsrEnvelope*> env;
SoundFontEntry* lowNotesSound = nullptr;
SoundFontEntry* normalNotesSound = nullptr;
SoundFontEntry* highNotesSound = nullptr;
};
struct AudioTableEntry
{
uint32_t ptr;
uint32_t size;
uint8_t medium;
uint8_t cachePolicy;
uint16_t data1;
uint16_t data2;
uint16_t data3;
std::vector<DrumEntry> drums;
std::vector<SoundFontEntry*> soundEffects;
std::vector<InstrumentEntry> instruments;
};
class ZAudio : public ZResource
{
public:
std::vector<AudioTableEntry> soundFontTable;
std::vector<AudioTableEntry> sequenceTable;
std::vector<AudioTableEntry> sampleBankTable;
std::vector<std::vector<char>> sequences;
std::map<uint32_t, SampleEntry*> samples;
std::vector<std::vector<uint32_t>> fontIndices;
std::vector<std::string> seqNames;
std::map<uint32_t, std::string> soundFontNames;
// First Key = Bank ID, Sec Key = LoopDataOffset, Third Key = Sample Data Offset
std::map<uint32_t, std::map<uint32_t, std::map<uint32_t, std::string>>> sampleOffsets;
// Key = Loop Offset, Value = Sample Offset
std::map<uint32_t, uint32_t> specialLoopSamples;
ZAudio(ZFile* nParent);
void ParseXML(tinyxml2::XMLElement* reader) override;
void DecodeADPCMSample(SampleEntry* sample);
std::vector<AdsrEnvelope*> ParseEnvelopeData(std::vector<uint8_t> audioBank, std::vector<uint8_t> audioTable,
int envelopeOffset, int baseOffset);
SoundFontEntry* ParseSoundFontEntry(std::vector<uint8_t> audioBank,
std::vector<uint8_t> audioTable,
AudioTableEntry audioSampleBankEntry, int bankIndex,
int soundFontOffset,
int baseOffset);
SampleEntry* ParseSampleEntry(std::vector<uint8_t> audioBank, std::vector<uint8_t> audioTable,
AudioTableEntry audioSampleBankEntry, int bankIndex,
int sampleOffset, int baseOffset);
std::vector<AudioTableEntry> ParseAudioTable(std::vector<uint8_t> codeData, int baseOffset);
void ParseSoundFont(std::vector<uint8_t> codeData, std::vector<uint8_t> audioTable,
std::vector<AudioTableEntry> audioSampleBank, AudioTableEntry& entry);
void ParseRawData() override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
};

View File

@@ -0,0 +1,669 @@
/**
* Bruteforcing decoder for converting ADPCM-encoded AIFC into AIFF, in a way
* that roundtrips with vadpcm_enc.
*/
#include <assert.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
typedef signed char s8;
typedef short s16;
typedef int s32;
typedef long long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef float f32;
typedef double f64;
#ifdef _MSC_VER
#define __builtin_bswap16 _byteswap_ushort
#define __builtin_bswap32 _byteswap_ulong
#endif
#define bswap16(x) __builtin_bswap16(x)
#define bswap32(x) __builtin_bswap32(x)
#define BSWAP16(x) x = __builtin_bswap16(x)
#define BSWAP32(x) x = __builtin_bswap32(x)
#define BSWAP16_MANY(x, n) \
for (s32 _i = 0; _i < n; _i++) \
BSWAP16((x)[_i])
#define NORETURN __attribute__((noreturn))
#define UNUSED __attribute__((unused))
typedef struct
{
u32 ckID;
u32 ckSize;
} ChunkHeader;
typedef struct
{
u32 ckID;
u32 ckSize;
u32 formType;
} Chunk;
typedef struct
{
s16 numChannels;
u16 numFramesH;
u16 numFramesL;
s16 sampleSize;
s16 sampleRate[5]; // 80-bit float
u16 compressionTypeH;
u16 compressionTypeL;
} CommonChunk;
typedef struct
{
s16 MarkerID;
u16 positionH;
u16 positionL;
} Marker;
typedef struct
{
s16 playMode;
s16 beginLoop;
s16 endLoop;
} Loop;
typedef struct
{
s8 baseNote;
s8 detune;
s8 lowNote;
s8 highNote;
s8 lowVelocity;
s8 highVelocity;
s16 gain;
Loop sustainLoop;
Loop releaseLoop;
} InstrumentChunk;
typedef struct
{
s32 offset;
s32 blockSize;
} SoundDataChunk;
typedef struct
{
s16 version;
s16 order;
s16 nEntries;
} CodeChunk;
typedef struct
{
u32 start;
u32 end;
u32 count;
s16 state[16];
} ALADPCMloop;
static char usage[] = "input.aifc output.aiff";
static const char *progname, *infilename;
static int framesize = 9;
void fail_parse(const char* fmt, ...)
{
char* formatted = NULL;
va_list ap;
va_start(ap, fmt);
int size = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
if (size >= 0)
{
size++;
formatted = (char*)malloc(size);
if (formatted != NULL)
{
va_start(ap, fmt);
size = vsnprintf(formatted, size, fmt, ap);
va_end(ap);
if (size < 0)
{
free(formatted);
formatted = NULL;
}
}
}
if (formatted != NULL)
{
fprintf(stderr, "%s: %s [%s]\n", progname, formatted, infilename);
free(formatted);
}
exit(1);
}
s32 myrand()
{
static u64 state = 1619236481962341ULL;
state *= 3123692312237ULL;
state += 1;
return state >> 33;
}
s16 qsample(f32 x, s32 scale)
{
if (x > 0.0f)
{
return (s16)((x / scale) + 0.4999999);
}
else
{
return (s16)((x / scale) - 0.4999999);
}
}
void clamp_to_s16(f32* in, s32* out)
{
f32 llevel = -0x8000;
f32 ulevel = 0x7fff;
for (s32 i = 0; i < 16; i++)
{
if (in[i] > ulevel)
in[i] = ulevel;
if (in[i] < llevel)
in[i] = llevel;
if (in[i] > 0.0f)
{
out[i] = (s32)(in[i] + 0.5);
}
else
{
out[i] = (s32)(in[i] - 0.5);
}
}
}
s16 clamp_bits(s32 x, s32 bits)
{
s32 lim = 1 << (bits - 1);
if (x < -lim)
return -lim;
if (x > lim - 1)
return lim - 1;
return x;
}
s32 readaifccodebook(FILE* fhandle, s32**** table, s16* order, s16* npredictors)
{
BSWAP16(*order);
BSWAP16(*npredictors);
*table = (s32***)malloc(*npredictors * sizeof(s32**));
for (s32 i = 0; i < *npredictors; i++)
{
(*table)[i] = (s32**)malloc(8 * sizeof(s32*));
for (s32 j = 0; j < 8; j++)
{
(*table)[i][j] = (s32*)malloc((*order + 8) * sizeof(s32));
}
}
for (s32 i = 0; i < *npredictors; i++)
{
s32** table_entry = (*table)[i];
for (s32 j = 0; j < *order; j++)
{
for (s32 k = 0; k < 8; k++)
{
s16 ts = 0;
BSWAP16(ts);
table_entry[k][j] = ts;
}
}
for (s32 k = 1; k < 8; k++)
{
table_entry[k][*order] = table_entry[k - 1][*order - 1];
}
table_entry[0][*order] = 1 << 11;
for (s32 k = 1; k < 8; k++)
{
s32 j = 0;
for (; j < k; j++)
{
table_entry[j][k + *order] = 0;
}
for (; j < 8; j++)
{
table_entry[j][k + *order] = table_entry[j - k][*order];
}
}
}
return 0;
}
ALADPCMloop* readlooppoints(FILE* ifile, s16* nloops)
{
BSWAP16(*nloops);
ALADPCMloop* al = (ALADPCMloop*)malloc(*nloops * sizeof(ALADPCMloop));
for (s32 i = 0; i < *nloops; i++)
{
BSWAP32(al[i].start);
BSWAP32(al[i].end);
BSWAP32(al[i].count);
BSWAP16_MANY(al[i].state, 16);
}
return al;
}
s32 inner_product(s32 length, s32* v1, s32* v2)
{
s32 out = 0;
for (s32 i = 0; i < length; i++)
{
out += v1[i] * v2[i];
}
// Compute "out / 2^11", rounded down.
s32 dout = out / (1 << 11);
s32 fiout = dout * (1 << 11);
return dout - (out - fiout < 0);
}
void my_decodeframe(u8* frame, s32* decompressed, s32* state, s32 order, s32*** coefTable)
{
s32 ix[16];
u8 header = frame[0];
s32 scale = 1 << (header >> 4);
s32 optimalp = header & 0xf;
if (framesize == 5)
{
for (s32 i = 0; i < 16; i += 4)
{
u8 c = frame[1 + i / 4];
ix[i] = c >> 6;
ix[i + 1] = (c >> 4) & 0x3;
ix[i + 2] = (c >> 2) & 0x3;
ix[i + 3] = c & 0x3;
}
}
else
{
for (s32 i = 0; i < 16; i += 2)
{
u8 c = frame[1 + i / 2];
ix[i] = c >> 4;
ix[i + 1] = c & 0xf;
}
}
for (s32 i = 0; i < 16; i++)
{
if (framesize == 5)
{
if (ix[i] >= 2)
ix[i] -= 4;
}
else
{
if (ix[i] >= 8)
ix[i] -= 16;
}
decompressed[i] = ix[i];
ix[i] *= scale;
}
for (s32 j = 0; j < 2; j++)
{
s32 in_vec[16];
if (j == 0)
{
for (s32 i = 0; i < order; i++)
{
in_vec[i] = state[16 - order + i];
}
}
else
{
for (s32 i = 0; i < order; i++)
{
in_vec[i] = state[8 - order + i];
}
}
for (s32 i = 0; i < 8; i++)
{
s32 ind = j * 8 + i;
in_vec[order + i] = ix[ind];
state[ind] = inner_product(order + i, coefTable[optimalp][i], in_vec) + ix[ind];
}
}
}
void get_bounds(s32* in, s32* decompressed, s32 scale, s32* minVals, s32* maxVals)
{
s32 minv, maxv;
if (framesize == 9)
{
minv = -8;
maxv = 7;
}
else
{
minv = -2;
maxv = 1;
}
for (s32 i = 0; i < 16; i++)
{
s32 lo = in[i] - scale / 2;
s32 hi = in[i] + scale / 2;
lo -= scale;
hi += scale;
if (decompressed[i] == minv)
lo -= scale;
else if (decompressed[i] == maxv)
hi += scale;
minVals[i] = lo;
maxVals[i] = hi;
}
}
void write_header(FILE* ofile, const char* id, s32 size)
{
fwrite(id, 4, 1, ofile);
BSWAP32(size);
fwrite(&size, sizeof(s32), 1, ofile);
}
char* OldMain(char* infilename)
{
s16 order = -1;
s16 nloops = 0;
ALADPCMloop* aloops = NULL;
s16 npredictors = -1;
s32*** coefTable = NULL;
s32 state[16];
s32 decompressed[16];
s32 soundPointer = -1;
s32 currPos = 0;
s32 nSamples = 0;
Chunk FormChunk = Chunk();
ChunkHeader Header = ChunkHeader();
CommonChunk CommChunk = CommonChunk();
InstrumentChunk InstChunk;
SoundDataChunk SndDChunk = SoundDataChunk();
FILE* ifile = NULL;
FILE* ofile = NULL;
if ((ifile = fopen(infilename, "rb")) == NULL)
{
fail_parse("AIFF-C file could not be opened");
exit(1);
}
memset(&InstChunk, 0, sizeof(InstChunk));
BSWAP32(FormChunk.ckID);
BSWAP32(FormChunk.formType);
if ((FormChunk.ckID != 0x464f524d) || (FormChunk.formType != 0x41494643))
{ // FORM, AIFC
fail_parse("not an AIFF-C file");
}
for (;;)
{
s32 num = fread(&Header, sizeof(Header), 1, ifile);
u32 ts = 0;
if (num <= 0)
break;
BSWAP32(Header.ckID);
BSWAP32(Header.ckSize);
Header.ckSize++;
Header.ckSize &= ~1;
s32 offset = ftell(ifile);
switch (Header.ckID)
{
case 0x434f4d4d: // COMM
{
BSWAP16(CommChunk.numChannels);
BSWAP16(CommChunk.numFramesH);
BSWAP16(CommChunk.numFramesL);
BSWAP16(CommChunk.sampleSize);
BSWAP16(CommChunk.compressionTypeH);
BSWAP16(CommChunk.compressionTypeL);
s32 cType = (CommChunk.compressionTypeH << 16) + CommChunk.compressionTypeL;
if (cType == 0x56415043 || cType == 0x41445039)
{ // VAPC or ADP9
framesize = 9;
}
else if (cType == 0x41445035)
{ // ADP5
framesize = 5;
}
else if (cType == 0x4850434d)
{ // HPCM
framesize = 16;
}
else
{
char comprType[5] = {
static_cast<char>(CommChunk.compressionTypeH >> 8), static_cast<char>(CommChunk.compressionTypeH & 0xFF),
static_cast<char>(CommChunk.compressionTypeL >> 8), static_cast<char>(CommChunk.compressionTypeL & 0xFF), 0};
fail_parse("file is of the wrong compression type [got %s (%08x)]", &comprType,
cType);
}
if (CommChunk.numChannels != 1)
{
fail_parse("file contains %d channels, only 1 channel supported",
CommChunk.numChannels);
}
if (CommChunk.sampleSize != 16)
{
fail_parse("file contains %d bit samples, only 16 bit samples supported",
CommChunk.sampleSize);
}
nSamples = (CommChunk.numFramesH << 16) + CommChunk.numFramesL;
// Allow broken input lengths
if (nSamples % 16)
{
nSamples -= (nSamples % 16);
}
if (nSamples % 16 != 0)
{
fail_parse("number of chunks must be a multiple of 16, found %d with remainder %d",
nSamples, nSamples % 16);
}
}
break;
case 0x53534e44: // SSND
BSWAP32(SndDChunk.offset);
BSWAP32(SndDChunk.blockSize);
assert(SndDChunk.offset == 0);
assert(SndDChunk.blockSize == 0);
soundPointer = ftell(ifile);
break;
case 0x4150504c: // APPL
BSWAP32(ts);
if (ts == 0x73746f63)
{ // stoc
u8 len = 0;
if (len == 11)
{
char ChunkName[12];
s16 version;
ChunkName[11] = '\0';
if (strcmp("VADPCMCODES", ChunkName) == 0)
{
BSWAP16(version);
if (version != 1)
{
fail_parse("Unknown codebook chunk version");
}
readaifccodebook(ifile, &coefTable, &order, &npredictors);
}
else if (strcmp("VADPCMLOOPS", ChunkName) == 0)
{
BSWAP16(version);
if (version != 1)
{
fail_parse("Unknown loop chunk version");
}
aloops = readlooppoints(ifile, &nloops);
if (nloops != 1)
{
fail_parse("Only a single loop supported");
}
}
}
}
break;
}
fseek(ifile, offset + Header.ckSize, SEEK_SET);
}
if (coefTable == NULL)
{
fail_parse("Codebook missing from bitstream");
}
for (s32 i = 0; i < order; i++)
{
state[15 - i] = 0;
}
u32 outputBytes = nSamples * sizeof(s16);
u8* outputBuf = (u8*)malloc(outputBytes);
fseek(ifile, soundPointer, SEEK_SET);
s32 fails = 0;
while (currPos < nSamples)
{
u8 input[9];
u8 encoded[9];
s32 lastState[16];
s32 decoded[16];
s16 guess[16];
s16 origGuess[16];
memcpy(lastState, state, sizeof(state));
// Decode for real
my_decodeframe(input, decompressed, state, order, coefTable);
memcpy(decoded, state, sizeof(state));
// Create a guess from that, by clamping to 16 bits
for (s32 i = 0; i < 16; i++)
{
origGuess[i] = clamp_bits(state[i], 16);
}
memcpy(state, decoded, sizeof(state));
memcpy(outputBuf + currPos * 2, decoded, sizeof(decoded));
currPos += 16;
}
if (fails)
{
fprintf(stderr, "%s %d\n", infilename, fails);
}
// Write an incomplete file header. We'll fill in the size later.
fwrite("FORM\0\0\0\0AIFF", 12, 1, ofile);
// Subtract 4 from the COMM size to skip the compression field.
write_header(ofile, "COMM", sizeof(CommonChunk) - 4);
CommChunk.numFramesH = nSamples >> 16;
CommChunk.numFramesL = nSamples & 0xffff;
BSWAP16(CommChunk.numChannels);
BSWAP16(CommChunk.numFramesH);
BSWAP16(CommChunk.numFramesL);
BSWAP16(CommChunk.sampleSize);
fwrite(&CommChunk, sizeof(CommonChunk) - 4, 1, ofile);
if (nloops > 0)
{
s32 startPos = aloops[0].start, endPos = aloops[0].end;
const char* markerNames[2] = {"start", "end"};
Marker markers[2] = {{1, static_cast<u16>(startPos >> 16), static_cast<u16>(startPos & 0xffff)},
{2, static_cast<u16>(endPos >> 16), static_cast<u16>(endPos & 0xffff)}};
write_header(ofile, "MARK", 2 + 2 * sizeof(Marker) + 1 + 5 + 1 + 3);
s16 numMarkers = bswap16(2);
fwrite(&numMarkers, sizeof(s16), 1, ofile);
for (s32 i = 0; i < 2; i++)
{
u8 len = (u8)strlen(markerNames[i]);
BSWAP16(markers[i].MarkerID);
BSWAP16(markers[i].positionH);
BSWAP16(markers[i].positionL);
fwrite(&markers[i], sizeof(Marker), 1, ofile);
fwrite(&len, 1, 1, ofile);
fwrite(markerNames[i], len, 1, ofile);
}
write_header(ofile, "INST", sizeof(InstrumentChunk));
InstChunk.sustainLoop.playMode = bswap16(1);
InstChunk.sustainLoop.beginLoop = bswap16(1);
InstChunk.sustainLoop.endLoop = bswap16(2);
InstChunk.releaseLoop.playMode = 0;
InstChunk.releaseLoop.beginLoop = 0;
InstChunk.releaseLoop.endLoop = 0;
fwrite(&InstChunk, sizeof(InstrumentChunk), 1, ofile);
}
// Save the coefficient table for use when encoding. Ideally this wouldn't
// be needed and "tabledesign -s 1" would generate the right table, but in
// practice it's difficult to adjust samples to make that happen.
write_header(ofile, "APPL", 4 + 12 + sizeof(CodeChunk) + npredictors * order * 8 * 2);
fwrite("stoc", 4, 1, ofile);
CodeChunk cChunk;
cChunk.version = bswap16(1);
cChunk.order = bswap16(order);
cChunk.nEntries = bswap16(npredictors);
fwrite("\x0bVADPCMCODES", 12, 1, ofile);
fwrite(&cChunk, sizeof(CodeChunk), 1, ofile);
for (s32 i = 0; i < npredictors; i++)
{
for (s32 j = 0; j < order; j++)
{
for (s32 k = 0; k < 8; k++)
{
s16 ts = bswap16(coefTable[i][k][j]);
fwrite(&ts, sizeof(s16), 1, ofile);
}
}
}
write_header(ofile, "SSND", outputBytes + 8);
SndDChunk.offset = 0;
SndDChunk.blockSize = 0;
fwrite(&SndDChunk, sizeof(SoundDataChunk), 1, ofile);
fwrite(outputBuf, outputBytes, 1, ofile);
// Fix the size in the header
s32 fileSize = bswap32(ftell(ofile) - 8);
fseek(ofile, 4, SEEK_SET);
fwrite(&fileSize, 4, 1, ofile);
fclose(ifile);
fclose(ofile);
return 0;
}

195
ZAPDTR/ZAPD/ZBackground.cpp Normal file
View File

@@ -0,0 +1,195 @@
#include "ZBackground.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include <Utils/DiskFile.h>
#include "Utils/Path.h"
#include "Utils/StringHelper.h"
#include "WarningHandler.h"
#include "ZFile.h"
REGISTER_ZFILENODE(Background, ZBackground);
#define JPEG_MARKER 0xFFD8FFE0
#define MARKER_DQT 0xFFDB
#define MARKER_EOI 0xFFD9
ZBackground::ZBackground(ZFile* nParent) : ZResource(nParent)
{
}
void ZBackground::ParseRawData()
{
ZResource::ParseRawData();
const auto& rawData = parent->GetRawData();
size_t i = 0;
while (true)
{
uint8_t val = rawData.at(rawDataIndex + i);
data.push_back(val);
if (BitConverter::ToUInt16BE(rawData, rawDataIndex + i) == MARKER_EOI)
{
data.push_back(rawData.at(rawDataIndex + i + 1));
break;
}
i++;
}
}
void ZBackground::ParseBinaryFile(const std::string& inFolder, bool appendOutName)
{
fs::path filepath(inFolder);
if (appendOutName)
filepath = filepath / (outName + "." + GetExternalExtension());
data = DiskFile::ReadAllBytes(filepath.string());
// Add padding.
data.insert(data.end(), GetRawDataSize() - data.size(), 0x00);
CheckValidJpeg(filepath.generic_string());
}
void ZBackground::CheckValidJpeg(const std::string& filepath)
{
std::string filename = outName;
if (filepath != "")
{
filename = filepath;
}
uint32_t jpegMarker = BitConverter::ToUInt32BE(data, 0);
if (jpegMarker != JPEG_MARKER)
{
HANDLE_WARNING_PROCESS(
WarningType::InvalidJPEG,
StringHelper::Sprintf("missing jpeg marker at beginning of file: '%s'",
filename.c_str()),
"The game will skip this jpeg.");
}
if (data.at(6) != 'J' || data.at(7) != 'F' || data.at(8) != 'I' || data.at(9) != 'F' ||
data.at(10) != '\0')
{
std::string jfifIdentifier(data.begin() + 6, data.begin() + 6 + 5);
HANDLE_WARNING_PROCESS(
WarningType::InvalidJPEG, "missing 'JFIF' identifier",
StringHelper::Sprintf(
"This image may be corrupted, or not a jpeg. The identifier found was: '%s'",
jfifIdentifier.c_str()));
}
uint8_t majorVersion = data.at(11);
uint8_t minorVersion = data.at(12);
if (majorVersion != 0x01 || minorVersion != 0x01)
{
HANDLE_WARNING_PROCESS(
WarningType::InvalidJPEG,
StringHelper::Sprintf("wrong JFIF version '%i.%02i'", majorVersion, minorVersion),
"The expected version is '1.01'. The game may be unable to decode this image "
"correctly.");
}
if (BitConverter::ToUInt16BE(data, 20) != MARKER_DQT)
{
// This may happen when creating a custom image with Exif, XMP, thumbnail, progressive, etc.
// enabled.
HANDLE_WARNING_PROCESS(WarningType::InvalidJPEG,
"there seems to be extra data before the image data in this file",
"The game may not be able to decode this image correctly.");
}
if (data.size() > GetRawDataSize())
{
HANDLE_WARNING_PROCESS(
WarningType::InvalidJPEG, "the image is bigger than the screen buffer",
StringHelper::Sprintf("Image size: %zu bytes\nScreen buffer size: %zu bytes",
data.size(), GetRawDataSize()));
}
}
size_t ZBackground::GetRawDataSize() const
{
// Jpgs use the whole sceen buffer, which is a u16 matrix.
return Globals::Instance->cfg.bgScreenHeight * Globals::Instance->cfg.bgScreenWidth * 2;
}
Declaration* ZBackground::DeclareVar(const std::string& prefix,
[[maybe_unused]] const std::string& bodyStr)
{
std::string auxName = name;
std::string auxOutName = outName;
if (auxName == "")
auxName = GetDefaultName(prefix);
if (auxOutName == "")
auxOutName = GetDefaultName(prefix);
auto filepath = Globals::Instance->outputPath / fs::path(auxOutName).stem();
std::string incStr =
StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), GetExternalExtension().c_str());
Declaration* decl = parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(),
GetSourceTypeName(), auxName, 0);
decl->arrayItemCntStr = "SCREEN_WIDTH * SCREEN_HEIGHT / 4";
decl->forceArrayCnt = true;
decl->staticConf = staticConf;
return decl;
}
bool ZBackground::IsExternalResource() const
{
return true;
}
std::string ZBackground::GetExternalExtension() const
{
return "jpg";
}
void ZBackground::Save(const fs::path& outFolder)
{
if (!Globals::Instance->otrMode)
{
fs::path filepath = outFolder / (outName + "." + GetExternalExtension());
DiskFile::WriteAllBytes(filepath.string(), data);
}
}
std::string ZBackground::GetBodySourceCode() const
{
std::string bodyStr = " ";
for (size_t i = 0; i < data.size() / 8; ++i)
{
bodyStr += StringHelper::Sprintf("0x%016llX, ", BitConverter::ToUInt64BE(data, i * 8));
if (i % 8 == 7)
bodyStr += "\n ";
}
bodyStr += "\n";
return bodyStr;
}
std::string ZBackground::GetDefaultName(const std::string& prefix) const
{
return StringHelper::Sprintf("%sBackground_%06X", prefix.c_str(), rawDataIndex);
}
std::string ZBackground::GetSourceTypeName() const
{
return "u64";
}
ZResourceType ZBackground::GetResourceType() const
{
return ZResourceType::Background;
}
DeclarationAlignment ZBackground::GetDeclarationAlignment() const
{
return DeclarationAlignment::Align8;
}

34
ZAPDTR/ZAPD/ZBackground.h Normal file
View File

@@ -0,0 +1,34 @@
#pragma once
#include <cstdint>
#include <vector>
#include "ZResource.h"
class ZBackground : public ZResource
{
protected:
std::vector<uint8_t> data;
public:
ZBackground(ZFile* nParent);
void ParseBinaryFile(const std::string& inFolder, bool appendOutName);
void ParseRawData() override;
Declaration* DeclareVar(const std::string& prefix, const std::string& bodyStr) override;
std::string GetBodySourceCode() const override;
std::string GetDefaultName(const std::string& prefix) const override;
void Save(const fs::path& outFolder) override;
bool IsExternalResource() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
std::string GetExternalExtension() const override;
size_t GetRawDataSize() const override;
DeclarationAlignment GetDeclarationAlignment() const override;
void CheckValidJpeg(const std::string& filepath);
};

116
ZAPDTR/ZAPD/ZBlob.cpp Normal file
View File

@@ -0,0 +1,116 @@
#include "ZBlob.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include <Utils/DiskFile.h>
#include "Utils/Path.h"
#include "Utils/StringHelper.h"
#include "ZFile.h"
REGISTER_ZFILENODE(Blob, ZBlob);
ZBlob::ZBlob(ZFile* nParent) : ZResource(nParent)
{
genOTRDef = true;
RegisterRequiredAttribute("Size");
}
ZBlob* ZBlob::FromFile(const std::string& filePath)
{
ZBlob* blob = new ZBlob(nullptr);
blob->name = StringHelper::Split(Path::GetFileNameWithoutExtension(filePath), ".")[0];
blob->blobData = DiskFile::ReadAllBytes(filePath);
return blob;
}
void ZBlob::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
blobSize = StringHelper::StrToL(registeredAttributes.at("Size").value, 16);
}
void ZBlob::ParseRawData()
{
blobData.assign(parent->GetRawData().begin() + rawDataIndex,
parent->GetRawData().begin() + rawDataIndex + blobSize);
}
Declaration* ZBlob::DeclareVar(const std::string& prefix,
[[maybe_unused]] const std::string& bodyStr)
{
std::string auxName = name;
std::string auxOutName = outName;
if (auxName == "")
auxName = GetDefaultName(prefix);
if (auxOutName == "")
auxOutName = GetDefaultName(prefix);
std::string path = Path::GetFileNameWithoutExtension(auxOutName);
std::string assetOutDir =
(Globals::Instance->outputPath / Path::GetFileNameWithoutExtension(GetOutName())).string();
std::string incStr =
StringHelper::Sprintf("%s.%s.inc.c", assetOutDir.c_str(), GetExternalExtension().c_str());
return parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(),
GetSourceTypeName(), auxName, blobData.size());
}
std::string ZBlob::GetBodySourceCode() const
{
std::string sourceOutput;
for (size_t i = 0; i < blobData.size(); i += 1)
{
if (i % 16 == 0)
sourceOutput += "\t";
sourceOutput += StringHelper::Sprintf("0x%02X, ", blobData[i]);
if (i % 16 == 15)
sourceOutput += "\n";
}
// Ensure there's always a trailing line feed to prevent dumb warnings.
// Please don't remove this line, unless you somehow made a way to prevent
// that warning when building the OoT repo.
sourceOutput += "\n";
return sourceOutput;
}
void ZBlob::Save(const fs::path& outFolder)
{
if (!Globals::Instance->otrMode)
DiskFile::WriteAllBytes((outFolder / (name + ".bin")).string(), blobData);
}
bool ZBlob::IsExternalResource() const
{
return true;
}
std::string ZBlob::GetExternalExtension() const
{
return "bin";
}
std::string ZBlob::GetSourceTypeName() const
{
return "u8";
}
ZResourceType ZBlob::GetResourceType() const
{
return ZResourceType::Blob;
}
size_t ZBlob::GetRawDataSize() const
{
return blobSize;
}

31
ZAPDTR/ZAPD/ZBlob.h Normal file
View File

@@ -0,0 +1,31 @@
#pragma once
#include "ZResource.h"
#include "tinyxml2.h"
class ZBlob : public ZResource
{
public:
ZBlob(ZFile* nParent);
static ZBlob* FromFile(const std::string& filePath);
void ParseXML(tinyxml2::XMLElement* reader) override;
void ParseRawData() override;
Declaration* DeclareVar(const std::string& prefix, const std::string& bodyStr) override;
std::string GetBodySourceCode() const override;
void Save(const fs::path& outFolder) override;
bool IsExternalResource() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
std::string GetExternalExtension() const override;
size_t GetRawDataSize() const override;
protected:
std::vector<uint8_t> blobData;
size_t blobSize = 0;
};

307
ZAPDTR/ZAPD/ZCKeyFrame.cpp Normal file
View File

@@ -0,0 +1,307 @@
#include "ZCKeyFrame.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
#include "WarningHandler.h"
REGISTER_ZFILENODE(KeyFrameSkel, ZKeyFrameSkel);
REGISTER_ZFILENODE(KeyFrameLimbList, ZKeyFrameLimbList);
ZKeyFrameSkel::ZKeyFrameSkel(ZFile* nParent) : ZResource(nParent)
{
RegisterRequiredAttribute("LimbType");
genOTRDef = true;
}
ZKeyFrameSkel::~ZKeyFrameSkel()
{
}
ZKeyFrameLimb::ZKeyFrameLimb(ZFile* nParent) : ZResource(nParent)
{
}
ZKeyFrameStandardLimb::ZKeyFrameStandardLimb(ZFile* nParent) : ZKeyFrameLimb(nParent)
{
}
ZKeyFrameFlexLimb::ZKeyFrameFlexLimb(ZFile* nParent) : ZKeyFrameLimb(nParent)
{
}
ZKeyFrameLimbList::ZKeyFrameLimbList(ZFile* nParent) : ZResource(nParent)
{
RegisterRequiredAttribute("LimbType");
RegisterRequiredAttribute("LimbCount");
}
ZKeyFrameLimbList::ZKeyFrameLimbList(ZFile* nParent, uint32_t limbCount, ZKeyframeSkelType type)
: ZResource(nParent)
{
numLimbs = limbCount;
limbType = type;
}
ZKeyFrameLimbList::~ZKeyFrameLimbList()
{
for (const auto l : limbs)
delete l;
}
void ZKeyFrameSkel::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
std::string limbTypeStr = registeredAttributes.at("LimbType").value;
limbType = ZKeyFrameLimbList::ParseLimbTypeStr(limbTypeStr);
if (limbType == ZKeyframeSkelType::Error)
HANDLE_ERROR_RESOURCE(
WarningType::InvalidXML, parent, this, rawDataIndex, "Invalid limb type",
StringHelper::Sprintf("Invalid limb type. Was expecting 'Flex' or 'Normal'. Got %s.",
limbTypeStr.c_str()));
}
void ZKeyFrameLimbList::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
std::string limbTypeStr = registeredAttributes.at("LimbType").value;
std::string numLimbStr = registeredAttributes.at("LimbCount").value;
limbType = ParseLimbTypeStr(limbTypeStr);
if (limbType == ZKeyframeSkelType::Error)
HANDLE_ERROR_RESOURCE(
WarningType::InvalidXML, parent, this, rawDataIndex, "Invalid limb type",
StringHelper::Sprintf("Invalid limb type. Was expecting 'Flex' or 'Normal'. Got %s.",
limbTypeStr.c_str()));
numLimbs = (uint8_t)StringHelper::StrToL(numLimbStr);
}
void ZKeyFrameSkel::ParseRawData()
{
ZResource::ParseRawData();
const auto& rawData = parent->GetRawData();
limbCount = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0);
dListCount = BitConverter::ToUInt8BE(rawData, rawDataIndex + 1);
limbsPtr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 4);
limbList = std::make_unique<ZKeyFrameLimbList>(parent, limbCount, limbType);
limbList->SetRawDataIndex(GETSEGOFFSET(limbsPtr));
limbList->ParseRawData();
}
void ZKeyFrameSkel::DeclareReferences(const std::string& prefix)
{
std::string defaultPrefix = name;
std::string declaration;
if (defaultPrefix == "")
defaultPrefix = prefix;
ZResource::DeclareReferences(defaultPrefix);
declaration += limbList->GetBodySourceCode();
parent->AddDeclarationArray(
GETSEGOFFSET(limbsPtr), DeclarationAlignment::Align4, limbList->GetRawDataSize(),
limbList->GetSourceTypeName(),
StringHelper::Sprintf("%s_KeyFrameLimbs_%06X", prefix.c_str(), rawDataIndex),
limbList->limbs.size(), declaration);
}
std::string ZKeyFrameSkel::GetBodySourceCode() const
{
std::string limbStr;
if (limbType == ZKeyframeSkelType::Normal)
Globals::Instance->GetSegmentedPtrName(limbsPtr, parent, "KeyFrameStandardLimb", limbStr,
parent->workerID);
else
Globals::Instance->GetSegmentedPtrName(limbsPtr, parent, "KeyFrameFlexLimb", limbStr,
parent->workerID);
return StringHelper::Sprintf("\n\t0x%02X, 0x%02X, %s\n", limbCount, dListCount,
limbStr.c_str());
}
size_t ZKeyFrameSkel::GetRawDataSize() const
{
return 0x8;
}
std::string ZKeyFrameSkel::GetSourceTypeName() const
{
return "KeyFrameSkeleton";
}
ZResourceType ZKeyFrameSkel::GetResourceType() const
{
return ZResourceType::KeyFrameSkel;
}
size_t ZKeyFrameStandardLimb::GetRawDataSize() const
{
return 0xC;
}
size_t ZKeyFrameFlexLimb::GetRawDataSize() const
{
return 0x8;
}
size_t ZKeyFrameLimbList::GetRawDataSize() const
{
size_t limbSize;
if (limbType == ZKeyframeSkelType::Flex)
limbSize = 0x8;
else
limbSize = 0xC;
return limbSize * numLimbs;
}
ZKeyframeSkelType ZKeyFrameLimbList::ParseLimbTypeStr(const std::string& typeStr)
{
if (typeStr == "Flex")
return ZKeyframeSkelType::Flex;
else if (typeStr == "Normal")
return ZKeyframeSkelType::Normal;
else
return ZKeyframeSkelType::Error;
}
void ZKeyFrameLimb::ParseRawData()
{
const auto& rawData = parent->GetRawData();
dlist = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x0);
numChildren = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x4);
flags = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x5);
}
void ZKeyFrameStandardLimb::ParseRawData()
{
const auto& rawData = parent->GetRawData();
ZKeyFrameLimb::ParseRawData();
translation.x = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x6);
translation.y = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x8);
translation.z = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0xA);
}
void ZKeyFrameFlexLimb::ParseRawData()
{
const auto& rawData = parent->GetRawData();
ZKeyFrameLimb::ParseRawData();
callbackIndex = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0x6);
}
void ZKeyFrameLimbList::ParseRawData()
{
limbs.reserve(numLimbs);
rawDataIndex = GetRawDataIndex();
for (uint32_t i = 0; i < numLimbs; i++)
{
ZKeyFrameLimb* limb;
if (limbType == ZKeyframeSkelType::Flex)
limb = new ZKeyFrameFlexLimb(parent);
else
limb = new ZKeyFrameStandardLimb(parent);
limb->SetRawDataIndex(rawDataIndex + (offset_t)(i * limb->GetRawDataSize()));
limb->ParseRawData();
limbs.push_back(limb);
}
}
std::string ZKeyFrameLimbList::GetBodySourceCode() const
{
std::string declaration;
for (const auto l : limbs)
declaration += StringHelper::Sprintf("\t{ %s },\n", l->GetBodySourceCode().c_str());
// Remove last newline
return declaration.substr(0, declaration.length() - 1);
}
std::string ZKeyFrameStandardLimb::GetBodySourceCode() const
{
std::string declaration;
std::string dlString;
Globals::Instance->GetSegmentedArrayIndexedName(dlist, 8, parent, "Gfx", dlString,
parent->workerID);
declaration +=
StringHelper::Sprintf("%s, 0x%02X, 0x%02X, { 0x%04X, 0x%04X, 0x%04X},", dlString.c_str(),
numChildren, flags, translation.x, translation.y, translation.z);
return declaration;
}
std::string ZKeyFrameFlexLimb::GetBodySourceCode() const
{
std::string declaration;
std::string dlString;
Globals::Instance->GetSegmentedArrayIndexedName(dlist, 8, parent, "Gfx", dlString,
parent->workerID);
declaration += StringHelper::Sprintf("%s, 0x%02X, 0x%02X, 0x%02X", dlString.c_str(),
numChildren, flags, callbackIndex);
return declaration;
}
std::string ZKeyFrameStandardLimb::GetSourceTypeName() const
{
return "KeyFrameStandardLimb";
}
std::string ZKeyFrameFlexLimb::GetSourceTypeName() const
{
return "KeyFrameFlexLimb";
}
std::string ZKeyFrameLimbList::GetSourceTypeName() const
{
switch (limbType)
{
case ZKeyframeSkelType::Flex:
return "KeyFrameFlexLimb";
case ZKeyframeSkelType::Normal:
return "KeyFrameStandardLimb";
default:
HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex,
"Invalid limb type", "");
break;
}
}
ZResourceType ZKeyFrameStandardLimb::GetResourceType() const
{
return ZResourceType::KeyFrameStandardLimb;
}
ZResourceType ZKeyFrameFlexLimb::GetResourceType() const
{
return ZResourceType::KeyFrameFlexLimb;
}
ZResourceType ZKeyFrameLimbList::GetResourceType() const
{
switch (limbType)
{
case ZKeyframeSkelType::Flex:
return ZResourceType::KeyFrameFlexLimb;
case ZKeyframeSkelType::Normal:
return ZResourceType::KeyFrameStandardLimb;
default:
HANDLE_ERROR_RESOURCE(WarningType::InvalidXML, parent, this, rawDataIndex,
"Invalid limb type", "");
break;
}
}

121
ZAPDTR/ZAPD/ZCKeyFrame.h Normal file
View File

@@ -0,0 +1,121 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <memory>
#include "ZFile.h"
class ZKeyFrameLimb;
struct Vec3s
{
int16_t x;
int16_t y;
int16_t z;
};
enum class ZKeyframeSkelType
{
Normal,
Flex,
Error,
};
class ZKeyFrameLimbList : public ZResource
{
public:
ZKeyFrameLimbList();
ZKeyFrameLimbList(ZFile* nParent);
ZKeyFrameLimbList(ZFile* nParent, uint32_t limbCount, ZKeyframeSkelType type);
~ZKeyFrameLimbList();
void ParseRawData() override;
std::string GetBodySourceCode() const override;
void ParseXML(tinyxml2::XMLElement* reader) override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
static ZKeyframeSkelType ParseLimbTypeStr(const std::string& typeStr);
std::vector<ZKeyFrameLimb*> limbs;
ZKeyframeSkelType limbType;
uint8_t numLimbs;
};
class ZKeyFrameLimb : public ZResource
{
public:
segptr_t dlist;
uint8_t numChildren;
uint8_t flags;
ZKeyFrameLimb(ZFile* nParent);
void ParseRawData() override;
};
class ZKeyFrameStandardLimb : public ZKeyFrameLimb
{
public:
Vec3s translation;
ZKeyFrameStandardLimb(ZFile* nParent);
void ParseRawData() override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
};
class ZKeyFrameFlexLimb : public ZKeyFrameLimb
{
public:
uint8_t callbackIndex;
ZKeyFrameFlexLimb(ZFile* nParent);
// void ParseXML(tinyxml2::XMLElement* reader) override;
void ParseRawData() override;
std::string GetBodySourceCode() const override;
// std::string GetSourceOutputHeader(const std::string& prefix) override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
};
class ZKeyFrameSkel : public ZResource
{
public:
std::unique_ptr<ZKeyFrameLimbList> limbList;
segptr_t limbsPtr;
ZKeyframeSkelType limbType;
uint8_t limbCount;
uint8_t dListCount;
ZKeyFrameSkel(ZFile* nParent);
~ZKeyFrameSkel();
void ParseXML(tinyxml2::XMLElement* reader) override;
void ParseRawData() override;
void DeclareReferences(const std::string& prefix) override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
};

View File

@@ -0,0 +1,221 @@
#include "ZCkeyFrameAnim.h"
#include "ZCKeyFrame.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
REGISTER_ZFILENODE(KeyFrameAnimation, ZKeyFrameAnim);
ZKeyFrameAnim::ZKeyFrameAnim(ZFile* nParent) : ZResource(nParent)
{
RegisterRequiredAttribute("Skel");
genOTRDef = true;
}
ZKeyFrameAnim::~ZKeyFrameAnim()
{
}
void ZKeyFrameAnim::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
std::string skelAddrStr = registeredAttributes.at("Skel").value;
skelOffset = (offset_t)StringHelper::StrToL(skelAddrStr, 16);
}
void ZKeyFrameAnim::DeclareReferencesLate(const std::string& prefix)
{
std::string defaultPrefix = name;
std::string declaration;
if (defaultPrefix == "")
defaultPrefix = prefix;
ZResource::DeclareReferences(defaultPrefix);
declaration += "\t";
if (skel->limbType == ZKeyframeSkelType::Normal)
{
for (const auto b : bitFlags)
{
declaration += StringHelper::Sprintf("0x%02X, ", b);
parent->AddDeclarationArray(
GETSEGOFFSET(bitFlagsAddr), DeclarationAlignment::Align4, bitFlags.size(), "u8",
StringHelper::Sprintf("%s_bitFlags_%06X", prefix.c_str(), rawDataIndex),
bitFlags.size(), declaration);
}
}
else
{
for (const auto b : bitFlagsFlex)
{
declaration += StringHelper::Sprintf("0x%04X, ", b);
parent->AddDeclarationArray(
GETSEGOFFSET(bitFlagsAddr), DeclarationAlignment::Align4, bitFlagsFlex.size() * 2,
"u16", StringHelper::Sprintf("%s_flexBitFlags_%06X", prefix.c_str(), rawDataIndex),
bitFlagsFlex.size(), declaration);
}
}
declaration.clear();
for (const auto kf : keyFrames)
{
declaration +=
StringHelper::Sprintf(" \t { %i, %i, %i, },\n", kf.frame, kf.value, kf.velocity);
}
// Remove last new line to prevent an extra line after the last element
declaration = declaration.substr(0, declaration.length() - 1);
parent->AddDeclarationArray(
GETSEGOFFSET(keyFramesAddr), DeclarationAlignment::Align4, keyFrames.size() * 6, "KeyFrame",
StringHelper::Sprintf("%s_KeyFrame_%06X", prefix.c_str(), rawDataIndex), keyFrames.size(),
declaration);
declaration.clear();
declaration += "\t";
for (const auto kfNum : kfNums)
{
declaration += StringHelper::Sprintf("0x%04X, ", kfNum);
}
parent->AddDeclarationArray(
GETSEGOFFSET(kfNumsAddr), DeclarationAlignment::Align4, kfNums.size() * 2, "s16",
StringHelper::Sprintf("%s_kfNums_%06X", prefix.c_str(), rawDataIndex), kfNums.size(),
declaration);
declaration += "\n";
declaration.clear();
declaration += "\t";
for (const auto pv : presetValues)
{
declaration += StringHelper::Sprintf("0x%04X, ", pv);
}
declaration += "\n";
parent->AddDeclarationArray(
GETSEGOFFSET(presentValuesAddr), DeclarationAlignment::Align4, presetValues.size() * 2,
"s16", StringHelper::Sprintf("%s_presetValues_%06X", prefix.c_str(), rawDataIndex),
presetValues.size(), declaration);
}
// ParseRawDataLate is used because we need to make sure the flex skel has been processed first.
void ZKeyFrameAnim::ParseRawDataLate()
{
const auto& rawData = parent->GetRawData();
skel = static_cast<ZKeyFrameSkel*>(parent->FindResource(skelOffset));
size_t numLimbs = skel->limbCount;
bitFlagsAddr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x0);
keyFramesAddr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x4);
kfNumsAddr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x8);
presentValuesAddr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0xC);
uint32_t kfNumsSize = 0;
uint32_t presetValuesSize = 0;
uint32_t keyFramesCount = 0;
if (skel->limbType == ZKeyframeSkelType::Normal)
{
bitFlags.reserve(numLimbs);
for (size_t i = 0; i < numLimbs; i++)
{
uint8_t e = BitConverter::ToUInt8BE(rawData, GETSEGOFFSET(bitFlagsAddr) + i);
bitFlags.push_back(e);
kfNumsSize += GetSetBits((uint8_t)(e & 0b111111));
presetValuesSize += GetSetBits((uint8_t)((e ^ 0xFF) & 0b111111));
}
}
else
{
bitFlagsFlex.reserve(numLimbs);
for (size_t i = 0; i < numLimbs; i++)
{
uint16_t e = BitConverter::ToUInt16BE(rawData, GETSEGOFFSET(bitFlagsAddr) + (i * 2));
bitFlagsFlex.push_back(e);
kfNumsSize += GetSetBits((uint16_t)(e & 0b111111111));
presetValuesSize += GetSetBits((uint16_t)((e ^ 0xFFFF) & 0b111111111));
}
}
kfNums.reserve(kfNumsSize);
for (uint32_t i = 0; i < kfNumsSize; i++)
{
int16_t kfNum = BitConverter::ToUInt16BE(rawData, GETSEGOFFSET(kfNumsAddr) + (i * 2));
keyFramesCount += kfNum;
kfNums.push_back(kfNum);
}
keyFrames.reserve(keyFramesCount);
for (uint32_t i = 0; i < keyFramesCount; i++)
{
KeyFrame kf;
kf.frame = BitConverter::ToInt16BE(rawData, (GETSEGOFFSET(keyFramesAddr) + 0) + (i * 6));
kf.value = BitConverter::ToInt16BE(rawData, (GETSEGOFFSET(keyFramesAddr) + 2) + (i * 6));
kf.velocity = BitConverter::ToInt16BE(rawData, (GETSEGOFFSET(keyFramesAddr) + 4) + (i * 6));
keyFrames.push_back(kf);
}
presetValues.reserve(presetValuesSize);
for (uint32_t i = 0; i < presetValuesSize; i++)
{
presetValues.push_back(
BitConverter::ToInt16BE(rawData, GETSEGOFFSET(presentValuesAddr) + (i * 2)));
}
unk_10 = BitConverter::ToInt16BE(rawData, GETSEGOFFSET(rawDataIndex) + 0x10);
duration = BitConverter::ToInt16BE(rawData, GETSEGOFFSET(rawDataIndex) + 0x12);
}
std::string ZKeyFrameAnim::GetBodySourceCode() const
{
std::string declaration;
std::string bitFlagsStr;
std::string keyFrameStr;
std::string kfNumsStr;
std::string presetValuesStr;
Globals::Instance->GetSegmentedPtrName(bitFlagsAddr, parent, "", bitFlagsStr, parent->workerID);
Globals::Instance->GetSegmentedPtrName(keyFramesAddr, parent, "", keyFrameStr, parent->workerID);
Globals::Instance->GetSegmentedPtrName(kfNumsAddr, parent, "", kfNumsStr, parent->workerID);
Globals::Instance->GetSegmentedPtrName(presentValuesAddr, parent, "", presetValuesStr,
parent->workerID);
return StringHelper::Sprintf("\n\t%s, %s, %s, %s, 0x%04X, 0x%04X\n", bitFlagsStr.c_str(),
keyFrameStr.c_str(), kfNumsStr.c_str(), presetValuesStr.c_str(),
unk_10, duration);
}
std::string ZKeyFrameAnim::GetSourceTypeName() const
{
return "KeyFrameAnimation";
}
ZResourceType ZKeyFrameAnim::GetResourceType() const
{
return ZResourceType::KeyFrameAnimation;
}
size_t ZKeyFrameAnim::GetRawDataSize() const
{
return 0x14;
}
template <typename T>
uint32_t ZKeyFrameAnim::GetSetBits(T data) const
{
uint32_t num = 0;
for (size_t i = 0; i < sizeof(T) * 8; i++)
{
if ((data >> i) & 1)
num++;
}
return num;
}

View File

@@ -0,0 +1,52 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include <memory>
#include "ZFile.h"
class ZKeyFrameSkel;
typedef struct
{
int16_t frame;
int16_t value;
int16_t velocity;
} KeyFrame;
class ZKeyFrameAnim : public ZResource
{
public:
ZKeyFrameSkel* skel;
std::vector<uint8_t> bitFlags; // Standard only
std::vector<uint16_t> bitFlagsFlex; // Flex only
std::vector<KeyFrame> keyFrames;
std::vector<int16_t> kfNums;
std::vector<int16_t> presetValues;
uint16_t unk_10;
int16_t duration;
ZKeyFrameAnim(ZFile* nParent);
~ZKeyFrameAnim();
void ParseXML(tinyxml2::XMLElement* reader) override;
void DeclareReferencesLate(const std::string& prefix) override;
void ParseRawDataLate() override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
private:
offset_t skelOffset;
segptr_t bitFlagsAddr;
segptr_t keyFramesAddr;
segptr_t kfNumsAddr;
segptr_t presentValuesAddr;
template <typename T>
uint32_t GetSetBits(T data) const;
};

400
ZAPDTR/ZAPD/ZCollision.cpp Normal file
View File

@@ -0,0 +1,400 @@
#include "ZCollision.h"
#include <cassert>
#include <cstdint>
#include <string>
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
REGISTER_ZFILENODE(Collision, ZCollisionHeader);
ZCollisionHeader::ZCollisionHeader(ZFile* nParent) : ZResource(nParent)
{
genOTRDef = true;
}
ZCollisionHeader::~ZCollisionHeader()
{
delete camData;
}
void ZCollisionHeader::ParseRawData()
{
const auto& rawData = parent->GetRawData();
absMinX = BitConverter::ToInt16BE(rawData, rawDataIndex + 0);
absMinY = BitConverter::ToInt16BE(rawData, rawDataIndex + 2);
absMinZ = BitConverter::ToInt16BE(rawData, rawDataIndex + 4);
absMaxX = BitConverter::ToInt16BE(rawData, rawDataIndex + 6);
absMaxY = BitConverter::ToInt16BE(rawData, rawDataIndex + 8);
absMaxZ = BitConverter::ToInt16BE(rawData, rawDataIndex + 10);
numVerts = BitConverter::ToUInt16BE(rawData, rawDataIndex + 12);
vtxAddress = BitConverter::ToInt32BE(rawData, rawDataIndex + 16);
numPolygons = BitConverter::ToUInt16BE(rawData, rawDataIndex + 20);
polyAddress = BitConverter::ToInt32BE(rawData, rawDataIndex + 24);
polyTypeDefAddress = BitConverter::ToInt32BE(rawData, rawDataIndex + 28);
camDataAddress = BitConverter::ToInt32BE(rawData, rawDataIndex + 32);
numWaterBoxes = BitConverter::ToUInt16BE(rawData, rawDataIndex + 36);
waterBoxAddress = BitConverter::ToInt32BE(rawData, rawDataIndex + 40);
vtxSegmentOffset = Seg2Filespace(vtxAddress, parent->baseAddress);
polySegmentOffset = Seg2Filespace(polyAddress, parent->baseAddress);
polyTypeDefSegmentOffset = Seg2Filespace(polyTypeDefAddress, parent->baseAddress);
camDataSegmentOffset = Seg2Filespace(camDataAddress, parent->baseAddress);
waterBoxSegmentOffset = Seg2Filespace(waterBoxAddress, parent->baseAddress);
vertices.reserve(numVerts);
polygons.reserve(numPolygons);
offset_t currentPtr = vtxSegmentOffset;
for (uint16_t i = 0; i < numVerts; i++)
{
ZVector vec(parent);
vec.ExtractFromBinary(currentPtr, ZScalarType::ZSCALAR_S16, 3);
currentPtr += vec.GetRawDataSize();
vertices.push_back(vec);
}
for (uint16_t i = 0; i < numPolygons; i++)
{
ZCollisionPoly poly(parent);
poly.SetRawDataIndex(polySegmentOffset + (i * 16));
poly.ParseRawData();
polygons.push_back(poly);
}
uint16_t highestPolyType = 0;
for (const ZCollisionPoly& poly : polygons)
{
if (poly.type > highestPolyType)
highestPolyType = poly.type;
}
for (uint16_t i = 0; i < highestPolyType + 1; i++)
{
ZSurfaceType surfaceType(parent);
surfaceType.SetRawDataIndex(polyTypeDefSegmentOffset + (i * 8));
surfaceType.ParseRawData();
PolygonTypes.push_back(surfaceType);
}
// polygonTypes.push_back(
// BitConverter::ToUInt64BE(rawData, polyTypeDefSegmentOffset + (i * 8)));
if (camDataAddress != SEGMENTED_NULL)
{
// Try to guess how many elements the CamDataList array has.
// The "guessing algorithm" is basically a "best effort" one and it
// is error-prone.
// This is based mostly on observation of how CollisionHeader data is
// usually ordered. If for some reason the data was in some other funny
// order, this would probably break.
// The most common ordering is:
// - *CamData*
// - SurfaceType
// - CollisionPoly
// - Vertices
// - WaterBoxes
// - CollisionHeader
offset_t upperCameraBoundary = polyTypeDefSegmentOffset;
if (upperCameraBoundary == 0)
{
upperCameraBoundary = polySegmentOffset;
}
if (upperCameraBoundary == 0)
{
upperCameraBoundary = vtxSegmentOffset;
}
if (upperCameraBoundary == 0)
{
upperCameraBoundary = waterBoxSegmentOffset;
}
if (upperCameraBoundary == 0)
{
upperCameraBoundary = rawDataIndex;
}
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))));
}
void ZCollisionHeader::DeclareReferences(const std::string& prefix)
{
std::string declaration = "";
std::string auxName = name;
if (name == "")
auxName = GetDefaultName(prefix);
if (waterBoxes.size() > 0)
{
if (!Globals::Instance->otrMode)
{
for (size_t i = 0; i < waterBoxes.size(); i++)
{
declaration +=
StringHelper::Sprintf("\t{ %s },", waterBoxes[i].GetBodySourceCode().c_str());
if (i + 1 < waterBoxes.size())
declaration += "\n";
}
}
parent->AddDeclarationArray(
waterBoxSegmentOffset, DeclarationAlignment::Align4, 16 * waterBoxes.size(), "WaterBox",
StringHelper::Sprintf("%sWaterBoxes", auxName.c_str()), waterBoxes.size(), declaration);
}
if (polygons.size() > 0)
{
declaration.clear();
if (!Globals::Instance->otrMode)
{
for (size_t i = 0; i < polygons.size(); i++)
{
declaration +=
StringHelper::Sprintf("\t%s,", polygons[i].GetBodySourceCode().c_str());
if (i + 1 < polygons.size())
declaration += "\n";
}
}
parent->AddDeclarationArray(polySegmentOffset, DeclarationAlignment::Align4,
polygons.size() * 16, polygons[0].GetSourceTypeName().c_str(),
StringHelper::Sprintf("%sPolygons", auxName.c_str()),
polygons.size(), declaration);
}
declaration.clear();
for (const auto& polyType : PolygonTypes)
{
declaration += StringHelper::Sprintf("\t%s,", polyType.GetBodySourceCode().c_str());
}
if (polyTypeDefAddress != SEGMENTED_NULL)
parent->AddDeclarationArray(polyTypeDefSegmentOffset, DeclarationAlignment::Align4,
PolygonTypes.size() * 8,
PolygonTypes[0].GetSourceTypeName().c_str(),
StringHelper::Sprintf("%sSurfaceType", auxName.c_str()),
PolygonTypes.size(), declaration);
declaration.clear();
if (vertices.size() > 0)
{
declaration.clear();
if (!Globals::Instance->otrMode)
{
for (size_t i = 0; i < vertices.size(); i++)
{
declaration +=
StringHelper::Sprintf("\t{ %s },", vertices[i].GetBodySourceCode().c_str());
if (i < vertices.size() - 1)
declaration += "\n";
}
}
const auto& first = vertices.front();
if (vtxAddress != 0)
parent->AddDeclarationArray(
vtxSegmentOffset, first.GetDeclarationAlignment(),
vertices.size() * first.GetRawDataSize(), first.GetSourceTypeName(),
StringHelper::Sprintf("%sVertices", auxName.c_str()), vertices.size(), declaration);
}
}
std::string ZCollisionHeader::GetBodySourceCode() const
{
std::string declaration = "";
if (Globals::Instance->otrMode)
return declaration;
declaration += "\n";
declaration += StringHelper::Sprintf("\t{ %i, %i, %i },\n", absMinX, absMinY, absMinZ);
declaration += StringHelper::Sprintf("\t{ %i, %i, %i },\n", absMaxX, absMaxY, absMaxZ);
std::string vtxName;
Globals::Instance->GetSegmentedPtrName(vtxAddress, parent, "Vec3s", vtxName, parent->workerID);
declaration += StringHelper::Sprintf("\t%i,\n\t%s,\n", numVerts, vtxName.c_str());
std::string polyName;
Globals::Instance->GetSegmentedPtrName(polyAddress, parent, "CollisionPoly", polyName,
parent->workerID);
declaration += StringHelper::Sprintf("\t%i,\n\t%s,\n", numPolygons, polyName.c_str());
std::string surfaceName;
Globals::Instance->GetSegmentedPtrName(polyTypeDefAddress, parent, "SurfaceType", surfaceName,
parent->workerID);
declaration += StringHelper::Sprintf("\t%s,\n", surfaceName.c_str());
std::string camName;
Globals::Instance->GetSegmentedPtrName(camDataAddress, parent, "CamData", camName,
parent->workerID);
declaration += StringHelper::Sprintf("\t%s,\n", camName.c_str());
std::string waterBoxName;
Globals::Instance->GetSegmentedPtrName(waterBoxAddress, parent, "WaterBox", waterBoxName,
parent->workerID);
declaration += StringHelper::Sprintf("\t%i,\n\t%s\n", numWaterBoxes, waterBoxName.c_str());
return declaration;
}
std::string ZCollisionHeader::GetDefaultName(const std::string& prefix) const
{
return StringHelper::Sprintf("%sCol_%06X", prefix.c_str(), rawDataIndex);
}
std::string ZCollisionHeader::GetSourceTypeName() const
{
return "CollisionHeader";
}
ZResourceType ZCollisionHeader::GetResourceType() const
{
return ZResourceType::CollisionHeader;
}
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)
{
std::string declaration;
// Parse CameraDataEntries
size_t numElements = (upperCameraBoundary - rawDataIndex) / 8;
assert(numElements < 10000);
offset_t cameraPosDataSeg = rawDataIndex;
for (size_t i = 0; i < numElements; i++)
{
CameraDataEntry* entry = new CameraDataEntry();
entry->cameraSType =
BitConverter::ToInt16BE(rawData, rawDataIndex + (entries.size() * 8) + 0);
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)
{
cameraPosDataSeg = rawDataIndex + (entries.size() * 8);
break;
}
if (entry->cameraPosDataSeg != 0 && cameraPosDataSeg > (entry->cameraPosDataSeg & 0xFFFFFF))
cameraPosDataSeg = (entry->cameraPosDataSeg & 0xFFFFFF);
entries.push_back(entry);
}
// Setting cameraPosDataAddr to rawDataIndex give a pos list length of 0
uint32_t cameraPosDataOffset = cameraPosDataSeg & 0xFFFFFF;
for (size_t i = 0; i < entries.size(); i++)
{
char camSegLine[2048];
if (entries[i]->cameraPosDataSeg != 0)
{
int32_t index =
((entries[i]->cameraPosDataSeg & 0x00FFFFFF) - cameraPosDataOffset) / 0x6;
sprintf(camSegLine, "&%sCamPosData[%i]", prefix.c_str(), index);
}
else
sprintf(camSegLine, "NULL");
declaration +=
StringHelper::Sprintf(" { 0x%04X, %i, %s },", entries[i]->cameraSType,
entries[i]->numData, camSegLine, rawDataIndex + (i * 8));
if (i < entries.size() - 1)
declaration += "\n";
}
parent->AddDeclarationArray(
rawDataIndex, DeclarationAlignment::Align4, entries.size() * 8, "CamData",
StringHelper::Sprintf("%sCamDataList", prefix.c_str(), rawDataIndex), entries.size(),
declaration);
uint32_t numDataTotal = (rawDataIndex - cameraPosDataOffset) / 0x6;
if (numDataTotal > 0)
{
declaration.clear();
for (uint32_t i = 0; i < numDataTotal; i++)
{
CameraPositionData* data =
new CameraPositionData(rawData, cameraPosDataOffset + (i * 6));
cameraPositionData.push_back(data);
declaration += StringHelper::Sprintf("\t{ %6i, %6i, %6i },", data->x, data->y, data->z);
if (i + 1 < numDataTotal)
declaration += "\n";
}
int32_t cameraPosDataIndex = GETSEGOFFSET(cameraPosDataSeg);
uint32_t entrySize = numDataTotal * 0x6;
parent->AddDeclarationArray(cameraPosDataIndex, DeclarationAlignment::Align4, entrySize,
"Vec3s", StringHelper::Sprintf("%sCamPosData", prefix.c_str()),
numDataTotal, declaration);
}
}
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)
{
x = BitConverter::ToInt16BE(rawData, rawDataIndex + 0);
y = BitConverter::ToInt16BE(rawData, rawDataIndex + 2);
z = BitConverter::ToInt16BE(rawData, rawDataIndex + 4);
}

90
ZAPDTR/ZAPD/ZCollision.h Normal file
View File

@@ -0,0 +1,90 @@
#pragma once
#include "ZCollisionPoly.h"
#include "ZFile.h"
#include "ZResource.h"
#include "ZRoom/ZRoom.h"
#include "ZSurfaceType.h"
#include "ZVector.h"
class WaterBoxHeader
{
public:
int16_t xMin;
int16_t ySurface;
int16_t zMin;
int16_t xLength;
int16_t zLength;
int16_t pad;
int32_t properties;
WaterBoxHeader(const std::vector<uint8_t>& rawData, uint32_t rawDataIndex);
std::string GetBodySourceCode() const;
};
class CameraPositionData
{
public:
int16_t x, y, z;
CameraPositionData(const std::vector<uint8_t>& rawData, uint32_t rawDataIndex);
};
class CameraDataEntry
{
public:
uint16_t cameraSType;
int16_t numData;
int32_t cameraPosDataSeg;
};
class CameraDataList
{
public:
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);
~CameraDataList();
};
class ZCollisionHeader : public ZResource
{
public:
int16_t absMinX, absMinY, absMinZ;
int16_t absMaxX, absMaxY, absMaxZ;
uint16_t numVerts;
segptr_t vtxAddress;
uint16_t numPolygons;
segptr_t polyAddress;
segptr_t polyTypeDefAddress;
segptr_t camDataAddress;
int32_t numWaterBoxes;
segptr_t waterBoxAddress;
uint32_t vtxSegmentOffset, polySegmentOffset, polyTypeDefSegmentOffset, camDataSegmentOffset,
waterBoxSegmentOffset;
std::vector<ZVector> vertices;
std::vector<ZCollisionPoly> polygons;
std::vector<ZSurfaceType> PolygonTypes;
std::vector<WaterBoxHeader> waterBoxes;
CameraDataList* camData = nullptr;
ZCollisionHeader(ZFile* nParent);
~ZCollisionHeader();
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;
size_t GetRawDataSize() const override;
};

View File

@@ -0,0 +1,78 @@
#include "ZCollisionPoly.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
REGISTER_ZFILENODE(CollisionPoly, ZCollisionPoly);
ZCollisionPoly::ZCollisionPoly(ZFile* nParent) : ZResource(nParent)
{
}
ZCollisionPoly::~ZCollisionPoly()
{
}
void ZCollisionPoly::ParseRawData()
{
const auto& rawData = parent->GetRawData();
type = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0);
vtxA = BitConverter::ToUInt16BE(rawData, rawDataIndex + 2);
vtxB = BitConverter::ToUInt16BE(rawData, rawDataIndex + 4);
vtxC = BitConverter::ToUInt16BE(rawData, rawDataIndex + 6);
normX = BitConverter::ToUInt16BE(rawData, rawDataIndex + 8);
normY = BitConverter::ToUInt16BE(rawData, rawDataIndex + 10);
normZ = BitConverter::ToUInt16BE(rawData, rawDataIndex + 12);
dist = BitConverter::ToUInt16BE(rawData, rawDataIndex + 14);
}
void ZCollisionPoly::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 ZCollisionPoly::GetBodySourceCode() const
{
std::string declaration;
declaration +=
StringHelper::Sprintf("{0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X}",
type, vtxA, vtxB, vtxC, normX, normY, normZ, dist);
return declaration;
}
std::string ZCollisionPoly::GetDefaultName(const std::string& prefix) const
{
return StringHelper::Sprintf("%sCollisionPoly_%06X", prefix.c_str(), rawDataIndex);
}
ZResourceType ZCollisionPoly::GetResourceType() const
{
return ZResourceType::CollisionPoly;
}
size_t ZCollisionPoly::GetRawDataSize() const
{
return 16;
}
std::string ZCollisionPoly::GetSourceTypeName() const
{
return "CollisionPoly";
}
bool ZCollisionPoly::DoesSupportArray() const
{
return true;
}

View File

@@ -0,0 +1,29 @@
#pragma once
#include "ZFile.h"
#include "ZResource.h"
class ZCollisionPoly : public ZResource
{
public:
uint16_t type;
uint16_t vtxA, vtxB, vtxC;
uint16_t normX, normY, normZ;
uint16_t dist;
ZCollisionPoly(ZFile* nParent);
~ZCollisionPoly();
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;
};

389
ZAPDTR/ZAPD/ZCutscene.cpp Normal file
View File

@@ -0,0 +1,389 @@
#include "ZCutscene.h"
#include <cassert>
#include "Globals.h"
#include "OtherStructs/CutsceneMM_Commands.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
#include "WarningHandler.h"
#include "ZResource.h"
REGISTER_ZFILENODE(Cutscene, ZCutscene);
ZCutscene::ZCutscene(ZFile* nParent) : ZResource(nParent)
{
genOTRDef = true;
}
ZCutscene::~ZCutscene()
{
for (CutsceneCommand* cmd : commands)
delete cmd;
}
std::string ZCutscene::GetBodySourceCode() const
{
std::string output = "";
output += StringHelper::Sprintf(" CS_BEGIN_CUTSCENE(%i, %i),\n", commands.size(), endFrame);
for (size_t i = 0; i < commands.size(); i++)
{
CutsceneCommand* cmd = commands[i];
output += " " + cmd->GenerateSourceCode();
}
output += StringHelper::Sprintf(" CS_END(),", commands.size(), endFrame);
return output;
}
size_t ZCutscene::GetRawDataSize() const
{
size_t size = 0;
// Beginning
size += 8;
for (size_t i = 0; i < commands.size(); i++)
{
CutsceneCommand* cmd = commands[i];
size += cmd->GetCommandSize();
}
// End
if (Globals::Instance->game == ZGame::MM_RETAIL)
{
size += 4;
}
else
{
size += 8;
}
return size;
}
void ZCutscene::ParseRawData()
{
ZResource::ParseRawData();
const auto& rawData = parent->GetRawData();
numCommands = BitConverter::ToInt32BE(rawData, rawDataIndex + 0);
commands = std::vector<CutsceneCommand*>();
endFrame = BitConverter::ToInt32BE(rawData, rawDataIndex + 4);
offset_t currentPtr = rawDataIndex + 8;
commands.reserve(numCommands);
for (int32_t i = 0; i < numCommands; i++)
{
uint32_t id = BitConverter::ToUInt32BE(rawData, currentPtr);
if (id == 0xFFFFFFFF)
break;
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
{
printf("Cutscene Command: 0x%X (%i)\n", id, id);
}
currentPtr += 4;
CutsceneCommand* cmd = nullptr;
if (Globals::Instance->game == ZGame::MM_RETAIL)
{
cmd = GetCommandMM(id, currentPtr);
}
else
{
cmd = GetCommandOoT(id, currentPtr);
}
if (cmd == nullptr)
{
HANDLE_WARNING_RESOURCE(
WarningType::NotImplemented, parent, this, rawDataIndex,
StringHelper::Sprintf("Cutscene command not implemented"),
StringHelper::Sprintf("Command ID: 0x%X\nIndex: %d\ncurrentPtr-rawDataIndex: 0x%X",
id, i, currentPtr - rawDataIndex));
cmd = new CutsceneMMCommand_NonImplemented(rawData, currentPtr);
}
assert(cmd != nullptr);
cmd->commandIndex = i;
cmd->SetCommandID(id);
size_t commmandSize = cmd->GetCommandSize();
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
{
printf("\t Command size: 0x%zX (%zu)\n", commmandSize, commmandSize);
}
currentPtr += commmandSize - 4;
commands.push_back(cmd);
}
}
CutsceneCommand* ZCutscene::GetCommandOoT(uint32_t id, offset_t currentPtr) const
{
CutsceneCommands cmdID = static_cast<CutsceneCommands>(id);
const auto& rawData = parent->GetRawData();
switch (id)
{
case 10: // CutsceneCommands::SetPlayerAction
case 15: // CutsceneCommands::SetActorAction1
case 17:
case 18:
case 23:
case 34:
case 39:
case 46:
case 76:
case 85:
case 93:
case 105:
case 107:
case 110:
case 119:
case 123:
case 138:
case 139:
case 144:
case 14: // CutsceneCommands::SetActorAction2
case 16:
case 24:
case 35:
case 40:
case 48:
case 64:
case 68:
case 70:
case 78:
case 80:
case 94:
case 116:
case 118:
case 120:
case 125:
case 131:
case 141:
case 25: // CutsceneCommands::SetActorAction3
case 36:
case 41:
case 50:
case 67:
case 69:
case 72:
case 81:
case 106:
case 117:
case 121:
case 126:
case 132:
case 29: // CutsceneCommands::SetActorAction4
case 37:
case 42:
case 51:
case 53:
case 63:
case 65:
case 66:
case 75:
case 82:
case 108:
case 127:
case 133:
case 30: // CutsceneCommands::SetActorAction5
case 38:
case 43:
case 47:
case 54:
case 79:
case 83:
case 128:
case 135:
case 44: // CutsceneCommands::SetActorAction6
case 55:
case 77:
case 84:
case 90:
case 129:
case 136:
case 31: // CutsceneCommands::SetActorAction7
case 52:
case 57:
case 58:
case 88:
case 115:
case 130:
case 137:
case 49: // CutsceneCommands::SetActorAction8
case 60:
case 89:
case 111:
case 114:
case 134:
case 142:
case 62: // CutsceneCommands::SetActorAction9
case 143: // CutsceneCommands::SetActorAction10
return new CutsceneCommand_ActorAction(rawData, currentPtr);
case 0x0B:
case 0x0D:
case 0x1A:
case 0x1B:
case 0x1C:
case 0x20:
case 0x21:
case 0x3B:
case 0x3D:
case 0x47:
case 0x49:
case 0x6D:
case 0x15:
case 0x16:
case 0x70:
case 0x71:
case 0x4A:
return new CutsceneCommand_GenericCmd(rawData, currentPtr, cmdID);
}
switch (cmdID)
{
case CutsceneCommands::Misc:
case CutsceneCommands::SetLighting:
case CutsceneCommands::PlayBGM:
case CutsceneCommands::StopBGM:
case CutsceneCommands::FadeBGM:
return new CutsceneCommand_GenericCmd(rawData, currentPtr, cmdID);
case CutsceneCommands::SetCameraPos:
case CutsceneCommands::SetCameraFocus:
case CutsceneCommands::SetCameraPosLink:
case CutsceneCommands::SetCameraFocusLink:
return new CutsceneCommandSetCameraPos(rawData, currentPtr);
case CutsceneCommands::Cmd07:
break;
case CutsceneCommands::Cmd08:
break;
case CutsceneCommands::Cmd09:
return new CutsceneCommand_Rumble(rawData, currentPtr);
case CutsceneCommands::Textbox:
return new CutsceneCommand_TextBox(rawData, currentPtr);
case CutsceneCommands::SetPlayerAction:
case CutsceneCommands::SetActorAction1:
case CutsceneCommands::SetActorAction2:
case CutsceneCommands::SetActorAction3:
case CutsceneCommands::SetActorAction4:
case CutsceneCommands::SetActorAction5:
case CutsceneCommands::SetActorAction6:
case CutsceneCommands::SetActorAction7:
case CutsceneCommands::SetActorAction8:
case CutsceneCommands::SetActorAction9:
case CutsceneCommands::SetActorAction10:
break;
case CutsceneCommands::SetSceneTransFX:
return new CutsceneCommandSceneTransFX(rawData, currentPtr);
case CutsceneCommands::SetTime:
return new CutsceneCommand_SetTime(rawData, currentPtr);
case CutsceneCommands::Terminator:
return new CutsceneCommand_Terminator(rawData, currentPtr);
}
return nullptr;
}
CutsceneCommand* ZCutscene::GetCommandMM(uint32_t id, offset_t currentPtr) const
{
CutsceneMMCommands cmdID = static_cast<CutsceneMMCommands>(id);
const auto& rawData = parent->GetRawData();
if (((id >= 100) && (id < 150)) || (id == 201) || ((id >= 450) && (id < 600)))
{
return new CutsceneCommand_ActorAction(rawData, currentPtr);
}
switch (cmdID)
{
case CutsceneMMCommands::CS_CMD_MISC:
case CutsceneMMCommands::CS_CMD_SET_LIGHTING:
case CutsceneMMCommands::CS_CMD_SCENE_TRANS_FX:
case CutsceneMMCommands::CS_CMD_MOTIONBLUR:
case CutsceneMMCommands::CS_CMD_GIVETATL:
case CutsceneMMCommands::CS_CMD_PLAYSEQ:
case CutsceneMMCommands::CS_CMD_130:
case CutsceneMMCommands::CS_CMD_131:
case CutsceneMMCommands::CS_CMD_132:
case CutsceneMMCommands::CS_CMD_STOPSEQ:
case CutsceneMMCommands::CS_CMD_PLAYAMBIENCE:
case CutsceneMMCommands::CS_CMD_FADEAMBIENCE:
case CutsceneMMCommands::CS_CMD_TERMINATOR:
case CutsceneMMCommands::CS_CMD_CHOOSE_CREDITS_SCENES:
case CutsceneMMCommands::CS_CMD_UNK_FA:
case CutsceneMMCommands::CS_CMD_UNK_FE:
case CutsceneMMCommands::CS_CMD_UNK_FF:
case CutsceneMMCommands::CS_CMD_UNK_100:
case CutsceneMMCommands::CS_CMD_UNK_101:
case CutsceneMMCommands::CS_CMD_UNK_102:
case CutsceneMMCommands::CS_CMD_UNK_103:
case CutsceneMMCommands::CS_CMD_UNK_104:
case CutsceneMMCommands::CS_CMD_UNK_105:
case CutsceneMMCommands::CS_CMD_UNK_108:
case CutsceneMMCommands::CS_CMD_UNK_109:
case CutsceneMMCommands::CS_CMD_UNK_12D:
return new CutsceneMMCommand_GenericCmd(rawData, currentPtr, cmdID);
case CutsceneMMCommands::CS_CMD_TEXTBOX:
return new CutsceneCommand_TextBox(rawData, currentPtr);
case CutsceneMMCommands::CS_CMD_CAMERA:
return new CutsceneMMCommand_Camera(rawData, currentPtr);
case CutsceneMMCommands::CS_CMD_FADESCREEN:
return new CutsceneMMCommand_FadeScreen(rawData, currentPtr);
case CutsceneMMCommands::CS_CMD_FADESEQ:
return new CutsceneMMCommand_FadeSeq(rawData, currentPtr);
case CutsceneMMCommands::CS_CMD_SETTIME:
return new CutsceneCommand_SetTime(rawData, currentPtr);
case CutsceneMMCommands::CS_CMD_SET_PLAYER_ACTION:
return new CutsceneCommand_ActorAction(rawData, currentPtr);
case CutsceneMMCommands::CS_CMD_RUMBLE:
return new CutsceneCommand_Rumble(rawData, currentPtr);
}
return nullptr;
}
Declaration* ZCutscene::DeclareVar(const std::string& prefix, const std::string& bodyStr)
{
std::string auxName = name;
if (auxName == "")
auxName = GetDefaultName(prefix);
Declaration* decl =
parent->AddDeclarationArray(rawDataIndex, GetDeclarationAlignment(), GetRawDataSize(),
GetSourceTypeName(), auxName, 0, bodyStr);
decl->staticConf = staticConf;
return decl;
}
std::string ZCutscene::GetSourceTypeName() const
{
return "CutsceneData";
}
ZResourceType ZCutscene::GetResourceType() const
{
return ZResourceType::Cutscene;
}

36
ZAPDTR/ZAPD/ZCutscene.h Normal file
View File

@@ -0,0 +1,36 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "tinyxml2.h"
#include "OtherStructs/Cutscene_Commands.h"
#include "ZFile.h"
#include "ZResource.h"
class ZCutscene : public ZResource
{
public:
ZCutscene(ZFile* nParent);
~ZCutscene();
void ParseRawData() override;
Declaration* DeclareVar(const std::string& prefix, const std::string& bodyStr) override;
std::string GetBodySourceCode() const override;
size_t GetRawDataSize() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
int32_t numCommands;
int32_t endFrame;
std::vector<CutsceneCommand*> commands;
protected:
CutsceneCommand* GetCommandOoT(uint32_t id, offset_t currentPtr) const;
CutsceneCommand* GetCommandMM(uint32_t id, offset_t currentPtr) const;
};

2254
ZAPDTR/ZAPD/ZDisplayList.cpp Normal file

File diff suppressed because it is too large Load Diff

262
ZAPDTR/ZAPD/ZDisplayList.h Normal file
View File

@@ -0,0 +1,262 @@
#pragma once
#include "ZMtx.h"
#include "ZResource.h"
#include "ZRoom/ZRoom.h"
#include "ZTexture.h"
#include "ZVtx.h"
#include "tinyxml2.h"
#include <map>
#include <string>
#include <vector>
enum class F3DEXOpcode
{
G_SPNOOP = 0x00,
G_MTX = 0x01,
G_MOVEMEM = 0x03,
G_VTX = 0x04,
G_DL = 0x06,
G_LOAD_UCODE = 0xAF,
G_BRANCH_Z = 0xB0,
G_TRI2 = 0xB1,
G_MODIFYVTX = 0xB2,
G_RDPHALF_2 = 0xB3,
G_RDPHALF_1 = 0xB4,
G_QUAD = 0xB5,
G_CLEARGEOMETRYMODE = 0xB6,
G_SETGEOMETRYMODE = 0xB7,
G_ENDDL = 0xB8,
G_SETOTHERMODE_L = 0xB9,
G_SETOTHERMODE_H = 0xBA,
G_TEXTURE = 0xBB,
G_MOVEWORD = 0xBC,
G_POPMTX = 0xBD,
G_CULLDL = 0xBE,
G_TRI1 = 0xBF,
G_NOOP = 0xC0,
G_TEXRECT = 0xE4,
G_TEXRECTFLIP = 0xE5,
G_RDPLOADSYNC = 0xE6,
G_RDPPIPESYNC = 0xE7,
G_RDPTILESYNC = 0xE8,
G_RDPFULLSYNC = 0xE9,
G_SETKEYGB = 0xEA,
G_SETKEYR = 0xEB,
G_SETCONVERT = 0xEC,
G_SETSCISSOR = 0xED,
G_SETPRIMDEPTH = 0xEE,
G_RDPSETOTHERMODE = 0xEF,
G_LOADTLUT = 0xF0,
G_SETTILESIZE = 0xF2,
G_LOADBLOCK = 0xF3,
G_LOADTILE = 0xF4,
G_SETTILE = 0xF5,
G_FILLRECT = 0xF6,
G_SETFILLCOLOR = 0xF7,
G_SETFOGCOLOR = 0xF8,
G_SETBLENDCOLOR = 0xF9,
G_SETPRIMCOLOR = 0xFA,
G_SETENVCOLOR = 0xFB,
G_SETCOMBINE = 0xFC,
G_SETTIMG = 0xFD,
G_SETZIMG = 0xFE,
G_SETCIMG = 0xFF
};
enum class F3DZEXOpcode
{
G_NOOP = 0x00,
G_VTX = 0x01,
G_MODIFYVTX = 0x02,
G_CULLDL = 0x03,
G_BRANCH_Z = 0x04,
G_TRI1 = 0x05,
G_TRI2 = 0x06,
G_QUAD = 0x07,
G_SPECIAL_3 = 0xD3,
G_SPECIAL_2 = 0xD4,
G_SPECIAL_1 = 0xD5,
G_DMA_IO = 0xD6,
G_TEXTURE = 0xD7,
G_POPMTX = 0xD8,
G_GEOMETRYMODE = 0xD9,
G_MTX = 0xDA,
G_MOVEWORD = 0xDB,
G_MOVEMEM = 0xDC,
G_LOAD_UCODE = 0xDD,
G_DL = 0xDE,
G_ENDDL = 0xDF,
G_SPNOOP = 0xE0,
G_RDPHALF_1 = 0xE1,
G_SETOTHERMODE_L = 0xE2,
G_SETOTHERMODE_H = 0xE3,
G_TEXRECT = 0xE4,
G_TEXRECTFLIP = 0xE5,
G_RDPLOADSYNC = 0xE6,
G_RDPPIPESYNC = 0xE7,
G_RDPTILESYNC = 0xE8,
G_RDPFULLSYNC = 0xE9,
G_SETKEYGB = 0xEA,
G_SETKEYR = 0xEB,
G_SETCONVERT = 0xEC,
G_SETSCISSOR = 0xED,
G_SETPRIMDEPTH = 0xEE,
G_RDPSETOTHERMODE = 0xEF,
G_LOADTLUT = 0xF0,
G_RDPHALF_2 = 0xF1,
G_SETTILESIZE = 0xF2,
G_LOADBLOCK = 0xF3,
G_LOADTILE = 0xF4,
G_SETTILE = 0xF5,
G_FILLRECT = 0xF6,
G_SETFILLCOLOR = 0xF7,
G_SETFOGCOLOR = 0xF8,
G_SETBLENDCOLOR = 0xF9,
G_SETPRIMCOLOR = 0xFA,
G_SETENVCOLOR = 0xFB,
G_SETCOMBINE = 0xFC,
G_SETTIMG = 0xFD,
G_SETZIMG = 0xFE,
G_SETCIMG = 0xFF,
};
enum class F3DZEXTexFormats
{
G_IM_FMT_RGBA,
G_IM_FMT_YUV,
G_IM_FMT_CI,
G_IM_FMT_IA,
G_IM_FMT_I
};
enum class F3DZEXTexSizes
{
G_IM_SIZ_4b,
G_IM_SIZ_8b,
G_IM_SIZ_16b,
G_IM_SIZ_32b
};
enum class DListType
{
F3DZEX,
F3DEX,
};
enum class OoTSegments
{
DirectReference = 0,
TitleStatic = 1,
Scene = 2,
Room = 3,
GameplayKeep = 4,
FieldDungeonKeep = 5,
Object = 6,
LinkAnimation = 7,
IconItemStatic = 8,
IconItem24Static = 9,
Unknown10 = 10,
Unknown11 = 11,
Unknown12 = 12,
IconFieldDungeonStatic = 13,
IconItemLanguageStatic = 14,
ZBuffer = 15,
FrameBuffer = 16,
};
class ZDisplayList : public ZResource
{
protected:
static TextureType TexFormatToTexType(F3DZEXTexFormats fmt, F3DZEXTexSizes siz);
void ParseF3DZEX(F3DZEXOpcode opcode, uint64_t data, int32_t i, const std::string& prefix,
char* line);
void ParseF3DEX(F3DEXOpcode opcode, uint64_t data, const std::string& prefix, char* line);
// Various Instruction Optimizations
bool SequenceCheck(std::vector<F3DZEXOpcode> sequence, int32_t startIndex);
int32_t OptimizationChecks(int32_t startIndex, std::string& output, const std::string& prefix);
int32_t OptimizationCheck_LoadTextureBlock(int32_t startIndex, std::string& output,
const std::string& prefix);
// int32_t OptimizationCheck_LoadMultiBlock(int32_t startIndex, std::string& output, std::string
// prefix);
// F3DEX Specific Opcode Values
void Opcode_F3DEX_G_SETOTHERMODE_L(uint64_t data, char* line);
// Shared Opcodes between F3DZEX and F3DEX
void Opcode_G_DL(uint64_t data, const std::string& prefix, char* line);
void Opcode_G_MODIFYVTX(uint64_t data, char* line);
void Opcode_G_CULLDL(uint64_t data, char* line);
void Opcode_G_TRI1(uint64_t data, char* line);
void Opcode_G_TRI2(uint64_t data, char* line);
void Opcode_G_MTX(uint64_t data, char* line);
void Opcode_G_VTX(uint64_t data, char* line);
void Opcode_G_TEXTURE(uint64_t data, char* line);
void Opcode_G_SETTIMG(uint64_t data, const std::string& prefix, char* line);
void Opcode_G_SETTILE(uint64_t data, char* line);
void Opcode_G_SETTILESIZE(uint64_t data, const std::string& prefix, char* line);
void Opcode_G_LOADBLOCK(uint64_t data, char* line);
void Opcode_G_SETCOMBINE(uint64_t data, char* line);
void Opcode_G_SETPRIMCOLOR(uint64_t data, char* line);
void Opcode_G_SETOTHERMODE_L(uint64_t data, char* line);
void Opcode_G_SETOTHERMODE_H(uint64_t data, char* line);
void Opcode_G_LOADTLUT(uint64_t data, const std::string& prefix, char* line);
void Opcode_G_ENDDL(const std::string& prefix, char* line);
public:
std::vector<uint64_t> instructions;
int32_t lastTexWidth, lastTexHeight, lastTexAddr, lastTexSeg;
F3DZEXTexFormats lastTexFmt;
F3DZEXTexSizes lastTexSiz, lastTexSizTest, lastCISiz;
bool lastTexLoaded;
bool lastTexIsPalette;
DListType dListType;
std::map<uint32_t, std::vector<ZVtx>> vertices;
std::vector<ZDisplayList*> otherDLists;
ZTexture* lastTexture = nullptr;
ZTexture* lastTlut = nullptr;
std::vector<segptr_t> references;
std::vector<ZMtx> mtxList;
ZDisplayList(ZFile* nParent);
~ZDisplayList();
void ExtractFromXML(tinyxml2::XMLElement* reader, uint32_t nRawDataIndex) override;
void ExtractFromBinary(uint32_t nRawDataIndex, int32_t rawDataSize);
void ParseRawData() override;
Declaration* DeclareVar(const std::string& prefix, const std::string& bodyStr) override;
std::string GetDefaultName(const std::string& prefix) const override;
void TextureGenCheck();
static bool TextureGenCheck(int32_t texWidth, int32_t texHeight, uint32_t texAddr,
uint32_t texSeg, F3DZEXTexFormats texFmt, F3DZEXTexSizes texSiz,
bool texLoaded, bool texIsPalette, ZDisplayList* self);
static int32_t GetDListLength(const std::vector<uint8_t>& rawData, uint32_t rawDataIndex,
DListType dListType);
size_t GetRawDataSize() const override;
DeclarationAlignment GetDeclarationAlignment() const override;
void DeclareReferences(const std::string& prefix) override;
std::string ProcessLegacy(const std::string& prefix);
std::string ProcessGfxDis(const std::string& prefix);
bool IsExternalResource() const override;
std::string GetExternalExtension() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
protected:
size_t numInstructions;
};

1429
ZAPDTR/ZAPD/ZFile.cpp Normal file

File diff suppressed because it is too large Load Diff

141
ZAPDTR/ZAPD/ZFile.h Normal file
View File

@@ -0,0 +1,141 @@
#pragma once
#include <string>
#include <vector>
#include "ZSymbol.h"
#include "ZTexture.h"
#include "tinyxml2.h"
enum class ZFileMode
{
BuildTexture,
BuildOverlay,
BuildBlob,
BuildSourceFile,
BuildBackground,
Extract,
ExternalFile,
ExtractDirectory,
Invalid,
Custom = 1000, // Used for exporter file modes
};
enum class ZGame
{
OOT_RETAIL,
OOT_SW97,
MM_RETAIL
};
class ZFile
{
public:
std::map<offset_t, Declaration*> declarations;
std::vector<ZResource*> resources;
std::string defines;
int workerID;
bool isCompilable = false;
// Default to using virtual addresses
uint32_t segment = 0x80;
uint32_t baseAddress, rangeStart, rangeEnd;
bool isExternalFile = false;
ZFile(const fs::path& nOutPath, const std::string& nName);
ZFile(ZFileMode nMode, tinyxml2::XMLElement* reader, const fs::path& nBasePath,
const fs::path& nOutPath, const std::string& filename, const fs::path& nXmlFilePath, int nWorkerID);
~ZFile();
std::string GetName() const;
std::string GetOutName() const;
ZFileMode GetMode() const;
const fs::path& GetXmlFilePath() const;
const std::vector<uint8_t>& GetRawData() const;
void ExtractResources();
void BuildSourceFile();
void AddResource(ZResource* res);
ZResource* FindResource(offset_t rawDataIndex);
std::vector<ZResource*> GetResourcesOfType(ZResourceType resType);
Declaration* AddDeclaration(offset_t address, DeclarationAlignment alignment, size_t size,
const std::string& varType, const std::string& varName,
const std::string& body);
Declaration* AddDeclarationArray(offset_t address, DeclarationAlignment alignment, size_t size,
const std::string& varType, const std::string& varName,
size_t arrayItemCnt, const std::string& body);
Declaration* AddDeclarationArray(offset_t address, DeclarationAlignment alignment, size_t size,
const std::string& varType, const std::string& varName,
const std::string& arrayItemCntStr, const std::string& body);
Declaration* AddDeclarationPlaceholder(offset_t address, const std::string& varName);
Declaration* AddDeclarationInclude(offset_t address, const std::string& includePath,
size_t size, const std::string& varType,
const std::string& varName);
Declaration* AddDeclarationIncludeArray(offset_t address, std::string& includePath, size_t size,
const std::string& varType, const std::string& varName,
size_t arrayItemCnt);
bool GetDeclarationPtrName(segptr_t segAddress, const std::string& expectedType,
std::string& declName) const;
bool GetDeclarationArrayIndexedName(segptr_t segAddress, size_t elementSize,
const std::string& expectedType,
std::string& declName) const;
Declaration* GetDeclaration(offset_t address) const;
Declaration* GetDeclarationRanged(offset_t address) const;
bool HasDeclaration(offset_t address);
std::string GetHeaderInclude() const;
std::string GetZRoomHeaderInclude() const;
std::string GetExternalFileHeaderInclude() const;
void GeneratePlaceholderDeclarations();
void AddTextureResource(uint32_t offset, ZTexture* tex);
ZTexture* GetTextureResource(uint32_t offset) const;
void AddSymbolResource(uint32_t offset, ZSymbol* sym);
ZSymbol* GetSymbolResource(uint32_t offset) const;
ZSymbol* GetSymbolResourceRanged(uint32_t offset) const;
fs::path GetSourceOutputFolderPath() const;
bool IsOffsetInFileRange(uint32_t offset) const;
bool IsSegmentedInFilespaceRange(segptr_t segAddress) const;
static std::map<std::string, ZResourceFactoryFunc*>* GetNodeMap();
static void RegisterNode(std::string nodeName, ZResourceFactoryFunc* nodeFunc);
protected:
std::string name;
fs::path outName = "";
fs::path basePath;
fs::path outputPath;
fs::path xmlFilePath;
std::vector<uint8_t> rawData;
// Keep track of every texture of this ZFile.
// The pointers declared here are "borrowed" (somebody else is the owner),
// so ZFile shouldn't delete/free those textures.
std::map<uint32_t, ZTexture*> texturesResources;
std::map<uint32_t, ZSymbol*> symbolResources;
ZFileMode mode = ZFileMode::Invalid;
ZFile();
void ParseXML(tinyxml2::XMLElement* reader, const std::string& filename);
void DeclareResourceSubReferences();
void GenerateSourceFiles();
void GenerateSourceHeaderFiles();
bool AddDeclarationChecks(uint32_t address, const std::string& varName);
std::string ProcessDeclarations();
void ProcessDeclarationText(Declaration* decl);
std::string ProcessExterns();
std::string ProcessTextureIntersections(const std::string& prefix);
void HandleUnaccountedData();
bool HandleUnaccountedAddress(offset_t currentAddress, offset_t lastAddr, uint32_t& lastSize);
};

420
ZAPDTR/ZAPD/ZLimb.cpp Normal file
View File

@@ -0,0 +1,420 @@
#include "ZLimb.h"
#include <cassert>
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
#include "WarningHandler.h"
#include "ZSkeleton.h"
REGISTER_ZFILENODE(Limb, ZLimb);
ZLimb::ZLimb(ZFile* nParent) : ZResource(nParent), segmentStruct(nParent)
{
RegisterOptionalAttribute("EnumName");
RegisterOptionalAttribute("LimbType");
RegisterOptionalAttribute("Type");
}
void ZLimb::ExtractFromBinary(uint32_t nRawDataIndex, ZLimbType nType)
{
rawDataIndex = nRawDataIndex;
type = nType;
// Don't parse raw data of external files
if (parent->GetMode() == ZFileMode::ExternalFile)
return;
ParseRawData();
}
void ZLimb::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
auto& enumNameXml = registeredAttributes.at("EnumName").value;
if (enumNameXml != "")
{
enumName = enumNameXml;
}
// Reading from a <Skeleton/>
std::string limbType = registeredAttributes.at("LimbType").value;
if (limbType == "") // Reading from a <Limb/>
limbType = registeredAttributes.at("Type").value;
if (limbType == "")
{
HANDLE_ERROR_RESOURCE(WarningType::MissingAttribute, parent, this, rawDataIndex,
"missing 'LimbType' attribute in <Limb>", "");
}
type = GetTypeByAttributeName(limbType);
if (type == ZLimbType::Invalid)
{
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
"invalid value found for 'LimbType' attribute", "");
}
}
void ZLimb::ParseRawData()
{
ZResource::ParseRawData();
const auto& rawData = parent->GetRawData();
if (type == ZLimbType::Curve)
{
childIndex = BitConverter::ToUInt8BE(rawData, rawDataIndex + 0);
siblingIndex = BitConverter::ToUInt8BE(rawData, rawDataIndex + 1);
dListPtr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 4);
dList2Ptr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8);
return;
}
if (type == ZLimbType::Legacy)
{
dListPtr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x00);
legTransX = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x04);
legTransY = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x08);
legTransZ = BitConverter::ToFloatBE(rawData, rawDataIndex + 0x0C);
rotX = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x10);
rotY = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x12);
rotZ = BitConverter::ToUInt16BE(rawData, rawDataIndex + 0x14);
childPtr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x18);
siblingPtr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 0x1C);
return;
}
transX = BitConverter::ToInt16BE(rawData, rawDataIndex + 0);
transY = BitConverter::ToInt16BE(rawData, rawDataIndex + 2);
transZ = BitConverter::ToInt16BE(rawData, rawDataIndex + 4);
childIndex = rawData.at(rawDataIndex + 6);
siblingIndex = rawData.at(rawDataIndex + 7);
switch (type)
{
case ZLimbType::LOD:
dList2Ptr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 12);
[[fallthrough]];
case ZLimbType::Standard:
dListPtr = BitConverter::ToUInt32BE(rawData, rawDataIndex + 8);
break;
case ZLimbType::Skin:
skinSegmentType =
static_cast<ZLimbSkinType>(BitConverter::ToInt32BE(rawData, rawDataIndex + 8));
skinSegment = BitConverter::ToUInt32BE(rawData, rawDataIndex + 12);
if (skinSegmentType == ZLimbSkinType::SkinType_4)
{
if (skinSegment != 0 && GETSEGNUM(skinSegment) == parent->segment)
{
uint32_t skinSegmentOffset = Seg2Filespace(skinSegment, parent->baseAddress);
segmentStruct.ExtractFromFile(skinSegmentOffset);
}
}
break;
case ZLimbType::Curve:
case ZLimbType::Legacy:
break;
case ZLimbType::Invalid:
assert(!"whoops");
break;
}
}
void ZLimb::DeclareReferences(const std::string& prefix)
{
std::string varPrefix = name;
if (varPrefix == "")
varPrefix = prefix;
ZResource::DeclareReferences(varPrefix);
std::string suffix;
switch (type)
{
case ZLimbType::Legacy:
if (childPtr != 0 && GETSEGNUM(childPtr) == parent->segment)
{
uint32_t childOffset = Seg2Filespace(childPtr, parent->baseAddress);
if (!parent->HasDeclaration(childOffset))
{
ZLimb* child = new ZLimb(parent);
child->ExtractFromBinary(childOffset, ZLimbType::Legacy);
child->DeclareVar(varPrefix, "");
child->DeclareReferences(varPrefix);
parent->AddResource(child);
}
}
if (siblingPtr != 0 && GETSEGNUM(siblingPtr) == parent->segment)
{
uint32_t siblingdOffset = Seg2Filespace(siblingPtr, parent->baseAddress);
if (!parent->HasDeclaration(siblingdOffset))
{
ZLimb* sibling = new ZLimb(parent);
sibling->ExtractFromBinary(siblingdOffset, ZLimbType::Legacy);
sibling->DeclareVar(varPrefix, "");
sibling->DeclareReferences(varPrefix);
parent->AddResource(sibling);
}
}
break;
case ZLimbType::Curve:
case ZLimbType::LOD:
suffix = "Far";
if (type == ZLimbType::Curve)
suffix = "Curve2";
DeclareDList(dList2Ptr, varPrefix, suffix);
[[fallthrough]];
case ZLimbType::Standard:
suffix = "";
if (type == ZLimbType::Curve)
suffix = "Curve";
DeclareDList(dListPtr, varPrefix, suffix);
break;
case ZLimbType::Skin:
switch (skinSegmentType)
{
case ZLimbSkinType::SkinType_4:
if (skinSegment != 0 && GETSEGNUM(skinSegment) == parent->segment)
{
segmentStruct.DeclareReferences(varPrefix);
segmentStruct.GetSourceOutputCode(varPrefix);
}
break;
case ZLimbSkinType::SkinType_DList:
DeclareDList(skinSegment, varPrefix, "");
break;
default:
break;
}
break;
case ZLimbType::Invalid:
break;
}
}
size_t ZLimb::GetRawDataSize() const
{
switch (type)
{
case ZLimbType::Standard:
case ZLimbType::Curve:
return 0x0C;
case ZLimbType::LOD:
case ZLimbType::Skin:
return 0x10;
case ZLimbType::Legacy:
return 0x20;
case ZLimbType::Invalid:
break;
}
return 0x0C;
}
std::string ZLimb::GetBodySourceCode() const
{
if (Globals::Instance->otrMode)
return "";
std::string dListStr;
std::string dListStr2;
Globals::Instance->GetSegmentedArrayIndexedName(dListPtr, 8, parent, "Gfx", dListStr,
parent->workerID);
Globals::Instance->GetSegmentedArrayIndexedName(dList2Ptr, 8, parent, "Gfx", dListStr2,
parent->workerID);
std::string entryStr = "\n\t";
if (type == ZLimbType::Legacy)
{
std::string childName;
std::string siblingName;
Globals::Instance->GetSegmentedPtrName(childPtr, parent, "LegacyLimb", childName,
parent->workerID);
Globals::Instance->GetSegmentedPtrName(siblingPtr, parent, "LegacyLimb", siblingName,
parent->workerID);
entryStr += StringHelper::Sprintf("%s,\n", dListStr.c_str());
entryStr +=
StringHelper::Sprintf("\t{ %ff, %ff, %ff },\n", legTransX, legTransY, legTransZ);
entryStr += StringHelper::Sprintf("\t{ 0x%04X, 0x%04X, 0x%04X },\n", rotX, rotY, rotZ);
entryStr += StringHelper::Sprintf("\t%s,\n", childName.c_str());
entryStr += StringHelper::Sprintf("\t%s\n", siblingName.c_str());
}
else
{
std::string childStr;
std::string siblingStr;
if (limbsTable != nullptr)
{
childStr = limbsTable->GetLimbEnumName(childIndex);
siblingStr = limbsTable->GetLimbEnumName(siblingIndex);
}
else
{
childStr = StringHelper::Sprintf("0x%02X", childIndex);
siblingStr = StringHelper::Sprintf("0x%02X", siblingIndex);
}
if (type != ZLimbType::Curve)
{
entryStr += StringHelper::Sprintf("{ %i, %i, %i }, ", transX, transY, transZ);
}
entryStr += StringHelper::Sprintf("%s, %s,\n", childStr.c_str(), siblingStr.c_str());
switch (type)
{
case ZLimbType::Standard:
entryStr += StringHelper::Sprintf("\t%s\n", dListStr.c_str());
break;
case ZLimbType::LOD:
case ZLimbType::Curve:
entryStr +=
StringHelper::Sprintf("\t{ %s, %s }\n", dListStr.c_str(), dListStr2.c_str());
break;
case ZLimbType::Skin:
{
std::string skinSegmentStr;
Globals::Instance->GetSegmentedPtrName(skinSegment, parent, "", skinSegmentStr,
parent->workerID);
entryStr +=
StringHelper::Sprintf("\t0x%02X, %s\n", skinSegmentType, skinSegmentStr.c_str());
}
break;
case ZLimbType::Legacy:
break;
case ZLimbType::Invalid:
break;
}
}
return entryStr;
}
std::string ZLimb::GetDefaultName(const std::string& prefix) const
{
return StringHelper::Sprintf("%sLimb_%06X", prefix.c_str(), rawDataIndex);
}
std::string ZLimb::GetSourceTypeName() const
{
return GetSourceTypeName(type);
}
ZResourceType ZLimb::GetResourceType() const
{
return ZResourceType::Limb;
}
ZLimbType ZLimb::GetLimbType()
{
return type;
}
void ZLimb::SetLimbType(ZLimbType value)
{
type = value;
}
const char* ZLimb::GetSourceTypeName(ZLimbType limbType)
{
switch (limbType)
{
case ZLimbType::Standard:
return "StandardLimb";
case ZLimbType::LOD:
return "LodLimb";
case ZLimbType::Skin:
return "SkinLimb";
case ZLimbType::Curve:
return "SkelCurveLimb";
case ZLimbType::Legacy:
return "LegacyLimb";
default:
return "StandardLimb";
}
}
ZLimbType ZLimb::GetTypeByAttributeName(const std::string& attrName)
{
if (attrName == "Standard")
{
return ZLimbType::Standard;
}
if (attrName == "LOD")
{
return ZLimbType::LOD;
}
if (attrName == "Skin")
{
return ZLimbType::Skin;
}
if (attrName == "Curve")
{
return ZLimbType::Curve;
}
if (attrName == "Legacy")
{
return ZLimbType::Legacy;
}
return ZLimbType::Invalid;
}
void ZLimb::SetLimbIndex(uint8_t nLimbIndex)
{
limbIndex = nLimbIndex;
}
void ZLimb::DeclareDList(segptr_t dListSegmentedPtr, const std::string& prefix,
const std::string& limbSuffix)
{
if (dListSegmentedPtr == 0 || GETSEGNUM(dListSegmentedPtr) != parent->segment)
return;
uint32_t dlistOffset = Seg2Filespace(dListSegmentedPtr, parent->baseAddress);
if (parent->HasDeclaration(dlistOffset))
return;
if (!parent->IsOffsetInFileRange(dlistOffset) || dlistOffset >= parent->GetRawData().size())
return;
std::string dlistName;
bool declFound = Globals::Instance->GetSegmentedArrayIndexedName(dListSegmentedPtr, 8, parent,
"Gfx", dlistName, parent->workerID);
if (declFound)
return;
int32_t dlistLength = ZDisplayList::GetDListLength(
parent->GetRawData(), dlistOffset,
Globals::Instance->game == ZGame::OOT_SW97 ? DListType::F3DEX : DListType::F3DZEX);
ZDisplayList* dlist = new ZDisplayList(parent);
dlist->ExtractFromBinary(dlistOffset, dlistLength);
std::string dListStr =
StringHelper::Sprintf("%s%sDL_%06X", prefix.c_str(), limbSuffix.c_str(), dlistOffset);
dlist->SetName(dListStr);
dlist->DeclareVar(prefix, "");
parent->AddResource(dlist);
}

74
ZAPDTR/ZAPD/ZLimb.h Normal file
View File

@@ -0,0 +1,74 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
#include "OtherStructs/SkinLimbStructs.h"
#include "ZDisplayList.h"
#include "ZFile.h"
enum class ZLimbType
{
Invalid,
Standard,
LOD,
Skin,
Curve,
Legacy,
};
class ZLimbTable;
class ZLimb : public ZResource
{
public:
std::string enumName;
ZLimbTable* limbsTable = nullptr; // borrowed pointer, do not delete!
ZLimbType type = ZLimbType::Standard;
ZLimbSkinType skinSegmentType = ZLimbSkinType::SkinType_0; // Skin only
segptr_t skinSegment = 0; // Skin only
Struct_800A5E28 segmentStruct = {0}; // Skin only
// Legacy only
float legTransX = 0, legTransY = 0, legTransZ = 0; // Vec3f
uint16_t rotX = 0, rotY = 0, rotZ = 0; // Vec3s
segptr_t childPtr = 0; // LegacyLimb*
segptr_t siblingPtr = 0; // LegacyLimb*
segptr_t dListPtr = 0;
segptr_t dList2Ptr = 0; // LOD and Curve Only
int16_t transX = 0, transY = 0, transZ = 0;
uint8_t childIndex = 0, siblingIndex = 0;
uint8_t limbIndex = 0;
ZLimb(ZFile* nParent);
void ExtractFromBinary(uint32_t nRawDataIndex, ZLimbType nType);
void ParseXML(tinyxml2::XMLElement* reader) override;
void ParseRawData() override;
void DeclareReferences(const std::string& prefix) override;
std::string GetBodySourceCode() const override;
std::string GetDefaultName(const std::string& prefix) const override;
size_t GetRawDataSize() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
ZLimbType GetLimbType();
void SetLimbType(ZLimbType value);
static const char* GetSourceTypeName(ZLimbType limbType);
static ZLimbType GetTypeByAttributeName(const std::string& attrName);
void SetLimbIndex(uint8_t nLimbIndex);
protected:
void DeclareDList(segptr_t dListSegmentedPtr, const std::string& prefix,
const std::string& limbSuffix);
};

58
ZAPDTR/ZAPD/ZMtx.cpp Normal file
View File

@@ -0,0 +1,58 @@
#include "ZMtx.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
#include "ZFile.h"
REGISTER_ZFILENODE(Mtx, ZMtx);
ZMtx::ZMtx(ZFile* nParent) : ZResource(nParent)
{
}
void ZMtx::ParseRawData()
{
ZResource::ParseRawData();
const auto& rawData = parent->GetRawData();
for (size_t i = 0; i < 4; ++i)
for (size_t j = 0; j < 4; ++j)
mtx[i][j] = BitConverter::ToInt32BE(rawData, rawDataIndex + (i * 4 + j) * 4);
}
size_t ZMtx::GetRawDataSize() const
{
return 64;
}
std::string ZMtx::GetBodySourceCode() const
{
std::string bodyStr = "\n";
for (const auto& row : mtx)
{
bodyStr += " ";
for (int32_t val : row)
bodyStr += StringHelper::Sprintf("%-11i, ", val);
bodyStr += "\n";
}
return bodyStr;
}
std::string ZMtx::GetSourceTypeName() const
{
return "Mtx";
}
ZResourceType ZMtx::GetResourceType() const
{
return ZResourceType::Mtx;
}
DeclarationAlignment ZMtx::GetDeclarationAlignment() const
{
return DeclarationAlignment::Align8;
}

24
ZAPDTR/ZAPD/ZMtx.h Normal file
View File

@@ -0,0 +1,24 @@
#pragma once
#include <array>
#include <cstdint>
#include "ZResource.h"
class ZMtx : public ZResource
{
public:
ZMtx(ZFile* nParent);
void ParseRawData() override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
DeclarationAlignment GetDeclarationAlignment() const override;
public:
std::array<std::array<int32_t, 4>, 4> mtx;
};

212
ZAPDTR/ZAPD/ZPath.cpp Normal file
View File

@@ -0,0 +1,212 @@
#include "ZPath.h"
#include "Globals.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
#include "WarningHandler.h"
#include "ZFile.h"
REGISTER_ZFILENODE(Path, ZPath);
ZPath::ZPath(ZFile* nParent) : ZResource(nParent)
{
numPaths = 1;
RegisterOptionalAttribute("NumPaths", "1");
}
void ZPath::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
numPaths = StringHelper::StrToL(registeredAttributes.at("NumPaths").value);
if (numPaths < 1)
{
HANDLE_ERROR_RESOURCE(
WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
StringHelper::Sprintf("invalid value '%d' found for 'NumPaths' attribute", numPaths),
"Should be at least '1'");
}
}
void ZPath::ParseRawData()
{
ZResource::ParseRawData();
uint32_t currentPtr = rawDataIndex;
pathways.reserve(numPaths);
for (size_t pathIndex = 0; pathIndex < numPaths; pathIndex++)
{
PathwayEntry path(parent);
path.ExtractFromFile(currentPtr);
if (path.GetListAddress() == 0)
break;
currentPtr += path.GetRawDataSize();
pathways.push_back(path);
}
}
void ZPath::DeclareReferences(const std::string& prefix)
{
ZResource::DeclareReferences(prefix);
for (auto& entry : pathways)
entry.DeclareReferences(prefix);
}
Declaration* ZPath::DeclareVar(const std::string& prefix, const std::string& bodyStr)
{
std::string auxName = name;
if (name == "")
auxName = GetDefaultName(prefix);
Declaration* decl =
parent->AddDeclarationArray(rawDataIndex, GetDeclarationAlignment(), GetRawDataSize(),
GetSourceTypeName(), name, pathways.size(), bodyStr);
decl->staticConf = staticConf;
return decl;
}
std::string ZPath::GetBodySourceCode() const
{
std::string declaration;
size_t index = 0;
for (const auto& entry : pathways)
{
declaration += StringHelper::Sprintf("\t{ %s },", entry.GetBodySourceCode().c_str());
if (index < pathways.size() - 1)
declaration += "\n";
index++;
}
return declaration;
}
std::string ZPath::GetSourceTypeName() const
{
return "Path";
}
ZResourceType ZPath::GetResourceType() const
{
return ZResourceType::Path;
}
size_t ZPath::GetRawDataSize() const
{
return pathways.size() * pathways.at(0).GetRawDataSize();
}
void ZPath::SetNumPaths(uint32_t nNumPaths)
{
numPaths = nNumPaths;
}
/* PathwayEntry */
PathwayEntry::PathwayEntry(ZFile* nParent) : ZResource(nParent)
{
}
void PathwayEntry::ParseRawData()
{
ZResource::ParseRawData();
auto parentRawData = parent->GetRawData();
numPoints = parentRawData.at(rawDataIndex + 0);
unk1 = parentRawData.at(rawDataIndex + 1);
unk2 = BitConverter::ToInt16BE(parentRawData, rawDataIndex + 2);
listSegmentAddress = BitConverter::ToInt32BE(parentRawData, rawDataIndex + 4);
uint32_t currentPtr = GETSEGOFFSET(listSegmentAddress);
points.reserve(numPoints);
for (int32_t i = 0; i < numPoints; i++)
{
ZVector vec(parent);
vec.ExtractFromBinary(currentPtr, ZScalarType::ZSCALAR_S16, 3);
currentPtr += vec.GetRawDataSize();
points.push_back(vec);
}
}
void PathwayEntry::DeclareReferences(const std::string& prefix)
{
ZResource::DeclareReferences(prefix);
if (points.empty())
return;
std::string pointsName;
bool addressFound = Globals::Instance->GetSegmentedPtrName(listSegmentAddress, parent, "Vec3s",
pointsName, parent->workerID);
if (addressFound)
return;
std::string declaration = "";
size_t index = 0;
for (const auto& point : points)
{
declaration += StringHelper::Sprintf("\t{ %s },", point.GetBodySourceCode().c_str());
if (index < points.size() - 1)
declaration += "\n";
index++;
}
uint32_t pointsOffset = Seg2Filespace(listSegmentAddress, parent->baseAddress);
Declaration* decl = parent->GetDeclaration(pointsOffset);
if (decl == nullptr)
{
pointsName = StringHelper::Sprintf("%sPathwayList_%06X", prefix.c_str(), pointsOffset);
parent->AddDeclarationArray(pointsOffset, points.at(0).GetDeclarationAlignment(),
points.size() * 6, points.at(0).GetSourceTypeName(), pointsName,
points.size(), declaration);
}
else
decl->text = declaration;
}
std::string PathwayEntry::GetBodySourceCode() const
{
std::string declaration;
std::string listName;
Globals::Instance->GetSegmentedPtrName(listSegmentAddress, parent, "Vec3s", listName,
parent->workerID);
if (Globals::Instance->game == ZGame::MM_RETAIL)
declaration +=
StringHelper::Sprintf("%i, %i, %i, %s", numPoints, unk1, unk2, listName.c_str());
else
declaration += StringHelper::Sprintf("%i, %s", numPoints, listName.c_str());
return declaration;
}
std::string PathwayEntry::GetSourceTypeName() const
{
return "Path";
}
ZResourceType PathwayEntry::GetResourceType() const
{
return ZResourceType::Path;
}
size_t PathwayEntry::GetRawDataSize() const
{
return 0x08;
}
segptr_t PathwayEntry::GetListAddress() const
{
return listSegmentAddress;
}

51
ZAPDTR/ZAPD/ZPath.h Normal file
View File

@@ -0,0 +1,51 @@
#pragma once
#include "ZResource.h"
#include "ZVector.h"
class PathwayEntry : public ZResource
{
public:
PathwayEntry(ZFile* nParent);
void ParseRawData() override;
void DeclareReferences(const std::string& prefix) override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
segptr_t GetListAddress() const;
public:
int32_t numPoints;
int8_t unk1; // (MM Only)
int16_t unk2; // (MM Only)
segptr_t listSegmentAddress;
std::vector<ZVector> points;
};
class ZPath : public ZResource
{
public:
ZPath(ZFile* nParent);
void ParseXML(tinyxml2::XMLElement* reader) override;
void ParseRawData() override;
void DeclareReferences(const std::string& prefix) override;
Declaration* DeclareVar(const std::string& prefix, const std::string& bodyStr) override;
std::string GetBodySourceCode() const override;
std::string GetSourceTypeName() const override;
ZResourceType GetResourceType() const override;
size_t GetRawDataSize() const override;
void SetNumPaths(uint32_t nNumPaths);
public:
uint32_t numPaths;
std::vector<PathwayEntry> pathways;
};

View File

@@ -0,0 +1,101 @@
#include "ZPlayerAnimationData.h"
#include "Utils/BitConverter.h"
#include "Utils/StringHelper.h"
#include "ZFile.h"
#include <Globals.h>
REGISTER_ZFILENODE(PlayerAnimationData, ZPlayerAnimationData);
ZPlayerAnimationData::ZPlayerAnimationData(ZFile* nParent) : ZResource(nParent)
{
RegisterRequiredAttribute("FrameCount");
}
void ZPlayerAnimationData::ParseXML(tinyxml2::XMLElement* reader)
{
ZResource::ParseXML(reader);
std::string& frameCountXml = registeredAttributes.at("FrameCount").value;
frameCount = StringHelper::StrToL(frameCountXml);
}
void ZPlayerAnimationData::ParseRawData()
{
ZResource::ParseRawData();
const auto& rawData = parent->GetRawData();
size_t totalSize = GetRawDataSize();
// Divided by 2 because each value is an s16
limbRotData.reserve(totalSize * frameCount / 2);
for (size_t i = 0; i < totalSize; i += 2)
{
limbRotData.push_back(BitConverter::ToUInt16BE(rawData, rawDataIndex + i));
}
}
Declaration* ZPlayerAnimationData::DeclareVar(const std::string& prefix, const std::string& bodyStr)
{
std::string auxName = name;
if (auxName == "")
auxName = GetDefaultName(prefix);
Declaration* decl =
parent->AddDeclarationArray(rawDataIndex, GetDeclarationAlignment(), GetRawDataSize(),
GetSourceTypeName(), name, limbRotData.size(), bodyStr);
decl->staticConf = staticConf;
return decl;
}
std::string ZPlayerAnimationData::GetBodySourceCode() const
{
std::string declaration = "";
if (Globals::Instance->otrMode)
return "";
size_t index = 0;
for (const auto& entry : limbRotData)
{
if (index % 8 == 0)
{
declaration += "\t";
}
declaration += StringHelper::Sprintf("0x%04X, ", entry);
if ((index + 1) % 8 == 0)
{
declaration += "\n";
}
index++;
}
return declaration;
}
std::string ZPlayerAnimationData::GetDefaultName(const std::string& prefix) const
{
return StringHelper::Sprintf("%sPlayerAnimationData_%06X", prefix.c_str(), rawDataIndex);
}
std::string ZPlayerAnimationData::GetSourceTypeName() const
{
return "s16";
}
ZResourceType ZPlayerAnimationData::GetResourceType() const
{
return ZResourceType::PlayerAnimationData;
}
size_t ZPlayerAnimationData::GetRawDataSize() const
{
// (sizeof(Vec3s) * limbCount + 2) * frameCount
return (6 * 22 + 2) * frameCount;
}

Some files were not shown because too many files have changed in this diff Show More