Merge branch 'develop'

This commit is contained in:
Kenix 2022-05-13 19:00:09 -04:00
commit ab2819d9fb
1448 changed files with 39805 additions and 5529 deletions

403
.gitignore vendored Normal file
View File

@ -0,0 +1,403 @@
# Cache files
__pycache__/
.pyc
.DS_Store
# Text editor remnants
.vscode/
.vs/
.idea/
CMakeLists.txt
cmake-build-debug
venv/
# Project-specific ignores
build/
expected/
notes/
baserom/
docs/doxygen/
*.elf
*.sra
*.z64
*.n64
*.v64
*.map
*.dump
out.txt
# Tool artifacts
tools/mipspro7.2_compiler/
tools/overlayhelpers/batchdisasm/output/*
tools/overlayhelpers/batchdisasm/output2/*
tools/overlayhelpers/batchdisasm/mipsdisasm/*
tools/disasm/output/*
tools/asmsplitter/asm/*
tools/asmsplitter/c/*
ctx.c
tools/*dSYM/
graphs/
# Assets
*.png
*.jpg
*.mdli
*.anmi
*.obj
*.mtl
*.fbx
!*_custom*
.extracted-assets.json
# Docs
!docs/tutorial/
# Per-user configuration
.python-version
## 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/
external/
ZAPDUtils/build/
ZAPD/BuildInfo.h
DebugObj/*
ReleaseObj/*

66
BUILDING.md Normal file
View File

@ -0,0 +1,66 @@
# Building Ship of Harkinian
## Windows
1. Install [Python](https://www.python.org/downloads/) >= 3.6.
2. Install [Visual Studio 2022 Community Edition](https://visualstudio.microsoft.com/vs/community/)
3. In the Visual Studio Installer, install `MSVC v142 - VS 2019 C++`.
4. Clone the Ship of Harkinian repository.
5. Place one or more [compatible](#compatible-roms) roms in the `OTRExporter` directory with namings of your choice.
6. Run `OTRExporter/OTRExporter.sln`.
7. Switch the solution to `Release x64`.
8. Build the solution.
9. Launching `OTRExporter/extract_assets.py` will generate an `oot.otr` archive file in `OTRExporter/oot.otr`.
10. Run `soh/soh.sln`
11. Switch the solution to `Release x86`.
12. Build the solution.
13. Copy the `OTRExporter/oot.otr` archive file to `soh/Release`.
14. Launch `soh.exe`.
## Linux
```bash
# Clone the repo
git clone git@github.com:HarbourMasters/ShipWright.git
cd ShipWright
# Copy the baserom to the OTRExporter folder
cp <path to your ROM> OTRExporter
# Build the docker image
sudo docker build . -t soh
# Run the docker image with the working directory mounted to /soh
sudo docker run --rm -it -v $(pwd):/soh soh /bin/bash
```
Inside the Docker container:
```bash
# Clone and build StormLib
git clone https://github.com/ladislav-zezula/StormLib external/StormLib
cmake -B external/StormLib/build -S external/StormLib
cmake --build external/StormLib/build
cp external/StormLib/build/libstorm.a external
cp /usr/local/lib/libGLEW.a external
cd soh
# Extract the assets/Compile the exporter/Run the exporter
make setup -j$(nproc) OPTFLAGS=-O0 DEBUG=0
# Compile the code
make -j $(nproc) OPTFLAGS=-O0 DEBUG=0
```
# Compatible Roms
```
OOT_PAL_GC checksum 0x09465AC3
OOT_PAL_GC_DBG1 checksum 0x871E1C92 (debug non-master quest)
```
# OTRExporter Usage
The OTRExporter exports an `oot.otr` archive file which Ship of Harkinian requires to play.
Use the `extract_assets.py` script file to run the exporter using any of the following methods:
1. Double click on the script after placing one or more roms in the directory.
2. Drag & Drop a rom onto the script.
3. In a terminal run `python3 extract_assets.py` after placing one or more roms in the directory.
4. In a terminal run `python3 extract_assets.py <path_to_rom>`
If the script finds multiple roms the user is prompted which to use. Selection is done using the number keys and then pressing the carriage return key.

38
Dockerfile Normal file
View File

@ -0,0 +1,38 @@
FROM ubuntu:21.04 as build
ENV LANG C.UTF-8
ARG DEBIAN_FRONTEND=noninteractive
RUN dpkg --add-architecture i386 && \
apt-get update && \
apt-get upgrade -y && \
apt-get install -y \
binutils:i386 \
gcc-10:i386 \
g++-10:i386 \
python3.10 \
python \
make \
cmake \
git \
lld \
libsdl2-dev:i386 \
zlib1g-dev:i386 \
libbz2-dev:i386 \
libpng-dev:i386 \
libgles2-mesa-dev && \
ln -sf /usr/bin/python3.10 /usr/bin/python3 && \
ln -s /usr/bin/gcc-10 /usr/bin/gcc && \
ln -s /usr/bin/gcc-10 /usr/bin/cc && \
ln -s /usr/bin/g++-10 /usr/bin/g++ && \
ln -s /usr/bin/g++-10 /usr/bin/c++
RUN git clone https://github.com/Perlmint/glew-cmake.git && \
cmake glew-cmake && \
make -j$(nproc) && \
make install ARCH64=false
RUN mkdir /soh
WORKDIR /soh

117
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,117 @@
pipeline {
agent none
options {
timestamps()
skipDefaultCheckout(true)
}
stages {
stage ('Build Windows') {
environment {
MSBUILD='C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\Msbuild\\Current\\Bin\\msbuild.exe'
CONFIG='Release'
OTRPLATFORM='x64'
PLATFORM='x86'
ZIP='C:\\Program Files\\7-Zip\\7z.exe'
PYTHON='C:\\Users\\jenkins\\AppData\\Local\\Programs\\Python\\Python310\\python.exe'
CMAKE='C:\\Program Files\\CMake\\bin\\cmake.exe'
TOOLSET='v142'
}
agent {
label "SoH-Builders"
}
steps {
checkout([
$class: 'GitSCM',
branches: scm.branches,
doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
extensions: scm.extensions,
userRemoteConfigs: scm.userRemoteConfigs
])
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
bat """
"${env.MSBUILD}" ".\\OTRExporter\\OTRExporter.sln" -t:build -p:Configuration=${env.CONFIG};Platform=${env.OTRPLATFORM};PlatformToolset=${env.TOOLSET};RestorePackagesConfig=true /restore /nodeReuse:false /m
xcopy "..\\..\\ZELOOTD.z64" "OTRExporter\\"
cd "OTRExporter"
"${env.PYTHON}" ".\\extract_assets.py"
cd "..\\"
"${env.MSBUILD}" ".\\soh\\soh.sln" -t:build -p:Configuration=${env.CONFIG};Platform=${env.PLATFORM};PlatformToolset=${env.TOOLSET} /nodeReuse:false /m
cd OTRGui
mkdir build
cd build
"${env.CMAKE}" ..
"${env.CMAKE}" --build . --config Release
cd "..\\..\\"
move "soh\\Release\\soh.exe" ".\\"
move "OTRGui\\build\\assets" ".\\"
move ".\\OTRExporter\\x64\\Release\\ZAPD.exe" ".\\assets\\extractor\\"
move ".\\OTRGui\\build\\Release\\OTRGui.exe" ".\\"
rename README.md readme.txt
"${env.ZIP}" a soh.7z soh.exe OTRGui.exe assets readme.txt
"""
archiveArtifacts artifacts: 'soh.7z', followSymlinks: false, onlyIfSuccessful: true
}
}
post {
always {
step([$class: 'WsCleanup']) // Clean workspace
}
}
}
stage ('Build Linux') {
agent {
label "SoH-Linux-Builders"
}
steps {
checkout([
$class: 'GitSCM',
branches: scm.branches,
doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
extensions: scm.extensions,
userRemoteConfigs: scm.userRemoteConfigs
])
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
sh '''
cp ../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64
docker build . -t soh
docker run --name sohcont -dit --rm -v $(pwd):/soh soh /bin/bash
cp ../../buildsoh.bash soh
docker exec sohcont soh/buildsoh.bash
mkdir build
mv soh/soh.elf build/
mv OTRGui/build/OTRGui build/
mv OTRGui/build/assets build/
mv ZAPDTR/ZAPD.out build/assets/extractor/
mv README.md build/readme.txt
cd build
7z a soh-linux.7z soh.elf OTRGui assets readme.txt
mv soh-linux.7z ../
'''
}
sh 'sudo docker container stop sohcont'
archiveArtifacts artifacts: 'soh-linux.7z', followSymlinks: false, onlyIfSuccessful: true
}
post {
always {
step([$class: 'WsCleanup']) // Clean workspace
}
}
}
}
}

View File

@ -345,6 +345,8 @@ baserom/
*.otr *.otr
*.swp *.swp
*.a *.a
*.z64
*.n64
Extract/ Extract/
tmp.txt tmp.txt

View File

@ -2,7 +2,7 @@
<SymbolMap File="SymbolMap_OoTMqDbg.txt"/> <SymbolMap File="SymbolMap_OoTMqDbg.txt"/>
<ActorList File="ActorList_OoTMqDbg.txt"/> <ActorList File="ActorList_OoTMqDbg.txt"/>
<ObjectList File="ObjectList_OoTMqDbg.txt"/> <ObjectList File="ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="../soh/assets/xml/"/> <ExternalXMLFolder Path="../soh/assets/xml/GC_NMQ_PAL_F/"/>
<TexturePool File="TexturePool.xml"/> <TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/> <ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root> </Root>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -49,12 +49,12 @@ void OTRExporter_Animation::Save(ZResource* res, const fs::path& outPath, Binary
writer->Write((uint32_t)normalAnim->rotationValues.size()); writer->Write((uint32_t)normalAnim->rotationValues.size());
for (int i = 0; i < normalAnim->rotationValues.size(); i++) for (size_t i = 0; i < normalAnim->rotationValues.size(); i++)
writer->Write(normalAnim->rotationValues[i]); writer->Write(normalAnim->rotationValues[i]);
writer->Write((uint32_t)normalAnim->rotationIndices.size()); writer->Write((uint32_t)normalAnim->rotationIndices.size());
for (int i = 0; i < normalAnim->rotationIndices.size(); i++) for (size_t i = 0; i < normalAnim->rotationIndices.size(); i++)
{ {
writer->Write(normalAnim->rotationIndices[i].x); writer->Write(normalAnim->rotationIndices[i].x);
writer->Write(normalAnim->rotationIndices[i].y); writer->Write(normalAnim->rotationIndices[i].y);

View File

@ -10,7 +10,7 @@ void OTRExporter_Array::Save(ZResource* res, const fs::path& outPath, BinaryWrit
writer->Write((uint32_t)arr->resList[0]->GetResourceType()); writer->Write((uint32_t)arr->resList[0]->GetResourceType());
writer->Write((uint32_t)arr->arrayCnt); writer->Write((uint32_t)arr->arrayCnt);
for (int i = 0; i < arr->arrayCnt; i++) for (size_t i = 0; i < arr->arrayCnt; i++)
{ {
if (arr->resList[i]->GetResourceType() == ZResourceType::Vertex) if (arr->resList[i]->GetResourceType() == ZResourceType::Vertex)
{ {
@ -32,7 +32,7 @@ void OTRExporter_Array::Save(ZResource* res, const fs::path& outPath, BinaryWrit
writer->Write((uint32_t)vec->scalarType); writer->Write((uint32_t)vec->scalarType);
writer->Write((uint32_t)vec->dimensions); writer->Write((uint32_t)vec->dimensions);
for (int k = 0; k < vec->dimensions; k++) for (size_t k = 0; k < vec->dimensions; k++)
{ {
// OTRTODO: Duplicate code here. Cleanup at a later date... // OTRTODO: Duplicate code here. Cleanup at a later date...
switch (vec->scalarType) switch (vec->scalarType)
@ -62,6 +62,8 @@ void OTRExporter_Array::Save(ZResource* res, const fs::path& outPath, BinaryWrit
writer->Write(vec->scalars[k].scalarData.u64); writer->Write(vec->scalars[k].scalarData.u64);
break; break;
// OTRTODO: ADD OTHER TYPES // OTRTODO: ADD OTHER TYPES
default:
break;
} }
} }
} }
@ -98,6 +100,8 @@ void OTRExporter_Array::Save(ZResource* res, const fs::path& outPath, BinaryWrit
writer->Write(scal->scalarData.u64); writer->Write(scal->scalarData.u64);
break; break;
// OTRTODO: ADD OTHER TYPES // OTRTODO: ADD OTHER TYPES
default:
break;
} }
} }
} }

View File

@ -29,7 +29,7 @@ void OTRExporter_Cutscene::Save(ZResource* res, const fs::path& outPath, BinaryW
for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries) for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries)
{ {
writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame)); writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame));
writer->Write(CMD_F(e->viewAngle)); writer->Write(e->viewAngle);
writer->Write(CMD_HH(e->posX, e->posY)); writer->Write(CMD_HH(e->posX, e->posY));
writer->Write(CMD_HH(e->posZ, e->unused)); writer->Write(CMD_HH(e->posZ, e->unused));
} }
@ -46,7 +46,7 @@ void OTRExporter_Cutscene::Save(ZResource* res, const fs::path& outPath, BinaryW
for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries) for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries)
{ {
writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame)); writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame));
writer->Write(CMD_F(e->viewAngle)); writer->Write(e->viewAngle);
writer->Write(CMD_HH(e->posX, e->posY)); writer->Write(CMD_HH(e->posX, e->posY));
writer->Write(CMD_HH(e->posZ, e->unused)); writer->Write(CMD_HH(e->posZ, e->unused));
} }
@ -105,7 +105,7 @@ void OTRExporter_Cutscene::Save(ZResource* res, const fs::path& outPath, BinaryW
for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries) for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries)
{ {
writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame)); writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame));
writer->Write(CMD_F(e->viewAngle)); writer->Write(e->viewAngle);
writer->Write(CMD_HH(e->posX, e->posY)); writer->Write(CMD_HH(e->posX, e->posY));
writer->Write(CMD_HH(e->posZ, e->unused)); writer->Write(CMD_HH(e->posZ, e->unused));
} }
@ -122,7 +122,7 @@ void OTRExporter_Cutscene::Save(ZResource* res, const fs::path& outPath, BinaryW
for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries) for (auto& e : ((CutsceneCommandSetCameraPos*)cs->commands[i])->entries)
{ {
writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame)); writer->Write(CMD_BBH(e->continueFlag, e->cameraRoll, e->nextPointFrame));
writer->Write(CMD_F(e->viewAngle)); writer->Write(e->viewAngle);
writer->Write(CMD_HH(e->posX, e->posY)); writer->Write(CMD_HH(e->posX, e->posY));
writer->Write(CMD_HH(e->posZ, e->unused)); writer->Write(CMD_HH(e->posZ, e->unused));
} }

View File

@ -29,20 +29,6 @@
Ab1, Ad1)) \ Ab1, Ad1)) \
} }
typedef int32_t Mtx_t[4][4];
typedef union Mtx
{
//_Alignas(8)
Mtx_t m;
int32_t l[16];
struct
{
int16_t i[16];
uint16_t f[16];
};
} Mtx;
#define gsSPBranchLessZraw2(dl, vtx, zval) \ #define gsSPBranchLessZraw2(dl, vtx, zval) \
{ _SHIFTL(G_BRANCH_Z,24,8)|_SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12),\ { _SHIFTL(G_BRANCH_Z,24,8)|_SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12),\
(unsigned int)(zval), } (unsigned int)(zval), }
@ -71,7 +57,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
// DEBUG: Write in a marker // DEBUG: Write in a marker
Declaration* dbgDecl = dList->parent->GetDeclaration(dList->GetRawDataIndex()); Declaration* dbgDecl = dList->parent->GetDeclaration(dList->GetRawDataIndex());
std::string dbgName = StringHelper::Sprintf("%s\\%s", GetParentFolderName(res).c_str(), dbgDecl->varName.c_str()); std::string dbgName = StringHelper::Sprintf("%s/%s", GetParentFolderName(res).c_str(), dbgDecl->varName.c_str());
uint64_t hash = CRC64(dbgName.c_str()); uint64_t hash = CRC64(dbgName.c_str());
writer->Write((uint32_t)(G_MARKER << 24)); writer->Write((uint32_t)(G_MARKER << 24));
writer->Write((uint32_t)0xBEEFBEEF); writer->Write((uint32_t)0xBEEFBEEF);
@ -81,7 +67,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
auto dlStart = std::chrono::steady_clock::now(); auto dlStart = std::chrono::steady_clock::now();
//for (auto data : dList->instructions) //for (auto data : dList->instructions)
for (int dataIdx = 0; dataIdx < dList->instructions.size(); dataIdx++) for (size_t dataIdx = 0; dataIdx < dList->instructions.size(); dataIdx++)
{ {
auto data = dList->instructions[dataIdx]; auto data = dList->instructions[dataIdx];
uint32_t word0 = 0; uint32_t word0 = 0;
@ -209,14 +195,14 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
break; break;
case G_MTX: case G_MTX:
{ {
if ((!Globals::Instance->HasSegment(GETSEGNUM(data))) || ((data & 0xFFFFFFFF) == 0x07000000)) // En_Zf and En_Ny place a DL in segment 7 if ((!Globals::Instance->HasSegment(GETSEGNUM(data), res->parent->workerID)) || ((data & 0xFFFFFFFF) == 0x07000000)) // En_Zf and En_Ny place a DL in segment 7
{ {
uint32_t pp = (data & 0x000000FF00000000) >> 32; uint32_t pp = (data & 0x000000FF00000000) >> 32;
uint32_t mm = (data & 0x00000000FFFFFFFF); uint32_t mm = (data & 0x00000000FFFFFFFF);
pp ^= G_MTX_PUSH; pp ^= G_MTX_PUSH;
mm = (mm & 0x0FFFFFFF) + 0xF0000000; mm = (mm & 0x0FFFFFFF) + 1;
Gfx value = gsSPMatrix(mm, pp); Gfx value = gsSPMatrix(mm, pp);
word0 = value.words.w0; word0 = value.words.w0;
@ -243,7 +229,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
if (mtxDecl != nullptr) if (mtxDecl != nullptr)
{ {
std::string vName = StringHelper::Sprintf("%s\\%s", (GetParentFolderName(res).c_str()), mtxDecl->varName.c_str()); std::string vName = StringHelper::Sprintf("%s/%s", (GetParentFolderName(res).c_str()), mtxDecl->varName.c_str());
uint64_t hash = CRC64(vName.c_str()); uint64_t hash = CRC64(vName.c_str());
@ -347,7 +333,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
if (dListDecl != nullptr) if (dListDecl != nullptr)
{ {
std::string vName = StringHelper::Sprintf("%s\\%s", (GetParentFolderName(res).c_str()), dListDecl->varName.c_str()); std::string vName = StringHelper::Sprintf("%s/%s", (GetParentFolderName(res).c_str()), dListDecl->varName.c_str());
uint64_t hash = CRC64(vName.c_str()); uint64_t hash = CRC64(vName.c_str());
@ -370,7 +356,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
//std::string fName = StringHelper::Sprintf("%s\\%s", GetParentFolderName(res).c_str(), dListDecl2->varName.c_str()); //std::string fName = StringHelper::Sprintf("%s\\%s", GetParentFolderName(res).c_str(), dListDecl2->varName.c_str());
std::string fName = OTRExporter_DisplayList::GetPathToRes(res, dListDecl2->varName.c_str()); std::string fName = OTRExporter_DisplayList::GetPathToRes(res, dListDecl2->varName.c_str());
if (!File::Exists("Extract\\" + fName)) if (files.find(fName) == files.end() && !File::Exists("Extract/" + fName))
{ {
MemoryStream* dlStream = new MemoryStream(); MemoryStream* dlStream = new MemoryStream();
BinaryWriter dlWriter = BinaryWriter(dlStream); BinaryWriter dlWriter = BinaryWriter(dlStream);
@ -382,7 +368,10 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
//otrArchive->RemoveFile(fName); //otrArchive->RemoveFile(fName);
#endif #endif
File::WriteAllBytes("Extract\\" + fName, dlStream->ToVector()); if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory)
File::WriteAllBytes("Extract/" + fName, dlStream->ToVector());
else
files[fName] = dlStream->ToVector();
//otrArchive->AddFile(fName, (uintptr_t)dlStream->ToVector().data(), dlWriter.GetBaseAddress()); //otrArchive->AddFile(fName, (uintptr_t)dlStream->ToVector().data(), dlWriter.GetBaseAddress());
} }
@ -401,14 +390,14 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
//case G_BRANCH_Z: //case G_BRANCH_Z:
case G_DL: case G_DL:
{ {
if ((!Globals::Instance->HasSegment(GETSEGNUM(data)) && (int)opF3D != G_BRANCH_Z) if ((!Globals::Instance->HasSegment(GETSEGNUM(data), res->parent->workerID) && (int)opF3D != G_BRANCH_Z)
|| ((data & 0xFFFFFFFF) == 0x07000000)) // En_Zf and En_Ny place a DL in segment 7 || ((data & 0xFFFFFFFF) == 0x07000000)) // En_Zf and En_Ny place a DL in segment 7
{ {
int32_t pp = (data & 0x00FF000000000000) >> 56; int32_t pp = (data & 0x00FF000000000000) >> 56;
Gfx value; Gfx value;
u32 dListVal = (data & 0x0FFFFFFF) + 0xF0000000; u32 dListVal = (data & 0x0FFFFFFF) + 1;
if (pp != 0) if (pp != 0)
value = gsSPBranchList(dListVal); value = gsSPBranchList(dListVal);
@ -441,7 +430,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
if (dListDecl != nullptr) if (dListDecl != nullptr)
{ {
std::string vName = StringHelper::Sprintf("%s\\%s", (GetParentFolderName(res).c_str()), dListDecl->varName.c_str()); std::string vName = StringHelper::Sprintf("%s/%s", (GetParentFolderName(res).c_str()), dListDecl->varName.c_str());
uint64_t hash = CRC64(vName.c_str()); uint64_t hash = CRC64(vName.c_str());
@ -464,14 +453,17 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
//std::string fName = StringHelper::Sprintf("%s\\%s", GetParentFolderName(res).c_str(), dListDecl2->varName.c_str()); //std::string fName = StringHelper::Sprintf("%s\\%s", GetParentFolderName(res).c_str(), dListDecl2->varName.c_str());
std::string fName = OTRExporter_DisplayList::GetPathToRes(res, dListDecl2->varName.c_str()); std::string fName = OTRExporter_DisplayList::GetPathToRes(res, dListDecl2->varName.c_str());
if (!File::Exists("Extract\\" + fName)) if (files.find(fName) == files.end() && !File::Exists("Extract/" + fName))
{ {
MemoryStream* dlStream = new MemoryStream(); MemoryStream* dlStream = new MemoryStream();
BinaryWriter dlWriter = BinaryWriter(dlStream); BinaryWriter dlWriter = BinaryWriter(dlStream);
Save(dList->otherDLists[i], outPath, &dlWriter); Save(dList->otherDLists[i], outPath, &dlWriter);
File::WriteAllBytes("Extract\\" + fName, dlStream->ToVector()); if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory)
File::WriteAllBytes("Extract/" + fName, dlStream->ToVector());
else
files[fName] = dlStream->ToVector();
} }
} }
else else
@ -527,7 +519,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
int32_t bb = ((data & 0x0000FF0000000000ULL) >> 40) / 2; int32_t bb = ((data & 0x0000FF0000000000ULL) >> 40) / 2;
int32_t cc = ((data & 0x000000FF00000000ULL) >> 32) / 2; int32_t cc = ((data & 0x000000FF00000000ULL) >> 32) / 2;
int32_t dd = ((data & 0x000000000000FFULL)) / 2; int32_t dd = ((data & 0x000000000000FFULL)) / 2;
Gfx test = gsSP1Quadrangle(aa, bb, cc, dd, 0); Gfx test = gsSP1Quadrangle(aa, bb, cc, dd, 0);
word0 = test.words.w0; word0 = test.words.w0;
word1 = test.words.w1; word1 = test.words.w1;
@ -661,7 +653,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
{ {
int sss = (data & 0x00FFF00000000000) >> 44; int sss = (data & 0x00FFF00000000000) >> 44;
int ttt = (data & 0x00000FFF00000000) >> 32; int ttt = (data & 0x00000FFF00000000) >> 32;
int i = (data & 0x000000000F000000) >> 16; int i = (data & 0x000000000F000000) >> 24;
int uuu = (data & 0x0000000000FFF000) >> 12; int uuu = (data & 0x0000000000FFF000) >> 12;
int vvv= (data & 0x0000000000000FFF); int vvv= (data & 0x0000000000000FFF);
@ -675,7 +667,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
uint32_t seg = data & 0xFFFFFFFF; uint32_t seg = data & 0xFFFFFFFF;
int32_t texAddress = Seg2Filespace(data, dList->parent->baseAddress); int32_t texAddress = Seg2Filespace(data, dList->parent->baseAddress);
if (!Globals::Instance->HasSegment(GETSEGNUM(seg))) if (!Globals::Instance->HasSegment(GETSEGNUM(seg), res->parent->workerID))
{ {
int32_t __ = (data & 0x00FF000000000000) >> 48; int32_t __ = (data & 0x00FF000000000000) >> 48;
int32_t www = (data & 0x00000FFF00000000) >> 32; int32_t www = (data & 0x00000FFF00000000) >> 32;
@ -683,7 +675,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
uint32_t fmt = (__ & 0xE0) >> 5; uint32_t fmt = (__ & 0xE0) >> 5;
uint32_t siz = (__ & 0x18) >> 3; uint32_t siz = (__ & 0x18) >> 3;
Gfx value = gsDPSetTextureImage(fmt, siz, www - 1, (seg & 0x0FFFFFFF) + 0xF0000000); Gfx value = gsDPSetTextureImage(fmt, siz, www + 1, (seg & 0x0FFFFFFF) + 1);
word0 = value.words.w0; word0 = value.words.w0;
word1 = value.words.w1; word1 = value.words.w1;
@ -693,7 +685,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
else else
{ {
std::string texName = ""; std::string texName = "";
bool foundDecl = Globals::Instance->GetSegmentedPtrName(seg, dList->parent, "", texName); bool foundDecl = Globals::Instance->GetSegmentedPtrName(seg, dList->parent, "", texName, res->parent->workerID);
int32_t __ = (data & 0x00FF000000000000) >> 48; int32_t __ = (data & 0x00FF000000000000) >> 48;
int32_t www = (data & 0x00000FFF00000000) >> 32; int32_t www = (data & 0x00000FFF00000000) >> 32;
@ -701,7 +693,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
uint32_t fmt = (__ & 0xE0) >> 5; uint32_t fmt = (__ & 0xE0) >> 5;
uint32_t siz = (__ & 0x18) >> 3; uint32_t siz = (__ & 0x18) >> 3;
Gfx value = gsDPSetTextureImage(fmt, siz, www - 1, __); Gfx value = gsDPSetTextureImage(fmt, siz, www + 1, __);
word0 = value.words.w0 & 0x00FFFFFF; word0 = value.words.w0 & 0x00FFFFFF;
word0 += (G_SETTIMG_OTR << 24); word0 += (G_SETTIMG_OTR << 24);
//word1 = value.words.w1; //word1 = value.words.w1;
@ -712,10 +704,10 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
if (foundDecl) if (foundDecl)
{ {
ZFile* assocFile = Globals::Instance->GetSegment(GETSEGNUM(seg)); ZFile* assocFile = Globals::Instance->GetSegment(GETSEGNUM(seg), res->parent->workerID);
std::string assocFileName = assocFile->GetName(); std::string assocFileName = assocFile->GetName();
std::string fName = ""; std::string fName = "";
if (GETSEGNUM(seg) == SEGMENT_SCENE || GETSEGNUM(seg) == SEGMENT_ROOM) if (GETSEGNUM(seg) == SEGMENT_SCENE || GETSEGNUM(seg) == SEGMENT_ROOM)
fName = GetPathToRes(res, texName.c_str()); fName = GetPathToRes(res, texName.c_str());
else else
@ -747,45 +739,10 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
Gfx value = gsSPVertex(data & 0xFFFFFFFF, nn, ((aa >> 1) - nn)); Gfx value = gsSPVertex(data & 0xFFFFFFFF, nn, ((aa >> 1) - nn));
word0 = value.words.w0; word0 = value.words.w0;
word1 = value.words.w1 | 0xF0000000; word1 = value.words.w1 | 1;
} }
else else
//if (dList->vertices.size() > 0)
{ {
// Connect neighboring vertex arrays
std::vector<std::pair<uint32_t, std::vector<ZVtx>>> vertsKeys(dList->vertices.begin(),
dList->vertices.end());
if (vertsKeys.size() > 0)
{
auto lastItem = vertsKeys[0];
for (size_t i = 1; i < vertsKeys.size(); i++)
{
auto curItem = vertsKeys[i];
int32_t sizeDiff = curItem.first - (lastItem.first + (lastItem.second.size() * 16));
// Make sure there isn't an unaccounted inbetween these two
if (sizeDiff == 0)
{
for (auto v : curItem.second)
{
dList->vertices[lastItem.first].push_back(v);
lastItem.second.push_back(v);
}
dList->vertices.erase(curItem.first);
vertsKeys.erase(vertsKeys.begin() + i);
i--;
continue;
}
lastItem = curItem;
}
}
// Write CRC64 of vtx file name // Write CRC64 of vtx file name
uint32_t addr = data & 0xFFFFFFFF; uint32_t addr = data & 0xFFFFFFFF;
@ -793,10 +750,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
addr -= dList->parent->baseAddress; addr -= dList->parent->baseAddress;
auto segOffset = GETSEGOFFSET(addr); auto segOffset = GETSEGOFFSET(addr);
//uint32_t seg = data & 0xFFFFFFFF;
Declaration* vtxDecl = dList->parent->GetDeclarationRanged(segOffset); Declaration* vtxDecl = dList->parent->GetDeclarationRanged(segOffset);
//std::string vtxName = "";
//bool foundDecl = Globals::Instance->GetSegmentedPtrName(seg, dList->parent, "", vtxName);
int32_t aa = (data & 0x000000FF00000000ULL) >> 32; int32_t aa = (data & 0x000000FF00000000ULL) >> 32;
int32_t nn = (data & 0x000FF00000000000ULL) >> 44; int32_t nn = (data & 0x000FF00000000000ULL) >> 44;
@ -822,9 +776,8 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
word0 = hash >> 32; word0 = hash >> 32;
word1 = hash & 0xFFFFFFFF; word1 = hash & 0xFFFFFFFF;
if (!File::Exists("Extract\\" + fName)) if (files.find(fName) == files.end() && !File::Exists("Extract/" + fName))
{ {
//printf("Exporting VTX Data %s\n", fName.c_str());
// Write vertices to file // Write vertices to file
MemoryStream* vtxStream = new MemoryStream(); MemoryStream* vtxStream = new MemoryStream();
BinaryWriter vtxWriter = BinaryWriter(vtxStream); BinaryWriter vtxWriter = BinaryWriter(vtxStream);
@ -833,7 +786,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
auto split = StringHelper::Split(vtxDecl->text, "\n"); auto split = StringHelper::Split(vtxDecl->text, "\n");
for (int i = 0; i < split.size(); i++) for (size_t i = 0; i < split.size(); i++)
{ {
std::string line = split[i]; std::string line = split[i];
@ -847,44 +800,40 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
vtxWriter.Write((uint32_t)ZResourceType::Vertex); vtxWriter.Write((uint32_t)ZResourceType::Vertex);
vtxWriter.Write((uint32_t)arrCnt); vtxWriter.Write((uint32_t)arrCnt);
size_t sz = dList->vertices[vtxDecl->address].size(); auto start = std::chrono::steady_clock::now();
//if (sz > 0) // God dammit this is so dumb
for (size_t i = 0; i < split.size(); i++)
{ {
auto start = std::chrono::steady_clock::now(); std::string line = split[i];
// God dammit this is so dumb if (StringHelper::Contains(line, "VTX("))
for (size_t i = 0; i < split.size(); i++)
{ {
std::string line = split[i]; auto split2 = StringHelper::Split(StringHelper::Split(StringHelper::Split(line, "VTX(")[1], ")")[0], ",");
if (StringHelper::Contains(line, "VTX(")) vtxWriter.Write((int16_t)std::stoi(split2[0], nullptr, 10)); // v.x
{ vtxWriter.Write((int16_t)std::stoi(split2[1], nullptr, 10)); // v.y
auto split2 = StringHelper::Split(StringHelper::Split(StringHelper::Split(line, "VTX(")[1], ")")[0], ","); vtxWriter.Write((int16_t)std::stoi(split2[2], nullptr, 10)); // v.z
vtxWriter.Write((int16_t)std::stoi(split2[0], nullptr, 10)); // v.x vtxWriter.Write((int16_t)0); // v.flag
vtxWriter.Write((int16_t)std::stoi(split2[1], nullptr, 10)); // v.y
vtxWriter.Write((int16_t)std::stoi(split2[2], nullptr, 10)); // v.z
vtxWriter.Write((int16_t)0); // v.flag vtxWriter.Write((int16_t)std::stoi(split2[3], nullptr, 10)); // v.s
vtxWriter.Write((int16_t)std::stoi(split2[4], nullptr, 10)); // v.t
vtxWriter.Write((int16_t)std::stoi(split2[3], nullptr, 10)); // v.s
vtxWriter.Write((int16_t)std::stoi(split2[4], nullptr, 10)); // v.t vtxWriter.Write((uint8_t)std::stoi(split2[5], nullptr, 10)); // v.r
vtxWriter.Write((uint8_t)std::stoi(split2[6], nullptr, 10)); // v.g
vtxWriter.Write((uint8_t)std::stoi(split2[5], nullptr, 10)); // v.r vtxWriter.Write((uint8_t)std::stoi(split2[7], nullptr, 10)); // v.b
vtxWriter.Write((uint8_t)std::stoi(split2[6], nullptr, 10)); // v.g vtxWriter.Write((uint8_t)std::stoi(split2[8], nullptr, 10)); // v.a
vtxWriter.Write((uint8_t)std::stoi(split2[7], nullptr, 10)); // v.b
vtxWriter.Write((uint8_t)std::stoi(split2[8], nullptr, 10)); // v.a
}
} }
File::WriteAllBytes("Extract\\" + fName, vtxStream->ToVector());
auto end = std::chrono::steady_clock::now();
size_t diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
//printf("Exported VTX Array %s in %zums\n", fName.c_str(), diff);
} }
if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory)
File::WriteAllBytes("Extract/" + fName, vtxStream->ToVector());
else
files[fName] = vtxStream->ToVector();
auto end = std::chrono::steady_clock::now();
size_t diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
} }
} }
else else
@ -892,19 +841,10 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
spdlog::error("vtxDecl == nullptr!"); spdlog::error("vtxDecl == nullptr!");
} }
} }
/*else
{
writer->Write(word0);
writer->Write(word1);
word0 = 0;
word1 = 0;
spdlog::error("dList->vertices.size() <= 0!");
}*/
} }
break; break;
} }
writer->Write(word0); writer->Write(word0);
writer->Write(word1); writer->Write(word1);
} }
@ -918,7 +858,7 @@ void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, Bina
std::string OTRExporter_DisplayList::GetPathToRes(ZResource* res, std::string varName) std::string OTRExporter_DisplayList::GetPathToRes(ZResource* res, std::string varName)
{ {
std::string prefix = GetPrefix(res); std::string prefix = GetPrefix(res);
std::string fName = StringHelper::Sprintf("%s\\%s", GetParentFolderName(res).c_str(), varName.c_str()); std::string fName = StringHelper::Sprintf("%s/%s", GetParentFolderName(res).c_str(), varName.c_str());
return fName; return fName;
} }
@ -932,7 +872,7 @@ std::string OTRExporter_DisplayList::GetParentFolderName(ZResource* res)
{ {
auto split = StringHelper::Split(oName, "_"); auto split = StringHelper::Split(oName, "_");
oName = ""; oName = "";
for (int i = 0; i < split.size() - 1; i++) for (size_t i = 0; i < split.size() - 1; i++)
oName += split[i] + "_"; oName += split[i] + "_";
oName += "scene"; oName += "scene";
@ -943,7 +883,7 @@ std::string OTRExporter_DisplayList::GetParentFolderName(ZResource* res)
} }
if (prefix != "") if (prefix != "")
oName = prefix + "\\" + oName; oName = prefix + "/" + oName;
return oName; return oName;
} }

