mirror of
https://github.com/zeldaret/oot.git
synced 2025-06-08 17:41:56 +00:00
Building on Macs (#1086)
* git subrepo pull (merge) tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "945e6ca1a" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "50242eca9" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * Fix extract_assets.py multithreading * Update binutils doc a bit * Remove * import, add multiprocessing option and way to pass arguments to ZAPD * Update format.sh to be more platform-independent * git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "fd5a7f434" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "fd5a7f434" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * Remove ; * Update formatting script to not just use 11 * Add Python requirements, move the Mac stuff in the README into its own doc * Fix readme link * Minor format thing * . * Move ZAPDArgs into its own function * Update readme and remove requirements.txt * Dragorn-inspired rewrite of processZAPDArgs * git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "a0d3f7b68" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "a0d3f7b68" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * Fix function definition * Building docs overhaul * Add Python packages to Mac and Cygwin * Heading number * format format.sh (!) * Replace "currently" * Remove Debian * git subrepo pull (merge) --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "0ba781304" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "0ba781304" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
parent
9450272503
commit
9b67778a00
41 changed files with 640 additions and 325 deletions
4
Makefile
4
Makefile
|
@ -34,6 +34,8 @@ else
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
N_THREADS ?= $(shell nproc)
|
||||||
|
|
||||||
#### Tools ####
|
#### Tools ####
|
||||||
ifeq ($(shell type mips-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0)
|
ifeq ($(shell type mips-linux-gnu-ld >/dev/null 2>/dev/null; echo $$?), 0)
|
||||||
MIPS_BINUTILS_PREFIX := mips-linux-gnu-
|
MIPS_BINUTILS_PREFIX := mips-linux-gnu-
|
||||||
|
@ -203,7 +205,7 @@ setup:
|
||||||
$(MAKE) -C tools
|
$(MAKE) -C tools
|
||||||
python3 fixbaserom.py
|
python3 fixbaserom.py
|
||||||
python3 extract_baserom.py
|
python3 extract_baserom.py
|
||||||
python3 extract_assets.py
|
python3 extract_assets.py -j$(N_THREADS)
|
||||||
|
|
||||||
resources: $(ASSET_FILES_OUT)
|
resources: $(ASSET_FILES_OUT)
|
||||||
test: $(ROM)
|
test: $(ROM)
|
||||||
|
|
100
README.md
100
README.md
|
@ -39,37 +39,24 @@ It builds the following ROM:
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
We recommend using WSL on Windows, or native Linux, which the rest of this readme describes. We currently have instructions for
|
||||||
|
|
||||||
|
* [Windows](#Windows), with and without WSL
|
||||||
|
* [macOS](docs/BUILDING_MACOS.md)
|
||||||
|
* [Linux](#Linux-Native-or-under-WSL--VM), natively or using WSL / VM
|
||||||
|
* [Docker](docs/BUILDING_DOCKER.md)
|
||||||
|
|
||||||
|
(These will also depend on the Linux instructions.)
|
||||||
|
Some of these may also be out of date or unmaintained; usually our contributors use WSL, Linux, and macOS, so these instructions should be up to date.
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
For Windows 10 or 11, install WSL and a distribution by following this
|
For Windows 10 or 11, install WSL and a distribution by following this
|
||||||
[WSL Installation Guide](https://docs.microsoft.com/en-us/windows/wsl/install).
|
[WSL Installation Guide](https://docs.microsoft.com/en-us/windows/wsl/install).
|
||||||
We recommend using Debian or Ubuntu 20.04 Linux distributions.
|
We recommend using Ubuntu 20.04 as the Linux distribution.
|
||||||
|
|
||||||
For older versions of Windows, install a Linux VM or refer to either [Cygwin](#Cygwin) or [Docker](#Docker) instructions.
|
For older versions of Windows, install a Linux VM or refer to either [Cygwin](docs/BUILDING_CYGWIN.md) or [Docker](docs/BUILDING_DOCKER.md) instructions.
|
||||||
|
|
||||||
### macOS
|
|
||||||
|
|
||||||
For macOS, use homebrew to install the following dependencies:
|
|
||||||
|
|
||||||
* coreutils
|
|
||||||
* make
|
|
||||||
* python3
|
|
||||||
* md5sha1sum
|
|
||||||
* libpng
|
|
||||||
|
|
||||||
You can install them with the following commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
brew update
|
|
||||||
brew install coreutils make python3 md5sha1sum libpng
|
|
||||||
```
|
|
||||||
|
|
||||||
You'll also need to [build and install mips-linux-binutils](docs/BUILDING_BINUTILS_MACOS.md).
|
|
||||||
|
|
||||||
Going forward in this guide, please use `gmake` whenever you encounter a `make` command.
|
|
||||||
The `make` that comes with macOS behaves differently than GNU make and is incompatible with this project.
|
|
||||||
|
|
||||||
You should now be able to continue from [step 2](#2-clone-the-repository) of the Linux instructions.
|
|
||||||
|
|
||||||
### Linux (Native or under WSL / VM)
|
### Linux (Native or under WSL / VM)
|
||||||
|
|
||||||
|
@ -90,6 +77,12 @@ sudo apt-get update
|
||||||
sudo apt-get install git build-essential binutils-mips-linux-gnu python3 libpng-dev
|
sudo apt-get install git build-essential binutils-mips-linux-gnu python3 libpng-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To install the Python dependencies simply run in a terminal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m pip install colorama
|
||||||
|
```
|
||||||
|
|
||||||
#### 2. Clone the repository
|
#### 2. Clone the repository
|
||||||
|
|
||||||
Clone `https://github.com/zeldaret/oot.git` where you wish to have the project, with a command such as:
|
Clone `https://github.com/zeldaret/oot.git` where you wish to have the project, with a command such as:
|
||||||
|
@ -98,6 +91,12 @@ Clone `https://github.com/zeldaret/oot.git` where you wish to have the project,
|
||||||
git clone https://github.com/zeldaret/oot.git
|
git clone https://github.com/zeldaret/oot.git
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This will copy the GitHub repository contents into a new folder in the current directory called `oot`. Change into this directory before doing anything else:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd oot
|
||||||
|
```
|
||||||
|
|
||||||
#### 3. Prepare a base ROM
|
#### 3. Prepare a base ROM
|
||||||
|
|
||||||
Copy over your copy of the Master Quest (Debug) ROM inside the root of this new project directory.
|
Copy over your copy of the Master Quest (Debug) ROM inside the root of this new project directory.
|
||||||
|
@ -145,57 +144,6 @@ This means that the built ROM isn't the same as the base one, so something went
|
||||||
|
|
||||||
Both of these have the disadvantage that the ordering of the terminal output is scrambled, so for debugging it is best to stick to one thread (i.e. not pass `-j` or `-jN`).
|
Both of these have the disadvantage that the ordering of the terminal output is scrambled, so for debugging it is best to stick to one thread (i.e. not pass `-j` or `-jN`).
|
||||||
|
|
||||||
### Cygwin
|
|
||||||
|
|
||||||
If you want to use Cygwin, you will need to:
|
|
||||||
|
|
||||||
* Download and install [Git Bash](https://git-scm.com/download/win).
|
|
||||||
* Download and install [Cygwin](https://cygwin.com).
|
|
||||||
* [Build and install mips-linux-binutils](docs/BUILDING_BINUTILS_CYGWIN.md).
|
|
||||||
|
|
||||||
Once mips-linux-binutils is installed you will need to install the following packages using Cygwin's installer:
|
|
||||||
|
|
||||||
* libiconv
|
|
||||||
* dos2unix
|
|
||||||
* python3
|
|
||||||
* libpng-devel
|
|
||||||
|
|
||||||
Then you can continue from step [step 2](#2-clone-the-repository) of the Linux instructions.
|
|
||||||
|
|
||||||
Note that, before building anything, you will need to run the following commands to fix line endings:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
dos2unix fixle.sh
|
|
||||||
./fixle.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
### Docker
|
|
||||||
|
|
||||||
#### 1. Setup requirements
|
|
||||||
|
|
||||||
To use Docker, you'll need either Docker Desktop or Docker Toolbox installed and setup based on your system.
|
|
||||||
|
|
||||||
You'll also need to prepare a local version of the project with a copied base ROM (see steps [2](#2-clone-the-repository) and [3](#3-prepare-a-base-rom) of the Linux instructions).
|
|
||||||
|
|
||||||
#### 2. Create the Docker image
|
|
||||||
|
|
||||||
From inside your local project, run the following command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker build . -t oot
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 3. Start the container
|
|
||||||
|
|
||||||
To start the container, you can mount your local filesystem into the Docker container and run an interactive bash session.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker run -it --rm --mount type=bind,source="$(pwd)",destination=/oot oot /bin/bash
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4. Setup and Build the ROM
|
|
||||||
|
|
||||||
Once inside the container, you can follow steps [4](#4-setup-the-rom-and-build-process) and [5](#5-build-the-rom) of the Linux instructions to setup and build the ROM, or run any other command you need.
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
# Building mips-linux-binutils on MacOS
|
|
||||||
|
|
||||||
The following instructions are written for MacOS users but should apply to any unix-like system, with maybe some modifications at the end regarding the bash_profile.
|
|
||||||
|
|
||||||
Create destination dir for binutils
|
|
||||||
```bash
|
|
||||||
sudo mkdir -p /opt/cross
|
|
||||||
```
|
|
||||||
|
|
||||||
Create and enter local working dir
|
|
||||||
```bash
|
|
||||||
mkdir ~/binutils-tmp
|
|
||||||
cd ~/binutils-tmp
|
|
||||||
```
|
|
||||||
|
|
||||||
Get and extract binutils source
|
|
||||||
```bash
|
|
||||||
wget https://ftp.gnu.org/gnu/binutils/binutils-2.35.tar.bz2
|
|
||||||
tar xjf binutils-2.35.tar.bz2
|
|
||||||
```
|
|
||||||
|
|
||||||
Create and enter build dir
|
|
||||||
```bash
|
|
||||||
mkdir build-binutils
|
|
||||||
cd build-binutils
|
|
||||||
```
|
|
||||||
|
|
||||||
Configure the build
|
|
||||||
```bash
|
|
||||||
../binutils-2.35/configure --target=mips-linux-gnu --prefix=/opt/cross --disable-gprof --disable-gdb --disable-werror
|
|
||||||
```
|
|
||||||
|
|
||||||
Make and install binutils
|
|
||||||
```bash
|
|
||||||
make -j
|
|
||||||
sudo make install
|
|
||||||
```
|
|
||||||
|
|
||||||
Edit your ~/.bash_profile to add the new binutils binaries to the system PATH
|
|
||||||
```bash
|
|
||||||
echo "export PATH=$PATH:/opt/cross/bin" >> ~/.bash_profile
|
|
||||||
```
|
|
||||||
|
|
||||||
Reload ~/.bash_profile (or just launch a new terminal tab)
|
|
||||||
```bash
|
|
||||||
source ~/.bash_profile
|
|
||||||
```
|
|
|
@ -1,4 +1,17 @@
|
||||||
# Building mips-linux-binutils on Windows using Cygwin
|
# Building with Cygwin
|
||||||
|
|
||||||
|
**N.B.** These have not been tested recently, you may find the requirements have changed a bit.
|
||||||
|
|
||||||
|
If you want to use Cygwin, you will need to:
|
||||||
|
|
||||||
|
|
||||||
|
## 1. Install Git Bash and Cygwin
|
||||||
|
|
||||||
|
* Download and install [Git Bash](https://git-scm.com/download/win).
|
||||||
|
* Download and install [Cygwin](https://cygwin.com).
|
||||||
|
|
||||||
|
|
||||||
|
## 2. Build mips-linux-binutils on Windows using Cygwin
|
||||||
|
|
||||||
First, you will need to install the following packages using the Cygwin installer:
|
First, you will need to install the following packages using the Cygwin installer:
|
||||||
- make
|
- make
|
||||||
|
@ -40,3 +53,34 @@ Add the new binutils binaries to your system PATH:
|
||||||
You can do that by adding `PATH=$PATH:/opt/cross/bin` to `~/.bashrc` and then reloading `~/.bashrc`.
|
You can do that by adding `PATH=$PATH:/opt/cross/bin` to `~/.bashrc` and then reloading `~/.bashrc`.
|
||||||
|
|
||||||
Alternatively you can edit the `Path` variable in `Edit the system environment variables`>`Environment Variables` (in which case you will need to relaunch your terminal).
|
Alternatively you can edit the `Path` variable in `Edit the system environment variables`>`Environment Variables` (in which case you will need to relaunch your terminal).
|
||||||
|
|
||||||
|
|
||||||
|
## 3. Install required Cygwin packages
|
||||||
|
|
||||||
|
Once mips-linux-binutils is installed you will need to install the following packages using Cygwin's installer:
|
||||||
|
|
||||||
|
* libiconv
|
||||||
|
* dos2unix
|
||||||
|
* python3
|
||||||
|
* libpng-devel
|
||||||
|
|
||||||
|
|
||||||
|
## 4. Install required Python packages
|
||||||
|
|
||||||
|
To install the Python dependencies simply run in a terminal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m pip install colorama
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 5. Continue with Linux instructions
|
||||||
|
|
||||||
|
You should be able to continue from step [step 2](../README.md#2-clone-the-repository) of the Linux instructions.
|
||||||
|
|
||||||
|
**N.B.** Before building anything, you will need to run the following commands to fix line endings:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dos2unix fixle.sh
|
||||||
|
./fixle.sh
|
||||||
|
```
|
27
docs/BUILDING_DOCKER.md
Normal file
27
docs/BUILDING_DOCKER.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# Building using Docker
|
||||||
|
|
||||||
|
## 1. Setup requirements
|
||||||
|
|
||||||
|
To use Docker, you'll need either Docker Desktop or Docker Toolbox installed and setup based on your system.
|
||||||
|
|
||||||
|
You'll also need to prepare a local version of the project with a copied base ROM (see steps [2](../README.md#2-clone-the-repository) and [3](../README.md#3-prepare-a-base-rom) of the Linux instructions).
|
||||||
|
|
||||||
|
## 2. Create the Docker image
|
||||||
|
|
||||||
|
From inside your local project, run the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build . -t oot
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Start the container
|
||||||
|
|
||||||
|
To start the container, you can mount your local filesystem into the Docker container and run an interactive bash session.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -it --rm --mount type=bind,source="$(pwd)",destination=/oot oot /bin/bash
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. Setup and Build the ROM
|
||||||
|
|
||||||
|
Once inside the container, you can follow steps [4](../README.md#4-setup-the-rom-and-build-process) and [5](../README.md#5-build-the-rom) of the Linux instructions to setup and build the ROM, or run any other command you need.
|
89
docs/BUILDING_MACOS.md
Normal file
89
docs/BUILDING_MACOS.md
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
# Building on macOS
|
||||||
|
|
||||||
|
**N.B.** C++17 is required to build the asset processing program that we use (ZAPD), so check your OS version can support this before proceeding.
|
||||||
|
|
||||||
|
|
||||||
|
## 1. Dependencies
|
||||||
|
|
||||||
|
For macOS, use Homebrew to install the following dependencies:
|
||||||
|
|
||||||
|
* coreutils
|
||||||
|
* make
|
||||||
|
* python3
|
||||||
|
* libpng
|
||||||
|
* bash
|
||||||
|
* clang-format
|
||||||
|
|
||||||
|
You can install them with the following commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew update
|
||||||
|
brew install coreutils make python3 libpng bash clang-format
|
||||||
|
```
|
||||||
|
|
||||||
|
(The repository expects Homebrew-installed programs to be either linked correctly in `$PATH` etc. or in their default locations.)
|
||||||
|
|
||||||
|
To install the Python dependencies simply run in a terminal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m pip install colorama
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 2. Building mips-linux-binutils
|
||||||
|
|
||||||
|
The following instructions are written for MacOS users but should apply to any Unix-like system, with maybe some modifications at the end regarding the bash_profile.
|
||||||
|
|
||||||
|
Create destination dir for binutils
|
||||||
|
```bash
|
||||||
|
sudo mkdir -p /opt/cross
|
||||||
|
```
|
||||||
|
|
||||||
|
Create and enter local working dir
|
||||||
|
```bash
|
||||||
|
mkdir ~/binutils-tmp
|
||||||
|
cd ~/binutils-tmp
|
||||||
|
```
|
||||||
|
|
||||||
|
Get and extract binutils source
|
||||||
|
```bash
|
||||||
|
wget https://ftp.gnu.org/gnu/binutils/binutils-2.35.tar.bz2
|
||||||
|
tar xjf binutils-2.35.tar.bz2
|
||||||
|
```
|
||||||
|
(You may find this command does not work: if so, just access the URL in a browser and save it to `~/binutils-tmp`.)
|
||||||
|
|
||||||
|
Create and enter a build directory
|
||||||
|
```bash
|
||||||
|
mkdir build-binutils
|
||||||
|
cd build-binutils
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure the build
|
||||||
|
```bash
|
||||||
|
../binutils-2.35/configure --target=mips-linux-gnu --prefix=/opt/cross --disable-gprof --disable-gdb --disable-werror
|
||||||
|
```
|
||||||
|
|
||||||
|
Make and install binutils
|
||||||
|
```bash
|
||||||
|
make -j
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
Edit your `~/.bash_profile`/`~/.zsh_profile` (or whichever shell you use) to add the new binutils binaries to the system PATH
|
||||||
|
```bash
|
||||||
|
echo "export PATH=$PATH:/opt/cross/bin" >> ~/.bash_profile
|
||||||
|
```
|
||||||
|
|
||||||
|
Reload `~/.bash_profile` (or just launch a new terminal tab)
|
||||||
|
```bash
|
||||||
|
source ~/.bash_profile
|
||||||
|
```
|
||||||
|
|
||||||
|
If this worked, you can now delete the temporary directory `~/binutils-tmp`.
|
||||||
|
|
||||||
|
|
||||||
|
## 3. Final note
|
||||||
|
|
||||||
|
Apple's version of `make` is very out-of-date, so you should use the brew-installed `gmake` in place of `make` in this repo from now on.
|
||||||
|
|
||||||
|
You should now be able to continue from [step 2](../README.md#2-clone-the-repository) of the Linux instructions.
|
|
@ -1,7 +1,8 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import argparse, json, os, signal, time
|
import argparse, json, os, signal, time, colorama, multiprocessing
|
||||||
from multiprocessing import Pool, cpu_count, Event, Manager, ProcessError
|
|
||||||
|
colorama.init()
|
||||||
|
|
||||||
EXTRACTED_ASSETS_NAMEFILE = ".extracted-assets.json"
|
EXTRACTED_ASSETS_NAMEFILE = ".extracted-assets.json"
|
||||||
|
|
||||||
|
@ -16,13 +17,13 @@ def ExtractFile(xmlPath, outputPath, outputSourcePath):
|
||||||
# Don't extract if another file wasn't extracted properly.
|
# Don't extract if another file wasn't extracted properly.
|
||||||
return
|
return
|
||||||
|
|
||||||
execStr = "tools/ZAPD/ZAPD.out e -eh -i %s -b baserom/ -o %s -osf %s -gsf 1 -rconf tools/ZAPDConfigs/MqDbg/Config.xml" % (xmlPath, outputPath, outputSourcePath)
|
execStr = f"tools/ZAPD/ZAPD.out e -eh -i {xmlPath} -b baserom/ -o {outputPath} -osf {outputSourcePath} -gsf 1 -rconf tools/ZAPDConfigs/MqDbg/Config.xml {ZAPDArgs}"
|
||||||
|
|
||||||
if "overlays" in xmlPath:
|
if "overlays" in xmlPath:
|
||||||
execStr += " --static"
|
execStr += " --static"
|
||||||
|
|
||||||
if globalUnaccounted:
|
if globalUnaccounted:
|
||||||
execStr += " -wu"
|
execStr += " -Wunaccounted"
|
||||||
|
|
||||||
print(execStr)
|
print(execStr)
|
||||||
exitValue = os.system(execStr)
|
exitValue = os.system(execStr)
|
||||||
|
@ -67,16 +68,35 @@ def initializeWorker(abort, unaccounted: bool, extractedAssetsTracker: dict, man
|
||||||
globalExtractedAssetsTracker = extractedAssetsTracker
|
globalExtractedAssetsTracker = extractedAssetsTracker
|
||||||
globalManager = manager
|
globalManager = manager
|
||||||
|
|
||||||
|
def processZAPDArgs(argsZ):
|
||||||
|
badZAPDArg = False
|
||||||
|
for z in argsZ:
|
||||||
|
if z[0] == '-':
|
||||||
|
print(f"{colorama.Fore.LIGHTRED_EX}error{colorama.Fore.RESET}: argument \"{z}\" starts with \"-\", which is not supported.", file=os.sys.stderr)
|
||||||
|
badZAPDArg = True
|
||||||
|
|
||||||
|
if badZAPDArg:
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
ZAPDArgs = " ".join(f"-{z}" for z in argsZ)
|
||||||
|
print("Using extra ZAPD arguments: " + ZAPDArgs)
|
||||||
|
return ZAPDArgs
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="baserom asset extractor")
|
parser = argparse.ArgumentParser(description="baserom asset extractor")
|
||||||
parser.add_argument("-s", "--single", help="asset path relative to assets/, e.g. objects/gameplay_keep")
|
parser.add_argument("-s", "--single", help="asset path relative to assets/, e.g. objects/gameplay_keep")
|
||||||
parser.add_argument("-f", "--force", help="Force the extraction of every xml instead of checking the touched ones.", action="store_true")
|
parser.add_argument("-f", "--force", help="Force the extraction of every xml instead of checking the touched ones.", action="store_true")
|
||||||
|
parser.add_argument("-j", "--jobs", help="Number of cpu cores to extract with.")
|
||||||
parser.add_argument("-u", "--unaccounted", help="Enables ZAPD unaccounted detector warning system.", action="store_true")
|
parser.add_argument("-u", "--unaccounted", help="Enables ZAPD unaccounted detector warning system.", action="store_true")
|
||||||
|
parser.add_argument("-Z", help="Pass the argument on to ZAPD, e.g. `-ZWunaccounted` to warn about unaccounted blocks in XMLs. Each argument should be passed separately, *without* the leading dash.", metavar="ZAPD_ARG", action="append")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
global ZAPDArgs
|
||||||
|
ZAPDArgs = processZAPDArgs(args.Z) if args.Z else ""
|
||||||
|
|
||||||
global mainAbort
|
global mainAbort
|
||||||
mainAbort = Event()
|
mainAbort = multiprocessing.Event()
|
||||||
manager = Manager()
|
manager = multiprocessing.Manager()
|
||||||
signal.signal(signal.SIGINT, SignalHandler)
|
signal.signal(signal.SIGINT, SignalHandler)
|
||||||
|
|
||||||
extractedAssetsTracker = manager.dict()
|
extractedAssetsTracker = manager.dict()
|
||||||
|
@ -88,7 +108,7 @@ def main():
|
||||||
if asset_path is not None:
|
if asset_path is not None:
|
||||||
fullPath = os.path.join("assets", "xml", asset_path + ".xml")
|
fullPath = os.path.join("assets", "xml", asset_path + ".xml")
|
||||||
if not os.path.exists(fullPath):
|
if not os.path.exists(fullPath):
|
||||||
print(f"Error. File {fullPath} doesn't exists.", file=os.sys.stderr)
|
print(f"Error. File {fullPath} does not exist.", file=os.sys.stderr)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
initializeWorker(mainAbort, args.unaccounted, extractedAssetsTracker, manager)
|
initializeWorker(mainAbort, args.unaccounted, extractedAssetsTracker, manager)
|
||||||
|
@ -117,11 +137,13 @@ def main():
|
||||||
xmlFiles.append(fullPath)
|
xmlFiles.append(fullPath)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
numCores = cpu_count()
|
numCores = int(args.jobs or 0)
|
||||||
print("Extracting assets with " + str(numCores) + " CPU cores.")
|
if numCores <= 0:
|
||||||
with Pool(numCores, initializer=initializeWorker, initargs=(mainAbort, args.unaccounted, extractedAssetsTracker, manager)) as p:
|
numCores = 1
|
||||||
|
print("Extracting assets with " + str(numCores) + " CPU core" + ("s" if numCores > 1 else "") + ".")
|
||||||
|
with multiprocessing.get_context("fork").Pool(numCores, initializer=initializeWorker, initargs=(mainAbort, args.unaccounted, extractedAssetsTracker, manager)) as p:
|
||||||
p.map(ExtractFunc, xmlFiles)
|
p.map(ExtractFunc, xmlFiles)
|
||||||
except (ProcessError, TypeError):
|
except (multiprocessing.ProcessError, TypeError):
|
||||||
print("Warning: Multiprocessing exception ocurred.", file=os.sys.stderr)
|
print("Warning: Multiprocessing exception ocurred.", file=os.sys.stderr)
|
||||||
print("Disabling mutliprocessing.", file=os.sys.stderr)
|
print("Disabling mutliprocessing.", file=os.sys.stderr)
|
||||||
|
|
||||||
|
|
38
format.sh
38
format.sh
|
@ -1,29 +1,57 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
FORMAT_VER="11"
|
||||||
FORMAT_OPTS="-i -style=file"
|
FORMAT_OPTS="-i -style=file"
|
||||||
TIDY_OPTS="-p . --fix --fix-errors"
|
TIDY_OPTS="-p . --fix --fix-errors"
|
||||||
COMPILER_OPTS="-fno-builtin -std=gnu90 -Iinclude -Isrc -D_LANGUAGE_C -DNON_MATCHING"
|
COMPILER_OPTS="-fno-builtin -std=gnu90 -Iinclude -Isrc -D_LANGUAGE_C -DNON_MATCHING"
|
||||||
|
|
||||||
|
# https://backreference.org/2010/05/23/sanitizing-files-with-no-trailing-newline/index.html
|
||||||
|
# "gets the last character of the file pipes it into read, which will exit with
|
||||||
|
# a nonzero exit code if it encounters EOF before newline (so, if the last
|
||||||
|
# character of the file isn't a newline). If read exits nonzero, then append a
|
||||||
|
# newline onto the file using echo (if read exits 0, that satisfies the ||, so
|
||||||
|
# the echo command isn't run)." (https://stackoverflow.com/a/34865616)
|
||||||
|
function add_final_newline () {
|
||||||
|
for file in "$@"
|
||||||
|
do
|
||||||
|
tail -c1 $file | read -r _ || echo >> $file
|
||||||
|
done
|
||||||
|
}
|
||||||
|
export -f add_final_newline
|
||||||
|
|
||||||
shopt -s globstar
|
shopt -s globstar
|
||||||
|
|
||||||
|
if [ $(command -v clang-format) ]
|
||||||
|
then
|
||||||
|
CLANG_FORMAT="clang-format"
|
||||||
|
else
|
||||||
|
if [ $(command -v clang-format-${FORMAT_VER}) ]
|
||||||
|
then
|
||||||
|
CLANG_FORMAT="clang-format-${FORMAT_VER}"
|
||||||
|
else
|
||||||
|
echo "Neither clang-format nor clang-format-${FORMAT_VER} found. Exiting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if (( $# > 0 )); then
|
if (( $# > 0 )); then
|
||||||
echo "Formatting file(s) $*"
|
echo "Formatting file(s) $*"
|
||||||
echo "Running clang-format..."
|
echo "Running clang-format..."
|
||||||
clang-format ${FORMAT_OPTS} "$@"
|
${CLANG_FORMAT} ${FORMAT_OPTS} "$@"
|
||||||
echo "Running clang-tidy..."
|
echo "Running clang-tidy..."
|
||||||
clang-tidy ${TIDY_OPTS} "$@" -- ${COMPILER_OPTS} &> /dev/null
|
clang-tidy ${TIDY_OPTS} "$@" -- ${COMPILER_OPTS} &> /dev/null
|
||||||
echo "Adding missing final new lines..."
|
echo "Adding missing final new lines..."
|
||||||
sed -i -e '$a\' "$@"
|
add_final_newline "$@"
|
||||||
echo "Done formatting file(s) $*"
|
echo "Done formatting file(s) $*"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Formatting C files. This will take a bit"
|
echo "Formatting C files. This will take a bit"
|
||||||
echo "Running clang-format..."
|
echo "Running clang-format..."
|
||||||
clang-format ${FORMAT_OPTS} src/**/*.c
|
${CLANG_FORMAT} ${FORMAT_OPTS} src/**/*.c
|
||||||
echo "Running clang-tidy..."
|
echo "Running clang-tidy..."
|
||||||
clang-tidy ${TIDY_OPTS} src/**/*.c -- ${COMPILER_OPTS} &> /dev/null
|
clang-tidy ${TIDY_OPTS} src/**/*.c -- ${COMPILER_OPTS} &> /dev/null
|
||||||
echo "Adding missing final new lines..."
|
echo "Adding missing final new lines..."
|
||||||
find src/ -type f -name "*.c" -exec sed -i -e '$a\' {} \;
|
find src/ -type f -name "*.c" -exec bash -c 'add_final_newline "$@"' bash {} +
|
||||||
find assets/xml/ -type f -name "*.xml" -exec sed -i -e '$a\' {} \;
|
find assets/xml/ -type f -name "*.xml" -exec bash -c 'add_final_newline "$@"' bash {} +
|
||||||
echo "Done formatting all files."
|
echo "Done formatting all files."
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
[subrepo]
|
[subrepo]
|
||||||
remote = https://github.com/zeldaret/ZAPD.git
|
remote = https://github.com/zeldaret/ZAPD.git
|
||||||
branch = master
|
branch = master
|
||||||
commit = a3363333d809e8089a55efc3ea32eaea9ddb8d8c
|
commit = 0ba78130478ee1272bc0e2f2fec2d162e7f7f995
|
||||||
parent = 1cf11907fa8d636babba2df854850035f04bd4fc
|
parent = 4afee2cfb8bc9cd5c7c217c38138174a9ce1fd99
|
||||||
method = merge
|
method = merge
|
||||||
cmdver = 0.4.3
|
cmdver = 0.4.3
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Only used for standalone compilation, usually inherits these from the main makefile
|
# Only used for standalone compilation, usually inherits these from the main makefile
|
||||||
CXXFLAGS ?= -Wall -Wextra -O2 -g -std=c++17
|
CXXFLAGS ?= -Wall -Wextra -O2 -g -std=c++17
|
||||||
|
|
||||||
SRC_DIRS := $(shell find -type d -not -path "*build*")
|
SRC_DIRS := $(shell find . -type d -not -path "*build*")
|
||||||
CPP_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
|
CPP_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
|
||||||
H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h))
|
H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h))
|
||||||
|
|
||||||
|
|
58
tools/ZAPD/Jenkinsfile
vendored
58
tools/ZAPD/Jenkinsfile
vendored
|
@ -7,7 +7,7 @@ pipeline {
|
||||||
// Non-parallel ZAPD stage
|
// Non-parallel ZAPD stage
|
||||||
stage('Build ZAPD') {
|
stage('Build ZAPD') {
|
||||||
steps {
|
steps {
|
||||||
sh 'make -j'
|
sh 'make -j WERROR=1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,13 +22,13 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// stage('Checkout mm') {
|
stage('Checkout mm') {
|
||||||
// steps{
|
steps{
|
||||||
// dir('mm') {
|
dir('mm') {
|
||||||
// git url: 'https://github.com/zeldaret/mm.git'
|
git url: 'https://github.com/zeldaret/mm.git'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,20 +51,20 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// stage('Setup MM') {
|
stage('Setup MM') {
|
||||||
// steps {
|
steps {
|
||||||
// dir('mm') {
|
dir('mm') {
|
||||||
// sh 'cp /usr/local/etc/roms/mm.us.rev1.z64 baserom.mm.us.rev1.z64'
|
sh 'cp /usr/local/etc/roms/mm.us.rev1.z64 baserom.mm.us.rev1.z64'
|
||||||
|
|
||||||
// // Identical to `make setup` except for copying our newer ZAPD.out into mm
|
// Identical to `make setup` except for copying our newer ZAPD.out into mm
|
||||||
// sh 'make -C tools'
|
sh 'make -C tools'
|
||||||
// sh 'cp ../ZAPD.out tools/ZAPD/'
|
sh 'cp ../ZAPD.out tools/ZAPD/'
|
||||||
// sh 'python3 tools/fixbaserom.py'
|
sh 'python3 tools/fixbaserom.py'
|
||||||
// sh 'python3 tools/extract_baserom.py'
|
sh 'python3 tools/extract_baserom.py'
|
||||||
// sh 'python3 extract_assets.py -t 4'
|
sh 'python3 extract_assets.py -j $(nproc)'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,14 +78,14 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// stage('Build mm') {
|
stage('Build mm') {
|
||||||
// steps {
|
steps {
|
||||||
// dir('mm') {
|
dir('mm') {
|
||||||
// sh 'make -j disasm'
|
sh 'make -j disasm'
|
||||||
// sh 'make -j all'
|
sh 'make -j all'
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ DEPRECATION_ON ?= 1
|
||||||
DEBUG ?= 0
|
DEBUG ?= 0
|
||||||
COPYCHECK_ARGS ?=
|
COPYCHECK_ARGS ?=
|
||||||
LLD ?= 0
|
LLD ?= 0
|
||||||
|
WERROR ?= 0
|
||||||
|
|
||||||
# Use clang++ if available, else use g++
|
# Use clang++ if available, else use g++
|
||||||
ifeq ($(shell command -v clang++ >/dev/null 2>&1; echo $$?),0)
|
ifeq ($(shell command -v clang++ >/dev/null 2>&1; echo $$?),0)
|
||||||
|
@ -23,14 +24,16 @@ ifneq ($(DEBUG),0)
|
||||||
CXXFLAGS += -g3 -DDEVELOPMENT -D_DEBUG
|
CXXFLAGS += -g3 -DDEVELOPMENT -D_DEBUG
|
||||||
COPYCHECK_ARGS += --devel
|
COPYCHECK_ARGS += --devel
|
||||||
DEPRECATION_ON = 0
|
DEPRECATION_ON = 0
|
||||||
else
|
endif
|
||||||
|
|
||||||
|
ifneq ($(WERROR),0)
|
||||||
CXXFLAGS += -Werror
|
CXXFLAGS += -Werror
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(OPTIMIZATION_ON),0)
|
ifeq ($(OPTIMIZATION_ON),0)
|
||||||
OPTFLAGS := -O0
|
OPTFLAGS := -O0
|
||||||
else
|
else
|
||||||
OPTFLAGS := -O2 -march=native -mtune=native
|
OPTFLAGS := -O2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(ASAN),0)
|
ifneq ($(ASAN),0)
|
||||||
|
@ -53,10 +56,23 @@ ifneq ($(LLD),0)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
UNAME := $(shell uname)
|
UNAME := $(shell uname)
|
||||||
|
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
|
||||||
|
else
|
||||||
|
EXPORTERS := -Wl,-force_load ExporterTest/ExporterTest.a
|
||||||
|
ifeq ($(UNAMEM),arm64)
|
||||||
|
ifeq ($(shell brew list libpng > /dev/null 2>&1; echo $$?),0)
|
||||||
|
LDFLAGS += -L $(shell brew --prefix)/lib
|
||||||
|
INC += -I $(shell brew --prefix)/include
|
||||||
|
else
|
||||||
|
$(error Please install libpng via Homebrew)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
ZAPD_SRC_DIRS := $(shell find ZAPD -type d)
|
ZAPD_SRC_DIRS := $(shell find ZAPD -type d)
|
||||||
SRC_DIRS = $(ZAPD_SRC_DIRS) lib/tinyxml2
|
SRC_DIRS = $(ZAPD_SRC_DIRS) lib/tinyxml2
|
||||||
|
|
||||||
|
@ -115,4 +131,4 @@ ZAPDUtils:
|
||||||
|
|
||||||
# Linking
|
# Linking
|
||||||
ZAPD.out: $(O_FILES) lib/libgfxd/libgfxd.a ExporterTest ZAPDUtils
|
ZAPD.out: $(O_FILES) lib/libgfxd/libgfxd.a ExporterTest ZAPDUtils
|
||||||
$(CXX) $(CXXFLAGS) $(O_FILES) lib/libgfxd/libgfxd.a ZAPDUtils/ZAPDUtils.a -Wl,--whole-archive ExporterTest/ExporterTest.a -Wl,--no-whole-archive $(LDFLAGS) $(OUTPUT_OPTION)
|
$(CXX) $(CXXFLAGS) $(O_FILES) lib/libgfxd/libgfxd.a ZAPDUtils/ZAPDUtils.a $(EXPORTERS) $(LDFLAGS) $(OUTPUT_OPTION)
|
||||||
|
|
|
@ -16,6 +16,14 @@ In a Debian/Ubuntu based environment, those could be installed with the followin
|
||||||
sudo apt install libpng-dev
|
sudo apt install libpng-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
On a Mac, you will need to install libpng with Homebrew or MacPorts; we currently only support Homebrew. You can run
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew install libpng
|
||||||
|
```
|
||||||
|
|
||||||
|
to install it via Homebrew.
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
#### Linux / *nix
|
#### Linux / *nix
|
||||||
|
@ -111,6 +119,7 @@ ZAPD also accepts the following list of extra parameters:
|
||||||
- `-tm MODE`: Test Mode (enables certain experimental features). To enable it, set `MODE` to `1`.
|
- `-tm MODE`: Test Mode (enables certain experimental features). To enable it, set `MODE` to `1`.
|
||||||
- `-se` / `--set-exporter` : Sets which exporter to use.
|
- `-se` / `--set-exporter` : Sets which exporter to use.
|
||||||
- `--gcc-compat` : Enables GCC compatibly mode. Slower.
|
- `--gcc-compat` : Enables GCC compatibly mode. Slower.
|
||||||
|
- `-us` / `--unaccounted-static` : Mark unaccounted data as `static`
|
||||||
- `-s` / `--static` : Mark every asset as `static`.
|
- `-s` / `--static` : Mark every asset as `static`.
|
||||||
- This behaviour can be overridden per asset using `Static=` in the respective XML node.
|
- This behaviour can be overridden per asset using `Static=` in the respective XML node.
|
||||||
- `-W...`: warning flags, see below
|
- `-W...`: warning flags, see below
|
||||||
|
|
|
@ -171,7 +171,7 @@ std::string Declaration::GetExternalDeclarationStr() const
|
||||||
|
|
||||||
std::string Declaration::GetExternStr() const
|
std::string Declaration::GetExternStr() const
|
||||||
{
|
{
|
||||||
if (IsStatic() || varType == "")
|
if (IsStatic() || varType == "" || isUnaccounted)
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,7 @@ typedef uint32_t offset_t;
|
||||||
enum class DeclarationAlignment
|
enum class DeclarationAlignment
|
||||||
{
|
{
|
||||||
Align4,
|
Align4,
|
||||||
Align8,
|
Align8
|
||||||
Align16
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class StaticConfig
|
enum class StaticConfig
|
||||||
|
|
|
@ -152,8 +152,8 @@ bool Globals::GetSegmentedPtrName(segptr_t segAddress, ZFile* currentFile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& symbolFromMap = Globals::Instance->symbolMap.find(segAddress);
|
const auto& symbolFromMap = Globals::Instance->cfg.symbolMap.find(segAddress);
|
||||||
if (symbolFromMap != Globals::Instance->symbolMap.end())
|
if (symbolFromMap != Globals::Instance->cfg.symbolMap.end())
|
||||||
{
|
{
|
||||||
declName = "&" + symbolFromMap->second;
|
declName = "&" + symbolFromMap->second;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -58,11 +58,11 @@ public:
|
||||||
bool verboseUnaccounted = false;
|
bool verboseUnaccounted = false;
|
||||||
bool gccCompat = false;
|
bool gccCompat = false;
|
||||||
bool forceStatic = false;
|
bool forceStatic = false;
|
||||||
|
bool forceUnaccountedStatic = false;
|
||||||
|
|
||||||
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<uint32_t, std::string> symbolMap;
|
|
||||||
|
|
||||||
std::string currentExporter;
|
std::string currentExporter;
|
||||||
static std::map<std::string, ExporterSet*>& GetExporterMap();
|
static std::map<std::string, ExporterSet*>& GetExporterMap();
|
||||||
|
|
|
@ -48,7 +48,7 @@ void ErrorHandler(int sig)
|
||||||
const char* crashEasterEgg[] = {
|
const char* crashEasterEgg[] = {
|
||||||
"\tYou've met with a terrible fate, haven't you?",
|
"\tYou've met with a terrible fate, haven't you?",
|
||||||
"\tSEA BEARS FOAM. SLEEP BEARS DREAMS. \n\tBOTH END IN THE SAME WAY: CRASSSH!",
|
"\tSEA BEARS FOAM. SLEEP BEARS DREAMS. \n\tBOTH END IN THE SAME WAY: CRASSSH!",
|
||||||
"ZAPD has fallen and cannot get up."
|
"\tZAPD has fallen and cannot get up.",
|
||||||
};
|
};
|
||||||
|
|
||||||
srand(time(nullptr));
|
srand(time(nullptr));
|
||||||
|
@ -216,6 +216,10 @@ int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
Globals::Instance->forceStatic = true;
|
Globals::Instance->forceStatic = true;
|
||||||
}
|
}
|
||||||
|
else if (arg == "-us" || arg == "--unaccounted-static")
|
||||||
|
{
|
||||||
|
Globals::Instance->forceUnaccountedStatic = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse File Mode
|
// Parse File Mode
|
||||||
|
@ -430,6 +434,10 @@ void BuildAssetTexture(const fs::path& pngFilePath, TextureType texType, const f
|
||||||
std::string name = outPath.stem().string();
|
std::string name = outPath.stem().string();
|
||||||
|
|
||||||
ZTexture tex(nullptr);
|
ZTexture tex(nullptr);
|
||||||
|
|
||||||
|
if (name.find("u32") != std::string::npos)
|
||||||
|
tex.dWordAligned = false;
|
||||||
|
|
||||||
tex.FromPNG(pngFilePath.string(), texType);
|
tex.FromPNG(pngFilePath.string(), texType);
|
||||||
std::string cfgPath = StringHelper::Split(pngFilePath.string(), ".")[0] + ".cfg";
|
std::string cfgPath = StringHelper::Split(pngFilePath.string(), ".")[0] + ".cfg";
|
||||||
|
|
||||||
|
|
|
@ -263,7 +263,7 @@ void Struct_800A5E28::DeclareReferences(const std::string& prefix)
|
||||||
|
|
||||||
ZResource::DeclareReferences(varPrefix);
|
ZResource::DeclareReferences(varPrefix);
|
||||||
|
|
||||||
if (unk_4 != 0 && GETSEGNUM(unk_4) == parent->segment)
|
if (unk_4 != SEGMENTED_NULL && GETSEGNUM(unk_4) == parent->segment)
|
||||||
{
|
{
|
||||||
const auto& res = unk_4_arr.at(0);
|
const auto& res = unk_4_arr.at(0);
|
||||||
std::string unk_4_Str = res.GetDefaultName(varPrefix);
|
std::string unk_4_Str = res.GetDefaultName(varPrefix);
|
||||||
|
@ -293,7 +293,7 @@ void Struct_800A5E28::DeclareReferences(const std::string& prefix)
|
||||||
decl->text = entryStr;
|
decl->text = entryStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unk_8 != 0 && GETSEGNUM(unk_8) == parent->segment)
|
if (unk_8 != SEGMENTED_NULL && GETSEGNUM(unk_8) == parent->segment)
|
||||||
{
|
{
|
||||||
uint32_t unk_8_Offset = Seg2Filespace(unk_8, parent->baseAddress);
|
uint32_t unk_8_Offset = Seg2Filespace(unk_8, parent->baseAddress);
|
||||||
|
|
||||||
|
@ -306,6 +306,8 @@ void Struct_800A5E28::DeclareReferences(const std::string& prefix)
|
||||||
std::string dListStr =
|
std::string dListStr =
|
||||||
StringHelper::Sprintf("%sSkinLimbDL_%06X", varPrefix.c_str(), unk_8_Offset);
|
StringHelper::Sprintf("%sSkinLimbDL_%06X", varPrefix.c_str(), unk_8_Offset);
|
||||||
unk_8_dlist->SetName(dListStr);
|
unk_8_dlist->SetName(dListStr);
|
||||||
|
unk_8_dlist->DeclareVar(varPrefix, "");
|
||||||
|
unk_8_dlist->DeclareReferences(varPrefix);
|
||||||
parent->AddResource(unk_8_dlist);
|
parent->AddResource(unk_8_dlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,8 @@ ZOverlay* ZOverlay::FromBuild(fs::path buildPath, fs::path cfgFolderPath)
|
||||||
std::vector<elfio*> readers;
|
std::vector<elfio*> readers;
|
||||||
for (size_t i = 1; i < cfgLines.size(); i++)
|
for (size_t i = 1; i < cfgLines.size(); i++)
|
||||||
{
|
{
|
||||||
std::string elfPath = (buildPath / (cfgLines[i].substr(0, cfgLines[i].size() - 2) + ".o")).string();
|
std::string elfPath =
|
||||||
|
(buildPath / (cfgLines[i].substr(0, cfgLines[i].size() - 2) + ".o")).string();
|
||||||
elfio* reader = new elfio();
|
elfio* reader = new elfio();
|
||||||
|
|
||||||
if (!reader->load(elfPath))
|
if (!reader->load(elfPath))
|
||||||
|
|
|
@ -104,7 +104,7 @@ void ZNormalAnimation::DeclareReferences(const std::string& prefix)
|
||||||
valuesStr += "\n ";
|
valuesStr += "\n ";
|
||||||
}
|
}
|
||||||
|
|
||||||
parent->AddDeclarationArray(rotationValuesOffset, DeclarationAlignment::Align16,
|
parent->AddDeclarationArray(rotationValuesOffset, DeclarationAlignment::Align4,
|
||||||
rotationValues.size() * 2, "s16",
|
rotationValues.size() * 2, "s16",
|
||||||
StringHelper::Sprintf("%sFrameData", defaultPrefix.c_str()),
|
StringHelper::Sprintf("%sFrameData", defaultPrefix.c_str()),
|
||||||
rotationValues.size(), valuesStr);
|
rotationValues.size(), valuesStr);
|
||||||
|
@ -118,7 +118,7 @@ void ZNormalAnimation::DeclareReferences(const std::string& prefix)
|
||||||
indicesStr += "\n";
|
indicesStr += "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
parent->AddDeclarationArray(rotationIndicesOffset, DeclarationAlignment::Align16,
|
parent->AddDeclarationArray(rotationIndicesOffset, DeclarationAlignment::Align4,
|
||||||
rotationIndices.size() * 6, "JointIndex",
|
rotationIndices.size() * 6, "JointIndex",
|
||||||
StringHelper::Sprintf("%sJointIndices", defaultPrefix.c_str()),
|
StringHelper::Sprintf("%sJointIndices", defaultPrefix.c_str()),
|
||||||
rotationIndices.size(), indicesStr);
|
rotationIndices.size(), indicesStr);
|
||||||
|
@ -385,7 +385,7 @@ size_t ZCurveAnimation::GetRawDataSize() const
|
||||||
|
|
||||||
DeclarationAlignment ZCurveAnimation::GetDeclarationAlignment() const
|
DeclarationAlignment ZCurveAnimation::GetDeclarationAlignment() const
|
||||||
{
|
{
|
||||||
return DeclarationAlignment::Align16;
|
return DeclarationAlignment::Align4;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ZCurveAnimation::GetSourceTypeName() const
|
std::string ZCurveAnimation::GetSourceTypeName() const
|
||||||
|
|
|
@ -101,11 +101,18 @@ std::string ZArray::GetBodySourceCode() const
|
||||||
const auto& res = resList[i];
|
const auto& res = resList[i];
|
||||||
output += "\t";
|
output += "\t";
|
||||||
|
|
||||||
if (res->GetResourceType() == ZResourceType::Scalar ||
|
switch (res->GetResourceType())
|
||||||
res->GetResourceType() == ZResourceType::Vertex)
|
{
|
||||||
|
case ZResourceType::Pointer:
|
||||||
|
case ZResourceType::Scalar:
|
||||||
|
case ZResourceType::Vertex:
|
||||||
output += resList.at(i)->GetBodySourceCode();
|
output += resList.at(i)->GetBodySourceCode();
|
||||||
else
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
output += StringHelper::Sprintf("{ %s }", resList.at(i)->GetBodySourceCode().c_str());
|
output += StringHelper::Sprintf("{ %s }", resList.at(i)->GetBodySourceCode().c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (i < arrayCnt - 1 || res->IsExternalResource())
|
if (i < arrayCnt - 1 || res->IsExternalResource())
|
||||||
output += ",\n";
|
output += ",\n";
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "ZCollision.h"
|
#include "ZCollision.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -76,9 +77,42 @@ void ZCollisionHeader::ParseRawData()
|
||||||
polygonTypes.push_back(
|
polygonTypes.push_back(
|
||||||
BitConverter::ToUInt64BE(rawData, polyTypeDefSegmentOffset + (i * 8)));
|
BitConverter::ToUInt64BE(rawData, polyTypeDefSegmentOffset + (i * 8)));
|
||||||
|
|
||||||
if (camDataAddress != 0)
|
if (camDataAddress != SEGMENTED_NULL)
|
||||||
camData = new CameraDataList(parent, name, rawData, camDataSegmentOffset,
|
{
|
||||||
polyTypeDefSegmentOffset, polygonTypes.size());
|
// Try to guess how many elements the CamDataList array has.
|
||||||
|
// The "guessing algorithm" is basically a "best effort" one and it
|
||||||
|
// is error-prone.
|
||||||
|
// This is based mostly on observation of how CollisionHeader data is
|
||||||
|
// usually ordered. If for some reason the data was in some other funny
|
||||||
|
// order, this would probably break.
|
||||||
|
// The most common ordering is:
|
||||||
|
// - *CamData*
|
||||||
|
// - SurfaceType
|
||||||
|
// - CollisionPoly
|
||||||
|
// - Vertices
|
||||||
|
// - WaterBoxes
|
||||||
|
// - CollisionHeader
|
||||||
|
offset_t upperCameraBoundary = polyTypeDefSegmentOffset;
|
||||||
|
if (upperCameraBoundary == 0)
|
||||||
|
{
|
||||||
|
upperCameraBoundary = polySegmentOffset;
|
||||||
|
}
|
||||||
|
if (upperCameraBoundary == 0)
|
||||||
|
{
|
||||||
|
upperCameraBoundary = vtxSegmentOffset;
|
||||||
|
}
|
||||||
|
if (upperCameraBoundary == 0)
|
||||||
|
{
|
||||||
|
upperCameraBoundary = waterBoxSegmentOffset;
|
||||||
|
}
|
||||||
|
if (upperCameraBoundary == 0)
|
||||||
|
{
|
||||||
|
upperCameraBoundary = rawDataIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
camData =
|
||||||
|
new CameraDataList(parent, name, rawData, camDataSegmentOffset, upperCameraBoundary);
|
||||||
|
}
|
||||||
|
|
||||||
for (uint16_t i = 0; i < numWaterBoxes; i++)
|
for (uint16_t i = 0; i < numWaterBoxes; i++)
|
||||||
waterBoxes.push_back(WaterBoxHeader(
|
waterBoxes.push_back(WaterBoxHeader(
|
||||||
|
@ -106,8 +140,7 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix)
|
||||||
|
|
||||||
parent->AddDeclarationArray(
|
parent->AddDeclarationArray(
|
||||||
waterBoxSegmentOffset, DeclarationAlignment::Align4, 16 * waterBoxes.size(), "WaterBox",
|
waterBoxSegmentOffset, DeclarationAlignment::Align4, 16 * waterBoxes.size(), "WaterBox",
|
||||||
StringHelper::Sprintf("%s_waterBoxes_%06X", auxName.c_str(), waterBoxSegmentOffset),
|
StringHelper::Sprintf("%sWaterBoxes", auxName.c_str()), waterBoxes.size(), declaration);
|
||||||
waterBoxes.size(), declaration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (polygons.size() > 0)
|
if (polygons.size() > 0)
|
||||||
|
@ -126,8 +159,7 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix)
|
||||||
|
|
||||||
parent->AddDeclarationArray(
|
parent->AddDeclarationArray(
|
||||||
polySegmentOffset, DeclarationAlignment::Align4, polygons.size() * 16, "CollisionPoly",
|
polySegmentOffset, DeclarationAlignment::Align4, polygons.size() * 16, "CollisionPoly",
|
||||||
StringHelper::Sprintf("%s_polygons_%08X", auxName.c_str(), polySegmentOffset),
|
StringHelper::Sprintf("%sPolygons", auxName.c_str()), polygons.size(), declaration);
|
||||||
polygons.size(), declaration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declaration.clear();
|
declaration.clear();
|
||||||
|
@ -141,11 +173,10 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (polyTypeDefAddress != 0)
|
if (polyTypeDefAddress != 0)
|
||||||
parent->AddDeclarationArray(
|
parent->AddDeclarationArray(polyTypeDefSegmentOffset, DeclarationAlignment::Align4,
|
||||||
polyTypeDefSegmentOffset, DeclarationAlignment::Align4, polygonTypes.size() * 8,
|
polygonTypes.size() * 8, "SurfaceType",
|
||||||
"SurfaceType",
|
StringHelper::Sprintf("%sSurfaceType", auxName.c_str()),
|
||||||
StringHelper::Sprintf("%s_surfaceType_%08X", auxName.c_str(), polyTypeDefSegmentOffset),
|
polygonTypes.size(), declaration);
|
||||||
polygonTypes.size(), declaration);
|
|
||||||
|
|
||||||
declaration.clear();
|
declaration.clear();
|
||||||
|
|
||||||
|
@ -167,8 +198,7 @@ void ZCollisionHeader::DeclareReferences(const std::string& prefix)
|
||||||
parent->AddDeclarationArray(
|
parent->AddDeclarationArray(
|
||||||
vtxSegmentOffset, first.GetDeclarationAlignment(),
|
vtxSegmentOffset, first.GetDeclarationAlignment(),
|
||||||
vertices.size() * first.GetRawDataSize(), first.GetSourceTypeName(),
|
vertices.size() * first.GetRawDataSize(), first.GetSourceTypeName(),
|
||||||
StringHelper::Sprintf("%s_vtx_%08X", auxName.c_str(), vtxSegmentOffset),
|
StringHelper::Sprintf("%sVertices", auxName.c_str()), vertices.size(), declaration);
|
||||||
vertices.size(), declaration);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,11 +213,11 @@ std::string ZCollisionHeader::GetBodySourceCode() const
|
||||||
|
|
||||||
std::string vtxName;
|
std::string vtxName;
|
||||||
Globals::Instance->GetSegmentedPtrName(vtxAddress, parent, "Vec3s", vtxName);
|
Globals::Instance->GetSegmentedPtrName(vtxAddress, parent, "Vec3s", vtxName);
|
||||||
declaration += StringHelper::Sprintf("\t%i,\n\t%s,\n", numVerts, vtxName.c_str());
|
declaration += StringHelper::Sprintf("\t%i, %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);
|
||||||
declaration += StringHelper::Sprintf("\t%i,\n\t%s,\n", numPolygons, polyName.c_str());
|
declaration += StringHelper::Sprintf("\t%i, %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);
|
||||||
|
@ -199,7 +229,7 @@ std::string ZCollisionHeader::GetBodySourceCode() const
|
||||||
|
|
||||||
std::string waterBoxName;
|
std::string waterBoxName;
|
||||||
Globals::Instance->GetSegmentedPtrName(waterBoxAddress, parent, "WaterBox", waterBoxName);
|
Globals::Instance->GetSegmentedPtrName(waterBoxAddress, parent, "WaterBox", waterBoxName);
|
||||||
declaration += StringHelper::Sprintf("\t%i,\n\t%s\n", numWaterBoxes, waterBoxName.c_str());
|
declaration += StringHelper::Sprintf("\t%i, %s\n", numWaterBoxes, waterBoxName.c_str());
|
||||||
|
|
||||||
return declaration;
|
return declaration;
|
||||||
}
|
}
|
||||||
|
@ -261,16 +291,17 @@ std::string WaterBoxHeader::GetBodySourceCode() const
|
||||||
}
|
}
|
||||||
|
|
||||||
CameraDataList::CameraDataList(ZFile* parent, const std::string& prefix,
|
CameraDataList::CameraDataList(ZFile* parent, const std::string& prefix,
|
||||||
const std::vector<uint8_t>& rawData, uint32_t rawDataIndex,
|
const std::vector<uint8_t>& rawData, offset_t rawDataIndex,
|
||||||
uint32_t polyTypeDefSegmentOffset,
|
offset_t upperCameraBoundary)
|
||||||
[[maybe_unused]] uint32_t polygonTypesCnt)
|
|
||||||
{
|
{
|
||||||
std::string declaration;
|
std::string declaration;
|
||||||
|
|
||||||
// Parse CameraDataEntries
|
// Parse CameraDataEntries
|
||||||
int32_t numElements = (polyTypeDefSegmentOffset - rawDataIndex) / 8;
|
size_t numElements = (upperCameraBoundary - rawDataIndex) / 8;
|
||||||
uint32_t cameraPosDataSeg = rawDataIndex;
|
assert(numElements < 10000);
|
||||||
for (int32_t i = 0; i < numElements; i++)
|
|
||||||
|
offset_t cameraPosDataSeg = rawDataIndex;
|
||||||
|
for (size_t i = 0; i < numElements; i++)
|
||||||
{
|
{
|
||||||
CameraDataEntry* entry = new CameraDataEntry();
|
CameraDataEntry* entry = new CameraDataEntry();
|
||||||
|
|
||||||
|
@ -302,8 +333,7 @@ CameraDataList::CameraDataList(ZFile* parent, const std::string& prefix,
|
||||||
{
|
{
|
||||||
int32_t index =
|
int32_t index =
|
||||||
((entries[i]->cameraPosDataSeg & 0x00FFFFFF) - cameraPosDataOffset) / 0x6;
|
((entries[i]->cameraPosDataSeg & 0x00FFFFFF) - cameraPosDataOffset) / 0x6;
|
||||||
sprintf(camSegLine, "&%s_camPosData_%08X[%i]", prefix.c_str(), cameraPosDataOffset,
|
sprintf(camSegLine, "&%sCamPosData[%i]", prefix.c_str(), index);
|
||||||
index);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sprintf(camSegLine, "NULL");
|
sprintf(camSegLine, "NULL");
|
||||||
|
@ -318,7 +348,7 @@ CameraDataList::CameraDataList(ZFile* parent, const std::string& prefix,
|
||||||
|
|
||||||
parent->AddDeclarationArray(
|
parent->AddDeclarationArray(
|
||||||
rawDataIndex, DeclarationAlignment::Align4, entries.size() * 8, "CamData",
|
rawDataIndex, DeclarationAlignment::Align4, entries.size() * 8, "CamData",
|
||||||
StringHelper::Sprintf("%s_camDataList_%08X", prefix.c_str(), rawDataIndex), entries.size(),
|
StringHelper::Sprintf("%sCamDataList", prefix.c_str(), rawDataIndex), entries.size(),
|
||||||
declaration);
|
declaration);
|
||||||
|
|
||||||
uint32_t numDataTotal = (rawDataIndex - cameraPosDataOffset) / 0x6;
|
uint32_t numDataTotal = (rawDataIndex - cameraPosDataOffset) / 0x6;
|
||||||
|
@ -339,10 +369,9 @@ CameraDataList::CameraDataList(ZFile* parent, const std::string& prefix,
|
||||||
|
|
||||||
int32_t cameraPosDataIndex = GETSEGOFFSET(cameraPosDataSeg);
|
int32_t cameraPosDataIndex = GETSEGOFFSET(cameraPosDataSeg);
|
||||||
uint32_t entrySize = numDataTotal * 0x6;
|
uint32_t entrySize = numDataTotal * 0x6;
|
||||||
parent->AddDeclarationArray(
|
parent->AddDeclarationArray(cameraPosDataIndex, DeclarationAlignment::Align4, entrySize,
|
||||||
cameraPosDataIndex, DeclarationAlignment::Align4, entrySize, "Vec3s",
|
"Vec3s", StringHelper::Sprintf("%sCamPosData", prefix.c_str()),
|
||||||
StringHelper::Sprintf("%s_camPosData_%08X", prefix.c_str(), cameraPosDataIndex),
|
numDataTotal, declaration);
|
||||||
numDataTotal, declaration);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,8 +55,7 @@ public:
|
||||||
std::vector<CameraPositionData*> cameraPositionData;
|
std::vector<CameraPositionData*> cameraPositionData;
|
||||||
|
|
||||||
CameraDataList(ZFile* parent, const std::string& prefix, const std::vector<uint8_t>& rawData,
|
CameraDataList(ZFile* parent, const std::string& prefix, const std::vector<uint8_t>& rawData,
|
||||||
uint32_t rawDataIndex, uint32_t polyTypeDefSegmentOffset,
|
offset_t rawDataIndex, offset_t upperCameraBoundary);
|
||||||
uint32_t polygonTypesCnt);
|
|
||||||
~CameraDataList();
|
~CameraDataList();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <cinttypes>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
|
@ -26,8 +27,8 @@ ZDisplayList::ZDisplayList(ZFile* nParent) : ZResource(nParent)
|
||||||
lastTexSizTest = F3DZEXTexSizes::G_IM_SIZ_16b;
|
lastTexSizTest = F3DZEXTexSizes::G_IM_SIZ_16b;
|
||||||
lastTexLoaded = false;
|
lastTexLoaded = false;
|
||||||
lastTexIsPalette = false;
|
lastTexIsPalette = false;
|
||||||
name = "";
|
|
||||||
dListType = Globals::Instance->game == ZGame::OOT_SW97 ? DListType::F3DEX : DListType::F3DZEX;
|
dListType = Globals::Instance->game == ZGame::OOT_SW97 ? DListType::F3DEX : DListType::F3DZEX;
|
||||||
|
RegisterOptionalAttribute("Ucode");
|
||||||
}
|
}
|
||||||
|
|
||||||
ZDisplayList::~ZDisplayList()
|
ZDisplayList::~ZDisplayList()
|
||||||
|
@ -43,13 +44,29 @@ void ZDisplayList::ExtractFromXML(tinyxml2::XMLElement* reader, uint32_t nRawDat
|
||||||
{
|
{
|
||||||
rawDataIndex = nRawDataIndex;
|
rawDataIndex = nRawDataIndex;
|
||||||
ParseXML(reader);
|
ParseXML(reader);
|
||||||
|
// TODO add error handling here
|
||||||
|
bool ucodeSet = registeredAttributes.at("Ucode").wasSet;
|
||||||
|
std::string ucodeValue = registeredAttributes.at("Ucode").value;
|
||||||
|
if ((Globals::Instance->game == ZGame::OOT_SW97) || (ucodeValue == "f3dex"))
|
||||||
|
{
|
||||||
|
dListType = DListType::F3DEX;
|
||||||
|
}
|
||||||
|
else if (!ucodeSet || ucodeValue == "f3dex2")
|
||||||
|
{
|
||||||
|
dListType = DListType::F3DZEX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HANDLE_ERROR_RESOURCE(
|
||||||
|
WarningType::InvalidAttributeValue, parent, this, rawDataIndex,
|
||||||
|
StringHelper::Sprintf("Invalid ucode type in node: %s\n", reader->Name()), "");
|
||||||
|
}
|
||||||
|
|
||||||
// Don't parse raw data of external files
|
// Don't parse raw data of external files
|
||||||
if (parent->GetMode() != ZFileMode::ExternalFile)
|
if (parent->GetMode() != ZFileMode::ExternalFile)
|
||||||
{
|
{
|
||||||
int32_t rawDataSize = ZDisplayList::GetDListLength(
|
int32_t rawDataSize =
|
||||||
parent->GetRawData(), rawDataIndex,
|
ZDisplayList::GetDListLength(parent->GetRawData(), rawDataIndex, dListType);
|
||||||
Globals::Instance->game == ZGame::OOT_SW97 ? DListType::F3DEX : DListType::F3DZEX);
|
|
||||||
numInstructions = rawDataSize / 8;
|
numInstructions = rawDataSize / 8;
|
||||||
ParseRawData();
|
ParseRawData();
|
||||||
}
|
}
|
||||||
|
@ -106,7 +123,7 @@ void ZDisplayList::ParseF3DZEX(F3DZEXOpcode opcode, uint64_t data, int32_t i,
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case F3DZEXOpcode::G_NOOP:
|
case F3DZEXOpcode::G_NOOP:
|
||||||
sprintf(line, "gsDPNoOpTag(0x%08lX),", data & 0xFFFFFFFF);
|
sprintf(line, "gsDPNoOpTag(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
|
||||||
break;
|
break;
|
||||||
case F3DZEXOpcode::G_DL:
|
case F3DZEXOpcode::G_DL:
|
||||||
Opcode_G_DL(data, prefix, line);
|
Opcode_G_DL(data, prefix, line);
|
||||||
|
@ -221,7 +238,7 @@ void ZDisplayList::ParseF3DZEX(F3DZEXOpcode opcode, uint64_t data, int32_t i,
|
||||||
break;
|
break;
|
||||||
case F3DZEXOpcode::G_POPMTX:
|
case F3DZEXOpcode::G_POPMTX:
|
||||||
{
|
{
|
||||||
sprintf(line, "gsSPPopMatrix(%li),", data);
|
sprintf(line, "gsSPPopMatrix(%" PRIi64 "),", data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case F3DZEXOpcode::G_LOADTLUT:
|
case F3DZEXOpcode::G_LOADTLUT:
|
||||||
|
@ -298,7 +315,7 @@ void ZDisplayList::ParseF3DEX(F3DEXOpcode opcode, uint64_t data, const std::stri
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case F3DEXOpcode::G_NOOP:
|
case F3DEXOpcode::G_NOOP:
|
||||||
sprintf(line, "gsDPNoOpTag(0x%08lX),", data & 0xFFFFFFFF);
|
sprintf(line, "gsDPNoOpTag(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
|
||||||
break;
|
break;
|
||||||
case F3DEXOpcode::G_VTX:
|
case F3DEXOpcode::G_VTX:
|
||||||
Opcode_G_VTX(data, line);
|
Opcode_G_VTX(data, line);
|
||||||
|
@ -688,20 +705,22 @@ 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))
|
||||||
sprintf(line, "gsSPBranchList(0x%08lX),", 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());
|
||||||
else
|
else
|
||||||
sprintf(line, "gsSPBranchList(%sDlist0x%06lX),", prefix.c_str(), GETSEGOFFSET(data));
|
sprintf(line, "gsSPBranchList(%sDlist0x%06" PRIX64 "),", prefix.c_str(),
|
||||||
|
GETSEGOFFSET(data));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!Globals::Instance->HasSegment(segNum))
|
if (!Globals::Instance->HasSegment(segNum))
|
||||||
sprintf(line, "gsSPDisplayList(0x%08lX),", 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());
|
||||||
else
|
else
|
||||||
sprintf(line, "gsSPDisplayList(%sDlist0x%06lX),", prefix.c_str(), GETSEGOFFSET(data));
|
sprintf(line, "gsSPDisplayList(%sDlist0x%06" PRIX64 "),", prefix.c_str(),
|
||||||
|
GETSEGOFFSET(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (segNum == 8 || segNum == 9 || segNum == 10 || segNum == 11 || segNum == 12 || segNum ==
|
// if (segNum == 8 || segNum == 9 || segNum == 10 || segNum == 11 || segNum == 12 || segNum ==
|
||||||
|
@ -709,9 +728,9 @@ void ZDisplayList::Opcode_G_DL(uint64_t data, const std::string& prefix, char* l
|
||||||
if (!Globals::Instance->HasSegment(segNum))
|
if (!Globals::Instance->HasSegment(segNum))
|
||||||
{
|
{
|
||||||
if (pp != 0)
|
if (pp != 0)
|
||||||
sprintf(line, "gsSPBranchList(0x%08lX),", data & 0xFFFFFFFF);
|
sprintf(line, "gsSPBranchList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
|
||||||
else
|
else
|
||||||
sprintf(line, "gsSPDisplayList(0x%08lX),", data & 0xFFFFFFFF);
|
sprintf(line, "gsSPDisplayList(0x%08" PRIX64 "),", data & 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -831,7 +850,7 @@ void ZDisplayList::Opcode_G_VTX(uint64_t data, char* line)
|
||||||
{
|
{
|
||||||
segptr_t segmented = data & 0xFFFFFFFF;
|
segptr_t segmented = data & 0xFFFFFFFF;
|
||||||
references.push_back(segmented);
|
references.push_back(segmented);
|
||||||
parent->AddDeclaration(segmented, DeclarationAlignment::Align16, 16, "Vtx",
|
parent->AddDeclaration(segmented, DeclarationAlignment::Align8, 16, "Vtx",
|
||||||
StringHelper::Sprintf("0x%08X", segmented), "");
|
StringHelper::Sprintf("0x%08X", segmented), "");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -943,7 +962,7 @@ void ZDisplayList::Opcode_G_SETTIMG(uint64_t data, const std::string& prefix, ch
|
||||||
sprintf(texStr, "%sTex_%06X", prefix.c_str(), texAddress);
|
sprintf(texStr, "%sTex_%06X", prefix.c_str(), texAddress);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(texStr, "0x%08lX", data & 0xFFFFFFFF);
|
sprintf(texStr, "0x%08" PRIX64, data & 0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
@ -1747,7 +1766,7 @@ void ZDisplayList::DeclareReferences(const std::string& prefix)
|
||||||
if (vertices.size() > 0)
|
if (vertices.size() > 0)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<uint32_t, std::vector<ZVtx>>> verticesSorted(vertices.begin(),
|
std::vector<std::pair<uint32_t, std::vector<ZVtx>>> verticesSorted(vertices.begin(),
|
||||||
vertices.end());
|
vertices.end());
|
||||||
|
|
||||||
for (size_t i = 0; i < verticesSorted.size() - 1; i++)
|
for (size_t i = 0; i < verticesSorted.size() - 1; i++)
|
||||||
{
|
{
|
||||||
|
@ -1795,7 +1814,7 @@ void ZDisplayList::DeclareReferences(const std::string& prefix)
|
||||||
if (vertices.size() > 0)
|
if (vertices.size() > 0)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<uint32_t, std::vector<ZVtx>>> verticesSorted(vertices.begin(),
|
std::vector<std::pair<uint32_t, std::vector<ZVtx>>> verticesSorted(vertices.begin(),
|
||||||
vertices.end());
|
vertices.end());
|
||||||
|
|
||||||
for (size_t i = 0; i < verticesSorted.size() - 1; i++)
|
for (size_t i = 0; i < verticesSorted.size() - 1; i++)
|
||||||
{
|
{
|
||||||
|
@ -1889,10 +1908,10 @@ std::string ZDisplayList::ProcessLegacy(const std::string& prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto end = std::chrono::steady_clock::now();
|
auto end = std::chrono::steady_clock::now();
|
||||||
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
int64_t diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||||
|
|
||||||
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG && diff > 5)
|
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG && diff > 5)
|
||||||
printf("F3DOP: 0x%02X, TIME: %lims\n", opcode, diff);
|
printf("F3DOP: 0x%02X, TIME: %" PRIi64 "ms\n", opcode, diff);
|
||||||
|
|
||||||
sourceOutput += line;
|
sourceOutput += line;
|
||||||
|
|
||||||
|
@ -1973,7 +1992,7 @@ bool ZDisplayList::TextureGenCheck(int32_t texWidth, int32_t texHeight, uint32_t
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Try to find a non-external file (ie, 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])
|
for (auto& otherFile : Globals::Instance->cfg.segmentRefFiles[segmentNumber])
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "Globals.h"
|
#include "Globals.h"
|
||||||
#include "OutputFormatter.h"
|
#include "OutputFormatter.h"
|
||||||
#include "Utils/BinaryWriter.h"
|
#include "Utils/BinaryWriter.h"
|
||||||
|
#include "Utils/BitConverter.h"
|
||||||
#include "Utils/Directory.h"
|
#include "Utils/Directory.h"
|
||||||
#include "Utils/File.h"
|
#include "Utils/File.h"
|
||||||
#include "Utils/MemoryStream.h"
|
#include "Utils/MemoryStream.h"
|
||||||
|
@ -192,7 +193,7 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||||
rawData = File::ReadAllBytes((basePath / name).string());
|
rawData = File::ReadAllBytes((basePath / name).string());
|
||||||
|
|
||||||
if (reader->Attribute("RangeEnd") == nullptr)
|
if (reader->Attribute("RangeEnd") == nullptr)
|
||||||
rangeEnd = rawData.size();
|
rangeEnd = rawData.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_set<std::string> nameSet;
|
std::unordered_set<std::string> nameSet;
|
||||||
|
@ -378,7 +379,7 @@ void ZFile::ExtractResources()
|
||||||
ZResourceExporter* exporter = Globals::Instance->GetExporter(res->GetResourceType());
|
ZResourceExporter* exporter = Globals::Instance->GetExporter(res->GetResourceType());
|
||||||
if (exporter != nullptr)
|
if (exporter != nullptr)
|
||||||
{
|
{
|
||||||
//exporter->Save(res, Globals::Instance->outputPath.string(), &writerFile);
|
// exporter->Save(res, Globals::Instance->outputPath.string(), &writerFile);
|
||||||
exporter->Save(res, Globals::Instance->outputPath.string(), &writerRes);
|
exporter->Save(res, Globals::Instance->outputPath.string(), &writerRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +392,7 @@ void ZFile::ExtractResources()
|
||||||
File::WriteAllBytes(StringHelper::Sprintf("%s%s.bin",
|
File::WriteAllBytes(StringHelper::Sprintf("%s%s.bin",
|
||||||
Globals::Instance->outputPath.string().c_str(),
|
Globals::Instance->outputPath.string().c_str(),
|
||||||
GetName().c_str()),
|
GetName().c_str()),
|
||||||
memStreamFile->ToVector());
|
memStreamFile->ToVector());
|
||||||
}
|
}
|
||||||
|
|
||||||
writerFile.Close();
|
writerFile.Close();
|
||||||
|
@ -949,9 +950,6 @@ std::string ZFile::ProcessDeclarations()
|
||||||
|
|
||||||
defines += ProcessTextureIntersections(name);
|
defines += ProcessTextureIntersections(name);
|
||||||
|
|
||||||
// Account for padding/alignment
|
|
||||||
uint32_t lastAddr = 0;
|
|
||||||
|
|
||||||
// printf("RANGE START: 0x%06X - RANGE END: 0x%06X\n", rangeStart, rangeEnd);
|
// printf("RANGE START: 0x%06X - RANGE END: 0x%06X\n", rangeStart, rangeEnd);
|
||||||
|
|
||||||
// Optimization: See if there are any arrays side by side that can be merged...
|
// Optimization: See if there are any arrays side by side that can be merged...
|
||||||
|
@ -1002,43 +1000,6 @@ std::string ZFile::ProcessDeclarations()
|
||||||
{
|
{
|
||||||
while (item.second->size % 4 != 0)
|
while (item.second->size % 4 != 0)
|
||||||
item.second->size++;
|
item.second->size++;
|
||||||
|
|
||||||
if (lastAddr != 0)
|
|
||||||
{
|
|
||||||
if (item.second->alignment == DeclarationAlignment::Align16)
|
|
||||||
{
|
|
||||||
int32_t curPtr = lastAddr + declarations[lastAddr]->size;
|
|
||||||
|
|
||||||
while (curPtr % 4 != 0)
|
|
||||||
{
|
|
||||||
declarations[lastAddr]->size++;
|
|
||||||
curPtr++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (item.second->alignment == DeclarationAlignment::Align8)
|
|
||||||
{
|
|
||||||
size_t curPtr = lastAddr + declarations[lastAddr]->size;
|
|
||||||
|
|
||||||
while (curPtr % 4 != 0)
|
|
||||||
{
|
|
||||||
declarations[lastAddr]->size++;
|
|
||||||
curPtr++;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (curPtr % 8 != 0)
|
|
||||||
{
|
|
||||||
char buffer[2048];
|
|
||||||
|
|
||||||
sprintf(buffer, "u32 %s_align%02zX = 0;\n", name.c_str(), curPtr);
|
|
||||||
item.second->preText = buffer + item.second->preText;
|
|
||||||
|
|
||||||
declarations[lastAddr]->size += 4;
|
|
||||||
curPtr += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lastAddr = item.first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleUnaccountedData();
|
HandleUnaccountedData();
|
||||||
|
@ -1199,14 +1160,15 @@ void ZFile::HandleUnaccountedData()
|
||||||
{
|
{
|
||||||
uint32_t lastAddr = 0;
|
uint32_t lastAddr = 0;
|
||||||
uint32_t lastSize = 0;
|
uint32_t lastSize = 0;
|
||||||
std::vector<uint32_t> declsAddresses;
|
std::vector<offset_t> declsAddresses;
|
||||||
|
|
||||||
for (const auto& item : declarations)
|
for (const auto& item : declarations)
|
||||||
{
|
{
|
||||||
declsAddresses.push_back(item.first);
|
declsAddresses.push_back(item.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool breakLoop = false;
|
bool breakLoop = false;
|
||||||
for (uint32_t currentAddress : declsAddresses)
|
for (offset_t currentAddress : declsAddresses)
|
||||||
{
|
{
|
||||||
if (currentAddress >= rangeEnd)
|
if (currentAddress >= rangeEnd)
|
||||||
{
|
{
|
||||||
|
@ -1235,7 +1197,7 @@ void ZFile::HandleUnaccountedData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZFile::HandleUnaccountedAddress(uint32_t currentAddress, uint32_t lastAddr, uint32_t& lastSize)
|
bool ZFile::HandleUnaccountedAddress(offset_t currentAddress, offset_t lastAddr, uint32_t& lastSize)
|
||||||
{
|
{
|
||||||
if (currentAddress != lastAddr && declarations.find(lastAddr) != declarations.end())
|
if (currentAddress != lastAddr && declarations.find(lastAddr) != declarations.end())
|
||||||
{
|
{
|
||||||
|
@ -1275,6 +1237,29 @@ bool ZFile::HandleUnaccountedAddress(uint32_t currentAddress, uint32_t lastAddr,
|
||||||
xmlFilePath.c_str(), currentAddress, name.c_str(), rawData.size()));
|
xmlFilePath.c_str(), currentAddress, name.c_str(), rawData.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle Align8
|
||||||
|
if (currentAddress % 8 == 0 && diff % 8 != 0)
|
||||||
|
{
|
||||||
|
Declaration* currentDecl = GetDeclaration(currentAddress);
|
||||||
|
|
||||||
|
if (currentDecl != nullptr)
|
||||||
|
{
|
||||||
|
if (currentDecl->alignment == DeclarationAlignment::Align8)
|
||||||
|
{
|
||||||
|
// Check removed bytes are zeroes
|
||||||
|
if (BitConverter::ToUInt32BE(rawData, unaccountedAddress + diff - 4) == 0)
|
||||||
|
{
|
||||||
|
diff -= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diff == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < diff; i++)
|
for (int i = 0; i < diff; i++)
|
||||||
{
|
{
|
||||||
uint8_t val = rawData.at(unaccountedAddress + i);
|
uint8_t val = rawData.at(unaccountedAddress + i);
|
||||||
|
@ -1320,7 +1305,10 @@ bool ZFile::HandleUnaccountedAddress(uint32_t currentAddress, uint32_t lastAddr,
|
||||||
StringHelper::Sprintf("%s_%s_%06X", name.c_str(), unaccountedPrefix.c_str(),
|
StringHelper::Sprintf("%s_%s_%06X", name.c_str(), unaccountedPrefix.c_str(),
|
||||||
unaccountedAddress),
|
unaccountedAddress),
|
||||||
diff, src);
|
diff, src);
|
||||||
|
|
||||||
decl->isUnaccounted = true;
|
decl->isUnaccounted = true;
|
||||||
|
if (Globals::Instance->forceUnaccountedStatic)
|
||||||
|
decl->staticConf = StaticConfig::On;
|
||||||
|
|
||||||
if (nonZeroUnaccounted)
|
if (nonZeroUnaccounted)
|
||||||
{
|
{
|
||||||
|
|
|
@ -133,5 +133,5 @@ protected:
|
||||||
|
|
||||||
std::string ProcessTextureIntersections(const std::string& prefix);
|
std::string ProcessTextureIntersections(const std::string& prefix);
|
||||||
void HandleUnaccountedData();
|
void HandleUnaccountedData();
|
||||||
bool HandleUnaccountedAddress(uint32_t currentAddress, uint32_t lastAddr, uint32_t& lastSize);
|
bool HandleUnaccountedAddress(offset_t currentAddress, offset_t lastAddr, uint32_t& lastSize);
|
||||||
};
|
};
|
||||||
|
|
|
@ -228,8 +228,8 @@ std::string ZLimb::GetBodySourceCode() const
|
||||||
{
|
{
|
||||||
std::string childName;
|
std::string childName;
|
||||||
std::string siblingName;
|
std::string siblingName;
|
||||||
Globals::Instance->GetSegmentedPtrName(childPtr, parent, "Gfx", childName);
|
Globals::Instance->GetSegmentedPtrName(childPtr, parent, "LegacyLimb", childName);
|
||||||
Globals::Instance->GetSegmentedPtrName(siblingPtr, parent, "Gfx", siblingName);
|
Globals::Instance->GetSegmentedPtrName(siblingPtr, parent, "LegacyLimb", siblingName);
|
||||||
|
|
||||||
entryStr += StringHelper::Sprintf("%s,\n", dListStr.c_str());
|
entryStr += StringHelper::Sprintf("%s,\n", dListStr.c_str());
|
||||||
entryStr +=
|
entryStr +=
|
||||||
|
|
57
tools/ZAPD/ZAPD/ZPointer.cpp
Normal file
57
tools/ZAPD/ZAPD/ZPointer.cpp
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#include "ZPointer.h"
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "Utils/BitConverter.h"
|
||||||
|
#include "Utils/StringHelper.h"
|
||||||
|
#include "WarningHandler.h"
|
||||||
|
#include "ZFile.h"
|
||||||
|
|
||||||
|
REGISTER_ZFILENODE(Pointer, ZPointer);
|
||||||
|
|
||||||
|
ZPointer::ZPointer(ZFile* nParent) : ZResource(nParent)
|
||||||
|
{
|
||||||
|
RegisterRequiredAttribute("Type");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZPointer::ParseXML(tinyxml2::XMLElement* reader)
|
||||||
|
{
|
||||||
|
ZResource::ParseXML(reader);
|
||||||
|
|
||||||
|
type = registeredAttributes.at("Type").value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZPointer::ParseRawData()
|
||||||
|
{
|
||||||
|
auto& rawData = parent->GetRawData();
|
||||||
|
|
||||||
|
ptr = BitConverter::ToUInt32BE(rawData, rawDataIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ZPointer::GetBodySourceCode() const
|
||||||
|
{
|
||||||
|
std::string ptrName;
|
||||||
|
|
||||||
|
Globals::Instance->GetSegmentedPtrName(ptr, parent, "", ptrName);
|
||||||
|
|
||||||
|
return ptrName;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZPointer::DoesSupportArray() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ZPointer::GetSourceTypeName() const
|
||||||
|
{
|
||||||
|
return type + "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
ZResourceType ZPointer::GetResourceType() const
|
||||||
|
{
|
||||||
|
return ZResourceType::Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ZPointer::GetRawDataSize() const
|
||||||
|
{
|
||||||
|
return 0x04;
|
||||||
|
}
|
22
tools/ZAPD/ZAPD/ZPointer.h
Normal file
22
tools/ZAPD/ZAPD/ZPointer.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ZResource.h"
|
||||||
|
|
||||||
|
class ZPointer : public ZResource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
segptr_t ptr = SEGMENTED_NULL;
|
||||||
|
std::string type;
|
||||||
|
|
||||||
|
ZPointer(ZFile* nParent);
|
||||||
|
|
||||||
|
void ParseXML(tinyxml2::XMLElement* reader) override;
|
||||||
|
void ParseRawData() override;
|
||||||
|
std::string GetBodySourceCode() const override;
|
||||||
|
|
||||||
|
bool DoesSupportArray() const override;
|
||||||
|
std::string GetSourceTypeName() const override;
|
||||||
|
ZResourceType GetResourceType() const override;
|
||||||
|
|
||||||
|
size_t GetRawDataSize() const override;
|
||||||
|
};
|
|
@ -38,6 +38,7 @@ enum class ZResourceType
|
||||||
Mtx,
|
Mtx,
|
||||||
Path,
|
Path,
|
||||||
PlayerAnimationData,
|
PlayerAnimationData,
|
||||||
|
Pointer,
|
||||||
Room,
|
Room,
|
||||||
RoomCommand,
|
RoomCommand,
|
||||||
Scalar,
|
Scalar,
|
||||||
|
|
|
@ -152,7 +152,6 @@ void PolygonDlist::GetSourceOutputCode(const std::string& prefix)
|
||||||
DeclareVar(prefix, bodyStr);
|
DeclareVar(prefix, bodyStr);
|
||||||
else
|
else
|
||||||
decl->text = bodyStr;
|
decl->text = bodyStr;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string PolygonDlist::GetSourceTypeName() const
|
std::string PolygonDlist::GetSourceTypeName() const
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#include "SetSpecialObjects.h"
|
#include "SetSpecialObjects.h"
|
||||||
|
|
||||||
#include "Utils/BitConverter.h"
|
#include "Utils/BitConverter.h"
|
||||||
#include "Utils/StringHelper.h"
|
#include "Utils/StringHelper.h"
|
||||||
|
#include "ZRoom/ZNames.h"
|
||||||
|
|
||||||
SetSpecialObjects::SetSpecialObjects(ZFile* nParent) : ZRoomCommand(nParent)
|
SetSpecialObjects::SetSpecialObjects(ZFile* nParent) : ZRoomCommand(nParent)
|
||||||
{
|
{
|
||||||
|
@ -15,8 +17,10 @@ void SetSpecialObjects::ParseRawData()
|
||||||
|
|
||||||
std::string SetSpecialObjects::GetBodySourceCode() const
|
std::string SetSpecialObjects::GetBodySourceCode() const
|
||||||
{
|
{
|
||||||
return StringHelper::Sprintf("SCENE_CMD_SPECIAL_FILES(0x%02X, 0x%04X)", elfMessage,
|
std::string objectName = ZNames::GetObjectName(globalObject);
|
||||||
globalObject);
|
|
||||||
|
return StringHelper::Sprintf("SCENE_CMD_SPECIAL_FILES(0x%02X, %s)", elfMessage,
|
||||||
|
objectName.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string SetSpecialObjects::GetCommandCName() const
|
std::string SetSpecialObjects::GetCommandCName() const
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <cinttypes>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include "Commands/EndMarker.h"
|
#include "Commands/EndMarker.h"
|
||||||
#include "Commands/SetActorCutsceneList.h"
|
#include "Commands/SetActorCutsceneList.h"
|
||||||
#include "Commands/SetActorList.h"
|
#include "Commands/SetActorList.h"
|
||||||
|
@ -259,9 +261,10 @@ void ZRoom::ParseRawData()
|
||||||
if (Globals::Instance->profile)
|
if (Globals::Instance->profile)
|
||||||
{
|
{
|
||||||
auto end = std::chrono::steady_clock::now();
|
auto end = std::chrono::steady_clock::now();
|
||||||
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
int64_t diff =
|
||||||
|
std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
|
||||||
if (diff > 50)
|
if (diff > 50)
|
||||||
printf("OP: %s, TIME: %lims\n", cmd->GetCommandCName().c_str(), diff);
|
printf("OP: %s, TIME: %" PRIi64 "ms\n", cmd->GetCommandCName().c_str(), diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd->cmdIndex = currentIndex;
|
cmd->cmdIndex = currentIndex;
|
||||||
|
|
|
@ -139,7 +139,7 @@ ZResourceType ZSkeleton::GetResourceType() const
|
||||||
|
|
||||||
DeclarationAlignment ZSkeleton::GetDeclarationAlignment() const
|
DeclarationAlignment ZSkeleton::GetDeclarationAlignment() const
|
||||||
{
|
{
|
||||||
return DeclarationAlignment::Align16;
|
return DeclarationAlignment::Align4;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ZSkeleton::GetLimbCount()
|
uint8_t ZSkeleton::GetLimbCount()
|
||||||
|
|
|
@ -16,6 +16,7 @@ ZTexture::ZTexture(ZFile* nParent) : ZResource(nParent)
|
||||||
{
|
{
|
||||||
width = 0;
|
width = 0;
|
||||||
height = 0;
|
height = 0;
|
||||||
|
dWordAligned = true;
|
||||||
|
|
||||||
RegisterRequiredAttribute("Width");
|
RegisterRequiredAttribute("Width");
|
||||||
RegisterRequiredAttribute("Height");
|
RegisterRequiredAttribute("Height");
|
||||||
|
@ -105,10 +106,7 @@ void ZTexture::ParseXML(tinyxml2::XMLElement* reader)
|
||||||
void ZTexture::ParseRawData()
|
void ZTexture::ParseRawData()
|
||||||
{
|
{
|
||||||
if (rawDataIndex % 8 != 0)
|
if (rawDataIndex % 8 != 0)
|
||||||
{
|
dWordAligned = false;
|
||||||
HANDLE_WARNING_RESOURCE(WarningType::NotImplemented, parent, this, rawDataIndex,
|
|
||||||
"this texture is not 64-bit aligned", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (format)
|
switch (format)
|
||||||
{
|
{
|
||||||
|
@ -724,7 +722,12 @@ void ZTexture::Save(const fs::path& outFolder)
|
||||||
if (!Directory::Exists(outPath.string()))
|
if (!Directory::Exists(outPath.string()))
|
||||||
Directory::CreateDirectory(outPath.string());
|
Directory::CreateDirectory(outPath.string());
|
||||||
|
|
||||||
auto outFileName = outPath / (outName + "." + GetExternalExtension() + ".png");
|
fs::path outFileName;
|
||||||
|
|
||||||
|
if (!dWordAligned)
|
||||||
|
outFileName = outPath / (outName + ".u32" + "." + GetExternalExtension() + ".png");
|
||||||
|
else
|
||||||
|
outFileName = outPath / (outName + +"." + GetExternalExtension() + ".png");
|
||||||
|
|
||||||
#ifdef TEXTURE_DEBUG
|
#ifdef TEXTURE_DEBUG
|
||||||
printf("Saving PNG: %s\n", outFileName.c_str());
|
printf("Saving PNG: %s\n", outFileName.c_str());
|
||||||
|
@ -745,7 +748,7 @@ Declaration* ZTexture::DeclareVar(const std::string& prefix,
|
||||||
{
|
{
|
||||||
std::string auxName = name;
|
std::string auxName = name;
|
||||||
std::string auxOutName = outName;
|
std::string auxOutName = outName;
|
||||||
|
std::string incStr;
|
||||||
if (auxName == "")
|
if (auxName == "")
|
||||||
auxName = GetDefaultName(prefix);
|
auxName = GetDefaultName(prefix);
|
||||||
|
|
||||||
|
@ -754,8 +757,12 @@ Declaration* ZTexture::DeclareVar(const std::string& prefix,
|
||||||
|
|
||||||
auto filepath = Globals::Instance->outputPath / fs::path(auxOutName).stem();
|
auto filepath = Globals::Instance->outputPath / fs::path(auxOutName).stem();
|
||||||
|
|
||||||
std::string incStr =
|
if (dWordAligned)
|
||||||
StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), GetExternalExtension().c_str());
|
incStr =
|
||||||
|
StringHelper::Sprintf("%s.%s.inc.c", filepath.c_str(), GetExternalExtension().c_str());
|
||||||
|
else
|
||||||
|
incStr = StringHelper::Sprintf("%s.u32.%s.inc.c", filepath.c_str(),
|
||||||
|
GetExternalExtension().c_str());
|
||||||
|
|
||||||
if (!Globals::Instance->cfg.texturePool.empty())
|
if (!Globals::Instance->cfg.texturePool.empty())
|
||||||
{
|
{
|
||||||
|
@ -765,13 +772,19 @@ Declaration* ZTexture::DeclareVar(const std::string& prefix,
|
||||||
const auto& poolEntry = Globals::Instance->cfg.texturePool.find(hash);
|
const auto& poolEntry = Globals::Instance->cfg.texturePool.find(hash);
|
||||||
if (poolEntry != Globals::Instance->cfg.texturePool.end())
|
if (poolEntry != Globals::Instance->cfg.texturePool.end())
|
||||||
{
|
{
|
||||||
incStr = StringHelper::Sprintf("%s.%s.inc.c", poolEntry->second.path.c_str(),
|
if (dWordAligned)
|
||||||
GetExternalExtension().c_str());
|
incStr = StringHelper::Sprintf("%s.%s.inc.c", poolEntry->second.path.c_str(),
|
||||||
|
GetExternalExtension().c_str());
|
||||||
|
else
|
||||||
|
incStr = StringHelper::Sprintf("%s.u32.%s.inc.c", poolEntry->second.path.c_str(),
|
||||||
|
GetExternalExtension().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
size_t texSizeDivisor = (dWordAligned) ? 8 : 4;
|
||||||
|
|
||||||
Declaration* decl = parent->AddDeclarationIncludeArray(
|
Declaration* decl = parent->AddDeclarationIncludeArray(rawDataIndex, incStr, GetRawDataSize(),
|
||||||
rawDataIndex, incStr, GetRawDataSize(), GetSourceTypeName(), auxName, GetRawDataSize() / 8);
|
GetSourceTypeName(), auxName,
|
||||||
|
GetRawDataSize() / texSizeDivisor);
|
||||||
decl->staticConf = staticConf;
|
decl->staticConf = staticConf;
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
@ -779,15 +792,17 @@ Declaration* ZTexture::DeclareVar(const std::string& prefix,
|
||||||
std::string ZTexture::GetBodySourceCode() const
|
std::string ZTexture::GetBodySourceCode() const
|
||||||
{
|
{
|
||||||
std::string sourceOutput;
|
std::string sourceOutput;
|
||||||
|
size_t texSizeInc = (dWordAligned) ? 8 : 4;
|
||||||
for (size_t i = 0; i < textureDataRaw.size(); i += 8)
|
for (size_t i = 0; i < textureDataRaw.size(); i += texSizeInc)
|
||||||
{
|
{
|
||||||
if (i % 32 == 0)
|
if (i % 32 == 0)
|
||||||
sourceOutput += " ";
|
sourceOutput += " ";
|
||||||
|
if (dWordAligned)
|
||||||
sourceOutput +=
|
sourceOutput +=
|
||||||
StringHelper::Sprintf("0x%016llX, ", BitConverter::ToUInt64BE(textureDataRaw, i));
|
StringHelper::Sprintf("0x%016llX, ", BitConverter::ToUInt64BE(textureDataRaw, i));
|
||||||
|
else
|
||||||
|
sourceOutput +=
|
||||||
|
StringHelper::Sprintf("0x%08llX, ", BitConverter::ToUInt32BE(textureDataRaw, i));
|
||||||
if (i % 32 == 24)
|
if (i % 32 == 24)
|
||||||
sourceOutput += StringHelper::Sprintf(" // 0x%06X \n", rawDataIndex + ((i / 32) * 32));
|
sourceOutput += StringHelper::Sprintf(" // 0x%06X \n", rawDataIndex + ((i / 32) * 32));
|
||||||
}
|
}
|
||||||
|
@ -812,7 +827,7 @@ ZResourceType ZTexture::GetResourceType() const
|
||||||
|
|
||||||
std::string ZTexture::GetSourceTypeName() const
|
std::string ZTexture::GetSourceTypeName() const
|
||||||
{
|
{
|
||||||
return "u64";
|
return dWordAligned ? "u64" : "u32";
|
||||||
}
|
}
|
||||||
|
|
||||||
void ZTexture::CalcHash()
|
void ZTexture::CalcHash()
|
||||||
|
|
|
@ -54,6 +54,7 @@ public:
|
||||||
ZTexture(ZFile* nParent);
|
ZTexture(ZFile* nParent);
|
||||||
|
|
||||||
bool isPalette = false;
|
bool isPalette = false;
|
||||||
|
bool dWordAligned = true;
|
||||||
|
|
||||||
void ExtractFromBinary(uint32_t nRawDataIndex, int32_t nWidth, int32_t nHeight,
|
void ExtractFromBinary(uint32_t nRawDataIndex, int32_t nWidth, int32_t nHeight,
|
||||||
TextureType nType, bool nIsPalette);
|
TextureType nType, bool nIsPalette);
|
||||||
|
|
|
@ -82,5 +82,5 @@ std::string ZVtx::GetExternalExtension() const
|
||||||
|
|
||||||
DeclarationAlignment ZVtx::GetDeclarationAlignment() const
|
DeclarationAlignment ZVtx::GetDeclarationAlignment() const
|
||||||
{
|
{
|
||||||
return DeclarationAlignment::Align16;
|
return DeclarationAlignment::Align8;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Only used for standalone compilation, usually inherits these from the main makefile
|
# Only used for standalone compilation, usually inherits these from the main makefile
|
||||||
CXXFLAGS ?= -Wall -Wextra -O2 -g -std=c++17
|
CXXFLAGS ?= -Wall -Wextra -O2 -g -std=c++17
|
||||||
|
|
||||||
SRC_DIRS := $(shell find -type d -not -path "*build*")
|
SRC_DIRS := $(shell find . -type d -not -path "*build*")
|
||||||
CPP_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
|
CPP_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.cpp))
|
||||||
H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h))
|
H_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.h))
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,6 @@ public:
|
||||||
static bool IEquals(const std::string& a, const std::string& b)
|
static bool IEquals(const std::string& a, const std::string& b)
|
||||||
{
|
{
|
||||||
return std::equal(a.begin(), a.end(), b.begin(), b.end(),
|
return std::equal(a.begin(), a.end(), b.begin(), b.end(),
|
||||||
[](char a, char b) { return tolower(a) == tolower(b); });
|
[](char a, char b) { return tolower(a) == tolower(b); });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,7 @@ This document aims to be a small reference of how to create a compatible xml fil
|
||||||
- [Basic XML](#basic-xml)
|
- [Basic XML](#basic-xml)
|
||||||
- [Resources types](#resources-types)
|
- [Resources types](#resources-types)
|
||||||
- [File](#file)
|
- [File](#file)
|
||||||
|
- [ExternalFile](#externalfile)
|
||||||
- [Texture](#texture)
|
- [Texture](#texture)
|
||||||
- [Background](#background)
|
- [Background](#background)
|
||||||
- [Blob](#blob)
|
- [Blob](#blob)
|
||||||
|
@ -33,6 +34,7 @@ This document aims to be a small reference of how to create a compatible xml fil
|
||||||
- [Array](#array)
|
- [Array](#array)
|
||||||
- [Path](#path)
|
- [Path](#path)
|
||||||
- [PlayerAnimationData](#playeranimationdata)
|
- [PlayerAnimationData](#playeranimationdata)
|
||||||
|
- [Pointer](#pointer)
|
||||||
|
|
||||||
## Basic XML
|
## Basic XML
|
||||||
|
|
||||||
|
@ -589,7 +591,7 @@ Vec3s D_04002040[24] = {
|
||||||
|
|
||||||
The `Array` element is special, because it needs an inner element to work. It will declare an array of its inner element.
|
The `Array` element is special, because it needs an inner element to work. It will declare an array of its inner element.
|
||||||
|
|
||||||
Currently, only [`Scalar`](#scalar), [`Vector`](#vector) and [`Vtx`](#vtx) support being wrapped in an array.
|
Currently, only [`Pointer`](#pointer), [`Scalar`](#scalar), [`Vector`](#vector) and [`Vtx`](#vtx) support being wrapped in an array.
|
||||||
|
|
||||||
- Example:
|
- Example:
|
||||||
|
|
||||||
|
@ -637,3 +639,24 @@ Allows the extraction of the specific data of the player animations which are fo
|
||||||
- `FrameCount`: Required. The length of the animation in frames. It must be a positive integer.
|
- `FrameCount`: Required. The length of the animation in frames. It must be a positive integer.
|
||||||
|
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
### Pointer
|
||||||
|
|
||||||
|
Allows the extraction of a variable that contains a pointer
|
||||||
|
|
||||||
|
- Example:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<Array Name="object_hanareyama_obj_DLArray_004638" Count="54" Offset="0x4638">
|
||||||
|
<Pointer Type="Gfx"/>
|
||||||
|
</Array>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Attributes:
|
||||||
|
|
||||||
|
- `Name`: Required.
|
||||||
|
- `Type`: Required. The type of the extracted pointer.
|
||||||
|
|
||||||
|
※ Can be wrapped in an [`Array`](#array) tag.
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
|
Loading…
Add table
Reference in a new issue