Compare commits

..

No commits in common. "develop" and "7.0.2" have entirely different histories.

11205 changed files with 694277 additions and 575435 deletions

View file

@ -1 +1 @@
libusb-dev libusb-1.0-0-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev nlohmann-json3-dev libtinyxml2-dev libspdlog-dev ninja-build libogg-dev libopus-dev opus-tools libopusfile-dev libvorbis-dev libespeak-ng-dev libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev ninja-build

View file

@ -1,21 +0,0 @@
name: clang-format
on: [pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
clang-format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Install clang-format
run: |
sudo apt-get update
sudo apt-get install -y clang-format-14
- name: Run clang-format
run: |
./run-clang-format.sh
git diff --exit-code

View file

@ -6,324 +6,311 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
generate-soh-otr: generate-soh-otr:
runs-on: ubuntu-22.04 runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }}
steps: steps:
- name: Git Checkout - uses: actions/checkout@v3
uses: actions/checkout@v4
with: with:
submodules: true submodules: true
- name: Configure ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
with: with:
save: ${{ github.ref_name == github.event.repository.default_branch }} key: ${{ runner.os }}-soh-otr-ccache
key: ${{ runner.os }}-otr-ccache-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-otr-ccache-${{ github.ref }}
${{ runner.os }}-otr-ccache
- name: Install dependencies - name: Install dependencies
if: ${{ !vars.LINUX_RUNNER }}
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) libzip-dev zipcmp zipmerge ziptool sudo apt-get install -y $(cat .github/workflows/apt-deps.txt)
- name: Restore Cached deps folder
uses: actions/cache/restore@v4
with:
key: ${{ runner.os }}-deps-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-deps-${{ github.ref }}-
${{ runner.os }}-deps-
path: deps
- name: Create deps folder
run: mkdir -p deps
- name: Install latest SDL - name: Install latest SDL
if: ${{ !vars.LINUX_RUNNER }}
run: | run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "deps/SDL2-2.30.3" ]; then wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz
wget https://github.com/libsdl-org/SDL/releases/download/release-2.30.3/SDL2-2.30.3.tar.gz tar -xzf SDL2-2.26.1.tar.gz
tar -xzf SDL2-2.30.3.tar.gz -C deps cd SDL2-2.26.1
fi ./configure
cd deps/SDL2-2.30.3
./configure --enable-hidapi-libusb
make -j 10 make -j 10
sudo make install sudo make install
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
- name: Install latest tinyxml2 - name: Install latest SDL_net
if: ${{ !vars.LINUX_RUNNER }}
run: | run: |
sudo apt-get remove libtinyxml2-dev
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "deps/tinyxml2-10.0.0" ]; then wget https://www.libsdl.org/projects/SDL_net/release/SDL2_net-2.2.0.tar.gz
wget https://github.com/leethomason/tinyxml2/archive/refs/tags/10.0.0.tar.gz tar -xzf SDL2_net-2.2.0.tar.gz
tar -xzf 10.0.0.tar.gz -C deps cd SDL2_net-2.2.0
fi ./configure
cd deps/tinyxml2-10.0.0 make -j 10
mkdir -p build
cd build
cmake ..
make
sudo make install sudo make install
- name: Generate soh.o2r sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
- name: Generate soh.otr
run: | run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release
cmake --build build-cmake --config Release --target GenerateSohOtr -j3 cmake --build build-cmake --config Release --target ZAPD
- name: Upload soh.o2r mkdir Extract
uses: actions/upload-artifact@v4 cp -r OTRExporter/assets/ ./Extract/assets
./build-cmake/ZAPD/ZAPD.out botr -se OTR --norom
- uses: actions/upload-artifact@v3
with: with:
name: soh.o2r name: soh.otr
path: soh.o2r path: soh.otr
retention-days: 3 retention-days: 1
build-macos: build-macos:
needs: generate-soh-otr needs: generate-soh-otr
runs-on: macos-14 runs-on: ${{ (vars.MAC_RUNNER && fromJSON(vars.MAC_RUNNER)) || 'macos-12' }}
steps: steps:
- name: Git Checkout - uses: actions/checkout@v3
uses: actions/checkout@v4
with: with:
submodules: true submodules: true
- name: Configure ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
with: with:
create-symlink: true key: ${{ runner.os }}-ccache
save: ${{ github.ref_name == github.event.repository.default_branch }}
key: ${{ runner.os }}-14-ccache-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-14-ccache-${{ github.ref }}
${{ runner.os }}-14-ccache
# Needed to apply sudo for macports cache restore
- name: Install gtar wrapper - name: Install gtar wrapper
if: ${{ !vars.MAC_RUNNER }}
run: | run: |
sudo mv /opt/homebrew/bin/gtar /opt/homebrew/bin/gtar.orig sudo mv /usr/local/bin/gtar /usr/local/bin/gtar.orig
sudo cp .github/workflows/gtar /opt/homebrew/bin/gtar sudo cp .github/workflows//gtar /usr/local/bin/gtar
sudo chmod +x /opt/homebrew/bin/gtar sudo chmod +x /usr/local/bin/gtar
- name: Restore Cached MacPorts - name: Cache MacPorts
id: restore-cache-macports id: cache-macports
uses: actions/cache/restore@v4 if: ${{ !vars.MAC_RUNNER }}
uses: actions/cache@v2
with: with:
key: ${{ runner.os }}-14-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-14-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }}-
${{ runner.os }}-14-macports-
path: /opt/local/ path: /opt/local/
# Updated PATH applies to the next step and onwards key: ${{ runner.os }}-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }}
restore-keys: |
${{ runner.os }}-macports-
- name: Install MacPorts (if necessary) - name: Install MacPorts (if necessary)
if: ${{ !vars.MAC_RUNNER }}
run: | run: |
if command -v /opt/local/bin/port 2>&1 >/dev/null; then if [ -d /opt/local/ ]; then
echo "MacPorts already installed" echo "MacPorts already installed"
else else
echo "Installing MacPorts" wget https://github.com/macports/macports-base/releases/download/v2.7.2/MacPorts-2.7.2-12-Monterey.pkg
wget https://github.com/macports/macports-base/releases/download/v2.9.3/MacPorts-2.9.3-14-Sonoma.pkg sudo installer -pkg ./MacPorts-2.7.2-12-Monterey.pkg -target /
sudo installer -pkg ./MacPorts-2.9.3-14-Sonoma.pkg -target /
fi fi
echo "/opt/local/bin:/opt/local/sbin" >> "$GITHUB_PATH" echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH
- name: Install dependencies - name: Install dependencies
if: ${{ !vars.MAC_RUNNER }}
run: | run: |
brew uninstall --ignore-dependencies libpng brew uninstall --ignore-dependencies libpng
sudo port install $(cat .github/workflows/macports-deps.txt) sudo port install $(cat .github/workflows/macports-deps.txt)
brew install ninja brew install ninja
- name: Download soh.o2r - name: Download soh.otr
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: soh.o2r name: soh.otr
path: build-cmake/soh
- name: Build SoH - name: Build SoH
run: | run: |
export PATH="/usr/lib/ccache:/opt/homebrew/opt/ccache/libexec:/usr/local/opt/ccache/libexec:$PATH" export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DBUILD_REMOTE_CONTROL=1 cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
cmake --build build-cmake --config Release --parallel 10 cmake --build build-cmake --config Release --parallel 10
mv soh.otr build-cmake/soh
(cd build-cmake && cpack) (cd build-cmake && cpack)
mv _packages/*.dmg SoH.dmg mv _packages/*.dmg SoH.dmg
mv README.md readme.txt mv README.md readme.txt
- name: Upload build - name: Upload build
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: soh-mac name: soh-mac
path: | path: |
SoH.dmg SoH.dmg
readme.txt readme.txt
- name: Save Cache MacPorts
if: ${{ github.ref_name == github.event.repository.default_branch }}
uses: actions/cache/save@v4
with:
key: ${{ steps.restore-cache-macports.outputs.cache-primary-key }}
path: /opt/local/
build-linux: build-linux:
needs: generate-soh-otr needs: generate-soh-otr
runs-on: ubuntu-22.04 strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-20.04
gcc: 10
archive-suffix: compatibility
- os: ubuntu-22.04
gcc: 12
archive-suffix: performance
runs-on: ${{ (matrix.os == 'ubuntu-20.04' && ((vars.LINUX_COMPATIBILITY_RUNNER && fromJSON(vars.LINUX_COMPATIBILITY_RUNNER)) || matrix.os)) || (matrix.os == 'ubuntu-22.04' && ((vars.LINUX_PERFORMANCE_RUNNER && fromJSON(vars.LINUX_PERFORMANCE_RUNNER)) || matrix.os)) }}
steps: steps:
- name: Git Checkout - uses: actions/checkout@v3
uses: actions/checkout@v4
with: with:
submodules: true submodules: true
- name: Install dependencies - name: Install dependencies
if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }}
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) sudo apt-get install -y $(cat .github/workflows/apt-deps.txt)
- name: Configure ccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
with: with:
save: ${{ github.ref_name == github.event.repository.default_branch }} key: ${{ matrix.os }}-ccache
key: ${{ runner.os }}-ccache-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-ccache-${{ github.ref }}
${{ runner.os }}-ccache
- name: Restore Cached deps folder
id: restore-cache-deps
uses: actions/cache/restore@v4
with:
key: ${{ runner.os }}-deps-${{ github.ref }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-deps-${{ github.ref }}-
${{ runner.os }}-deps-
path: deps
- name: Create deps folder
run: mkdir -p deps
- name: Install latest SDL - name: Install latest SDL
if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }}
run: | run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "deps/SDL2-2.30.3" ]; then wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz
wget https://github.com/libsdl-org/SDL/releases/download/release-2.30.3/SDL2-2.30.3.tar.gz tar -xzf SDL2-2.26.1.tar.gz
tar -xzf SDL2-2.30.3.tar.gz -C deps cd SDL2-2.26.1
fi
cd deps/SDL2-2.30.3
./configure --enable-hidapi-libusb
make -j 10
sudo make install
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
- name: Install latest SDL_net
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "deps/SDL2_net-2.2.0" ]; then
wget https://www.libsdl.org/projects/SDL_net/release/SDL2_net-2.2.0.tar.gz
tar -xzf SDL2_net-2.2.0.tar.gz -C deps
fi
cd deps/SDL2_net-2.2.0
./configure ./configure
make -j 10 make -j 10
sudo make install sudo make install
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
- name: Install latest tinyxml2 - name: Install latest SDL_net
run: | if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }}
sudo apt-get remove libtinyxml2-dev
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "deps/tinyxml2-10.0.0" ]; then
wget https://github.com/leethomason/tinyxml2/archive/refs/tags/10.0.0.tar.gz
tar -xzf 10.0.0.tar.gz -C deps
fi
cd deps/tinyxml2-10.0.0
mkdir -p build
cd build
cmake ..
make
sudo make install
- name: Install libzip without crypto
run: | run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
if [ ! -d "deps/libzip-1.10.1" ]; then wget https://www.libsdl.org/projects/SDL_net/release/SDL2_net-2.2.0.tar.gz
wget https://github.com/nih-at/libzip/releases/download/v1.10.1/libzip-1.10.1.tar.gz tar -xzf SDL2_net-2.2.0.tar.gz
tar -xzf libzip-1.10.1.tar.gz -C deps cd SDL2_net-2.2.0
fi ./configure
cd deps/libzip-1.10.1 make -j 10
mkdir -p build
cd build
cmake .. -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_MBEDTLS=OFF -DENABLE_OPENSSL=OFF
make
sudo make install sudo make install
sudo cp -av /usr/local/lib/libzip* /lib/x86_64-linux-gnu/ sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
- name: Download soh.o2r - name: Download soh.otr
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: soh.o2r name: soh.otr
path: build-cmake/soh
- name: Build SoH - name: Build SoH
run: | run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_REMOTE_CONTROL=1 cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release
cmake --build build-cmake --config Release -j3 cmake --build build-cmake --config Release -j3
(cd build-cmake && cpack -G External) (cd build-cmake && cpack -G External)
mv README.md readme.txt mv README.md readme.txt
mv build-cmake/*.appimage soh.appimage mv build-cmake/*.appimage soh.appimage
env: env:
CC: gcc-12 CC: gcc-${{ matrix.gcc }}
CXX: g++-12 CXX: g++-${{ matrix.gcc }}
- name: Upload build - name: Upload build
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: soh-linux name: soh-linux-${{ matrix.archive-suffix }}
path: | path: |
soh.appimage soh.appimage
readme.txt readme.txt
- name: Save Cache deps folder build-switch:
if: ${{ github.ref_name == github.event.repository.default_branch }}
uses: actions/cache/save@v4
with:
key: ${{ steps.restore-cache-deps.outputs.cache-primary-key }}
path: deps
build-windows:
needs: generate-soh-otr needs: generate-soh-otr
runs-on: windows-latest runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }}
container:
image: devkitpro/devkita64:latest
steps: steps:
- name: Install dependencies - name: Install dependencies
run: | run: |
choco install ninja -y sudo apt-get update
Remove-Item -Path "C:\ProgramData\Chocolatey\bin\ccache.exe" -Force -ErrorAction SilentlyContinue sudo apt-get install -y ninja-build
- name: Git Checkout - name: Fix dubious ownership error
uses: actions/checkout@v4 if: ${{ vars.LINUX_RUNNER }}
run: git config --global --add safe.directory '*'
- uses: actions/checkout@v3
with: with:
submodules: true submodules: true
- name: Configure sccache - name: ccache
uses: hendrikmuhs/ccache-action@v1.2 uses: hendrikmuhs/ccache-action@v1.2
with: with:
variant: sccache key: ${{ runner.os }}-switch-ccache
max-size: "2G" - name: Build SoH
evict-old-files: job run: |
save: ${{ github.ref_name == github.event.repository.default_branch }} cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache
key: ${{ runner.os }}-ccache-${{ github.ref }}-${{ github.sha }} cmake --build build-switch --target soh_nro -j3
restore-keys: |
${{ runner.os }}-ccache-${{ github.ref }} mv build-switch/soh/*.nro soh.nro
${{ runner.os }}-ccache mv README.md readme.txt
- name: Restore Cached VCPKG folder - name: Download soh.otr
id: restore-cache-vcpkg uses: actions/download-artifact@v3
uses: actions/cache/restore@v4 with:
with: name: soh.otr
key: ${{ runner.os }}-vcpkg-${{ github.ref }}-${{ github.sha }} - name: Upload build
restore-keys: | uses: actions/upload-artifact@v3
${{ runner.os }}-vcpkg-${{ github.ref }}- with:
${{ runner.os }}-vcpkg- name: soh-switch
path: vcpkg path: |
- name: Configure Developer Command Prompt soh.nro
uses: ilammy/msvc-dev-cmd@v1 soh.otr
- name: Download soh.o2r readme.txt
uses: actions/download-artifact@v4 # build-wiiu:
with: # needs: generate-soh-otr
name: soh.o2r # runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }}
path: build-windows/soh # container:
# image: devkitpro/devkitppc:latest
# steps:
# - name: Install dependencies
# if: ${{ !vars.LINUX_RUNNER }}
# run: |
# sudo apt-get update
# sudo apt-get install -y ninja-build
# - uses: actions/checkout@v3
# with:
# submodules: true
# - name: ccache
# uses: hendrikmuhs/ccache-action@v1.2
# with:
# key: ${{ runner.os }}-wiiu-ccache
# - name: Build SoH
# run: |
# cmake -H. -Bbuild-wiiu -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache
# cmake --build build-wiiu --target soh_wuhb --config Release -j3
# mv build-wiiu/soh/*.rpx soh.rpx
# mv build-wiiu/soh/*.wuhb soh.wuhb
# mv README.md readme.txt
# env:
# DEVKITPRO: /opt/devkitpro
# DEVKITPPC: /opt/devkitpro/devkitPPC
# - name: Download soh.otr
# uses: actions/download-artifact@v3
# with:
# name: soh.otr
# - name: Upload build
# uses: actions/upload-artifact@v3
# with:
# name: soh-wiiu
# path: |
# soh.rpx
# soh.wuhb
# soh.otr
# readme.txt
build-windows:
needs: generate-soh-otr
runs-on: ${{ (vars.WINDOWS_RUNNER && fromJSON(vars.WINDOWS_RUNNER)) || 'windows-latest' }}
steps:
- name: Install dependencies
if: ${{ !vars.WINDOWS_RUNNER }}
run: |
choco install ninja
Remove-Item -Path "C:\ProgramData\Chocolatey\bin\ccache.exe" -Force
- uses: actions/checkout@v3
with:
submodules: true
- name: ccache
uses: dcvz/ccache-action@27b9f33213c0079872f064f6b6ba0233dfa16ba2
with:
key: ${{ runner.os }}-ccache
- uses: ilammy/msvc-dev-cmd@v1
- name: Build SoH - name: Build SoH
env:
VCPKG_ROOT: ${{github.workspace}}/vcpkg
run: | run: |
set $env:PATH="$env:USERPROFILE/.cargo/bin;$env:PATH" set $env:PATH="$env:USERPROFILE/.cargo/bin;$env:PATH"
cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DBUILD_REMOTE_CONTROL=1 cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake --build build-windows --config Release --parallel 10 cmake --build build-windows --config Release --parallel 10
(cd build-windows && cpack) mkdir soh-windows
cd .. mv ./x64/Release/soh.exe ./soh-windows/soh.exe
mv _packages/*.zip _packages/soh-windows.zip mkdir soh-windows/debug
- name: Unzip package mkdir soh-windows/mods
run: Expand-Archive -Path _packages/soh-windows.zip -DestinationPath soh-windows New-Item soh-windows/mods/custom_otr_files_go_here.txt -type file
mv ./x64/Release/soh.pdb ./soh-windows/debug/soh.pdb
mv ./README.md ./soh-windows/readme.txt
mv ./build-windows/gamecontrollerdb.txt ./soh-windows/gamecontrollerdb.txt
mv ./build-windows/OTRGui/assets ./soh-windows
mv ./build-windows/ZAPD/ZAPD.exe ./soh-windows/assets/extractor/ZAPD.exe
- name: Download soh.otr
uses: actions/download-artifact@v3
with:
name: soh.otr
path: soh-windows
- name: Upload build - name: Upload build
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: soh-windows name: soh-windows
path: soh-windows path: soh-windows
- name: Save Cache VCPKG folder
if: ${{ github.ref_name == github.event.repository.default_branch }}
uses: actions/cache/save@v4
with:
key: ${{ steps.restore-cache-vcpkg.outputs.cache-primary-key }}
path: vcpkg

View file

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec sudo /opt/homebrew/bin/gtar.orig "$@" exec sudo /usr/local/bin/gtar.orig "$@"

View file

@ -1 +1 @@
libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal libzip +universal nlohmann-json +universal tinyxml2 +universal libogg +universal libopus +universal opusfile +universal libvorbis +universal libsdl2 +universal libpng +universal glew +universal

View file

@ -12,7 +12,7 @@ jobs:
if: ${{ github.event.workflow_run.event == 'pull_request' }} if: ${{ github.event.workflow_run.event == 'pull_request' }}
steps: steps:
- id: 'pr-number' - id: 'pr-number'
uses: actions/github-script@v7 uses: actions/github-script@v6
with: with:
result-encoding: string result-encoding: string
script: | script: |
@ -20,9 +20,8 @@ jobs:
const pullHeadSHA = '${{github.event.workflow_run.head_sha}}'; const pullHeadSHA = '${{github.event.workflow_run.head_sha}}';
const pullUserId = ${{github.event.sender.id}}; const pullUserId = ${{github.event.sender.id}};
const prNumber = await (async () => { const prNumber = await (async () => {
for await (const { data } of github.paginate.iterator( const pulls = await github.rest.pulls.list({owner, repo});
github.rest.pulls.list, { owner, repo } for await (const {data} of github.paginate.iterator(pulls)) {
)) {
for (const pull of data) { for (const pull of data) {
if (pull.head.sha === pullHeadSHA && pull.user.id === pullUserId) { if (pull.head.sha === pullHeadSHA && pull.user.id === pullUserId) {
return pull.number; return pull.number;
@ -37,7 +36,7 @@ jobs:
return prNumber; return prNumber;
- id: 'artifacts-text' - id: 'artifacts-text'
uses: actions/github-script@v7 uses: actions/github-script@v6
with: with:
result-encoding: string result-encoding: string
script: | script: |
@ -48,13 +47,13 @@ jobs:
}); });
return allArtifacts.data.artifacts.reduce((acc, item) => { return allArtifacts.data.artifacts.reduce((acc, item) => {
if (item.name === "soh.o2r") return acc; if (item.name === "assets") return acc;
acc += ` acc += `
- [${item.name}.zip](https://nightly.link/${context.repo.owner}/${context.repo.repo}/actions/artifacts/${item.id}.zip)`; - [${item.name}.zip](https://nightly.link/${context.repo.owner}/${context.repo.repo}/actions/artifacts/${item.id}.zip)`;
return acc; return acc;
}, '### Build Artifacts'); }, '### Build Artifacts');
- id: 'add-to-pr' - id: 'add-to-pr'
uses: garrettjoecox/pr-section@4.0.0 uses: garrettjoecox/pr-section@3.1.0
with: with:
repo-token: '${{ secrets.GITHUB_TOKEN }}' repo-token: '${{ secrets.GITHUB_TOKEN }}'
pr-number: ${{ steps.pr-number.outputs.result }} pr-number: ${{ steps.pr-number.outputs.result }}

View file

@ -1,72 +0,0 @@
name: test-builds-on-distros
on:
workflow_dispatch: # by request
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
strategy:
matrix:
image: ["archlinux:base", "opensuse/tumbleweed:latest", "ubuntu:mantic", "debian:bookworm", "fedora:39"]
cc: ["gcc", "clang"]
include:
- cxx: g++
cc: gcc
- cxx: clang++
cc: clang
runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }}
container:
image: ${{ matrix.image }}
steps:
- name: Install dependencies (pacman)
if: ${{ matrix.image == 'archlinux:base' }}
run: |
echo arch
echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net
pacman -Syu --noconfirm
pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net
- name: Install dependencies (dnf)
if: ${{ matrix.image == 'fedora:39' }}
run: |
echo fedora
echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} wget git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools tinyxml2-devel spdlog-devel
dnf -y upgrade
dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} wget git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools tinyxml2-devel spdlog-devel
- name: Install dependencies (apt)
if: ${{ matrix.image == 'ubuntu:mantic' || matrix.image == 'debian:bookworm' }}
run: |
echo debian based
echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libopengl-dev
apt-get update
apt-get -y full-upgrade
apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libopengl-dev
- name: Install dependencies (zypper)
if: ${{ matrix.image == 'opensuse/tumbleweed:latest' }}
run: |
echo openSUSE
echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel
zypper --non-interactive dup
zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel
- name: Install latest nlohmann
if: ${{ matrix.image == 'fedora:39' }}
run: |
wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz
tar -xzvf v3.11.3.tar.gz
cd json-3.11.3
mkdir build
cd build
cmake ..
make
sudo make install
- uses: actions/checkout@v4
with:
submodules: true
- name: Build SoH
run: |
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DBUILD_REMOTE_CONTROL=1
cmake --build build-cmake --config Release -j3
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}

14
.gitignore vendored
View file

@ -4,9 +4,7 @@ __pycache__/
.DS_Store .DS_Store
# Text editor remnants # Text editor remnants
.vscode/* .vscode/
!.vscode/tasks.json
.vs/ .vs/
.idea/ .idea/
cmake-build-** cmake-build-**
@ -43,7 +41,6 @@ tools/asmsplitter/c/*
ctx.c ctx.c
tools/*dSYM/ tools/*dSYM/
graphs/ graphs/
.netcoredbg_hist
# Assets # Assets
*.png *.png
@ -402,6 +399,7 @@ ASALocalRun/
lib/libgfxd/libgfxd.a lib/libgfxd/libgfxd.a
ExporterTest/ExporterTest.a ExporterTest/ExporterTest.a
ZAPDUtils/ZAPDUtils.a ZAPDUtils/ZAPDUtils.a
.vscode/
build/ build/
external/ external/
ZAPDUtils/build/ ZAPDUtils/build/
@ -412,7 +410,6 @@ ReleaseObj/*
.tags .tags
tags tags
*.otr *.otr
*.o2r
*.sav *.sav
shipofharkinian.ini shipofharkinian.ini
shipofharkinian.json shipofharkinian.json
@ -451,10 +448,5 @@ _packages
*/extract_assets_cmake* */extract_assets_cmake*
/build* /build*
soh/src/boot/build.c soh/build.c
soh/properties.h soh/properties.h
# Tools
/clang-format
/clang-format.exe
*.o2r

6
.gitmodules vendored
View file

@ -1,9 +1,3 @@
[submodule "libultraship"] [submodule "libultraship"]
path = libultraship path = libultraship
url = https://github.com/kenix3/libultraship.git url = https://github.com/kenix3/libultraship.git
[submodule "ZAPDTR"]
path = ZAPDTR
url = https://github.com/harbourmasters/ZAPDTR
[submodule "OTRExporter"]
path = OTRExporter
url = https://github.com/harbourmasters/OTRExporter

61
.vscode/tasks.json vendored
View file

@ -1,61 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Setup CMake Project",
"type": "shell",
"command": "cmake",
"args": [
"-S",
".",
"-B",
"build/x64",
"-G",
"Visual Studio 17 2022",
"-T",
"v143",
"-A",
"x64"
],
"group": "build",
"problemMatcher": []
},
{
"label": "Generate SOH OTR",
"type": "shell",
"command": "cmake",
"args": [
"--build",
"./build/x64",
"--target",
"GenerateSohOtr"
],
"group": "build",
"problemMatcher": []
},
{
"label": "Build Project",
"type": "shell",
"command": "cmake",
"args": [
"--build",
"./build/x64"
],
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": ["Generate SOH OTR"],
"problemMatcher": []
},
{
"label": "Build All",
"dependsOrder": "sequence",
"dependsOn": [
"Setup CMake Project",
"Generate SOH OTR",
"Build Project"
]
}
]
}

View file

@ -8,9 +8,5 @@ if(MSVC)
set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL") set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
set_config_specific_property("DEFAULT_CXX_EXCEPTION_HANDLING" "/EHsc") set_config_specific_property("DEFAULT_CXX_EXCEPTION_HANDLING" "/EHsc")
if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache") set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi")
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Z7")
else()
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi")
endif()
endif() endif()

View file

@ -1,61 +0,0 @@
# - Find ogg
# Find the native ogg includes and libraries
#
# OGG_INCLUDE_DIRS - where to find ogg.h, etc.
# OGG_LIBRARIES - List of libraries when using ogg.
# OGG_FOUND - True if ogg found.
if (OGG_INCLUDE_DIR)
# Already in cache, be silent
set(OGG_FIND_QUIETLY TRUE)
endif ()
find_package (PkgConfig QUIET)
pkg_check_modules (PC_OGG QUIET ogg>=1.3.0)
set (OGG_VERSION ${PC_OGG_VERSION})
find_path (OGG_INCLUDE_DIR ogg/ogg.h
HINTS
${PC_OGG_INCLUDEDIR}
${PC_OGG_INCLUDE_DIRS}
${OGG_ROOT}
)
# MSVC built ogg may be named ogg_static.
# The provided project files name the library with the lib prefix.
find_library (OGG_LIBRARY
NAMES
ogg
ogg_static
libogg
libogg_static
HINTS
${PC_OGG_LIBDIR}
${PC_OGG_LIBRARY_DIRS}
${OGG_ROOT}
)
# Handle the QUIETLY and REQUIRED arguments and set OGG_FOUND
# to TRUE if all listed variables are TRUE.
include (FindPackageHandleStandardArgs)
find_package_handle_standard_args (Ogg
REQUIRED_VARS
OGG_LIBRARY
OGG_INCLUDE_DIR
VERSION_VAR
OGG_VERSION
)
if (OGG_FOUND)
set (OGG_LIBRARIES ${OGG_LIBRARY})
set (OGG_INCLUDE_DIRS ${OGG_INCLUDE_DIR})
if(NOT TARGET Ogg::ogg)
add_library(Ogg::ogg UNKNOWN IMPORTED)
set_target_properties(Ogg::ogg PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${OGG_INCLUDE_DIRS}"
IMPORTED_LOCATION "${OGG_LIBRARIES}"
)
endif ()
endif ()
mark_as_advanced (OGG_INCLUDE_DIR OGG_LIBRARY)

View file

@ -1,44 +0,0 @@
# - FindOpus.cmake
# Find the native opus includes and libraries
#
# OPUS_INCLUDE_DIRS - where to find opus/opus.h, etc.
# OPUS_LIBRARIES - List of libraries when using libopus(file).
# OPUS_FOUND - True if libopus found.
if(OPUS_INCLUDE_DIR AND OPUS_LIBRARY AND OPUSFILE_LIBRARY)
# Already in cache, be silent
set(OPUS_FIND_QUIETLY TRUE)
endif(OPUS_INCLUDE_DIR AND OPUS_LIBRARY AND OPUSFILE_LIBRARY)
find_path(OPUS_INCLUDE_DIR
NAMES opusfile.h
PATH_SUFFIXES opus
)
# MSVC built opus may be named opus_static
# The provided project files name the library with the lib prefix.
find_library(OPUS_LIBRARY
NAMES opus opus_static libopus libopus_static
)
#find_library(OPUSFILE_LIBRARY
# NAMES opusfile opusfile_static libopusfile libopusfile_static
#)
# Handle the QUIETLY and REQUIRED arguments and set OPUS_FOUND
# to TRUE if all listed variables are TRUE.
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Opus DEFAULT_MSG
OPUS_LIBRARY OPUS_INCLUDE_DIR
)
if(OPUS_FOUND)
set(OPUS_LIBRARIES ${OPUS_LIBRARY})
set(OPUS_INCLUDE_DIRS ${OPUS_INCLUDE_DIR})
if(NOT TARGET Opus::opus)
add_library(Opus::opus UNKNOWN IMPORTED)
set_target_properties(Opus::opus PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${OPUS_INCLUDE_DIRS}"
IMPORTED_LOCATION "${OPUS_LIBRARIES}"
)
endif()
endif(OPUS_FOUND)

View file