View File

@ -25,6 +25,7 @@ std::string otrFileName = "oot.otr";
std::shared_ptr<Ship::Archive> otrArchive; std::shared_ptr<Ship::Archive> otrArchive;
BinaryWriter* fileWriter; BinaryWriter* fileWriter;
std::chrono::steady_clock::time_point fileStart, resStart; std::chrono::steady_clock::time_point fileStart, resStart;
std::map<std::string, std::vector<char>> files;
void InitVersionInfo(); void InitVersionInfo();
@ -39,6 +40,8 @@ static void ExporterParseFileMode(const std::string& buildMode, ZFileMode& fileM
{ {
fileMode = (ZFileMode)ExporterFileMode::BuildOTR; fileMode = (ZFileMode)ExporterFileMode::BuildOTR;
printf("BOTR: Generating OTR Archive...\n");
if (File::Exists(otrFileName)) if (File::Exists(otrFileName))
otrArchive = std::shared_ptr<Ship::Archive>(new Ship::Archive(otrFileName, true)); otrArchive = std::shared_ptr<Ship::Archive>(new Ship::Archive(otrFileName, true));
else else
@ -49,11 +52,40 @@ static void ExporterParseFileMode(const std::string& buildMode, ZFileMode& fileM
for (auto item : lst) for (auto item : lst)
{ {
auto fileData = File::ReadAllBytes(item); auto fileData = File::ReadAllBytes(item);
otrArchive->AddFile(StringHelper::Split(item, "Extract\\")[1], (uintptr_t)fileData.data(), fileData.size()); otrArchive->AddFile(StringHelper::Split(item, "Extract/")[1], (uintptr_t)fileData.data(), fileData.size());
} }
} }
} }
static void ExporterProgramEnd()
{
if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
{
printf("Generating OTR Archive...\n");
otrArchive = Ship::Archive::CreateArchive(otrFileName, 65536 / 2);
for (auto item : files)
{
auto fileData = item.second;
otrArchive->AddFile(item.first, (uintptr_t)fileData.data(), fileData.size());
}
// Add any additional files that need to be manually copied...
auto lst = Directory::ListFiles("Extract");
for (auto item : lst)
{
auto fileData = File::ReadAllBytes(item);
otrArchive->AddFile(StringHelper::Split(item, "Extract/")[1], (uintptr_t)fileData.data(), fileData.size());
}
otrArchive->AddFile("Audiobank", (uintptr_t)Globals::Instance->GetBaseromFile("Audiobank").data(), Globals::Instance->GetBaseromFile("Audiobank").size());
otrArchive->AddFile("Audioseq", (uintptr_t)Globals::Instance->GetBaseromFile("Audioseq").data(), Globals::Instance->GetBaseromFile("Audioseq").size());
otrArchive->AddFile("Audiotable", (uintptr_t)Globals::Instance->GetBaseromFile("Audiotable").data(), Globals::Instance->GetBaseromFile("Audiotable").size());
}
}
static void ExporterParseArgs(int argc, char* argv[], int& i) static void ExporterParseArgs(int argc, char* argv[], int& i)
{ {
std::string arg = argv[i]; std::string arg = argv[i];
@ -85,6 +117,7 @@ static void ExporterFileBegin(ZFile* file)
static void ExporterFileEnd(ZFile* file) static void ExporterFileEnd(ZFile* file)
{ {
// delete fileWriter;
} }
static void ExporterResourceEnd(ZResource* res, BinaryWriter& writer) static void ExporterResourceEnd(ZResource* res, BinaryWriter& writer)
@ -107,7 +140,7 @@ static void ExporterResourceEnd(ZResource* res, BinaryWriter& writer)
{ {
auto split = StringHelper::Split(oName, "_"); auto split = StringHelper::Split(oName, "_");
oName = ""; oName = "";
for (int i = 0; i < split.size() - 1; i++) for (size_t i = 0; i < split.size() - 1; i++)
oName += split[i] + "_"; oName += split[i] + "_";
oName += "scene"; oName += "scene";
@ -120,11 +153,14 @@ static void ExporterResourceEnd(ZResource* res, BinaryWriter& writer)
std::string fName = ""; std::string fName = "";
if (prefix != "") if (prefix != "")
fName = StringHelper::Sprintf("%s\\%s\\%s", prefix.c_str(), oName.c_str(), rName.c_str()); fName = StringHelper::Sprintf("%s/%s/%s", prefix.c_str(), oName.c_str(), rName.c_str());
else else
fName = StringHelper::Sprintf("%s\\%s", oName.c_str(), rName.c_str()); fName = StringHelper::Sprintf("%s/%s", oName.c_str(), rName.c_str());
File::WriteAllBytes("Extract\\" + fName, strem->ToVector()); if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
files[fName] = strem->ToVector();
else
File::WriteAllBytes("Extract/" + fName, strem->ToVector());
} }
auto end = std::chrono::steady_clock::now(); auto end = std::chrono::steady_clock::now();
@ -155,6 +191,8 @@ static void ImportExporters()
exporterSet->beginXMLFunc = ExporterXMLBegin; exporterSet->beginXMLFunc = ExporterXMLBegin;
exporterSet->endXMLFunc = ExporterXMLEnd; exporterSet->endXMLFunc = ExporterXMLEnd;
exporterSet->resSaveFunc = ExporterResourceEnd; exporterSet->resSaveFunc = ExporterResourceEnd;
exporterSet->endProgramFunc = ExporterProgramEnd;
exporterSet->exporters[ZResourceType::Background] = new OTRExporter_Background(); exporterSet->exporters[ZResourceType::Background] = new OTRExporter_Background();
exporterSet->exporters[ZResourceType::Texture] = new OTRExporter_Texture(); exporterSet->exporters[ZResourceType::Texture] = new OTRExporter_Texture();
exporterSet->exporters[ZResourceType::Room] = new OTRExporter_Room(); exporterSet->exporters[ZResourceType::Room] = new OTRExporter_Room();

View File

@ -2,4 +2,5 @@
#include <Archive.h> #include <Archive.h>
extern std::shared_ptr<Ship::Archive> otrArchive; extern std::shared_ptr<Ship::Archive> otrArchive;
extern std::map<std::string, std::vector<char>> files;

View File

@ -39,13 +39,13 @@ D_FILES := $(O_FILES:%.o=%.d)
LIB := OTRExporter.a LIB := OTRExporter.a
INC_DIRS := $(addprefix -I, \ INC_DIRS := $(addprefix -I, \
../../ZAPD/ZAPD \ ../../ZAPDTR/ZAPD \
../../ZAPD/lib/tinyxml2 \ ../../ZAPDTR/lib/tinyxml2 \
../../ZAPD/lib/libgfxd \ ../../ZAPDTR/lib/libgfxd \
../../ZAPD/ZAPDUtils \ ../../ZAPDTR/ZAPDUtils \
../../OtrLib/otrlib \ ../../libultraship/libultraship \
../../OtrLib/otrlib/Lib/spdlog/include \ ../../libultraship/libultraship/Lib/spdlog/include \
../../OtrLib/otrlib/Lib/Fast3D/U64 \ ../../libultraship/libultraship/Lib/Fast3D/U64 \
) )
# create build directories # create build directories

View File

@ -63,6 +63,12 @@
<ClCompile Include="VersionInfo.cpp" /> <ClCompile Include="VersionInfo.cpp" />
<ClCompile Include="VtxExporter.cpp" /> <ClCompile Include="VtxExporter.cpp" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\OTRGui\build\ZERO_CHECK.vcxproj">
<Project>{02d10590-9542-3f55-aaf8-6055677e2a2a}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals"> <PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion> <VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
@ -118,19 +124,31 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<IncludePath>$(SolutionDir)otrlib;$(SolutionDir)\ZAPD\ZAPD\;$(SolutionDir)\ZAPD\lib\tinyxml2;$(SolutionDir)\ZAPD\lib\libgfxd;$(SolutionDir)\ZAPD\lib\elfio;$(SolutionDir)\ZAPD\lib\assimp\include;$(SolutionDir)\ZAPD\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath> <IncludePath>$(SolutionDir)otrlib;$(SolutionDir)\ZAPD\ZAPD\;$(SolutionDir)\ZAPD\lib\tinyxml2;$(SolutionDir)\ZAPD\lib\libgfxd;$(SolutionDir)\ZAPD\lib\elfio;$(SolutionDir)\ZAPD\lib\assimp\include;$(SolutionDir)\ZAPD\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<IncludePath>$(ProjectDir)..\..\ZAPDTR\ZAPD;$(ProjectDir)..\..\ZAPDTR\lib\tinyxml2;$(ProjectDir)..\..\ZAPDTR\lib\libgfxd;$(ProjectDir)..\..\ZAPDTR\ZAPDUtils;$(ProjectDir)..\..\libultraship\libultraship;$(ProjectDir)..\..\libultraship\libultraship\lib\spdlog\include;$(ProjectDir)..\..\libultraship\libultraship\Lib\Fast3D\U64;$(IncludePath)</IncludePath> <IncludePath>$(ProjectDir)..\..\ZAPDTR\ZAPD;$(ProjectDir)..\..\ZAPDTR\lib\tinyxml2;$(ProjectDir)..\..\ZAPDTR\lib\libgfxd;$(ProjectDir)..\..\ZAPDTR\ZAPDUtils;$(ProjectDir)..\..\libultraship\libultraship;$(ProjectDir)..\..\libultraship\libultraship\lib\spdlog\include;$(ProjectDir)..\..\libultraship\libultraship\Lib\Fast3D\U64;$(IncludePath)</IncludePath>
<LibraryPath>$(ProjectDir)..\..\libultraship\libultraship;$(LibraryPath)</LibraryPath> <LibraryPath>$(ProjectDir)..\..\libultraship\libultraship;$(LibraryPath)</LibraryPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<IncludePath>$(ProjectDir)..\..\ZAPDTR\ZAPD;$(ProjectDir)..\..\ZAPDTR\lib\tinyxml2;$(ProjectDir)..\..\ZAPDTR\lib\libgfxd;$(ProjectDir)..\..\ZAPDTR\ZAPDUtils;$(ProjectDir)..\..\libultraship\libultraship;$(ProjectDir)..\..\libultraship\libultraship\lib\spdlog\include;$(ProjectDir)..\..\libultraship\libultraship\Lib\Fast3D\U64;$(IncludePath)</IncludePath> <IncludePath>$(ProjectDir)..\..\ZAPDTR\ZAPD;$(ProjectDir)..\..\ZAPDTR\lib\tinyxml2;$(ProjectDir)..\..\ZAPDTR\lib\libgfxd;$(ProjectDir)..\..\ZAPDTR\ZAPDUtils;$(ProjectDir)..\..\libultraship\libultraship;$(ProjectDir)..\..\libultraship\libultraship\lib\spdlog\include;$(ProjectDir)..\..\libultraship\libultraship\Lib\Fast3D\U64;$(IncludePath)</IncludePath>
<LibraryPath>$(ProjectDir)..\..\libultraship\libultraship;$(LibraryPath)</LibraryPath> <LibraryPath>$(ProjectDir)..\..\libultraship\libultraship;$(LibraryPath)</LibraryPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>

View File

@ -9,11 +9,11 @@ void OTRExporter_Path::Save(ZResource* res, const fs::path& outPath, BinaryWrite
writer->Write((uint32_t)path->pathways.size()); writer->Write((uint32_t)path->pathways.size());
for (int k = 0; k < path->pathways.size(); k++) for (size_t k = 0; k < path->pathways.size(); k++)
{ {
writer->Write((uint32_t)path->pathways[k].points.size()); writer->Write((uint32_t)path->pathways[k].points.size());
for (int i = 0; i < path->pathways[k].points.size(); i++) for (size_t i = 0; i < path->pathways[k].points.size(); i++)
{ {
writer->Write(path->pathways[k].points[i].scalars[0].scalarData.s16); writer->Write(path->pathways[k].points[i].scalars[0].scalarData.s16);
writer->Write(path->pathways[k].points[i].scalars[1].scalarData.s16); writer->Write(path->pathways[k].points[i].scalars[1].scalarData.s16);

View File

@ -46,7 +46,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
for (size_t i = 0; i < room->commands.size(); i++) for (size_t i = 0; i < room->commands.size(); i++)
{ {
ZRoomCommand* cmd = room->commands[i]; ZRoomCommand* cmd = room->commands[i];
writer->Write((uint32_t)cmd->cmdID); writer->Write((uint32_t)cmd->cmdID);
switch (cmd->cmdID) switch (cmd->cmdID)
@ -172,7 +172,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
writer->Write((uint32_t)cmdCsCam->points.size()); writer->Write((uint32_t)cmdCsCam->points.size());
for (int i = 0; i < cmdCsCam->points.size(); i++) for (size_t i = 0; i < cmdCsCam->points.size(); i++)
{ {
writer->Write(cmdCsCam->points[i].scalars[0].scalarData.s16); writer->Write(cmdCsCam->points[i].scalars[0].scalarData.s16);
writer->Write(cmdCsCam->points[i].scalars[1].scalarData.s16); writer->Write(cmdCsCam->points[i].scalars[1].scalarData.s16);
@ -183,7 +183,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
case RoomCommand::SetMesh: case RoomCommand::SetMesh:
{ {
SetMesh* cmdMesh = (SetMesh*)cmd; SetMesh* cmdMesh = (SetMesh*)cmd;
writer->Write((uint8_t)cmdMesh->data); // 0x01 writer->Write((uint8_t)cmdMesh->data); // 0x01
writer->Write(cmdMesh->meshHeaderType); writer->Write(cmdMesh->meshHeaderType);
@ -207,12 +207,12 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
Declaration* dListDeclXlu = poly->parent->GetDeclaration(GETSEGOFFSET(test->xlu)); Declaration* dListDeclXlu = poly->parent->GetDeclaration(GETSEGOFFSET(test->xlu));
if (test->opa != 0) if (test->opa != 0)
writer->Write(StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclOpa->varName.c_str())); writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclOpa->varName.c_str()));
else else
writer->Write(""); writer->Write("");
if (test->xlu != 0) if (test->xlu != 0)
writer->Write(StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclXlu->varName.c_str())); writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclXlu->varName.c_str()));
else else
writer->Write(""); writer->Write("");
@ -228,7 +228,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
Declaration* bgDecl = poly->parent->GetDeclarationRanged(GETSEGOFFSET(poly->multiList[i].source)); Declaration* bgDecl = poly->parent->GetDeclarationRanged(GETSEGOFFSET(poly->multiList[i].source));
writer->Write(OTRExporter_DisplayList::GetPathToRes(poly->multiList[i].sourceBackground, bgDecl->varName)); writer->Write(OTRExporter_DisplayList::GetPathToRes(poly->multiList[i].sourceBackground, bgDecl->varName));
writer->Write(poly->multiList[i].unk_0C); writer->Write(poly->multiList[i].unk_0C);
writer->Write(poly->multiList[i].tlut); writer->Write(poly->multiList[i].tlut);
writer->Write(poly->multiList[i].width); writer->Write(poly->multiList[i].width);
@ -338,7 +338,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
for (size_t i = 0;i < cmdRoom->romfile->numRooms; i++) for (size_t i = 0;i < cmdRoom->romfile->numRooms; i++)
{ {
//std::string roomName = StringHelper::Sprintf("%s\\%s_room_%i", (StringHelper::Split(room->GetName(), "_")[0] + "_scene").c_str(), StringHelper::Split(room->GetName(), "_scene")[0].c_str(), i); //std::string roomName = StringHelper::Sprintf("%s/%s_room_%i", (StringHelper::Split(room->GetName(), "_")[0] + "_scene").c_str(), StringHelper::Split(room->GetName(), "_scene")[0].c_str(), i);
std::string roomName = OTRExporter_DisplayList::GetPathToRes(room, StringHelper::Sprintf("%s_room_%i", StringHelper::Split(room->GetName(), "_scene")[0].c_str(), i)); std::string roomName = OTRExporter_DisplayList::GetPathToRes(room, StringHelper::Sprintf("%s_room_%i", StringHelper::Split(room->GetName(), "_scene")[0].c_str(), i));
writer->Write(roomName); writer->Write(roomName);
writer->Write(cmdRoom->romfile->rooms[i].virtualAddressStart); writer->Write(cmdRoom->romfile->rooms[i].virtualAddressStart);
@ -383,7 +383,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
uint32_t baseStreamEnd = writer->GetStream().get()->GetLength(); uint32_t baseStreamEnd = writer->GetStream().get()->GetLength();
writer->Write((uint32_t)cmdStartPos->actors.size()); // 0x01 writer->Write((uint32_t)cmdStartPos->actors.size()); // 0x01
for (const ActorSpawnEntry& entry : cmdStartPos->actors) for (const ActorSpawnEntry& entry : cmdStartPos->actors)
{ {
writer->Write(entry.actorNum); writer->Write(entry.actorNum);
@ -407,7 +407,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
{ {
uint32_t seg = cmdHeaders->headers[i] & 0xFFFFFFFF; uint32_t seg = cmdHeaders->headers[i] & 0xFFFFFFFF;
std::string headerName = ""; std::string headerName = "";
bool foundDecl = Globals::Instance->GetSegmentedPtrName(seg, room->parent, "", headerName); bool foundDecl = Globals::Instance->GetSegmentedPtrName(seg, room->parent, "", headerName, res->parent->workerID);
if (headerName == "NULL") if (headerName == "NULL")
writer->Write(""); writer->Write("");
else else
@ -441,9 +441,9 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
case RoomCommand::SetCutscenes: case RoomCommand::SetCutscenes:
{ {
SetCutscenes* cmdSetCutscenes = (SetCutscenes*)cmd; SetCutscenes* cmdSetCutscenes = (SetCutscenes*)cmd;
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdSetCutscenes->cmdArg2, room->parent, "CutsceneData", listName); Globals::Instance->GetSegmentedPtrName(cmdSetCutscenes->cmdArg2, room->parent, "CutsceneData", listName, res->parent->workerID);
std::string fName = OTRExporter_DisplayList::GetPathToRes(room, listName); std::string fName = OTRExporter_DisplayList::GetPathToRes(room, listName);
//std::string fName = StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), listName.c_str()); //std::string fName = StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), listName.c_str());
writer->Write(fName); writer->Write(fName);
@ -453,7 +453,10 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
OTRExporter_Cutscene cs; OTRExporter_Cutscene cs;
cs.Save(cmdSetCutscenes->cutscenes[0], "", &csWriter); cs.Save(cmdSetCutscenes->cutscenes[0], "", &csWriter);
File::WriteAllBytes("Extract\\" + fName, csStream->ToVector()); if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory)
File::WriteAllBytes("Extract/" + fName, csStream->ToVector());
else
files[fName] = csStream->ToVector();
//std::string fName = OTRExporter_DisplayList::GetPathToRes(res, vtxDecl->varName); //std::string fName = OTRExporter_DisplayList::GetPathToRes(res, vtxDecl->varName);
//otrArchive->AddFile(fName, (uintptr_t)csStream->ToVector().data(), csWriter.GetBaseAddress()); //otrArchive->AddFile(fName, (uintptr_t)csStream->ToVector().data(), csWriter.GetBaseAddress());
@ -465,7 +468,7 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
writer->Write((uint32_t)cmdSetPathways->pathwayList.pathways.size()); writer->Write((uint32_t)cmdSetPathways->pathwayList.pathways.size());
for (int i = 0; i < cmdSetPathways->pathwayList.pathways.size(); i++) for (size_t i = 0; i < cmdSetPathways->pathwayList.pathways.size(); i++)
{ {
Declaration* decl = room->parent->GetDeclaration(GETSEGOFFSET(cmdSetPathways->pathwayList.pathways[i].listSegmentAddress)); Declaration* decl = room->parent->GetDeclaration(GETSEGOFFSET(cmdSetPathways->pathwayList.pathways[i].listSegmentAddress));
//std::string path = StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), decl->varName.c_str()); //std::string path = StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), decl->varName.c_str());
@ -477,7 +480,10 @@ void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWrite
OTRExporter_Path pathExp; OTRExporter_Path pathExp;
pathExp.Save(&cmdSetPathways->pathwayList, outPath, &pathWriter); pathExp.Save(&cmdSetPathways->pathwayList, outPath, &pathWriter);
File::WriteAllBytes("Extract\\" + path, pathStream->ToVector()); if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory)
File::WriteAllBytes("Extract/" + path, pathStream->ToVector());
else
files[path] = pathStream->ToVector();
//otrArchive->AddFile(path, (uintptr_t)pathStream->ToVector().data(), pathWriter.GetBaseAddress()); //otrArchive->AddFile(path, (uintptr_t)pathStream->ToVector().data(), pathWriter.GetBaseAddress());
@ -508,12 +514,12 @@ void OTRExporter_Room::WritePolyDList(BinaryWriter* writer, ZRoom* room, Polygon
writer->Write(dlist->unk_06); writer->Write(dlist->unk_06);
[[fallthrough]]; [[fallthrough]];
default: default:
//writer->Write(StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclOpa->varName.c_str())); //writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclOpa->varName.c_str()));
if (dlist->opaDList != nullptr) if (dlist->opaDList != nullptr)
{ {
auto opaDecl = room->parent->GetDeclaration(GETSEGOFFSET(dlist->opaDList->GetRawDataIndex())); auto opaDecl = room->parent->GetDeclaration(GETSEGOFFSET(dlist->opaDList->GetRawDataIndex()));
writer->Write(StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), opaDecl->varName.c_str())); writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), opaDecl->varName.c_str()));
} }
else else
writer->Write(""); writer->Write("");
@ -521,7 +527,7 @@ void OTRExporter_Room::WritePolyDList(BinaryWriter* writer, ZRoom* room, Polygon
if (dlist->xluDList != nullptr) if (dlist->xluDList != nullptr)
{ {
auto xluDecl = room->parent->GetDeclaration(GETSEGOFFSET(dlist->xluDList->GetRawDataIndex())); auto xluDecl = room->parent->GetDeclaration(GETSEGOFFSET(dlist->xluDList->GetRawDataIndex()));
writer->Write(StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), xluDecl->varName.c_str())); writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), xluDecl->varName.c_str()));
} }
else else
writer->Write(""); writer->Write("");

View File

@ -23,7 +23,7 @@ void OTRExporter_Skeleton::Save(ZResource* res, const fs::path& outPath, BinaryW
Declaration* skelDecl = skel->parent->GetDeclarationRanged(GETSEGOFFSET(skel->limbsTable.limbsAddresses[i])); Declaration* skelDecl = skel->parent->GetDeclarationRanged(GETSEGOFFSET(skel->limbsTable.limbsAddresses[i]));
std::string name; std::string name;
bool foundDecl = Globals::Instance->GetSegmentedPtrName(skel->limbsTable.limbsAddresses[i], skel->parent, "", name); bool foundDecl = Globals::Instance->GetSegmentedPtrName(skel->limbsTable.limbsAddresses[i], skel->parent, "", name, res->parent->workerID);
if (foundDecl) if (foundDecl)
{ {
if (name.at(0) == '&') if (name.at(0) == '&')

View File

@ -86,7 +86,7 @@ void OTRExporter_SkeletonLimb::Save(ZResource* res, const fs::path& outPath, Bin
if (limb->childPtr != 0) if (limb->childPtr != 0)
{ {
std::string name; std::string name;
bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->childPtr, limb->parent, "", name); bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->childPtr, limb->parent, "", name, res->parent->workerID);
if (foundDecl) if (foundDecl)
{ {
if (name.at(0) == '&') if (name.at(0) == '&')
@ -107,7 +107,7 @@ void OTRExporter_SkeletonLimb::Save(ZResource* res, const fs::path& outPath, Bin
if (limb->siblingPtr != 0) if (limb->siblingPtr != 0)
{ {
std::string name; std::string name;
bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->siblingPtr, limb->parent, "", name); bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->siblingPtr, limb->parent, "", name, res->parent->workerID);
if (foundDecl) if (foundDecl)
{ {
if (name.at(0) == '&') if (name.at(0) == '&')
@ -128,7 +128,7 @@ void OTRExporter_SkeletonLimb::Save(ZResource* res, const fs::path& outPath, Bin
if (limb->dListPtr != 0) if (limb->dListPtr != 0)
{ {
std::string name; std::string name;
bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->dListPtr, limb->parent, "", name); bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->dListPtr, limb->parent, "", name, res->parent->workerID);
if (foundDecl) if (foundDecl)
{ {
if (name.at(0) == '&') if (name.at(0) == '&')
@ -149,7 +149,7 @@ void OTRExporter_SkeletonLimb::Save(ZResource* res, const fs::path& outPath, Bin
if (limb->dList2Ptr != 0) if (limb->dList2Ptr != 0)
{ {
std::string name; std::string name;
bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->dList2Ptr, limb->parent, "", name); bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->dList2Ptr, limb->parent, "", name, res->parent->workerID);
if (foundDecl) if (foundDecl)
{ {
if (name.at(0) == '&') if (name.at(0) == '&')

View File

@ -8,8 +8,8 @@ void OTRExporter_Text::Save(ZResource* res, const fs::path& outPath, BinaryWrite
WriteHeader(txt, outPath, writer, Ship::ResourceType::Text); WriteHeader(txt, outPath, writer, Ship::ResourceType::Text);
writer->Write((uint32_t)txt->messages.size()); writer->Write((uint32_t)txt->messages.size());
for (int i = 0; i < txt->messages.size(); i++) for (size_t i = 0; i < txt->messages.size(); i++)
{ {
writer->Write(txt->messages[i].id); writer->Write(txt->messages[i].id);
writer->Write(txt->messages[i].textboxType); writer->Write(txt->messages[i].textboxType);

View File

@ -5,21 +5,23 @@ std::map<Ship::ResourceType, uint32_t> resourceVersions;
void InitVersionInfo() void InitVersionInfo()
{ {
resourceVersions[Ship::ResourceType::Animation] = 0; resourceVersions = {
resourceVersions[Ship::ResourceType::Model] = 0; { Ship::ResourceType::Animation, 0 },
resourceVersions[Ship::ResourceType::Texture] = 0; { Ship::ResourceType::Model, 0 },
resourceVersions[Ship::ResourceType::Material] = 0; { Ship::ResourceType::Texture, 0 },
resourceVersions[Ship::ResourceType::PlayerAnimation] = 0; { Ship::ResourceType::Material, 0 },
resourceVersions[Ship::ResourceType::DisplayList] = 0; { Ship::ResourceType::PlayerAnimation, 0 },
resourceVersions[Ship::ResourceType::Room] = 0; { Ship::ResourceType::DisplayList, 0 },
resourceVersions[Ship::ResourceType::CollisionHeader] = 0; { Ship::ResourceType::Room, 0 },
resourceVersions[Ship::ResourceType::Skeleton] = 0; { Ship::ResourceType::CollisionHeader, 0 },
resourceVersions[Ship::ResourceType::SkeletonLimb] = 0; { Ship::ResourceType::Skeleton, 0 },
resourceVersions[Ship::ResourceType::Matrix] = 0; { Ship::ResourceType::SkeletonLimb, 0 },
resourceVersions[Ship::ResourceType::Path] = 0; { Ship::ResourceType::Matrix, 0 },
resourceVersions[Ship::ResourceType::Vertex] = 0; { Ship::ResourceType::Path, 0 },
resourceVersions[Ship::ResourceType::Cutscene] = 0; { Ship::ResourceType::Vertex, 0 },
resourceVersions[Ship::ResourceType::Array] = 0; { Ship::ResourceType::Cutscene, 0 },
resourceVersions[Ship::ResourceType::Text] = 0; { Ship::ResourceType::Array, 0 },
resourceVersions[Ship::ResourceType::Blob] = 0; { Ship::ResourceType::Text, 0 },
{ Ship::ResourceType::Blob, 0 },
};
} }

View File

@ -1,24 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse, json, os, signal, time, sys, shutil import os, sys, shutil
from multiprocessing import Pool, cpu_count, Event, Manager, ProcessError
import shutil import shutil
from rom_info import Z64Rom
import rom_chooser
def SignalHandler(sig, frame): def BuildOTR(xmlPath, rom):
print(f'Signal {sig} received. Aborting...')
mainAbort.set()
# Don't exit immediately to update the extracted assets file.
def BuildOTR():
shutil.copyfile("baserom/Audiobank", "Extract/Audiobank")
shutil.copyfile("baserom/Audioseq", "Extract/Audioseq")
shutil.copyfile("baserom/Audiotable", "Extract/Audiotable")
shutil.copytree("assets", "Extract/assets") shutil.copytree("assets", "Extract/assets")
execStr = "x64\\Release\\ZAPD.exe" if sys.platform == "win32" else "../ZAPD/ZAPD.out" execStr = "x64\\Release\\ZAPD.exe" if sys.platform == "win32" else "../ZAPDTR/ZAPD.out"
execStr += " ed -i %s -b %s -fl CFG/filelists -o placeholder -osf placeholder -gsf 1 -rconf CFG/Config.xml -se OTR" % (xmlPath, rom)
execStr += " botr -se OTR"
print(execStr) print(execStr)
exitValue = os.system(execStr) exitValue = os.system(execStr)
@ -28,90 +19,14 @@ def BuildOTR():
print("Aborting...", file=os.sys.stderr) print("Aborting...", file=os.sys.stderr)
print("\n") print("\n")
def ExtractFile(xmlPath, outputPath, outputSourcePath):
execStr = "x64\\Release\\ZAPD.exe" if sys.platform == "win32" else "../ZAPD/ZAPD.out"
execStr += " e -eh -i %s -b baserom/ -o %s -osf %s -gsf 1 -rconf CFG/Config.xml -se OTR" % (xmlPath, outputPath, outputSourcePath)
if "overlays" in xmlPath:
execStr += " --static"
print(execStr)
exitValue = os.system(execStr)
#exitValue = 0
if exitValue != 0:
print("\n")
print("Error when extracting from file " + xmlPath, file=os.sys.stderr)
print("Aborting...", file=os.sys.stderr)
print("\n")
def ExtractFunc(fullPath):
*pathList, xmlName = fullPath.split(os.sep)
objectName = os.path.splitext(xmlName)[0]
outPath = os.path.join("..\\soh\\assets\\", *pathList[4:], objectName)
os.makedirs(outPath, exist_ok=True)
outSourcePath = outPath
ExtractFile(fullPath, outPath, outSourcePath)
def initializeWorker(abort, test):
global globalAbort
globalAbort = abort
def main(): def main():
parser = argparse.ArgumentParser(description="baserom asset extractor") rom_path = rom_chooser.chooseROM()
parser.add_argument("-s", "--single", help="asset path relative to assets/, e.g. objects/gameplay_keep") rom = Z64Rom(rom_path)
parser.add_argument("-f", "--force", help="Force the extraction of every xml instead of checking the touched ones.", action="store_true")
parser.add_argument("-u", "--unaccounted", help="Enables ZAPD unaccounted detector warning system.", action="store_true")
args = parser.parse_args()
global mainAbort if (os.path.exists("Extract")):
mainAbort = Event()
manager = Manager()
signal.signal(signal.SIGINT, SignalHandler)
extractedAssetsTracker = manager.dict()
asset_path = args.single
if asset_path is not None:
fullPath = os.path.join("..\\soh\\assets", "xml", asset_path + ".xml")
if not os.path.exists(fullPath):
print(f"Error. File {fullPath} doesn't exists.", file=os.sys.stderr)
exit(1)
ExtractFunc(fullPath)
else:
extract_text_path = "assets/text/message_data.h"
if os.path.isfile(extract_text_path):
extract_text_path = None
extract_staff_text_path = "assets/text/message_data_staff.h"
if os.path.isfile(extract_staff_text_path):
extract_staff_text_path = None
xmlFiles = []
for currentPath, _, files in os.walk(os.path.join("..\\soh\\assets", "xml")):
for file in files:
fullPath = os.path.join(currentPath, file)
if file.endswith(".xml"):
xmlFiles.append(fullPath)
try:
numCores = 2
print("Extracting assets with " + str(numCores) + " CPU cores.")
with Pool(numCores, initializer=initializeWorker, initargs=(mainAbort, 0)) as p:
p.map(ExtractFunc, xmlFiles)
except Exception as e:
print("Warning: Multiprocessing exception ocurred.", file=os.sys.stderr)
print("Disabling mutliprocessing.", file=os.sys.stderr)
initializeWorker(mainAbort, 0)
for singlePath in xmlFiles:
ExtractFunc(singlePath)
BuildOTR()
shutil.rmtree("Extract") shutil.rmtree("Extract")
BuildOTR("../soh/assets/xml/" + rom.version.xml_ver + "/", rom_path)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -0,0 +1,53 @@
#!/usr/bin/python3
import os
import sys
import struct
from multiprocessing import Pool, cpu_count
from rom_info import Z64Rom
import rom_chooser
rom = None
def initialize_worker(input_rom):
global rom
rom = input_rom
def ExtractFunc(i):
dma_file = rom.getDmaEntryByIndex(i)
dma_data = rom.readDmaEntry(dma_file)
filename = '../soh/baserom/' + rom.version.file_table[i]
print('extracting ' + filename + " (0x%08X, 0x%08X)" % (dma_file.virtStart, dma_file.virtEnd))
try:
with open(filename, 'wb') as f:
f.write(dma_data)
except IOError:
print('failed to write file ' + filename)
# TODO: handle this better
if dma_file.compressed:
os.system('tools/yaz0 -d ' + filename + ' ' + filename)
#####################################################################
def main():
try:
os.mkdir('../soh/baserom')
except:
pass
rom_path = rom_chooser.chooseROM()
input_rom = Z64Rom(rom_path)
# extract files
num_cores = cpu_count()
print("Extracting baserom with " + str(num_cores) + " CPU cores.")
with Pool(num_cores, initialize_worker, (input_rom,)) as p:
p.map(ExtractFunc, range(len(input_rom.version.file_table)))
if __name__ == "__main__":
main()

View File

@ -0,0 +1,37 @@
import os, sys, glob
from rom_info import Z64Rom
def chooseROM():
roms = []
for file in glob.glob("*.z64"):
if Z64Rom.isValidRom(file):
roms.append(file)
if not (roms):
print("Error: No roms located, place one in the OTRExporter directory", file=os.sys.stderr)
sys.exit(1)
if (len(roms) == 1):
return roms[0]
print(str(len(roms))+ " roms found, please select one by pressing 1-"+str(len(roms)))
for i in range(len(roms)):
print(str(i+1)+ ". " + roms[i])
while(1):
try:
selection = int(input())
except:
print("Bad input. Try again with the number keys.")
continue
if (selection < 1 or selection > len(roms)):
print("Bad input. Try again.")
continue
else: break
return roms[selection - 1]

87
OTRExporter/rom_info.py Normal file
View File

@ -0,0 +1,87 @@
from enum import Enum
from tabnanny import check
import struct
class Checksums(Enum):
OOT_NTSC_10 = "EC7011B7"
OOT_NTSC_11 = "D43DA81F"
OOT_NTSC_12 = "693BA2AE"
OOT_PAL_10 = "B044B569"
OOT_PAL_11 = "B2055FBD"
OOT_NTSC_JP_GC_CE = "F7F52DB8"
OOT_NTSC_JP_GC = "F611F4BA"
OOT_NTSC_US_GC = "F3DD35BA"
OOT_PAL_GC = "09465AC3"
OOT_NTSC_JP_MQ = "F43B45BA"
OOT_NTSC_US_MQ = "F034001A"
OOT_PAL_MQ = "1D4136F3"
OOT_PAL_GC_DBG1 = "871E1C92"
OOT_PAL_GC_DBG2 = "87121EFE"
OOT_PAL_GC_MQ_DBG = "917D18F6"
OOT_IQUE_TW = "3D81FB3E"
OOT_IQUE_CN = "B1E1E07B"
OOT_UNKNOWN = "FFFFFFFF"
@classmethod
def has_value(self, value):
return value in self._value2member_map_
class RomVersion:
def __init__(self, file_table_path, file_table_off, xml_ver):
self.file_table_off = file_table_off
self.xml_ver = xml_ver
with open(file_table_path, 'r') as f:
self.file_table = [line.strip('\n') for line in f]
ROM_INFO_TABLE = dict()
ROM_INFO_TABLE[Checksums.OOT_PAL_GC] = RomVersion("CFG/filelists/gamecube_pal.txt", 0x7170, "GC_NMQ_PAL_F")
ROM_INFO_TABLE[Checksums.OOT_PAL_GC_DBG1] = RomVersion("CFG/filelists/dbg.txt", 0x12F70, "GC_NMQ_D")
class RomDmaEntry:
def __init__(self, rom, i):
off = rom.version.file_table_off + 16 * i
(self.virtStart, \
self.virtEnd, \
self.physStart, \
self.physEnd) = struct.unpack('>IIII', rom.rom_data[off:off+4*4])
self.compressed = self.physEnd != 0
self.size = self.physEnd - self.physStart \
if self.compressed \
else self.virtEnd - self.virtStart
self.name = rom.version.file_table[i]
class Z64Rom:
def __init__(self, file_path):
self.file_path = file_path
with open(file_path, 'rb') as f:
self.rom_data = f.read()
self.is_valid = len(self.rom_data) > 20 * 1024 * 1024
if not self.is_valid:
return
# get checkum
checksum_str = self.rom_data[16:16+4].hex().upper()
self.checksum = Checksums(checksum_str) if Checksums.has_value(checksum_str) else Checksums.OOT_UNKNOWN
if self.checksum == Checksums.OOT_UNKNOWN:
self.is_valid = False
return
# get rom version
self.version = ROM_INFO_TABLE[self.checksum]
def getDmaEntryByIndex(self, i):
return RomDmaEntry(self, i)
def readDmaEntry(self, entry):
return self.rom_data[entry.physStart:entry.physStart + entry.size]
@staticmethod
def isValidRom(rom_path):
return Z64Rom(rom_path).is_valid

View File

@ -2,7 +2,7 @@
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/> <SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/> <ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/> <ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/"/> <ExternalXMLFolder Path="assets/extractor/xmls/GC_MQ_D/"/>
<TexturePool File="TexturePool.xml"/> <TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/> <ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root> </Root>

View File

@ -0,0 +1,8 @@
<Root>
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_D/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

View File

@ -0,0 +1,8 @@
<Root>
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_PAL_F/"/>
<TexturePool File="TexturePool.xml"/>
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
</Root>

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ Shader shader = { 0 };
Light light = { 0 }; Light light = { 0 };
Vector3 lightPos = { -5.0f, 10.0f, 10.0f }; Vector3 lightPos = { -5.0f, 10.0f, 10.0f };
Vector2 dragOffset; Vector2 dragOffset;
bool isDragging = false;
std::string sohFolder = NULLSTR; std::string sohFolder = NULLSTR;
bool extracting = false; bool extracting = false;
bool rom_ready = false; bool rom_ready = false;
@ -25,6 +26,7 @@ bool single_thread = false;
bool hide_second_btn = false; bool hide_second_btn = false;
RomVersion version; RomVersion version;
const char* patched_rom = "tmp/rom.z64"; const char* patched_rom = "tmp/rom.z64";
extern bool oldExtractMode;
static std::string currentStep = "None"; static std::string currentStep = "None";
@ -65,17 +67,35 @@ void OTRGame::init(){
mat.shader = shader; mat.shader = shader;
} }
if(fs::exists("soh.exe") && !fs::exists("oot.otr")) { if((fs::exists("soh.exe") || fs::exists("soh.elf")) && !fs::exists("oot.otr")) {
hide_second_btn = true; hide_second_btn = true;
sohFolder = "."; sohFolder = ".";
} }
} }
void ExtractRom() { void ExtractRom()
const WriteResult result = ExtractBaserom(patched_rom); {
WriteResult result;
if (oldExtractMode)
ExtractBaserom(patched_rom);
else
result.error = NULLSTR;
if (result.error == NULLSTR) { if (result.error == NULLSTR) {
if (MoonUtils::exists("oot.otr")) MoonUtils::rm("oot.otr"); if (MoonUtils::exists("oot.otr")) MoonUtils::rm("oot.otr");
startWorker(); if (MoonUtils::exists("Extract")) MoonUtils::rm("Extract");
MoonUtils::mkdir("Extract");
//MoonUtils::copy("tmp/baserom/Audiobank", "Extract/Audiobank");
//MoonUtils::copy("tmp/baserom/Audioseq", "Extract/Audioseq");
//MoonUtils::copy("tmp/baserom/Audiotable", "Extract/Audiotable");
//MoonUtils::copy("tmp/baserom/version", "Extract/version");
MoonUtils::write("Extract/version", (char*)&version.crc, sizeof(version.crc));
MoonUtils::copy("assets/game/", "Extract/assets/");
startWorker(version);
extracting = true; extracting = true;
} }
} }
@ -95,69 +115,103 @@ void OTRGame::update(){
} }
void OTRGame::draw() { void OTRGame::draw() {
Vector2 windowSize(GetScreenWidth(), GetScreenHeight());
Rectangle titlebar = Rectangle(0, 0, windowSize.x - 50, 35);
Vector2 mousePos = GetMousePosition();
Vector2 mouseDelta = GetMouseDelta();
if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && !isDragging &&
mousePos.x >= titlebar.x && mousePos.y >= titlebar.y && mousePos.x <= titlebar.x + titlebar.width && mousePos.y <= titlebar.y + titlebar.height) {
isDragging = true;
dragOffset = mousePos;
}
else if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT) && isDragging) {
isDragging = false;
dragOffset = Vector2(0, 0);
}
if (isDragging && (mouseDelta.x != 0.0f || mouseDelta.y != 0.0f)) {
Vector2 wndPos = GetWindowPosition();
wndPos = Vector2(wndPos.x + (mousePos.x - dragOffset.x), wndPos.y + (mousePos.y - dragOffset.y));
// Calculate virtual screen total size in case there are multiple monitors
int vsX1 = 0, vsY1 = 0, vsX2 = 0, vsY2 = 0;
int monitorCount = GetMonitorCount();
for (int m = 0; m < monitorCount; m++) {
Vector2 monitorPos = GetMonitorPosition(m);
Vector2 monitorSize = Vector2(GetMonitorWidth(m), GetMonitorHeight(m));
if (monitorPos.x < vsX1) vsX1 = monitorPos.x;
if (monitorPos.y < vsY1) vsY1 = monitorPos.y;
if (monitorPos.x + monitorSize.x > vsX2) vsX2 = monitorPos.x + monitorSize.x;
if (monitorPos.y + monitorSize.y > vsY2) vsY2 = monitorPos.y + monitorSize.y;
}
// Clamp the window to the borders of the monitors
if (wndPos.x < vsX1) wndPos.x = vsX1;
if (wndPos.x < vsX1) wndPos.x = vsX1;
if (wndPos.y < vsY1) wndPos.y = vsY1;
if (wndPos.x + windowSize.x > vsX2) wndPos.x = vsX2 - windowSize.x;
if (wndPos.y + windowSize.y > vsY2) wndPos.y = vsY2 - windowSize.y;
SetWindowPosition(wndPos.x, wndPos.y);
}
BeginDrawing(); BeginDrawing();
ClearBackground(Color(40, 40, 40, 255)); ClearBackground(Color(40, 40, 40, 255));
Vector3 windowSize(GetScreenWidth(), GetScreenHeight());
Rectangle titlebar = Rectangle(0, 0, windowSize.x - 50, 35);
Vector2 mousePos = Vector2(GetMouseX(), GetMouseY());
bool hoveredTitlebar = mousePos.x >= titlebar.x && mousePos.y >= titlebar.y && mousePos.x <= titlebar.x + titlebar.width && mousePos.y <= titlebar.y + titlebar.height;
if (hoveredTitlebar && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { DrawTexture(Textures["Frame"], 0, 0, WHITE);
if (dragOffset.x == 0 && dragOffset.y == 0) dragOffset = mousePos;
Vector2 wndPos = GetWindowPosition();
SetWindowPosition(wndPos.x + (mousePos.x - dragOffset.x), wndPos.y + (mousePos.y - dragOffset.y)); Texture2D titleTex = Textures["Title"];
} DrawTexture(titleTex, windowSize.x / 2 - titleTex.width / 2, titlebar.height / 2 - titleTex.height / 2, WHITE);
else dragOffset = Vector2(0, 0);
DrawTexture(Textures["Frame"], 0, 0, WHITE); if (UIUtils::GuiIcon("Exit", windowSize.x - 36, titlebar.height / 2 - 10) && (extracting && currentStep.find("Done") != std::string::npos || !extracting)) {
closeRequested = true;
}
Texture2D titleTex = Textures["Title"]; BeginMode3D(camera);
DrawTexture(titleTex, windowSize.x / 2 - titleTex.width / 2, titlebar.height / 2 - titleTex.height / 2, WHITE); DrawModelEx(Models["Ship"], Vector3Zero(), Vector3(.0f, 1.0f, .0f), this->ModelRotation, SCALE(1.0f), WHITE);
EndMode3D();
if (UIUtils::GuiIcon("Exit", windowSize.x - 36, titlebar.height / 2 - 10) && (extracting && currentStep.find("Done") != std::string::npos || !extracting)) { constexpr float text_y = 125.f;
CloseWindow(); UIUtils::GuiShadowText(("Rom Type: " + version.version).c_str(), 32, text_y, 10, WHITE, BLACK);
} UIUtils::GuiShadowText("Tool Version: 1.0", 32, text_y + 15, 10, WHITE, BLACK);
UIUtils::GuiShadowText("OTR Version: 1.0", 32, text_y + 30, 10, WHITE, BLACK);
BeginMode3D(camera); if (oldExtractMode)
DrawModelEx(Models["Ship"] ,Vector3Zero(), Vector3(.0f, 1.0f, .0f), this->ModelRotation, SCALE(1.0f), WHITE);
EndMode3D();
constexpr float text_y = 125.f;
UIUtils::GuiShadowText(("Rom Type: " + version.version).c_str(), 32, text_y, 10, WHITE, BLACK);
UIUtils::GuiShadowText("Tool Version: 1.0", 32, text_y + 15, 10, WHITE, BLACK);
UIUtils::GuiShadowText("OTR Version: 1.0", 32, text_y + 30, 10, WHITE, BLACK);
UIUtils::GuiToggle(&single_thread, "Single Thread", 32, text_y + 40, currentStep != NULLSTR); UIUtils::GuiToggle(&single_thread, "Single Thread", 32, text_y + 40, currentStep != NULLSTR);
if(!hide_second_btn && UIUtils::GuiIconButton("Folder", "Open\nShip Folder", 109, 50, currentStep != NULLSTR, "Select your Ship of Harkinian Folder\n\nYou could use another folder\nfor development purposes")) {
const std::string path = NativeFS->LaunchFileExplorer(LaunchType::FOLDER);
sohFolder = path;
}
if (UIUtils::GuiIconButton("Cartridge", "Open\nOoT Rom", 32, 50, currentStep != NULLSTR, "Select an Ocarina of Time\nMaster Quest or Vanilla Debug Rom\n\nYou can dump it or lend one from Nintendo")) { if (!hide_second_btn && UIUtils::GuiIconButton("Folder", "Open\nShip Folder", 109, 50, currentStep != NULLSTR, "Select your Ship of Harkinian Folder\n\nYou could use another folder\nfor development purposes")) {
const std::string path = NativeFS->LaunchFileExplorer(LaunchType::FILE); const std::string path = NativeFS->LaunchFileExplorer(LaunchType::FOLDER);
if (path != NULLSTR) { sohFolder = path;
const std::string patched_n64 = std::string(patched_rom); }
MoonUtils::rm(patched_n64);
version = GetVersion(fopen(path.c_str(), "r")); if (UIUtils::GuiIconButton("Cartridge", "Open\nOoT Rom", 32, 50, currentStep != NULLSTR, "Select an Ocarina of Time\nGameCube PAL or Vanilla Debug Rom\n\nYou can dump it or lend one from Nintendo")) {
if (version.version != NULLSTR) { const std::string path = NativeFS->LaunchFileExplorer(LaunchType::FILE);
MoonUtils::copy(path, patched_n64); if (path != NULLSTR) {
rom_ready = true; const std::string patched_n64 = std::string(patched_rom);
return; MoonUtils::rm(patched_n64);
} version = GetVersion(fopen(path.c_str(), "r"));
fix_baserom(path.c_str(), patched_rom); if (version.version != NULLSTR) {
version = GetVersion(fopen(patched_rom, "r")); MoonUtils::copy(path, patched_n64);
if (version.version != NULLSTR) rom_ready = true; rom_ready = true;
return;
} }
fix_baserom(path.c_str(), patched_rom);
version = GetVersion(fopen(patched_rom, "r"));
if (version.version != NULLSTR) rom_ready = true;
} }
}
if(currentStep != NULLSTR) { if (currentStep != NULLSTR) {
DrawRectangle(0, 0, windowSize.x, windowSize.y, Color(0, 0, 0, 160)); DrawRectangle(0, 0, windowSize.x, windowSize.y, Color(0, 0, 0, 160));
DrawTexture(Textures["Modal"], windowSize.x / 2 - Textures["Modal"].width / 2, windowSize.y / 2 - Textures["Modal"].height / 2, WHITE); DrawTexture(Textures["Modal"], windowSize.x / 2 - Textures["Modal"].width / 2, windowSize.y / 2 - Textures["Modal"].height / 2, WHITE);
UIUtils::GuiShadowText(currentStep.c_str(), 0, windowSize.y / 2, 10, WHITE, BLACK, windowSize.x, true); UIUtils::GuiShadowText(currentStep.c_str(), 0, windowSize.y / 2, 10, WHITE, BLACK, windowSize.x, true);
} }
EndDrawing(); EndDrawing();
} }
void setCurrentStep(const std::string& step) { void setCurrentStep(const std::string& step) {
@ -166,4 +220,4 @@ void setCurrentStep(const std::string& step) {
void OTRGame::exit(){ void OTRGame::exit(){
} }

View File

@ -19,6 +19,8 @@ public:
void update(); void update();
void draw(); void draw();
void exit(); void exit();
inline bool CloseRequested() { return closeRequested; }
protected: protected:
void LoadTexture(const std::string& name, const std::string& path) { void LoadTexture(const std::string& name, const std::string& path) {
const Image tmp = LoadImage(path.c_str()); const Image tmp = LoadImage(path.c_str());
@ -32,6 +34,9 @@ protected:
SetTextureFilter(font.texture, TEXTURE_FILTER_POINT); SetTextureFilter(font.texture, TEXTURE_FILTER_POINT);
Fonts[name] = font; Fonts[name] = font;
} }
private:
bool closeRequested = false;
}; };
extern OTRGame* Game; extern OTRGame* Game;

View File

@ -83,37 +83,37 @@ RomVersion GetVersion(FILE* rom) {
break; break;
case OOT_NTSC_JP_GC: case OOT_NTSC_JP_GC:
version.version = "JP GameCube (MQ Disk)"; version.version = "JP GameCube (MQ Disk)";
version.listPath = "gamecube_mq.txt"; version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_GC; version.offset = OOT_OFF_JP_GC;
break; break;
case OOT_NTSC_JP_GC_CE: case OOT_NTSC_JP_GC_CE:
version.version = "GameCube (Collectors Edition Disk)"; version.version = "GameCube (Collectors Edition Disk)";
version.listPath = "gamecube_mq.txt"; version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_GC_CE; version.offset = OOT_OFF_JP_GC_CE;
break; break;
case OOT_NTSC_JP_MQ: case OOT_NTSC_JP_MQ:
version.version = "JP Master Quest"; version.version = "JP Master Quest";
version.listPath = "gamecube_mq.txt"; version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_MQ; version.offset = OOT_OFF_JP_MQ;
break; break;
case OOT_NTSC_US_MQ: case OOT_NTSC_US_MQ:
version.version = "NTSC Master Quest"; version.version = "NTSC Master Quest";
version.listPath = "gamecube_mq.txt"; version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_MQ; version.offset = OOT_OFF_JP_MQ;
break; break;
case OOT_NTSC_US_GC: case OOT_NTSC_US_GC:
version.version = "NTSC GameCube"; version.version = "NTSC GameCube";
version.listPath = "gamecube_mq.txt"; version.listPath = "gamecube.txt";
version.offset = OOT_OFF_US_MQ; version.offset = OOT_OFF_US_MQ;
break; break;
case OOT_PAL_GC: case OOT_PAL_GC:
version.version = "PAL GameCube"; version.version = "PAL GameCube";
version.listPath = "gamecube_mq.txt"; version.listPath = "gamecube_pal.txt";
version.offset = OOT_OFF_PAL_GC; version.offset = OOT_OFF_PAL_GC;
break; break;
case OOT_PAL_MQ: case OOT_PAL_MQ:
version.version = "PAL Master Quest"; version.version = "PAL Master Quest";
version.listPath = "pal_mq.txt"; version.listPath = "gamecube_pal.txt";
version.offset = OOT_OFF_PAL_MQ; version.offset = OOT_OFF_PAL_MQ;
break; break;
case OOT_PAL_GC_DBG1: case OOT_PAL_GC_DBG1:
@ -179,6 +179,8 @@ WriteResult ExtractBaserom(const char* romPath) {
const std::vector<std::string> lines = MoonUtils::split(read(MoonUtils::join("assets/extractor/filelists", version.listPath)), '\n'); const std::vector<std::string> lines = MoonUtils::split(read(MoonUtils::join("assets/extractor/filelists", version.listPath)), '\n');
std::vector<uint8_t> decompressedData(1);
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
FILE* outFile = fopen(MoonUtils::join("tmp/baserom", lines[i]).c_str(), "wb"); FILE* outFile = fopen(MoonUtils::join("tmp/baserom", lines[i]).c_str(), "wb");
const int romOffset = version.offset + (DMA_ENTRY_SIZE * i); const int romOffset = version.offset + (DMA_ENTRY_SIZE * i);
@ -196,10 +198,13 @@ WriteResult ExtractBaserom(const char* romPath) {
auto outData = new uint8_t[size]; auto outData = new uint8_t[size];
memcpy(outData, romData + physStart, size); memcpy(outData, romData + physStart, size);
if (compressed) { if (compressed) {
std::vector<uint8_t> compressedData = yaz0_encode(outData, size); int decSize = virtEnd - virtStart;
outData = compressedData.data(); decompressedData = std::vector<uint8_t>(decSize);
size = compressedData.size(); yaz0_decode(outData, decompressedData.data(), decSize);
outData = decompressedData.data();
size = decSize;
} }
fwrite(outData, sizeof(char), size, outFile); fwrite(outData, sizeof(char), size, outFile);

View File

@ -1,23 +1,7 @@
#ifndef EXTRACT_BASEROM_H_ #ifndef EXTRACT_BASEROM_H_
#define EXTRACT_BASEROM_H_ #define EXTRACT_BASEROM_H_
#define OOT_NTSC_10 0xEC7011B7 #include "../../libultraship/libultraship/GameVersions.h"
#define OOT_NTSC_11 0xD43DA81F
#define OOT_NTSC_12 0x693BA2AE
#define OOT_PAL_10 0xB044B569
#define OOT_PAL_11 0xB2055FBD
#define OOT_NTSC_JP_GC_CE 0xF7F52DB8
#define OOT_NTSC_JP_GC 0xF611F4BA
#define OOT_NTSC_US_GC 0xF3DD35BA
#define OOT_PAL_GC 0x09465AC3
#define OOT_NTSC_JP_MQ 0xF43B45BA
#define OOT_NTSC_US_MQ 0xF034001A
#define OOT_PAL_MQ 0x1D4136F3
#define OOT_PAL_GC_DBG1 0x871E1C92 // 03-21-2002 build
#define OOT_PAL_GC_DBG2 0x87121EFE // 03-13-2002 build
#define OOT_PAL_GC_MQ_DBG 0x917D18F6
#define OOT_IQUE_TW 0x3D81FB3E
#define OOT_IQUE_CN 0xB1E1E07B
#include <cstdio> #include <cstdio>
#include <string> #include <string>

View File

@ -5,6 +5,7 @@
#include "utils/mutils.h" #include "utils/mutils.h"
#include "ctpl/ctpl_stl.h" #include "ctpl/ctpl_stl.h"
#include <thread> #include <thread>
#include <impl/baserom_extractor/baserom_extractor.h>
#ifdef _WIN32 #ifdef _WIN32
#define PLATFORM Platforms::WINDOWS #define PLATFORM Platforms::WINDOWS
@ -13,6 +14,7 @@
#endif #endif
namespace Util = MoonUtils; namespace Util = MoonUtils;
bool oldExtractMode = false;
static int maxResources = 0; static int maxResources = 0;
static int extractedResources = 0; static int extractedResources = 0;
bool buildingOtr = false; bool buildingOtr = false;
@ -22,19 +24,29 @@ bool isWindows() {
return (PLATFORM == Platforms::WINDOWS); return (PLATFORM == Platforms::WINDOWS);
} }
void BuildOTR(const std::string output) { std::string GetXMLVersion(RomVersion version)
Util::copy("tmp/baserom/Audiobank", "Extract/Audiobank"); {
Util::copy("tmp/baserom/Audioseq", "Extract/Audioseq"); switch (version.crc)
Util::copy("tmp/baserom/Audiotable", "Extract/Audiotable"); {
case OOT_PAL_GC_DBG1: return "GC_NMQ_D";
Util::copy("assets/game/", "Extract/assets/"); case OOT_PAL_GC_DBG2: return "GC_MQ_D";
case OOT_PAL_GC: return "GC_NMQ_PAL_F";
std::string execStr = Util::format("assets/extractor/%s", isWindows() ? "ZAPD.exe" : "ZAPD.out") + " botr -se OTR";
ProcessResult result = NativeFS->LaunchProcess(execStr);
if(result.exitCode != 0) {
std::cout << "\nError when building the OTR file with error code: " << result.exitCode << " !" << std::endl;
std::cout << "Aborting...\n" << std::endl;
} }
return "ERROR";
}
void BuildOTR(const std::string output) {
if (oldExtractMode)
{
std::string execStr = Util::format("assets/extractor/%s", isWindows() ? "ZAPD.exe" : "ZAPD.out") + " botr -se OTR";
ProcessResult result = NativeFS->LaunchProcess(execStr);
if (result.exitCode != 0) {
std::cout << "\nError when building the OTR file with error code: " << result.exitCode << " !" << std::endl;
std::cout << "Aborting...\n" << std::endl;
}
}
setCurrentStep("Done!"); setCurrentStep("Done!");
if (output == ".") return; if (output == ".") return;
@ -44,9 +56,9 @@ void BuildOTR(const std::string output) {
MoonUtils::copy("oot.otr", outputPath); MoonUtils::copy("oot.otr", outputPath);
} }
void ExtractFile(std::string xmlPath, std::string outPath, std::string outSrcPath) { void ExtractFile(std::string xmlPath, std::string outPath, std::string outSrcPath, RomVersion version) {
std::string execStr = Util::format("assets/extractor/%s", isWindows() ? "ZAPD.exe" : "ZAPD.out"); std::string execStr = Util::format("assets/extractor/%s", isWindows() ? "ZAPD.exe" : "ZAPD.out");
std::string args = Util::format(" e -eh -i %s -b tmp/baserom/ -o %s -osf %s -gsf 1 -rconf assets/extractor/Config.xml -se OTR %s", xmlPath.c_str(), outPath.c_str(), outSrcPath.c_str(), xmlPath.find("overlays") != std::string::npos ? "--static" : ""); std::string args = Util::format(" e -eh -i %s -b tmp/baserom/ -o %s -osf %s -gsf 1 -rconf assets/extractor/Config_%s.xml -se OTR %s", xmlPath.c_str(), outPath.c_str(), outSrcPath.c_str(), GetXMLVersion(version).c_str(), xmlPath.find("overlays") != std::string::npos ? "--static" : "");
ProcessResult result = NativeFS->LaunchProcess(execStr + args); ProcessResult result = NativeFS->LaunchProcess(execStr + args);
if (result.exitCode != 0) { if (result.exitCode != 0) {
@ -55,49 +67,77 @@ void ExtractFile(std::string xmlPath, std::string outPath, std::string outSrcPat
} }
} }
void ExtractFunc(std::string fullPath) { void ExtractFunc(std::string fullPath, RomVersion version) {
std::vector<std::string> path = Util::split(fullPath, Util::pathSeparator()); std::vector<std::string> path = Util::split(fullPath, Util::pathSeparator());
std::string outPath = Util::join(Util::join("assets/extractor/xmls/output", path[4]), Util::basename(fullPath)); std::string outPath = Util::join(Util::join("assets/extractor/xmls/output", path[4]), Util::basename(fullPath));
Util::mkdir(outPath); Util::mkdir(outPath);
ExtractFile(fullPath, outPath, outPath); ExtractFile(fullPath, outPath, outPath, version);
setCurrentStep("Extracting: " + Util::basename(fullPath)); setCurrentStep("Extracting: " + Util::basename(fullPath));
extractedResources++; extractedResources++;
} }
void startWorker() { void startWorker(RomVersion version) {
std::string path = "assets/extractor/xmls"; std::string path = "assets/extractor/xmls/";
std::vector<std::string> files;
Util::dirscan(path, files);
std::vector<std::string> xmlFiles;
const int num_threads = std::thread::hardware_concurrency(); path += GetXMLVersion(version);
ctpl::thread_pool pool(num_threads / 2);
for(auto &file : files) {
if (file.find(".xml") != std::string::npos) xmlFiles.push_back(file);
}
for (auto& file : xmlFiles) { Util::write("tmp/baserom/version", (char*)&version.crc, sizeof(version.crc));
if(single_thread) {
ExtractFunc(file); if (oldExtractMode)
} else { {
pool.push([file](int) { std::vector<std::string> files;
ExtractFunc(file); Util::dirscan(path, files);
}); std::vector<std::string> xmlFiles;
const int num_threads = std::thread::hardware_concurrency();
ctpl::thread_pool pool(num_threads / 2);
for (auto& file : files) {
if (file.find(".xml") != std::string::npos) xmlFiles.push_back(file);
} }
}
maxResources = xmlFiles.size(); for (auto& file : xmlFiles) {
if (single_thread) {
ExtractFunc(file, version);
}
else {
pool.push([file, version](int) {
ExtractFunc(file, version);
});
}
}
maxResources = xmlFiles.size();
}
else
{
std::string execStr = Util::format("assets/extractor/%s", isWindows() ? "ZAPD.exe" : "ZAPD.out");
std::string args = Util::format(" ed -eh -i %s -b tmp/rom.z64 -fl assets/extractor/filelists -o %s -osf %s -gsf 1 -rconf assets/extractor/Config_%s.xml -se OTR %s", path.c_str(), path + "../", path + "../", GetXMLVersion(version).c_str(), "");
ProcessResult result = NativeFS->LaunchProcess(execStr + args);
if (result.exitCode != 0) {
std::cout << "\nError when extracting the ROM with error code: " << result.exitCode << " !" << std::endl;
std::cout << "Aborting...\n" << std::endl;
}
else
{
printf("All done?\n");
}
maxResources = 1;
}
} }
void updateWorker(const std::string& output) { void updateWorker(const std::string& output) {
if (maxResources > 0 && !buildingOtr && extractedResources >= maxResources) { if (maxResources > 0 && !buildingOtr && (extractedResources >= maxResources || !oldExtractMode))
{
setCurrentStep("Building OTR..."); setCurrentStep("Building OTR...");
if (skipFrames < 3) { if (skipFrames < 3) {
skipFrames++; skipFrames++;
return; return;
} }
buildingOtr = true; buildingOtr = true;
if (single_thread){
if (single_thread || !oldExtractMode){
BuildOTR(output); BuildOTR(output);
return; return;
} }

View File

@ -5,5 +5,7 @@ enum Platforms {
WINDOWS, LINUX WINDOWS, LINUX
}; };
void startWorker(); struct RomVersion;
void startWorker(RomVersion version);
void updateWorker(const std::string& output); void updateWorker(const std::string& output);

View File

@ -17,8 +17,8 @@ void UpdateDrawFrame(void) {
} }
int main() { int main() {
constexpr Vector2 windowSize = Vector2(400, 200); constexpr Vector2 windowSize = Vector2(400, 200);
SetTargetFPS(144); SetConfigFlags(FLAG_VSYNC_HINT);
SetConfigFlags(FLAG_WINDOW_HIGHDPI); SetConfigFlags(FLAG_WINDOW_HIGHDPI);
SetConfigFlags(FLAG_WINDOW_UNDECORATED); SetConfigFlags(FLAG_WINDOW_UNDECORATED);
SetConfigFlags(FLAG_MSAA_4X_HINT); SetConfigFlags(FLAG_MSAA_4X_HINT);
@ -32,7 +32,7 @@ int main() {
Game = new OTRGame(); Game = new OTRGame();
Game->preload(); Game->preload();
Game->init(); Game->init();
while(!WindowShouldClose()) { while(!WindowShouldClose() && !Game->CloseRequested()) {
UpdateDrawFrame(); UpdateDrawFrame();
} }
CloseWindow(); CloseWindow();

View File

@ -72,7 +72,11 @@ namespace MoonUtils {
vector<string> result; vector<string> result;
stringstream ss (s); stringstream ss (s);
string item; string item;
while (getline(ss, item, delim)) { while (getline(ss, item, delim))
{
if (item.at(item.size() - 1) == '\r')
item = item.substr(0, item.size() - 1);
result.push_back (item); result.push_back (item);
} }
return result; return result;

111
README.md
View File

@ -6,15 +6,23 @@ The Ship does not include assets and as such requires a prior copy of the game t
## Quick Start ## Quick Start
1) Download The Ship of Harkinian from Discord. 1) Download The Ship of Harkinian from [Discord](https://discord.com/invite/BtBmd55HVH).
2) Get a ZRET OoT Debug ROM 2) Requires a supported copy of the game (See supported games below).
```
Build date: `zelda@srd022j 03-02-21 00:49:18`
sha1: cee6bc3c2a634b41728f2af8da54d9bf8cc14099
```
3) Use the OTRGui to generate an `oot.otr` archive file. 3) Use the OTRGui to generate an `oot.otr` archive file.
4) Launch `soh.exe` 4) Launch `soh.exe`
### Supported Games
Ocarina of Time Debug (not Master Quest)
```
Build team: `zelda@srd022j`
Build date: `03-02-21 00:49:18` (year-month-day)
sha1: cee6bc3c2a634b41728f2af8da54d9bf8cc14099
```
Ocarina of Time PAL GameCube
```
sha1: 0227d7c0074f2d0ac935631990da8ec5914597b4
```
Congratulations, you are now sailing with the Ship of Harkinian! Have fun! Congratulations, you are now sailing with the Ship of Harkinian! Have fun!
## Additional Setup Information ## Additional Setup Information
@ -36,7 +44,7 @@ If you still cannot get the tool to work, join our [Discord Server](https://disc
### Running The Ship of Harkinian ### Running The Ship of Harkinian
Launch the game. If the window immediately closes, or if there are visual artifacts, you may have selected the wrong rom in the OTRGui tool. Launch the game. If the window immediately closes, or if there are visual artifacts, you may have selected the wrong rom in the OTRGui tool.
Currently, DirectX 11 and OpenGL is supported. Change the renderer by opening the `shipofharkinian.ini` configuration file in notepad and add `sdl` to `gfx backend` for OpenGL or leave blank for DirectX. Currently, DirectX 11 and OpenGL is supported. Change the renderer by opening the `shipofharkinian.ini` configuration file in notepad and add `sdl` to `gfx backend` for OpenGL or leave blank for DirectX.
@ -50,23 +58,7 @@ Official Discord: https://discord.com/invite/BtBmd55HVH
## Building The Ship of Harkinian ## Building The Ship of Harkinian
1. Install [Python](https://www.python.org/ftp/python/3.10.2/python-3.10.2-amd64.exe) Refer to the [building instructions](BUILDING.md) to compile SoH.
2. Install [Visual Studio 2022 Community Edition](https://visualstudio.microsoft.com/vs/community/)
2b. In the Visual Studio Installer, install `MSVC v142 - VS 2019 C++`.
4. Clone the Ship of Harkinian repository.
5. Put your 2020 OoT debug rom in the `soh` folder.
6. Launch `soh/fixbaserom.py`.
7. Launch `soh/extract_baserom.py`.
8. Copy the `baserom` folder from the `soh` folder into the `OTRExporter` folder.
9. Run `OTRExporter/OTRExporter.sln`.
10. Switch the solution to `Release x64`.
11. Build the solution.
12. Launching `OTRExporter/extract_assets.py` will generate an `oot.otr` archive file in `OTRExporter/oot.otr`.
13. Run `soh/soh.sln`
14. Switch the solution to `Release x86`.
15. Build the solution.
16. Copy the `OTRExporter/oot.otr` archive file to `soh/Release`.
17. Launch `soh.exe`.
## Troubleshooting The Exporter ## Troubleshooting The Exporter
- Affirm that you have an `/assets` folder filled with XMLs in the same directory as OTRGui.exe - Affirm that you have an `/assets` folder filled with XMLs in the same directory as OTRGui.exe
@ -75,38 +67,45 @@ Official Discord: https://discord.com/invite/BtBmd55HVH
## The Harbour Masters Are... ## The Harbour Masters Are...
Kenix | Lead Developer/Public Relations - Resource Management Programmer, Audio System Programmer, and General Programmer Kenix | Lead Developer/Public Relations - Resource Management Programmer, Audio System Programmer, and General Programmer
Jack Walker | Lead Developer - OTR Format Programmer, Resource Load Programmer, and General Programmer Jack Walker | Lead Developer - OTR Format Programmer, Resource Load Programmer, and General Programmer
Louist103 | Developer - Save System Programmer and General Programmer Louist103 | Developer - Save System Programmer and General Programmer
Emil | Developer - Fast3D Programmer Emil | Developer - Fast3D Programmer
m4xw | Developer - Shipwright, Throwing Baguettes, and General Programmer m4xw | Developer - Shipwright, Throwing Baguettes, and General Programmer
MelonSpeedruns | Developer - General Programmer MelonSpeedruns | Developer - General Programmer
Rozlette | Developer - General Programmer Rozlette | Developer - General Programmer
JoshDuMan | Developer - General Programmer JoshDuMan | Developer - General Programmer
KiritoDev/Lywx | Developer - General Programmer KiritoDev/Lywx | Developer - General Programmer
Theo3 | Developer - General Programmer Theo3 | Developer - General Programmer
Random06457 | Developer - Linux Build Random06457 | Developer - Linux Build
## Special Thanks ## Special Thanks
Decomp & ZAPD | Made this project even possible in the first place! Decomp & ZAPD | Made this project even possible in the first place!
MNGoldenEagle | Patiently explained audio data formats, encouragement, and founding ZSO which was the first source of the game's code and resource format documentation. MNGoldenEagle | Patiently explained audio data formats, encouragement, and founding ZSO which was the first source of the game's code and resource format documentation.
Rrrrry123 | Speedbunner, encouragement, and community moderation Rrrrry123 | Speedbunner, encouragement, and community moderation
Fierce deity | Encouragement and community moderation Fierce deity | Encouragement and community moderation
mzxrules | For his contributions to decomp mzxrules | For his contributions to decomp
Aloxado | Developer - General Programmer zel. | For his contributions to decomp
MegaMech | Developer - General Programmer Aloxado | Developer - General Programmer
Revo | Tester - GCC support and General Testing MegaMech | Developer - General Programmer
zfg | Tester - General Testing Revo | Tester - GCC support and General Testing
Horseless Headman | Tester - General Testing zfg | Tester - General Testing
Steven Pritchett | Tester - General Testing Horseless Headman | Tester - General Testing
Trenton May | Tester - General Testing Steven Pritchett | Tester - General Testing
Zeldaboy14 | Tester - General Testing, encouragement, and community moderation Trenton May | Tester - General Testing
Koby Howell | Tester - General Testing Zeldaboy14 | Tester - General Testing, encouragement, and community moderation
Logg | Tester - General Testing Koby Howell | Tester - General Testing
Taylor Daley | Graphic Design Logg | Tester - General Testing
Can't Sleep | Graphic Design Taylor Daley | Graphic Design
MicTheMicrophone | Voice actor for the King Can't Sleep | Graphic Design
Amphibibro | Voice actor for Link
## Video Credits
Lemons Kenix | Producer / Writer
rainbow_fash | Executive Producer
TheLegendOfXela | Editor
MicTheMicrophone | Gwonam / The King
Amphibibro | Link
AceHeart | Zelda
###### Lemons

View File

@ -1,6 +1,6 @@
#include "CollisionExporter.h" #include "CollisionExporter.h"
void ExporterExample_Collision::Save(ZResource* res, [[maybe_unused]] fs::path outPath, void ExporterExample_Collision::Save(ZResource* res, [[maybe_unused]] const fs::path& outPath,
BinaryWriter* writer) BinaryWriter* writer)
{ {
ZCollisionHeader* col = (ZCollisionHeader*)res; ZCollisionHeader* col = (ZCollisionHeader*)res;

View File

@ -6,5 +6,5 @@
class ExporterExample_Collision : public ZResourceExporter class ExporterExample_Collision : public ZResourceExporter
{ {
public: public:
void Save(ZResource* res, fs::path outPath, BinaryWriter* writer) override; void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
}; };

View File

@ -20,7 +20,7 @@
#include "ZRoom/Commands/SetTimeSettings.h" #include "ZRoom/Commands/SetTimeSettings.h"
#include "ZRoom/Commands/SetWind.h" #include "ZRoom/Commands/SetWind.h"
void ExporterExample_Room::Save(ZResource* res, fs::path outPath, BinaryWriter* writer) void ExporterExample_Room::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{ {
ZRoom* room = dynamic_cast<ZRoom*>(res); ZRoom* room = dynamic_cast<ZRoom*>(res);

View File

@ -6,5 +6,5 @@
class ExporterExample_Room : public ZResourceExporter class ExporterExample_Room : public ZResourceExporter
{ {
public: public:
void Save(ZResource* res, fs::path outPath, BinaryWriter* writer) override; void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
}; };

View File

@ -1,7 +1,7 @@
#include "TextureExporter.h" #include "TextureExporter.h"
#include "../ZAPD/ZFile.h" #include "../ZAPD/ZFile.h"
void ExporterExample_Texture::Save(ZResource* res, [[maybe_unused]] fs::path outPath, void ExporterExample_Texture::Save(ZResource* res, [[maybe_unused]] const fs::path& outPath,
BinaryWriter* writer) BinaryWriter* writer)
{ {
ZTexture* tex = (ZTexture*)res; ZTexture* tex = (ZTexture*)res;

View File

@ -7,5 +7,5 @@
class ExporterExample_Texture : public ZResourceExporter class ExporterExample_Texture : public ZResourceExporter
{ {
public: public:
void Save(ZResource* res, fs::path outPath, BinaryWriter* writer) override; void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
}; };

View File

@ -44,7 +44,8 @@ ifneq ($(DEPRECATION_ON),0)
endif endif
# CXXFLAGS += -DTEXTURE_DEBUG # CXXFLAGS += -DTEXTURE_DEBUG
LDFLAGS := -lm -ldl -lpng LDFLAGS := -lm -ldl -lpng \
-L../external -L../libultraship -lz -lbz2 -pthread -lpulse -lultraship -lstorm -lSDL2 -lGLEW -lGL -lX11
# Use LLD if available. Set LLD=0 to not use it # Use LLD if available. Set LLD=0 to not use it
ifeq ($(shell command -v ld.lld >/dev/null 2>&1; echo $$?),0) ifeq ($(shell command -v ld.lld >/dev/null 2>&1; echo $$?),0)
@ -59,9 +60,9 @@ UNAME := $(shell uname)
UNAMEM := $(shell uname -m) UNAMEM := $(shell uname -m)
ifneq ($(UNAME), Darwin) ifneq ($(UNAME), Darwin)
LDFLAGS += -Wl,-export-dynamic -lstdc++fs LDFLAGS += -Wl,-export-dynamic -lstdc++fs
EXPORTERS := -Wl,--whole-archive ExporterTest/ExporterTest.a -Wl,--no-whole-archive EXPORTERS := -Wl,--whole-archive ../OTRExporter/OTRExporter/OTRExporter.a -Wl,--no-whole-archive
else else
EXPORTERS := -Wl,-force_load ExporterTest/ExporterTest.a EXPORTERS := -Wl,-force_load ../OTRExporter/OTRExporter/OTRExporter.a
ifeq ($(UNAMEM),arm64) ifeq ($(UNAMEM),arm64)
ifeq ($(shell brew list libpng > /dev/null 2>&1; echo $$?),0) ifeq ($(shell brew list libpng > /dev/null 2>&1; echo $$?),0)
LDFLAGS += -L $(shell brew --prefix)/lib LDFLAGS += -L $(shell brew --prefix)/lib

View File

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

View File

@ -1,6 +1,7 @@
#include "Declaration.h" #include "Declaration.h"
#include "Globals.h" #include "Globals.h"
#include "ZVtx.h"
#include "Utils/StringHelper.h" #include "Utils/StringHelper.h"
Declaration::Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize, Declaration::Declaration(offset_t nAddress, DeclarationAlignment nAlignment, size_t nSize,
@ -61,6 +62,12 @@ Declaration::Declaration(offset_t nAddress, const std::string& nIncludePath, siz
varName = nVarName; varName = nVarName;
} }
Declaration::~Declaration()
{
//for (auto item : vertexHack)
//delete item;
}
bool Declaration::IsStatic() const bool Declaration::IsStatic() const
{ {
switch (staticConf) switch (staticConf)

View File

@ -22,6 +22,8 @@ enum class StaticConfig
On On
}; };
class ZVtx;
class Declaration class Declaration
{ {
public: public:
@ -38,6 +40,8 @@ public:
std::string varName; std::string varName;
std::string includePath; std::string includePath;
std::vector<ZVtx*> vertexHack;
bool isExternal = false; bool isExternal = false;
bool isArray = false; bool isArray = false;
bool forceArrayCnt = false; bool forceArrayCnt = false;
@ -65,6 +69,8 @@ public:
Declaration(offset_t nAddress, const std::string& nIncludePath, size_t nSize, Declaration(offset_t nAddress, const std::string& nIncludePath, size_t nSize,
const std::string& nVarType, const std::string& nVarName); const std::string& nVarType, const std::string& nVarName);
~Declaration();
bool IsStatic() const; bool IsStatic() const;
std::string GetNormalDeclarationStr() const; std::string GetNormalDeclarationStr() const;

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;
};

View File

@ -20,6 +20,7 @@ Globals::Globals()
profile = false; profile = false;
useLegacyZDList = false; useLegacyZDList = false;
useExternalResources = true; useExternalResources = true;
singleThreaded = true;
verbosity = VerbosityLevel::VERBOSITY_SILENT; verbosity = VerbosityLevel::VERBOSITY_SILENT;
outputPath = Directory::GetCurrentDirectory(); outputPath = Directory::GetCurrentDirectory();
} }
@ -34,30 +35,88 @@ Globals::~Globals()
} }
} }
void Globals::AddSegment(int32_t segment, ZFile* file) void Globals::AddSegment(int32_t segment, ZFile* file, int workerID)
{ {
if (std::find(segments.begin(), segments.end(), segment) == segments.end()) if (!Globals::Instance->singleThreaded)
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)
{
return std::find(segments.begin(), segments.end(), segment) != segments.end();
}
ZFile* Globals::GetSegment(int32_t segment)
{
if (HasSegment(segment))
{ {
int idx = std::find(segments.begin(), segments.end(), segment) - segments.begin(); auto worker = workerData[workerID];
return files[idx];
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 else
return nullptr; {
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);
} }
std::map<std::string, ExporterSet*>& Globals::GetExporterMap() std::map<std::string, ExporterSet*>& Globals::GetExporterMap()
@ -93,8 +152,22 @@ ExporterSet* Globals::GetExporterSet()
return nullptr; 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 File::ReadAllBytes(fileName);
}
bool Globals::GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile, bool Globals::GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile,
const std::string& expectedType, std::string& declName) const std::string& expectedType, std::string& declName, int workerID)
{ {
if (segAddress == 0) if (segAddress == 0)
{ {
@ -130,9 +203,11 @@ bool Globals::GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile,
if (currentFile->GetDeclarationPtrName(segAddress, expectedType, declName)) if (currentFile->GetDeclarationPtrName(segAddress, expectedType, declName))
return true; return true;
} }
else if (HasSegment(segment)) else if (HasSegment(segment, workerID))
{ {
for (auto file : cfg.segmentRefFiles[segment]) // OTRTODO: Multithreading
auto segs = GetSegmentRefFiles(workerID);
for (auto file : segs[segment])
{ {
offset = Seg2Filespace(segAddress, file->baseAddress); offset = Seg2Filespace(segAddress, file->baseAddress);
@ -176,7 +251,7 @@ bool Globals::GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile,
bool Globals::GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSize, bool Globals::GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSize,
ZFile* currentFile, const std::string& expectedType, ZFile* currentFile, const std::string& expectedType,
std::string& declName) std::string& declName, int workerID)
{ {
if (segAddress == 0) if (segAddress == 0)
{ {
@ -193,9 +268,11 @@ bool Globals::GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSi
if (addressFound) if (addressFound)
return true; return true;
} }
else if (HasSegment(segment)) else if (HasSegment(segment, workerID))
{ {
for (auto file : cfg.segmentRefFiles[segment]) // OTRTODO: Multithreading
auto segs = GetSegmentRefFiles(workerID);
for (auto file : segs[segment])
{ {
if (file->IsSegmentedInFilespaceRange(segAddress)) if (file->IsSegmentedInFilespaceRange(segAddress))
{ {

View File

@ -5,6 +5,8 @@
#include <vector> #include <vector>
#include "GameConfig.h" #include "GameConfig.h"
#include "ZFile.h" #include "ZFile.h"
#include <ZRom.h>
#include <FileWorker.h>
class ZRoom; class ZRoom;
@ -36,6 +38,7 @@ public:
ExporterSetFuncVoid3 beginXMLFunc = nullptr; ExporterSetFuncVoid3 beginXMLFunc = nullptr;
ExporterSetFuncVoid3 endXMLFunc = nullptr; ExporterSetFuncVoid3 endXMLFunc = nullptr;
ExporterSetResSave resSaveFunc = nullptr; ExporterSetResSave resSaveFunc = nullptr;
ExporterSetFuncVoid3 endProgramFunc = nullptr;
}; };
class Globals class Globals
@ -49,9 +52,10 @@ public:
bool outputCrc = false; bool outputCrc = false;
bool profile; // Measure performance of certain operations bool profile; // Measure performance of certain operations
bool useLegacyZDList; bool useLegacyZDList;
bool singleThreaded;
VerbosityLevel verbosity; // ZAPD outputs additional information VerbosityLevel verbosity; // ZAPD outputs additional information
ZFileMode fileMode; ZFileMode fileMode;
fs::path baseRomPath, inputPath, outputPath, sourceOutputPath, cfgPath; fs::path baseRomPath, inputPath, outputPath, sourceOutputPath, cfgPath, fileListPath;
TextureType texType; TextureType texType;
ZGame game; ZGame game;
GameConfig cfg; GameConfig cfg;
@ -61,10 +65,13 @@ public:
bool forceUnaccountedStatic = false; bool forceUnaccountedStatic = false;
bool otrMode = true; bool otrMode = true;
ZRom* rom;
std::vector<ZFile*> files; std::vector<ZFile*> files;
std::vector<ZFile*> externalFiles; std::vector<ZFile*> externalFiles;
std::vector<int32_t> segments; std::vector<int32_t> segments;
std::map<int, FileWorker*> workerData;
std::string currentExporter; std::string currentExporter;
static std::map<std::string, ExporterSet*>& GetExporterMap(); static std::map<std::string, ExporterSet*>& GetExporterMap();
static void AddExporter(std::string exporterName, ExporterSet* exporterSet); static void AddExporter(std::string exporterName, ExporterSet* exporterSet);
@ -72,13 +79,18 @@ public:
Globals(); Globals();
~Globals(); ~Globals();
void AddSegment(int32_t segment, ZFile* file); void AddSegment(int32_t segment, ZFile* file, int workerID);
bool HasSegment(int32_t segment); bool HasSegment(int32_t segment, int workerID);
ZFile* GetSegment(int32_t segment); 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);
ZResourceExporter* GetExporter(ZResourceType resType); ZResourceExporter* GetExporter(ZResourceType resType);
ExporterSet* GetExporterSet(); ExporterSet* GetExporterSet();
std::vector<uint8_t> GetBaseromFile(std::string fileName);
/** /**
* Search in every file (and the symbol map) for the `segAddress` passed as parameter. * 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 * If the segment of `currentFile` is the same segment of `segAddress`, then that file will be
@ -88,8 +100,8 @@ public:
* in which case `declName` will be set to the address formatted as a pointer. * in which case `declName` will be set to the address formatted as a pointer.
*/ */
bool GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile, bool GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile,
const std::string& expectedType, std::string& declName); const std::string& expectedType, std::string& declName, int workerID);
bool GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSize, ZFile* currentFile, bool GetSegmentedArrayIndexedName(segptr_t segAddress, size_t elementSize, ZFile* currentFile,
const std::string& expectedType, std::string& declName); const std::string& expectedType, std::string& declName, int workerID);
}; };

View File

@ -10,7 +10,7 @@
#include "ZFile.h" #include "ZFile.h"
#include "ZTexture.h" #include "ZTexture.h"
#if !defined(_MSC_VER) && !defined(__CYGWIN__) #ifdef __linux__
#include <csignal> #include <csignal>
#include <cstdlib> #include <cstdlib>
#include <ctime> #include <ctime>
@ -23,18 +23,47 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include "tinyxml2.h" #include "tinyxml2.h"
#include <ctpl_stl.h>
//extern const char gBuildHash[]; //extern const char gBuildHash[];
const char gBuildHash[] = ""; const char gBuildHash[] = "";
// LINUX_TODO: remove, those are because of soh <-> lus dependency problems
float divisor_num = 0.0f;
extern "C" void Audio_SetGameVolume(int player_id, float volume)
{
}
extern "C" int ResourceMgr_OTRSigCheck(char* imgData)
{
}
void DebugConsole_SaveCVars()
{
}
void DebugConsole_LoadCVars()
{
}
bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath, bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath,
ZFileMode fileMode); ZFileMode fileMode, int workerID);
void BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const fs::path& outPath); void BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const fs::path& outPath);
void BuildAssetBackground(const fs::path& imageFilePath, const fs::path& outPath); void BuildAssetBackground(const fs::path& imageFilePath, const fs::path& outPath);
void BuildAssetBlob(const fs::path& blobFilePath, 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);
#if !defined(_MSC_VER) && !defined(__CYGWIN__) volatile int numWorkersLeft = 0;
#ifdef __linux__
#define ARRAY_COUNT(arr) (sizeof(arr) / sizeof(arr[0])) #define ARRAY_COUNT(arr) (sizeof(arr) / sizeof(arr[0]))
void ErrorHandler(int sig) void ErrorHandler(int sig)
{ {
@ -182,20 +211,26 @@ int main(int argc, char* argv[])
{ {
Globals::Instance->cfgPath = argv[++i]; Globals::Instance->cfgPath = argv[++i];
} }
else if (arg == "-fl") // Set baserom filelist path
{
Globals::Instance->fileListPath = argv[++i];
}
else if (arg == "-rconf") // Read Config File else if (arg == "-rconf") // Read Config File
{ {
Globals::Instance->cfg.ReadConfigFile(argv[++i]); Globals::Instance->cfg.ReadConfigFile(argv[++i]);
} }
else if (arg == "-eh") // Enable Error Handler else if (arg == "-eh") // Enable Error Handler
{ {
#if !defined(_MSC_VER) && !defined(__CYGWIN__) #ifdef __linux__
signal(SIGSEGV, ErrorHandler); signal(SIGSEGV, ErrorHandler);
signal(SIGABRT, ErrorHandler); signal(SIGABRT, ErrorHandler);
#else #else
HANDLE_WARNING(WarningType::Always, // HANDLE_WARNING(WarningType::Always,
"tried to set error handler, but this ZAPD build lacks support for one", // "tried to set error handler, but this ZAPD build lacks support for one",
""); // "");
#endif #endif
} }
else if (arg == "-v") // Verbose else if (arg == "-v") // Verbose
{ {
@ -240,6 +275,8 @@ int main(int argc, char* argv[])
fileMode = ZFileMode::BuildBlob; fileMode = ZFileMode::BuildBlob;
else if (buildMode == "e") else if (buildMode == "e")
fileMode = ZFileMode::Extract; fileMode = ZFileMode::Extract;
else if (buildMode == "ed")
fileMode = ZFileMode::ExtractDirectory;
else if (exporterSet != nullptr && exporterSet->parseFileModeFunc != nullptr) else if (exporterSet != nullptr && exporterSet->parseFileModeFunc != nullptr)
exporterSet->parseFileModeFunc(buildMode, fileMode); exporterSet->parseFileModeFunc(buildMode, fileMode);
@ -249,6 +286,11 @@ int main(int argc, char* argv[])
return 1; return 1;
} }
Globals::Instance->fileMode = fileMode;
if (fileMode == ZFileMode::ExtractDirectory)
Globals::Instance->rom = new ZRom(Globals::Instance->baseRomPath.string());
// We've parsed through our commands once. If an exporter exists, it's been set by now. // 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. // Now we'll parse through them again but pass them on to our exporter if one is available.
@ -267,7 +309,7 @@ int main(int argc, char* argv[])
} }
// TODO: switch // TODO: switch
if (fileMode == ZFileMode::Extract || fileMode == ZFileMode::BuildSourceFile) if (fileMode == ZFileMode::Extract || fileMode == ZFileMode::BuildSourceFile || fileMode == ZFileMode::ExtractDirectory)
{ {
bool procFileModeSuccess = false; bool procFileModeSuccess = false;
@ -276,30 +318,85 @@ int main(int argc, char* argv[])
if (!procFileModeSuccess) if (!procFileModeSuccess)
{ {
bool parseSuccessful; if (fileMode == ZFileMode::ExtractDirectory)
for (auto& extFile : Globals::Instance->cfg.externalFiles)
{ {
fs::path externalXmlFilePath = std::vector<std::string> fileList =
Globals::Instance->cfg.externalXmlFolder / extFile.xmlPath; Directory::ListFiles(Globals::Instance->inputPath.string());
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO) const int num_threads = std::thread::hardware_concurrency();
ctpl::thread_pool pool(num_threads / 2);
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++)
{ {
printf("Parsing external file from config: '%s'\n", if (Globals::Instance->singleThreaded)
externalXmlFilePath.c_str()); {
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);
});
}
} }
parseSuccessful = Parse(externalXmlFilePath, Globals::Instance->baseRomPath, if (!Globals::Instance->singleThreaded)
extFile.outPath, ZFileMode::ExternalFile); {
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) if (!parseSuccessful)
return 1; return 1;
} }
parseSuccessful = Parse(Globals::Instance->inputPath, Globals::Instance->baseRomPath,
Globals::Instance->outputPath, fileMode);
if (!parseSuccessful)
return 1;
} }
} }
else if (fileMode == ZFileMode::BuildTexture) else if (fileMode == ZFileMode::BuildTexture)
@ -315,23 +412,77 @@ int main(int argc, char* argv[])
{ {
BuildAssetBlob(Globals::Instance->inputPath, Globals::Instance->outputPath); BuildAssetBlob(Globals::Instance->inputPath, Globals::Instance->outputPath);
} }
else if (fileMode == ZFileMode::BuildOverlay)
{
ZOverlay* overlay =
ZOverlay::FromBuild(Path::GetDirectoryName(Globals::Instance->inputPath),
Path::GetDirectoryName(Globals::Instance->cfgPath));
if (overlay != nullptr) if (exporterSet != nullptr && exporterSet->endProgramFunc != nullptr)
File::WriteAllText(Globals::Instance->outputPath.string(), exporterSet->endProgramFunc();
overlay->GetSourceOutputCode(""));
}
delete g; delete g;
return 0; 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, bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path& outPath,
ZFileMode fileMode) ZFileMode fileMode, int workerID)
{ {
tinyxml2::XMLDocument doc; tinyxml2::XMLDocument doc;
tinyxml2::XMLError eResult = doc.LoadFile(xmlFilePath.string().c_str()); tinyxml2::XMLError eResult = doc.LoadFile(xmlFilePath.string().c_str());
@ -359,11 +510,11 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path
{ {
if (std::string_view(child->Name()) == "File") if (std::string_view(child->Name()) == "File")
{ {
ZFile* file = new ZFile(fileMode, child, basePath, outPath, "", xmlFilePath); ZFile* file = new ZFile(fileMode, child, basePath, outPath, "", xmlFilePath, workerID);
Globals::Instance->files.push_back(file); Globals::Instance->AddFile(file, workerID);
if (fileMode == ZFileMode::ExternalFile) if (fileMode == ZFileMode::ExternalFile)
{ {
Globals::Instance->externalFiles.push_back(file); Globals::Instance->AddExternalFile(file, workerID);
file->isExternalFile = true; file->isExternalFile = true;
} }
} }
@ -396,7 +547,7 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path
} }
// Recursion. What can go wrong? // Recursion. What can go wrong?
Parse(externalXmlFilePath, basePath, externalOutFilePath, ZFileMode::ExternalFile); Parse(externalXmlFilePath, basePath, externalOutFilePath, ZFileMode::ExternalFile, workerID);
} }
else else
{ {
@ -415,7 +566,14 @@ bool Parse(const fs::path& xmlFilePath, const fs::path& basePath, const fs::path
if (exporterSet != nullptr && exporterSet->beginXMLFunc != nullptr) if (exporterSet != nullptr && exporterSet->beginXMLFunc != nullptr)
exporterSet->beginXMLFunc(); exporterSet->beginXMLFunc();
for (ZFile* file : Globals::Instance->files) 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) if (fileMode == ZFileMode::BuildSourceFile)
file->BuildSourceFile(); file->BuildSourceFile();

View File

@ -199,8 +199,10 @@ std::string Struct_800A598C::GetBodySourceCode() const
{ {
std::string unk_8_Str; std::string unk_8_Str;
std::string unk_C_Str; std::string unk_C_Str;
Globals::Instance->GetSegmentedPtrName(unk_8, parent, "Struct_800A57C0", unk_8_Str); Globals::Instance->GetSegmentedPtrName(unk_8, parent, "Struct_800A57C0", unk_8_Str,
Globals::Instance->GetSegmentedPtrName(unk_C, parent, "Struct_800A598C_2", unk_C_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", std::string entryStr = StringHelper::Sprintf("\n\t\tARRAY_COUNTU(%s), ARRAY_COUNTU(%s),\n",
unk_8_Str.c_str(), unk_C_Str.c_str()); unk_8_Str.c_str(), unk_C_Str.c_str());
@ -316,8 +318,9 @@ std::string Struct_800A5E28::GetBodySourceCode() const
{ {
std::string unk_4_Str; std::string unk_4_Str;
std::string unk_8_Str; std::string unk_8_Str;
Globals::Instance->GetSegmentedPtrName(unk_4, parent, "Struct_800A598C", unk_4_Str); Globals::Instance->GetSegmentedPtrName(unk_4, parent, "Struct_800A598C", unk_4_Str,
Globals::Instance->GetSegmentedPtrName(unk_8, parent, "Gfx", unk_8_Str); parent->workerID);
Globals::Instance->GetSegmentedPtrName(unk_8, parent, "Gfx", unk_8_Str, parent->workerID);
std::string entryStr = "\n"; std::string entryStr = "\n";
entryStr += StringHelper::Sprintf("\t%i, ARRAY_COUNTU(%s),\n", unk_0, unk_4_Str.c_str()); entryStr += StringHelper::Sprintf("\t%i, ARRAY_COUNTU(%s),\n", unk_0, unk_4_Str.c_str());

View File

@ -3,7 +3,7 @@
void OutputFormatter::Flush() void OutputFormatter::Flush()
{ {
//if (!Globals::Instance->otrMode) //if (!Globals::Instance->otrMode) // OTRTODO: MULTITHREADING
{ {
if (col > lineLimit && !Globals::Instance->otrMode) if (col > lineLimit && !Globals::Instance->otrMode)
{ {
@ -31,6 +31,10 @@ void OutputFormatter::Flush()
int OutputFormatter::Write(const char* buf, int count) int OutputFormatter::Write(const char* buf, int count)
{ {
// OTRTODO
//if (!Globals::Instance->singleThreaded)
//return 0;
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
char c = buf[i]; char c = buf[i];
@ -92,7 +96,7 @@ int OutputFormatter::Write(const std::string& buf)
return Write(buf.data(), buf.size()); return Write(buf.data(), buf.size());
} }
OutputFormatter* OutputFormatter::Instance; thread_local OutputFormatter* OutputFormatter::Instance;
int OutputFormatter::WriteStatic(const char* buf, int count) int OutputFormatter::WriteStatic(const char* buf, int count)
{ {

View File

@ -25,7 +25,7 @@ private:
void Flush(); void Flush();
static OutputFormatter* Instance; static thread_local OutputFormatter* Instance;
static int WriteStatic(const char* buf, int count); static int WriteStatic(const char* buf, int count);
public: public:

View File

@ -1,3 +1,4 @@
#if 0
#include "ZOverlay.h" #include "ZOverlay.h"
#include <cassert> #include <cassert>
@ -350,3 +351,4 @@ ELFIO::Elf_Half ZOverlay::FindSymbolInSection(const std::string& curSymName,
} }
return SHN_UNDEF; return SHN_UNDEF;
} }
#endif

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#if 0
#include "Utils/Directory.h" #include "Utils/Directory.h"
#include "ZResource.h" #include "ZResource.h"
#include "elfio/elfio.hpp" #include "elfio/elfio.hpp"
@ -73,3 +75,4 @@ private:
ELFIO::Elf_Half FindSymbolInSection(const std::string& curSymName, ELFIO::section* sectionData, ELFIO::Elf_Half FindSymbolInSection(const std::string& curSymName, ELFIO::section* sectionData,
ELFIO::elfio& reader, size_t readerId); ELFIO::elfio& reader, size_t readerId);
}; };
#endif

View File

@ -74,15 +74,29 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>$(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\..\OTRExporter\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(ProjectDir)..\..\libultraship\libultraship\;$(LibraryPath)</LibraryPath> <LibraryPath>$(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\..\OTRExporter\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(ProjectDir)..\..\libultraship\libultraship\;$(LibraryPath)</LibraryPath>
<IncludePath>$(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath> <IncludePath>$(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>$(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath> <IncludePath>$(ProjectDir)..\ZAPDUtils;$(ProjectDir)..\lib\tinyxml2;$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\lib\elfio;$(ProjectDir)..\lib\stb;$(ProjectDir);$(IncludePath)</IncludePath>
<LibraryPath>$(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\..\OTRExporter\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(ProjectDir)..\..\libultraship\libultraship\;$(LibraryPath)</LibraryPath> <LibraryPath>$(OutDir);$(ProjectDir)..\lib\libgfxd;$(ProjectDir)..\..\OTRExporter\packages\libpng-v142.1.6.37.2\build\native\lib\x64\v142\Debug\;$(ProjectDir)..\..\libultraship\libultraship\;$(LibraryPath)</LibraryPath>
<PreBuildEventUseInBuild>false</PreBuildEventUseInBuild> <PreBuildEventUseInBuild>false</PreBuildEventUseInBuild>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <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> <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> <LibraryPath>$(SolutionDir)ZAPD\lib\libgfxd;$(SolutionDir)x64\Debug;$(SolutionDir)packages\libpng.1.6.28.1\build\native\lib\x64\v140\dynamic\Debug;$(LibraryPath)</LibraryPath>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
@ -170,6 +184,7 @@
<ClCompile Include="..\lib\libgfxd\uc_f3dex2.c" /> <ClCompile Include="..\lib\libgfxd\uc_f3dex2.c" />
<ClCompile Include="..\lib\libgfxd\uc_f3dexb.c" /> <ClCompile Include="..\lib\libgfxd\uc_f3dexb.c" />
<ClCompile Include="Declaration.cpp" /> <ClCompile Include="Declaration.cpp" />
<ClCompile Include="FileWorker.cpp" />
<ClCompile Include="GameConfig.cpp" /> <ClCompile Include="GameConfig.cpp" />
<ClCompile Include="Globals.cpp" /> <ClCompile Include="Globals.cpp" />
<ClCompile Include="ImageBackend.cpp" /> <ClCompile Include="ImageBackend.cpp" />
@ -178,6 +193,7 @@
<ClCompile Include="OutputFormatter.cpp" /> <ClCompile Include="OutputFormatter.cpp" />
<ClCompile Include="Overlays\ZOverlay.cpp" /> <ClCompile Include="Overlays\ZOverlay.cpp" />
<ClCompile Include="WarningHandler.cpp" /> <ClCompile Include="WarningHandler.cpp" />
<ClCompile Include="yaz0\yaz0.cpp" />
<ClCompile Include="ZArray.cpp" /> <ClCompile Include="ZArray.cpp" />
<ClCompile Include="ZBackground.cpp" /> <ClCompile Include="ZBackground.cpp" />
<ClCompile Include="ZCutsceneMM.cpp" /> <ClCompile Include="ZCutsceneMM.cpp" />
@ -185,6 +201,7 @@
<ClCompile Include="ZMtx.cpp" /> <ClCompile Include="ZMtx.cpp" />
<ClCompile Include="ZPath.cpp" /> <ClCompile Include="ZPath.cpp" />
<ClCompile Include="ZPlayerAnimationData.cpp" /> <ClCompile Include="ZPlayerAnimationData.cpp" />
<ClCompile Include="ZRom.cpp" />
<ClCompile Include="ZRoom\Commands\SetActorCutsceneList.cpp" /> <ClCompile Include="ZRoom\Commands\SetActorCutsceneList.cpp" />
<ClCompile Include="ZRoom\Commands\SetAnimatedMaterialList.cpp" /> <ClCompile Include="ZRoom\Commands\SetAnimatedMaterialList.cpp" />
<ClCompile Include="ZRoom\Commands\SetCsCamera.cpp" /> <ClCompile Include="ZRoom\Commands\SetCsCamera.cpp" />
@ -257,7 +274,9 @@
<ClInclude Include="..\lib\stb\stb_image_write.h" /> <ClInclude Include="..\lib\stb\stb_image_write.h" />
<ClInclude Include="..\lib\stb\tinyxml2.h" /> <ClInclude Include="..\lib\stb\tinyxml2.h" />
<ClInclude Include="CRC32.h" /> <ClInclude Include="CRC32.h" />
<ClInclude Include="ctpl_stl.h" />
<ClInclude Include="Declaration.h" /> <ClInclude Include="Declaration.h" />
<ClInclude Include="FileWorker.h" />
<ClInclude Include="GameConfig.h" /> <ClInclude Include="GameConfig.h" />
<ClInclude Include="Globals.h" /> <ClInclude Include="Globals.h" />
<ClInclude Include="ImageBackend.h" /> <ClInclude Include="ImageBackend.h" />
@ -265,6 +284,8 @@
<ClInclude Include="OutputFormatter.h" /> <ClInclude Include="OutputFormatter.h" />
<ClInclude Include="Overlays\ZOverlay.h" /> <ClInclude Include="Overlays\ZOverlay.h" />
<ClInclude Include="WarningHandler.h" /> <ClInclude Include="WarningHandler.h" />
<ClInclude Include="yaz0\readwrite.h" />
<ClInclude Include="yaz0\yaz0.h" />
<ClInclude Include="ZAnimation.h" /> <ClInclude Include="ZAnimation.h" />
<ClInclude Include="ZArray.h" /> <ClInclude Include="ZArray.h" />
<ClInclude Include="ZBackground.h" /> <ClInclude Include="ZBackground.h" />
@ -278,6 +299,7 @@
<ClInclude Include="ZMtx.h" /> <ClInclude Include="ZMtx.h" />
<ClInclude Include="ZPath.h" /> <ClInclude Include="ZPath.h" />
<ClInclude Include="ZPlayerAnimationData.h" /> <ClInclude Include="ZPlayerAnimationData.h" />
<ClInclude Include="ZRom.h" />
<ClInclude Include="ZRoom\Commands\SetActorCutsceneList.h" /> <ClInclude Include="ZRoom\Commands\SetActorCutsceneList.h" />
<ClInclude Include="ZRoom\Commands\SetAnimatedMaterialList.h" /> <ClInclude Include="ZRoom\Commands\SetAnimatedMaterialList.h" />
<ClInclude Include="ZRoom\Commands\SetCsCamera.h" /> <ClInclude Include="ZRoom\Commands\SetCsCamera.h" />
@ -334,6 +356,12 @@
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\OTRGui\build\ZERO_CHECK.vcxproj">
<Project>{02d10590-9542-3f55-aaf8-6055677e2a2a}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">
<Import Project="..\..\OTRExporter\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets" Condition="Exists('..\..\OTRExporter\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets')" /> <Import Project="..\..\OTRExporter\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets" Condition="Exists('..\..\OTRExporter\packages\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.1.2.8.8\build\native\zlib.v120.windesktop.msvcstl.dyn.rt-dyn.targets')" />

View File

@ -58,6 +58,12 @@
<Filter Include="NuGet"> <Filter Include="NuGet">
<UniqueIdentifier>{730beb67-6d59-4849-9d9b-702c4a565fc0}</UniqueIdentifier> <UniqueIdentifier>{730beb67-6d59-4849-9d9b-702c4a565fc0}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Source Files\Yaz0">
<UniqueIdentifier>{b26457d2-cdb8-4c92-9ed7-a55bf6d3619e}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Yaz0">
<UniqueIdentifier>{9651a041-1019-4486-9e90-1dccfa9471e9}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Main.cpp"> <ClCompile Include="Main.cpp">
@ -282,6 +288,15 @@
<ClCompile Include="ZText.cpp"> <ClCompile Include="ZText.cpp">
<Filter>Source Files\Z64</Filter> <Filter>Source Files\Z64</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="ZRom.cpp">
<Filter>Source Files\Z64</Filter>
</ClCompile>
<ClCompile Include="yaz0\yaz0.cpp">
<Filter>Source Files\Yaz0</Filter>
</ClCompile>
<ClCompile Include="FileWorker.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="ZRoom\ZRoom.h"> <ClInclude Include="ZRoom\ZRoom.h">
@ -539,6 +554,21 @@
<ClInclude Include="ZText.h"> <ClInclude Include="ZText.h">
<Filter>Header Files\Z64</Filter> <Filter>Header Files\Z64</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="ZRom.h">
<Filter>Header Files\Z64</Filter>
</ClInclude>
<ClInclude Include="yaz0\readwrite.h">
<Filter>Header Files\Yaz0</Filter>
</ClInclude>
<ClInclude Include="yaz0\yaz0.h">
<Filter>Header Files\Yaz0</Filter>
</ClInclude>
<ClInclude Include="FileWorker.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ctpl_stl.h">
<Filter>Header Files\Libraries</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Text Include="..\SymbolMap_OoTMqDbg.txt"> <Text Include="..\SymbolMap_OoTMqDbg.txt">

View File

@ -112,12 +112,15 @@ void ZNormalAnimation::DeclareReferences(const std::string& prefix)
const uint8_t lineLength = 14; const uint8_t lineLength = 14;
const uint8_t offset = 0; const uint8_t offset = 0;
for (size_t i = 0; i < rotationValues.size(); i++) if (!Globals::Instance->otrMode)
{ {
valuesStr += StringHelper::Sprintf("0x%04X, ", rotationValues[i]); for (size_t i = 0; i < rotationValues.size(); i++)
{
valuesStr += StringHelper::Sprintf("0x%04X, ", rotationValues[i]);
if ((i - offset + 1) % lineLength == 0) if ((i - offset + 1) % lineLength == 0)
valuesStr += "\n "; valuesStr += "\n ";
}
} }
parent->AddDeclarationArray(rotationValuesOffset, DeclarationAlignment::Align4, parent->AddDeclarationArray(rotationValuesOffset, DeclarationAlignment::Align4,
@ -125,13 +128,17 @@ void ZNormalAnimation::DeclareReferences(const std::string& prefix)
StringHelper::Sprintf("%sFrameData", defaultPrefix.c_str()), StringHelper::Sprintf("%sFrameData", defaultPrefix.c_str()),
rotationValues.size(), valuesStr); rotationValues.size(), valuesStr);
for (size_t i = 0; i < rotationIndices.size(); i++) if (!Globals::Instance->otrMode)
{ {
indicesStr += StringHelper::Sprintf(" { 0x%04X, 0x%04X, 0x%04X },", rotationIndices[i].x, for (size_t i = 0; i < rotationIndices.size(); i++)
rotationIndices[i].y, rotationIndices[i].z); {
indicesStr +=
StringHelper::Sprintf(" { 0x%04X, 0x%04X, 0x%04X },", rotationIndices[i].x,
rotationIndices[i].y, rotationIndices[i].z);
if (i != (rotationIndices.size() - 1)) if (i != (rotationIndices.size() - 1))
indicesStr += "\n"; indicesStr += "\n";
}
} }
parent->AddDeclarationArray(rotationIndicesOffset, DeclarationAlignment::Align4, parent->AddDeclarationArray(rotationIndicesOffset, DeclarationAlignment::Align4,
@ -143,10 +150,11 @@ void ZNormalAnimation::DeclareReferences(const std::string& prefix)
std::string ZNormalAnimation::GetBodySourceCode() const std::string ZNormalAnimation::GetBodySourceCode() const
{ {
std::string frameDataName; std::string frameDataName;
Globals::Instance->GetSegmentedPtrName(rotationValuesSeg, parent, "s16", frameDataName); Globals::Instance->GetSegmentedPtrName(rotationValuesSeg, parent, "s16", frameDataName,
parent->workerID);
std::string jointIndicesName; std::string jointIndicesName;
Globals::Instance->GetSegmentedPtrName(rotationIndicesSeg, parent, "JointIndex", Globals::Instance->GetSegmentedPtrName(rotationIndicesSeg, parent, "JointIndex",
jointIndicesName); jointIndicesName, parent->workerID);
std::string headerStr = std::string headerStr =
StringHelper::Sprintf("\n\t{ %i }, %s,\n", frameCount, frameDataName.c_str()); StringHelper::Sprintf("\n\t{ %i }, %s,\n", frameCount, frameDataName.c_str());
@ -183,7 +191,7 @@ void ZLinkAnimation::ParseRawData()
std::string ZLinkAnimation::GetBodySourceCode() const std::string ZLinkAnimation::GetBodySourceCode() const
{ {
std::string segSymbol; std::string segSymbol;
Globals::Instance->GetSegmentedPtrName(segmentAddress, parent, "", segSymbol); Globals::Instance->GetSegmentedPtrName(segmentAddress, parent, "", segSymbol, parent->workerID);
return StringHelper::Sprintf("\n\t{ %i }, %s\n", frameCount, segSymbol.c_str()); return StringHelper::Sprintf("\n\t{ %i }, %s\n", frameCount, segSymbol.c_str());
} }
@ -383,12 +391,13 @@ void ZCurveAnimation::DeclareReferences(const std::string& prefix)
std::string ZCurveAnimation::GetBodySourceCode() const std::string ZCurveAnimation::GetBodySourceCode() const
{ {
std::string refIndexStr; std::string refIndexStr;
Globals::Instance->GetSegmentedPtrName(refIndex, parent, "u8", refIndexStr); Globals::Instance->GetSegmentedPtrName(refIndex, parent, "u8", refIndexStr, parent->workerID);
std::string transformDataStr; std::string transformDataStr;
Globals::Instance->GetSegmentedPtrName(transformData, parent, "TransformData", Globals::Instance->GetSegmentedPtrName(transformData, parent, "TransformData",
transformDataStr); transformDataStr, parent->workerID);
std::string copyValuesStr; std::string copyValuesStr;
Globals::Instance->GetSegmentedPtrName(copyValues, parent, "s16", 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(), 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); transformDataStr.c_str(), copyValuesStr.c_str(), unk_0C, unk_10);
@ -510,8 +519,10 @@ std::string ZLegacyAnimation::GetBodySourceCode() const
std::string frameDataName; std::string frameDataName;
std::string jointKeyName; std::string jointKeyName;
Globals::Instance->GetSegmentedPtrName(frameData, parent, "s16", frameDataName); Globals::Instance->GetSegmentedPtrName(frameData, parent, "s16", frameDataName,
Globals::Instance->GetSegmentedPtrName(jointKey, parent, "JointKey", jointKeyName); parent->workerID);
Globals::Instance->GetSegmentedPtrName(jointKey, parent, "JointKey", jointKeyName,
parent->workerID);
body += StringHelper::Sprintf("\t%i, %i,\n", frameCount, limbCount); body += StringHelper::Sprintf("\t%i, %i,\n", frameCount, limbCount);
body += StringHelper::Sprintf("\t%s,\n", frameDataName.c_str()); body += StringHelper::Sprintf("\t%s,\n", frameDataName.c_str());

View File

@ -102,8 +102,7 @@ std::string ZArray::GetBodySourceCode() const
const auto& res = resList[i]; const auto& res = resList[i];
output += "\t"; output += "\t";
if (res->GetResourceType() == ZResourceType::Scalar || if (res->GetResourceType() == ZResourceType::Scalar || res->GetResourceType() == ZResourceType::Vertex)
res->GetResourceType() == ZResourceType::Vertex)
output += resList.at(i)->GetBodySourceCode(); output += resList.at(i)->GetBodySourceCode();
else else
output += StringHelper::Sprintf("{ %s }", resList.at(i)->GetBodySourceCode().c_str()); output += StringHelper::Sprintf("{ %s }", resList.at(i)->GetBodySourceCode().c_str());

View File

@ -150,8 +150,11 @@ std::string ZBackground::GetExternalExtension() const
void ZBackground::Save(const fs::path& outFolder) void ZBackground::Save(const fs::path& outFolder)
{ {
fs::path filepath = outFolder / (outName + "." + GetExternalExtension()); if (!Globals::Instance->otrMode)
File::WriteAllBytes(filepath.string(), data); {
fs::path filepath = outFolder / (outName + "." + GetExternalExtension());
File::WriteAllBytes(filepath.string(), data);
}
} }
std::string ZBackground::GetBodySourceCode() const std::string ZBackground::GetBodySourceCode() const

View File

@ -97,12 +97,15 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix)
if (waterBoxes.size() > 0) if (waterBoxes.size() > 0)
{ {
for (size_t i = 0; i < waterBoxes.size(); i++) if (!Globals::Instance->otrMode)
{ {
declaration += for (size_t i = 0; i < waterBoxes.size(); i++)
StringHelper::Sprintf("\t{ %s },", waterBoxes[i].GetBodySourceCode().c_str()); {
if (i + 1 < waterBoxes.size()) declaration +=
declaration += "\n"; StringHelper::Sprintf("\t{ %s },", waterBoxes[i].GetBodySourceCode().c_str());
if (i + 1 < waterBoxes.size())
declaration += "\n";
}
} }
parent->AddDeclarationArray( parent->AddDeclarationArray(
@ -115,14 +118,17 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix)
{ {
declaration.clear(); declaration.clear();
for (size_t i = 0; i < polygons.size(); i++) if (!Globals::Instance->otrMode)
{ {
declaration += StringHelper::Sprintf( for (size_t i = 0; i < polygons.size(); i++)
"\t{ 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X },", {
polygons[i].type, polygons[i].vtxA, polygons[i].vtxB, polygons[i].vtxC, declaration += StringHelper::Sprintf(
polygons[i].a, polygons[i].b, polygons[i].c, polygons[i].d); "\t{ 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X, 0x%04X },",
if (i + 1 < polygons.size()) polygons[i].type, polygons[i].vtxA, polygons[i].vtxB, polygons[i].vtxC,
declaration += "\n"; polygons[i].a, polygons[i].b, polygons[i].c, polygons[i].d);
if (i + 1 < polygons.size())
declaration += "\n";
}
} }
parent->AddDeclarationArray( parent->AddDeclarationArray(
@ -132,13 +138,16 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix)
} }
declaration.clear(); declaration.clear();
for (size_t i = 0; i < polygonTypes.size(); i++) if (!Globals::Instance->otrMode)
{ {
declaration += StringHelper::Sprintf("\t{ 0x%08lX, 0x%08lX },", polygonTypes[i] >> 32, for (size_t i = 0; i < polygonTypes.size(); i++)
polygonTypes[i] & 0xFFFFFFFF); {
declaration += StringHelper::Sprintf("\t{ 0x%08lX, 0x%08lX },", polygonTypes[i] >> 32,
polygonTypes[i] & 0xFFFFFFFF);
if (i < polygonTypes.size() - 1) if (i < polygonTypes.size() - 1)
declaration += "\n"; declaration += "\n";
}
} }
if (polyTypeDefAddress != 0) if (polyTypeDefAddress != 0)
@ -154,13 +163,16 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix)
{ {
declaration.clear(); declaration.clear();
for (size_t i = 0; i < vertices.size(); i++) if (!Globals::Instance->otrMode)
{ {
declaration += for (size_t i = 0; i < vertices.size(); i++)
StringHelper::Sprintf("\t{ %s },", vertices[i].GetBodySourceCode().c_str()); {
declaration +=
StringHelper::Sprintf("\t{ %s },", vertices[i].GetBodySourceCode().c_str());
if (i < vertices.size() - 1) if (i < vertices.size() - 1)
declaration += "\n"; declaration += "\n";
}
} }
const auto& first = vertices.front(); const auto& first = vertices.front();
@ -177,29 +189,36 @@ std::string ZCollisionHeader::GetBodySourceCode() const
{ {
std::string declaration = ""; std::string declaration = "";
if (Globals::Instance->otrMode)
return declaration;
declaration += "\n"; declaration += "\n";
declaration += StringHelper::Sprintf("\t{ %i, %i, %i },\n", absMinX, absMinY, absMinZ); declaration += StringHelper::Sprintf("\t{ %i, %i, %i },\n", absMinX, absMinY, absMinZ);
declaration += StringHelper::Sprintf("\t{ %i, %i, %i },\n", absMaxX, absMaxY, absMaxZ); declaration += StringHelper::Sprintf("\t{ %i, %i, %i },\n", absMaxX, absMaxY, absMaxZ);
std::string vtxName; std::string vtxName;
Globals::Instance->GetSegmentedPtrName(vtxAddress, parent, "Vec3s", vtxName); Globals::Instance->GetSegmentedPtrName(vtxAddress, parent, "Vec3s", vtxName, parent->workerID);
declaration += StringHelper::Sprintf("\t%i,\n\t%s,\n", numVerts, vtxName.c_str()); declaration += StringHelper::Sprintf("\t%i,\n\t%s,\n", numVerts, vtxName.c_str());
std::string polyName; std::string polyName;
Globals::Instance->GetSegmentedPtrName(polyAddress, parent, "CollisionPoly", polyName); Globals::Instance->GetSegmentedPtrName(polyAddress, parent, "CollisionPoly", polyName,
parent->workerID);
declaration += StringHelper::Sprintf("\t%i,\n\t%s,\n", numPolygons, polyName.c_str()); declaration += StringHelper::Sprintf("\t%i,\n\t%s,\n", numPolygons, polyName.c_str());
std::string surfaceName; std::string surfaceName;
Globals::Instance->GetSegmentedPtrName(polyTypeDefAddress, parent, "SurfaceType", surfaceName); Globals::Instance->GetSegmentedPtrName(polyTypeDefAddress, parent, "SurfaceType", surfaceName,
parent->workerID);
declaration += StringHelper::Sprintf("\t%s,\n", surfaceName.c_str()); declaration += StringHelper::Sprintf("\t%s,\n", surfaceName.c_str());
std::string camName; std::string camName;
Globals::Instance->GetSegmentedPtrName(camDataAddress, parent, "CamData", camName); Globals::Instance->GetSegmentedPtrName(camDataAddress, parent, "CamData", camName,
parent->workerID);
declaration += StringHelper::Sprintf("\t%s,\n", camName.c_str()); declaration += StringHelper::Sprintf("\t%s,\n", camName.c_str());
std::string waterBoxName; std::string waterBoxName;
Globals::Instance->GetSegmentedPtrName(waterBoxAddress, parent, "WaterBox", waterBoxName); Globals::Instance->GetSegmentedPtrName(waterBoxAddress, parent, "WaterBox", waterBoxName,
parent->workerID);
declaration += StringHelper::Sprintf("\t%i,\n\t%s\n", numWaterBoxes, waterBoxName.c_str()); declaration += StringHelper::Sprintf("\t%i,\n\t%s\n", numWaterBoxes, waterBoxName.c_str());
return declaration; return declaration;

View File

@ -15,6 +15,124 @@
#include "WarningHandler.h" #include "WarningHandler.h"
#include "gfxd.h" #include "gfxd.h"
#define G_MDSFT_ALPHACOMPARE 0
#define G_MDSFT_ZSRCSEL 2
#define G_MDSFT_RENDERMODE 3
#define G_MDSFT_BLENDER 16
#define G_RM_FOG_SHADE_A 0xC8000000
#define G_RM_FOG_PRIM_A 0xC4000000
#define G_RM_PASS 0x0C080000
#define G_RM_AA_ZB_OPA_SURF 0x442078
#define G_RM_AA_ZB_OPA_SURF2 0x112078
#define G_RM_AA_ZB_XLU_SURF 0x4049D8
#define G_RM_AA_ZB_XLU_SURF2 0x1049D8
#define G_RM_AA_ZB_OPA_DECAL 0x442D58
#define G_RM_AA_ZB_OPA_DECAL2 0x112D58
#define G_RM_AA_ZB_XLU_DECAL 0x404DD8
#define G_RM_AA_ZB_XLU_DECAL2 0x104DD8
#define G_RM_AA_ZB_OPA_INTER 0x442478
#define G_RM_AA_ZB_OPA_INTER2 0x112478
#define G_RM_AA_ZB_XLU_INTER 0x4045D8
#define G_RM_AA_ZB_XLU_INTER2 0x1045D8
#define G_RM_AA_ZB_XLU_LINE 0x407858
#define G_RM_AA_ZB_XLU_LINE2 0x107858
#define G_RM_AA_ZB_DEC_LINE 0x407F58
#define G_RM_AA_ZB_DEC_LINE2 0x107F58
#define G_RM_AA_ZB_TEX_EDGE 0x443078
#define G_RM_AA_ZB_TEX_EDGE2 0x113078
#define G_RM_AA_ZB_TEX_INTER 0x443478
#define G_RM_AA_ZB_TEX_INTER2 0x113478
#define G_RM_AA_ZB_SUB_SURF 0x442878
#define G_RM_AA_ZB_SUB_SURF2 0x112278
#define G_RM_AA_ZB_PCL_SURF 0x40007B
#define G_RM_AA_ZB_PCL_SURF2 0x10007B
#define G_RM_AA_ZB_OPA_TERR 0x402078
#define G_RM_AA_ZB_OPA_TERR2 0x102078
#define G_RM_AA_ZB_TEX_TERR 0x403078
#define G_RM_AA_ZB_TEX_TERR2 0x103078
#define G_RM_AA_ZB_SUB_TERR 0x402278
#define G_RM_AA_ZB_SUB_TERR2 0x102278
#define G_RM_RA_ZB_OPA_SURF 0x442038
#define G_RM_RA_ZB_OPA_SURF2 0x112038
#define G_RM_RA_ZB_OPA_DECAL 0x442D18
#define G_RM_RA_ZB_OPA_DECAL2 0x112D18
#define G_RM_RA_ZB_OPA_INTER 0x442438
#define G_RM_RA_ZB_OPA_INTER2 0x112438
#define G_RM_AA_OPA_SURF 0x442048
#define G_RM_AA_OPA_SURF2 0x112048
#define G_RM_AA_XLU_SURF 0x4041C8
#define G_RM_AA_XLU_SURF2 0x1041C8
#define G_RM_AA_XLU_LINE 0x407048
#define G_RM_AA_XLU_LINE2 0x107048
#define G_RM_AA_DEC_LINE 0x407248
#define G_RM_AA_DEC_LINE2 0x107248
#define G_RM_AA_TEX_EDGE 0x443048
#define G_RM_AA_TEX_EDGE2 0x113048
#define G_RM_AA_SUB_SURF 0x442248
#define G_RM_AA_SUB_SURF2 0x112248
#define G_RM_AA_PCL_SURF 0x40004B
#define G_RM_AA_PCL_SURF2 0x10004B
#define G_RM_AA_OPA_TERR 0x402048
#define G_RM_AA_OPA_TERR2 0x102048
#define G_RM_AA_TEX_TERR 0x403048
#define G_RM_AA_TEX_TERR2 0x103048
#define G_RM_AA_SUB_TERR 0x402248
#define G_RM_AA_SUB_TERR2 0x102248
#define G_RM_RA_OPA_SURF 0x442008
#define G_RM_RA_OPA_SURF2 0x112008
#define G_RM_ZB_OPA_SURF 0x442230
#define G_RM_ZB_OPA_SURF2 0x112230
#define G_RM_ZB_XLU_SURF 0x404A50
#define G_RM_ZB_XLU_SURF2 0x104A50
#define G_RM_ZB_OPA_DECAL 0x442E10
#define G_RM_ZB_OPA_DECAL2 0x112E10
#define G_RM_ZB_XLU_DECAL 0x404E50
#define G_RM_ZB_XLU_DECAL2 0x104E50
#define G_RM_ZB_CLD_SURF 0x404B50
#define G_RM_ZB_CLD_SURF2 0x104B50
#define G_RM_ZB_OVL_SURF 0x404F50
#define G_RM_ZB_OVL_SURF2 0x104F50
#define G_RM_ZB_PCL_SURF 0x0C080233
#define G_RM_ZB_PCL_SURF2 0x03020233
#define G_RM_OPA_SURF 0x0C084000
#define G_RM_OPA_SURF2 0x03024000
#define G_RM_XLU_SURF 0x00404200
#define G_RM_XLU_SURF2 0x00104240
#define G_RM_CLD_SURF 0x00404340
#define G_RM_CLD_SURF2 0x00104340
#define G_RM_TEX_EDGE 0x0C087008
#define G_RM_TEX_EDGE2 0x03027008
#define G_RM_PCL_SURF 0x0C084203
#define G_RM_PCL_SURF2 0x03024203
#define G_RM_ADD 0x04484340
#define G_RM_ADD2 0x01124340
#define G_RM_NOOP 0x00000000
#define G_RM_NOOP2 0x00000000
#define G_RM_VISCVG 0x0C844040
#define G_RM_VISCVG2 0x03214040
#define G_RM_OPA_CI 0x0C080000
#define G_RM_OPA_CI2 0x03020000
#define AA_EN 0x8
#define Z_CMP 0x10
#define Z_UPD 0x20
#define IM_RD 0x40
#define CLR_ON_CVG 0x80
#define CVG_DST_CLAMP 0
#define CVG_DST_WRAP 0x100
#define CVG_DST_FULL 0x200
#define CVG_DST_SAVE 0x300
#define ZMODE_OPA 0
#define ZMODE_INTER 0x400
#define ZMODE_XLU 0x800
#define ZMODE_DEC 0xc00
#define CVG_X_ALPHA 0x1000
#define ALPHA_CVG_SEL 0x2000
#define FORCE_BL 0x4000
#define TEX_EDGE 0x0000
REGISTER_ZFILENODE(DList, ZDisplayList); REGISTER_ZFILENODE(DList, ZDisplayList);
ZDisplayList::ZDisplayList(ZFile* nParent) : ZResource(nParent) ZDisplayList::ZDisplayList(ZFile* nParent) : ZResource(nParent)
@ -553,7 +671,8 @@ int32_t ZDisplayList::OptimizationCheck_LoadTextureBlock(int32_t startIndex, std
lastTexSeg = segmentNumber; lastTexSeg = segmentNumber;
Globals::Instance->GetSegmentedPtrName(data & 0xFFFFFFFF, parent, "", texStr); Globals::Instance->GetSegmentedPtrName(data & 0xFFFFFFFF, parent, "", texStr,
parent->workerID);
} }
// gsDPSetTile // gsDPSetTile
@ -705,7 +824,7 @@ void ZDisplayList::Opcode_G_DL(uint64_t data, const std::string& prefix, char* l
if (pp != 0) if (pp != 0)
{ {
if (!Globals::Instance->HasSegment(segNum)) if (!Globals::Instance->HasSegment(segNum, parent->workerID))
sprintf(line, "gsSPBranchList(0x%08" PRIX64 "),", data & 0xFFFFFFFF); sprintf(line, "gsSPBranchList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
else if (dListDecl != nullptr) else if (dListDecl != nullptr)
sprintf(line, "gsSPBranchList(%s),", dListDecl->varName.c_str()); sprintf(line, "gsSPBranchList(%s),", dListDecl->varName.c_str());
@ -715,7 +834,7 @@ void ZDisplayList::Opcode_G_DL(uint64_t data, const std::string& prefix, char* l
} }
else else
{ {
if (!Globals::Instance->HasSegment(segNum)) if (!Globals::Instance->HasSegment(segNum, parent->workerID))
sprintf(line, "gsSPDisplayList(0x%08" PRIX64 "),", data & 0xFFFFFFFF); sprintf(line, "gsSPDisplayList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
else if (dListDecl != nullptr) else if (dListDecl != nullptr)
sprintf(line, "gsSPDisplayList(%s),", dListDecl->varName.c_str()); sprintf(line, "gsSPDisplayList(%s),", dListDecl->varName.c_str());
@ -726,7 +845,7 @@ void ZDisplayList::Opcode_G_DL(uint64_t data, const std::string& prefix, char* l
// if (segNum == 8 || segNum == 9 || segNum == 10 || segNum == 11 || segNum == 12 || segNum == // if (segNum == 8 || segNum == 9 || segNum == 10 || segNum == 11 || segNum == 12 || segNum ==
// 13) // Used for runtime-generated display lists // 13) // Used for runtime-generated display lists
if (!Globals::Instance->HasSegment(segNum)) if (!Globals::Instance->HasSegment(segNum, parent->workerID))
{ {
if (pp != 0) if (pp != 0)
sprintf(line, "gsSPBranchList(0x%08" PRIX64 "),", data & 0xFFFFFFFF); sprintf(line, "gsSPBranchList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
@ -847,7 +966,7 @@ void ZDisplayList::Opcode_G_VTX(uint64_t data, char* line)
} }
// Hack: Don't extract vertices from a unknown segment. // Hack: Don't extract vertices from a unknown segment.
if (!Globals::Instance->HasSegment(GETSEGNUM(data))) if (!Globals::Instance->HasSegment(GETSEGNUM(data), parent->workerID))
{ {
segptr_t segmented = data & 0xFFFFFFFF; segptr_t segmented = data & 0xFFFFFFFF;
references.push_back(segmented); references.push_back(segmented);
@ -951,7 +1070,7 @@ void ZDisplayList::Opcode_G_SETTIMG(uint64_t data, const std::string& prefix, ch
if (parent != nullptr) if (parent != nullptr)
{ {
if (Globals::Instance->HasSegment(segmentNumber)) if (Globals::Instance->HasSegment(segmentNumber, parent->workerID))
texDecl = parent->GetDeclaration(texAddress); texDecl = parent->GetDeclaration(texAddress);
else else
texDecl = parent->GetDeclaration(data); texDecl = parent->GetDeclaration(data);
@ -959,7 +1078,7 @@ void ZDisplayList::Opcode_G_SETTIMG(uint64_t data, const std::string& prefix, ch
if (texDecl != nullptr) if (texDecl != nullptr)
sprintf(texStr, "%s", texDecl->varName.c_str()); sprintf(texStr, "%s", texDecl->varName.c_str());
else if (data != 0 && Globals::Instance->HasSegment(segmentNumber)) else if (data != 0 && Globals::Instance->HasSegment(segmentNumber, parent->workerID))
sprintf(texStr, "%sTex_%06X", prefix.c_str(), texAddress); sprintf(texStr, "%sTex_%06X", prefix.c_str(), texAddress);
else else
{ {
@ -972,7 +1091,7 @@ void ZDisplayList::Opcode_G_SETTIMG(uint64_t data, const std::string& prefix, ch
else else
{ {
std::string texName; std::string texName;
Globals::Instance->GetSegmentedPtrName(data, parent, "", texName); Globals::Instance->GetSegmentedPtrName(data, parent, "", texName, parent->workerID);
sprintf(line, "gsDPSetTextureImage(%s, %s, %i, %s),", fmtTbl[fmt], sizTbl[siz], www + 1, sprintf(line, "gsDPSetTextureImage(%s, %s, %i, %s),", fmtTbl[fmt], sizTbl[siz], www + 1,
texName.c_str()); texName.c_str());
} }
@ -1647,7 +1766,9 @@ static int32_t GfxdCallback_Vtx(uint32_t seg, int32_t count)
} }
self->references.push_back(seg); self->references.push_back(seg);
gfxd_puts("@r");
if (!Globals::Instance->otrMode)
gfxd_puts("@r");
return 1; return 1;
} }
@ -1670,7 +1791,7 @@ static int32_t GfxdCallback_Texture(segptr_t seg, int32_t fmt, int32_t siz, int3
self->TextureGenCheck(); self->TextureGenCheck();
std::string texName; std::string texName;
Globals::Instance->GetSegmentedPtrName(seg, self->parent, "", texName); Globals::Instance->GetSegmentedPtrName(seg, self->parent, "", texName, self->parent->workerID);
gfxd_puts(texName.c_str()); gfxd_puts(texName.c_str());
@ -1694,7 +1815,7 @@ static int32_t GfxdCallback_Palette(uint32_t seg, [[maybe_unused]] int32_t idx,
self->TextureGenCheck(); self->TextureGenCheck();
std::string palName; std::string palName;
Globals::Instance->GetSegmentedPtrName(seg, self->parent, "", palName); Globals::Instance->GetSegmentedPtrName(seg, self->parent, "", palName, self->parent->workerID);
gfxd_puts(palName.c_str()); gfxd_puts(palName.c_str());
@ -1708,7 +1829,8 @@ static int32_t GfxdCallback_DisplayList(uint32_t seg)
uint32_t dListSegNum = GETSEGNUM(seg); uint32_t dListSegNum = GETSEGNUM(seg);
std::string dListName = ""; std::string dListName = "";
bool addressFound = Globals::Instance->GetSegmentedPtrName(seg, self->parent, "Gfx", dListName); bool addressFound = Globals::Instance->GetSegmentedPtrName(seg, self->parent, "Gfx", dListName,
self->parent->workerID);
if (!addressFound && self->parent->segment == dListSegNum) if (!addressFound && self->parent->segment == dListSegNum)
{ {
@ -1731,7 +1853,8 @@ static int32_t GfxdCallback_Matrix(uint32_t seg)
std::string mtxName; std::string mtxName;
ZDisplayList* self = static_cast<ZDisplayList*>(gfxd_udata_get()); ZDisplayList* self = static_cast<ZDisplayList*>(gfxd_udata_get());
bool addressFound = Globals::Instance->GetSegmentedPtrName(seg, self->parent, "Mtx", mtxName); bool addressFound = Globals::Instance->GetSegmentedPtrName(seg, self->parent, "Mtx", mtxName,
self->parent->workerID);
if (!addressFound && GETSEGNUM(seg) == self->parent->segment) if (!addressFound && GETSEGNUM(seg) == self->parent->segment)
{ {
Declaration* decl = Declaration* decl =
@ -1805,6 +1928,23 @@ void ZDisplayList::DeclareReferences(const std::string& prefix)
curAddr, firstVtx.GetDeclarationAlignment(), curAddr, firstVtx.GetDeclarationAlignment(),
item.second.size() * firstVtx.GetRawDataSize(), firstVtx.GetSourceTypeName(), item.second.size() * firstVtx.GetRawDataSize(), firstVtx.GetSourceTypeName(),
firstVtx.GetDefaultName(name), item.second.size(), declaration); firstVtx.GetDefaultName(name), item.second.size(), declaration);
/*for (auto vtx : item.second)
{
ZVtx* nVtx = new ZVtx(vtx.parent);
nVtx->x = vtx.x;
nVtx->y = vtx.y;
nVtx->z = vtx.z;
nVtx->flag = vtx.flag;
nVtx->s = vtx.s;
nVtx->t = vtx.t;
nVtx->r = vtx.r;
nVtx->g = vtx.g;
nVtx->b = vtx.b;
nVtx->a = vtx.a;
decl->vertexHack.push_back(nVtx);
}*/
decl->isExternal = true; decl->isExternal = true;
} }
} }
@ -1850,15 +1990,15 @@ void ZDisplayList::DeclareReferences(const std::string& prefix)
{ {
auto& item = vertices[vtxKeys[i]]; auto& item = vertices[vtxKeys[i]];
std::string declaration; //std::string declaration;
for (auto& vtx : item) //for (auto& vtx : item)
declaration += StringHelper::Sprintf("\t%s,\n", vtx.GetBodySourceCode().c_str()); //declaration += StringHelper::Sprintf("\t%s,\n", vtx.GetBodySourceCode().c_str());
// Ensure there's always a trailing line feed to prevent dumb warnings. // 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 // Please don't remove this line, unless you somehow made a way to prevent
// that warning when building the OoT repo. // that warning when building the OoT repo.
declaration += "\n"; //declaration += "\n";
if (parent != nullptr) if (parent != nullptr)
{ {
@ -1870,12 +2010,6 @@ void ZDisplayList::DeclareReferences(const std::string& prefix)
else else
vtxName = StringHelper::Sprintf("%sVtx_%06X", prefix.c_str(), vtxKeys[i]); vtxName = StringHelper::Sprintf("%sVtx_%06X", prefix.c_str(), vtxKeys[i]);
if (StringHelper::Contains(vtxName, "4B18"))
{
int bp = 0;
}
auto filepath = Globals::Instance->outputPath / vtxName; auto filepath = Globals::Instance->outputPath / vtxName;
std::string incStr = StringHelper::Sprintf("%s.%s.inc", filepath.string().c_str(), "vtx"); std::string incStr = StringHelper::Sprintf("%s.%s.inc", filepath.string().c_str(), "vtx");
@ -1991,7 +2125,7 @@ bool ZDisplayList::TextureGenCheck(int32_t texWidth, int32_t texHeight, uint32_t
texWidth, texHeight, texIsPalette, texAddr); texWidth, texHeight, texIsPalette, texAddr);
if ((texSeg != 0 || texAddr != 0) && texWidth > 0 && texHeight > 0 && texLoaded && if ((texSeg != 0 || texAddr != 0) && texWidth > 0 && texHeight > 0 && texLoaded &&
Globals::Instance->HasSegment(segmentNumber)) Globals::Instance->HasSegment(segmentNumber, self->parent->workerID))
{ {
ZFile* auxParent = nullptr; ZFile* auxParent = nullptr;
if (segmentNumber == self->parent->segment) if (segmentNumber == self->parent->segment)
@ -2002,7 +2136,8 @@ bool ZDisplayList::TextureGenCheck(int32_t texWidth, int32_t texHeight, uint32_t
{ {
// Try to find a non-external file (i.e., one we are actually extracting) // Try to find a non-external file (i.e., one we are actually extracting)
// which has the same segment number we are looking for. // which has the same segment number we are looking for.
for (auto& otherFile : Globals::Instance->cfg.segmentRefFiles[segmentNumber]) auto segs = Globals::Instance->GetSegmentRefFiles(self->parent->workerID);
for (auto& otherFile : segs[segmentNumber])
{ {
if (!otherFile->isExternalFile) if (!otherFile->isExternalFile)
{ {

View File

@ -166,122 +166,6 @@ enum class OoTSegments
FrameBuffer = 16, FrameBuffer = 16,
}; };
#define G_MDSFT_ALPHACOMPARE 0
#define G_MDSFT_ZSRCSEL 2
#define G_MDSFT_RENDERMODE 3
#define G_MDSFT_BLENDER 16
#define G_RM_FOG_SHADE_A 0xC8000000
#define G_RM_FOG_PRIM_A 0xC4000000
#define G_RM_PASS 0x0C080000
#define G_RM_AA_ZB_OPA_SURF 0x442078
#define G_RM_AA_ZB_OPA_SURF2 0x112078
#define G_RM_AA_ZB_XLU_SURF 0x4049D8
#define G_RM_AA_ZB_XLU_SURF2 0x1049D8
#define G_RM_AA_ZB_OPA_DECAL 0x442D58
#define G_RM_AA_ZB_OPA_DECAL2 0x112D58
#define G_RM_AA_ZB_XLU_DECAL 0x404DD8
#define G_RM_AA_ZB_XLU_DECAL2 0x104DD8
#define G_RM_AA_ZB_OPA_INTER 0x442478
#define G_RM_AA_ZB_OPA_INTER2 0x112478
#define G_RM_AA_ZB_XLU_INTER 0x4045D8
#define G_RM_AA_ZB_XLU_INTER2 0x1045D8
#define G_RM_AA_ZB_XLU_LINE 0x407858
#define G_RM_AA_ZB_XLU_LINE2 0x107858
#define G_RM_AA_ZB_DEC_LINE 0x407F58
#define G_RM_AA_ZB_DEC_LINE2 0x107F58
#define G_RM_AA_ZB_TEX_EDGE 0x443078
#define G_RM_AA_ZB_TEX_EDGE2 0x113078
#define G_RM_AA_ZB_TEX_INTER 0x443478
#define G_RM_AA_ZB_TEX_INTER2 0x113478
#define G_RM_AA_ZB_SUB_SURF 0x442878
#define G_RM_AA_ZB_SUB_SURF2 0x112278
#define G_RM_AA_ZB_PCL_SURF 0x40007B
#define G_RM_AA_ZB_PCL_SURF2 0x10007B
#define G_RM_AA_ZB_OPA_TERR 0x402078
#define G_RM_AA_ZB_OPA_TERR2 0x102078
#define G_RM_AA_ZB_TEX_TERR 0x403078
#define G_RM_AA_ZB_TEX_TERR2 0x103078
#define G_RM_AA_ZB_SUB_TERR 0x402278
#define G_RM_AA_ZB_SUB_TERR2 0x102278
#define G_RM_RA_ZB_OPA_SURF 0x442038
#define G_RM_RA_ZB_OPA_SURF2 0x112038
#define G_RM_RA_ZB_OPA_DECAL 0x442D18
#define G_RM_RA_ZB_OPA_DECAL2 0x112D18
#define G_RM_RA_ZB_OPA_INTER 0x442438
#define G_RM_RA_ZB_OPA_INTER2 0x112438
#define G_RM_AA_OPA_SURF 0x442048
#define G_RM_AA_OPA_SURF2 0x112048
#define G_RM_AA_XLU_SURF 0x4041C8
#define G_RM_AA_XLU_SURF2 0x1041C8
#define G_RM_AA_XLU_LINE 0x407048
#define G_RM_AA_XLU_LINE2 0x107048
#define G_RM_AA_DEC_LINE 0x407248
#define G_RM_AA_DEC_LINE2 0x107248
#define G_RM_AA_TEX_EDGE 0x443048
#define G_RM_AA_TEX_EDGE2 0x113048
#define G_RM_AA_SUB_SURF 0x442248
#define G_RM_AA_SUB_SURF2 0x112248
#define G_RM_AA_PCL_SURF 0x40004B
#define G_RM_AA_PCL_SURF2 0x10004B
#define G_RM_AA_OPA_TERR 0x402048
#define G_RM_AA_OPA_TERR2 0x102048
#define G_RM_AA_TEX_TERR 0x403048
#define G_RM_AA_TEX_TERR2 0x103048
#define G_RM_AA_SUB_TERR 0x402248
#define G_RM_AA_SUB_TERR2 0x102248
#define G_RM_RA_OPA_SURF 0x442008
#define G_RM_RA_OPA_SURF2 0x112008
#define G_RM_ZB_OPA_SURF 0x442230
#define G_RM_ZB_OPA_SURF2 0x112230
#define G_RM_ZB_XLU_SURF 0x404A50
#define G_RM_ZB_XLU_SURF2 0x104A50
#define G_RM_ZB_OPA_DECAL 0x442E10
#define G_RM_ZB_OPA_DECAL2 0x112E10
#define G_RM_ZB_XLU_DECAL 0x404E50
#define G_RM_ZB_XLU_DECAL2 0x104E50
#define G_RM_ZB_CLD_SURF 0x404B50
#define G_RM_ZB_CLD_SURF2 0x104B50
#define G_RM_ZB_OVL_SURF 0x404F50
#define G_RM_ZB_OVL_SURF2 0x104F50
#define G_RM_ZB_PCL_SURF 0x0C080233
#define G_RM_ZB_PCL_SURF2 0x03020233
#define G_RM_OPA_SURF 0x0C084000
#define G_RM_OPA_SURF2 0x03024000
#define G_RM_XLU_SURF 0x00404200
#define G_RM_XLU_SURF2 0x00104240
#define G_RM_CLD_SURF 0x00404340
#define G_RM_CLD_SURF2 0x00104340
#define G_RM_TEX_EDGE 0x0C087008
#define G_RM_TEX_EDGE2 0x03027008
#define G_RM_PCL_SURF 0x0C084203
#define G_RM_PCL_SURF2 0x03024203
#define G_RM_ADD 0x04484340
#define G_RM_ADD2 0x01124340
#define G_RM_NOOP 0x00000000
#define G_RM_NOOP2 0x00000000
#define G_RM_VISCVG 0x0C844040
#define G_RM_VISCVG2 0x03214040
#define G_RM_OPA_CI 0x0C080000
#define G_RM_OPA_CI2 0x03020000
#define AA_EN 0x8
#define Z_CMP 0x10
#define Z_UPD 0x20
#define IM_RD 0x40
#define CLR_ON_CVG 0x80
#define CVG_DST_CLAMP 0
#define CVG_DST_WRAP 0x100
#define CVG_DST_FULL 0x200
#define CVG_DST_SAVE 0x300
#define ZMODE_OPA 0
#define ZMODE_INTER 0x400
#define ZMODE_XLU 0x800
#define ZMODE_DEC 0xc00
#define CVG_X_ALPHA 0x1000
#define ALPHA_CVG_SEL 0x2000
#define FORCE_BL 0x4000
#define TEX_EDGE 0x0000
class ZDisplayList : public ZResource class ZDisplayList : public ZResource
{ {

View File

@ -41,6 +41,7 @@ ZFile::ZFile()
baseAddress = 0; baseAddress = 0;
rangeStart = 0x000000000; rangeStart = 0x000000000;
rangeEnd = 0xFFFFFFFF; rangeEnd = 0xFFFFFFFF;
workerID = 0;
} }
ZFile::ZFile(const fs::path& nOutPath, const std::string& nName) : ZFile() ZFile::ZFile(const fs::path& nOutPath, const std::string& nName) : ZFile()
@ -51,7 +52,7 @@ ZFile::ZFile(const fs::path& nOutPath, const std::string& nName) : ZFile()
} }
ZFile::ZFile(ZFileMode nMode, tinyxml2::XMLElement* reader, const fs::path& nBasePath, ZFile::ZFile(ZFileMode nMode, tinyxml2::XMLElement* reader, const fs::path& nBasePath,
const fs::path& nOutPath, const std::string& filename, const fs::path& nXmlFilePath) const fs::path& nOutPath, const std::string& filename, const fs::path& nXmlFilePath, int nWorkerID)
: ZFile() : ZFile()
{ {
xmlFilePath = nXmlFilePath; xmlFilePath = nXmlFilePath;
@ -66,6 +67,7 @@ ZFile::ZFile(ZFileMode nMode, tinyxml2::XMLElement* reader, const fs::path& nBas
outputPath = nOutPath; outputPath = nOutPath;
mode = nMode; mode = nMode;
workerID = nWorkerID;
ParseXML(reader, filename); ParseXML(reader, filename);
if (mode != ZFileMode::ExternalFile) if (mode != ZFileMode::ExternalFile)
@ -167,7 +169,7 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
} }
} }
} }
Globals::Instance->AddSegment(segment, this); Globals::Instance->AddSegment(segment, this, workerID);
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO) if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
{ {
@ -181,16 +183,22 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
} }
} }
if (mode == ZFileMode::Extract || mode == ZFileMode::ExternalFile) if (mode == ZFileMode::Extract || mode == ZFileMode::ExternalFile || mode == ZFileMode::ExtractDirectory)
{ {
if (!File::Exists((basePath / name).string())) if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory)
{ {
std::string errorHeader = StringHelper::Sprintf("binary file '%s' does not exist.", if (!File::Exists((basePath / name).string()))
(basePath / name).c_str()); {
HANDLE_ERROR_PROCESS(WarningType::Always, errorHeader, ""); std::string errorHeader = StringHelper::Sprintf("binary file '%s' does not exist.",
(basePath / name).c_str());
HANDLE_ERROR_PROCESS(WarningType::Always, errorHeader, "");
}
} }
rawData = File::ReadAllBytes((basePath / name).string()); if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
rawData = Globals::Instance->GetBaseromFile(name);
else
rawData = Globals::Instance->GetBaseromFile((basePath / name).string());
if (reader->Attribute("RangeEnd") == nullptr) if (reader->Attribute("RangeEnd") == nullptr)
rangeEnd = rawData.size(); rangeEnd = rawData.size();
@ -260,7 +268,7 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
{ {
ZResource* nRes = nodeMap[nodeName](this); ZResource* nRes = nodeMap[nodeName](this);
if (mode == ZFileMode::Extract || mode == ZFileMode::ExternalFile) if (mode == ZFileMode::Extract || mode == ZFileMode::ExternalFile || mode == ZFileMode::ExtractDirectory)
nRes->ExtractFromXML(child, rawDataIndex); nRes->ExtractFromXML(child, rawDataIndex);
switch (nRes->GetResourceType()) switch (nRes->GetResourceType())
@ -813,7 +821,34 @@ void ZFile::GenerateSourceHeaderFiles()
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO) if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_INFO)
printf("Writing H file: %s\n", headerFilename.c_str()); printf("Writing H file: %s\n", headerFilename.c_str());
File::WriteAllText(headerFilename, formatter.GetOutput()); if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory)
File::WriteAllText(headerFilename, formatter.GetOutput());
else if (Globals::Instance->sourceOutputPath != "")
{
std::string xmlPath = xmlFilePath.string();
xmlPath = StringHelper::Replace(xmlPath, "\\", "/");
auto pathList = StringHelper::Split(xmlPath, "/");
std::string outPath = "";
for (int i = 0; i < 3; i++)
outPath += pathList[i] + "/";
for (int i = 5; i < pathList.size(); i++)
{
if (i == pathList.size() - 1)
{
outPath += Path::GetFileNameWithoutExtension(pathList[i]) + "/";
outPath += outName.string() + ".h";
}
else
outPath += pathList[i];
if (i < pathList.size() - 1)
outPath += "/";
}
File::WriteAllText(outPath, formatter.GetOutput());
}
} }
std::string ZFile::GetHeaderInclude() const std::string ZFile::GetHeaderInclude() const
@ -999,6 +1034,10 @@ std::string ZFile::ProcessDeclarations()
lastItem.second->size += curItem.second->size; lastItem.second->size += curItem.second->size;
lastItem.second->arrayItemCnt += curItem.second->arrayItemCnt; lastItem.second->arrayItemCnt += curItem.second->arrayItemCnt;
lastItem.second->text += "\n" + curItem.second->text; lastItem.second->text += "\n" + curItem.second->text;
for (auto vtx : curItem.second->vertexHack)
lastItem.second->vertexHack.push_back(vtx);
declarations.erase(curItem.first); declarations.erase(curItem.first);
declarationKeys.erase(declarationKeys.begin() + i); declarationKeys.erase(declarationKeys.begin() + i);
delete curItem.second; delete curItem.second;
@ -1087,7 +1126,7 @@ void ZFile::ProcessDeclarationText(Declaration* decl)
{ {
std::string vtxName; std::string vtxName;
Globals::Instance->GetSegmentedArrayIndexedName(decl->references[refIndex], 0x10, this, Globals::Instance->GetSegmentedArrayIndexedName(decl->references[refIndex], 0x10, this,
"Vtx", vtxName); "Vtx", vtxName, workerID);
decl->text.replace(i, 2, vtxName); decl->text.replace(i, 2, vtxName);
refIndex++; refIndex++;
@ -1190,6 +1229,9 @@ void ZFile::HandleUnaccountedData()
uint32_t lastSize = 0; uint32_t lastSize = 0;
std::vector<offset_t> declsAddresses; std::vector<offset_t> declsAddresses;
if (Globals::Instance->otrMode)
return;
for (const auto& item : declarations) for (const auto& item : declarations)
{ {
declsAddresses.push_back(item.first); declsAddresses.push_back(item.first);

View File

@ -16,6 +16,7 @@ enum class ZFileMode
BuildBackground, BuildBackground,
Extract, Extract,
ExternalFile, ExternalFile,
ExtractDirectory,
Invalid, Invalid,
Custom = 1000, // Used for exporter file modes Custom = 1000, // Used for exporter file modes
}; };
@ -34,6 +35,8 @@ public:
std::string defines; std::string defines;
std::vector<ZResource*> resources; std::vector<ZResource*> resources;
int workerID;
// Default to using virtual addresses // Default to using virtual addresses
uint32_t segment = 0x80; uint32_t segment = 0x80;
uint32_t baseAddress, rangeStart, rangeEnd; uint32_t baseAddress, rangeStart, rangeEnd;
@ -41,7 +44,7 @@ public:
ZFile(const fs::path& nOutPath, const std::string& nName); ZFile(const fs::path& nOutPath, const std::string& nName);
ZFile(ZFileMode nMode, tinyxml2::XMLElement* reader, const fs::path& nBasePath, ZFile(ZFileMode nMode, tinyxml2::XMLElement* reader, const fs::path& nBasePath,
const fs::path& nOutPath, const std::string& filename, const fs::path& nXmlFilePath); const fs::path& nOutPath, const std::string& filename, const fs::path& nXmlFilePath, int nWorkerID);
~ZFile(); ~ZFile();
std::string GetName() const; std::string GetName() const;
@ -107,12 +110,12 @@ public:
static void RegisterNode(std::string nodeName, ZResourceFactoryFunc* nodeFunc); static void RegisterNode(std::string nodeName, ZResourceFactoryFunc* nodeFunc);
protected: protected:
std::vector<uint8_t> rawData;
std::string name; std::string name;
fs::path outName = ""; fs::path outName = "";
fs::path basePath; fs::path basePath;
fs::path outputPath; fs::path outputPath;
fs::path xmlFilePath; fs::path xmlFilePath;
std::vector<uint8_t> rawData;
// Keep track of every texture of this ZFile. // Keep track of every texture of this ZFile.
// The pointers declared here are "borrowed" (somebody else is the owner), // The pointers declared here are "borrowed" (somebody else is the owner),

View File

@ -218,18 +218,25 @@ size_t ZLimb::GetRawDataSize() const
std::string ZLimb::GetBodySourceCode() const std::string ZLimb::GetBodySourceCode() const
{ {
if (Globals::Instance->otrMode)
return "";
std::string dListStr; std::string dListStr;
std::string dListStr2; std::string dListStr2;
Globals::Instance->GetSegmentedArrayIndexedName(dListPtr, 8, parent, "Gfx", dListStr); Globals::Instance->GetSegmentedArrayIndexedName(dListPtr, 8, parent, "Gfx", dListStr,
Globals::Instance->GetSegmentedArrayIndexedName(dList2Ptr, 8, parent, "Gfx", dListStr2); parent->workerID);
Globals::Instance->GetSegmentedArrayIndexedName(dList2Ptr, 8, parent, "Gfx", dListStr2,
parent->workerID);
std::string entryStr = "\n\t"; std::string entryStr = "\n\t";
if (type == ZLimbType::Legacy) if (type == ZLimbType::Legacy)
{ {
std::string childName; std::string childName;
std::string siblingName; std::string siblingName;
Globals::Instance->GetSegmentedPtrName(childPtr, parent, "LegacyLimb", childName); Globals::Instance->GetSegmentedPtrName(childPtr, parent, "LegacyLimb", childName,
Globals::Instance->GetSegmentedPtrName(siblingPtr, parent, "LegacyLimb", siblingName); parent->workerID);
Globals::Instance->GetSegmentedPtrName(siblingPtr, parent, "LegacyLimb", siblingName,
parent->workerID);
entryStr += StringHelper::Sprintf("%s,\n", dListStr.c_str()); entryStr += StringHelper::Sprintf("%s,\n", dListStr.c_str());
entryStr += entryStr +=
@ -261,7 +268,8 @@ std::string ZLimb::GetBodySourceCode() const
case ZLimbType::Skin: case ZLimbType::Skin:
{ {
std::string skinSegmentStr; std::string skinSegmentStr;
Globals::Instance->GetSegmentedPtrName(skinSegment, parent, "", skinSegmentStr); Globals::Instance->GetSegmentedPtrName(skinSegment, parent, "", skinSegmentStr,
parent->workerID);
entryStr += entryStr +=
StringHelper::Sprintf("\t0x%02X, %s\n", skinSegmentType, skinSegmentStr.c_str()); StringHelper::Sprintf("\t0x%02X, %s\n", skinSegmentType, skinSegmentStr.c_str());
} }
@ -367,7 +375,7 @@ void ZLimb::DeclareDList(segptr_t dListSegmentedPtr, const std::string& prefix,
std::string dlistName; std::string dlistName;
bool declFound = Globals::Instance->GetSegmentedArrayIndexedName(dListSegmentedPtr, 8, parent, bool declFound = Globals::Instance->GetSegmentedArrayIndexedName(dListSegmentedPtr, 8, parent,
"Gfx", dlistName); "Gfx", dlistName, parent->workerID);
if (declFound) if (declFound)
return; return;

View File

@ -25,19 +25,19 @@ public:
ZLimbSkinType skinSegmentType = ZLimbSkinType::SkinType_0; // Skin only ZLimbSkinType skinSegmentType = ZLimbSkinType::SkinType_0; // Skin only
segptr_t skinSegment = 0; // Skin only segptr_t skinSegment = 0; // Skin only
Struct_800A5E28 segmentStruct; // Skin only Struct_800A5E28 segmentStruct = {0}; // Skin only
// Legacy only // Legacy only
float legTransX, legTransY, legTransZ; // Vec3f float legTransX = 0, legTransY = 0, legTransZ = 0; // Vec3f
uint16_t rotX, rotY, rotZ; // Vec3s uint16_t rotX = 0, rotY = 0, rotZ = 0; // Vec3s
segptr_t childPtr; // LegacyLimb* segptr_t childPtr = 0; // LegacyLimb*
segptr_t siblingPtr; // LegacyLimb* segptr_t siblingPtr = 0; // LegacyLimb*
segptr_t dListPtr = 0; segptr_t dListPtr = 0;
segptr_t dList2Ptr = 0; // LOD and Curve Only segptr_t dList2Ptr = 0; // LOD and Curve Only
int16_t transX, transY, transZ; int16_t transX = 0, transY = 0, transZ = 0;
uint8_t childIndex, siblingIndex; uint8_t childIndex = 0, siblingIndex = 0;
ZLimb(ZFile* nParent); ZLimb(ZFile* nParent);

View File

@ -142,8 +142,8 @@ void PathwayEntry::DeclareReferences(const std::string& prefix)
return; return;
std::string pointsName; std::string pointsName;
bool addressFound = bool addressFound = Globals::Instance->GetSegmentedPtrName(listSegmentAddress, parent, "Vec3s",
Globals::Instance->GetSegmentedPtrName(listSegmentAddress, parent, "Vec3s", pointsName); pointsName, parent->workerID);
if (addressFound) if (addressFound)
return; return;
@ -177,7 +177,8 @@ std::string PathwayEntry::GetBodySourceCode() const
{ {
std::string declaration; std::string declaration;
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(listSegmentAddress, parent, "Vec3s", listName); Globals::Instance->GetSegmentedPtrName(listSegmentAddress, parent, "Vec3s", listName,
parent->workerID);
if (Globals::Instance->game == ZGame::MM_RETAIL) if (Globals::Instance->game == ZGame::MM_RETAIL)
declaration += declaration +=

View File

@ -3,6 +3,7 @@
#include "Utils/BitConverter.h" #include "Utils/BitConverter.h"
#include "Utils/StringHelper.h" #include "Utils/StringHelper.h"
#include "ZFile.h" #include "ZFile.h"
#include <Globals.h>
REGISTER_ZFILENODE(PlayerAnimationData, ZPlayerAnimationData); REGISTER_ZFILENODE(PlayerAnimationData, ZPlayerAnimationData);
@ -54,6 +55,9 @@ std::string ZPlayerAnimationData::GetBodySourceCode() const
{ {
std::string declaration = ""; std::string declaration = "";
if (Globals::Instance->otrMode)
return "";
size_t index = 0; size_t index = 0;
for (const auto& entry : limbRotData) for (const auto& entry : limbRotData)
{ {

View File

@ -8,6 +8,7 @@
#include "ZFile.h" #include "ZFile.h"
#include <Globals.h> #include <Globals.h>
#include <ZDisplayList.h> #include <ZDisplayList.h>
#include <ZArray.h>
ZResource::ZResource(ZFile* nParent) ZResource::ZResource(ZFile* nParent)
{ {
@ -18,6 +19,7 @@ ZResource::ZResource(ZFile* nParent)
sourceOutput = ""; sourceOutput = "";
rawDataIndex = 0; rawDataIndex = 0;
outputDeclaration = true; outputDeclaration = true;
hash = 0;
RegisterRequiredAttribute("Name"); RegisterRequiredAttribute("Name");
RegisterOptionalAttribute("OutName"); RegisterOptionalAttribute("OutName");
@ -119,14 +121,21 @@ void ZResource::ParseXML(tinyxml2::XMLElement* reader)
name = registeredAttributes.at("Name").value; name = registeredAttributes.at("Name").value;
static std::regex r("[a-zA-Z_]+[a-zA-Z0-9_]*", std::regex::icase | std::regex::optimize);
if (!isInner || (isInner && name != "")) // Disable this check for OTR file generation for now since it takes up a considerable amount of CPU time
if (!Globals::Instance->otrMode)
{ {
if (!std::regex_match(name, r)) static std::regex r("[a-zA-Z_]+[a-zA-Z0-9_]*",
std::regex::icase | std::regex::optimize);
if (!isInner || (isInner && name != ""))
{ {
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this, if (!std::regex_match(name, r))
rawDataIndex, "invalid value found for 'Name' attribute", ""); {
HANDLE_ERROR_RESOURCE(WarningType::InvalidAttributeValue, parent, this,
rawDataIndex, "invalid value found for 'Name' attribute",
"");
}
} }
} }
@ -273,6 +282,21 @@ void ZResource::GetSourceOutputCode([[maybe_unused]] const std::string& prefix)
else else
decl->text = bodyStr; decl->text = bodyStr;
// OTRTODO: This is a hack and we need something more elegant in the future...
if (GetResourceType() == ZResourceType::Array)
{
ZArray* arr = (ZArray*)this;
if (arr->resList[0]->GetResourceType() == ZResourceType::Vertex)
{
for (int i = 0; i < arr->resList.size(); i++)
{
ZVtx* vtx = (ZVtx*)arr->resList[i];
decl->vertexHack.push_back(vtx);
}
}
}
if (decl != nullptr) if (decl != nullptr)
decl->staticConf = staticConf; decl->staticConf = staticConf;
} }

202
ZAPDTR/ZAPD/ZRom.cpp Normal file
View File

@ -0,0 +1,202 @@
#include "ZRom.h"
#include "Utils/BitConverter.h"
#include "Utils/File.h"
#include "Utils/Directory.h"
#include "yaz0/yaz0.h"
#ifndef _MSC_VER
#include <byteswap.h>
#endif
#include <Globals.h>
namespace fs = std::filesystem;
#define DMA_ENTRY_SIZE 16
#if defined(_MSC_VER)
#define __bswap_32 _byteswap_ulong
#define bswap_32 _byteswap_ulong
#endif
// ROM DMA Table Start
#define OOT_OFF_NTSC_10_RC 0x7430
#define OOT_OFF_NTSC_10 0x7430
#define OOT_OFF_NTSC_11 0x7430
#define OOT_OFF_PAL_10 0x7950
#define OOT_OFF_NTSC_12 0x7960
#define OOT_OFF_PAL_11 0x7950
#define OOT_OFF_JP_GC 0x7170
#define OOT_OFF_JP_MQ 0x7170
#define OOT_OFF_US_GC 0x7170
#define OOT_OFF_US_MQ 0x7170
#define OOT_OFF_PAL_GC_DBG1 0x12F70
#define OOT_OFF_PAL_MQ_DBG 0x12F70
#define OOT_OFF_PAL_GC_DBG2 0x12F70
#define OOT_OFF_PAL_GC 0x7170
#define OOT_OFF_PAL_MQ 0x7170
#define OOT_OFF_JP_GC_CE 007170
#define OOT_OFF_CN_IQUE 0xB7A0
#define OOT_OFF_TW_IQUE 0xB240
#define MM_OFF_US_10 0x1A500
#define MM_OFF_JP_10 0x1C110
#define MM_OFF_JP_11 0x1C050
#define MM_OFF_DBG 0x24F60
#define OOT_NTSC_10 0xEC7011B7
#define OOT_NTSC_11 0xD43DA81F
#define OOT_NTSC_12 0x693BA2AE
#define OOT_PAL_10 0xB044B569
#define OOT_PAL_11 0xB2055FBD
#define OOT_NTSC_JP_GC_CE 0xF7F52DB8
#define OOT_NTSC_JP_GC 0xF611F4BA
#define OOT_NTSC_US_GC 0xF3DD35BA
#define OOT_PAL_GC 0x09465AC3
#define OOT_NTSC_JP_MQ 0xF43B45BA
#define OOT_NTSC_US_MQ 0xF034001A
#define OOT_PAL_MQ 0x1D4136F3
#define OOT_PAL_GC_DBG1 0x871E1C92 // 03-21-2002 build
#define OOT_PAL_GC_DBG2 0x87121EFE // 03-13-2002 build
#define OOT_PAL_GC_MQ_DBG 0x917D18F6
#define OOT_IQUE_TW 0x3D81FB3E
#define OOT_IQUE_CN 0xB1E1E07B
#define OOT_UNKNOWN 0xFFFFFFFF
ZRom::ZRom(std::string romPath)
{
RomVersion version;
romData = File::ReadAllBytes(romPath);
version.crc = BitConverter::ToInt32BE(romData, 0x10);
switch (version.crc)
{
case OOT_NTSC_10:
version.version = "N64 NTSC 1.0";
version.listPath = "ntsc_oot.txt";
version.offset = OOT_OFF_NTSC_10;
break;
case OOT_NTSC_11:
version.version = "N64 NTSC 1.1";
version.listPath = "ntsc_oot.txt";
version.offset = OOT_OFF_NTSC_11;
break;
case OOT_NTSC_12:
version.version = "N64 NTSC 1.2";
version.listPath = "ntsc_oot.txt";
version.offset = OOT_OFF_NTSC_12;
break;
case OOT_PAL_10:
version.version = "N64 PAL 1.0";
version.listPath = "pal_oot.txt";
version.offset = OOT_OFF_PAL_10;
break;
case OOT_PAL_11:
version.version = "N64 PAL 1.1";
version.listPath = "pal_oot.txt";
version.offset = OOT_OFF_PAL_11;
break;
case OOT_NTSC_JP_GC:
version.version = "JP GameCube (MQ Disk)";
version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_GC;
break;
case OOT_NTSC_JP_GC_CE:
version.version = "GameCube (Collectors Edition Disk)";
version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_GC_CE;
break;
case OOT_NTSC_JP_MQ:
version.version = "JP Master Quest";
version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_MQ;
break;
case OOT_NTSC_US_MQ:
version.version = "NTSC Master Quest";
version.listPath = "gamecube.txt";
version.offset = OOT_OFF_JP_MQ;
break;
case OOT_NTSC_US_GC:
version.version = "NTSC GameCube";
version.listPath = "gamecube.txt";
version.offset = OOT_OFF_US_MQ;
break;
case OOT_PAL_GC:
version.version = "PAL GameCube";
version.listPath = "gamecube_pal.txt";
version.offset = OOT_OFF_PAL_GC;
break;
case OOT_PAL_MQ:
version.version = "PAL Master Quest";
version.listPath = "gamecube_pal.txt";
version.offset = OOT_OFF_PAL_MQ;
break;
case OOT_PAL_GC_DBG1:
version.version = "GameCube Debug 1.0";
version.listPath = "dbg.txt";
version.offset = OOT_OFF_PAL_GC_DBG1;
break;
case OOT_PAL_GC_DBG2:
version.version = "GameCube Debug 2.0";
version.listPath = "dbg.txt";
version.offset = OOT_OFF_PAL_GC_DBG2;
break;
case OOT_PAL_GC_MQ_DBG:
version.version = "GameCube MQ-Debug";
version.listPath = "dbg.txt";
version.offset = OOT_OFF_PAL_MQ_DBG;
break;
case OOT_IQUE_CN:
version.version = "OoT IQue";
version.listPath = "ique.txt";
version.offset = OOT_OFF_CN_IQUE;
break;
case OOT_IQUE_TW:
version.version = "TW IQue";
version.listPath = "ique.txt";
version.offset = OOT_OFF_TW_IQUE;
break;
}
auto path = StringHelper::Sprintf("%s/%s", Globals::Instance->fileListPath.string().c_str(), version.listPath.c_str());
auto txt = File::ReadAllText(path);
std::vector<std::string> lines = StringHelper::Split(txt, "\n");
std::vector<uint8_t> decompressedData(1);
for (int i = 0; i < lines.size(); i++)
{
lines[i] = StringHelper::Strip(lines[i], "\r");
const int romOffset = version.offset + (DMA_ENTRY_SIZE * i);
const int virtStart = BitConverter::ToInt32BE(romData, romOffset + 0);
const int virtEnd = BitConverter::ToInt32BE(romData, romOffset + 4);
const int physStart = BitConverter::ToInt32BE(romData, romOffset + 8);
const int physEnd = BitConverter::ToInt32BE(romData, romOffset + 12);
const bool compressed = physEnd != 0;
int size = compressed ? physEnd - physStart : virtEnd - virtStart;
auto outData = std::vector<uint8_t>();
outData.resize(size);
memcpy(outData.data(), romData.data() + physStart, size);
if (compressed)
{
int decSize = virtEnd - virtStart;
decompressedData = std::vector<uint8_t>();
decompressedData.resize(decSize);
yaz0_decode(outData.data(), decompressedData.data(), decSize);
files[lines[i]] = decompressedData;
}
else
files[lines[i]] = outData;
}
int bp = 0;
}
std::vector<uint8_t> ZRom::GetFile(std::string fileName)
{
return files[fileName];
}

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

@ -0,0 +1,27 @@
#pragma once
#include <stdint.h>
#include <vector>
#include <map>
#include <string>
class ZRom
{
public:
ZRom(std::string romPath);
std::vector<uint8_t> GetFile(std::string fileName);
protected:
std::vector<uint8_t> romData;
std::map<std::string, std::vector<uint8_t>> files;
};
struct RomVersion
{
std::string version = "None";
std::string error = "None";
std::string listPath = "None";
int offset;
uint32_t crc;
};

View File

@ -54,7 +54,8 @@ void SetActorCutsceneList::DeclareReferences(const std::string& prefix)
std::string SetActorCutsceneList::GetBodySourceCode() const std::string SetActorCutsceneList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "ActorCutscene", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "ActorCutscene", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_ACTOR_CUTSCENE_LIST(%i, %s)", cutscenes.size(), return StringHelper::Sprintf("SCENE_CMD_ACTOR_CUTSCENE_LIST(%i, %s)", cutscenes.size(),
listName.c_str()); listName.c_str());
} }

View File

@ -81,7 +81,8 @@ void SetActorList::DeclareReferencesLate(const std::string& prefix)
std::string SetActorList::GetBodySourceCode() const std::string SetActorList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "ActorEntry", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "ActorEntry", listName,
parent->workerID);
if (numActors != actors.size()) if (numActors != actors.size())
{ {
printf("%s: numActors(%i) ~ actors(%li)\n", parent->GetName().c_str(), numActors, printf("%s: numActors(%i) ~ actors(%li)\n", parent->GetName().c_str(), numActors,

View File

@ -48,7 +48,8 @@ void SetAlternateHeaders::DeclareReferencesLate(const std::string& prefix)
for (size_t i = 0; i < headers.size(); i++) for (size_t i = 0; i < headers.size(); i++)
{ {
std::string altHeaderName; std::string altHeaderName;
Globals::Instance->GetSegmentedPtrName(headers.at(i), parent, "", altHeaderName); Globals::Instance->GetSegmentedPtrName(headers.at(i), parent, "", altHeaderName,
parent->workerID);
declaration += StringHelper::Sprintf("\t%s,", altHeaderName.c_str()); declaration += StringHelper::Sprintf("\t%s,", altHeaderName.c_str());
@ -66,7 +67,8 @@ void SetAlternateHeaders::DeclareReferencesLate(const std::string& prefix)
std::string SetAlternateHeaders::GetBodySourceCode() const std::string SetAlternateHeaders::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "SceneCmd*", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "SceneCmd*", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_ALTERNATE_HEADER_LIST(%s)", listName.c_str()); return StringHelper::Sprintf("SCENE_CMD_ALTERNATE_HEADER_LIST(%s)", listName.c_str());
} }

View File

@ -33,7 +33,8 @@ void SetAnimatedMaterialList::DeclareReferences(const std::string& prefix)
std::string SetAnimatedMaterialList::GetBodySourceCode() const std::string SetAnimatedMaterialList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "AnimatedMaterial", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "AnimatedMaterial", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_ANIMATED_MATERIAL_LIST(%s)", listName.c_str()); return StringHelper::Sprintf("SCENE_CMD_ANIMATED_MATERIAL_LIST(%s)", listName.c_str());
} }

View File

@ -29,7 +29,8 @@ void SetCollisionHeader::DeclareReferences(const std::string& prefix)
std::string SetCollisionHeader::GetBodySourceCode() const std::string SetCollisionHeader::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "CollisionHeader", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "CollisionHeader", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_COL_HEADER(%s)", listName.c_str()); return StringHelper::Sprintf("SCENE_CMD_COL_HEADER(%s)", listName.c_str());
} }

View File

@ -71,7 +71,7 @@ void SetCsCamera::DeclareReferences(const std::string& prefix)
{ {
std::string camPointsName; std::string camPointsName;
Globals::Instance->GetSegmentedPtrName(cameras.at(0).GetCamAddress(), parent, "Vec3s", Globals::Instance->GetSegmentedPtrName(cameras.at(0).GetCamAddress(), parent, "Vec3s",
camPointsName); camPointsName, parent->workerID);
std::string declaration; std::string declaration;
size_t index = 0; size_t index = 0;
@ -103,7 +103,8 @@ void SetCsCamera::DeclareReferences(const std::string& prefix)
std::string SetCsCamera::GetBodySourceCode() const std::string SetCsCamera::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "CsCameraEntry", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "CsCameraEntry", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(%i, %s)", cameras.size(), return StringHelper::Sprintf("SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(%i, %s)", cameras.size(),
listName.c_str()); listName.c_str());
} }

View File

@ -86,7 +86,8 @@ void SetCutscenes::ParseRawData()
std::string SetCutscenes::GetBodySourceCode() const std::string SetCutscenes::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "CutsceneData", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "CutsceneData", listName,
parent->workerID);
if (Globals::Instance->game == ZGame::MM_RETAIL) if (Globals::Instance->game == ZGame::MM_RETAIL)
return StringHelper::Sprintf("SCENE_CMD_CUTSCENE_LIST(%i, %s)", numCutscenes, return StringHelper::Sprintf("SCENE_CMD_CUTSCENE_LIST(%i, %s)", numCutscenes,

View File

@ -63,7 +63,8 @@ void SetEntranceList::DeclareReferencesLate([[maybe_unused]] const std::string&
std::string SetEntranceList::GetBodySourceCode() const std::string SetEntranceList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "EntranceEntry", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "EntranceEntry", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_ENTRANCE_LIST(%s)", listName.c_str()); return StringHelper::Sprintf("SCENE_CMD_ENTRANCE_LIST(%s)", listName.c_str());
} }

View File

@ -58,7 +58,7 @@ void SetExitList::DeclareReferencesLate([[maybe_unused]] const std::string& pref
std::string SetExitList::GetBodySourceCode() const std::string SetExitList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "u16", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "u16", listName, parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_EXIT_LIST(%s)", listName.c_str()); return StringHelper::Sprintf("SCENE_CMD_EXIT_LIST(%s)", listName.c_str());
} }

View File

@ -52,7 +52,8 @@ void SetLightList::DeclareReferences(const std::string& prefix)
std::string SetLightList::GetBodySourceCode() const std::string SetLightList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "LightInfo", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "LightInfo", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_LIGHT_LIST(%i, %s)", numLights, listName.c_str()); return StringHelper::Sprintf("SCENE_CMD_LIGHT_LIST(%i, %s)", numLights, listName.c_str());
} }

View File

@ -44,7 +44,8 @@ void SetLightingSettings::DeclareReferences(const std::string& prefix)
std::string SetLightingSettings::GetBodySourceCode() const std::string SetLightingSettings::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "LightSettings", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "LightSettings", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_ENV_LIGHT_SETTINGS(%i, %s)", settings.size(), return StringHelper::Sprintf("SCENE_CMD_ENV_LIGHT_SETTINGS(%i, %s)", settings.size(),
listName.c_str()); listName.c_str());
} }

View File

@ -78,7 +78,7 @@ std::string SetMesh::GenDListExterns(ZDisplayList* dList)
std::string SetMesh::GetBodySourceCode() const std::string SetMesh::GetBodySourceCode() const
{ {
std::string list; std::string list;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "", list); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "", list, parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_MESH(%s)", list.c_str()); return StringHelper::Sprintf("SCENE_CMD_MESH(%s)", list.c_str());
} }
@ -129,8 +129,8 @@ std::string PolygonDlist::GetBodySourceCode() const
std::string bodyStr; std::string bodyStr;
std::string opaStr; std::string opaStr;
std::string xluStr; std::string xluStr;
Globals::Instance->GetSegmentedPtrName(opa, parent, "Gfx", opaStr); Globals::Instance->GetSegmentedPtrName(opa, parent, "Gfx", opaStr, parent->workerID);
Globals::Instance->GetSegmentedPtrName(xlu, parent, "Gfx", xluStr); Globals::Instance->GetSegmentedPtrName(xlu, parent, "Gfx", xluStr, parent->workerID);
if (polyType == 2) if (polyType == 2)
{ {
@ -294,7 +294,7 @@ std::string BgImage::GetBodySourceCode() const
} }
std::string backgroundName; std::string backgroundName;
Globals::Instance->GetSegmentedPtrName(source, parent, "", backgroundName); Globals::Instance->GetSegmentedPtrName(source, parent, "", backgroundName, parent->workerID);
bodyStr += StringHelper::Sprintf("%s, ", backgroundName.c_str()); bodyStr += StringHelper::Sprintf("%s, ", backgroundName.c_str());
bodyStr += "\n "; bodyStr += "\n ";
if (!isSubStruct) if (!isSubStruct)
@ -493,7 +493,7 @@ std::string PolygonType1::GetBodySourceCode() const
bodyStr += StringHelper::Sprintf("%i, %i, ", type, format); bodyStr += StringHelper::Sprintf("%i, %i, ", type, format);
std::string dlistStr; std::string dlistStr;
Globals::Instance->GetSegmentedPtrName(dlist, parent, "", dlistStr); Globals::Instance->GetSegmentedPtrName(dlist, parent, "", dlistStr, parent->workerID);
bodyStr += StringHelper::Sprintf("%s, ", dlistStr.c_str()); bodyStr += StringHelper::Sprintf("%s, ", dlistStr.c_str());
bodyStr += "}, \n"; bodyStr += "}, \n";
@ -505,7 +505,7 @@ std::string PolygonType1::GetBodySourceCode() const
bodyStr += single.GetBodySourceCode(); bodyStr += single.GetBodySourceCode();
break; break;
case 2: case 2:
Globals::Instance->GetSegmentedPtrName(list, parent, "BgImage", listStr); Globals::Instance->GetSegmentedPtrName(list, parent, "BgImage", listStr, parent->workerID);
bodyStr += StringHelper::Sprintf(" %i, %s, \n", count, listStr.c_str()); bodyStr += StringHelper::Sprintf(" %i, %s, \n", count, listStr.c_str());
break; break;
@ -592,7 +592,7 @@ void PolygonType2::DeclareReferences(const std::string& prefix)
std::string PolygonType2::GetBodySourceCode() const std::string PolygonType2::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(start, parent, "", listName); Globals::Instance->GetSegmentedPtrName(start, parent, "", listName, parent->workerID);
std::string body = StringHelper::Sprintf("\n %i, %i,\n", type, polyDLists.size()); std::string body = StringHelper::Sprintf("\n %i, %i,\n", type, polyDLists.size());
body += StringHelper::Sprintf(" %s,\n", listName.c_str()); body += StringHelper::Sprintf(" %s,\n", listName.c_str());

View File

@ -50,7 +50,8 @@ void SetMinimapChests::DeclareReferences(const std::string& prefix)
std::string SetMinimapChests::GetBodySourceCode() const std::string SetMinimapChests::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "MinimapChest", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "MinimapChest", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_MINIMAP_COMPASS_ICON_INFO(0x%02X, %s)", chests.size(), return StringHelper::Sprintf("SCENE_CMD_MINIMAP_COMPASS_ICON_INFO(0x%02X, %s)", chests.size(),
listName.c_str()); listName.c_str());
} }

View File

@ -52,7 +52,8 @@ void SetMinimapList::DeclareReferences(const std::string& prefix)
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(listSegmentAddr, parent, "MinimapEntry", listName); Globals::Instance->GetSegmentedPtrName(listSegmentAddr, parent, "MinimapEntry", listName,
parent->workerID);
std::string declaration = StringHelper::Sprintf("\n\t%s, 0x%08X\n", listName.c_str(), unk4); std::string declaration = StringHelper::Sprintf("\n\t%s, 0x%08X\n", listName.c_str(), unk4);
parent->AddDeclaration( parent->AddDeclaration(
@ -65,7 +66,8 @@ void SetMinimapList::DeclareReferences(const std::string& prefix)
std::string SetMinimapList::GetBodySourceCode() const std::string SetMinimapList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "MinimapList", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "MinimapList", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_MINIMAP_INFO(%s)", listName.c_str()); return StringHelper::Sprintf("SCENE_CMD_MINIMAP_INFO(%s)", listName.c_str());
} }

View File

@ -51,7 +51,7 @@ void SetObjectList::DeclareReferences(const std::string& prefix)
std::string SetObjectList::GetBodySourceCode() const std::string SetObjectList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "s16", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "s16", listName, parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_OBJECT_LIST(%i, %s)", objects.size(), listName.c_str()); return StringHelper::Sprintf("SCENE_CMD_OBJECT_LIST(%i, %s)", objects.size(), listName.c_str());
} }

View File

@ -50,7 +50,7 @@ void SetPathways::DeclareReferencesLate(const std::string& prefix)
std::string SetPathways::GetBodySourceCode() const std::string SetPathways::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "Path", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "Path", listName, parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_PATH_LIST(%s)", listName.c_str()); return StringHelper::Sprintf("SCENE_CMD_PATH_LIST(%s)", listName.c_str());
} }

View File

@ -34,7 +34,7 @@ void SetRoomList::DeclareReferences(const std::string& prefix)
std::string SetRoomList::GetBodySourceCode() const std::string SetRoomList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "RomFile", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "RomFile", listName, parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_ROOM_LIST(%i, %s)", romfile->rooms.size(), return StringHelper::Sprintf("SCENE_CMD_ROOM_LIST(%i, %s)", romfile->rooms.size(),
listName.c_str()); listName.c_str());
} }

View File

@ -51,7 +51,8 @@ void SetStartPositionList::DeclareReferences(const std::string& prefix)
std::string SetStartPositionList::GetBodySourceCode() const std::string SetStartPositionList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "ActorEntry", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "ActorEntry", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_SPAWN_LIST(%i, %s)", actors.size(), listName.c_str()); return StringHelper::Sprintf("SCENE_CMD_SPAWN_LIST(%i, %s)", actors.size(), listName.c_str());
} }

View File

@ -52,7 +52,8 @@ void SetTransitionActorList::DeclareReferences(const std::string& prefix)
std::string SetTransitionActorList::GetBodySourceCode() const std::string SetTransitionActorList::GetBodySourceCode() const
{ {
std::string listName; std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "TransitionActorEntry", listName); Globals::Instance->GetSegmentedPtrName(cmdArg2, parent, "TransitionActorEntry", listName,
parent->workerID);
return StringHelper::Sprintf("SCENE_CMD_TRANSITION_ACTOR_LIST(%i, %s)", transitionActors.size(), return StringHelper::Sprintf("SCENE_CMD_TRANSITION_ACTOR_LIST(%i, %s)", transitionActors.size(),
listName.c_str()); listName.c_str());
} }

View File

@ -89,7 +89,8 @@ void ZSkeleton::DeclareReferences(const std::string& prefix)
std::string ZSkeleton::GetBodySourceCode() const std::string ZSkeleton::GetBodySourceCode() const
{ {
std::string limbArrayName; std::string limbArrayName;
Globals::Instance->GetSegmentedPtrName(limbsArrayAddress, parent, "", limbArrayName); Globals::Instance->GetSegmentedPtrName(limbsArrayAddress, parent, "", limbArrayName,
parent->workerID);
switch (type) switch (type)
{ {
@ -245,7 +246,8 @@ std::string ZLimbTable::GetBodySourceCode() const
for (size_t i = 0; i < count; i++) for (size_t i = 0; i < count; i++)
{ {
std::string limbName; std::string limbName;
Globals::Instance->GetSegmentedPtrName(limbsAddresses[i], parent, "", limbName); Globals::Instance->GetSegmentedPtrName(limbsAddresses[i], parent, "", limbName,
parent->workerID);
body += StringHelper::Sprintf("\t%s,", limbName.c_str()); body += StringHelper::Sprintf("\t%s,", limbName.c_str());
if (i + 1 < count) if (i + 1 < count)

View File

@ -12,6 +12,7 @@ REGISTER_ZFILENODE(Text, ZText);
ZText::ZText(ZFile* nParent) : ZResource(nParent) ZText::ZText(ZFile* nParent) : ZResource(nParent)
{ {
RegisterRequiredAttribute("CodeOffset"); RegisterRequiredAttribute("CodeOffset");
RegisterOptionalAttribute("LangOffset", "0");
} }
void ZText::ParseRawData() void ZText::ParseRawData()
@ -20,12 +21,23 @@ void ZText::ParseRawData()
const auto& rawData = parent->GetRawData(); const auto& rawData = parent->GetRawData();
uint32_t currentPtr = StringHelper::StrToL(registeredAttributes.at("CodeOffset").value, 16); uint32_t currentPtr = StringHelper::StrToL(registeredAttributes.at("CodeOffset").value, 16);
uint32_t langPtr = currentPtr;
bool isPalLang = false;
std::vector<uint8_t> codeData = File::ReadAllBytes(Globals::Instance->baseRomPath.string() + "\\code"); if (StringHelper::StrToL(registeredAttributes.at("LangOffset").value, 16) != 0)
{
langPtr = StringHelper::StrToL(registeredAttributes.at("LangOffset").value, 16);
// In some cases with the multi-process extractor it seems that it fails to read the code file if something else is reading from it at the same time. if (langPtr != currentPtr)
while (codeData.size() == 0) isPalLang = true;
codeData = File::ReadAllBytes(Globals::Instance->baseRomPath.string() + "\\code"); }
std::vector<uint8_t> codeData;
if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
codeData = Globals::Instance->GetBaseromFile("code");
else
codeData = Globals::Instance->GetBaseromFile(Globals::Instance->baseRomPath.string() + "code");
while (true) while (true)
{ {
@ -33,8 +45,18 @@ void ZText::ParseRawData()
msgEntry.id = BitConverter::ToInt16BE(codeData, currentPtr + 0); msgEntry.id = BitConverter::ToInt16BE(codeData, currentPtr + 0);
msgEntry.textboxType = (codeData[currentPtr + 2] & 0xF0) >> 4; msgEntry.textboxType = (codeData[currentPtr + 2] & 0xF0) >> 4;
msgEntry.textboxYPos = (codeData[currentPtr + 2] & 0x0F); msgEntry.textboxYPos = (codeData[currentPtr + 2] & 0x0F);
msgEntry.segmentId = (codeData[currentPtr + 4]);
msgEntry.msgOffset = BitConverter::ToInt32BE(codeData, currentPtr + 4) & 0x00FFFFFF; if (isPalLang)
{
msgEntry.segmentId = (codeData[langPtr + 0]);
msgEntry.msgOffset = BitConverter::ToInt32BE(codeData, langPtr + 0) & 0x00FFFFFF;
}
else
{
msgEntry.segmentId = (codeData[langPtr + 4]);
msgEntry.msgOffset = BitConverter::ToInt32BE(codeData, langPtr + 4) & 0x00FFFFFF;
}
uint32_t msgPtr = msgEntry.msgOffset; uint32_t msgPtr = msgEntry.msgOffset;
unsigned char c = rawData[msgPtr]; unsigned char c = rawData[msgPtr];
@ -81,6 +103,11 @@ void ZText::ParseRawData()
break; break;
currentPtr += 8; currentPtr += 8;
if (isPalLang)
langPtr += 4;
else
langPtr += 8;
} }
int bp2 = 0; int bp2 = 0;

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