@ -1,55 +0,0 @@
# FindOpusFile.cmake
# Locate the libopusfile library and its dependencies (libopus and libogg).
# Defines the following variables on success:
# OPUSFILE_FOUND - Indicates if opusfile was found
# OPUSFILE_INCLUDE_DIR - Directory containing opusfile.h
# OPUSFILE_LIBRARY - Path to the opusfile library
# OPUSFILE_LIBRARIES - Full list of libraries to link (opusfile, opus, ogg)
# Search for the OpusFile header
find_path(OPUSFILE_INCLUDE_DIR
NAMES opusfile.h
PATHS /usr/include/opus /usr/local/include/opus /opt/local/include/opus /opt/homebrew/include/opus
DOC "Directory where opusfile.h is located"
)
# Search for the OpusFile library
find_library(OPUSFILE_LIBRARY
NAMES opusfile
DOC "Path to the libopusfile library"
)
# Search for the Opus library (dependency of OpusFile)
find_library(OPUS_LIBRARY
NAMES opus
DOC "Path to the libopus library (dependency of libopusfile)"
)
# Search for the Ogg library (dependency of OpusFile)
find_library(OGG_LIBRARY
NAMES ogg
DOC "Path to the libogg library (dependency of libopusfile)"
)
# Check if all required components are found
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpusFile
REQUIRED_VARS OPUSFILE_LIBRARY OPUSFILE_INCLUDE_DIR OPUS_LIBRARY OGG_LIBRARY
VERSION_VAR OPUSFILE_VERSION
)
# Define an imported target if everything is found
if (OPUSFILE_FOUND)
add_library(Opusfile::Opusfile INTERFACE IMPORTED)
set_target_properties(Opusfile::Opusfile PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${OPUSFILE_INCLUDE_DIR}"
INTERFACE_LINK_LIBRARIES "${OPUSFILE_LIBRARY};${OPUS_LIBRARY};${OGG_LIBRARY}"
)
# Optionally expose the include and libraries separately
set(OPUSFILE_LIBRARIES ${OPUSFILE_LIBRARY} ${OPUS_LIBRARY} ${OGG_LIBRARY})
set(OPUSFILE_INCLUDE_DIRS ${OPUSFILE_INCLUDE_DIR})
else()
set(OPUSFILE_FOUND FALSE)
endif()

View file

@ -1,210 +0,0 @@
#[=======================================================================[.rst:
FindVorbis
----------
Finds the native vorbis, vorbisenc amd vorbisfile includes and libraries.
Imported Targets
^^^^^^^^^^^^^^^^
This module provides the following imported targets, if found:
``Vorbis::vorbis``
The Vorbis library
``Vorbis::vorbisenc``
The VorbisEnc library
``Vorbis::vorbisfile``
The VorbisFile library
Result Variables
^^^^^^^^^^^^^^^^
This will define the following variables:
``Vorbis_Vorbis_INCLUDE_DIRS``
List of include directories when using vorbis.
``Vorbis_Enc_INCLUDE_DIRS``
List of include directories when using vorbisenc.
``Vorbis_File_INCLUDE_DIRS``
List of include directories when using vorbisfile.
``Vorbis_Vorbis_LIBRARIES``
List of libraries when using vorbis.
``Vorbis_Enc_LIBRARIES``
List of libraries when using vorbisenc.
``Vorbis_File_LIBRARIES``
List of libraries when using vorbisfile.
``Vorbis_FOUND``
True if vorbis and requested components found.
``Vorbis_Vorbis_FOUND``
True if vorbis found.
``Vorbis_Enc_FOUND``
True if vorbisenc found.
``Vorbis_Enc_FOUND``
True if vorbisfile found.
Cache variables
^^^^^^^^^^^^^^^
The following cache variables may also be set:
``Vorbis_Vorbis_INCLUDE_DIR``
The directory containing ``vorbis/vorbis.h``.
``Vorbis_Enc_INCLUDE_DIR``
The directory containing ``vorbis/vorbisenc.h``.
``Vorbis_File_INCLUDE_DIR``
The directory containing ``vorbis/vorbisenc.h``.
``Vorbis_Vorbis_LIBRARY``
The path to the vorbis library.
``Vorbis_Enc_LIBRARY``
The path to the vorbisenc library.
``Vorbis_File_LIBRARY``
The path to the vorbisfile library.
Hints
^^^^^
A user may set ``Vorbis_ROOT`` to a vorbis installation root to tell this module where to look.
#]=======================================================================]
if (Vorbis_Vorbis_INCLUDE_DIR)
# Already in cache, be silent
set (Vorbis_FIND_QUIETLY TRUE)
endif ()
set (Vorbis_Vorbis_FIND_QUIETLY TRUE)
set (Vorbis_Enc_FIND_QUIETLY TRUE)
set (Vorbis_File_FIND_QUIETLY TRUE)
find_package (Ogg QUIET)
find_package (PkgConfig QUIET)
pkg_check_modules (PC_Vorbis_Vorbis QUIET vorbis)
pkg_check_modules (PC_Vorbis_Enc QUIET vorbisenc)
pkg_check_modules (PC_Vorbis_File QUIET vorbisfile)
set (Vorbis_VERSION ${PC_Vorbis_Vorbis_VERSION})
find_path (Vorbis_Vorbis_INCLUDE_DIR vorbis/codec.h
HINTS
${PC_Vorbis_Vorbis_INCLUDEDIR}
${PC_Vorbis_Vorbis_INCLUDE_DIRS}
${Vorbis_ROOT}
)
find_path (Vorbis_Enc_INCLUDE_DIR vorbis/vorbisenc.h
HINTS
${PC_Vorbis_Enc_INCLUDEDIR}
${PC_Vorbis_Enc_INCLUDE_DIRS}
${Vorbis_ROOT}
)
find_path (Vorbis_File_INCLUDE_DIR vorbis/vorbisfile.h
HINTS
${PC_Vorbis_File_INCLUDEDIR}
${PC_Vorbis_File_INCLUDE_DIRS}
${Vorbis_ROOT}
)
find_library (Vorbis_Vorbis_LIBRARY
NAMES
vorbis
vorbis_static
libvorbis
libvorbis_static
HINTS
${PC_Vorbis_Vorbis_LIBDIR}
${PC_Vorbis_Vorbis_LIBRARY_DIRS}
${Vorbis_ROOT}
)
find_library (Vorbis_Enc_LIBRARY
NAMES
vorbisenc
vorbisenc_static
libvorbisenc
libvorbisenc_static
HINTS
${PC_Vorbis_Enc_LIBDIR}
${PC_Vorbis_Enc_LIBRARY_DIRS}
${Vorbis_ROOT}
)
find_library (Vorbis_File_LIBRARY
NAMES
vorbisfile
vorbisfile_static
libvorbisfile
libvorbisfile_static
HINTS
${PC_Vorbis_File_LIBDIR}
${PC_Vorbis_File_LIBRARY_DIRS}
${Vorbis_ROOT}
)
include (FindPackageHandleStandardArgs)
if (Vorbis_Vorbis_LIBRARY AND Vorbis_Vorbis_INCLUDE_DIR AND Ogg_FOUND)
set (Vorbis_Vorbis_FOUND TRUE)
endif ()
if (Vorbis_Enc_LIBRARY AND Vorbis_Enc_INCLUDE_DIR AND Vorbis_Vorbis_FOUND)
set (Vorbis_Enc_FOUND TRUE)
endif ()
if (Vorbis_Vorbis_FOUND AND Vorbis_File_LIBRARY AND Vorbis_File_INCLUDE_DIR)
set (Vorbis_File_FOUND TRUE)
endif ()
find_package_handle_standard_args (Vorbis
REQUIRED_VARS
Vorbis_Vorbis_LIBRARY
Vorbis_Vorbis_INCLUDE_DIR
Ogg_FOUND
HANDLE_COMPONENTS
VERSION_VAR Vorbis_VERSION)
if (Vorbis_Vorbis_FOUND)
set (Vorbis_Vorbis_INCLUDE_DIRS ${VORBIS_INCLUDE_DIR})
set (Vorbis_Vorbis_LIBRARIES ${VORBIS_LIBRARY} ${OGG_LIBRARIES})
if (NOT TARGET Vorbis::vorbis)
add_library (Vorbis::vorbis UNKNOWN IMPORTED)
set_target_properties (Vorbis::vorbis PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_Vorbis_INCLUDE_DIR}"
IMPORTED_LOCATION "${Vorbis_Vorbis_LIBRARY}"
INTERFACE_LINK_LIBRARIES Ogg::ogg
)
endif ()
if (Vorbis_Enc_FOUND)
set (Vorbis_Enc_INCLUDE_DIRS ${Vorbis_Enc_INCLUDE_DIR})
set (Vorbis_Enc_LIBRARIES ${Vorbis_Enc_LIBRARY} ${Vorbis_Enc_LIBRARIES})
if (NOT TARGET Vorbis::vorbisenc)
add_library (Vorbis::vorbisenc UNKNOWN IMPORTED)
set_target_properties (Vorbis::vorbisenc PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_Enc_INCLUDE_DIR}"
IMPORTED_LOCATION "${Vorbis_Enc_LIBRARY}"
INTERFACE_LINK_LIBRARIES Vorbis::vorbis
)
endif ()
endif ()
if (Vorbis_File_FOUND)
set (Vorbis_File_INCLUDE_DIRS ${Vorbis_File_INCLUDE_DIR})
set (Vorbis_File_LIBRARIES ${Vorbis_File_LIBRARY} ${Vorbis_File_LIBRARIES})
if (NOT TARGET Vorbis::vorbisfile)
add_library (Vorbis::vorbisfile UNKNOWN IMPORTED)
set_target_properties (Vorbis::vorbisfile PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_File_INCLUDE_DIR}"
IMPORTED_LOCATION "${Vorbis_File_LIBRARY}"
INTERFACE_LINK_LIBRARIES Vorbis::vorbis
)
endif ()
endif ()
endif ()
mark_as_advanced (Vorbis_Vorbis_INCLUDE_DIR Vorbis_Vorbis_LIBRARY)
mark_as_advanced (Vorbis_Enc_INCLUDE_DIR Vorbis_Enc_LIBRARY)
mark_as_advanced (Vorbis_File_INCLUDE_DIR Vorbis_File_LIBRARY)

View file

@ -1,9 +1,9 @@
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
set(CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY 0) set(CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY 0)
set(CPACK_COMPONENTS_ALL "ship") set(CPACK_COMPONENTS_ALL "ship" "appimage")
if (CPACK_GENERATOR STREQUAL "External") if (NOT CPACK_GENERATOR STREQUAL "External")
list(APPEND CPACK_COMPONENTS_ALL "extractor" "appimage") list(REMOVE_ITEM CPACK_COMPONENTS_ALL "appimage")
endif() endif()
if (CPACK_GENERATOR MATCHES "DEB|RPM") if (CPACK_GENERATOR MATCHES "DEB|RPM")
@ -24,5 +24,7 @@ if (CPACK_GENERATOR MATCHES "Bundle")
set(CPACK_BUNDLE_NAME "soh") set(CPACK_BUNDLE_NAME "soh")
set(CPACK_BUNDLE_PLIST "macosx/Info.plist") set(CPACK_BUNDLE_PLIST "macosx/Info.plist")
set(CPACK_BUNDLE_ICON "macosx/soh.icns") set(CPACK_BUNDLE_ICON "macosx/soh.icns")
set(CPACK_BUNDLE_STARTUP_COMMAND "../soh/macosx/soh-macos.sh")
set(CPACK_BUNDLE_APPLE_CERT_APP "-") set(CPACK_BUNDLE_APPLE_CERT_APP "-")
endif() endif()

View file

@ -60,7 +60,7 @@ if (NOT LINUXDEPLOY_EXECUTABLE)
message(STATUS "Downloading linuxdeploy") message(STATUS "Downloading linuxdeploy")
set(LINUXDEPLOY_EXECUTABLE ${CPACK_PACKAGE_DIRECTORY}/linuxdeploy/linuxdeploy) set(LINUXDEPLOY_EXECUTABLE ${CPACK_PACKAGE_DIRECTORY}/linuxdeploy/linuxdeploy)
file(DOWNLOAD file(DOWNLOAD
https://github.com/linuxdeploy/linuxdeploy/releases/download/1-alpha-20240109-1/linuxdeploy-x86_64.AppImage https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
${LINUXDEPLOY_EXECUTABLE} ${LINUXDEPLOY_EXECUTABLE}
INACTIVITY_TIMEOUT 10 INACTIVITY_TIMEOUT 10
LOG ${CPACK_PACKAGE_DIRECTORY}/linuxdeploy/download.log LOG ${CPACK_PACKAGE_DIRECTORY}/linuxdeploy/download.log

View file

@ -1,20 +0,0 @@
set(CVAR_VSYNC_ENABLED "${CVAR_PREFIX_SETTING}.VsyncEnabled" CACHE STRING "")
set(CVAR_Z_FIGHTING_MODE "${CVAR_PREFIX_SETTING}.ZFightingMode" CACHE STRING "")
set(CVAR_INTERNAL_RESOLUTION "${CVAR_PREFIX_SETTING}.InternalResolution" CACHE STRING "")
set(CVAR_MSAA_VALUE "${CVAR_PREFIX_SETTING}.MSAAValue" CACHE STRING "")
set(CVAR_SDL_WINDOWED_FULLSCREEN "${CVAR_PREFIX_SETTING}.SdlWindowedFullscreen" CACHE STRING "")
set(CVAR_TEXTURE_FILTER "${CVAR_PREFIX_SETTING}.TextureFilter" CACHE STRING "")
set(CVAR_IMGUI_CONTROLLER_NAV "${CVAR_PREFIX_SETTING}.ControlNav" CACHE STRING "")
set(CVAR_CONSOLE_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.Console" CACHE STRING "")
set(CVAR_CONTROLLER_DISCONNECTED_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.ControllerDisconnected" CACHE STRING "")
set(CVAR_CONTROLLER_REORDERING_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.ControllerReordering" CACHE STRING "")
set(CVAR_GFX_DEBUGGER_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.GfxDebugger" CACHE STRING "")
set(CVAR_STATS_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.Stats" CACHE STRING "")
set(CVAR_ENABLE_MULTI_VIEWPORTS "${CVAR_PREFIX_SETTING}.EnableMultiViewports" CACHE STRING "")
set(CVAR_LOW_RES_MODE "${CVAR_PREFIX_SETTING}.LowResMode" CACHE STRING "")
set(CVAR_SIMULATED_INPUT_LAG "${CVAR_PREFIX_SETTING}.SimulatedInputLag" CACHE STRING "")
set(CVAR_GAME_OVERLAY_FONT "${CVAR_PREFIX_SETTING}.OverlayFont" CACHE STRING "")
set(CVAR_MENU_BAR_OPEN "${CVAR_PREFIX_SETTING}.OpenMenuBar" CACHE STRING "")
set(CVAR_PREFIX_CONTROLLERS "${CVAR_PREFIX_SETTING}.Controllers" CACHE STRING "")
set(CVAR_PREFIX_ADVANCED_RESOLUTION "${CVAR_PREFIX_SETTING}.AdvancedResolution" CACHE STRING "")
include("libultraship/cmake/cvars.cmake")

View file

@ -1,30 +0,0 @@
set(CVAR_PREFIX_RANDOMIZER_ENHANCEMENT "gRandoEnhancements")
set(CVAR_PREFIX_RANDOMIZER_SETTING "gRandoSettings")
set(CVAR_PREFIX_COSMETIC "gCosmetics")
set(CVAR_PREFIX_AUDIO "gAudioEditor")
set(CVAR_PREFIX_CHEAT "gCheats")
set(CVAR_PREFIX_ENHANCEMENT "gEnhancements")
set(CVAR_PREFIX_SETTING "gSettings")
set(CVAR_PREFIX_WINDOW "gOpenWindows")
set(CVAR_PREFIX_TRACKER "gTrackers")
set(CVAR_PREFIX_DEVELOPER_TOOLS "gDeveloperTools")
set(CVAR_PREFIX_GENERAL "gGeneral")
set(CVAR_PREFIX_REMOTE "gRemote")
set(CVAR_PREFIX_GAMEPLAY_STATS "gGameplayStats")
set(CVAR_PREFIX_TIME_DISPLAY "gTimeDisplay")
add_compile_definitions(
CVAR_PREFIX_RANDOMIZER_ENHANCEMENT="${CVAR_PREFIX_RANDOMIZER_ENHANCEMENT}"
CVAR_PREFIX_RANDOMIZER_SETTING="${CVAR_PREFIX_RANDOMIZER_SETTING}"
CVAR_PREFIX_COSMETIC="${CVAR_PREFIX_COSMETIC}"
CVAR_PREFIX_AUDIO="${CVAR_PREFIX_AUDIO}"
CVAR_PREFIX_CHEAT="${CVAR_PREFIX_CHEAT}"
CVAR_PREFIX_ENHANCEMENT="${CVAR_PREFIX_ENHANCEMENT}"
CVAR_PREFIX_SETTING="${CVAR_PREFIX_SETTING}"
CVAR_PREFIX_WINDOW="${CVAR_PREFIX_WINDOW}"
CVAR_PREFIX_TRACKER="${CVAR_PREFIX_TRACKER}"
CVAR_PREFIX_DEVELOPER_TOOLS="${CVAR_PREFIX_DEVELOPER_TOOLS}"
CVAR_PREFIX_GENERAL="${CVAR_PREFIX_GENERAL}"
CVAR_PREFIX_REMOTE="${CVAR_PREFIX_REMOTE}"
CVAR_PREFIX_GAMEPLAY_STATS="${CVAR_PREFIX_GAMEPLAY_STATS}"
CVAR_PREFIX_TIME_DISPLAY="${CVAR_PREFIX_TIME_DISPLAY}"
)

View file

@ -1,94 +1,34 @@
cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR) cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE) set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE)
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
set(CMAKE_C_STANDARD 23 CACHE STRING "The C standard to use")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
project(Ship VERSION 9.0.5 LANGUAGES C CXX) project(Ship VERSION 7.0.2 LANGUAGES C CXX)
include(CMake/soh-cvars.cmake) set(PROJECT_BUILD_NAME "Spock Charlie" CACHE STRING "")
include(CMake/lus-cvars.cmake) set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
option(SUPPRESS_WARNINGS "Suppress warnings in LUS and src (decomp)" ON)
if(SUPPRESS_WARNINGS)
MESSAGE("Suppressing warnings in LUS and src")
if(MSVC)
set(WARNING_OVERRIDE /w)
else()
set(WARNING_OVERRIDE -w)
endif()
else()
MESSAGE("Skipping warning suppression")
endif()
set(NATO_PHONETIC_ALPHABET
"Alfa" "Bravo" "Charlie" "Delta" "Echo" "Foxtrot" "Golf" "Hotel"
"India" "Juliett" "Kilo" "Lima" "Mike" "November" "Oscar" "Papa"
"Quebec" "Romeo" "Sierra" "Tango" "Uniform" "Victor" "Whiskey"
"Xray" "Yankee" "Zulu"
)
# Get the patch version number from the project version
math(EXPR PATCH_INDEX "${PROJECT_VERSION_PATCH}")
# Use the patch number to select the correct word
list(GET NATO_PHONETIC_ALPHABET ${PATCH_INDEX} PROJECT_PATCH_WORD)
set(PROJECT_BUILD_NAME "Blair ${PROJECT_PATCH_WORD}" CACHE STRING "" FORCE)
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "" FORCE)
execute_process(
COMMAND git branch --show-current
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(CMAKE_PROJECT_GIT_BRANCH "${GIT_BRANCH}" CACHE STRING "Git branch" FORCE)
execute_process(
COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Get only the first 7 characters of the hash
string(SUBSTRING "${GIT_COMMIT_HASH}" 0 7 SHORT_COMMIT_HASH)
set(CMAKE_PROJECT_GIT_COMMIT_HASH "${SHORT_COMMIT_HASH}" CACHE STRING "Git commit hash" FORCE)
execute_process(
COMMAND git describe --tags --abbrev=0 --exact-match HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_TAG
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT GIT_COMMIT_TAG)
set(GIT_COMMIT_TAG "" CACHE STRING "Git commit tag" FORCE)
endif()
set(CMAKE_PROJECT_GIT_COMMIT_TAG "${GIT_COMMIT_TAG}" CACHE STRING "Git commit tag" FORCE)
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh) set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>) add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/MP>)
add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/utf-8>) add_compile_options($<$<CXX_COMPILER_ID:MSVC>:/utf-8>)
if (CMAKE_SYSTEM_NAME STREQUAL "Windows") if (CMAKE_SYSTEM_NAME MATCHES "Windows|Linux")
include(CMake/automate-vcpkg.cmake) if(NOT DEFINED BUILD_CROWD_CONTROL)
set(BUILD_CROWD_CONTROL ON)
set(VCPKG_TRIPLET x64-windows-static)
set(VCPKG_TARGET_TRIPLET x64-windows-static)
vcpkg_bootstrap()
vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3 nlohmann-json tinyxml2 spdlog libogg libvorbis opus opusfile)
if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache")
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
endif() endif()
endif() endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
include(CMake/automate-vcpkg.cmake)
set(VCPKG_TRIPLET x64-windows-static)
set(VCPKG_TARGET_TRIPLET x64-windows-static)
vcpkg_bootstrap()
vcpkg_install_packages(zlib bzip2 libpng sdl2 sdl2-net glew glfw3)
endif()
################################################################################ ################################################################################
# Set target arch type if empty. Visual studio solution generator provides it. # Set target arch type if empty. Visual studio solution generator provides it.
################################################################################ ################################################################################
@ -144,49 +84,24 @@ include(CMake/GlobalSettingsInclude.cmake OPTIONAL)
################################################################################ ################################################################################
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
################################################################################
# Set LUS vars
################################################################################
# Enable the Gfx debugger in LUS to use libgfxd from ZAPDTR
set(GFX_DEBUG_DISASSEMBLER ON)
# Tell LUS we're using F3DEX_GBI_2 (in a way that doesn't break libgfxd)
set(GBI_UCODE F3DEX_GBI_2)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
# Enable MPQ and OTR support
set(INCLUDE_MPQ_SUPPORT ON)
################################################################################
# Set CONTROLLERBUTTONS_T
################################################################################
add_compile_definitions(CONTROLLERBUTTONS_T=uint32_t)
################################################################################ ################################################################################
# Sub-projects # Sub-projects
################################################################################ ################################################################################
add_subdirectory(libultraship ${CMAKE_BINARY_DIR}/libultraship) add_subdirectory(libultraship ${CMAKE_BINARY_DIR}/libultraship)
target_compile_options(libultraship PRIVATE "${WARNING_OVERRIDE}")
target_compile_definitions(libultraship PUBLIC INCLUDE_MPQ_SUPPORT)
add_subdirectory(ZAPDTR/ZAPD ${CMAKE_BINARY_DIR}/ZAPD) add_subdirectory(ZAPDTR/ZAPD ${CMAKE_BINARY_DIR}/ZAPD)
add_subdirectory(OTRExporter) add_subdirectory(OTRExporter)
add_subdirectory(soh) add_subdirectory(soh)
if(CMAKE_SYSTEM_NAME MATCHES "Windows|Linux")
add_subdirectory(OTRGui)
endif()
set_property(TARGET soh PROPERTY APPIMAGE_DESKTOP_FILE_TERMINAL YES) set_property(TARGET soh PROPERTY APPIMAGE_DESKTOP_FILE_TERMINAL YES)
set_property(TARGET soh PROPERTY APPIMAGE_DESKTOP_FILE "${CMAKE_SOURCE_DIR}/scripts/linux/appimage/soh.desktop") set_property(TARGET soh PROPERTY APPIMAGE_DESKTOP_FILE "${CMAKE_SOURCE_DIR}/scripts/linux/appimage/soh.desktop")
set_property(TARGET soh PROPERTY APPIMAGE_ICON_FILE "${CMAKE_BINARY_DIR}/sohIcon.png") set_property(TARGET soh PROPERTY APPIMAGE_ICON_FILE "${CMAKE_BINARY_DIR}/sohIcon.png")
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
install(FILES "${CMAKE_BINARY_DIR}/soh/soh.o2r" DESTINATION . COMPONENT ship) install(PROGRAMS "${CMAKE_SOURCE_DIR}/scripts/linux/appimage/soh.sh" DESTINATION . COMPONENT appimage)
install(TARGETS ZAPD DESTINATION ./assets/extractor COMPONENT extractor) install(FILES "${CMAKE_SOURCE_DIR}/soh.otr" DESTINATION . COMPONENT appimage)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets COMPONENT extractor)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml COMPONENT extractor)
endif()
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/ COMPONENT ship)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml COMPONENT ship)
endif() endif()
find_package(Python3 COMPONENTS Interpreter) find_package(Python3 COMPONENTS Interpreter)
@ -194,50 +109,30 @@ find_package(Python3 COMPONENTS Interpreter)
# Target to generate OTRs # Target to generate OTRs
add_custom_target( add_custom_target(
ExtractAssets ExtractAssets
COMMAND ${CMAKE_COMMAND} -E rm -f oot.o2r oot-mq.o2r soh.o2r # CMake versions prior to 3.17 do not have the rm command, use remove instead for older versions
COMMAND ${CMAKE_COMMAND} -E $<IF:$<VERSION_LESS:${CMAKE_VERSION},3.17>,remove,rm> -f oot.otr oot-mq.otr soh.otr
# copy LUS default shaders into assets/custom COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive
COMMAND ${CMAKE_COMMAND} -E rm -r -f ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/libultraship/src/graphic/Fast3D/shaders/ ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive --xml-root assets/xml --custom-otr-file soh.o2r "--custom-assets-path" ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom --port-ver "${CMAKE_PROJECT_VERSION}"
COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$<TARGET_FILE_DIR:ZAPD>" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$<TARGET_FILE_DIR:ZAPD>" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
COMMENT "Running asset extraction..." COMMENT "Running asset extraction..."
DEPENDS ZAPD DEPENDS ZAPD
BYPRODUCTS oot.o2r ${CMAKE_SOURCE_DIR}/oot.o2r oot-mq.o2r ${CMAKE_SOURCE_DIR}/oot-mq.o2r ${CMAKE_SOURCE_DIR}/soh.o2r BYPRODUCTS oot.otr ${CMAKE_SOURCE_DIR}/oot.otr oot-mq.otr ${CMAKE_SOURCE_DIR}/oot-mq.otr ${CMAKE_SOURCE_DIR}/soh.otr
) )
# Target to generate headers # Target to generate headers
add_custom_target( add_custom_target(
ExtractAssetHeaders ExtractAssetHeaders
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive --xml-root assets/xml --gen-headers COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive --gen-headers
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
COMMENT "Generating asset headers..." COMMENT "Generating asset headers..."
DEPENDS ZAPD DEPENDS ZAPD
) )
# Target to generate only soh.o2r
add_custom_target(
GenerateSohOtr
COMMAND ${CMAKE_COMMAND} -E rm -f soh.o2r
# copy LUS default shaders into assets/custom
COMMAND ${CMAKE_COMMAND} -E rm -r -f ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/libultraship/src/graphic/Fast3D/shaders/ ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --norom --custom-otr-file soh.o2r "--custom-assets-path" ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom --port-ver "${CMAKE_PROJECT_VERSION}"
COMMAND ${CMAKE_COMMAND} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME} -DTARGET_DIR="$<TARGET_FILE_DIR:ZAPD>" -DSOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBINARY_DIR=${CMAKE_BINARY_DIR} -DONLYSOHOTR=On -P ${CMAKE_CURRENT_SOURCE_DIR}/copy-existing-otrs.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh
COMMENT "Generating soh.o2r..."
DEPENDS ZAPD
)
if(CMAKE_SYSTEM_NAME MATCHES "Linux") if(CMAKE_SYSTEM_NAME MATCHES "Linux")
find_package(ImageMagick COMPONENTS convert) find_package(ImageMagick COMPONENTS convert)
if (ImageMagick_FOUND) if (ImageMagick_FOUND)
execute_process ( execute_process (
COMMAND ${ImageMagick_convert_EXECUTABLE} ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png -resize 512x512 ${CMAKE_BINARY_DIR}/sohIcon.png COMMAND ${ImageMagick_convert_EXECUTABLE} soh/macosx/sohIcon.png -resize 512x512 ${CMAKE_BINARY_DIR}/sohIcon.png
OUTPUT_VARIABLE outVar OUTPUT_VARIABLE outVar
) )
endif() endif()
@ -246,35 +141,42 @@ endif()
if(CMAKE_SYSTEM_NAME MATCHES "Darwin") if(CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_custom_target(CreateOSXIcons add_custom_target(CreateOSXIcons
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/macosx/soh.iconset COMMAND mkdir -p ${CMAKE_BINARY_DIR}/macosx/soh.iconset
COMMAND sips -z 16 16 ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_16x16.png COMMAND sips -z 16 16 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_16x16.png
COMMAND sips -z 32 32 ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_16x16@2x.png COMMAND sips -z 32 32 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_16x16@2x.png
COMMAND sips -z 32 32 ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_32x32.png COMMAND sips -z 32 32 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_32x32.png
COMMAND sips -z 64 64 ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_32x32@2x.png COMMAND sips -z 64 64 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_32x32@2x.png
COMMAND sips -z 128 128 ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_128x128.png COMMAND sips -z 128 128 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_128x128.png
COMMAND sips -z 256 256 ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_128x128@2x.png COMMAND sips -z 256 256 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_128x128@2x.png
COMMAND sips -z 256 256 ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_256x256.png COMMAND sips -z 256 256 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_256x256.png
COMMAND sips -z 512 512 ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_256x256@2x.png COMMAND sips -z 512 512 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_256x256@2x.png
COMMAND sips -z 512 512 ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_512x512.png COMMAND sips -z 512 512 soh/macosx/sohIcon.png --out ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_512x512.png
COMMAND cp ${CMAKE_SOURCE_DIR}/soh/macosx/sohIcon.png ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_512x512@2x.png COMMAND cp soh/macosx/sohIcon.png ${CMAKE_BINARY_DIR}/macosx/soh.iconset/icon_512x512@2x.png
COMMAND iconutil -c icns -o ${CMAKE_BINARY_DIR}/macosx/soh.icns ${CMAKE_BINARY_DIR}/macosx/soh.iconset COMMAND iconutil -c icns -o ${CMAKE_BINARY_DIR}/macosx/soh.icns ${CMAKE_BINARY_DIR}/macosx/soh.iconset
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Creating OSX icons ..." COMMENT "Creating OSX icons ..."
) )
add_dependencies(soh CreateOSXIcons) add_dependencies(soh CreateOSXIcons)
install(TARGETS ZAPD DESTINATION ${CMAKE_BINARY_DIR}/assets) add_custom_target(Assets ALL
COMMAND ${CMAKE_COMMAND} -Dsrc_dir="${CMAKE_SOURCE_DIR}/OTRGui/assets/extractor" -Ddst_dir="${CMAKE_BINARY_DIR}/assets/extractor" -P "${CMAKE_SOURCE_DIR}/OTRGui/Overwrite.cmake"
COMMAND ${CMAKE_COMMAND} -Dsrc_dir="${CMAKE_SOURCE_DIR}/OTRExporter/assets" -Ddst_dir="${CMAKE_BINARY_DIR}/assets/game" -P "${CMAKE_SOURCE_DIR}/OTRGui/Overwrite.cmake"
COMMAND ${CMAKE_COMMAND} -Dsrc_dir="${CMAKE_SOURCE_DIR}/soh/assets/xml" -Ddst_dir="${CMAKE_BINARY_DIR}/assets/extractor/xmls" -P "${CMAKE_SOURCE_DIR}/OTRGui/Overwrite.cmake"
)
add_dependencies(soh Assets)
install(TARGETS ZAPD DESTINATION ${CMAKE_BINARY_DIR}/assets/extractor)
set(PROGRAM_PERMISSIONS_EXECUTE OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) set(PROGRAM_PERMISSIONS_EXECUTE OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ)
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/) install(DIRECTORY ${CMAKE_BINARY_DIR}/assets
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml) DESTINATION .
PATTERN ZAPD.out
# Rename the installed soh binary to drop the macos suffix PERMISSIONS ${PROGRAM_PERMISSIONS_EXECUTE}
INSTALL(CODE "FILE(RENAME \${CMAKE_INSTALL_PREFIX}/../MacOS/soh-macos \${CMAKE_INSTALL_PREFIX}/../MacOS/soh)") )
install(CODE " install(CODE "
include(BundleUtilities) include(BundleUtilities)
fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/../MacOS/soh\" \"\" \"${dirs}\") fixup_bundle(\"\${CMAKE_INSTALL_PREFIX}/soh-macos\" \"\" \"${dirs}\")
") ")
endif() endif()

@ -1 +0,0 @@
Subproject commit 461ab19a36cde807591543397e136cae19aa6e7c

353
OTRExporter/.gitignore vendored Normal file
View file

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

12
OTRExporter/.gitrepo Normal file
View file

@ -0,0 +1,12 @@
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
;
[subrepo]
remote = https://github.com/HarbourMasters/OTRExporter.git
branch = master
commit = 1503d3eefa0b51164371c60c2aae8ad057678319
parent = d24c8453db1035f382e1b0853be00ebd281bbbdd
method = rebase
cmdver = 0.4.1

View file

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

View file

@ -0,0 +1,65 @@
################################################################################
# Command for variable_watch. This command issues error message, if a variable
# is changed. If variable PROPERTY_READER_GUARD_DISABLED is TRUE nothing happens
# variable_watch(<variable> property_reader_guard)
################################################################################
function(property_reader_guard VARIABLE ACCESS VALUE CURRENT_LIST_FILE STACK)
if("${PROPERTY_READER_GUARD_DISABLED}")
return()
endif()
if("${ACCESS}" STREQUAL "MODIFIED_ACCESS")
message(FATAL_ERROR
" Variable ${VARIABLE} is not supposed to be changed.\n"
" It is used only for reading target property ${VARIABLE}.\n"
" Use\n"
" set_target_properties(\"<target>\" PROPERTIES \"${VARIABLE}\" \"<value>\")\n"
" or\n"
" set_target_properties(\"<target>\" PROPERTIES \"${VARIABLE}_<CONFIG>\" \"<value>\")\n"
" instead.\n")
endif()
endfunction()
################################################################################
# Create variable <name> with generator expression that expands to value of
# target property <name>_<CONFIG>. If property is empty or not set then property
# <name> is used instead. Variable <name> has watcher property_reader_guard that
# doesn't allow to edit it.
# create_property_reader(<name>)
# Input:
# name - Name of watched property and output variable
################################################################################
function(create_property_reader NAME)
set(PROPERTY_READER_GUARD_DISABLED TRUE)
set(CONFIG_VALUE "$<TARGET_GENEX_EVAL:${PROPS_TARGET},$<TARGET_PROPERTY:${PROPS_TARGET},${NAME}_$<UPPER_CASE:$<CONFIG>>>>")
set(IS_CONFIG_VALUE_EMPTY "$<STREQUAL:${CONFIG_VALUE},>")
set(GENERAL_VALUE "$<TARGET_GENEX_EVAL:${PROPS_TARGET},$<TARGET_PROPERTY:${PROPS_TARGET},${NAME}>>")
set("${NAME}" "$<IF:${IS_CONFIG_VALUE_EMPTY},${GENERAL_VALUE},${CONFIG_VALUE}>" PARENT_SCOPE)
variable_watch("${NAME}" property_reader_guard)
endfunction()
################################################################################
# Set property $<name>_${PROPS_CONFIG_U} of ${PROPS_TARGET} to <value>
# set_config_specific_property(<name> <value>)
# Input:
# name - Prefix of property name
# value - New value
################################################################################
function(set_config_specific_property NAME VALUE)
set_target_properties("${PROPS_TARGET}" PROPERTIES "${NAME}_${PROPS_CONFIG_U}" "${VALUE}")
endfunction()
################################################################################
create_property_reader("TARGET_NAME")
create_property_reader("OUTPUT_DIRECTORY")
set_config_specific_property("TARGET_NAME" "${PROPS_TARGET}")
set_config_specific_property("OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("ARCHIVE_OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("LIBRARY_OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("RUNTIME_OUTPUT_NAME" "${TARGET_NAME}")
set_config_specific_property("ARCHIVE_OUTPUT_DIRECTORY" "${OUTPUT_DIRECTORY}")
set_config_specific_property("LIBRARY_OUTPUT_DIRECTORY" "${OUTPUT_DIRECTORY}")
set_config_specific_property("RUNTIME_OUTPUT_DIRECTORY" "${OUTPUT_DIRECTORY}")

View file

@ -0,0 +1,12 @@
include("${CMAKE_CURRENT_LIST_DIR}/Default.cmake")
set_config_specific_property("OUTPUT_DIRECTORY" "${CMAKE_SOURCE_DIR}$<$<NOT:$<STREQUAL:${CMAKE_VS_PLATFORM_NAME},Win32>>:/${CMAKE_VS_PLATFORM_NAME}>/${PROPS_CONFIG}")
if(MSVC)
create_property_reader("DEFAULT_CXX_EXCEPTION_HANDLING")
create_property_reader("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT")
set_target_properties("${PROPS_TARGET}" PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
set_config_specific_property("DEFAULT_CXX_EXCEPTION_HANDLING" "/EHsc")
set_config_specific_property("DEFAULT_CXX_DEBUG_INFORMATION_FORMAT" "/Zi")
endif()

View file

@ -0,0 +1,233 @@
# utils file for projects came from visual studio solution with cmake-converter.
################################################################################
# Wrap each token of the command with condition
################################################################################
cmake_policy(PUSH)
cmake_policy(SET CMP0054 NEW)
macro(prepare_commands)
unset(TOKEN_ROLE)
unset(COMMANDS)
foreach(TOKEN ${ARG_COMMANDS})
if("${TOKEN}" STREQUAL "COMMAND")
set(TOKEN_ROLE "KEYWORD")
elseif("${TOKEN_ROLE}" STREQUAL "KEYWORD")
set(TOKEN_ROLE "CONDITION")
elseif("${TOKEN_ROLE}" STREQUAL "CONDITION")
set(TOKEN_ROLE "COMMAND")
elseif("${TOKEN_ROLE}" STREQUAL "COMMAND")
set(TOKEN_ROLE "ARG")
endif()
if("${TOKEN_ROLE}" STREQUAL "KEYWORD")
list(APPEND COMMANDS "${TOKEN}")
elseif("${TOKEN_ROLE}" STREQUAL "CONDITION")
set(CONDITION ${TOKEN})
elseif("${TOKEN_ROLE}" STREQUAL "COMMAND")
list(APPEND COMMANDS "$<$<NOT:${CONDITION}>:${DUMMY}>$<${CONDITION}:${TOKEN}>")
elseif("${TOKEN_ROLE}" STREQUAL "ARG")
list(APPEND COMMANDS "$<${CONDITION}:${TOKEN}>")
endif()
endforeach()
endmacro()
cmake_policy(POP)
################################################################################
# Transform all the tokens to absolute paths
################################################################################
macro(prepare_output)
unset(OUTPUT)
foreach(TOKEN ${ARG_OUTPUT})
if(IS_ABSOLUTE ${TOKEN})
list(APPEND OUTPUT "${TOKEN}")
else()
list(APPEND OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/${TOKEN}")
endif()
endforeach()
endmacro()
################################################################################
# Parse add_custom_command_if args.
#
# Input:
# PRE_BUILD - Pre build event option
# PRE_LINK - Pre link event option
# POST_BUILD - Post build event option
# TARGET - Target
# OUTPUT - List of output files
# DEPENDS - List of files on which the command depends
# COMMANDS - List of commands(COMMAND condition1 commannd1 args1 COMMAND
# condition2 commannd2 args2 ...)
# Output:
# OUTPUT - Output files
# DEPENDS - Files on which the command depends
# COMMENT - Comment
# PRE_BUILD - TRUE/FALSE
# PRE_LINK - TRUE/FALSE
# POST_BUILD - TRUE/FALSE
# TARGET - Target name
# COMMANDS - Prepared commands(every token is wrapped in CONDITION)
# NAME - Unique name for custom target
# STEP - PRE_BUILD/PRE_LINK/POST_BUILD
################################################################################
function(add_custom_command_if_parse_arguments)
cmake_parse_arguments("ARG" "PRE_BUILD;PRE_LINK;POST_BUILD" "TARGET;COMMENT" "DEPENDS;OUTPUT;COMMANDS" ${ARGN})
if(WIN32)
set(DUMMY "cd.")
elseif(UNIX)
set(DUMMY "true")
endif()
prepare_commands()
prepare_output()
set(DEPENDS "${ARG_DEPENDS}")
set(COMMENT "${ARG_COMMENT}")
set(PRE_BUILD "${ARG_PRE_BUILD}")
set(PRE_LINK "${ARG_PRE_LINK}")
set(POST_BUILD "${ARG_POST_BUILD}")
set(TARGET "${ARG_TARGET}")
if(PRE_BUILD)
set(STEP "PRE_BUILD")
elseif(PRE_LINK)
set(STEP "PRE_LINK")
elseif(POST_BUILD)
set(STEP "POST_BUILD")
endif()
set(NAME "${TARGET}_${STEP}")
set(OUTPUT "${OUTPUT}" PARENT_SCOPE)
set(DEPENDS "${DEPENDS}" PARENT_SCOPE)
set(COMMENT "${COMMENT}" PARENT_SCOPE)
set(PRE_BUILD "${PRE_BUILD}" PARENT_SCOPE)
set(PRE_LINK "${PRE_LINK}" PARENT_SCOPE)
set(POST_BUILD "${POST_BUILD}" PARENT_SCOPE)
set(TARGET "${TARGET}" PARENT_SCOPE)
set(COMMANDS "${COMMANDS}" PARENT_SCOPE)
set(STEP "${STEP}" PARENT_SCOPE)
set(NAME "${NAME}" PARENT_SCOPE)
endfunction()
################################################################################
# Add conditional custom command
#
# Generating Files
# The first signature is for adding a custom command to produce an output:
# add_custom_command_if(
# <OUTPUT output1 [output2 ...]>
# <COMMANDS>
# <COMMAND condition command1 [args1...]>
# [COMMAND condition command2 [args2...]]
# [DEPENDS [depends...]]
# [COMMENT comment]
#
# Build Events
# add_custom_command_if(
# <TARGET target>
# <PRE_BUILD | PRE_LINK | POST_BUILD>
# <COMMAND condition command1 [args1...]>
# [COMMAND condition command2 [args2...]]
# [COMMENT comment]
#
# Input:
# output - Output files the command is expected to produce
# condition - Generator expression for wrapping the command
# command - Command-line(s) to execute at build time.
# args - Command`s args
# depends - Files on which the command depends
# comment - Display the given message before the commands are executed at
# build time.
# PRE_BUILD - Run before any other rules are executed within the target
# PRE_LINK - Run after sources have been compiled but before linking the
# binary
# POST_BUILD - Run after all other rules within the target have been
# executed
################################################################################
function(add_custom_command_if)
add_custom_command_if_parse_arguments(${ARGN})
if(OUTPUT AND TARGET)
message(FATAL_ERROR "Wrong syntax. A TARGET and OUTPUT can not both be specified.")
endif()
if(OUTPUT)
add_custom_command(OUTPUT ${OUTPUT}
${COMMANDS}
DEPENDS ${DEPENDS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT ${COMMENT})
elseif(TARGET)
if(PRE_BUILD AND NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio")
add_custom_target(
${NAME}
${COMMANDS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT ${COMMENT})
add_dependencies(${TARGET} ${NAME})
else()
add_custom_command(
TARGET ${TARGET}
${STEP}
${COMMANDS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT ${COMMENT})
endif()
else()
message(FATAL_ERROR "Wrong syntax. A TARGET or OUTPUT must be specified.")
endif()
endfunction()
################################################################################
# Use props file for a target and configs
# use_props(<target> <configs...> <props_file>)
# Inside <props_file> there are following variables:
# PROPS_TARGET - <target>
# PROPS_CONFIG - One of <configs...>
# PROPS_CONFIG_U - Uppercase PROPS_CONFIG
# Input:
# target - Target to apply props file
# configs - Build configurations to apply props file
# props_file - CMake script
################################################################################
macro(use_props TARGET CONFIGS PROPS_FILE)
set(PROPS_TARGET "${TARGET}")
foreach(PROPS_CONFIG ${CONFIGS})
string(TOUPPER "${PROPS_CONFIG}" PROPS_CONFIG_U)
get_filename_component(ABSOLUTE_PROPS_FILE "${PROPS_FILE}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
if(EXISTS "${ABSOLUTE_PROPS_FILE}")
include("${ABSOLUTE_PROPS_FILE}")
else()
message(WARNING "Corresponding cmake file from props \"${ABSOLUTE_PROPS_FILE}\" doesn't exist")
endif()
endforeach()
endmacro()
################################################################################
# Add compile options to source file
# source_file_compile_options(<source_file> [compile_options...])
# Input:
# source_file - Source file
# compile_options - Options to add to COMPILE_FLAGS property
################################################################################
function(source_file_compile_options SOURCE_FILE)
if("${ARGC}" LESS_EQUAL "1")
return()
endif()
get_source_file_property(COMPILE_OPTIONS "${SOURCE_FILE}" COMPILE_OPTIONS)
if(COMPILE_OPTIONS)
list(APPEND COMPILE_OPTIONS ${ARGN})
else()
set(COMPILE_OPTIONS "${ARGN}")
endif()
set_source_files_properties("${SOURCE_FILE}" PROPERTIES COMPILE_OPTIONS "${COMPILE_OPTIONS}")
endfunction()
################################################################################
# Default properties of visual studio projects
################################################################################
set(DEFAULT_CXX_PROPS "${CMAKE_CURRENT_LIST_DIR}/DefaultCXX.cmake")

View file

@ -0,0 +1,96 @@
cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE)
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
#set(CMAKE_C_STANDARD 11 CACHE STRING "The C standard to use")
set(CMAKE_C_STANDARD 11)
project(OTRExporter C CXX)
################################################################################
# Set target arch type if empty. Visual studio solution generator provides it.
################################################################################
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
if(NOT CMAKE_VS_PLATFORM_NAME)
set(CMAKE_VS_PLATFORM_NAME "x64")
endif()
message("${CMAKE_VS_PLATFORM_NAME} architecture in use")
if(NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64"
OR "${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32"))
message(FATAL_ERROR "${CMAKE_VS_PLATFORM_NAME} arch is not supported!")
endif()
endif()
################################################################################
# Global configuration types
################################################################################
set(CMAKE_CONFIGURATION_TYPES
"Debug"
"Release"
CACHE STRING "" FORCE
)
################################################################################
# Global compiler options
################################################################################
if(MSVC)
# remove default flags provided with CMake for MSVC
set(CMAKE_C_FLAGS "")
set(CMAKE_C_FLAGS_DEBUG "")
set(CMAKE_C_FLAGS_RELEASE "")
set(CMAKE_CXX_FLAGS "")
set(CMAKE_CXX_FLAGS_DEBUG "")
set(CMAKE_CXX_FLAGS_RELEASE "")
endif()
################################################################################
# Global linker options
################################################################################
if(MSVC)
# remove default flags provided with CMake for MSVC
set(CMAKE_EXE_LINKER_FLAGS "")
set(CMAKE_MODULE_LINKER_FLAGS "")
set(CMAKE_SHARED_LINKER_FLAGS "")
set(CMAKE_STATIC_LINKER_FLAGS "")
set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_DEBUG "${CMAKE_STATIC_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS}")
endif()
################################################################################
# Common utils
################################################################################
include(CMake/Utils.cmake)
################################################################################
# Additional Global Settings(add specific info there)
################################################################################
include(CMake/GlobalSettingsInclude.cmake OPTIONAL)
################################################################################
# Use solution folders feature
################################################################################
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
################################################################################
# Sub-projects
################################################################################
if (NOT TARGET libultraship)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../libultraship ${CMAKE_BINARY_DIR}/libultraship)
endif()
if (NOT TARGET ZAPD)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPD ${CMAKE_BINARY_DIR}/ZAPD)
endif()
if (NOT TARGET ZAPDUtils)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../libultraship/extern/ZAPDUtils ${CMAKE_BINARY_DIR}/ZAPDUtils)
endif()
add_subdirectory(OTRExporter)

9
OTRExporter/LICENSE Normal file
View file

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

View file

@ -0,0 +1,70 @@
#include "AnimationExporter.h"
#include <resource/type/Animation.h>
void OTRExporter_Animation::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZAnimation* anim = (ZAnimation*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::SOH_Animation);
ZNormalAnimation* normalAnim = dynamic_cast<ZNormalAnimation*>(anim);
ZCurveAnimation* curveAnim = dynamic_cast<ZCurveAnimation*>(anim);
ZLinkAnimation* linkAnim = dynamic_cast<ZLinkAnimation*>(anim);
if (linkAnim != nullptr)
{
writer->Write((uint32_t)LUS::AnimationType::Link);
writer->Write((uint16_t)linkAnim->frameCount);
writer->Write((uint32_t)linkAnim->segmentAddress);
}
else if (curveAnim != nullptr)
{
writer->Write((uint32_t)LUS::AnimationType::Curve);
writer->Write((uint16_t)curveAnim->frameCount);
writer->Write((uint32_t)curveAnim->refIndexArr.size());
for (auto val : curveAnim->refIndexArr)
writer->Write(val);
writer->Write((uint32_t)curveAnim->transformDataArr.size());
for (auto val : curveAnim->transformDataArr)
{
writer->Write(val.unk_00);
writer->Write(val.unk_02);
writer->Write(val.unk_04);
writer->Write(val.unk_06);
writer->Write(val.unk_08);
}
writer->Write((uint32_t)curveAnim->copyValuesArr.size());
for (auto val : curveAnim->copyValuesArr)
writer->Write(val);
}
else if (normalAnim != nullptr)
{
writer->Write((uint32_t)LUS::AnimationType::Normal);
writer->Write((uint16_t)normalAnim->frameCount);
writer->Write((uint32_t)normalAnim->rotationValues.size());
for (size_t i = 0; i < normalAnim->rotationValues.size(); i++)
writer->Write(normalAnim->rotationValues[i]);
writer->Write((uint32_t)normalAnim->rotationIndices.size());
for (size_t i = 0; i < normalAnim->rotationIndices.size(); i++)
{
writer->Write(normalAnim->rotationIndices[i].x);
writer->Write(normalAnim->rotationIndices[i].y);
writer->Write(normalAnim->rotationIndices[i].z);
}
writer->Write(normalAnim->limit);
}
else
{
writer->Write((uint32_t)LUS::AnimationType::Legacy);
}
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "ZResource.h"
#include "ZTexture.h"
#include "ZAnimation.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_Animation : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,108 @@
#include "ArrayExporter.h"
#include "VtxExporter.h"
#include <ZVector.h>
void OTRExporter_Array::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZArray* arr = (ZArray*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::Array);
writer->Write((uint32_t)arr->resList[0]->GetResourceType());
writer->Write((uint32_t)arr->arrayCnt);
for (size_t i = 0; i < arr->arrayCnt; i++)
{
if (arr->resList[i]->GetResourceType() == ZResourceType::Vertex)
{
ZVtx* vtx = (ZVtx*)arr->resList[i];
writer->Write(vtx->x);
writer->Write(vtx->y);
writer->Write(vtx->z);
writer->Write(vtx->flag);
writer->Write(vtx->s);
writer->Write(vtx->t);
writer->Write(vtx->r);
writer->Write(vtx->g);
writer->Write(vtx->b);
writer->Write(vtx->a);
}
else if (arr->resList[i]->GetResourceType() == ZResourceType::Vector)
{
ZVector* vec = (ZVector*)arr->resList[i];
writer->Write((uint32_t)vec->scalarType);
writer->Write((uint32_t)vec->dimensions);
for (size_t k = 0; k < vec->dimensions; k++)
{
// OTRTODO: Duplicate code here. Cleanup at a later date...
switch (vec->scalarType)
{
case ZScalarType::ZSCALAR_U8:
writer->Write(vec->scalars[k].scalarData.u8);
break;
case ZScalarType::ZSCALAR_S8:
writer->Write(vec->scalars[k].scalarData.s8);
break;
case ZScalarType::ZSCALAR_U16:
writer->Write(vec->scalars[k].scalarData.u16);
break;
case ZScalarType::ZSCALAR_S16:
writer->Write(vec->scalars[k].scalarData.s16);
break;
case ZScalarType::ZSCALAR_S32:
writer->Write(vec->scalars[k].scalarData.s32);
break;
case ZScalarType::ZSCALAR_U32:
writer->Write(vec->scalars[k].scalarData.u32);
break;
case ZScalarType::ZSCALAR_S64:
writer->Write(vec->scalars[k].scalarData.s64);
break;
case ZScalarType::ZSCALAR_U64:
writer->Write(vec->scalars[k].scalarData.u64);
break;
// OTRTODO: ADD OTHER TYPES
default:
break;
}
}
}
else
{
ZScalar* scal = (ZScalar*)arr->resList[i];
writer->Write((uint32_t)scal->scalarType);
switch (scal->scalarType)
{
case ZScalarType::ZSCALAR_U8:
writer->Write(scal->scalarData.u8);
break;
case ZScalarType::ZSCALAR_S8:
writer->Write(scal->scalarData.s8);
break;
case ZScalarType::ZSCALAR_U16:
writer->Write(scal->scalarData.u16);
break;
case ZScalarType::ZSCALAR_S16:
writer->Write(scal->scalarData.s16);
break;
case ZScalarType::ZSCALAR_S32:
writer->Write(scal->scalarData.s32);
break;
case ZScalarType::ZSCALAR_U32:
writer->Write(scal->scalarData.u32);
break;
case ZScalarType::ZSCALAR_S64:
writer->Write(scal->scalarData.s64);
break;
case ZScalarType::ZSCALAR_U64:
writer->Write(scal->scalarData.u64);
break;
// OTRTODO: ADD OTHER TYPES
default:
break;
}
}
}
}

View file

@ -0,0 +1,12 @@
#pragma once
#include "ZResource.h"
#include "ZArray.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_Array : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,191 @@
#include "AudioExporter.h"
#include "Main.h"
#include <Utils/MemoryStream.h>
#include <Globals.h>
#include <Utils/DiskFile.h>
#include "DisplayListExporter.h"
void OTRExporter_Audio::WriteSampleEntryReference(ZAudio* audio, SampleEntry* entry, std::map<uint32_t, SampleEntry*> samples, BinaryWriter* writer)
{
writer->Write((uint8_t)(entry != nullptr ? 1 : 0));
if (entry != nullptr)
{
if (audio->sampleOffsets[entry->bankId].find(entry->sampleLoopOffset) != audio->sampleOffsets[entry->bankId].end())
{
if (audio->sampleOffsets[entry->bankId][entry->sampleLoopOffset].find(entry->sampleDataOffset) != audio->sampleOffsets[entry->bankId][entry->sampleLoopOffset].end())
{
writer->Write(StringHelper::Sprintf("audio/samples/%s", audio->sampleOffsets[entry->bankId][entry->sampleLoopOffset][entry->sampleDataOffset].c_str()));
}
else
writer->Write(entry->fileName);
}
else
writer->Write(entry->fileName);
}
else
writer->Write("");
}
void OTRExporter_Audio::WriteSampleEntry(SampleEntry* entry, BinaryWriter* writer)
{
WriteHeader(nullptr, "", writer, LUS::ResourceType::SOH_AudioSample, 2);
writer->Write(entry->codec);
writer->Write(entry->medium);
writer->Write(entry->unk_bit26);
writer->Write(entry->unk_bit25);
writer->Write((uint32_t)entry->data.size());
writer->Write((char*)entry->data.data(), entry->data.size());
writer->Write((uint32_t)(entry->loop.start));
writer->Write((uint32_t)(entry->loop.end));
writer->Write((uint32_t)(entry->loop.count));
writer->Write((uint32_t)entry->loop.states.size());
for (size_t i = 0; i < entry->loop.states.size(); i++)
writer->Write((entry->loop.states[i]));
writer->Write((uint32_t)(entry->book.order));
writer->Write((uint32_t)(entry->book.npredictors));
writer->Write((uint32_t)entry->book.books.size());
for (size_t i = 0; i < entry->book.books.size(); i++)
writer->Write((entry->book.books[i]));
}
void OTRExporter_Audio::WriteSoundFontEntry(ZAudio* audio, SoundFontEntry* entry, std::map<uint32_t, SampleEntry*> samples, BinaryWriter* writer)
{
writer->Write((uint8_t)(entry != nullptr ? 1 : 0));
if (entry != nullptr)
{
WriteSampleEntryReference(audio, entry->sampleEntry, samples, writer);
writer->Write(entry->tuning);
}
}
void OTRExporter_Audio::WriteEnvData(std::vector<AdsrEnvelope*> envelopes, BinaryWriter* writer)
{
writer->Write((uint32_t)envelopes.size());
for (auto env : envelopes)
{
writer->Write(env->delay);
writer->Write(env->arg);
}
}
void OTRExporter_Audio::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZAudio* audio = (ZAudio*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::SOH_Audio, 2);
// Write Samples as individual files
for (auto pair : audio->samples)
{
MemoryStream* sampleStream = new MemoryStream();
BinaryWriter sampleWriter = BinaryWriter(sampleStream);
writer->Write((uint32_t)pair.first);
WriteSampleEntry(pair.second, &sampleWriter);
std::string basePath = "";
if (audio->sampleOffsets[pair.second->bankId].find(pair.second->sampleLoopOffset) != audio->sampleOffsets[pair.second->bankId].end())
{
if (audio->sampleOffsets[pair.second->bankId][pair.second->sampleLoopOffset].find(pair.second->sampleDataOffset) != audio->sampleOffsets[pair.second->bankId][pair.second->sampleLoopOffset].end())
basePath = StringHelper::Sprintf("samples/%s", audio->sampleOffsets[pair.second->bankId][pair.second->sampleLoopOffset][pair.second->sampleDataOffset].c_str());
else
basePath = StringHelper::Sprintf("samples/sample_%08X", pair.first);
}
else
basePath = StringHelper::Sprintf("samples/sample_%08X", pair.first);
std::string fName = OTRExporter_DisplayList::GetPathToRes(res, basePath);
AddFile(fName, sampleStream->ToVector());
}
// Write the soundfont table
for (size_t i = 0; i < audio->soundFontTable.size(); i++)
{
MemoryStream* fntStream = new MemoryStream();
BinaryWriter fntWriter = BinaryWriter(fntStream);
WriteHeader(nullptr, "", &fntWriter, LUS::ResourceType::SOH_AudioSoundFont, 2);
fntWriter.Write((uint32_t)i);
fntWriter.Write(audio->soundFontTable[i].medium);
fntWriter.Write(audio->soundFontTable[i].cachePolicy);
fntWriter.Write(audio->soundFontTable[i].data1);
fntWriter.Write(audio->soundFontTable[i].data2);
fntWriter.Write(audio->soundFontTable[i].data3);
fntWriter.Write((uint32_t)audio->soundFontTable[i].drums.size());
fntWriter.Write((uint32_t)audio->soundFontTable[i].instruments.size());
fntWriter.Write((uint32_t)audio->soundFontTable[i].soundEffects.size());
for (size_t k = 0; k < audio->soundFontTable[i].drums.size(); k++)
{
fntWriter.Write(audio->soundFontTable[i].drums[k].releaseRate);
fntWriter.Write(audio->soundFontTable[i].drums[k].pan);
fntWriter.Write(audio->soundFontTable[i].drums[k].loaded);
WriteEnvData(audio->soundFontTable[i].drums[k].env, &fntWriter);
WriteSampleEntryReference(audio, audio->soundFontTable[i].drums[k].sample, audio->samples, &fntWriter);
fntWriter.Write(audio->soundFontTable[i].drums[k].tuning);
}
for (size_t k = 0; k < audio->soundFontTable[i].instruments.size(); k++)
{
fntWriter.Write((uint8_t)audio->soundFontTable[i].instruments[k].isValidInstrument);
fntWriter.Write(audio->soundFontTable[i].instruments[k].loaded);
fntWriter.Write(audio->soundFontTable[i].instruments[k].normalRangeLo);
fntWriter.Write(audio->soundFontTable[i].instruments[k].normalRangeHi);
fntWriter.Write(audio->soundFontTable[i].instruments[k].releaseRate);
WriteEnvData(audio->soundFontTable[i].instruments[k].env, &fntWriter);
WriteSoundFontEntry(audio, audio->soundFontTable[i].instruments[k].lowNotesSound, audio->samples, &fntWriter);
WriteSoundFontEntry(audio, audio->soundFontTable[i].instruments[k].normalNotesSound, audio->samples, &fntWriter);
WriteSoundFontEntry(audio, audio->soundFontTable[i].instruments[k].highNotesSound, audio->samples, &fntWriter);
}
for (size_t k = 0; k < audio->soundFontTable[i].soundEffects.size(); k++)
{
WriteSoundFontEntry(audio, audio->soundFontTable[i].soundEffects[k], audio->samples, &fntWriter);
}
//std::string fName = OTRExporter_DisplayList::GetPathToRes(res, StringHelper::Sprintf("fonts/font_%02X", i));
std::string fName = OTRExporter_DisplayList::GetPathToRes(res, StringHelper::Sprintf("fonts/%s", audio->soundFontNames[i].c_str()));
AddFile(fName, fntStream->ToVector());
}
// Write Sequences
for (size_t i = 0; i < audio->sequences.size(); i++)
{
auto seq = audio->sequences[i];
MemoryStream* seqStream = new MemoryStream();
BinaryWriter seqWriter = BinaryWriter(seqStream);
WriteHeader(nullptr, "", &seqWriter, LUS::ResourceType::SOH_AudioSequence, 2);
seqWriter.Write((uint32_t)seq.size());
seqWriter.Write(seq.data(), seq.size());
seqWriter.Write((uint8_t)i);
seqWriter.Write((uint8_t)audio->sequenceTable[i].medium);
seqWriter.Write((uint8_t)audio->sequenceTable[i].cachePolicy);
seqWriter.Write((uint32_t)audio->fontIndices[i].size());
for (size_t k = 0; k < audio->fontIndices[i].size(); k++)
seqWriter.Write((uint8_t)audio->fontIndices[i][k]);
std::string fName = OTRExporter_DisplayList::GetPathToRes(res, StringHelper::Sprintf("sequences/%s", audio->seqNames[i].c_str()));
AddFile(fName, seqStream->ToVector());
}
}

View file

@ -0,0 +1,16 @@
#pragma once
#include "ZResource.h"
#include "ZAudio.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_Audio : public OTRExporter
{
public:
void WriteSampleEntry(SampleEntry* entry, BinaryWriter* writer);
void WriteSampleEntryReference(ZAudio* audio, SampleEntry* entry, std::map<uint32_t, SampleEntry*> samples, BinaryWriter* writer);
void WriteSoundFontEntry(ZAudio* audio, SoundFontEntry* entry, std::map<uint32_t, SampleEntry*> samples, BinaryWriter* writer);
void WriteEnvData(std::vector<AdsrEnvelope*> envelopes, BinaryWriter* writer);
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,14 @@
#include "BackgroundExporter.h"
#include "../ZAPD/ZFile.h"
void OTRExporter_Background::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZBackground* bg = (ZBackground*)res;
WriteHeader(bg, outPath, writer, LUS::ResourceType::SOH_Background);
writer->Write((uint32_t)bg->GetRawDataSize());
auto data = bg->parent->GetRawData();
writer->Write((char*)data.data() + bg->GetRawDataIndex(), bg->GetRawDataSize());
}

View file

@ -0,0 +1,12 @@
#pragma once
#include "ZResource.h"
#include "ZBackground.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_Background : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,21 @@
#include "BlobExporter.h"
#include "../ZAPD/ZFile.h"
void OTRExporter_Blob::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZBlob* blob = (ZBlob*)res;
WriteHeader(blob, outPath, writer, LUS::ResourceType::Blob);
auto start = std::chrono::steady_clock::now();
writer->Write((uint32_t)blob->GetRawDataSize());
auto data = blob->parent->GetRawData();
for (size_t i = blob->GetRawDataIndex(); i < blob->GetRawDataIndex() + blob->GetRawDataSize(); i++)
writer->Write(data[i]);
auto end = std::chrono::steady_clock::now();
size_t diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
}

View file

@ -0,0 +1,12 @@
#pragma once
#include "ZResource.h"
#include "ZBlob.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_Blob : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,245 @@
set(PROJECT_NAME OTRExporter)
################################################################################
# Source groups
################################################################################
set(Header_Files
"AnimationExporter.h"
"ArrayExporter.h"
"AudioExporter.h"
"BackgroundExporter.h"
"BlobExporter.h"
"CollisionExporter.h"
"command_macros_base.h"
"CutsceneExporter.h"
"DisplayListExporter.h"
"Exporter.h"
"Main.h"
"MtxExporter.h"
"PathExporter.h"
"PlayerAnimationExporter.h"
"RoomExporter.h"
"SkeletonExporter.h"
"SkeletonLimbExporter.h"
"TextExporter.h"
"TextureExporter.h"
"VersionInfo.h"
"VtxExporter.h"
"z64cutscene.h"
"z64cutscene_commands.h"
)
source_group("Header Files" FILES ${Header_Files})
set(Source_Files
"AnimationExporter.cpp"
"ArrayExporter.cpp"
"AudioExporter.cpp"
"BackgroundExporter.cpp"
"BlobExporter.cpp"
"CollisionExporter.cpp"
"CutsceneExporter.cpp"
"DisplayListExporter.cpp"
"Exporter.cpp"
"Main.cpp"
"MtxExporter.cpp"
"PathExporter.cpp"
"PlayerAnimationExporter.cpp"
"RoomExporter.cpp"
"SkeletonExporter.cpp"
"SkeletonLimbExporter.cpp"
"TextExporter.cpp"
"TextureExporter.cpp"
"VersionInfo.cpp"
"VtxExporter.cpp"
)
source_group("Source Files" FILES ${Source_Files})
set(ALL_FILES
${Header_Files}
${Source_Files}
)
################################################################################
# Target
################################################################################
add_library(${PROJECT_NAME} STATIC ${ALL_FILES})
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
use_props(${PROJECT_NAME} "${CMAKE_CONFIGURATION_TYPES}" "${DEFAULT_CXX_PROPS}")
endif()
set(ROOT_NAMESPACE OTRExporter)
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
set_target_properties(${PROJECT_NAME} PROPERTIES
VS_GLOBAL_KEYWORD "Win32Proj"
)
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
set_target_properties(${PROJECT_NAME} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE "TRUE"
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
set_target_properties(${PROJECT_NAME} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE "TRUE"
)
endif()
endif()
################################################################################
# MSVC runtime library
################################################################################
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
get_property(MSVC_RUNTIME_LIBRARY_DEFAULT TARGET ${PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY)
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
string(CONCAT "MSVC_RUNTIME_LIBRARY_STR"
$<$<CONFIG:Debug>:
MultiThreadedDebug
>
$<$<CONFIG:Release>:
MultiThreaded
>
$<$<NOT:$<OR:$<CONFIG:Debug>,$<CONFIG:Release>>>:${MSVC_RUNTIME_LIBRARY_DEFAULT}>
)
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES MSVC_RUNTIME_LIBRARY ${MSVC_RUNTIME_LIBRARY_STR})
endif()
################################################################################
# Compile definitions
################################################################################
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_compile_definitions(${PROJECT_NAME} PRIVATE
"$<$<CONFIG:Debug>:"
"_DEBUG"
">"
"$<$<CONFIG:Release>:"
"NDEBUG"
">"
"_CONSOLE;"
"_CRT_SECURE_NO_WARNINGS;"
"UNICODE;"
"_UNICODE"
STORMLIB_NO_AUTO_LINK
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
target_compile_definitions(${PROJECT_NAME} PRIVATE
"$<$<CONFIG:Debug>:"
"_DEBUG;"
"_CRT_SECURE_NO_WARNINGS"
">"
"$<$<CONFIG:Release>:"
"NDEBUG"
">"
"WIN32;"
"_CONSOLE;"
"UNICODE;"
"_UNICODE"
STORMLIB_NO_AUTO_LINK
)
endif()
endif()
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang")
target_compile_definitions(${PROJECT_NAME} PRIVATE
"$<$<CONFIG:Debug>:"
"_DEBUG"
">"
"$<$<CONFIG:Release>:"
"NDEBUG"
">"
"_CONSOLE;"
"_CRT_SECURE_NO_WARNINGS;"
"UNICODE;"
"_UNICODE"
)
endif()
################################################################################
# Compile and link options
################################################################################
target_include_directories(${PROJECT_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../../ZAPDTR/ZAPD/
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/include
# TODO: these should no longer be necessary if we were to link against LUS
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/src
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/Mercury
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/tinyxml2
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/ZAPDUtils
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/StormLib/src
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/spdlog/include
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/extern/nlohmann-json/include
${CMAKE_CURRENT_SOURCE_DIR}/../../libultraship/src/resource
${CMAKE_CURRENT_SOURCE_DIR}/../../soh/soh
.
)
if(MSVC)
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Release>:
/Oi;
/Gy
>
/permissive-;
/sdl;
/W3;
${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT};
${DEFAULT_CXX_EXCEPTION_HANDLING}
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
target_compile_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Release>:
/Oi;
/Gy
>
/permissive-;
/sdl;
/W3;
${DEFAULT_CXX_DEBUG_INFORMATION_FORMAT};
${DEFAULT_CXX_EXCEPTION_HANDLING}
)
endif()
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
target_link_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Release>:
/OPT:REF;
/OPT:ICF
>
/SUBSYSTEM:CONSOLE
)
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x86")
target_link_options(${PROJECT_NAME} PRIVATE
$<$<CONFIG:Release>:
/DEBUG;
/OPT:REF;
/OPT:ICF;
/INCREMENTAL:NO
>
/SUBSYSTEM:CONSOLE
)
endif()
endif()
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang")
target_compile_options(${PROJECT_NAME} PRIVATE
-Wall -Wextra -Wno-error
-Wno-unused-parameter
-Wno-unused-function
-Wno-unused-variable
-Wno-missing-field-initializers
-Wno-parentheses
-Wno-narrowing
$<$<COMPILE_LANGUAGE:CXX>:-Wno-deprecated-enum-enum-conversion>
)
endif()
################################################################################
# Dependencies
################################################################################
add_dependencies(${PROJECT_NAME}
libultraship
)
# Link with other targets.
target_link_libraries(${PROJECT_NAME} PUBLIC "${ADDITIONAL_LIBRARY_DEPENDENCIES}")

View file

@ -0,0 +1,84 @@
#include "CollisionExporter.h"
#include <libultraship/bridge.h>
void OTRExporter_Collision::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZCollisionHeader* col = (ZCollisionHeader*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::SOH_CollisionHeader);
writer->Write(col->absMinX);
writer->Write(col->absMinY);
writer->Write(col->absMinZ);
writer->Write(col->absMaxX);
writer->Write(col->absMaxY);
writer->Write(col->absMaxZ);
writer->Write((uint32_t)col->vertices.size());
for (uint16_t i = 0; i < col->vertices.size(); i++)
{
writer->Write(col->vertices[i].scalars[0].scalarData.s16);
writer->Write(col->vertices[i].scalars[1].scalarData.s16);
writer->Write(col->vertices[i].scalars[2].scalarData.s16);
}
writer->Write((uint32_t)col->polygons.size());
for (uint16_t i = 0; i < col->polygons.size(); i++)
{
writer->Write(col->polygons[i].type);
writer->Write(col->polygons[i].vtxA);
writer->Write(col->polygons[i].vtxB);
writer->Write(col->polygons[i].vtxC);
writer->Write(col->polygons[i].normX);
writer->Write(col->polygons[i].normY);
writer->Write(col->polygons[i].normZ);
writer->Write(col->polygons[i].dist);
}
writer->Write((uint32_t)col->PolygonTypes.size());
for (uint16_t i = 0; i < col->PolygonTypes.size(); i++) {
writer->Write(col->PolygonTypes[i].data[1]);
writer->Write(col->PolygonTypes[i].data[0]);
}
writer->Write((uint32_t)col->camData->entries.size());
for (auto entry : col->camData->entries)
{
auto camPosDecl = col->parent->GetDeclarationRanged(Seg2Filespace(entry->cameraPosDataSeg, col->parent->baseAddress));
int idx = 0;
if (camPosDecl != nullptr)
idx = ((entry->cameraPosDataSeg & 0x00FFFFFF) - camPosDecl->address) / 6;
writer->Write(entry->cameraSType);
writer->Write(entry->numData);
writer->Write((uint32_t)idx);
}
writer->Write((uint32_t)col->camData->cameraPositionData.size());
for (auto entry : col->camData->cameraPositionData)
{
writer->Write(entry->x);
writer->Write(entry->y);
writer->Write(entry->z);
}
writer->Write((uint32_t)col->waterBoxes.size());
for (auto waterBox : col->waterBoxes)
{
writer->Write(waterBox.xMin);
writer->Write(waterBox.ySurface);
writer->Write(waterBox.zMin);
writer->Write(waterBox.xLength);
writer->Write(waterBox.zLength);
writer->Write(waterBox.properties);
}
}

View file

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

View file

@ -0,0 +1,444 @@
#include "CutsceneExporter.h"
#include <libultraship/bridge.h>
void OTRExporter_Cutscene::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZCutscene* cs = (ZCutscene*)res;
WriteHeader(cs, outPath, writer, LUS::ResourceType::SOH_Cutscene);
writer->Write((uint32_t)0);
const auto currentStream = writer->GetBaseAddress();
writer->Write(CS_BEGIN_CUTSCENE(cs->numCommands, cs->endFrame));
for (size_t i = 0; i < cs->commands.size(); i++)
{
switch (cs->commands[i]->commandID)
{
case (uint32_t)CutsceneCommands::SetCameraPos:
{
CutsceneCommandSetCameraPos* cmdCamPos = (CutsceneCommandSetCameraPos*)cs->commands[i];
writer->Write(CS_CMD_CAM_EYE);
writer->Write(CMD_HH(0x0001, ((CutsceneCommandSetCameraPos*)cs->commands[i])->startFrame));
writer->Write(CMD_HH(cmdCamPos->endFrame, 0x0000));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneCameraPoint* point = (CutsceneCameraPoint*)e;
writer->Write(CMD_BBH(point->continueFlag, point->cameraRoll, point->nextPointFrame));
writer->Write(point->viewAngle);
writer->Write(CMD_HH(point->posX, point->posY));
writer->Write(CMD_HH(point->posZ, point->unused));
}
}
break;
case (uint32_t)CutsceneCommands::SetCameraFocus:
{
CutsceneCommandSetCameraPos* cmdCamPos = (CutsceneCommandSetCameraPos*)cs->commands[i];
writer->Write(CS_CMD_CAM_AT);
writer->Write(CMD_HH(0x0001, cmdCamPos->startFrame));
writer->Write(CMD_HH(cmdCamPos->endFrame, 0x0000));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneCameraPoint* point = (CutsceneCameraPoint*)e;
writer->Write(CMD_BBH(point->continueFlag, point->cameraRoll, point->nextPointFrame));
writer->Write(point->viewAngle);
writer->Write(CMD_HH(point->posX, point->posY));
writer->Write(CMD_HH(point->posZ, point->unused));
}
break;
}
case (uint32_t)CutsceneCommands::Misc:
{
writer->Write(CS_CMD_MISC);
writer->Write((uint32_t)CMD_W((cs->commands[i])->entries.size()));
for (const auto& e : cs->commands[i]->entries) //All in OOT seem to only have 1 entry
{
CutsceneSubCommandEntry_GenericCmd* cmd = (CutsceneSubCommandEntry_GenericCmd*)e;
writer->Write(CMD_HH(cmd->base, cmd->startFrame));
writer->Write(CMD_HH(cmd->endFrame, cmd->pad));
writer->Write(CMD_W(cmd->unused1));
writer->Write(CMD_W(cmd->unused2));
writer->Write(CMD_W(cmd->unused3));
writer->Write(CMD_W(cmd->unused4));
writer->Write(CMD_W(cmd->unused5));
writer->Write(CMD_W(cmd->unused6));
writer->Write(CMD_W(cmd->unused7));
writer->Write(CMD_W(cmd->unused8));
writer->Write(CMD_W(cmd->unused9));
writer->Write(CMD_W(cmd->unused10));
}
break;
}
case (uint32_t)CutsceneCommands::SetLighting:
{
writer->Write(CS_CMD_SET_LIGHTING);
writer->Write((uint32_t)CMD_W((cs->commands[i])->entries.size()));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneSubCommandEntry_GenericCmd* cmd = (CutsceneSubCommandEntry_GenericCmd*)e;
writer->Write(CMD_HH(cmd->base, cmd->startFrame));
writer->Write(CMD_HH(cmd->endFrame, cmd->pad));
writer->Write(CMD_W(cmd->unused1));
writer->Write(CMD_W(cmd->unused2));
writer->Write(CMD_W(cmd->unused3));
writer->Write(CMD_W(cmd->unused4));
writer->Write(CMD_W(cmd->unused5));
writer->Write(CMD_W(cmd->unused6));
writer->Write(CMD_W(cmd->unused7));
writer->Write((uint32_t)0x0);
writer->Write((uint32_t)0x0);
writer->Write((uint32_t)0x0);
}
break;
}
case (uint32_t)CutsceneCommands::SetCameraPosLink:
{
CutsceneCommandSetCameraPos* cmdCamPos = (CutsceneCommandSetCameraPos*)cs->commands[i];
writer->Write(CS_CMD_CAM_EYE_REL_TO_PLAYER);
writer->Write(CMD_HH(0x0001, ((CutsceneCommandSetCameraPos*)cs->commands[i])->startFrame));
writer->Write(CMD_HH(cmdCamPos->endFrame, 0x0000));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneCameraPoint* point = (CutsceneCameraPoint*)e;
writer->Write(CMD_BBH(point->continueFlag, point->cameraRoll, point->nextPointFrame));
writer->Write(point->viewAngle);
writer->Write(CMD_HH(point->posX, point->posY));
writer->Write(CMD_HH(point->posZ, point->unused));
}
break;
}
case (uint32_t)CutsceneCommands::SetCameraFocusLink:
{
CutsceneCommandSetCameraPos* cmdCamPos = (CutsceneCommandSetCameraPos*)cs->commands[i];
writer->Write(CS_CMD_CAM_AT_REL_TO_PLAYER);
writer->Write(CMD_HH(0x0001, ((CutsceneCommandSetCameraPos*)cs->commands[i])->startFrame));
writer->Write(CMD_HH(cmdCamPos->endFrame, 0x0000));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneCameraPoint* point = (CutsceneCameraPoint*)e;
writer->Write(CMD_BBH(point->continueFlag, point->cameraRoll, point->nextPointFrame));
writer->Write(point->viewAngle);
writer->Write(CMD_HH(point->posX, point->posY));
writer->Write(CMD_HH(point->posZ, point->unused));
}
break;
}
case (uint32_t)CutsceneCommands::Cmd07: // Not used in OOT
break;
case (uint32_t)CutsceneCommands::Cmd08: // Not used in OOT
break;
case (uint32_t)CutsceneCommands::Cmd09:
{
writer->Write(CS_CMD_09);
writer->Write((uint32_t)CMD_W(((CutsceneCommand_Rumble*)cs->commands[i])->entries.size()));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneSubCommandEntry_Rumble* r = (CutsceneSubCommandEntry_Rumble*)e;
writer->Write(CMD_HH(r->base, r->startFrame));
writer->Write(CMD_HBB(e->endFrame, r->unk_06, r->unk_07));
writer->Write(CMD_BBH(r->unk_08, r->unk_09, r->unk_0A));
}
break;
}
case 0x15://Both unused in OoT
case 0x1A://(uint32_t)CutsceneCommands::Unknown:
{
#if 0
CutsceneCommandUnknown* cmdUnk = (CutsceneCommandUnknown*)cs->commands[i];
writer->Write((uint32_t)cs->commands[i]->commandID);
writer->Write((uint32_t)cmdUnk->entries.size());
for (const auto e : cmdUnk->entries)
{
writer->Write(CMD_W(e->unused0));
writer->Write(CMD_W(e->unused1));
writer->Write(CMD_W(e->unused2));
writer->Write(CMD_W(e->unused3));
writer->Write(CMD_W(e->unused4));
writer->Write(CMD_W(e->unused5));
writer->Write(CMD_W(e->unused6));
writer->Write(CMD_W(e->unused7));
writer->Write(CMD_W(e->unused8));
writer->Write(CMD_W(e->unused9));
writer->Write(CMD_W(e->unused10));
writer->Write(CMD_W(e->unused11));
}
#endif
}
break;
case (uint32_t)CutsceneCommands::Textbox:
{
writer->Write(CS_CMD_TEXTBOX);
writer->Write((uint32_t)CMD_W((cs->commands[i])->entries.size()));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneSubCommandEntry_TextBox* textBox = (CutsceneSubCommandEntry_TextBox*)e;
if (textBox->base == 0xFFFF) // CS_TEXT_NONE
{
writer->Write(CMD_HH(0xFFFF, textBox->startFrame));
writer->Write(CMD_HH(textBox->endFrame, 0xFFFF));
writer->Write(CMD_HH(0xFFFF, 0xFFFF));
}
else // CS_TEXT_DISPLAY_TEXTBOX
{
writer->Write(CMD_HH(textBox->base, textBox->startFrame));
writer->Write(CMD_HH(textBox->endFrame, textBox->type));
writer->Write(CMD_HH(textBox->textId1, textBox->textId2));
}
}
break;
}
case 10: //ActorAction0
case (uint32_t)CutsceneCommands::SetActorAction1:
case 17:
case 18:
case 23:
case 34:
case 39:
case 46:
case 76:
case 85:
case 93:
case 105:
case 107:
case 110:
case 119:
case 123:
case 138:
case 139:
case 144:
case (uint32_t)CutsceneCommands::SetActorAction2:
case 16:
case 24:
case 35:
case 40:
case 48:
case 64:
case 68:
case 70:
case 78:
case 80:
case 94:
case 116:
case 118:
case 120:
case 125:
case 131:
case 141:
case (uint32_t)CutsceneCommands::SetActorAction3:
case 36:
case 41:
case 50:
case 67:
case 69:
case 72:
case 74:
case 81:
case 106:
case 117:
case 121:
case 126:
case 132:
case (uint32_t)CutsceneCommands::SetActorAction4:
case 37:
case 42:
case 51:
case 53:
case 63:
case 65:
case 66:
case 75:
case 82:
case 108:
case 127:
case 133:
case (uint32_t)CutsceneCommands::SetActorAction5:
case 38:
case 43:
case 47:
case 54:
case 79:
case 83:
case 128:
case 135:
case (uint32_t)CutsceneCommands::SetActorAction6:
case 55:
case 77:
case 84:
case 90:
case 129:
case 136:
case (uint32_t)CutsceneCommands::SetActorAction7:
case 52:
case 57:
case 58:
case 88:
case 115:
case 130:
case 137:
case (uint32_t)CutsceneCommands::SetActorAction8:
case 60:
case 89:
case 111:
case 114:
case 134:
case 142:
case (uint32_t)CutsceneCommands::SetActorAction9:
case (uint32_t)CutsceneCommands::SetActorAction10:
{
writer->Write((uint32_t)(CutsceneCommands)cs->commands[i]->commandID);
writer->Write((uint32_t)CMD_W(cs->commands[i]->entries.size()));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneSubCommandEntry_ActorAction* actorAct = (CutsceneSubCommandEntry_ActorAction*)e;
writer->Write(CMD_HH(actorAct->base, actorAct->startFrame));
writer->Write(CMD_HH(actorAct->endFrame, actorAct->rotX));
writer->Write(CMD_HH(actorAct->rotY, actorAct->rotZ));
writer->Write(CMD_W(actorAct->startPosX));
writer->Write(CMD_W(actorAct->startPosY));
writer->Write(CMD_W(actorAct->startPosZ));
writer->Write(CMD_W(actorAct->endPosX));
writer->Write(CMD_W(actorAct->endPosY));
writer->Write(CMD_W(actorAct->endPosZ));
writer->Write(CMD_W(actorAct->normalX));
writer->Write(CMD_W(actorAct->normalY));
writer->Write(CMD_W(actorAct->normalZ));
}
break;
}
case (uint32_t)CutsceneCommands::SetSceneTransFX:
{
CutsceneCommandSceneTransFX* cmdTFX = (CutsceneCommandSceneTransFX*)cs->commands[i];
writer->Write(CS_CMD_SCENE_TRANS_FX);
writer->Write((uint32_t)1);
writer->Write(CMD_HH((((CutsceneCommandSceneTransFX*)cs->commands[i])->base), ((CutsceneCommandSceneTransFX*)cs->commands[i])->startFrame));
writer->Write(CMD_HH((((CutsceneCommandSceneTransFX*)cs->commands[i])->endFrame), ((CutsceneCommandSceneTransFX*)cs->commands[i])->endFrame));
break;
}
case (uint32_t)CutsceneCommands::PlayBGM:
{
writer->Write(CS_CMD_PLAYBGM);
writer->Write((uint32_t)CMD_W(cs->commands[i]->entries.size()));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneSubCommandEntry_GenericCmd* cmd = (CutsceneSubCommandEntry_GenericCmd*)e;
writer->Write(CMD_HH(cmd->base, cmd->startFrame));
writer->Write(CMD_HH(cmd->endFrame, cmd->pad));
writer->Write(CMD_W(cmd->unused1));
writer->Write(CMD_W(cmd->unused2));
writer->Write(CMD_W(cmd->unused3));
writer->Write(CMD_W(cmd->unused4));
writer->Write(CMD_W(cmd->unused5));
writer->Write(CMD_W(cmd->unused6));
writer->Write(CMD_W(cmd->unused7));
writer->Write((uint32_t)0);
writer->Write((uint32_t)0);
writer->Write((uint32_t)0);
}
break;
}
case (uint32_t)CutsceneCommands::StopBGM:
{
writer->Write(CS_CMD_STOPBGM);
writer->Write((uint32_t)CMD_W(cs->commands[i]->entries.size()));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneSubCommandEntry_GenericCmd* cmd = (CutsceneSubCommandEntry_GenericCmd*)e;
writer->Write(CMD_HH(cmd->base, cmd->startFrame));
writer->Write(CMD_HH(cmd->endFrame, cmd->pad));
writer->Write(CMD_W(cmd->unused1));
writer->Write(CMD_W(cmd->unused2));
writer->Write(CMD_W(cmd->unused3));
writer->Write(CMD_W(cmd->unused4));
writer->Write(CMD_W(cmd->unused5));
writer->Write(CMD_W(cmd->unused6));
writer->Write(CMD_W(cmd->unused7));
writer->Write((uint32_t)0);
writer->Write((uint32_t)0);
writer->Write((uint32_t)0);
}
break;
}
case (uint32_t)CutsceneCommands::FadeBGM:
{
writer->Write(CS_CMD_FADEBGM);
writer->Write((uint32_t)CMD_W(cs->commands[i]->entries.size()));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneSubCommandEntry_GenericCmd* cmd = (CutsceneSubCommandEntry_GenericCmd*)e;
writer->Write(CMD_HH(cmd->base, cmd->startFrame));
writer->Write(CMD_HH(cmd->endFrame, cmd->pad));
writer->Write(CMD_W(cmd->unused1));
writer->Write(CMD_W(cmd->unused2));
writer->Write(CMD_W(cmd->unused3));
writer->Write(CMD_W(cmd->unused4));
writer->Write(CMD_W(cmd->unused5));
writer->Write(CMD_W(cmd->unused6));
writer->Write(CMD_W(cmd->unused7));
writer->Write((uint32_t)0);
writer->Write((uint32_t)0);
writer->Write((uint32_t)0);
}
break;
}
case (uint32_t)CutsceneCommands::SetTime:
{
writer->Write(CS_CMD_SETTIME);
writer->Write((uint32_t)CMD_W(cs->commands[i]->entries.size()));
for (const auto& e : cs->commands[i]->entries)
{
CutsceneSubCommandEntry_SetTime* t = (CutsceneSubCommandEntry_SetTime*)e;
writer->Write(CMD_HH(t->base, t->startFrame));
writer->Write(CMD_HBB(t->endFrame, t->hour, t->minute));
writer->Write((uint32_t)CMD_W(t->unk_08));
}
break;
}
case (uint32_t)CutsceneCommands::Terminator:
{
CutsceneCommand_Terminator* t = (CutsceneCommand_Terminator*)cs->commands[i];
writer->Write(CS_CMD_TERMINATOR);
writer->Write((uint32_t)1);
writer->Write(CMD_HH(t->base, t->startFrame));
writer->Write(CMD_HH(t->endFrame, t->endFrame));
break;
}
default:
{
//writer->Write((uint32_t)cs->commands[i]->commandID);
printf("Undefined CS Opcode: %04X\n", cs->commands[i]->commandID);
}
break;
}
}
//CS_END
writer->Write(0xFFFFFFFF);
writer->Write((uint32_t)0);
const auto endStream = writer->GetBaseAddress();
writer->Seek((uint32_t)currentStream - 4, SeekOffsetType::Start);
writer->Write((uint32_t)((endStream - currentStream) / 4));
writer->Seek((uint32_t)endStream, SeekOffsetType::Start);
}

View file

@ -0,0 +1,11 @@
#pragma once
#include "ZResource.h"
#include "ZCutscene.h"
#include "z64cutscene_commands.h"
#include "Exporter.h"
class OTRExporter_Cutscene : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,907 @@
#include "DisplayListExporter.h"
#include "Main.h"
#include "../ZAPD/ZFile.h"
#include <Utils/MemoryStream.h>
#include <Utils/BitConverter.h>
#include "StrHash64/StrHash64.h"
#include "spdlog/spdlog.h"
#include <libultraship/libultra/gbi.h>
#include <Globals.h>
#include <iostream>
#include <string>
#include "MtxExporter.h"
#include <Utils/DiskFile.h>
#include "VersionInfo.h"
#define GFX_SIZE 8
#define gsDPSetCombineLERP_NoMacros(a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, \
a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) \
{ \
_SHIFTL(G_SETCOMBINE, 24, 8) | \
_SHIFTL(GCCc0w0(a0, c0, \
Aa0, Ac0) | \
GCCc1w0(a1, c1), 0, 24), \
(unsigned int)(GCCc0w1(b0, d0, \
Ab0, Ad0) | \
GCCc1w1(b1, Aa1, \
Ac1, d1, \
Ab1, Ad1)) \
}
#define gsSPBranchLessZraw2(dl, vtx, zval) \
{ _SHIFTL(G_BRANCH_Z,24,8)|_SHIFTL((vtx)*5,12,12)|_SHIFTL((vtx)*2,0,12),\
(unsigned int)(zval), }
#define gsSPBranchLessZraw3(dl) \
{ _SHIFTL(G_RDPHALF_1,24,8), \
(unsigned int)(dl), }
#define gsDPWordLo(wordlo) \
gsImmp1(G_RDPHALF_2, (unsigned int)(wordlo))
#define gsSPTextureRectangle2(xl, yl, xh, yh, tile) \
{ (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | _SHIFTL(yh, 0, 12)),\
(_SHIFTL(tile, 24, 3) | _SHIFTL(xl, 12, 12) | _SHIFTL(yl, 0, 12)) }
void OTRExporter_DisplayList::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZDisplayList* dList = (ZDisplayList*)res;
//printf("Exporting DList %s\n", dList->GetName().c_str());
WriteHeader(res, outPath, writer, LUS::ResourceType::DisplayList);
while (writer->GetBaseAddress() % 8 != 0)
writer->Write((uint8_t)0xFF);
// DEBUG: Write in a marker
Declaration* dbgDecl = dList->parent->GetDeclaration(dList->GetRawDataIndex());
std::string dbgName = StringHelper::Sprintf("%s/%s", GetParentFolderName(res).c_str(), dbgDecl->varName.c_str());
uint64_t hash = CRC64(dbgName.c_str());
writer->Write((uint32_t)(G_MARKER << 24));
writer->Write((uint32_t)0xBEEFBEEF);
writer->Write((uint32_t)(hash >> 32));
writer->Write((uint32_t)(hash & 0xFFFFFFFF));
auto dlStart = std::chrono::steady_clock::now();
//for (auto data : dList->instructions)
for (size_t dataIdx = 0; dataIdx < dList->instructions.size(); dataIdx++)
{
auto data = dList->instructions[dataIdx];
uint32_t word0 = 0;
uint32_t word1 = 0;
uint8_t opcode = (uint8_t)(data >> 56);
F3DZEXOpcode opF3D = (F3DZEXOpcode)opcode;
if ((int)opF3D == G_DL)// || (int)opF3D == G_BRANCH_Z)
opcode = (uint8_t)G_DL_OTR_HASH;
if ((int)opF3D == G_MTX)
opcode = (uint8_t)G_MTX_OTR;
if ((int)opF3D == G_BRANCH_Z)
opcode = (uint8_t)G_BRANCH_Z_OTR;
if ((int)opF3D == G_VTX)
opcode = (uint8_t)G_VTX_OTR_HASH;
if ((int)opF3D == G_SETTIMG)
opcode = (uint8_t)G_SETTIMG_OTR_HASH;
word0 += (opcode << 24);
switch ((int)opF3D)
{
case G_NOOP:
{
Gfx value = {gsDPNoOp()};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_ENDDL:
{
Gfx value = {gsSPEndDisplayList()};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_MODIFYVTX:
{
int32_t ww = (data & 0x00FF000000000000ULL) >> 48;
int32_t nnnn = (data & 0x0000FFFF00000000ULL) >> 32;
int32_t vvvvvvvv = (data & 0x00000000FFFFFFFFULL);
Gfx value = {gsSPModifyVertex(nnnn / 2, ww, vvvvvvvv)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
default:
{
printf("Undefined opcode: %02X\n", opcode);
//word0 = _byteswap_ulong((uint32_t)(data >> 32));
//word1 = _byteswap_ulong((uint32_t)(data & 0xFFFFFFFF));
}
break;
case G_GEOMETRYMODE:
{
int32_t cccccc = (data & 0x00FFFFFF00000000) >> 32;
int32_t ssssssss = (data & 0xFFFFFFFF);
Gfx value = {gsSPGeometryMode(~cccccc, ssssssss)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_RDPPIPESYNC:
{
Gfx value = {gsDPPipeSync()};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_RDPLOADSYNC:
{
Gfx value = {gsDPLoadSync()};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_RDPTILESYNC:
{
Gfx value = {gsDPTileSync()};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_RDPFULLSYNC:
{
Gfx value = {gsDPFullSync()};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_RDPSETOTHERMODE:
{
int32_t hhhhhh = (data & 0x00FFFFFF00000000) >> 32;
int32_t llllllll = (data & 0x00000000FFFFFFFF);
Gfx value = {gsDPSetOtherMode(hhhhhh, llllllll)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_POPMTX:
{
Gfx value = {gsSPPopMatrix(data)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_SETENVCOLOR:
{
uint8_t r = (uint8_t)((data & 0xFF000000) >> 24);
uint8_t g = (uint8_t)((data & 0x00FF0000) >> 16);
uint8_t b = (uint8_t)((data & 0xFF00FF00) >> 8);
uint8_t a = (uint8_t)((data & 0x000000FF) >> 0);
Gfx value = {gsDPSetEnvColor(r, g, b, a)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_MTX:
{
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 mm = (data & 0x00000000FFFFFFFF);
pp ^= G_MTX_PUSH;
mm = (mm & 0x0FFFFFFF) + 1;
Gfx value = {gsSPMatrix(mm, pp)};
word0 = value.words.w0;
word1 = value.words.w1;
}
else
{
uint32_t pp = (data & 0x000000FF00000000) >> 32;
uint32_t mm = (data & 0x00000000FFFFFFFF);
pp ^= G_MTX_PUSH;
Gfx value = {gsSPMatrix(mm, pp)};
word0 = value.words.w0;
word1 = value.words.w1;
word0 = (word0 & 0x00FFFFFF) + (G_MTX_OTR << 24);
Declaration* mtxDecl = dList->parent->GetDeclaration(GETSEGOFFSET(mm));
int bp = 0;
writer->Write(word0);
writer->Write(word1);
if (mtxDecl != nullptr)
{
std::string vName = StringHelper::Sprintf("%s/%s", (GetParentFolderName(res).c_str()), mtxDecl->varName.c_str());
uint64_t hash = CRC64(vName.c_str());
word0 = hash >> 32;
word1 = hash & 0xFFFFFFFF;
}
else
{
word0 = 0;
word1 = 0;
spdlog::error(StringHelper::Sprintf("dListDecl == nullptr! Addr = {:08X}", GETSEGOFFSET(data)));
}
}
}
break;
case G_LOADBLOCK:
{
int32_t sss = (data & 0x00FFF00000000000) >> 48;
int32_t ttt = (data & 0x00000FFF00000000) >> 36;
int32_t i = (data & 0x000000000F000000) >> 24;
int32_t xxx = (data & 0x0000000000FFF000) >> 12;
int32_t ddd = (data & 0x0000000000000FFF);
Gfx value = {gsDPLoadBlock(i, sss, ttt, xxx, ddd)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_CULLDL:
{
int32_t vvvv = (data & 0xFFFF00000000) >> 32;
int32_t wwww = (data & 0x0000FFFF);
Gfx value = {gsSPCullDisplayList(vvvv / 2, wwww / 2)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_RDPHALF_1:
{
auto data2 = dList->instructions[dataIdx + 1];
if ((data2 >> 56) != G_BRANCH_Z)
{
uint32_t a = (data & 0x00FFF00000000000) >> 44;
uint32_t b = (data & 0x00000FFF00000000) >> 32;
uint32_t z = (data & 0x00000000FFFFFFFF) >> 0;
uint32_t h = (data & 0xFFFFFFFF);
Gfx value = {gsSPBranchLessZraw3(h & 0x00FFFFFF)};
word0 = value.words.w0;
word1 = value.words.w1;
}
else
{
word0 = (G_NOOP << 24);
word1 = 0;
}
}
break;
case G_RDPHALF_2:
{
Gfx value = {gsDPWordLo(data & 0xFFFFFFFF)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_TEXRECT:
{
int32_t xxx = (data & 0x00FFF00000000000) >> 44;
int32_t yyy = (data & 0x00000FFF00000000) >> 32;
int32_t i = (data & 0x000000000F000000) >> 24;
int32_t XXX = (data & 0x0000000000FFF000) >> 12;
int32_t YYY = (data & 0x0000000000000FFF);
Gfx value = {gsSPTextureRectangle2(XXX, YYY, xxx, yyy, i)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_BRANCH_Z:
{
uint32_t a = (data & 0x00FFF00000000000) >> 44;
uint32_t b = (data & 0x00000FFF00000000) >> 32;
uint32_t z = (data & 0x00000000FFFFFFFF) >> 0;
uint32_t h = (data & 0xFFFFFFFF);
auto data2 = dList->instructions[dataIdx - 1];
uint32_t dListPtr = GETSEGOFFSET(data2);
Declaration* dListDecl = dList->parent->GetDeclaration(dListPtr);
int bp = 0;
Gfx value = {gsSPBranchLessZraw2(0xDEADABCD, (a / 5) | (b / 2), z)};
word0 = (value.words.w0 & 0x00FFFFFF) + (G_BRANCH_Z_OTR << 24);
word1 = value.words.w1;
writer->Write(word0);
writer->Write(word1);
if (dListDecl != nullptr)
{
std::string vName = StringHelper::Sprintf("%s/%s", (GetParentFolderName(res).c_str()), dListDecl->varName.c_str());
uint64_t hash = CRC64(vName.c_str());
word0 = hash >> 32;
word1 = hash & 0xFFFFFFFF;
}
else
{
word0 = 0;
word1 = 0;
spdlog::error(StringHelper::Sprintf("dListDecl == nullptr! Addr = {:08X}", GETSEGOFFSET(data)));
}
for (size_t i = 0; i < dList->otherDLists.size(); i++)
{
Declaration* dListDecl2 = dList->parent->GetDeclaration(GETSEGOFFSET(dList->otherDLists[i]->GetRawDataIndex()));
if (dListDecl2 != nullptr)
{
//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());
if (files.find(fName) == files.end() && !DiskFile::Exists("Extract/" + fName))
{
MemoryStream* dlStream = new MemoryStream();
BinaryWriter dlWriter = BinaryWriter(dlStream);
Save(dList->otherDLists[i], outPath, &dlWriter);
AddFile(fName, dlStream->ToVector());
}
}
else
{
spdlog::error(StringHelper::Sprintf("dListDecl2 == nullptr! Addr = {:08X}", GETSEGOFFSET(data)));
}
}
//Gfx value = gsSPBranchLessZraw2(h & 0x00FFFFFF, (a / 5) | (b / 2), z);
//word0 = value.words.w0;
//word1 = value.words.w1;
}
break;
//case G_BRANCH_Z:
case G_DL:
{
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
{
int32_t pp = (data & 0x00FF000000000000) >> 56;
Gfx value;
u32 dListVal = (data & 0x0FFFFFFF) + 1;
if (pp != 0)
value = {gsSPBranchList(dListVal)};
else
value = {gsSPDisplayList(dListVal)};
word0 = value.words.w0;
word1 = value.words.w1;
}
else
{
uint32_t dListPtr = GETSEGOFFSET(data);
if ((int)opF3D == G_BRANCH_Z)
{
auto data2 = dList->instructions[dataIdx - 1];
dListPtr = GETSEGOFFSET(data2);
}
else
{
int bp = 0;
}
Declaration* dListDecl = dList->parent->GetDeclaration(dListPtr);
int bp = 0;
writer->Write(word0);
writer->Write(word1);
if (dListDecl != nullptr)
{
std::string vName = StringHelper::Sprintf("%s/%s", (GetParentFolderName(res).c_str()), dListDecl->varName.c_str());
uint64_t hash = CRC64(vName.c_str());
word0 = hash >> 32;
word1 = hash & 0xFFFFFFFF;
}
else
{
word0 = 0;
word1 = 0;
spdlog::error(StringHelper::Sprintf("dListDecl == nullptr! Addr = {:08X}", GETSEGOFFSET(data)));
}
for (size_t i = 0; i < dList->otherDLists.size(); i++)
{
Declaration* dListDecl2 = dList->parent->GetDeclaration(GETSEGOFFSET(dList->otherDLists[i]->GetRawDataIndex()));
if (dListDecl2 != nullptr)
{
//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());
if (files.find(fName) == files.end() && !DiskFile::Exists("Extract/" + fName))
{
MemoryStream* dlStream = new MemoryStream();
BinaryWriter dlWriter = BinaryWriter(dlStream);
Save(dList->otherDLists[i], outPath, &dlWriter);
AddFile(fName, dlStream->ToVector());
}
}
else
{
spdlog::error(StringHelper::Sprintf("dListDecl2 == nullptr! Addr = {:08X}", GETSEGOFFSET(data)));
}
}
}
}
break;
case G_TEXTURE:
{
int32_t ____ = (data & 0x0000FFFF00000000) >> 32;
int32_t ssss = (data & 0x00000000FFFF0000) >> 16;
int32_t tttt = (data & 0x000000000000FFFF);
int32_t lll = (____ & 0x3800) >> 11;
int32_t ddd = (____ & 0x700) >> 8;
int32_t nnnnnnn = (____ & 0xFE) >> 1;
Gfx value = {gsSPTexture(ssss, tttt, lll, ddd, nnnnnnn)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_TRI1:
{
int32_t aa = ((data & 0x00FF000000000000ULL) >> 48) / 2;
int32_t bb = ((data & 0x0000FF0000000000ULL) >> 40) / 2;
int32_t cc = ((data & 0x000000FF00000000ULL) >> 32) / 2;
Gfx test = {gsSP1Triangle(aa, bb, cc, 0)};
word0 = test.words.w0;
word1 = test.words.w1;
}
break;
case G_TRI2:
{
int32_t aa = ((data & 0x00FF000000000000ULL) >> 48) / 2;
int32_t bb = ((data & 0x0000FF0000000000ULL) >> 40) / 2;
int32_t cc = ((data & 0x000000FF00000000ULL) >> 32) / 2;
int32_t dd = ((data & 0x00000000FF0000ULL) >> 16) / 2;
int32_t ee = ((data & 0x0000000000FF00ULL) >> 8) / 2;
int32_t ff = ((data & 0x000000000000FFULL) >> 0) / 2;
Gfx test = {gsSP2Triangles(aa, bb, cc, 0, dd, ee, ff, 0)};
word0 = test.words.w0;
word1 = test.words.w1;
}
break;
case G_QUAD:
{
int32_t aa = ((data & 0x00FF000000000000ULL) >> 48) / 2;
int32_t bb = ((data & 0x0000FF0000000000ULL) >> 40) / 2;
int32_t cc = ((data & 0x000000FF00000000ULL) >> 32) / 2;
int32_t dd = ((data & 0x000000000000FFULL)) / 2;
Gfx test = {gsSP1Quadrangle(aa, bb, cc, dd, 0)};
word0 = test.words.w0;
word1 = test.words.w1;
}
break;
case G_SETPRIMCOLOR:
{
int32_t mm = (data & 0x0000FF0000000000) >> 40;
int32_t ff = (data & 0x000000FF00000000) >> 32;
int32_t rr = (data & 0x00000000FF000000) >> 24;
int32_t gg = (data & 0x0000000000FF0000) >> 16;
int32_t bb = (data & 0x000000000000FF00) >> 8;
int32_t aa = (data & 0x00000000000000FF) >> 0;
Gfx value = {gsDPSetPrimColor(mm, ff, rr, gg, bb, aa)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_SETOTHERMODE_L:
{
int32_t ss = (data & 0x0000FF0000000000) >> 40;
int32_t len = ((data & 0x000000FF00000000) >> 32) + 1;
int32_t sft = 32 - (len)-ss;
int32_t dd = (data & 0xFFFFFFFF);
// TODO: Output the correct render modes in data
Gfx value = {gsSPSetOtherMode(0xE2, sft, len, dd)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_SETOTHERMODE_H:
{
int32_t ss = (data & 0x0000FF0000000000) >> 40;
int32_t nn = (data & 0x000000FF00000000) >> 32;
int32_t dd = (data & 0xFFFFFFFF);
int32_t sft = 32 - (nn + 1) - ss;
Gfx value;
if (sft == 14) // G_MDSFT_TEXTLUT
{
const char* types[] = { "G_TT_NONE", "G_TT_NONE", "G_TT_RGBA16", "G_TT_IA16" };
value = {gsDPSetTextureLUT(dd >> 14)};
}
else
{
value = {gsSPSetOtherMode(0xE3, sft, nn + 1, dd)};
}
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_SETTILE:
{
int32_t fff = (data & 0b0000000011100000000000000000000000000000000000000000000000000000) >> 53;
int32_t ii = (data & 0b0000000000011000000000000000000000000000000000000000000000000000) >> 51;
int32_t nnnnnnnnn =
(data & 0b0000000000000011111111100000000000000000000000000000000000000000) >> 41;
int32_t mmmmmmmmm =
(data & 0b0000000000000000000000011111111100000000000000000000000000000000) >> 32;
int32_t ttt = (data & 0b0000000000000000000000000000000000000111000000000000000000000000) >> 24;
int32_t pppp =
(data & 0b0000000000000000000000000000000000000000111100000000000000000000) >> 20;
int32_t cc = (data & 0b0000000000000000000000000000000000000000000011000000000000000000) >> 18;
int32_t aaaa =
(data & 0b0000000000000000000000000000000000000000000000111100000000000000) >> 14;
int32_t ssss =
(data & 0b0000000000000000000000000000000000000000000000000011110000000000) >> 10;
int32_t dd = (data & 0b0000000000000000000000000000000000000000000000000000001100000000) >> 8;
int32_t bbbb = (data & 0b0000000000000000000000000000000000000000000000000000000011110000) >> 4;
int32_t uuuu = (data & 0b0000000000000000000000000000000000000000000000000000000000001111);
Gfx value = {gsDPSetTile(fff, ii, nnnnnnnnn, mmmmmmmmm, ttt, pppp, cc, aaaa, ssss, dd, bbbb, uuuu)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_SETCOMBINE:
{
int32_t a0 = (data & 0b000000011110000000000000000000000000000000000000000000000000000) >> 52;
int32_t c0 = (data & 0b000000000001111100000000000000000000000000000000000000000000000) >> 47;
int32_t aa0 = (data & 0b00000000000000011100000000000000000000000000000000000000000000) >> 44;
int32_t ac0 = (data & 0b00000000000000000011100000000000000000000000000000000000000000) >> 41;
int32_t a1 = (data & 0b000000000000000000000011110000000000000000000000000000000000000) >> 37;
int32_t c1 = (data & 0b000000000000000000000000001111100000000000000000000000000000000) >> 32;
int32_t b0 = (data & 0b000000000000000000000000000000011110000000000000000000000000000) >> 28;
int32_t b1 = (data & 0b000000000000000000000000000000000001111000000000000000000000000) >> 24;
int32_t aa1 = (data & 0b00000000000000000000000000000000000000111000000000000000000000) >> 21;
int32_t ac1 = (data & 0b00000000000000000000000000000000000000000111000000000000000000) >> 18;
int32_t d0 = (data & 0b000000000000000000000000000000000000000000000111000000000000000) >> 15;
int32_t ab0 = (data & 0b00000000000000000000000000000000000000000000000111000000000000) >> 12;
int32_t ad0 = (data & 0b00000000000000000000000000000000000000000000000000111000000000) >> 9;
int32_t d1 = (data & 0b000000000000000000000000000000000000000000000000000000111000000) >> 6;
int32_t ab1 = (data & 0b00000000000000000000000000000000000000000000000000000000111000) >> 3;
int32_t ad1 = (data & 0b00000000000000000000000000000000000000000000000000000000000111) >> 0;
Gfx value = { gsDPSetCombineLERP_NoMacros(a0, b0, c0, d0, aa0, ab0, ac0, ad0, a1, b1, c1, d1, aa1, ab1, ac1, ad1)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_SETTILESIZE:
{
int32_t sss = (data & 0x00FFF00000000000) >> 44;
int32_t ttt = (data & 0x00000FFF00000000) >> 32;
int32_t uuu = (data & 0x0000000000FFF000) >> 12;
int32_t vvv = (data & 0x0000000000000FFF);
int32_t i = (data & 0x000000000F000000) >> 24;
Gfx value = {gsDPSetTileSize(i, sss, ttt, uuu, vvv)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_LOADTLUT:
{
int32_t t = (data & 0x0000000007000000) >> 24;
int32_t ccc = (data & 0x00000000003FF000) >> 14;
Gfx value = {gsDPLoadTLUTCmd(t, ccc)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_LOADTILE:
{
int sss = (data & 0x00FFF00000000000) >> 44;
int ttt = (data & 0x00000FFF00000000) >> 32;
int i = (data & 0x000000000F000000) >> 24;
int uuu = (data & 0x0000000000FFF000) >> 12;
int vvv= (data & 0x0000000000000FFF);
Gfx value = {gsDPLoadTile(i, sss, ttt, uuu, vvv)};
word0 = value.words.w0;
word1 = value.words.w1;
}
break;
case G_SETTIMG:
{
uint32_t seg = data & 0xFFFFFFFF;
int32_t texAddress = Seg2Filespace(data, dList->parent->baseAddress);
if (!Globals::Instance->HasSegment(GETSEGNUM(seg), res->parent->workerID) || (res->GetName() == "sShadowMaterialDL"))
{
if (res->GetName() == "sShadowMaterialDL") {
// sShadowMaterialDL (In ovl_En_Jsjutan) has a texture in bss. This is a hack to override the reference to one
// to segment C. The actor has been modified to load the texture into segment C.
seg = 0x0C000000;
}
int32_t __ = (data & 0x00FF000000000000) >> 48;
int32_t www = (data & 0x00000FFF00000000) >> 32;
uint32_t fmt = (__ & 0xE0) >> 5;
uint32_t siz = (__ & 0x18) >> 3;
Gfx value = {gsDPSetTextureImage(fmt, siz, www + 1, (seg & 0x0FFFFFFF) + 1)};
word0 = value.words.w0;
word1 = value.words.w1;
writer->Write(word0);
writer->Write(word1);
}
else
{
std::string texName = "";
bool foundDecl = Globals::Instance->GetSegmentedPtrName(seg, dList->parent, "", texName, res->parent->workerID);
int32_t __ = (data & 0x00FF000000000000) >> 48;
int32_t www = (data & 0x00000FFF00000000) >> 32;
uint32_t fmt = (__ & 0xE0) >> 5;
uint32_t siz = (__ & 0x18) >> 3;
Gfx value = {gsDPSetTextureImage(fmt, siz, www + 1, __)};
word0 = value.words.w0 & 0x00FFFFFF;
word0 += (G_SETTIMG_OTR_HASH << 24);
//word1 = value.words.w1;
word1 = 0;
writer->Write(word0);
writer->Write(word1);
if (foundDecl)
{
ZFile* assocFile = Globals::Instance->GetSegment(GETSEGNUM(seg), res->parent->workerID);
std::string assocFileName = assocFile->GetName();
std::string fName = "";
if (GETSEGNUM(seg) == SEGMENT_SCENE || GETSEGNUM(seg) == SEGMENT_ROOM)
fName = GetPathToRes(res, texName.c_str());
else
fName = GetPathToRes(assocFile->resources[0], texName.c_str());
uint64_t hash = CRC64(fName.c_str());
word0 = hash >> 32;
word1 = hash & 0xFFFFFFFF;
}
else
{
word0 = 0;
word1 = 0;
spdlog::error("texDecl == nullptr! PTR = 0x{:08X}", texAddress);
}
}
}
break;
case G_VTX:
{
if (GETSEGNUM(data) == 0xC || GETSEGNUM(data) == 0x8)
{
// hack for dynamic verticies used in en_ganon_mant and en_jsjutan
// TODO is there a better way?
int32_t aa = (data & 0x000000FF00000000ULL) >> 32;
int32_t nn = (data & 0x000FF00000000000ULL) >> 44;
Gfx value = {gsSPVertex(data & 0xFFFFFFFF, nn, ((aa >> 1) - nn))};
word0 = value.words.w0;
word1 = value.words.w1 | 1;
}
else
{
// Write CRC64 of vtx file name
uint32_t addr = data & 0xFFFFFFFF;
if (GETSEGNUM(data) == 0x80)
addr -= dList->parent->baseAddress;
auto segOffset = GETSEGOFFSET(addr);
Declaration* vtxDecl = dList->parent->GetDeclarationRanged(segOffset);
int32_t aa = (data & 0x000000FF00000000ULL) >> 32;
int32_t nn = (data & 0x000FF00000000000ULL) >> 44;
if (vtxDecl != nullptr && vtxDecl->varType != "Gfx")
{
uint32_t diff = segOffset - vtxDecl->address;
Gfx value = {gsSPVertex(diff, nn, ((aa >> 1) - nn))};
word0 = value.words.w0;
word0 &= 0x00FFFFFF;
word0 += (G_VTX_OTR_HASH << 24);
word1 = value.words.w1;
writer->Write(word0);
writer->Write(word1);
std::string fName = OTRExporter_DisplayList::GetPathToRes(res, vtxDecl->varName);
uint64_t hash = CRC64(fName.c_str());
word0 = hash >> 32;
word1 = hash & 0xFFFFFFFF;
if (files.find(fName) == files.end() && !DiskFile::Exists("Extract/" + fName))
{
// Write vertices to file
MemoryStream* vtxStream = new MemoryStream();
BinaryWriter vtxWriter = BinaryWriter(vtxStream);
int arrCnt = 0;
auto split = StringHelper::Split(vtxDecl->text, "\n");
for (size_t i = 0; i < split.size(); i++)
{
std::string line = split[i];
if (StringHelper::Contains(line, "VTX("))
arrCnt++;
}
// OTRTODO: Once we aren't relying on text representations, we should call ArrayExporter...
OTRExporter::WriteHeader(nullptr, "", &vtxWriter, LUS::ResourceType::Array);
vtxWriter.Write((uint32_t)ZResourceType::Vertex);
vtxWriter.Write((uint32_t)arrCnt);
auto start = std::chrono::steady_clock::now();
// God dammit this is so dumb
for (size_t i = 0; i < split.size(); i++)
{
std::string line = split[i];
if (StringHelper::Contains(line, "VTX("))
{
auto split2 = StringHelper::Split(StringHelper::Split(StringHelper::Split(line, "VTX(")[1], ")")[0], ",");
vtxWriter.Write((int16_t)std::stoi(split2[0], nullptr, 10)); // v.x
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((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[7], nullptr, 10)); // v.b
vtxWriter.Write((uint8_t)std::stoi(split2[8], nullptr, 10)); // v.a
}
}
AddFile(fName, vtxStream->ToVector());
auto end = std::chrono::steady_clock::now();
size_t diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
}
}
else
{
spdlog::error("vtxDecl == nullptr!");
}
}
}
break;
}
writer->Write(word0);
writer->Write(word1);
}
auto dlEnd = std::chrono::steady_clock::now();
size_t dlDiff = std::chrono::duration_cast<std::chrono::milliseconds>(dlEnd - dlStart).count();
//printf("Display List Gen in %zums\n", dlDiff);
}
std::string OTRExporter_DisplayList::GetPathToRes(ZResource* res, std::string varName)
{
std::string prefix = GetPrefix(res);
std::string fName = StringHelper::Sprintf("%s/%s", GetParentFolderName(res).c_str(), varName.c_str());
return fName;
}
std::string OTRExporter_DisplayList::GetParentFolderName(ZResource* res)
{
std::string prefix = GetPrefix(res);
std::string oName = res->parent->GetOutName();
if (StringHelper::Contains(oName, "_scene"))
{
auto split = StringHelper::Split(oName, "_");
oName = "";
for (size_t i = 0; i < split.size() - 1; i++)
oName += split[i] + "_";
oName += "scene";
}
else if (StringHelper::Contains(oName, "_room"))
{
oName = StringHelper::Split(oName, "_room")[0] + "_scene";
}
if (prefix != "")
oName = prefix + "/" + oName;
return oName;
}
std::string OTRExporter_DisplayList::GetPrefix(ZResource* res)
{
std::string oName = res->parent->GetOutName();
std::string prefix = "";
std::string xmlPath = StringHelper::Replace(res->parent->GetXmlFilePath().string(), "\\", "/");
if (StringHelper::Contains(oName, "_scene") || StringHelper::Contains(oName, "_room")) {
prefix = "scenes";
if (Globals::Instance->rom->IsMQ()) {
prefix += "/mq";
} else {
prefix += "/nonmq";
}
}
else if (StringHelper::Contains(xmlPath, "objects/"))
prefix = "objects";
else if (StringHelper::Contains(xmlPath, "textures/"))
prefix = "textures";
else if (StringHelper::Contains(xmlPath, "overlays/"))
prefix = "overlays";
else if (StringHelper::Contains(xmlPath, "misc/"))
prefix = "misc";
else if (StringHelper::Contains(xmlPath, "text/"))
prefix = "text";
else if (StringHelper::Contains(xmlPath, "code/"))
prefix = "code";
return prefix;
}

View file

@ -0,0 +1,17 @@
#pragma once
#include "ZResource.h"
#include "ZTexture.h"
#include "ZDisplayList.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_DisplayList : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
static std::string GetParentFolderName(ZResource* res);
static std::string GetPathToRes(ZResource* res, std::string varName);
static std::string GetPrefix(ZResource* res);
};

View file

@ -0,0 +1,21 @@
#include "Exporter.h"
#include "VersionInfo.h"
void OTRExporter::WriteHeader(ZResource* res, const fs::path& outPath, BinaryWriter* writer, LUS::ResourceType resType, int32_t resVersion)
{
writer->Write((uint8_t)Endianness::Little); // 0x00
writer->Write((uint8_t)0); // 0x01
writer->Write((uint8_t)0); // 0x02
writer->Write((uint8_t)0); // 0x03
writer->Write((uint32_t)resType); // 0x04
//writer->Write((uint32_t)MAJOR_VERSION); // 0x08
writer->Write((uint32_t)resVersion); // 0x08
writer->Write((uint64_t)0xDEADBEEFDEADBEEF); // id, 0x0C
writer->Write((uint32_t)resourceVersions[resType]); // 0x10
writer->Write((uint64_t)0); // ROM CRC, 0x14
writer->Write((uint32_t)0); // ROM Enum, 0x1C
while (writer->GetBaseAddress() < 0x40)
writer->Write((uint32_t)0); // To be used at a later date!
}

View file

@ -0,0 +1,14 @@
#pragma once
#include "ZResource.h"
#include "ZArray.h"
#include "stdint.h"
//#include "OTRExporter.h"
#include <Utils/BinaryWriter.h>
#include <libultraship/bridge.h>
#include "VersionInfo.h"
class OTRExporter : public ZResourceExporter
{
protected:
static void WriteHeader(ZResource* res, const fs::path& outPath, BinaryWriter* writer, LUS::ResourceType resType, int32_t resVersion = 0);
};

View file

@ -0,0 +1,325 @@
#include "Main.h"
#include "Exporter.h"
#include "BackgroundExporter.h"
#include "TextureExporter.h"
#include "RoomExporter.h"
#include "CollisionExporter.h"
#include "DisplayListExporter.h"
#include "PlayerAnimationExporter.h"
#include "SkeletonExporter.h"
#include "SkeletonLimbExporter.h"
#include "ArrayExporter.h"
#include "VtxExporter.h"
#include "AnimationExporter.h"
#include "CutsceneExporter.h"
#include "PathExporter.h"
#include "TextExporter.h"
#include "BlobExporter.h"
#include "MtxExporter.h"
#include "AudioExporter.h"
#include <Globals.h>
#include <Utils/DiskFile.h>
#include <Utils/Directory.h>
#include <Utils/MemoryStream.h>
#include <Utils/BinaryWriter.h>
#include <bit>
#include <mutex>
std::string otrFileName = "oot.otr";
std::shared_ptr<LUS::Archive> otrArchive;
BinaryWriter* fileWriter;
std::chrono::steady_clock::time_point fileStart, resStart;
std::map<std::string, std::vector<char>> files;
std::mutex fileMutex;
void InitVersionInfo();
enum class ExporterFileMode
{
BuildOTR = (int)ZFileMode::Custom + 1,
};
static void ExporterParseFileMode(const std::string& buildMode, ZFileMode& fileMode)
{
if (buildMode == "botr")
{
fileMode = (ZFileMode)ExporterFileMode::BuildOTR;
printf("BOTR: Generating OTR Archive...\n");
if (DiskFile::Exists(otrFileName))
otrArchive = std::shared_ptr<LUS::Archive>(new LUS::Archive(otrFileName, true));
else
otrArchive = LUS::Archive::CreateArchive(otrFileName, 40000);
auto lst = Directory::ListFiles("Extract");
for (auto item : lst)
{
auto fileData = DiskFile::ReadAllBytes(item);
otrArchive->AddFile(StringHelper::Split(item, "Extract/")[1], (uintptr_t)fileData.data(), fileData.size());
}
}
}
static void ExporterProgramEnd()
{
uint32_t crc = 0xFFFFFFFF;
const uint8_t endianness = (uint8_t)Endianness::Big;
if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
{
std::string romPath = Globals::Instance->baseRomPath.string();
const std::vector<uint8_t>& romData = DiskFile::ReadAllBytes(romPath);
crc = BitConverter::ToUInt32BE(romData, 0x10);
printf("Creating version file...\n");
// Get crc from rom
MemoryStream *versionStream = new MemoryStream();
BinaryWriter writer(versionStream);
writer.SetEndianness(Endianness::Big);
writer.Write(endianness);
writer.Write(crc);
writer.Close();
printf("Created version file.\n");
printf("Generating OTR Archive...\n");
otrArchive = LUS::Archive::CreateArchive(otrFileName, 40000);
otrArchive->AddFile("version", (uintptr_t)versionStream->ToVector().data(), versionStream->GetLength());
for (const auto& item : files)
{
std::string fName = item.first;
if (fName.find("gTitleZeldaShieldLogoMQTex") != std::string::npos && !ZRom(romPath).IsMQ())
{
size_t pos = 0;
if ((pos = fName.find("gTitleZeldaShieldLogoMQTex", 0)) != std::string::npos)
{
fName.replace(pos, 27, "gTitleZeldaShieldLogoTex");
}
}
const auto& fileData = item.second;
otrArchive->AddFile(fName, (uintptr_t)fileData.data(),
fileData.size());
}
}
otrArchive = nullptr;
delete fileWriter;
files.clear();
// Add any additional files that need to be manually copied...
if (DiskFile::Exists("soh.otr")) {
return;
}
const auto& lst = Directory::ListFiles("Extract");
std::shared_ptr<LUS::Archive> sohOtr = LUS::Archive::CreateArchive("soh.otr", 4096);
//sohOtr->AddFile("version", (uintptr_t)versionStream->ToVector().data(), versionStream->GetLength());
for (const auto& item : lst)
{
std::vector<std::string> splitPath = StringHelper::Split(item, ".");
if (splitPath.size() >= 3)
{
const std::string extension = splitPath.at(splitPath.size() - 1);
const std::string format = splitPath.at(splitPath.size() - 2);
splitPath.pop_back();
splitPath.pop_back();
std::string afterPath = std::accumulate(splitPath.begin(), splitPath.end(), std::string(""));
if (extension == "png" && (format == "rgba32" || format == "rgb5a1" || format == "i4" || format == "i8" || format == "ia4" || format == "ia8" || format == "ia16" || format == "ci4" || format == "ci8"))
{
ZTexture tex(nullptr);
Globals::Instance->buildRawTexture = true;
tex.FromPNG(item, ZTexture::GetTextureTypeFromString(format));
printf("sohOtr->AddFile(%s)\n", StringHelper::Split(afterPath, "Extract/")[1].c_str());
OTRExporter_Texture exporter;
MemoryStream* stream = new MemoryStream();
BinaryWriter writer(stream);
exporter.Save(&tex, "", &writer);
std::string src = tex.GetBodySourceCode();
writer.Write((char *)src.c_str(), src.size());
std::vector<char> fileData = stream->ToVector();
sohOtr->AddFile(StringHelper::Split(afterPath, "Extract/assets/")[1], (uintptr_t)fileData.data(), fileData.size());
continue;
}
}
if (item.find("accessibility") != std::string::npos)
{
std::string extension = splitPath.at(splitPath.size() - 1);
splitPath.pop_back();
if (extension == "json")
{
const auto &fileData = DiskFile::ReadAllBytes(item);
printf("Adding accessibility texts %s\n", StringHelper::Split(item, "texts/")[1].c_str());
sohOtr->AddFile(StringHelper::Split(item, "Extract/assets/")[1], (uintptr_t)fileData.data(), fileData.size());
}
continue;
}
const auto& fileData = DiskFile::ReadAllBytes(item);
printf("sohOtr->AddFile(%s)\n", StringHelper::Split(item, "Extract/")[1].c_str());
sohOtr->AddFile(StringHelper::Split(item, item.find("Extract/assets/") != std::string::npos ? "Extract/assets/" : "Extract/")[1], (uintptr_t)fileData.data(), fileData.size());
}
sohOtr = nullptr;
}
static void ExporterParseArgs(int argc, char* argv[], int& i)
{
std::string arg = argv[i];
if (arg == "--otrfile")
{
otrFileName = argv[i + 1];
i++;
}
}
static bool ExporterProcessFileMode(ZFileMode fileMode)
{
// Do whatever work is associated with these custom file modes...
// Return true to indicate one of our own file modes is being processed
if (fileMode == (ZFileMode)ExporterFileMode::BuildOTR)
return true;
return false;
}
static void ExporterFileBegin(ZFile* file)
{
fileStart = std::chrono::steady_clock::now();
MemoryStream* stream = new MemoryStream();
fileWriter = new BinaryWriter(stream);
}
static void ExporterFileEnd(ZFile* file)
{
// delete fileWriter;
}
static void ExporterResourceEnd(ZResource* res, BinaryWriter& writer)
{
auto streamShared = writer.GetStream();
MemoryStream* strem = (MemoryStream*)streamShared.get();
auto start = std::chrono::steady_clock::now();
if (res->GetName() != "")
{
std::string oName = res->parent->GetOutName();
std::string rName = res->GetName();
std::string prefix = OTRExporter_DisplayList::GetPrefix(res);
//auto xmlFilePath = res->parent->GetXmlFilePath();
//prefix = StringHelper::Split(StringHelper::Split(xmlFilePath.string(), "xml\\")[1], ".xml")[0];
if (StringHelper::Contains(oName, "_scene"))
{
auto split = StringHelper::Split(oName, "_");
oName = "";
for (size_t i = 0; i < split.size() - 1; i++)
oName += split[i] + "_";
oName += "scene";
}
else if (StringHelper::Contains(oName, "_room"))
{
oName = StringHelper::Split(oName, "_room")[0] + "_scene";
}
std::string fName = "";
if (prefix != "")
fName = StringHelper::Sprintf("%s/%s/%s", prefix.c_str(), oName.c_str(), rName.c_str());
else
fName = StringHelper::Sprintf("%s/%s", oName.c_str(), rName.c_str());
if (Globals::Instance->fileMode == ZFileMode::ExtractDirectory)
{
std::unique_lock Lock(fileMutex);
files[fName] = strem->ToVector();
}
else
DiskFile::WriteAllBytes("Extract/" + fName, strem->ToVector());
}
auto end = std::chrono::steady_clock::now();
size_t diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
//if (diff > 10)
//printf("Exported Resource End %s in %zums\n", res->GetName().c_str(), diff);
}
static void ExporterProcessCompilable(tinyxml2::XMLElement* reader)
{
std::string nodeName = reader->Name();
}
static void ExporterXMLBegin()
{
}
static void ExporterXMLEnd()
{
}
void AddFile(std::string fName, std::vector<char> data)
{
if (Globals::Instance->fileMode != ZFileMode::ExtractDirectory)
DiskFile::WriteAllBytes("Extract/" + fName, data);
else
{
std::unique_lock Lock(fileMutex);
files[fName] = data;
}
}
void ImportExporters()
{
// In this example we set up a new exporter called "EXAMPLE".
// By running ZAPD with the argument -se EXAMPLE, we tell it that we want to use this exporter for our resources.
ExporterSet* exporterSet = new ExporterSet();
exporterSet->processFileModeFunc = ExporterProcessFileMode;
exporterSet->parseFileModeFunc = ExporterParseFileMode;
exporterSet->processCompilableFunc = ExporterProcessCompilable;
exporterSet->parseArgsFunc = ExporterParseArgs;
exporterSet->beginFileFunc = ExporterFileBegin;
exporterSet->endFileFunc = ExporterFileEnd;
exporterSet->beginXMLFunc = ExporterXMLBegin;
exporterSet->endXMLFunc = ExporterXMLEnd;
exporterSet->resSaveFunc = ExporterResourceEnd;
exporterSet->endProgramFunc = ExporterProgramEnd;
exporterSet->exporters[ZResourceType::Background] = new OTRExporter_Background();
exporterSet->exporters[ZResourceType::Texture] = new OTRExporter_Texture();
exporterSet->exporters[ZResourceType::Room] = new OTRExporter_Room();
exporterSet->exporters[ZResourceType::AltHeader] = new OTRExporter_Room();
exporterSet->exporters[ZResourceType::Scene] = new OTRExporter_Room();
exporterSet->exporters[ZResourceType::CollisionHeader] = new OTRExporter_Collision();
exporterSet->exporters[ZResourceType::DisplayList] = new OTRExporter_DisplayList();
exporterSet->exporters[ZResourceType::PlayerAnimationData] = new OTRExporter_PlayerAnimationExporter();
exporterSet->exporters[ZResourceType::Skeleton] = new OTRExporter_Skeleton();
exporterSet->exporters[ZResourceType::Limb] = new OTRExporter_SkeletonLimb();
exporterSet->exporters[ZResourceType::Animation] = new OTRExporter_Animation();
exporterSet->exporters[ZResourceType::Cutscene] = new OTRExporter_Cutscene();
exporterSet->exporters[ZResourceType::Vertex] = new OTRExporter_Vtx();
exporterSet->exporters[ZResourceType::Array] = new OTRExporter_Array();
exporterSet->exporters[ZResourceType::Path] = new OTRExporter_Path();
exporterSet->exporters[ZResourceType::Text] = new OTRExporter_Text();
exporterSet->exporters[ZResourceType::Blob] = new OTRExporter_Blob();
exporterSet->exporters[ZResourceType::Mtx] = new OTRExporter_MtxExporter();
exporterSet->exporters[ZResourceType::Audio] = new OTRExporter_Audio();
Globals::AddExporter("OTR", exporterSet);
InitVersionInfo();
}

View file

@ -0,0 +1,8 @@
#pragma once
#include <libultraship/bridge.h>
extern std::shared_ptr<LUS::Archive> otrArchive;
extern std::map<std::string, std::vector<char>> files;
void AddFile(std::string fName, std::vector<char> data);

View file

@ -0,0 +1,13 @@
#include "MtxExporter.h"
void OTRExporter_MtxExporter::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZMtx* mtx = (ZMtx*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::Matrix);
for (size_t i = 0; i < 4; i++)
for (size_t j = 0; j < 4; j++)
//TODO possibly utilize the array class better
writer->Write(mtx->mtx[i][j]);
}

View file

@ -0,0 +1,10 @@
#include "ZResource.h"
#include "ZMtx.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_MtxExporter : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,23 @@
#include "PathExporter.h"
#include "../ZAPD/ZFile.h"
void OTRExporter_Path::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZPath* path = (ZPath*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::SOH_Path);
writer->Write((uint32_t)path->pathways.size());
for (size_t k = 0; k < path->pathways.size(); k++)
{
writer->Write((uint32_t)path->pathways[k].points.size());
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[1].scalarData.s16);
writer->Write(path->pathways[k].points[i].scalars[2].scalarData.s16);
}
}
}

View file

@ -0,0 +1,12 @@
#pragma once
#include "ZResource.h"
#include "ZPath.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_Path : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,21 @@
#include "PlayerAnimationExporter.h"
#include <libultraship/bridge.h>
void OTRExporter_PlayerAnimationExporter::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZPlayerAnimationData* anim = (ZPlayerAnimationData*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::SOH_PlayerAnimation);
auto start = std::chrono::steady_clock::now();
writer->Write((uint32_t)anim->limbRotData.size());
for (size_t i = 0; i < anim->limbRotData.size(); i++)
writer->Write(anim->limbRotData[i]);
auto end = std::chrono::steady_clock::now();
size_t diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
//printf("Exported Player Anim %s in %zums\n", anim->GetName().c_str(), diff);
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "ZResource.h"
#include "ZTexture.h"
#include "ZPlayerAnimationData.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_PlayerAnimationExporter : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,521 @@
#include "RoomExporter.h"
#include "Utils/BinaryWriter.h"
#include "Utils/MemoryStream.h"
#include <Utils/DiskFile.h>
#include <ZRoom/Commands/SetMesh.h>
#include <ZRoom/Commands/SetWind.h>
#include <ZRoom/Commands/SetTimeSettings.h>
#include <ZRoom/Commands/SetSkyboxModifier.h>
#include <ZRoom/Commands/SetSoundSettings.h>
#include <ZRoom/Commands/SetCameraSettings.h>
#include <ZRoom/Commands/SetRoomBehavior.h>
#include <ZRoom/Commands/SetCsCamera.h>
#include <ZRoom/Commands/SetRoomList.h>
#include <ZRoom/Commands/SetCollisionHeader.h>
#include <ZRoom/Commands/SetEntranceList.h>
#include <ZRoom/Commands/SetSpecialObjects.h>
#include <ZRoom/Commands/SetStartPositionList.h>
#include <ZRoom/Commands/SetSkyboxSettings.h>
#include <ZRoom/Commands/SetLightingSettings.h>
#include <ZRoom/Commands/SetLightList.h>
#include <ZRoom/Commands/SetEchoSettings.h>
#include <ZRoom/Commands/SetObjectList.h>
#include <ZRoom/Commands/SetAlternateHeaders.h>
#include "CollisionExporter.h"
#include "DisplayListExporter.h"
#include <libultraship/bridge.h>
#include <Globals.h>
#include <ZRoom/Commands/SetExitList.h>
#include <ZRoom/Commands/SetPathways.h>
#include "TextureExporter.h"
#include "Main.h"
#include <ZRoom/Commands/SetCutscenes.h>
#include "CutsceneExporter.h"
#include <ZRoom/Commands/SetTransitionActorList.h>
#include "PathExporter.h"
#undef FindResource
void OTRExporter_Room::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZRoom* room = (ZRoom*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::SOH_Room);
writer->Write((uint32_t)room->commands.size());
for (size_t i = 0; i < room->commands.size(); i++)
{
ZRoomCommand* cmd = room->commands[i];
writer->Write((uint32_t)cmd->cmdID);
switch (cmd->cmdID)
{
case RoomCommand::SetTransitionActorList:
{
SetTransitionActorList* cmdTrans = (SetTransitionActorList*)cmd;
writer->Write((uint32_t)cmdTrans->transitionActors.size());
for (const TransitionActorEntry& entry : cmdTrans->transitionActors)
{
writer->Write(entry.frontObjectRoom);
writer->Write(entry.frontTransitionReaction);
writer->Write(entry.backObjectRoom);
writer->Write(entry.backTransitionReaction);
writer->Write(entry.actorNum);
writer->Write(entry.posX);
writer->Write(entry.posY);
writer->Write(entry.posZ);
writer->Write(entry.rotY);
writer->Write(entry.initVar);
}
}
break;
case RoomCommand::SetActorList:
{
SetActorList* cmdSetActorList = (SetActorList*)cmd;
// There are instance of the amount of actors in the file differing from the size listed in the command.
// This can cause issues if we export actors with garbage data, so let's trust the command size
writer->Write((uint32_t)cmdSetActorList->numActors);
for (const auto& entry : cmdSetActorList->actorList->actors)
{
writer->Write(entry.actorNum);
writer->Write(entry.posX);
writer->Write(entry.posY);
writer->Write(entry.posZ);
writer->Write(entry.rotX);
writer->Write(entry.rotY);
writer->Write(entry.rotZ);
writer->Write(entry.params);
}
}
break;
case RoomCommand::SetWind:
{
SetWind* cmdSetWind = (SetWind*)cmd;
writer->Write(cmdSetWind->windWest); // 0x04
writer->Write(cmdSetWind->windVertical); // 0x05
writer->Write(cmdSetWind->windSouth); // 0x06
writer->Write(cmdSetWind->clothFlappingStrength); // 0x07
}
break;
case RoomCommand::SetTimeSettings:
{
SetTimeSettings* cmdTime = (SetTimeSettings*)cmd;
writer->Write(cmdTime->hour); // 0x04
writer->Write(cmdTime->min); // 0x05
writer->Write(cmdTime->unk); // 0x06
}
break;
case RoomCommand::SetSkyboxModifier:
{
SetSkyboxModifier* cmdSkybox = (SetSkyboxModifier*)cmd;
writer->Write(cmdSkybox->disableSky); // 0x04
writer->Write(cmdSkybox->disableSunMoon); // 0x05
}
break;
case RoomCommand::SetEchoSettings:
{
SetEchoSettings* cmdEcho = (SetEchoSettings*)cmd;
writer->Write((uint8_t)cmdEcho->echo); // 0x07
}
break;
case RoomCommand::SetSoundSettings:
{
SetSoundSettings* cmdSound = (SetSoundSettings*)cmd;
writer->Write((uint8_t)cmdSound->reverb); // 0x01
writer->Write(cmdSound->nightTimeSFX); // 0x06
writer->Write(cmdSound->musicSequence); // 0x07
}
break;
case RoomCommand::SetSkyboxSettings:
{
SetSkyboxSettings* cmdSkybox = (SetSkyboxSettings*)cmd;
writer->Write((uint8_t)cmdSkybox->unk1); // 0x01
writer->Write((uint8_t)cmdSkybox->skyboxNumber); // 0x04
writer->Write((uint8_t)cmdSkybox->cloudsType); // 0x05
writer->Write((uint8_t)cmdSkybox->isIndoors); // 0x06
}
break;
case RoomCommand::SetRoomBehavior:
{
SetRoomBehavior* cmdRoom = (SetRoomBehavior*)cmd;
writer->Write((uint8_t)cmdRoom->gameplayFlags); // 0x01
writer->Write(cmdRoom->gameplayFlags2); // 0x04
}
break;
case RoomCommand::SetCsCamera:
{
SetCsCamera* cmdCsCam = (SetCsCamera*)cmd;
writer->Write((uint32_t)cmdCsCam->cameras.size());
for (size_t i = 0; i < cmdCsCam->cameras.size(); i++)
{
writer->Write(cmdCsCam->cameras[i].baseOffset);
writer->Write(cmdCsCam->cameras[i].type);
writer->Write(cmdCsCam->cameras[i].numPoints);
}
writer->Write((uint32_t)cmdCsCam->points.size());
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[1].scalarData.s16);
writer->Write(cmdCsCam->points[i].scalars[2].scalarData.s16);
}
}
break;
case RoomCommand::SetMesh:
{
SetMesh* cmdMesh = (SetMesh*)cmd;
writer->Write((uint8_t)cmdMesh->data); // 0x01
writer->Write(cmdMesh->meshHeaderType);
if (cmdMesh->meshHeaderType == 0 || cmdMesh->meshHeaderType == 2)
{
PolygonType2* poly = (PolygonType2*)cmdMesh->polyType.get();
writer->Write(poly->num);
for (int i = 0; i < poly->num; i++)
WritePolyDList(writer, room, &poly->polyDLists[i]);
}
else if (cmdMesh->meshHeaderType == 1)
{
PolygonType1* poly = (PolygonType1*)cmdMesh->polyType.get();
writer->Write(poly->format);
auto test = (PolygonDlist*)&poly->polyDLists[0];
Declaration* dListDeclOpa = poly->parent->GetDeclaration(GETSEGOFFSET(test->opa));
Declaration* dListDeclXlu = poly->parent->GetDeclaration(GETSEGOFFSET(test->xlu));
if (test->opa != 0)
writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclOpa->varName.c_str()));
else
writer->Write("");
if (test->xlu != 0)
writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclXlu->varName.c_str()));
else
writer->Write("");
if (poly->format == 2)
{
writer->Write((uint32_t)poly->count);
for (int i = 0; i < poly->count; i++)
{
writer->Write(poly->multiList[i].unk_00);
writer->Write(poly->multiList[i].id);
Declaration* bgDecl = poly->parent->GetDeclarationRanged(GETSEGOFFSET(poly->multiList[i].source));
writer->Write(OTRExporter_DisplayList::GetPathToRes(poly->multiList[i].sourceBackground, bgDecl->varName));
writer->Write(poly->multiList[i].unk_0C);
writer->Write(poly->multiList[i].tlut);
writer->Write(poly->multiList[i].width);
writer->Write(poly->multiList[i].height);
writer->Write(poly->multiList[i].fmt);
writer->Write(poly->multiList[i].siz);
writer->Write(poly->multiList[i].mode0);
writer->Write(poly->multiList[i].tlutCount);
}
}
else
{
writer->Write((uint32_t)1);
writer->Write(poly->single.unk_00);
writer->Write(poly->single.id);
Declaration* bgDecl = poly->parent->GetDeclarationRanged(GETSEGOFFSET(poly->single.source));
writer->Write(OTRExporter_DisplayList::GetPathToRes(poly->single.sourceBackground, bgDecl->varName));
writer->Write(poly->single.unk_0C);
writer->Write(poly->single.tlut);
writer->Write(poly->single.width);
writer->Write(poly->single.height);
writer->Write(poly->single.fmt);
writer->Write(poly->single.siz);
writer->Write(poly->single.mode0);
writer->Write(poly->single.tlutCount);
}
if (poly->dlist != 0)
WritePolyDList(writer, room, &poly->polyDLists[0]);
}
}
break;
case RoomCommand::SetCameraSettings:
{
SetCameraSettings* cmdCam = (SetCameraSettings*)cmd;
writer->Write((uint8_t)cmdCam->cameraMovement); // 0x01
writer->Write(cmdCam->mapHighlight); // 0x04
}
break;
case RoomCommand::SetLightList:
{
SetLightList* cmdLight = (SetLightList*)cmd;
writer->Write((uint32_t)cmdLight->lights.size());
for (size_t i = 0; i < cmdLight->lights.size(); i++)
{
writer->Write(cmdLight->lights[i].type);
writer->Write(cmdLight->lights[i].x);
writer->Write(cmdLight->lights[i].y);
writer->Write(cmdLight->lights[i].z);
writer->Write(cmdLight->lights[i].r);
writer->Write(cmdLight->lights[i].g);
writer->Write(cmdLight->lights[i].b);
writer->Write(cmdLight->lights[i].drawGlow);
writer->Write(cmdLight->lights[i].radius);
}
}
break;
case RoomCommand::SetLightingSettings:
{
SetLightingSettings* cmdLight = (SetLightingSettings*)cmd;
writer->Write((uint32_t)cmdLight->settings.size()); // 0x01
for (const LightingSettings& setting : cmdLight->settings)
{
writer->Write(setting.ambientClrR);
writer->Write(setting.ambientClrG);
writer->Write(setting.ambientClrB);
writer->Write(setting.diffuseClrA_R);
writer->Write(setting.diffuseClrA_G);
writer->Write(setting.diffuseClrA_B);
writer->Write(setting.diffuseDirA_X);
writer->Write(setting.diffuseDirA_Y);
writer->Write(setting.diffuseDirA_Z);
writer->Write(setting.diffuseClrB_R);
writer->Write(setting.diffuseClrB_G);
writer->Write(setting.diffuseClrB_B);
writer->Write(setting.diffuseDirB_X);
writer->Write(setting.diffuseDirB_Y);
writer->Write(setting.diffuseDirB_Z);
writer->Write(setting.fogClrR);
writer->Write(setting.fogClrG);
writer->Write(setting.fogClrB);
writer->Write(setting.unk);
writer->Write(setting.drawDistance);
}
}
break;
case RoomCommand::SetRoomList:
{
SetRoomList* cmdRoom = (SetRoomList*)cmd;
writer->Write((uint32_t)cmdRoom->romfile->numRooms); // 0x01
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 = OTRExporter_DisplayList::GetPathToRes(room, StringHelper::Sprintf("%s_room_%i", StringHelper::Split(room->GetName(), "_scene")[0].c_str(), i));
writer->Write(roomName);
writer->Write(cmdRoom->romfile->rooms[i].virtualAddressStart);
writer->Write(cmdRoom->romfile->rooms[i].virtualAddressEnd);
}
}
break;
case RoomCommand::SetCollisionHeader:
{
SetCollisionHeader* cmdCollHeader = (SetCollisionHeader*)cmd;
Declaration* colHeaderDecl = room->parent->GetDeclaration(cmdCollHeader->segmentOffset);
std::string path = OTRExporter_DisplayList::GetPathToRes(room, colHeaderDecl->varName);
writer->Write(path);
}
break;
case RoomCommand::SetEntranceList:
{
SetEntranceList* cmdEntrance = (SetEntranceList*)cmd;
writer->Write((uint32_t)cmdEntrance->entrances.size());
for (EntranceEntry entry : cmdEntrance->entrances)
{
writer->Write((uint8_t)entry.startPositionIndex);
writer->Write((uint8_t)entry.roomToLoad);
}
}
break;
case RoomCommand::SetSpecialObjects:
{
SetSpecialObjects* cmdSpecObj = (SetSpecialObjects*)cmd;
writer->Write((uint8_t)cmdSpecObj->elfMessage); // 0x01
writer->Write((uint16_t)cmdSpecObj->globalObject); // 0x06
}
break;
case RoomCommand::SetStartPositionList:
{
SetStartPositionList* cmdStartPos = (SetStartPositionList*)cmd;
uint32_t baseStreamEnd = writer->GetStream().get()->GetLength();
writer->Write((uint32_t)cmdStartPos->actors.size()); // 0x01
for (const ActorSpawnEntry& entry : cmdStartPos->actors)
{
writer->Write(entry.actorNum);
writer->Write(entry.posX);
writer->Write(entry.posY);
writer->Write(entry.posZ);
writer->Write(entry.rotX);
writer->Write(entry.rotY);
writer->Write(entry.rotZ);
writer->Write(entry.params);
}
}
break;
case RoomCommand::SetAlternateHeaders:
{
SetAlternateHeaders* cmdHeaders = (SetAlternateHeaders*)cmd;
writer->Write((uint32_t)cmdHeaders->headers.size());
for (size_t i = 0; i < cmdHeaders->headers.size(); i++)
{
uint32_t seg = cmdHeaders->headers[i] & 0xFFFFFFFF;
std::string headerName = "";
bool foundDecl = Globals::Instance->GetSegmentedPtrName(seg, room->parent, "", headerName, res->parent->workerID);
if (headerName == "NULL")
writer->Write("");
else
{
std::string name = OTRExporter_DisplayList::GetPathToRes(room, headerName);
writer->Write(name);
}
}
}
break;
case RoomCommand::SetExitList:
{
SetExitList* cmdExit = (SetExitList*)cmd;
writer->Write((uint32_t)cmdExit->exits.size());
for (size_t i = 0; i < cmdExit->exits.size(); i++)
writer->Write(cmdExit->exits[i]);
}
break;
case RoomCommand::SetObjectList:
{
SetObjectList* cmdSetObjectList = (SetObjectList*)cmd;
writer->Write((uint32_t)cmdSetObjectList->objects.size());
for (size_t i = 0; i < cmdSetObjectList->objects.size(); i++)
writer->Write(cmdSetObjectList->objects[i]);
}
break;
case RoomCommand::SetCutscenes:
{
SetCutscenes* cmdSetCutscenes = (SetCutscenes*)cmd;
std::string listName;
Globals::Instance->GetSegmentedPtrName(cmdSetCutscenes->cmdArg2, room->parent, "CutsceneData", listName, res->parent->workerID);
std::string fName = OTRExporter_DisplayList::GetPathToRes(room, listName);
//std::string fName = StringHelper::Sprintf("%s\\%s", OTRExporter_DisplayList::GetParentFolderName(room).c_str(), listName.c_str());
writer->Write(fName);
MemoryStream* csStream = new MemoryStream();
BinaryWriter csWriter = BinaryWriter(csStream);
OTRExporter_Cutscene cs;
cs.Save(cmdSetCutscenes->cutscenes[0], "", &csWriter);
AddFile(fName, csStream->ToVector());
}
break;
case RoomCommand::SetPathways:
{
SetPathways* cmdSetPathways = (SetPathways*)cmd;
writer->Write((uint32_t)cmdSetPathways->pathwayList.pathways.size());
for (size_t i = 0; i < cmdSetPathways->pathwayList.pathways.size(); i++)
{
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 = OTRExporter_DisplayList::GetPathToRes(room, decl->varName);
writer->Write(path);
MemoryStream* pathStream = new MemoryStream();
BinaryWriter pathWriter = BinaryWriter(pathStream);
OTRExporter_Path pathExp;
pathExp.Save(&cmdSetPathways->pathwayList, outPath, &pathWriter);
AddFile(path, pathStream->ToVector());
}
}
break;
case RoomCommand::EndMarker:
break;
default:
printf("UNIMPLEMENTED COMMAND: 0x%02X\n", (int)cmd->cmdID);
break;
}
}
}
void OTRExporter_Room::WritePolyDList(BinaryWriter* writer, ZRoom* room, PolygonDlist* dlist)
{
writer->Write(dlist->polyType);
switch (dlist->polyType)
{
case 2:
writer->Write(dlist->x);
writer->Write(dlist->y);
writer->Write(dlist->z);
writer->Write(dlist->unk_06);
[[fallthrough]];
default:
//writer->Write(StringHelper::Sprintf("%s/%s", OTRExporter_DisplayList::GetParentFolderName(res).c_str(), dListDeclOpa->varName.c_str()));
if (dlist->opaDList != nullptr)
{
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()));
}
else
writer->Write("");
if (dlist->xluDList != nullptr)
{
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()));
}
else
writer->Write("");
break;
}
}

View file

@ -0,0 +1,14 @@
#pragma once
#include "ZResource.h"
#include "Exporter.h"
#include "ZRoom/ZRoom.h"
class PolygonDlist;
class OTRExporter_Room : public OTRExporter
{
public:
void WritePolyDList(BinaryWriter* writer, ZRoom* room, PolygonDlist* dlist);
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,39 @@
#include "SkeletonExporter.h"
#include <libultraship/bridge.h>
#include <Globals.h>
#include "DisplayListExporter.h"
void OTRExporter_Skeleton::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZSkeleton* skel = (ZSkeleton*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::SOH_Skeleton);
writer->Write((uint8_t)skel->type);
writer->Write((uint8_t)skel->limbType);
writer->Write((uint32_t)skel->limbCount);
writer->Write((uint32_t)skel->dListCount);
writer->Write((uint8_t)skel->limbsTable->limbType);
writer->Write((uint32_t)skel->limbsTable->count);
for (size_t i = 0; i < skel->limbsTable->count; i++)
{
Declaration* skelDecl = skel->parent->GetDeclarationRanged(GETSEGOFFSET(skel->limbsTable->limbsAddresses[i]));
std::string name;
bool foundDecl = Globals::Instance->GetSegmentedPtrName(skel->limbsTable->limbsAddresses[i], skel->parent, "", name, res->parent->workerID);
if (foundDecl)
{
if (name.at(0) == '&')
name.erase(0, 1);
writer->Write(OTRExporter_DisplayList::GetPathToRes(res, name));
}
else
{
writer->Write("");
}
}
}

View file

@ -0,0 +1,14 @@
#pragma once
#include "ZResource.h"
#include "ZTexture.h"
#include "ZDisplayList.h"
#include "ZSkeleton.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_Skeleton : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,176 @@
#include "SkeletonLimbExporter.h"
#include "DisplayListExporter.h"
#include <libultraship/bridge.h>
#include <Globals.h>
void OTRExporter_SkeletonLimb::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZLimb* limb = (ZLimb*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::SOH_SkeletonLimb);
writer->Write((uint8_t)limb->type);
writer->Write((uint8_t)limb->skinSegmentType);
if (limb->skinSegmentType == ZLimbSkinType::SkinType_DList && limb->type == ZLimbType::Skin)
{
auto childDecl = limb->parent->GetDeclaration(GETSEGOFFSET(limb->skinSegment));
if (childDecl != nullptr)
writer->Write(OTRExporter_DisplayList::GetPathToRes(limb, childDecl->varName));
else
writer->Write("");
}
else
{
writer->Write("");
}
writer->Write((uint16_t)limb->segmentStruct.unk_0);
writer->Write((uint32_t)limb->segmentStruct.unk_4_arr.size());
for (auto item : limb->segmentStruct.unk_4_arr)
{
writer->Write(item.unk_4);
writer->Write((uint32_t)item.unk_8_arr.size());
for (auto item2 : item.unk_8_arr)
{
writer->Write(item2.unk_0);
writer->Write(item2.unk_2);
writer->Write(item2.unk_4);
writer->Write(item2.unk_6);
writer->Write(item2.unk_7);
writer->Write(item2.unk_8);
writer->Write(item2.unk_9);
}
writer->Write((uint32_t)item.unk_C_arr.size());
for (auto item2 : item.unk_C_arr)
{
writer->Write(item2.unk_0);
writer->Write(item2.x);
writer->Write(item2.y);
writer->Write(item2.z);
writer->Write(item2.unk_8);
}
}
if (limb->segmentStruct.unk_8 != 0)
{
auto skinGfxDecl = limb->parent->GetDeclaration(GETSEGOFFSET(limb->segmentStruct.unk_8));
if (skinGfxDecl != nullptr)
{
writer->Write(OTRExporter_DisplayList::GetPathToRes(limb, skinGfxDecl->varName));
}
else
{
writer->Write("");
}
}
else
{
writer->Write("");
}
writer->Write(limb->legTransX);
writer->Write(limb->legTransY);
writer->Write(limb->legTransZ);
writer->Write(limb->rotX);
writer->Write(limb->rotY);
writer->Write(limb->rotZ);
if (limb->childPtr != 0)
{
std::string name;
bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->childPtr, limb->parent, "", name, res->parent->workerID);
if (foundDecl)
{
if (name.at(0) == '&')
name.erase(0, 1);
writer->Write(OTRExporter_DisplayList::GetPathToRes(limb, name));
}
else
{
writer->Write("");
}
}
else
{
writer->Write("");
}
if (limb->siblingPtr != 0)
{
std::string name;
bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->siblingPtr, limb->parent, "", name, res->parent->workerID);
if (foundDecl)
{
if (name.at(0) == '&')
name.erase(0, 1);
writer->Write(OTRExporter_DisplayList::GetPathToRes(limb, name));
}
else
{
writer->Write("");
}
}
else
{
writer->Write("");
}
if (limb->dListPtr != 0)
{
std::string name;
bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->dListPtr, limb->parent, "", name, res->parent->workerID);
if (foundDecl)
{
if (name.at(0) == '&')
name.erase(0, 1);
writer->Write(OTRExporter_DisplayList::GetPathToRes(limb, name));
}
else
{
writer->Write("");
}
}
else
{
writer->Write("");
}
if (limb->dList2Ptr != 0)
{
std::string name;
bool foundDecl = Globals::Instance->GetSegmentedPtrName(limb->dList2Ptr, limb->parent, "", name, res->parent->workerID);
if (foundDecl)
{
if (name.at(0) == '&')
name.erase(0, 1);
writer->Write(OTRExporter_DisplayList::GetPathToRes(limb, name));
}
else
{
writer->Write("");
}
}
else
{
writer->Write("");
}
writer->Write(limb->transX);
writer->Write(limb->transY);
writer->Write(limb->transZ);
writer->Write(limb->childIndex);
writer->Write(limb->siblingIndex);
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "ZResource.h"
#include "ZTexture.h"
#include "ZDisplayList.h"
#include "ZSkeleton.h"
#include "ZLimb.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_SkeletonLimb : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,19 @@
#include "TextExporter.h"
#include "../ZAPD/ZFile.h"
void OTRExporter_Text::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZText* txt = (ZText*)res;
WriteHeader(txt, outPath, writer, LUS::ResourceType::SOH_Text);
writer->Write((uint32_t)txt->messages.size());
for (size_t i = 0; i < txt->messages.size(); i++)
{
writer->Write(txt->messages[i].id);
writer->Write(txt->messages[i].textboxType);
writer->Write(txt->messages[i].textboxYPos);
writer->Write(txt->messages[i].msg);
}
}

View file

@ -0,0 +1,12 @@
#pragma once
#include "ZResource.h"
#include "ZText.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_Text : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,32 @@
#include "TextureExporter.h"
#include "../ZAPD/ZFile.h"
void OTRExporter_Texture::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZTexture* tex = (ZTexture*)res;
WriteHeader(tex, outPath, writer, LUS::ResourceType::Texture);
auto start = std::chrono::steady_clock::now();
//printf("Exporting Texture %s\n", tex->GetName().c_str());
writer->Write((uint32_t)tex->GetTextureType());
writer->Write((uint32_t)tex->GetWidth());
writer->Write((uint32_t)tex->GetHeight());
writer->Write((uint32_t)tex->GetRawDataSize());
if (tex->parent != nullptr) {
auto data = tex->parent->GetRawData();
writer->Write((char*)data.data() + tex->GetRawDataIndex(), tex->GetRawDataSize());
}
auto end = std::chrono::steady_clock::now();
size_t diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
//printf("Exported Texture %s in %zums\n", tex->GetName().c_str(), diff);
//if (diff > 2)
//printf("Export took %lms\n", diff);
}

View file

@ -0,0 +1,12 @@
#pragma once
#include "ZResource.h"
#include "ZTexture.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_Texture : public OTRExporter
{
public:
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,25 @@
#include "VersionInfo.h"
#include <libultraship/bridge.h>
std::map<LUS::ResourceType, uint32_t> resourceVersions;
void InitVersionInfo()
{
resourceVersions = std::map<LUS::ResourceType, uint32_t> {
{ LUS::ResourceType::SOH_Animation, 0 },
{ LUS::ResourceType::Texture, 0 },
{ LUS::ResourceType::SOH_PlayerAnimation, 0 },
{ LUS::ResourceType::DisplayList, 0 },
{ LUS::ResourceType::SOH_Room, 0 },
{ LUS::ResourceType::SOH_CollisionHeader, 0 },
{ LUS::ResourceType::SOH_Skeleton, 0 },
{ LUS::ResourceType::SOH_SkeletonLimb, 0 },
{ LUS::ResourceType::Matrix, 0 },
{ LUS::ResourceType::SOH_Path, 0 },
{ LUS::ResourceType::Vertex, 0 },
{ LUS::ResourceType::SOH_Cutscene, 0 },
{ LUS::ResourceType::Array, 0 },
{ LUS::ResourceType::SOH_Text, 0 },
{ LUS::ResourceType::Blob, 0 },
};
}

View file

@ -0,0 +1,7 @@
#pragma once
#include <map>
#include <vector>
#include "src/resource/Resource.h"
extern std::map<LUS::ResourceType, uint32_t> resourceVersions;

View file

@ -0,0 +1,44 @@
#include "VtxExporter.h"
#include <libultraship/bridge.h>
#include "VersionInfo.h"
void OTRExporter_Vtx::SaveArr(ZResource* res, const fs::path& outPath, const std::vector<ZResource*>& vec, BinaryWriter* writer)
{
WriteHeader(res, outPath, writer, LUS::ResourceType::Vertex);
for (auto& res: vec) {
ZVtx* vtx = (ZVtx*)res;
writer->Write(vtx->x);
writer->Write(vtx->y);
writer->Write(vtx->z);
writer->Write(vtx->flag);
writer->Write(vtx->s);
writer->Write(vtx->t);
writer->Write(vtx->r);
writer->Write(vtx->g);
writer->Write(vtx->b);
writer->Write(vtx->a);
}
}
void OTRExporter_Vtx::Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer)
{
ZVtx* vtx = (ZVtx*)res;
WriteHeader(res, outPath, writer, LUS::ResourceType::Vertex);
writer->Write((uint32_t)1); //Yes I'm hard coding it to one, it *should* be fine.
writer->Write(vtx->x);
writer->Write(vtx->y);
writer->Write(vtx->z);
writer->Write(vtx->flag);
writer->Write(vtx->s);
writer->Write(vtx->t);
writer->Write(vtx->r);
writer->Write(vtx->g);
writer->Write(vtx->b);
writer->Write(vtx->a);
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "ZResource.h"
#include "ZVtx.h"
#include "Exporter.h"
#include <Utils/BinaryWriter.h>
class OTRExporter_Vtx : public OTRExporter
{
public:
void SaveArr(ZResource* res, const fs::path& outPath, const std::vector<ZResource*>&, BinaryWriter* writer);
virtual void Save(ZResource* res, const fs::path& outPath, BinaryWriter* writer) override;
};

View file

@ -0,0 +1,36 @@
#ifndef COMMAND_MACROS_BASE_H
#define COMMAND_MACROS_BASE_H
/**
* Command Base macros intended for use in designing of more specific command macros
* Each macro packs bytes (B), halfwords (H) and words (W, for consistency) into a single word
*/
#define _SHIFTL(v, s, w) \
((unsigned int) (((unsigned int)(v) & ((0x01 << (w)) - 1)) << (s)))
#define _SHIFTR(v, s, w) \
((unsigned int)(((unsigned int)(v) >> (s)) & ((0x01 << (w)) - 1)))
//#define CMD_BBBB(a, b, c, d) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 8, 8) | _SHIFTL(d, 0, 8))
#define CMD_BBBB(a, b, c, d) (_SHIFTL(d, 24, 8) | _SHIFTL(c, 16, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(a, 0, 8))
//#define CMD_BBH(a, b, c) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 0, 16))
#define CMD_BBH(a, b, c) (_SHIFTL(a, 0, 8) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 16, 16))
//#define CMD_HBB(a, b, c) (_SHIFTL(a, 16, 16) | _SHIFTL(b, 8, 8) | _SHIFTL(c, 0, 8))
#define CMD_HBB(a, b, c) (_SHIFTL(c, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(a, 0, 16))
//#define CMD_HH(a, b) (_SHIFTL(a, 16, 16) | _SHIFTL(b, 0, 16))
#define CMD_HH(a, b) (_SHIFTL(b, 16, 16) | _SHIFTL(a, 0, 16))
#define CMD_W(a) (a)
#if defined(__GNUC__)
#define CMD_F(a) {.f = (a)}
#else
#define CMD_F(a) {(a)}
#endif
#define CMD_PTR(a) (u32)(a)
#endif

View file

@ -0,0 +1,290 @@
#ifndef Z64CUTSCENE_H
#define Z64CUTSCENE_H
#if 0
#include <libultraship/libultra.h>
typedef struct {
/* 0x00 */ u16 entrance; // entrance index upon which the cutscene should trigger
/* 0x02 */ u8 ageRestriction; // 0 for adult only, 1 for child only, 2 for both ages
/* 0x03 */ u8 flag; // eventChkInf flag bound to the entrance cutscene
/* 0x04 */ void* segAddr; // segment offset location of the cutscene
} EntranceCutscene; // size = 0x8
typedef struct {
/* 0x00 */ s8 continueFlag;
/* 0x01 */ s8 cameraRoll;
/* 0x02 */ u16 nextPointFrame;
/* 0x04 */ f32 viewAngle; // in degrees
/* 0x08 */ Vec3s pos;
} CutsceneCameraPoint; // size = 0x10
typedef struct {
/* 0x00 */ Vec3f at;
/* 0x0C */ Vec3f eye;
/* 0x18 */ s16 roll;
/* 0x1A */ s16 fov;
} CutsceneCameraAngle; // size = 0x1C
typedef struct {
/* 0x0 */ CutsceneCameraPoint* atPoints;
/* 0x4 */ CutsceneCameraPoint* eyePoints;
/* 0x8 */ s16 relativeToPlayer;
} CutsceneCameraMove; // size = 0xC
typedef struct {
/* 0x00 */ u16 base;
/* 0x02 */ u16 startFrame;
/* 0x04 */ u16 endFrame;
} CsCmdBase; // size = 0x6
typedef struct {
/* 0x00 */ u8 unk_00;
/* 0x01 */ u8 setting;
/* 0x02 */ u16 startFrame;
/* 0x04 */ u16 endFrame;
} CsCmdEnvLighting; // size = 0x6
typedef struct {
/* 0x00 */ u8 unk_00;
/* 0x01 */ u8 sequence;
/* 0x02 */ u16 startFrame;
/* 0x04 */ u16 endFrame;
} CsCmdMusicChange; // size = 0x6
typedef struct {
/* 0x00 */ u16 type;
/* 0x02 */ u16 startFrame;
/* 0x04 */ u16 endFrame;
} CsCmdMusicFade; // size = 0x6
typedef struct {
/* 0x00 */ u16 unk_00;
/* 0x02 */ u16 startFrame;
/* 0x04 */ u16 endFrame;
/* 0x06 */ u8 unk_06;
/* 0x07 */ u8 unk_07;
/* 0x08 */ u8 unk_08;
} CsCmdUnknown9; // size = 0xA
typedef struct {
/* 0x00 */ u16 unk_00;
/* 0x02 */ u16 startFrame;
/* 0x04 */ u16 endFrame;
/* 0x06 */ u8 hour;
/* 0x07 */ u8 minute;
} CsCmdDayTime; // size = 0x8
typedef struct {
/* 0x00 */ u16 base;
/* 0x02 */ u16 startFrame;
/* 0x04 */ u16 endFrame;
/* 0x06 */ u16 type;
/* 0x08 */ u16 textId1;
/* 0x0A */ u16 textId2;
} CsCmdTextbox; // size = 0xC
typedef struct {
/* 0x00 */ u16 action; // "dousa"
/* 0x02 */ u16 startFrame;
/* 0x04 */ u16 endFrame;
union {
/* 0x06 */ Vec3s rot;
/* 0x06 */ Vec3us urot;
};
/* 0x0C */ Vec3i startPos;
/* 0x18 */ Vec3i endPos;
/* 0x24 */ Vec3i normal;
} CsCmdActorAction; // size = 0x30
#endif
typedef enum {
CS_STATE_IDLE,
CS_STATE_SKIPPABLE_INIT,
CS_STATE_SKIPPABLE_EXEC,
CS_STATE_UNSKIPPABLE_INIT,
CS_STATE_UNSKIPPABLE_EXEC
} CutsceneState;
typedef enum {
CS_CMD_00 = 0x0000,
CS_CMD_CAM_EYE = 0x0001,
CS_CMD_CAM_AT = 0x0002,
CS_CMD_MISC = 0x0003,
CS_CMD_SET_LIGHTING = 0x0004,
CS_CMD_CAM_EYE_REL_TO_PLAYER = 0x0005,
CS_CMD_CAM_AT_REL_TO_PLAYER = 0x0006,
CS_CMD_07 = 0x0007,
CS_CMD_08 = 0x0008,
CS_CMD_09 = 0x0009,
CS_CMD_TEXTBOX = 0x0013,
CS_CMD_SET_PLAYER_ACTION = 0x000A,
CS_CMD_SET_ACTOR_ACTION_1 = 0x000F,
CS_CMD_SET_ACTOR_ACTION_2 = 0x000E,
CS_CMD_SET_ACTOR_ACTION_3 = 0x0019,
CS_CMD_SET_ACTOR_ACTION_4 = 0x001D,
CS_CMD_SET_ACTOR_ACTION_5 = 0x001E,
CS_CMD_SET_ACTOR_ACTION_6 = 0x002C,
CS_CMD_SET_ACTOR_ACTION_7 = 0x001F,
CS_CMD_SET_ACTOR_ACTION_8 = 0x0031,
CS_CMD_SET_ACTOR_ACTION_9 = 0x003E,
CS_CMD_SET_ACTOR_ACTION_10 = 0x008F,
CS_CMD_SCENE_TRANS_FX = 0x002D,
CS_CMD_NOP = 0x000B,
CS_CMD_PLAYBGM = 0x0056,
CS_CMD_STOPBGM = 0x0057,
CS_CMD_FADEBGM = 0x007C,
CS_CMD_SETTIME = 0x008C,
CS_CMD_TERMINATOR = 0x03E8,
CS_CMD_END = 0xFFFF
} CutsceneCmd;
/**
* Special type for blocks of cutscene data, asm-processor checks
* arrays for CutsceneData type and converts floats within the array
* to their IEEE-754 representation. The array must close with };
* on its own line.
*
* Files that contain this type that are included in other C files
* must include an 'EARLY' qualifier to inform asm-processor that it
* must recursively process that include.
*
* Example: #include "file.c" EARLY
*/
typedef union CutsceneData {
int i;
float f;
short s[2];
char b[4];
} CutsceneData;
#define CS_CMD_CONTINUE 0
#define CS_CMD_STOP -1
// TODO confirm correctness, clarify names
typedef enum {
/* 0x00 */ INVALID_DESTINATION_0,
/* 0x01 */ CUTSCENE_MAP_GANON_HORSE,
/* 0x02 */ CUTSCENE_MAP_THREE_GODESSES_POST_DEKU_TREE,
/* 0x03 */ GERUDO_VALLEY_DIN,
/* 0x04 */ DEATH_MOUNTAIN_TRAIL_NAYRU,
/* 0x05 */ KOKIRI_FOREST_FARORE,
/* 0x06 */ CUTSCENE_MAP_TRIFORCE_CREATION,
/* 0x07 */ KOKIRI_FOREST_RECEIVE_KOKIRI_EMERALD,
/* 0x08 */ TEMPLE_OF_TIME_AFTER_USE_MS,
/* 0x09 */ GERUDO_VALLEY_DIN_2,
/* 0x0A */ LINKS_HOUSE_INTRO,
/* 0x0B */ KOKIRI_FOREST_INTRO,
/* 0x0C */ DEATH_MOUNTAIN_TRAIL_AFTER_GORON_RUBY,
/* 0x0D */ ZORAS_FOUNTAIN_AFTER_ZORAS_SAPPHIRE,
/* 0x0E */ KOKIRI_FOREST_AFTER_KOKIRI_EMERALD,
/* 0x0F */ TEMPLE_OF_TIME_KOKIRI_EMERALD, //unused
/* 0x10 */ TEMPLE_OF_TIME_GORON_RUBY, //unused
/* 0x11 */ TEMPLE_OF_TIME_ZORAS_SAPPHIRE, //unused
/* 0x12 */ TEMPLE_OF_TIME_AFTER_USE_MS_FIRST,
/* 0x13 */ DEATH_MOUNTAIN_TRAIL_AFTER_INTRO,
/* 0x14 */ INVALID_DESTINATION_14,
/* 0x15 */ LAKE_HYLIA_WATER_RISES,
/* 0x16 */ DESERT_COLOSSUS_REQUIEM,
/* 0x17 */ CUTSCENE_MAP_CURSE_YOU,
/* 0x18 */ JABU_JABU_INTRO,
/* 0x19 */ CHAMBER_OF_SAGES_LIGHT_MEDALLION,
/* 0x1A */ TEMPLE_OF_TIME_KOKIRI_EMERALD_2, //duplicate of 0x000F
/* 0x1B */ TEMPLE_OF_TIME_GORON_RUBY_2, //duplicate of 0x0010
/* 0x1C */ TEMPLE_OF_TIME_ZORAS_SAPPHIRE_2, //duplicate of 0x0011
/* 0x1D */ CHAMBER_OF_SAGES_FOREST_MEDALLION,
/* 0x1E */ CHAMBER_OF_SAGES_FIRE_MEDALLION,
/* 0x1F */ CHAMBER_OF_SAGES_WATER_MEDALLION,
/* 0x20 */ HYRULE_FIELD_FLASHBACK, //lacs part 4
/* 0x21 */ HYRULE_FIELD_AFTER_LAKE_HYLIA_OWL,
/* 0x22 */ CUTSCENE_MAP_GANON_AFTER_USE_MS,
/* 0x23 */ HYRULE_FIELD_INTRO_ZELDA_ESCAPE,
/* 0x24 */ INVALID_DESTINATION_24,
/* 0x25 */ INVALID_DESTINATION_25,
/* 0x26 */ CUTSCENE_MAP_SHEIKAH_LEGEND, //lacs part 2
/* 0x27 */ TEMPLE_OF_TIME_ZELDA_REVEAL, //lacs part 3
/* 0x28 */ TEMPLE_OF_TIME_GET_LIGHT_ARROWS, //lacs part 5
/* 0x29 */ LAKE_HYLIA_AFTER_BLUE_WARP,
/* 0x2A */ KAKARIKO_VILLAGE_DRAIN_WELL,
/* 0x2B */ WINDMILL_AFTER_DRAIN_WELL,
/* 0x2C */ TEMPLE_OF_TIME_AFTER_DOOR_OF_TIME_OPENS,
/* 0x2D */ INVALID_DESTINATION_2D,
/* 0x2E */ TEMPLE_OF_TIME_AFTER_USE_MS_FIRST_2, // duplicate of 0x0012
/* 0x2F */ KAKARIKO_VILLAGE_NOCTURNE_PART_2,
/* 0x30 */ DESERT_COLOSSUS_AFTER_REQUIEM,
/* 0x31 */ TEMPLE_OF_TIME_AFTER_LIGHT_ARROWS,
/* 0x32 */ KAKARIKO_VILLAGE_AFTER_NOCTURNE,
/* 0x33 */ HYRULE_FIELD_IMPA_ESCORT_CS,
/* 0x34 */ TEMPLE_OF_TIME_SONG_OF_TIME,
/* 0x35 */ HYRULE_FIELD_AFTER_SONG_OF_TIME,
/* 0x36 */ GERUDO_VALLEY_CREDITS,
/* 0x37 */ GERUDO_FORTRESS_CREDITS,
/* 0x38 */ KAKARIKO_VILLAGE_CREDITS,
/* 0x39 */ DEATH_MOUNTAIN_TRAIL_CREDITS_1,
/* 0x3A */ GORON_CITY_CREDITS, // unused?
/* 0x3B */ LAKE_HYLIA_CREDITS,
/* 0x3C */ ZORAS_FOUNTAIN_CREDITS, // unused
/* 0x3D */ ZORAS_DOMAIN_CREDITS,
/* 0x3E */ KOKIRI_FOREST_CREDITS_1,
/* 0x3F */ KOKIRI_FOREST_CREDITS_2,
/* 0x40 */ HYRULE_FIELD_CREDITS,
/* 0x41 */ LON_LON_RANCH_CREDITS_1,
/* 0x42 */ KAKARIKO_VILLAGE_AFTER_TRAIL_OWL,
/* 0x43 */ HTRULE_FIELD_UNUSED_ENTRANCE,
/* 0x44 */ CUTSCENE_MAP_FIRE,
/* 0x45 */ KOKIRI_FOREST_POST_FOREST_MEDALLION,
/* 0x46 */ DEATH_MOUNTAIN_TRAIL_CREDITS_2,
/* 0x47 */ TEMPLE_OF_TIME_CREDITS,
/* 0x48 */ ZELDAS_COURTYARD_CREDITS,
/* 0x49 */ LON_LON_RANCH_CREDITS_1_2, // duplicate of 0x0041
/* 0x4A */ LON_LON_RANCH_CREDITS_2,
/* 0x4B */ LON_LON_RANCH_CREDITS_3,
/* 0x4C */ LON_LON_RANCH_CREDITS_4,
/* 0x4D */ LON_LON_RANCH_CREDITS_5,
/* 0x4E */ LON_LON_RANCH_CREDITS_6,
/* 0x4F */ LON_LON_RANCH_NO_CS_1,
/* 0x50 */ LON_LON_RANCH_NO_CS_2,
/* 0x51 */ LON_LON_RANCH_NO_CS_3,
/* 0x52 */ LON_LON_RANCH_NO_CS_4,
/* 0x53 */ LON_LON_RANCH_NO_CS_5,
/* 0x54 */ LON_LON_RANCH_NO_CS_6,
/* 0x55 */ LON_LON_RANCH_NO_CS_7,
/* 0x56 */ LON_LON_RANCH_NO_CS_8,
/* 0x57 */ LON_LON_RANCH_NO_CS_9,
/* 0x58 */ LON_LON_RANCH_NO_CS_10,
/* 0x59 */ LON_LON_RANCH_NO_CS_11,
/* 0x5A */ LON_LON_RANCH_NO_CS_12,
/* 0x5B */ LON_LON_RANCH_NO_CS_13,
/* 0x5C */ LON_LON_RANCH_NO_CS_14,
/* 0x5D */ LON_LON_RANCH_NO_CS_15,
/* 0x5E */ LON_LON_RANCH_NO_CS_EPONAS_SONG,
/* 0x5F */ CONDITIONAL_DESTINATION, // TODO more descriptive name?
/* 0x60 */ DESERT_COLOSSUS_SPIRIT_BLUE_WARP,
/* 0x61 */ GRAVEYARD_AFTER_SHADOW_BLUE_WARP,
/* 0x62 */ DEATH_MOUNTAIN_CRATER_AFTER_FIRE_BLUE_WARP,
/* 0x63 */ SACRED_FOREST_MEADOW_AFTER_FOREST_BLUE_WARP,
/* 0x64 */ KOKIRI_FOREST_AFTER_FOREST_BLUE_WARP,
/* 0x65 */ DESERT_COLOSSUS_AFTER_SILVER_GAUNTLETS,
/* 0x66 */ TEMPLE_OF_TIME_FRONT_OF_PEDESTAL,
/* 0x67 */ HYRULE_FIELD_TITLE_SCREEN,
/* 0x68 */ SPIRIT_TEMPLE_BOSS_TITLE_SCREEN,
/* 0x69 */ GRAVEYARD_SUNS_SONG,
/* 0x6A */ ROYAL_FAMILYS_TOMB_SUNS_SONG,
/* 0x6B */ GANONS_CASTLE_AFTER_FOREST_TRIAL,
/* 0x6C */ GANONS_CASTLE_AFTER_WATER_TRIAL,
/* 0x6D */ GANONS_CASTLE_AFTER_SHADOW_TRIAL,
/* 0x6E */ GANONS_CASTLE_AFTER_FIRE_TRIAL,
/* 0x6F */ GANONS_CASTLE_AFTER_LIGHT_TRIAL,
/* 0x70 */ GANONS_CASTLE_AFTER_SPIRIT_TRIAL,
/* 0x71 */ GANONS_CASTLE_DISPEL_BARRIER_IF_CONDITIONS,
/* 0x72 */ HYRULE_FIELD_INTRO,
/* 0x73 */ HYRULE_FIELD_AFTER_IMPA_ESCORT,
/* 0x74 */ DESERT_COLOSSUS_SPIRIT_BLUE_WARP_2,
/* 0x75 */ HYRULE_FIELD_SKY,
/* 0x76 */ GANON_BATTLE_TOWER_COLLAPSE,
/* 0x77 */ ZELDAS_COURTYARD_RECEIVE_LETTER
} CutsceneTerminatorDestination;
#endif

View file

@ -0,0 +1,448 @@
#ifndef Z64CUTSCENE_COMMANDS_H
#define Z64CUTSCENE_COMMANDS_H
#include "command_macros_base.h"
#include "z64cutscene.h"
/**
* ARGS
* s32 totalEntries (e), s32 endFrame (n)
* FORMAT
* eeeeeeee nnnnnnnn
* size = 0x8
*/
#define CS_BEGIN_CUTSCENE(totalEntries, endFrame) CMD_W(totalEntries), CMD_W(endFrame)
/**
* ARGS
* s16 startFrame (s), s16 endFrame (e)
* FORMAT
* 00000001 0001ssss eeee0000
* size = 0xC
*/
#define CS_CAM_POS_LIST CS_CAM_EYE_LIST
#define CS_CAM_EYE_LIST(startFrame, endFrame) \
CS_CMD_CAM_EYE, CMD_HH(0x0001, startFrame), CMD_HH(endFrame, 0x0000)
/**
* ARGS
* s8 continueFlag (c), s8 roll (r), s16 frame (f), f32 viewAngle (a),
* s16 xPos (x), s16 yPos (y), s16 zPos (z)
* FORMAT
* Capital U is Unused
* ccrrffff aaaaaaaa xxxxyyyy zzzzUUUU
* size = 0x10
*/
#define CS_CAM_POS CS_CAM_EYE
#define CS_CAM_EYE(continueFlag, roll, frame, viewAngle, xPos, yPos, zPos, unused) \
CMD_BBH(continueFlag, roll, frame), CMD_F(viewAngle), CMD_HH(xPos, yPos), CMD_HH(zPos, unused)
/**
* ARGS
* s16 startFrame (s), s16 endFrame (e)
* FORMAT
* 00000002 0001ssss eeee0000
* size = 0xC
*/
#define CS_CAM_FOCUS_POINT_LIST CS_CAM_AT_LIST
#define CS_CAM_AT_LIST(startFrame, endFrame) \
CS_CMD_CAM_AT, CMD_HH(0x0001, startFrame), CMD_HH(endFrame, 0x0000)
/**
* ARGS
* s8 continueFlag (c), s8 roll (r), s16 frame (f), f32 viewAngle (a),
* s16 xPos (x), s16 yPos (y), s16 zPos (z)
* FORMAT
* Capital U is Unused
* ccrrffff aaaaaaaa xxxxyyyy zzzzUUUU
* size = 0x10
*/
#define CS_CAM_FOCUS_POINT CS_CAM_AT
#define CS_CAM_AT(continueFlag, roll, frame, viewAngle, xPos, yPos, zPos, unused) \
CMD_BBH(continueFlag, roll, frame), CMD_F(viewAngle), CMD_HH(xPos, yPos), CMD_HH(zPos, unused)
/**
* ARGS
* s32 entries (e)
* FORMAT
* 00000003 eeeeeeee
* size = 0x8
*/
#define CS_MISC_LIST(entries) CS_CMD_MISC, CMD_W(entries)
/**
* ARGS
* s16 unk (u), s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused
* uuuussss eeeeUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU
* size = 0x30
*/
#define CS_MISC(unk, startFrame, endFrame, unused0, unused1, unused2, unused3, unused4, unused5, unused6, unused7, unused8, unused9, unused10) \
CMD_HH(unk, startFrame), CMD_HH(endFrame, unused0), \
CMD_W(unused1), CMD_W(unused2), CMD_W(unused3), CMD_W(unused4), CMD_W(unused5), \
CMD_W(unused6), CMD_W(unused7), CMD_W(unused8), CMD_W(unused9), CMD_W(unused10)
/**
* ARGS
* s32 entries (e)
* FORMAT
* 00000004 eeeeeeee
* size = 0x8
*/
#define CS_LIGHTING_LIST(entries) CS_CMD_SET_LIGHTING, CMD_W(entries)
/**
* ARGS
* s16 setting (m), s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused
* mmmmssss eeeeUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU 00000000 00000000 00000000
* size = 0x30
*/
#define CS_LIGHTING(setting, startFrame, endFrame, unused0, unused1, unused2, unused3, unused4, unused5, unused6, unused7) \
CMD_HH(setting, startFrame), CMD_HH(endFrame, unused0), \
CMD_W(unused1), CMD_W(unused2), CMD_W(unused3), CMD_W(unused4), CMD_W(unused5), \
CMD_W(unused6), CMD_W(unused7), 0x00000000, 0x00000000, 0x00000000
/**
* ARGS
* s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused , may be consistently zero
* 00000005 0001ssss eeee0000
* size = 0xC
*/
#define CS_CAM_POS_PLAYER_LIST CS_CAM_EYE_REL_TO_PLAYER_LIST
#define CS_CAM_EYE_REL_TO_PLAYER_LIST(startFrame, endFrame) \
CS_CMD_CAM_EYE_REL_TO_PLAYER, CMD_HH(0x0001, startFrame), CMD_HH(endFrame, 0x0000)
/**
* ARGS
* s8 continueFlag (c), s8 roll (r), s16 frame (f), f32 viewAngle (a),
* s16 xPos (x), s16 yPos (y), s16 zPos (z)
* FORMAT
* Capital U is Unused
* ccrrffff aaaaaaaa xxxxyyyy zzzzUUUU
* size = 0x10
*/
#define CS_CAM_POS_PLAYER CS_CAM_EYE_REL_TO_PLAYER
#define CS_CAM_EYE_REL_TO_PLAYER(continueFlag, roll, frame, viewAngle, xPos, yPos, zPos, unused) \
CMD_BBH(continueFlag, roll, frame), CMD_F(viewAngle), CMD_HH(xPos, yPos), CMD_HH(zPos, unused)
/**
* ARGS
* s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused , may be consistently zero
* 00000006 0001ssss eeee0000
* size = 0xC
*/
#define CS_CAM_FOCUS_POINT_PLAYER_LIST CS_CAM_AT_REL_TO_PLAYER_LIST
#define CS_CAM_AT_REL_TO_PLAYER_LIST(startFrame, endFrame) \
CS_CMD_CAM_AT_REL_TO_PLAYER, CMD_HH(0x0001, startFrame), CMD_HH(endFrame, 0x0000)
/**
* ARGS
* s8 continueFlag (c), s8 roll (r), s16 frame (f), f32 viewAngle (a),
* s16 xPos (x), s16 yPos (y), s16 zPos (z)
* FORMAT
* Capital U is Unused
* ccrrffff aaaaaaaa xxxxyyyy zzzzUUUU
* size = 0x10
*/
#define CS_CAM_FOCUS_POINT_PLAYER CS_CAM_AT_REL_TO_PLAYER
#define CS_CAM_AT_REL_TO_PLAYER(continueFlag, roll, frame, viewAngle, xPos, yPos, zPos, unused) \
CMD_BBH(continueFlag, roll, frame), CMD_F(viewAngle), CMD_HH(xPos, yPos), CMD_HH(zPos, unused)
/**
* ARGS
* s16 unk (u), s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused
* 00000007 uuuussss eeeeUUUU
* size = 0xC
*/
#define CS_CMD_07_LIST(unk, startFrame, endFrame, unused) \
CS_CMD_07, CMD_HH(unk, startFrame), CMD_HH(endFrame, unused)
/**
* ARGS
* s8 continueFlag (c), s8 roll (r), s16 frame (f), f32 viewAngle (a),
* s16 xPos (x), s16 yPos (y), s16 zPos (z)
* FORMAT
* Capital U is Unused
* ccrrffff aaaaaaaa xxxxyyyy zzzzUUUU
* size = 0x10
*/
#define CS_CMD_07(continueFlag, roll, frame, viewAngle, xPos, yPos, zPos, unused) \
CMD_BBH(continueFlag, roll, frame), CMD_F(viewAngle), CMD_HH(xPos, yPos), CMD_HH(zPos, unused)
/**
* ARGS
* s16 unk (u), s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused
* 00000008 uuuussss eeeeUUUU
* size = 0xC
*/
#define CS_CMD_08_LIST(unk, startFrame, endFrame, unused) \
CS_CMD_08, CMD_HH(unk, startFrame), CMD_HH(endFrame, unused)
/**
* ARGS
* s8 continueFlag (c), s8 roll (r), s16 frame (f), f32 viewAngle (a),
* s16 xPos (x), s16 yPos (y), s16 zPos (z)
* FORMAT
* Capital U is Unused
* ccrrffff aaaaaaaa xxxxyyyy zzzzUUUU
* size = 0x10
*/
#define CS_CMD_08(continueFlag, roll, frame, viewAngle, xPos, yPos, zPos, unused) \
CMD_BBH(continueFlag, roll, frame), CMD_F(viewAngle), CMD_HH(xPos, yPos), CMD_HH(zPos, unused)
/**
* ARGS
* s32 entries (e)
* FORMAT
* 00000009 eeeeeeee
* size = 0x8
*/
#define CS_CMD_09_LIST(entries) CS_CMD_09, CMD_W(entries)
/**
* ARGS
* s16 unk (u), s16 startFrame (s), s16 endFrame (e), s16 unk2 (v), s16 unk3 (w), s16 unk4 (x)
* FORMAT
* Capital U is Unused
* uuuussss eeeevvww xxUUUUUU
* size = 0xC
*/
#define CS_CMD_09(unk, startFrame, endFrame, unk2, unk3, unk4, unused0, unused1) \
CMD_HH(unk, startFrame), CMD_HBB(endFrame, unk2, unk3), CMD_BBH(unk4, unused0, unused1)
/**
* ARGS
* s32 cmdType (c), s32 entries (e)
* FORMAT
* cccccccc eeeeeeee
* size = 0x8
*/
#define CS_UNK_DATA_LIST(cmdType, entries) CMD_W(cmdType), CMD_W(entries)
/**
* ARGS
* s32 unk1 (a), s32 unk2 (b), s32 unk3 (c), s32 unk4 (d), s32 unk5 (e), s32 unk6 (f),
* s32 unk7 (g), s32 unk8 (h), s32 unk9 (i), s32 unk10 (j), s32 unk11 (k), s32 unk12 (l)
* FORMAT
* aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh iiiiiiii jjjjjjjj kkkkkkkk llllllll
* size = 0x30
*/
#define CS_UNK_DATA(unk1, unk2, unk3, unk4, unk5, unk6, unk7, unk8, unk9, unk10, unk11, unk12) \
CMD_W(unk1), CMD_W(unk2), CMD_W(unk3), CMD_W(unk4), CMD_W(unk5), CMD_W(unk6), \
CMD_W(unk7), CMD_W(unk8), CMD_W(unk9), CMD_W(unk10), CMD_W(unk11), CMD_W(unk12)
/**
* ARGS
* s32 cmdType (c), s32 entries (e)
* FORMAT
* cccccccc eeeeeeee
* size = 0x8
*/
#define CS_NPC_ACTION_LIST(cmdType, entries) CMD_W(cmdType), CMD_W(entries)
/**
* ARGS
* s16 npcAction (a), s16 startFrame (s), s16 endFrame (e),
* s16 rotX (u), s16 rotY (v), s16 rotZ (w),
* s32 startX (i), s32 startY (j), s32 startZ (k),
* s32 endX (l), s32 endY (m), s32 endZ (n),
* f32 normX (x), f32 normY (y), f32 normZ (z),
* FORMAT
* aaaassss eeeeuuuu vvvvwwww iiiiiiii jjjjjjjj kkkkkkkk llllllll mmmmmmmm nnnnnnnn xxxxxxxx yyyyyyyy zzzzzzzz
* size = 0x30
*/
#define CS_NPC_ACTION(npcAction, startFrame, endFrame, rotX, rotY, rotZ, startX, startY, startZ, endX, endY, endZ, normX, normY, normZ) \
CMD_HH(npcAction, startFrame), CMD_HH(endFrame, rotX), CMD_HH(rotY, rotZ), \
CMD_W(startX), CMD_W(startY), CMD_W(startZ), \
CMD_W(endX), CMD_W(endY), CMD_W(endZ), \
CMD_F(normX), CMD_F(normY), CMD_F(normZ)
/**
* ARGS
* s32 cmdType (c), s32 entries (e)
* FORMAT
* cccccccc eeeeeeee
* size = 0x8
*/
#define CS_PLAYER_ACTION_LIST(entries) CS_CMD_SET_PLAYER_ACTION, CMD_W(entries)
/**
* ARGS
* s16 linkAction (a), s16 startFrame (s), s16 endFrame (e),
* s16 rotX (u), s16 rotY (v), s16 rotZ (w),
* s32 startX (i), s32 startY (j), s32 startZ (k),
* s32 endX (l), s32 endY (m), s32 endZ (n),
* f32 normX (x), f32 normY (y), f32 normZ (z),
* FORMAT
* aaaassss eeeeuuuu vvvvwwww iiiiiiii jjjjjjjj kkkkkkkk llllllll mmmmmmmm nnnnnnnn xxxxxxxx yyyyyyyy zzzzzzzz
* size = 0x30
*/
#define CS_PLAYER_ACTION(linkAction, startFrame, endFrame, rotX, rotY, rotZ, startX, startY, startZ, endX, endY, endZ, normX, normY, normZ) \
CS_NPC_ACTION(linkAction, startFrame, endFrame, rotX, rotY, rotZ, startX, startY, startZ, endX, endY, endZ, normX, normY, normZ)
/**
* ARGS
* s32 entries (e)
* FORMAT
* 00000013 eeeeeeee
* size = 0x8
*/
#define CS_TEXT_LIST(entries) CS_CMD_TEXTBOX, CMD_W(entries)
/**
* ARGS
* s16 messageId (i), s16 startFrame (s), s16 endFrame (e), s16 type (o),
* s16 topOptionBranch (y), s16 bottomOptionBranch (n)
* FORMAT
* iiiissss eeeeoooo yyyynnnn
* size = 0xC
*/
#define CS_TEXT_DISPLAY_TEXTBOX(messageId, startFrame, endFrame, type, topOptionBranch, bottomOptionBranch) \
CMD_HH(messageId, startFrame), CMD_HH(endFrame, type), CMD_HH(topOptionBranch, bottomOptionBranch)
/**
* ARGS
* s16 startFrame (s), s16 endFrame (e)
* FORMAT
* FFFFssss eeeeFFFF FFFFFFFF
* size = 0xC
*/
#define CS_TEXT_NONE(startFrame, endFrame) \
CS_TEXT_DISPLAY_TEXTBOX(0xFFFF, startFrame, endFrame, 0xFFFF, 0xFFFF, 0xFFFF)
/**
* ARGS
* s16 ocarinaSongAction (o), s16 startFrame (s), s16 endFrame (e), s16 topOptionBranch (i)
* FORMAT
* oooossss eeee0002 iiiiFFFF
* size = 0xC
*/
#define CS_TEXT_LEARN_SONG(ocarinaSongAction, startFrame, endFrame, messageId) \
CS_TEXT_DISPLAY_TEXTBOX(ocarinaSongAction, startFrame, endFrame, 0x0002, messageId, 0xFFFF)
/**
* ARGS
* s16 transitionType (t), s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused , endFrame duplicate
* 0000002D 00000001 ttttssss eeeeUUUU
* size = 0x10
*/
#define CS_SCENE_TRANS_FX(transitionType, startFrame, endFrame) \
CS_CMD_SCENE_TRANS_FX, 0x00000001, CMD_HH(transitionType, startFrame), CMD_HH(endFrame, endFrame)
/**
* ARGS
* s32 entries (e)
* FORMAT
* 00000056 eeeeeeee
* size = 0x8
*/
#define CS_PLAY_BGM_LIST(entries) CS_CMD_PLAYBGM, CMD_W(entries)
/**
* ARGS
* s16 sequence (q), s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused
* qqqqssss eeeeUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU 00000000 00000000 00000000
* size = 0x30
*/
#define CS_PLAY_BGM(sequence, startFrame, endFrame, unused0, unused1, unused2, unused3, unused4, unused5, unused6, unused7) \
CMD_HH(sequence, startFrame), CMD_HH(endFrame, unused0), \
CMD_W(unused1), CMD_W(unused2), CMD_W(unused3), CMD_W(unused4), CMD_W(unused5), \
CMD_W(unused6), CMD_W(unused7), 0x00000000, 0x00000000, 0x00000000
/**
* ARGS
* s32 entries (e)
* FORMAT
* 00000057 eeeeeeee
* size = 0x8
*/
#define CS_STOP_BGM_LIST(entries) CS_CMD_STOPBGM, CMD_W(entries)
/**
* ARGS
* s16 sequence (q), s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused
* uuqqssss eeeeUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU 00000000 00000000 00000000
* size = 0x30
*/
#define CS_STOP_BGM(sequence, startFrame, endFrame, unused0, unused1, unused2, unused3, unused4, unused5, unused6, unused7) \
CMD_HH(sequence, startFrame), CMD_HH(endFrame, unused0), \
CMD_W(unused1), CMD_W(unused2), CMD_W(unused3), CMD_W(unused4), CMD_W(unused5), \
CMD_W(unused6), CMD_W(unused7), 0x00000000, 0x00000000, 0x00000000
/**
* ARGS
* s32 entries (e)
* FORMAT
* 0000007C eeeeeeee
* size = 0x8
*/
#define CS_FADE_BGM_LIST(entries) CS_CMD_FADEBGM, CMD_W(entries)
/**
* ARGS
* s16 fadeType (t), s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused
* ttttssss eeeeUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU UUUUUUUU 00000000 00000000 00000000
* size = 0x30
*/
#define CS_FADE_BGM(fadeType, startFrame, endFrame, unused0, unused1, unused2, unused3, unused4, unused5, unused6, unused7) \
CMD_HH(fadeType, startFrame), CMD_HH(endFrame, unused0), \
CMD_W(unused1), CMD_W(unused2), CMD_W(unused3), CMD_W(unused4), CMD_W(unused5), \
CMD_W(unused6), CMD_W(unused7), 0x00000000, 0x00000000, 0x00000000
/**
* ARGS
* s32 entries (e)
* FORMAT
* 0000008C eeeeeeee
* size = 0x8
*/
#define CS_TIME_LIST(entries) CS_CMD_SETTIME, CMD_W(entries)
/**
* ARGS
* s16 unk (u), s16 startFrame (s), s16 endFrame (e), s8 hour (h), s8 min (m)
* FORMAT
* Capital U is Unused
* uuuussss eeeehhmm UUUUUUUU
* size = 0xC
*/
#define CS_TIME(unk, startFrame, endFrame, hour, min, unused) \
CMD_HH(unk, startFrame), \
CMD_HBB(endFrame, hour, min), \
CMD_W(unused)
/**
* ARGS
* CutsceneTerminatorDestination dest (d), s16 startFrame (s), s16 endFrame (e)
* FORMAT
* Capital U is Unused , endFrame duplicate
* 000003E8 00000001 ddddssss eeeeUUUU
* size = 0x10
*/
#define CS_TERMINATOR(dest, startFrame, endFrame) \
CS_CMD_TERMINATOR, 0x00000001, CMD_HH(dest, startFrame), CMD_HH(endFrame, endFrame)
/**
* Marks the end of a cutscene
*/
#define CS_END() 0xFFFFFFFF, 0x00000000
#endif

View file

@ -0,0 +1,16 @@
{
"file1": "File 1",
"file2": "File 2",
"file3": "File 3",
"options": "Options",
"copy": "Copy",
"erase": "Erase",
"quit": "Quit",
"confirm": "Yes",
"audio_stereo": "Sound - Stereo",
"audio_mono": "Sound - Mono",
"audio_headset": "Sound - Headset",
"audio_surround": "Sound - Surround",
"target_switch": "Targetting Mode - Switch",
"target_hold": "Targetting Mode - Hold"
}

View file

@ -0,0 +1,16 @@
{
"file1": "Fichier 1",
"file2": "Fichier 2",
"file3": "Fichier 3",
"options": "Options",
"copy": "Copier",
"erase": "Effacer",
"quit": "Retour",
"confirm": "Oui",
"audio_stereo": "Son - Stéréo",
"audio_mono": "Son - Mono",
"audio_headset": "Son - Casque",
"audio_surround": "Son - Surround",
"target_switch": "Visée - Fixe",
"target_hold": "Visée - Maintenue"
}

View file

@ -0,0 +1,16 @@
{
"file1": "Datei 1",
"file2": "Datei 2",
"file3": "Datei 3",
"options": "Optionen",
"copy": "Kopieren",
"erase": "Löschen",
"quit": "Zurück",
"confirm": "Ja",
"audio_stereo": "Sound - Stereo",
"audio_mono": "Sound - Mono",
"audio_headset": "Sound - Kopfhörer",
"audio_surround": "Sound - Surround",
"target_switch": "Zielerfassung - Einmal drücken",
"target_hold": "Zielerfassung - Trigger halten"
}

View file

@ -1,38 +1,24 @@
{ {
"health": "Health - $0 Hearts", "health": "health $0",
"magic": "Magic - $0", "magic": "magic $0",
"rupees": "Rupees - $0", "rupees": "rupees $0",
"keys": "Keys - $0", "0": "Deku Stick $0",
"floor": "Floor $0", "1": "Deku Nut $0",
"basement": "Basement $0", "2": "Bomb $0",
"item_menu": "Select Item", "3": "Fairy Bow $0",
"map_menu": "Map - $0",
"quest_menu": "Quest Status",
"equip_menu": "Equipment",
"overworld": "Overworld",
"equipped": "$0 - Equipped",
"save_prompt": "Would you like to save?",
"game_saved": "Game saved",
"game_over": "Game Over",
"continue_game": "Continue playing?",
"assigned_to": "Assigned to $0",
"0": "Deku Stick - $0",
"1": "Deku Nut - $0",
"2": "Bomb - $0",
"3": "Fairy Bow - $0",
"4": "Fire Arrow", "4": "Fire Arrow",
"5": "Din's Fire", "5": "Din's Fire",
"6": "Fairy Slingshot - $0", "6": "Fairy Slingshot $0",
"7": "Fairy Ocarina", "7": "Fairy Ocarina",
"8": "Ocarina of Time", "8": "Ocarina of Time",
"9": "Bombchu - $0", "9": "Bombchu $0",
"10": "Hookshot", "10": "Hookshot",
"11": "Longshot", "11": "Longshot",
"12": "Ice Arrow", "12": "Ice Arrow",
"13": "Farore's Wind", "13": "Farore's Wind",
"14": "Boomerang", "14": "Boomerang",
"15": "Lens of Truth", "15": "Lens of Truth",
"16": "Magic Beans - $0", "16": "Magic Beans $0",
"17": "Megaton Hammer", "17": "Megaton Hammer",
"18": "Light Arrow", "18": "Light Arrow",
"19": "Nayru's Love", "19": "Nayru's Love",
@ -129,8 +115,8 @@
"110": "Zora Sapphire", "110": "Zora Sapphire",
"111": "Stone of Agony", "111": "Stone of Agony",
"112": "Gerudo's Card", "112": "Gerudo's Card",
"113": "Skulltula Token - $0", "113": "Skulltula Token $0",
"114": "Piece of Heart - $0", "114": "Heart Container $0",
"115": "Piece of Heart", "115": "Piece of Heart",
"116": "Boss Key", "116": "Boss Key",
"117": "Compass", "117": "Compass",
@ -138,7 +124,7 @@
"119": "Small Key", "119": "Small Key",
"120": "MAGIC SMALL", "120": "MAGIC SMALL",
"121": "MAGIC LARGE", "121": "MAGIC LARGE",
"122": "Biggoron's Sword", "122": "PIECE OF HEART 2",
"123": "INVALID 1", "123": "INVALID 1",
"124": "INVALID 2", "124": "INVALID 2",
"125": "INVALID 3", "125": "INVALID 3",

View file

@ -1,38 +1,24 @@
{ {
"health": "Vie - $0 Coeurs", "health": "vie $0",
"magic": "Magie - $0", "magic": "magie $0",
"rupees": "Rubis - $0", "rupees": "rubis $0",
"keys": "Clés - $0", "0": "Bâton Mojo $0",
"floor": "Étage $0", "1": "Noix Mojo $0",
"basement": "Sous-sol $0", "2": "Bombes $0",
"item_menu": "Inventaire", "3": "Arc des Fées $0",
"map_menu": "Carte - $0",
"quest_menu": "Statut de la quête",
"equip_menu": "Equipment",
"overworld": "Surmonde",
"equipped": "$0 - Équipé",
"save_prompt": "Voulez-vous sauvegarder ?",
"game_saved": "Jeu sauvegardé",
"game_over": "Game Over",
"continue_game": "Continuer la partie ?",
"assigned_to": "Assigné au $0",
"0": "Bâton Mojo - $0",
"1": "Noix Mojo - $0",
"2": "Bombes - $0",
"3": "Arc des Fées - $0",
"4": "Flèche de Feu", "4": "Flèche de Feu",
"5": "Feu de Din", "5": "Feu de Din",
"6": "Lance-Pierre des Fées - $0", "6": "Lance-Pierre des Fées $0",
"7": "Ocarina des Fées", "7": "Ocarina des Fées",
"8": "Ocarina of Temps", "8": "Ocarina of Temps",
"9": "Missiles Teigneux - $0", "9": "Missiles Teigneux $0",
"10": "Grappin", "10": "Grappin",
"11": "Super Grappin", "11": "Super Grappin",
"12": "Flèche de Glace", "12": "Flèche de Glace",
"13": "Vent de Farore", "13": "Vent de Farore",
"14": "Boomerang", "14": "Boomerang",
"15": "Monocle de Vérité", "15": "Monocle de Vérité",
"16": "Haricot Magique - $0", "16": "Haricot Magique $0",
"17": "Masse des Titans", "17": "Masse des Titans",
"18": "Flèche de Lumière", "18": "Flèche de Lumière",
"19": "Amour de Nayru", "19": "Amour de Nayru",
@ -129,8 +115,8 @@
"110": "Saphir Zora", "110": "Saphir Zora",
"111": "Pierre de Souffrance", "111": "Pierre de Souffrance",
"112": "Carte Gerudo", "112": "Carte Gerudo",
"113": "Skulltula d'or - $0", "113": "Skulltula d'or $0",
"114": "Quart de Coeur - $0", "114": "Coeur d'Énergie $0",
"115": "Quart de Coeur", "115": "Quart de Coeur",
"116": "Clé d'or", "116": "Clé d'or",
"117": "Boussole", "117": "Boussole",
@ -138,7 +124,7 @@
"119": "Petite Clé", "119": "Petite Clé",
"120": "PETITE BOUTEILLE DE MAGIE", "120": "PETITE BOUTEILLE DE MAGIE",
"121": "GRANDE BOUTEILLE DE MAGIE", "121": "GRANDE BOUTEILLE DE MAGIE",
"122": "Épée de Biggoron", "122": "QUART DE COEUR 2",
"123": "INVALIDE 1", "123": "INVALIDE 1",
"124": "INVALIDE 2", "124": "INVALIDE 2",
"125": "INVALIDE 3", "125": "INVALIDE 3",

View file

@ -1,38 +1,24 @@
{ {
"health": "Energie - $0 Herzen", "health": "Energie $0",
"magic": "Magie - $0", "magic": "Magie $0",
"rupees": "Rubine - $0", "rupees": "Rubine $0",
"keys": "Schlüssel - $0", "0": "Deku-Stab $0",
"floor": "Etage $0", "1": "Deku-Nuß $0",
"basement": "Keller $0", "2": "Bombe $0",
"item_menu": "Gegenstände", "3": "Feen-Bogen $0",
"map_menu": "Karte - $0",
"quest_menu": "Quest Status",
"equip_menu": "Ausrüstung",
"overworld": "Überwelt",
"equipped": "$0 - Ausgerüstet",
"save_prompt": "Spielstand sichern ?",
"game_saved": "Spielstand gesichert",
"game_over": "Game Over",
"continue_game": "Spiel fortsetzen ?",
"assigned_to": "$0 zugeordnet",
"0": "Deku-Stab - $0",
"1": "Deku-Nuß - $0",
"2": "Bombe - $0",
"3": "Feen-Bogen - $0",
"4": "Feuer-Pfeil", "4": "Feuer-Pfeil",
"5": "Dins Feuerinferno", "5": "Dins Feuerinferno",
"6": "Feen-Schleuder - $0", "6": "Feen-Schleuder $0",
"7": "Feen-Okarina", "7": "Feen-Okarina",
"8": "Okarina der Zeit", "8": "Okarina der Zeit",
"9": "Krabbelmine - $0", "9": "Krabbelmine $0",
"10": "Fanghaken", "10": "Fanghaken",
"11": "Enterhaken", "11": "Enterhaken",
"12": "Eis-Pfeil", "12": "Eis-Pfeil",
"13": "Farores Donnersturm", "13": "Farores Donnersturm",
"14": "Bumerang", "14": "Bumerang",
"15": "Auge der Wahrheit", "15": "Auge der Wahrheit",
"16": "Wundererbsen - $0", "16": "Wundererbsen $0",
"17": "Stahlhammer", "17": "Stahlhammer",
"18": "Licht-Pfeil", "18": "Licht-Pfeil",
"19": "Nayrus Umarmung", "19": "Nayrus Umarmung",
@ -129,8 +115,8 @@
"110": "Zora-Saphir", "110": "Zora-Saphir",
"111": "Stein des Wissens", "111": "Stein des Wissens",
"112": "Gerudo-Paß", "112": "Gerudo-Paß",
"113": "Skulltula-Symbol - $0", "113": "Skulltula-Symbol $0",
"114": "Herzteil - $0", "114": "Herzcontainer $0",
"115": "Herzteil", "115": "Herzteil",
"116": "Master-Schlüssel", "116": "Master-Schlüssel",
"117": "Kompaß", "117": "Kompaß",
@ -138,7 +124,7 @@
"119": "Kleiner Schlüssel", "119": "Kleiner Schlüssel",
"120": "MAGIE KLEIN", "120": "MAGIE KLEIN",
"121": "MAGIE GROß", "121": "MAGIE GROß",
"122": "Biggoron-Schwert", "122": "HERZTEIL 2",
"123": "UNGÜLTIG 1", "123": "UNGÜLTIG 1",
"124": "UNGÜLTIG 2", "124": "UNGÜLTIG 2",
"125": "UNGÜLTIG 3", "125": "UNGÜLTIG 3",

View file

@ -0,0 +1,18 @@
{
"minutes_plural" : "$0 minutes",
"minutes_singular" : "$0 minute",
"seconds_plural" : "$0 seconds",
"seconds_singular" : "$0 second",
"input_button_a": "the A button",
"input_button_b": "the B button",
"input_button_c": "the C button",
"input_button_l": "the L button",
"input_button_r": "the R button",
"input_button_z": "the Z button",
"input_button_c_up": "C Up",
"input_button_c_down": "C Down",
"input_button_c_left": "C Left",
"input_button_c_right": "C Right",
"input_analog_stick": "the Analog Stick",
"input_d_pad": "the D-Pad"
}

View file

@ -0,0 +1,18 @@
{
"minutes_plural" : "$0 minutes",
"minutes_singular" : "$0 minute",
"seconds_plural" : "$0 secondes",
"seconds_singular" : "$0 seconde",
"input_button_a": "le bouton A",
"input_button_b": "le bouton B",
"input_button_c": "le bouton C",
"input_button_l": "le bouton L",
"input_button_r": "le bouton R",
"input_button_z": "le bouton Z",
"input_button_c_up": "C Haut",
"input_button_c_down": "C Bas",
"input_button_c_left": "C Gauche",
"input_button_c_right": "C Droit",
"input_analog_stick": "le Stick Analogique",
"input_d_pad": "D-Pad"
}

View file

@ -0,0 +1,18 @@
{
"minutes_plural" : "$0 Minuten",
"minutes_singular" : "eine Minute",
"seconds_plural" : "$0 Sekunden",
"seconds_singular" : "eine Sekunde",
"input_button_a": "den A-Knopf",
"input_button_b": "den B-Knopf",
"input_button_c": "den C-Knopf",
"input_button_l": "den L-Knopf",
"input_button_r": "den R-Knopf",
"input_button_z": "den Z-Knopf",
"input_button_c_up": "C Oben",
"input_button_c_down": "C Unten",
"input_button_c_left": "C Links",
"input_button_c_right": "C Rechts",
"input_analog_stick": "den Analog-Stick",
"input_d_pad": "das Steuerkreuz"
}

View file

@ -1,5 +1,5 @@
{ {
"0": "Arbre Mojo", "0": "Abre Mojo",
"1": "Caverne Dodongo", "1": "Caverne Dodongo",
"2": "Ventre de Jabu-Jabu", "2": "Ventre de Jabu-Jabu",
"3": "Temple de la Forêt", "3": "Temple de la Forêt",
@ -58,9 +58,9 @@
"56": "Laboratoire du Lac", "56": "Laboratoire du Lac",
"57": "", // Tente du Marathonien (No title card) "57": "", // Tente du Marathonien (No title card)
"58": "Cabane du fossoyeur", "58": "Cabane du fossoyeur",
"59": "Fontaine Royale des Fées", "59": "Fountaine Royale des Fées",
"60": "Fontaine des Fées", "60": "Fountaine des Fées",
"61": "Fontaine Royale des Fées", "61": "Fountaine Royale des Fées",
"62": "", // Grottes (No title card) "62": "", // Grottes (No title card)
"63": "", // Tombe 1 (No title card) "63": "", // Tombe 1 (No title card)
"64": "", // Tombe 2 (No title card) "64": "", // Tombe 2 (No title card)

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