mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-04-28 13:17:58 +03:00
Merge 931c80f5e1
into fbbfc07ff1
This commit is contained in:
commit
21947b34bb
66 changed files with 12242 additions and 563 deletions
2
.github/workflows/apt-deps.txt
vendored
2
.github/workflows/apt-deps.txt
vendored
|
@ -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
|
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
|
20
.github/workflows/generate-builds.yml
vendored
20
.github/workflows/generate-builds.yml
vendored
|
@ -62,16 +62,16 @@ jobs:
|
||||||
cmake ..
|
cmake ..
|
||||||
make
|
make
|
||||||
sudo make install
|
sudo make install
|
||||||
- name: Generate soh.otr
|
- name: Generate soh.o2r
|
||||||
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 GenerateSohOtr -j3
|
||||||
- name: Upload soh.otr
|
- name: Upload soh.o2r
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: soh.otr
|
name: soh.o2r
|
||||||
path: soh.otr
|
path: soh.o2r
|
||||||
retention-days: 3
|
retention-days: 3
|
||||||
|
|
||||||
build-macos:
|
build-macos:
|
||||||
|
@ -122,10 +122,10 @@ jobs:
|
||||||
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.otr
|
- name: Download soh.o2r
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: soh.otr
|
name: soh.o2r
|
||||||
path: build-cmake/soh
|
path: build-cmake/soh
|
||||||
- name: Build SoH
|
- name: Build SoH
|
||||||
run: |
|
run: |
|
||||||
|
@ -233,10 +233,10 @@ jobs:
|
||||||
make
|
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/libzip* /lib/x86_64-linux-gnu/
|
||||||
- name: Download soh.otr
|
- name: Download soh.o2r
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: soh.otr
|
name: soh.o2r
|
||||||
path: build-cmake/soh
|
path: build-cmake/soh
|
||||||
- name: Build SoH
|
- name: Build SoH
|
||||||
run: |
|
run: |
|
||||||
|
@ -298,10 +298,10 @@ jobs:
|
||||||
path: vcpkg
|
path: vcpkg
|
||||||
- name: Configure Developer Command Prompt
|
- name: Configure Developer Command Prompt
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
- name: Download soh.otr
|
- name: Download soh.o2r
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: soh.otr
|
name: soh.o2r
|
||||||
path: build-windows/soh
|
path: build-windows/soh
|
||||||
- name: Build SoH
|
- name: Build SoH
|
||||||
env:
|
env:
|
||||||
|
|
2
.github/workflows/macports-deps.txt
vendored
2
.github/workflows/macports-deps.txt
vendored
|
@ -1 +1 @@
|
||||||
libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal libzip +universal nlohmann-json +universal tinyxml2 +universal
|
libsdl2 +universal libsdl2_net +universal libpng +universal glew +universal libzip +universal nlohmann-json +universal tinyxml2 +universal libogg +universal libopus +universal opusfile +universal libvorbis +universal
|
2
.github/workflows/pr-artifacts.yml
vendored
2
.github/workflows/pr-artifacts.yml
vendored
|
@ -48,7 +48,7 @@ jobs:
|
||||||
});
|
});
|
||||||
|
|
||||||
return allArtifacts.data.artifacts.reduce((acc, item) => {
|
return allArtifacts.data.artifacts.reduce((acc, item) => {
|
||||||
if (item.name === "soh.otr") return acc;
|
if (item.name === "soh.o2r") 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;
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -412,6 +412,7 @@ ReleaseObj/*
|
||||||
.tags
|
.tags
|
||||||
tags
|
tags
|
||||||
*.otr
|
*.otr
|
||||||
|
*.o2r
|
||||||
*.sav
|
*.sav
|
||||||
shipofharkinian.ini
|
shipofharkinian.ini
|
||||||
shipofharkinian.json
|
shipofharkinian.json
|
||||||
|
|
61
CMake/FindOgg.cmake
Normal file
61
CMake/FindOgg.cmake
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
# - 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)
|
44
CMake/FindOpus.cmake
Normal file
44
CMake/FindOpus.cmake
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# - 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)
|
55
CMake/FindOpusFile.cmake
Normal file
55
CMake/FindOpusFile.cmake
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
# 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()
|
210
CMake/FindVorbis.cmake
Normal file
210
CMake/FindVorbis.cmake
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
#[=======================================================================[.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)
|
|
@ -82,8 +82,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
set(VCPKG_TARGET_TRIPLET x64-windows-static)
|
set(VCPKG_TARGET_TRIPLET x64-windows-static)
|
||||||
|
|
||||||
vcpkg_bootstrap()
|
vcpkg_bootstrap()
|
||||||
vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3 nlohmann-json tinyxml2 spdlog)
|
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")
|
if (CMAKE_C_COMPILER_LAUNCHER MATCHES "ccache|sccache")
|
||||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
|
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
|
||||||
endif()
|
endif()
|
||||||
|
@ -153,6 +152,7 @@ set(GFX_DEBUG_DISASSEMBLER ON)
|
||||||
|
|
||||||
# Tell LUS we're using F3DEX_GBI_2 (in a way that doesn't break libgfxd)
|
# Tell LUS we're using F3DEX_GBI_2 (in a way that doesn't break libgfxd)
|
||||||
set(GBI_UCODE F3DEX_GBI_2)
|
set(GBI_UCODE F3DEX_GBI_2)
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Set CONTROLLERBUTTONS_T
|
# Set CONTROLLERBUTTONS_T
|
||||||
|
@ -174,23 +174,15 @@ set_property(TARGET soh PROPERTY APPIMAGE_ICON_FILE "${CMAKE_BINARY_DIR}/sohIcon
|
||||||
|
|
||||||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||||
install(PROGRAMS "${CMAKE_BINARY_DIR}/linux/soh.sh" DESTINATION . COMPONENT appimage)
|
install(PROGRAMS "${CMAKE_BINARY_DIR}/linux/soh.sh" DESTINATION . COMPONENT appimage)
|
||||||
install(FILES "${CMAKE_BINARY_DIR}/soh/soh.otr" DESTINATION . COMPONENT ship)
|
install(FILES "${CMAKE_BINARY_DIR}/soh/soh.o2r" DESTINATION . COMPONENT ship)
|
||||||
install(TARGETS ZAPD DESTINATION ./assets/extractor COMPONENT extractor)
|
install(TARGETS ZAPD DESTINATION ./assets/extractor COMPONENT extractor)
|
||||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/extractor COMPONENT extractor)
|
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets COMPONENT extractor)
|
||||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/extractor/xmls COMPONENT extractor)
|
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml COMPONENT extractor)
|
||||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists/" DESTINATION ./assets/extractor/filelists COMPONENT extractor)
|
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT extractor)
|
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT extractor)
|
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT extractor)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
|
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
|
||||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/extractor COMPONENT ship)
|
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/ COMPONENT ship)
|
||||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/extractor/xmls COMPONENT ship)
|
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml COMPONENT ship)
|
||||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists/" DESTINATION ./assets/extractor/filelists COMPONENT ship)
|
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT ship)
|
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT ship)
|
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols COMPONENT ship)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Python3 COMPONENTS Interpreter)
|
find_package(Python3 COMPONENTS Interpreter)
|
||||||
|
@ -198,42 +190,42 @@ 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.otr oot-mq.otr soh.otr
|
COMMAND ${CMAKE_COMMAND} -E rm -f oot.o2r oot-mq.o2r soh.o2r
|
||||||
|
|
||||||
# copy LUS default shaders into assets/custom
|
# 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 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 ${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 ../soh/assets/xml --custom-otr-file soh.otr "--custom-assets-path" ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom --port-ver "${CMAKE_PROJECT_VERSION}"
|
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}/OTRExporter
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh
|
||||||
COMMENT "Running asset extraction..."
|
COMMENT "Running asset extraction..."
|
||||||
DEPENDS ZAPD
|
DEPENDS ZAPD
|
||||||
BYPRODUCTS oot.otr ${CMAKE_SOURCE_DIR}/oot.otr oot-mq.otr ${CMAKE_SOURCE_DIR}/oot-mq.otr ${CMAKE_SOURCE_DIR}/soh.otr
|
BYPRODUCTS oot.o2r ${CMAKE_SOURCE_DIR}/oot.o2r oot-mq.o2r ${CMAKE_SOURCE_DIR}/oot-mq.o2r ${CMAKE_SOURCE_DIR}/soh.o2r
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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 ../soh/assets/xml --gen-headers
|
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive --xml-root assets/xml --gen-headers
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh
|
||||||
COMMENT "Generating asset headers..."
|
COMMENT "Generating asset headers..."
|
||||||
DEPENDS ZAPD
|
DEPENDS ZAPD
|
||||||
)
|
)
|
||||||
|
|
||||||
# Target to generate only soh.otr
|
# Target to generate only soh.o2r
|
||||||
add_custom_target(
|
add_custom_target(
|
||||||
GenerateSohOtr
|
GenerateSohOtr
|
||||||
COMMAND ${CMAKE_COMMAND} -E rm -f soh.otr
|
COMMAND ${CMAKE_COMMAND} -E rm -f soh.o2r
|
||||||
|
|
||||||
# copy LUS default shaders into assets/custom
|
# 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 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 ${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.otr "--custom-assets-path" ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom --port-ver "${CMAKE_PROJECT_VERSION}"
|
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
|
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}/OTRExporter
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh
|
||||||
COMMENT "Generating soh.otr..."
|
COMMENT "Generating soh.o2r..."
|
||||||
DEPENDS ZAPD
|
DEPENDS ZAPD
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -266,16 +258,12 @@ add_custom_target(CreateOSXIcons
|
||||||
)
|
)
|
||||||
add_dependencies(soh CreateOSXIcons)
|
add_dependencies(soh CreateOSXIcons)
|
||||||
|
|
||||||
install(TARGETS ZAPD DESTINATION ${CMAKE_BINARY_DIR}/assets/extractor)
|
install(TARGETS ZAPD DESTINATION ${CMAKE_BINARY_DIR}/assets)
|
||||||
|
|
||||||
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/extractor)
|
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/)
|
||||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/extractor/xmls)
|
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml)
|
||||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists/" DESTINATION ./assets/extractor/filelists)
|
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols)
|
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols)
|
|
||||||
install(FILES "${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt" DESTINATION ./assets/extractor/symbols)
|
|
||||||
|
|
||||||
install(DIRECTORY ${CMAKE_BINARY_DIR}/assets
|
install(DIRECTORY ${CMAKE_BINARY_DIR}/assets
|
||||||
DESTINATION .
|
DESTINATION .
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 41052efcdf8df8e67517cc93da8975fcd4e14af9
|
Subproject commit 461ab19a36cde807591543397e136cae19aa6e7c
|
2
ZAPDTR
2
ZAPDTR
|
@ -1 +1 @@
|
||||||
Subproject commit 2aeababbfb81b00d34673406453e8e8e2deaa27b
|
Subproject commit 684f21a475dcfeee89938ae1f4afc42768a3e7ef
|
|
@ -1,37 +1,37 @@
|
||||||
message(STATUS "Copying otr files...")
|
message(STATUS "Copying otr files...")
|
||||||
|
|
||||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot.otr)
|
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot.o2r)
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${SOURCE_DIR})
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.o2r ${SOURCE_DIR})
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${BINARY_DIR}/soh/)
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.o2r ${BINARY_DIR}/soh/)
|
||||||
message(STATUS "Copied oot.otr")
|
message(STATUS "Copied oot.o2r")
|
||||||
endif()
|
endif()
|
||||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot-mq.otr)
|
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot-mq.o2r)
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.otr ${SOURCE_DIR})
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.o2r ${SOURCE_DIR})
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.otr ${BINARY_DIR}/soh/)
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.o2r ${BINARY_DIR}/soh/)
|
||||||
message(STATUS "Copied oot-mq.otr")
|
message(STATUS "Copied oot-mq.o2r")
|
||||||
endif()
|
endif()
|
||||||
if(EXISTS ${SOURCE_DIR}/OTRExporter/soh.otr)
|
if(EXISTS ${SOURCE_DIR}/soh/soh.o2r)
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.otr ${SOURCE_DIR})
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.o2r ${SOURCE_DIR})
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.otr ${BINARY_DIR}/soh/)
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.o2r ${BINARY_DIR}/soh/)
|
||||||
message(STATUS "Copied soh.otr")
|
message(STATUS "Copied soh.o2r")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Additionally for Windows, copy the otrs to the target dir, side by side with soh.exe
|
# Additionally for Windows, copy the otrs to the target dir, side by side with soh.exe
|
||||||
if(SYSTEM_NAME MATCHES "Windows")
|
if(SYSTEM_NAME MATCHES "Windows")
|
||||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot.otr)
|
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot.o2r)
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${TARGET_DIR})
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.o2r ${TARGET_DIR})
|
||||||
endif()
|
endif()
|
||||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot-mq.otr)
|
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot-mq.o2r)
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.otr ${TARGET_DIR})
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.o2r ${TARGET_DIR})
|
||||||
endif()
|
endif()
|
||||||
if(EXISTS ${SOURCE_DIR}/OTRExporter/soh.otr)
|
if(EXISTS ${SOURCE_DIR}/soh/soh.o2r)
|
||||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.otr ${TARGET_DIR})
|
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.o2r ${TARGET_DIR})
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT ONLYSOHOTR AND (NOT EXISTS ${SOURCE_DIR}/oot.otr AND NOT EXISTS ${SOURCE_DIR}/oot-mq.otr))
|
if(NOT ONLYSOHOTR AND (NOT EXISTS ${SOURCE_DIR}/oot.o2r AND NOT EXISTS ${SOURCE_DIR}/oot-mq.o2r))
|
||||||
message(FATAL_ERROR "Failed to copy. No OTR files found.")
|
message(FATAL_ERROR "Failed to copy. No OTR files found.")
|
||||||
endif()
|
endif()
|
||||||
if(NOT EXISTS ${SOURCE_DIR}/soh.otr)
|
if(NOT EXISTS ${SOURCE_DIR}/soh.o2r)
|
||||||
message(FATAL_ERROR "Failed to copy. No soh OTR found.")
|
message(FATAL_ERROR "Failed to copy. No soh OTR found.")
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -278,6 +278,14 @@ endif()
|
||||||
# Find/download Boost
|
# Find/download Boost
|
||||||
################################################################################
|
################################################################################
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
dr_libs
|
||||||
|
GIT_REPOSITORY https://github.com/mackron/dr_libs.git
|
||||||
|
GIT_TAG da35f9d6c7374a95353fd1df1d394d44ab66cf01
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(dr_libs)
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
Boost
|
Boost
|
||||||
URL https://archives.boost.io/release/1.81.0/source/boost_1_81_0.tar.gz
|
URL https://archives.boost.io/release/1.81.0/source/boost_1_81_0.tar.gz
|
||||||
|
@ -350,6 +358,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE assets
|
||||||
${SDL2-NET-INCLUDE}
|
${SDL2-NET-INCLUDE}
|
||||||
${BOOST-INCLUDE}
|
${BOOST-INCLUDE}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/assets/
|
${CMAKE_CURRENT_SOURCE_DIR}/assets/
|
||||||
|
${dr_libs_SOURCE_DIR}
|
||||||
.
|
.
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -589,6 +598,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
||||||
-Wno-missing-braces
|
-Wno-missing-braces
|
||||||
-Wno-int-conversion
|
-Wno-int-conversion
|
||||||
-Wno-implicit-int
|
-Wno-implicit-int
|
||||||
|
# -fsanitize=address
|
||||||
$<$<COMPILE_LANGUAGE:C>:
|
$<$<COMPILE_LANGUAGE:C>:
|
||||||
-Werror-implicit-function-declaration
|
-Werror-implicit-function-declaration
|
||||||
-Wno-incompatible-pointer-types
|
-Wno-incompatible-pointer-types
|
||||||
|
@ -601,6 +611,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
||||||
|
|
||||||
target_link_options(${PROJECT_NAME} PRIVATE
|
target_link_options(${PROJECT_NAME} PRIVATE
|
||||||
-pthread
|
-pthread
|
||||||
|
#-fsanitize=address
|
||||||
-Wl,-export-dynamic
|
-Wl,-export-dynamic
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
@ -618,11 +629,7 @@ if(NOT CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
|
||||||
COMMENT "Copying asset xmls..."
|
COMMENT "Copying asset xmls..."
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/soh/assets/extractor $<TARGET_FILE_DIR:soh>/assets/extractor
|
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/soh/assets/extractor $<TARGET_FILE_DIR:soh>/assets/extractor
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/soh/assets/xml $<TARGET_FILE_DIR:soh>/assets/extractor/xmls
|
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/soh/assets/xml $<TARGET_FILE_DIR:soh>/assets/extractor/xmls
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_SOURCE_DIR}/OTRExporter/CFG/filelists $<TARGET_FILE_DIR:soh>/assets/extractor/filelists
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:soh>/assets/extractor/symbols
|
COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:soh>/assets/extractor/symbols
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ActorList_OoTMqDbg.txt $<TARGET_FILE_DIR:soh>/assets/extractor/symbols
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/OTRExporter/CFG/ObjectList_OoTMqDbg.txt $<TARGET_FILE_DIR:soh>/assets/extractor/symbols
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/OTRExporter/CFG/SymbolMap_OoTMqDbg.txt $<TARGET_FILE_DIR:soh>/assets/extractor/symbols
|
|
||||||
COMMAND ${VS_COPY_ASSETS_CMD}
|
COMMAND ${VS_COPY_ASSETS_CMD}
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
@ -640,6 +647,15 @@ endif()
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
find_package(glfw3 REQUIRED)
|
find_package(glfw3 REQUIRED)
|
||||||
|
find_package(Ogg CONFIG REQUIRED)
|
||||||
|
link_libraries(Ogg::ogg)
|
||||||
|
|
||||||
|
find_package(Vorbis CONFIG REQUIRED)
|
||||||
|
link_libraries(Vorbis::vorbisfile)
|
||||||
|
find_package(Opus CONFIG REQUIRED)
|
||||||
|
link_libraries(Opus::opus)
|
||||||
|
find_package(OpusFile CONFIG REQUIRED)
|
||||||
|
link_libraries(OpusFile::opusfile CONFIG REQUIRED)
|
||||||
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
|
if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64")
|
||||||
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
||||||
"libultraship;"
|
"libultraship;"
|
||||||
|
@ -653,6 +669,12 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
"imm32;"
|
"imm32;"
|
||||||
"version;"
|
"version;"
|
||||||
"setupapi"
|
"setupapi"
|
||||||
|
"Ogg::ogg"
|
||||||
|
"Opus::opus"
|
||||||
|
"Vorbis::vorbis"
|
||||||
|
"Vorbis::vorbisenc"
|
||||||
|
"Vorbis::vorbisfile"
|
||||||
|
"OpusFile::opusfile"
|
||||||
)
|
)
|
||||||
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32")
|
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32")
|
||||||
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
||||||
|
@ -693,10 +715,21 @@ else()
|
||||||
find_package(SDL2)
|
find_package(SDL2)
|
||||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
find_package(Ogg REQUIRED)
|
||||||
|
find_package(Vorbis REQUIRED)
|
||||||
|
find_package(Opus REQUIRED)
|
||||||
|
find_package(OpusFile REQUIRED)
|
||||||
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
||||||
"libultraship;"
|
"libultraship;"
|
||||||
"ZAPDLib;"
|
"ZAPDLib;"
|
||||||
SDL2::SDL2
|
SDL2::SDL2
|
||||||
|
"Ogg::ogg"
|
||||||
|
"Vorbis::vorbis"
|
||||||
|
"Vorbis::vorbisenc"
|
||||||
|
"Vorbis::vorbisfile"
|
||||||
|
"Opus::opus"
|
||||||
|
"Opusfile::Opusfile"
|
||||||
"$<$<BOOL:${BUILD_REMOTE_CONTROL}>:SDL2_net::SDL2_net>"
|
"$<$<BOOL:${BUILD_REMOTE_CONTROL}>:SDL2_net::SDL2_net>"
|
||||||
${CMAKE_DL_LIBS}
|
${CMAKE_DL_LIBS}
|
||||||
Threads::Threads
|
Threads::Threads
|
||||||
|
@ -709,7 +742,7 @@ endif()
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
INSTALL(FILES $<TARGET_PDB_FILE:soh> DESTINATION ./debug COMPONENT ship)
|
INSTALL(FILES $<TARGET_PDB_FILE:soh> DESTINATION ./debug COMPONENT ship)
|
||||||
INSTALL(FILES ${CMAKE_BINARY_DIR}/soh/soh.otr DESTINATION . COMPONENT ship)
|
INSTALL(FILES ${CMAKE_BINARY_DIR}/soh/soh.o2r DESTINATION . COMPONENT ship)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
@ -723,7 +756,7 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||||
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/macosx/Info.plist.in ${CMAKE_BINARY_DIR}/macosx/Info.plist @ONLY)
|
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/macosx/Info.plist.in ${CMAKE_BINARY_DIR}/macosx/Info.plist @ONLY)
|
||||||
INSTALL(TARGETS soh DESTINATION ../MacOS COMPONENT ship)
|
INSTALL(TARGETS soh DESTINATION ../MacOS COMPONENT ship)
|
||||||
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION ../MacOS COMPONENT ship)
|
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION ../MacOS COMPONENT ship)
|
||||||
INSTALL(FILES ${CMAKE_BINARY_DIR}/soh/soh.otr DESTINATION ../Resources COMPONENT ship)
|
INSTALL(FILES ${CMAKE_BINARY_DIR}/soh/soh.o2r DESTINATION ../Resources COMPONENT ship)
|
||||||
elseif(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "NintendoSwitch|CafeOS")
|
elseif(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "NintendoSwitch|CafeOS")
|
||||||
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION . COMPONENT ship)
|
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION . COMPONENT ship)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_MQ_D/"/>
|
<ExternalXMLFolder Path="assets/xml/GC_MQ_D/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_MQ_NTSC_J/"/>
|
<ExternalXMLFolder Path="assets/xml/GC_MQ_NTSC_J/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_MQ_NTSC_U/"/>
|
<ExternalXMLFolder Path="assets/xml/GC_MQ_NTSC_U/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_MQ_PAL_F/"/>
|
<ExternalXMLFolder Path="assets/xml/GC_MQ_PAL_F/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_D/"/>
|
<ExternalXMLFolder Path="assets/xml/GC_NMQ_D/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_NTSC_J/"/>
|
<ExternalXMLFolder Path="assets/xml/GC_NMQ_NTSC_J/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_NTSC_J_CE/"/>
|
<ExternalXMLFolder Path="assets/xml/GC_NMQ_NTSC_J_CE/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_NTSC_U/"/>
|
<ExternalXMLFolder Path="assets/xml/GC_NMQ_NTSC_U/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_PAL_F/"/>
|
<ExternalXMLFolder Path="assets/xml/GC_NMQ_PAL_F/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/N64_NTSC_10/"/>
|
<ExternalXMLFolder Path="assets/xml/N64_NTSC_10/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/N64_NTSC_11/"/>
|
<ExternalXMLFolder Path="assets/xml/N64_NTSC_11/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/N64_NTSC_12/"/>
|
<ExternalXMLFolder Path="assets/xml/N64_NTSC_12/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/N64_PAL_10/"/>
|
<ExternalXMLFolder Path="assets/xml/N64_PAL_10/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||||
<ExternalXMLFolder Path="assets/extractor/xmls/N64_PAL_11/"/>
|
<ExternalXMLFolder Path="assets/xml/N64_PAL_11/"/>
|
||||||
<TexturePool File="TexturePool.xml"/>
|
<TexturePool File="TexturePool.xml"/>
|
||||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||||
</Root>
|
</Root>
|
||||||
|
|
1532
soh/assets/extractor/filelists/dbg.txt
Normal file
1532
soh/assets/extractor/filelists/dbg.txt
Normal file
File diff suppressed because it is too large
Load diff
1509
soh/assets/extractor/filelists/gamecube.txt
Normal file
1509
soh/assets/extractor/filelists/gamecube.txt
Normal file
File diff suppressed because it is too large
Load diff
1510
soh/assets/extractor/filelists/gamecube_pal.txt
Normal file
1510
soh/assets/extractor/filelists/gamecube_pal.txt
Normal file
File diff suppressed because it is too large
Load diff
1510
soh/assets/extractor/filelists/ntsc_12_oot.txt
Normal file
1510
soh/assets/extractor/filelists/ntsc_12_oot.txt
Normal file
File diff suppressed because it is too large
Load diff
1510
soh/assets/extractor/filelists/ntsc_oot.txt
Normal file
1510
soh/assets/extractor/filelists/ntsc_oot.txt
Normal file
File diff suppressed because it is too large
Load diff
1511
soh/assets/extractor/filelists/pal_oot.txt
Normal file
1511
soh/assets/extractor/filelists/pal_oot.txt
Normal file
File diff suppressed because it is too large
Load diff
472
soh/assets/extractor/symbols/ActorList_OoTMqDbg.txt
Normal file
472
soh/assets/extractor/symbols/ActorList_OoTMqDbg.txt
Normal file
|
@ -0,0 +1,472 @@
|
||||||
|
ACTOR_PLAYER
|
||||||
|
ACTOR_UNSET_1
|
||||||
|
ACTOR_EN_TEST
|
||||||
|
ACTOR_UNSET_3
|
||||||
|
ACTOR_EN_GIRLA
|
||||||
|
ACTOR_UNSET_5
|
||||||
|
ACTOR_UNSET_6
|
||||||
|
ACTOR_EN_PART
|
||||||
|
ACTOR_EN_LIGHT
|
||||||
|
ACTOR_EN_DOOR
|
||||||
|
ACTOR_EN_BOX
|
||||||
|
ACTOR_BG_DY_YOSEIZO
|
||||||
|
ACTOR_BG_HIDAN_FIREWALL
|
||||||
|
ACTOR_EN_POH
|
||||||
|
ACTOR_EN_OKUTA
|
||||||
|
ACTOR_BG_YDAN_SP
|
||||||
|
ACTOR_EN_BOM
|
||||||
|
ACTOR_EN_WALLMAS
|
||||||
|
ACTOR_EN_DODONGO
|
||||||
|
ACTOR_EN_FIREFLY
|
||||||
|
ACTOR_EN_HORSE
|
||||||
|
ACTOR_EN_ITEM00
|
||||||
|
ACTOR_EN_ARROW
|
||||||
|
ACTOR_UNSET_17
|
||||||
|
ACTOR_EN_ELF
|
||||||
|
ACTOR_EN_NIW
|
||||||
|
ACTOR_UNSET_1A
|
||||||
|
ACTOR_EN_TITE
|
||||||
|
ACTOR_EN_REEBA
|
||||||
|
ACTOR_EN_PEEHAT
|
||||||
|
ACTOR_EN_BUTTE
|
||||||
|
ACTOR_UNSET_1F
|
||||||
|
ACTOR_EN_INSECT
|
||||||
|
ACTOR_EN_FISH
|
||||||
|
ACTOR_UNSET_22
|
||||||
|
ACTOR_EN_HOLL
|
||||||
|
ACTOR_EN_SCENE_CHANGE
|
||||||
|
ACTOR_EN_ZF
|
||||||
|
ACTOR_EN_HATA
|
||||||
|
ACTOR_BOSS_DODONGO
|
||||||
|
ACTOR_BOSS_GOMA
|
||||||
|
ACTOR_EN_ZL1
|
||||||
|
ACTOR_EN_VIEWER
|
||||||
|
ACTOR_EN_GOMA
|
||||||
|
ACTOR_BG_PUSHBOX
|
||||||
|
ACTOR_EN_BUBBLE
|
||||||
|
ACTOR_DOOR_SHUTTER
|
||||||
|
ACTOR_EN_DODOJR
|
||||||
|
ACTOR_EN_BDFIRE
|
||||||
|
ACTOR_UNSET_31
|
||||||
|
ACTOR_EN_BOOM
|
||||||
|
ACTOR_EN_TORCH2
|
||||||
|
ACTOR_EN_BILI
|
||||||
|
ACTOR_EN_TP
|
||||||
|
ACTOR_UNSET_36
|
||||||
|
ACTOR_EN_ST
|
||||||
|
ACTOR_EN_BW
|
||||||
|
ACTOR_EN_A_OBJ
|
||||||
|
ACTOR_EN_EIYER
|
||||||
|
ACTOR_EN_RIVER_SOUND
|
||||||
|
ACTOR_EN_HORSE_NORMAL
|
||||||
|
ACTOR_EN_OSSAN
|
||||||
|
ACTOR_BG_TREEMOUTH
|
||||||
|
ACTOR_BG_DODOAGO
|
||||||
|
ACTOR_BG_HIDAN_DALM
|
||||||
|
ACTOR_BG_HIDAN_HROCK
|
||||||
|
ACTOR_EN_HORSE_GANON
|
||||||
|
ACTOR_BG_HIDAN_ROCK
|
||||||
|
ACTOR_BG_HIDAN_RSEKIZOU
|
||||||
|
ACTOR_BG_HIDAN_SEKIZOU
|
||||||
|
ACTOR_BG_HIDAN_SIMA
|
||||||
|
ACTOR_BG_HIDAN_SYOKU
|
||||||
|
ACTOR_EN_XC
|
||||||
|
ACTOR_BG_HIDAN_CURTAIN
|
||||||
|
ACTOR_BG_SPOT00_HANEBASI
|
||||||
|
ACTOR_EN_MB
|
||||||
|
ACTOR_EN_BOMBF
|
||||||
|
ACTOR_EN_ZL2
|
||||||
|
ACTOR_BG_HIDAN_FSLIFT
|
||||||
|
ACTOR_EN_OE2
|
||||||
|
ACTOR_BG_YDAN_HASI
|
||||||
|
ACTOR_BG_YDAN_MARUTA
|
||||||
|
ACTOR_BOSS_GANONDROF
|
||||||
|
ACTOR_UNSET_53
|
||||||
|
ACTOR_EN_AM
|
||||||
|
ACTOR_EN_DEKUBABA
|
||||||
|
ACTOR_EN_M_FIRE1
|
||||||
|
ACTOR_EN_M_THUNDER
|
||||||
|
ACTOR_BG_DDAN_JD
|
||||||
|
ACTOR_BG_BREAKWALL
|
||||||
|
ACTOR_EN_JJ
|
||||||
|
ACTOR_EN_HORSE_ZELDA
|
||||||
|
ACTOR_BG_DDAN_KD
|
||||||
|
ACTOR_DOOR_WARP1
|
||||||
|
ACTOR_OBJ_SYOKUDAI
|
||||||
|
ACTOR_ITEM_B_HEART
|
||||||
|
ACTOR_EN_DEKUNUTS
|
||||||
|
ACTOR_BG_MENKURI_KAITEN
|
||||||
|
ACTOR_BG_MENKURI_EYE
|
||||||
|
ACTOR_EN_VALI
|
||||||
|
ACTOR_BG_MIZU_MOVEBG
|
||||||
|
ACTOR_BG_MIZU_WATER
|
||||||
|
ACTOR_ARMS_HOOK
|
||||||
|
ACTOR_EN_FHG
|
||||||
|
ACTOR_BG_MORI_HINERI
|
||||||
|
ACTOR_EN_BB
|
||||||
|
ACTOR_BG_TOKI_HIKARI
|
||||||
|
ACTOR_EN_YUKABYUN
|
||||||
|
ACTOR_BG_TOKI_SWD
|
||||||
|
ACTOR_EN_FHG_FIRE
|
||||||
|
ACTOR_BG_MJIN
|
||||||
|
ACTOR_BG_HIDAN_KOUSI
|
||||||
|
ACTOR_DOOR_TOKI
|
||||||
|
ACTOR_BG_HIDAN_HAMSTEP
|
||||||
|
ACTOR_EN_BIRD
|
||||||
|
ACTOR_UNSET_73
|
||||||
|
ACTOR_UNSET_74
|
||||||
|
ACTOR_UNSET_75
|
||||||
|
ACTOR_UNSET_76
|
||||||
|
ACTOR_EN_WOOD02
|
||||||
|
ACTOR_UNSET_78
|
||||||
|
ACTOR_UNSET_79
|
||||||
|
ACTOR_UNSET_7A
|
||||||
|
ACTOR_UNSET_7B
|
||||||
|
ACTOR_EN_LIGHTBOX
|
||||||
|
ACTOR_EN_PU_BOX
|
||||||
|
ACTOR_UNSET_7E
|
||||||
|
ACTOR_UNSET_7F
|
||||||
|
ACTOR_EN_TRAP
|
||||||
|
ACTOR_EN_AROW_TRAP
|
||||||
|
ACTOR_EN_VASE
|
||||||
|
ACTOR_UNSET_83
|
||||||
|
ACTOR_EN_TA
|
||||||
|
ACTOR_EN_TK
|
||||||
|
ACTOR_BG_MORI_BIGST
|
||||||
|
ACTOR_BG_MORI_ELEVATOR
|
||||||
|
ACTOR_BG_MORI_KAITENKABE
|
||||||
|
ACTOR_BG_MORI_RAKKATENJO
|
||||||
|
ACTOR_EN_VM
|
||||||
|
ACTOR_DEMO_EFFECT
|
||||||
|
ACTOR_DEMO_KANKYO
|
||||||
|
ACTOR_BG_HIDAN_FWBIG
|
||||||
|
ACTOR_EN_FLOORMAS
|
||||||
|
ACTOR_EN_HEISHI1
|
||||||
|
ACTOR_EN_RD
|
||||||
|
ACTOR_EN_PO_SISTERS
|
||||||
|
ACTOR_BG_HEAVY_BLOCK
|
||||||
|
ACTOR_BG_PO_EVENT
|
||||||
|
ACTOR_OBJ_MURE
|
||||||
|
ACTOR_EN_SW
|
||||||
|
ACTOR_BOSS_FD
|
||||||
|
ACTOR_OBJECT_KANKYO
|
||||||
|
ACTOR_EN_DU
|
||||||
|
ACTOR_EN_FD
|
||||||
|
ACTOR_EN_HORSE_LINK_CHILD
|
||||||
|
ACTOR_DOOR_ANA
|
||||||
|
ACTOR_BG_SPOT02_OBJECTS
|
||||||
|
ACTOR_BG_HAKA
|
||||||
|
ACTOR_MAGIC_WIND
|
||||||
|
ACTOR_MAGIC_FIRE
|
||||||
|
ACTOR_UNSET_A0
|
||||||
|
ACTOR_EN_RU1
|
||||||
|
ACTOR_BOSS_FD2
|
||||||
|
ACTOR_EN_FD_FIRE
|
||||||
|
ACTOR_EN_DH
|
||||||
|
ACTOR_EN_DHA
|
||||||
|
ACTOR_EN_RL
|
||||||
|
ACTOR_EN_ENCOUNT1
|
||||||
|
ACTOR_DEMO_DU
|
||||||
|
ACTOR_DEMO_IM
|
||||||
|
ACTOR_DEMO_TRE_LGT
|
||||||
|
ACTOR_EN_FW
|
||||||
|
ACTOR_BG_VB_SIMA
|
||||||
|
ACTOR_EN_VB_BALL
|
||||||
|
ACTOR_BG_HAKA_MEGANE
|
||||||
|
ACTOR_BG_HAKA_MEGANEBG
|
||||||
|
ACTOR_BG_HAKA_SHIP
|
||||||
|
ACTOR_BG_HAKA_SGAMI
|
||||||
|
ACTOR_UNSET_B2
|
||||||
|
ACTOR_EN_HEISHI2
|
||||||
|
ACTOR_EN_ENCOUNT2
|
||||||
|
ACTOR_EN_FIRE_ROCK
|
||||||
|
ACTOR_EN_BROB
|
||||||
|
ACTOR_MIR_RAY
|
||||||
|
ACTOR_BG_SPOT09_OBJ
|
||||||
|
ACTOR_BG_SPOT18_OBJ
|
||||||
|
ACTOR_BOSS_VA
|
||||||
|
ACTOR_BG_HAKA_TUBO
|
||||||
|
ACTOR_BG_HAKA_TRAP
|
||||||
|
ACTOR_BG_HAKA_HUTA
|
||||||
|
ACTOR_BG_HAKA_ZOU
|
||||||
|
ACTOR_BG_SPOT17_FUNEN
|
||||||
|
ACTOR_EN_SYATEKI_ITM
|
||||||
|
ACTOR_EN_SYATEKI_MAN
|
||||||
|
ACTOR_EN_TANA
|
||||||
|
ACTOR_EN_NB
|
||||||
|
ACTOR_BOSS_MO
|
||||||
|
ACTOR_EN_SB
|
||||||
|
ACTOR_EN_BIGOKUTA
|
||||||
|
ACTOR_EN_KAREBABA
|
||||||
|
ACTOR_BG_BDAN_OBJECTS
|
||||||
|
ACTOR_DEMO_SA
|
||||||
|
ACTOR_DEMO_GO
|
||||||
|
ACTOR_EN_IN
|
||||||
|
ACTOR_EN_TR
|
||||||
|
ACTOR_BG_SPOT16_BOMBSTONE
|
||||||
|
ACTOR_UNSET_CE
|
||||||
|
ACTOR_BG_HIDAN_KOWARERUKABE
|
||||||
|
ACTOR_BG_BOMBWALL
|
||||||
|
ACTOR_BG_SPOT08_ICEBLOCK
|
||||||
|
ACTOR_EN_RU2
|
||||||
|
ACTOR_OBJ_DEKUJR
|
||||||
|
ACTOR_BG_MIZU_UZU
|
||||||
|
ACTOR_BG_SPOT06_OBJECTS
|
||||||
|
ACTOR_BG_ICE_OBJECTS
|
||||||
|
ACTOR_BG_HAKA_WATER
|
||||||
|
ACTOR_UNSET_D8
|
||||||
|
ACTOR_EN_MA2
|
||||||
|
ACTOR_EN_BOM_CHU
|
||||||
|
ACTOR_EN_HORSE_GAME_CHECK
|
||||||
|
ACTOR_BOSS_TW
|
||||||
|
ACTOR_EN_RR
|
||||||
|
ACTOR_EN_BA
|
||||||
|
ACTOR_EN_BX
|
||||||
|
ACTOR_EN_ANUBICE
|
||||||
|
ACTOR_EN_ANUBICE_FIRE
|
||||||
|
ACTOR_BG_MORI_HASHIGO
|
||||||
|
ACTOR_BG_MORI_HASHIRA4
|
||||||
|
ACTOR_BG_MORI_IDOMIZU
|
||||||
|
ACTOR_BG_SPOT16_DOUGHNUT
|
||||||
|
ACTOR_BG_BDAN_SWITCH
|
||||||
|
ACTOR_EN_MA1
|
||||||
|
ACTOR_BOSS_GANON
|
||||||
|
ACTOR_BOSS_SST
|
||||||
|
ACTOR_UNSET_EA
|
||||||
|
ACTOR_UNSET_EB
|
||||||
|
ACTOR_EN_NY
|
||||||
|
ACTOR_EN_FR
|
||||||
|
ACTOR_ITEM_SHIELD
|
||||||
|
ACTOR_BG_ICE_SHELTER
|
||||||
|
ACTOR_EN_ICE_HONO
|
||||||
|
ACTOR_ITEM_OCARINA
|
||||||
|
ACTOR_UNSET_F2
|
||||||
|
ACTOR_UNSET_F3
|
||||||
|
ACTOR_MAGIC_DARK
|
||||||
|
ACTOR_DEMO_6K
|
||||||
|
ACTOR_EN_ANUBICE_TAG
|
||||||
|
ACTOR_BG_HAKA_GATE
|
||||||
|
ACTOR_BG_SPOT15_SAKU
|
||||||
|
ACTOR_BG_JYA_GOROIWA
|
||||||
|
ACTOR_BG_JYA_ZURERUKABE
|
||||||
|
ACTOR_UNSET_FB
|
||||||
|
ACTOR_BG_JYA_COBRA
|
||||||
|
ACTOR_BG_JYA_KANAAMI
|
||||||
|
ACTOR_FISHING
|
||||||
|
ACTOR_OBJ_OSHIHIKI
|
||||||
|
ACTOR_BG_GATE_SHUTTER
|
||||||
|
ACTOR_EFF_DUST
|
||||||
|
ACTOR_BG_SPOT01_FUSYA
|
||||||
|
ACTOR_BG_SPOT01_IDOHASHIRA
|
||||||
|
ACTOR_BG_SPOT01_IDOMIZU
|
||||||
|
ACTOR_BG_PO_SYOKUDAI
|
||||||
|
ACTOR_BG_GANON_OTYUKA
|
||||||
|
ACTOR_BG_SPOT15_RRBOX
|
||||||
|
ACTOR_BG_UMAJUMP
|
||||||
|
ACTOR_UNSET_109
|
||||||
|
ACTOR_ARROW_FIRE
|
||||||
|
ACTOR_ARROW_ICE
|
||||||
|
ACTOR_ARROW_LIGHT
|
||||||
|
ACTOR_UNSET_10D
|
||||||
|
ACTOR_UNSET_10E
|
||||||
|
ACTOR_ITEM_ETCETERA
|
||||||
|
ACTOR_OBJ_KIBAKO
|
||||||
|
ACTOR_OBJ_TSUBO
|
||||||
|
ACTOR_EN_WONDER_ITEM
|
||||||
|
ACTOR_EN_IK
|
||||||
|
ACTOR_DEMO_IK
|
||||||
|
ACTOR_EN_SKJ
|
||||||
|
ACTOR_EN_SKJNEEDLE
|
||||||
|
ACTOR_EN_G_SWITCH
|
||||||
|
ACTOR_DEMO_EXT
|
||||||
|
ACTOR_DEMO_SHD
|
||||||
|
ACTOR_EN_DNS
|
||||||
|
ACTOR_ELF_MSG
|
||||||
|
ACTOR_EN_HONOTRAP
|
||||||
|
ACTOR_EN_TUBO_TRAP
|
||||||
|
ACTOR_OBJ_ICE_POLY
|
||||||
|
ACTOR_BG_SPOT03_TAKI
|
||||||
|
ACTOR_BG_SPOT07_TAKI
|
||||||
|
ACTOR_EN_FZ
|
||||||
|
ACTOR_EN_PO_RELAY
|
||||||
|
ACTOR_BG_RELAY_OBJECTS
|
||||||
|
ACTOR_EN_DIVING_GAME
|
||||||
|
ACTOR_EN_KUSA
|
||||||
|
ACTOR_OBJ_BEAN
|
||||||
|
ACTOR_OBJ_BOMBIWA
|
||||||
|
ACTOR_UNSET_128
|
||||||
|
ACTOR_UNSET_129
|
||||||
|
ACTOR_OBJ_SWITCH
|
||||||
|
ACTOR_OBJ_ELEVATOR
|
||||||
|
ACTOR_OBJ_LIFT
|
||||||
|
ACTOR_OBJ_HSBLOCK
|
||||||
|
ACTOR_EN_OKARINA_TAG
|
||||||
|
ACTOR_EN_YABUSAME_MARK
|
||||||
|
ACTOR_EN_GOROIWA
|
||||||
|
ACTOR_EN_EX_RUPPY
|
||||||
|
ACTOR_EN_TORYO
|
||||||
|
ACTOR_EN_DAIKU
|
||||||
|
ACTOR_UNSET_134
|
||||||
|
ACTOR_EN_NWC
|
||||||
|
ACTOR_EN_BLKOBJ
|
||||||
|
ACTOR_ITEM_INBOX
|
||||||
|
ACTOR_EN_GE1
|
||||||
|
ACTOR_OBJ_BLOCKSTOP
|
||||||
|
ACTOR_EN_SDA
|
||||||
|
ACTOR_EN_CLEAR_TAG
|
||||||
|
ACTOR_EN_NIW_LADY
|
||||||
|
ACTOR_EN_GM
|
||||||
|
ACTOR_EN_MS
|
||||||
|
ACTOR_EN_HS
|
||||||
|
ACTOR_BG_INGATE
|
||||||
|
ACTOR_EN_KANBAN
|
||||||
|
ACTOR_EN_HEISHI3
|
||||||
|
ACTOR_EN_SYATEKI_NIW
|
||||||
|
ACTOR_EN_ATTACK_NIW
|
||||||
|
ACTOR_BG_SPOT01_IDOSOKO
|
||||||
|
ACTOR_EN_SA
|
||||||
|
ACTOR_EN_WONDER_TALK
|
||||||
|
ACTOR_BG_GJYO_BRIDGE
|
||||||
|
ACTOR_EN_DS
|
||||||
|
ACTOR_EN_MK
|
||||||
|
ACTOR_EN_BOM_BOWL_MAN
|
||||||
|
ACTOR_EN_BOM_BOWL_PIT
|
||||||
|
ACTOR_EN_OWL
|
||||||
|
ACTOR_EN_ISHI
|
||||||
|
ACTOR_OBJ_HANA
|
||||||
|
ACTOR_OBJ_LIGHTSWITCH
|
||||||
|
ACTOR_OBJ_MURE2
|
||||||
|
ACTOR_EN_GO
|
||||||
|
ACTOR_EN_FU
|
||||||
|
ACTOR_UNSET_154
|
||||||
|
ACTOR_EN_CHANGER
|
||||||
|
ACTOR_BG_JYA_MEGAMI
|
||||||
|
ACTOR_BG_JYA_LIFT
|
||||||
|
ACTOR_BG_JYA_BIGMIRROR
|
||||||
|
ACTOR_BG_JYA_BOMBCHUIWA
|
||||||
|
ACTOR_BG_JYA_AMISHUTTER
|
||||||
|
ACTOR_BG_JYA_BOMBIWA
|
||||||
|
ACTOR_BG_SPOT18_BASKET
|
||||||
|
ACTOR_UNSET_15D
|
||||||
|
ACTOR_EN_GANON_ORGAN
|
||||||
|
ACTOR_EN_SIOFUKI
|
||||||
|
ACTOR_EN_STREAM
|
||||||
|
ACTOR_UNSET_161
|
||||||
|
ACTOR_EN_MM
|
||||||
|
ACTOR_EN_KO
|
||||||
|
ACTOR_EN_KZ
|
||||||
|
ACTOR_EN_WEATHER_TAG
|
||||||
|
ACTOR_BG_SST_FLOOR
|
||||||
|
ACTOR_EN_ANI
|
||||||
|
ACTOR_EN_EX_ITEM
|
||||||
|
ACTOR_BG_JYA_IRONOBJ
|
||||||
|
ACTOR_EN_JS
|
||||||
|
ACTOR_EN_JSJUTAN
|
||||||
|
ACTOR_EN_CS
|
||||||
|
ACTOR_EN_MD
|
||||||
|
ACTOR_EN_HY
|
||||||
|
ACTOR_EN_GANON_MANT
|
||||||
|
ACTOR_EN_OKARINA_EFFECT
|
||||||
|
ACTOR_EN_MAG
|
||||||
|
ACTOR_DOOR_GERUDO
|
||||||
|
ACTOR_ELF_MSG2
|
||||||
|
ACTOR_DEMO_GT
|
||||||
|
ACTOR_EN_PO_FIELD
|
||||||
|
ACTOR_EFC_ERUPC
|
||||||
|
ACTOR_BG_ZG
|
||||||
|
ACTOR_EN_HEISHI4
|
||||||
|
ACTOR_EN_ZL3
|
||||||
|
ACTOR_BOSS_GANON2
|
||||||
|
ACTOR_EN_KAKASI
|
||||||
|
ACTOR_EN_TAKARA_MAN
|
||||||
|
ACTOR_OBJ_MAKEOSHIHIKI
|
||||||
|
ACTOR_OCEFF_SPOT
|
||||||
|
ACTOR_END_TITLE
|
||||||
|
ACTOR_UNSET_180
|
||||||
|
ACTOR_EN_TORCH
|
||||||
|
ACTOR_DEMO_EC
|
||||||
|
ACTOR_SHOT_SUN
|
||||||
|
ACTOR_EN_DY_EXTRA
|
||||||
|
ACTOR_EN_WONDER_TALK2
|
||||||
|
ACTOR_EN_GE2
|
||||||
|
ACTOR_OBJ_ROOMTIMER
|
||||||
|
ACTOR_EN_SSH
|
||||||
|
ACTOR_EN_STH
|
||||||
|
ACTOR_OCEFF_WIPE
|
||||||
|
ACTOR_OCEFF_STORM
|
||||||
|
ACTOR_EN_WEIYER
|
||||||
|
ACTOR_BG_SPOT05_SOKO
|
||||||
|
ACTOR_BG_JYA_1FLIFT
|
||||||
|
ACTOR_BG_JYA_HAHENIRON
|
||||||
|
ACTOR_BG_SPOT12_GATE
|
||||||
|
ACTOR_BG_SPOT12_SAKU
|
||||||
|
ACTOR_EN_HINTNUTS
|
||||||
|
ACTOR_EN_NUTSBALL
|
||||||
|
ACTOR_BG_SPOT00_BREAK
|
||||||
|
ACTOR_EN_SHOPNUTS
|
||||||
|
ACTOR_EN_IT
|
||||||
|
ACTOR_EN_GELDB
|
||||||
|
ACTOR_OCEFF_WIPE2
|
||||||
|
ACTOR_OCEFF_WIPE3
|
||||||
|
ACTOR_EN_NIW_GIRL
|
||||||
|
ACTOR_EN_DOG
|
||||||
|
ACTOR_EN_SI
|
||||||
|
ACTOR_BG_SPOT01_OBJECTS2
|
||||||
|
ACTOR_OBJ_COMB
|
||||||
|
ACTOR_BG_SPOT11_BAKUDANKABE
|
||||||
|
ACTOR_OBJ_KIBAKO2
|
||||||
|
ACTOR_EN_DNT_DEMO
|
||||||
|
ACTOR_EN_DNT_JIJI
|
||||||
|
ACTOR_EN_DNT_NOMAL
|
||||||
|
ACTOR_EN_GUEST
|
||||||
|
ACTOR_BG_BOM_GUARD
|
||||||
|
ACTOR_EN_HS2
|
||||||
|
ACTOR_DEMO_KEKKAI
|
||||||
|
ACTOR_BG_SPOT08_BAKUDANKABE
|
||||||
|
ACTOR_BG_SPOT17_BAKUDANKABE
|
||||||
|
ACTOR_UNSET_1AA
|
||||||
|
ACTOR_OBJ_MURE3
|
||||||
|
ACTOR_EN_TG
|
||||||
|
ACTOR_EN_MU
|
||||||
|
ACTOR_EN_GO2
|
||||||
|
ACTOR_EN_WF
|
||||||
|
ACTOR_EN_SKB
|
||||||
|
ACTOR_DEMO_GJ
|
||||||
|
ACTOR_DEMO_GEFF
|
||||||
|
ACTOR_BG_GND_FIREMEIRO
|
||||||
|
ACTOR_BG_GND_DARKMEIRO
|
||||||
|
ACTOR_BG_GND_SOULMEIRO
|
||||||
|
ACTOR_BG_GND_NISEKABE
|
||||||
|
ACTOR_BG_GND_ICEBLOCK
|
||||||
|
ACTOR_EN_GB
|
||||||
|
ACTOR_EN_GS
|
||||||
|
ACTOR_BG_MIZU_BWALL
|
||||||
|
ACTOR_BG_MIZU_SHUTTER
|
||||||
|
ACTOR_EN_DAIKU_KAKARIKO
|
||||||
|
ACTOR_BG_BOWL_WALL
|
||||||
|
ACTOR_EN_WALL_TUBO
|
||||||
|
ACTOR_EN_PO_DESERT
|
||||||
|
ACTOR_EN_CROW
|
||||||
|
ACTOR_DOOR_KILLER
|
||||||
|
ACTOR_BG_SPOT11_OASIS
|
||||||
|
ACTOR_BG_SPOT18_FUTA
|
||||||
|
ACTOR_BG_SPOT18_SHUTTER
|
||||||
|
ACTOR_EN_MA3
|
||||||
|
ACTOR_EN_COW
|
||||||
|
ACTOR_BG_ICE_TURARA
|
||||||
|
ACTOR_BG_ICE_SHUTTER
|
||||||
|
ACTOR_EN_KAKASI2
|
||||||
|
ACTOR_EN_KAKASI3
|
||||||
|
ACTOR_OCEFF_WIPE4
|
||||||
|
ACTOR_EN_EG
|
||||||
|
ACTOR_BG_MENKURI_NISEKABE
|
||||||
|
ACTOR_EN_ZO
|
||||||
|
ACTOR_OBJ_MAKEKINSUTA
|
||||||
|
ACTOR_EN_GE3
|
||||||
|
ACTOR_OBJ_TIMEBLOCK
|
||||||
|
ACTOR_OBJ_HAMISHI
|
||||||
|
ACTOR_EN_ZL4
|
||||||
|
ACTOR_EN_MM2
|
||||||
|
ACTOR_BG_JYA_BLOCK
|
||||||
|
ACTOR_OBJ_WARP2BLOCK
|
||||||
|
ACTOR_ID_MAX
|
402
soh/assets/extractor/symbols/ObjectList_OoTMqDbg.txt
Normal file
402
soh/assets/extractor/symbols/ObjectList_OoTMqDbg.txt
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
OBJECT_INVALID
|
||||||
|
OBJECT_GAMEPLAY_KEEP
|
||||||
|
OBJECT_GAMEPLAY_FIELD_KEEP
|
||||||
|
OBJECT_GAMEPLAY_DANGEON_KEEP
|
||||||
|
OBJECT_UNSET_4
|
||||||
|
OBJECT_UNSET_5
|
||||||
|
OBJECT_HUMAN
|
||||||
|
OBJECT_OKUTA
|
||||||
|
OBJECT_CROW
|
||||||
|
OBJECT_POH
|
||||||
|
OBJECT_DY_OBJ
|
||||||
|
OBJECT_WALLMASTER
|
||||||
|
OBJECT_DODONGO
|
||||||
|
OBJECT_FIREFLY
|
||||||
|
OBJECT_BOX
|
||||||
|
OBJECT_FIRE
|
||||||
|
OBJECT_UNSET_10
|
||||||
|
OBJECT_UNSET_11
|
||||||
|
OBJECT_BUBBLE
|
||||||
|
OBJECT_NIW
|
||||||
|
OBJECT_LINK_BOY
|
||||||
|
OBJECT_LINK_CHILD
|
||||||
|
OBJECT_TITE
|
||||||
|
OBJECT_REEBA
|
||||||
|
OBJECT_PEEHAT
|
||||||
|
OBJECT_KINGDODONGO
|
||||||
|
OBJECT_HORSE
|
||||||
|
OBJECT_ZF
|
||||||
|
OBJECT_GOMA
|
||||||
|
OBJECT_ZL1
|
||||||
|
OBJECT_GOL
|
||||||
|
OBJECT_DODOJR
|
||||||
|
OBJECT_TORCH2
|
||||||
|
OBJECT_BL
|
||||||
|
OBJECT_TP
|
||||||
|
OBJECT_OA1
|
||||||
|
OBJECT_ST
|
||||||
|
OBJECT_BW
|
||||||
|
OBJECT_EI
|
||||||
|
OBJECT_HORSE_NORMAL
|
||||||
|
OBJECT_OB1
|
||||||
|
OBJECT_O_ANIME
|
||||||
|
OBJECT_SPOT04_OBJECTS
|
||||||
|
OBJECT_DDAN_OBJECTS
|
||||||
|
OBJECT_HIDAN_OBJECTS
|
||||||
|
OBJECT_HORSE_GANON
|
||||||
|
OBJECT_OA2
|
||||||
|
OBJECT_SPOT00_OBJECTS
|
||||||
|
OBJECT_MB
|
||||||
|
OBJECT_BOMBF
|
||||||
|
OBJECT_SK2
|
||||||
|
OBJECT_OE1
|
||||||
|
OBJECT_OE_ANIME
|
||||||
|
OBJECT_OE2
|
||||||
|
OBJECT_YDAN_OBJECTS
|
||||||
|
OBJECT_GND
|
||||||
|
OBJECT_AM
|
||||||
|
OBJECT_DEKUBABA
|
||||||
|
OBJECT_UNSET_3A
|
||||||
|
OBJECT_OA3
|
||||||
|
OBJECT_OA4
|
||||||
|
OBJECT_OA5
|
||||||
|
OBJECT_OA6
|
||||||
|
OBJECT_OA7
|
||||||
|
OBJECT_JJ
|
||||||
|
OBJECT_OA8
|
||||||
|
OBJECT_OA9
|
||||||
|
OBJECT_OB2
|
||||||
|
OBJECT_OB3
|
||||||
|
OBJECT_OB4
|
||||||
|
OBJECT_HORSE_ZELDA
|
||||||
|
OBJECT_OPENING_DEMO1
|
||||||
|
OBJECT_WARP1
|
||||||
|
OBJECT_B_HEART
|
||||||
|
OBJECT_DEKUNUTS
|
||||||
|
OBJECT_OE3
|
||||||
|
OBJECT_OE4
|
||||||
|
OBJECT_MENKURI_OBJECTS
|
||||||
|
OBJECT_OE5
|
||||||
|
OBJECT_OE6
|
||||||
|
OBJECT_OE7
|
||||||
|
OBJECT_OE8
|
||||||
|
OBJECT_OE9
|
||||||
|
OBJECT_OE10
|
||||||
|
OBJECT_OE11
|
||||||
|
OBJECT_OE12
|
||||||
|
OBJECT_VALI
|
||||||
|
OBJECT_OA10
|
||||||
|
OBJECT_OA11
|
||||||
|
OBJECT_MIZU_OBJECTS
|
||||||
|
OBJECT_FHG
|
||||||
|
OBJECT_OSSAN
|
||||||
|
OBJECT_MORI_HINERI1
|
||||||
|
OBJECT_BB
|
||||||
|
OBJECT_TOKI_OBJECTS
|
||||||
|
OBJECT_YUKABYUN
|
||||||
|
OBJECT_ZL2
|
||||||
|
OBJECT_MJIN
|
||||||
|
OBJECT_MJIN_FLASH
|
||||||
|
OBJECT_MJIN_DARK
|
||||||
|
OBJECT_MJIN_FLAME
|
||||||
|
OBJECT_MJIN_ICE
|
||||||
|
OBJECT_MJIN_SOUL
|
||||||
|
OBJECT_MJIN_WIND
|
||||||
|
OBJECT_MJIN_OKA
|
||||||
|
OBJECT_HAKA_OBJECTS
|
||||||
|
OBJECT_SPOT06_OBJECTS
|
||||||
|
OBJECT_ICE_OBJECTS
|
||||||
|
OBJECT_RELAY_OBJECTS
|
||||||
|
OBJECT_PO_FIELD
|
||||||
|
OBJECT_PO_COMPOSER
|
||||||
|
OBJECT_MORI_HINERI1A
|
||||||
|
OBJECT_MORI_HINERI2
|
||||||
|
OBJECT_MORI_HINERI2A
|
||||||
|
OBJECT_MORI_OBJECTS
|
||||||
|
OBJECT_MORI_TEX
|
||||||
|
OBJECT_SPOT08_OBJ
|
||||||
|
OBJECT_WARP2
|
||||||
|
OBJECT_HATA
|
||||||
|
OBJECT_BIRD
|
||||||
|
OBJECT_UNSET_78
|
||||||
|
OBJECT_UNSET_79
|
||||||
|
OBJECT_UNSET_7A
|
||||||
|
OBJECT_UNSET_7B
|
||||||
|
OBJECT_WOOD02
|
||||||
|
OBJECT_UNSET_7D
|
||||||
|
OBJECT_UNSET_7E
|
||||||
|
OBJECT_UNSET_7F
|
||||||
|
OBJECT_UNSET_80
|
||||||
|
OBJECT_LIGHTBOX
|
||||||
|
OBJECT_PU_BOX
|
||||||
|
OBJECT_UNSET_83
|
||||||
|
OBJECT_UNSET_84
|
||||||
|
OBJECT_TRAP
|
||||||
|
OBJECT_VASE
|
||||||
|
OBJECT_IM
|
||||||
|
OBJECT_TA
|
||||||
|
OBJECT_TK
|
||||||
|
OBJECT_XC
|
||||||
|
OBJECT_VM
|
||||||
|
OBJECT_BV
|
||||||
|
OBJECT_HAKACH_OBJECTS
|
||||||
|
OBJECT_EFC_CRYSTAL_LIGHT
|
||||||
|
OBJECT_EFC_FIRE_BALL
|
||||||
|
OBJECT_EFC_FLASH
|
||||||
|
OBJECT_EFC_LGT_SHOWER
|
||||||
|
OBJECT_EFC_STAR_FIELD
|
||||||
|
OBJECT_GOD_LGT
|
||||||
|
OBJECT_LIGHT_RING
|
||||||
|
OBJECT_TRIFORCE_SPOT
|
||||||
|
OBJECT_BDAN_OBJECTS
|
||||||
|
OBJECT_SD
|
||||||
|
OBJECT_RD
|
||||||
|
OBJECT_PO_SISTERS
|
||||||
|
OBJECT_HEAVY_OBJECT
|
||||||
|
OBJECT_GNDD
|
||||||
|
OBJECT_FD
|
||||||
|
OBJECT_DU
|
||||||
|
OBJECT_FW
|
||||||
|
OBJECT_MEDAL
|
||||||
|
OBJECT_HORSE_LINK_CHILD
|
||||||
|
OBJECT_SPOT02_OBJECTS
|
||||||
|
OBJECT_HAKA
|
||||||
|
OBJECT_RU1
|
||||||
|
OBJECT_SYOKUDAI
|
||||||
|
OBJECT_FD2
|
||||||
|
OBJECT_DH
|
||||||
|
OBJECT_RL
|
||||||
|
OBJECT_EFC_TW
|
||||||
|
OBJECT_DEMO_TRE_LGT
|
||||||
|
OBJECT_GI_KEY
|
||||||
|
OBJECT_MIR_RAY
|
||||||
|
OBJECT_BROB
|
||||||
|
OBJECT_GI_JEWEL
|
||||||
|
OBJECT_SPOT09_OBJ
|
||||||
|
OBJECT_SPOT18_OBJ
|
||||||
|
OBJECT_BDOOR
|
||||||
|
OBJECT_SPOT17_OBJ
|
||||||
|
OBJECT_SHOP_DUNGEN
|
||||||
|
OBJECT_NB
|
||||||
|
OBJECT_MO
|
||||||
|
OBJECT_SB
|
||||||
|
OBJECT_GI_MELODY
|
||||||
|
OBJECT_GI_HEART
|
||||||
|
OBJECT_GI_COMPASS
|
||||||
|
OBJECT_GI_BOSSKEY
|
||||||
|
OBJECT_GI_MEDAL
|
||||||
|
OBJECT_GI_NUTS
|
||||||
|
OBJECT_SA
|
||||||
|
OBJECT_GI_HEARTS
|
||||||
|
OBJECT_GI_ARROWCASE
|
||||||
|
OBJECT_GI_BOMBPOUCH
|
||||||
|
OBJECT_IN
|
||||||
|
OBJECT_TR
|
||||||
|
OBJECT_SPOT16_OBJ
|
||||||
|
OBJECT_OE1S
|
||||||
|
OBJECT_OE4S
|
||||||
|
OBJECT_OS_ANIME
|
||||||
|
OBJECT_GI_BOTTLE
|
||||||
|
OBJECT_GI_STICK
|
||||||
|
OBJECT_GI_MAP
|
||||||
|
OBJECT_OF1D_MAP
|
||||||
|
OBJECT_RU2
|
||||||
|
OBJECT_GI_SHIELD_1
|
||||||
|
OBJECT_DEKUJR
|
||||||
|
OBJECT_GI_MAGICPOT
|
||||||
|
OBJECT_GI_BOMB_1
|
||||||
|
OBJECT_OF1S
|
||||||
|
OBJECT_MA2
|
||||||
|
OBJECT_GI_PURSE
|
||||||
|
OBJECT_HNI
|
||||||
|
OBJECT_TW
|
||||||
|
OBJECT_RR
|
||||||
|
OBJECT_BXA
|
||||||
|
OBJECT_ANUBICE
|
||||||
|
OBJECT_GI_GERUDO
|
||||||
|
OBJECT_GI_ARROW
|
||||||
|
OBJECT_GI_BOMB_2
|
||||||
|
OBJECT_GI_EGG
|
||||||
|
OBJECT_GI_SCALE
|
||||||
|
OBJECT_GI_SHIELD_2
|
||||||
|
OBJECT_GI_HOOKSHOT
|
||||||
|
OBJECT_GI_OCARINA
|
||||||
|
OBJECT_GI_MILK
|
||||||
|
OBJECT_MA1
|
||||||
|
OBJECT_GANON
|
||||||
|
OBJECT_SST
|
||||||
|
OBJECT_NY_UNUSED
|
||||||
|
OBJECT_UNSET_E4
|
||||||
|
OBJECT_NY
|
||||||
|
OBJECT_FR
|
||||||
|
OBJECT_GI_PACHINKO
|
||||||
|
OBJECT_GI_BOOMERANG
|
||||||
|
OBJECT_GI_BOW
|
||||||
|
OBJECT_GI_GLASSES
|
||||||
|
OBJECT_GI_LIQUID
|
||||||
|
OBJECT_ANI
|
||||||
|
OBJECT_DEMO_6K
|
||||||
|
OBJECT_GI_SHIELD_3
|
||||||
|
OBJECT_GI_LETTER
|
||||||
|
OBJECT_SPOT15_OBJ
|
||||||
|
OBJECT_JYA_OBJ
|
||||||
|
OBJECT_GI_CLOTHES
|
||||||
|
OBJECT_GI_BEAN
|
||||||
|
OBJECT_GI_FISH
|
||||||
|
OBJECT_GI_SAW
|
||||||
|
OBJECT_GI_HAMMER
|
||||||
|
OBJECT_GI_GRASS
|
||||||
|
OBJECT_GI_LONGSWORD
|
||||||
|
OBJECT_SPOT01_OBJECTS
|
||||||
|
OBJECT_MD_UNUSED
|
||||||
|
OBJECT_MD
|
||||||
|
OBJECT_KM1
|
||||||
|
OBJECT_KW1
|
||||||
|
OBJECT_ZO
|
||||||
|
OBJECT_KZ
|
||||||
|
OBJECT_UMAJUMP
|
||||||
|
OBJECT_MASTERKOKIRI
|
||||||
|
OBJECT_MASTERKOKIRIHEAD
|
||||||
|
OBJECT_MASTERGOLON
|
||||||
|
OBJECT_MASTERZOORA
|
||||||
|
OBJECT_AOB
|
||||||
|
OBJECT_IK
|
||||||
|
OBJECT_AHG
|
||||||
|
OBJECT_CNE
|
||||||
|
OBJECT_GI_NIWATORI
|
||||||
|
OBJECT_SKJ
|
||||||
|
OBJECT_GI_BOTTLE_LETTER
|
||||||
|
OBJECT_BJI
|
||||||
|
OBJECT_BBA
|
||||||
|
OBJECT_GI_OCARINA_0
|
||||||
|
OBJECT_DS
|
||||||
|
OBJECT_ANE
|
||||||
|
OBJECT_BOJ
|
||||||
|
OBJECT_SPOT03_OBJECT
|
||||||
|
OBJECT_SPOT07_OBJECT
|
||||||
|
OBJECT_FZ
|
||||||
|
OBJECT_BOB
|
||||||
|
OBJECT_GE1
|
||||||
|
OBJECT_YABUSAME_POINT
|
||||||
|
OBJECT_GI_BOOTS_2
|
||||||
|
OBJECT_GI_SEED
|
||||||
|
OBJECT_GND_MAGIC
|
||||||
|
OBJECT_D_ELEVATOR
|
||||||
|
OBJECT_D_HSBLOCK
|
||||||
|
OBJECT_D_LIFT
|
||||||
|
OBJECT_MAMENOKI
|
||||||
|
OBJECT_GOROIWA
|
||||||
|
OBJECT_UNSET_120
|
||||||
|
OBJECT_TORYO
|
||||||
|
OBJECT_DAIKU
|
||||||
|
OBJECT_UNSET_123
|
||||||
|
OBJECT_NWC
|
||||||
|
OBJECT_BLKOBJ
|
||||||
|
OBJECT_GM
|
||||||
|
OBJECT_MS
|
||||||
|
OBJECT_HS
|
||||||
|
OBJECT_INGATE
|
||||||
|
OBJECT_LIGHTSWITCH
|
||||||
|
OBJECT_KUSA
|
||||||
|
OBJECT_TSUBO
|
||||||
|
OBJECT_GI_GLOVES
|
||||||
|
OBJECT_GI_COIN
|
||||||
|
OBJECT_KANBAN
|
||||||
|
OBJECT_GJYO_OBJECTS
|
||||||
|
OBJECT_OWL
|
||||||
|
OBJECT_MK
|
||||||
|
OBJECT_FU
|
||||||
|
OBJECT_GI_KI_TAN_MASK
|
||||||
|
OBJECT_GI_REDEAD_MASK
|
||||||
|
OBJECT_GI_SKJ_MASK
|
||||||
|
OBJECT_GI_RABIT_MASK
|
||||||
|
OBJECT_GI_TRUTH_MASK
|
||||||
|
OBJECT_GANON_OBJECTS
|
||||||
|
OBJECT_SIOFUKI
|
||||||
|
OBJECT_STREAM
|
||||||
|
OBJECT_MM
|
||||||
|
OBJECT_FA
|
||||||
|
OBJECT_OS
|
||||||
|
OBJECT_GI_EYE_LOTION
|
||||||
|
OBJECT_GI_POWDER
|
||||||
|
OBJECT_GI_MUSHROOM
|
||||||
|
OBJECT_GI_TICKETSTONE
|
||||||
|
OBJECT_GI_BROKENSWORD
|
||||||
|
OBJECT_JS
|
||||||
|
OBJECT_CS
|
||||||
|
OBJECT_GI_PRESCRIPTION
|
||||||
|
OBJECT_GI_BRACELET
|
||||||
|
OBJECT_GI_SOLDOUT
|
||||||
|
OBJECT_GI_FROG
|
||||||
|
OBJECT_MAG
|
||||||
|
OBJECT_DOOR_GERUDO
|
||||||
|
OBJECT_GT
|
||||||
|
OBJECT_EFC_ERUPC
|
||||||
|
OBJECT_ZL2_ANIME1
|
||||||
|
OBJECT_ZL2_ANIME2
|
||||||
|
OBJECT_GI_GOLONMASK
|
||||||
|
OBJECT_GI_ZORAMASK
|
||||||
|
OBJECT_GI_GERUDOMASK
|
||||||
|
OBJECT_GANON2
|
||||||
|
OBJECT_KA
|
||||||
|
OBJECT_TS
|
||||||
|
OBJECT_ZG
|
||||||
|
OBJECT_GI_HOVERBOOTS
|
||||||
|
OBJECT_GI_M_ARROW
|
||||||
|
OBJECT_DS2
|
||||||
|
OBJECT_EC
|
||||||
|
OBJECT_FISH
|
||||||
|
OBJECT_GI_SUTARU
|
||||||
|
OBJECT_GI_GODDESS
|
||||||
|
OBJECT_SSH
|
||||||
|
OBJECT_BIGOKUTA
|
||||||
|
OBJECT_BG
|
||||||
|
OBJECT_SPOT05_OBJECTS
|
||||||
|
OBJECT_SPOT12_OBJ
|
||||||
|
OBJECT_BOMBIWA
|
||||||
|
OBJECT_HINTNUTS
|
||||||
|
OBJECT_RS
|
||||||
|
OBJECT_SPOT00_BREAK
|
||||||
|
OBJECT_GLA
|
||||||
|
OBJECT_SHOPNUTS
|
||||||
|
OBJECT_GELDB
|
||||||
|
OBJECT_GR
|
||||||
|
OBJECT_DOG
|
||||||
|
OBJECT_JYA_IRON
|
||||||
|
OBJECT_JYA_DOOR
|
||||||
|
OBJECT_UNSET_16E
|
||||||
|
OBJECT_SPOT11_OBJ
|
||||||
|
OBJECT_KIBAKO2
|
||||||
|
OBJECT_DNS
|
||||||
|
OBJECT_DNK
|
||||||
|
OBJECT_GI_FIRE
|
||||||
|
OBJECT_GI_INSECT
|
||||||
|
OBJECT_GI_BUTTERFLY
|
||||||
|
OBJECT_GI_GHOST
|
||||||
|
OBJECT_GI_SOUL
|
||||||
|
OBJECT_BOWL
|
||||||
|
OBJECT_DEMO_KEKKAI
|
||||||
|
OBJECT_EFC_DOUGHNUT
|
||||||
|
OBJECT_GI_DEKUPOUCH
|
||||||
|
OBJECT_GANON_ANIME1
|
||||||
|
OBJECT_GANON_ANIME2
|
||||||
|
OBJECT_GANON_ANIME3
|
||||||
|
OBJECT_GI_RUPY
|
||||||
|
OBJECT_SPOT01_MATOYA
|
||||||
|
OBJECT_SPOT01_MATOYAB
|
||||||
|
OBJECT_MU
|
||||||
|
OBJECT_WF
|
||||||
|
OBJECT_SKB
|
||||||
|
OBJECT_GJ
|
||||||
|
OBJECT_GEFF
|
||||||
|
OBJECT_HAKA_DOOR
|
||||||
|
OBJECT_GS
|
||||||
|
OBJECT_PS
|
||||||
|
OBJECT_BWALL
|
||||||
|
OBJECT_COW
|
||||||
|
OBJECT_COB
|
||||||
|
OBJECT_GI_SWORD_1
|
||||||
|
OBJECT_DOOR_KILLER
|
||||||
|
OBJECT_OUKE_HAKA
|
||||||
|
OBJECT_TIMEBLOCK
|
||||||
|
OBJECT_ZL4
|
1
soh/assets/extractor/symbols/SymbolMap_OoTMqDbg.txt
Normal file
1
soh/assets/extractor/symbols/SymbolMap_OoTMqDbg.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
8012DB20 gMtxClear
|
|
@ -15,7 +15,7 @@ extern "C"
|
||||||
#include <soh/Enhancements/randomizer/randomizer_inf.h>
|
#include <soh/Enhancements/randomizer/randomizer_inf.h>
|
||||||
|
|
||||||
#if defined(INCLUDE_GAME_PRINTF) && defined(_DEBUG)
|
#if defined(INCLUDE_GAME_PRINTF) && defined(_DEBUG)
|
||||||
#define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, __VA_ARGS__)
|
#define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, ##__VA_ARGS__)
|
#define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, ##__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#ifndef Z64_AUDIO_H
|
#ifndef Z64_AUDIO_H
|
||||||
#define Z64_AUDIO_H
|
#define Z64_AUDIO_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <endianness.h>
|
#include <endianness.h>
|
||||||
|
|
||||||
#define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0))
|
#define MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0))
|
||||||
|
@ -24,8 +28,8 @@
|
||||||
|
|
||||||
//#define MAX_SEQUENCES 0x800
|
//#define MAX_SEQUENCES 0x800
|
||||||
extern size_t sequenceMapSize;
|
extern size_t sequenceMapSize;
|
||||||
|
extern size_t fontMapSize;
|
||||||
extern char* fontMap[256];
|
extern char** fontMap;
|
||||||
|
|
||||||
#define MAX_AUTHENTIC_SEQID 110
|
#define MAX_AUTHENTIC_SEQID 110
|
||||||
|
|
||||||
|
@ -54,7 +58,8 @@ typedef enum {
|
||||||
/* 2 */ CODEC_S16_INMEMORY,
|
/* 2 */ CODEC_S16_INMEMORY,
|
||||||
/* 3 */ CODEC_SMALL_ADPCM,
|
/* 3 */ CODEC_SMALL_ADPCM,
|
||||||
/* 4 */ CODEC_REVERB,
|
/* 4 */ CODEC_REVERB,
|
||||||
/* 5 */ CODEC_S16
|
/* 5 */ CODEC_S16,
|
||||||
|
/* 6 */ CODEC_OPUS,
|
||||||
} SampleCodec;
|
} SampleCodec;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -117,13 +122,14 @@ typedef struct {
|
||||||
/* 0x2 */ s16 arg;
|
/* 0x2 */ s16 arg;
|
||||||
} AdsrEnvelope; // size = 0x4
|
} AdsrEnvelope; // size = 0x4
|
||||||
|
|
||||||
typedef struct {
|
typedef struct AdpcmLoop {
|
||||||
/* 0x00 */ uintptr_t start;
|
/* 0x00 */ u32 start;
|
||||||
/* 0x04 */ uintptr_t end;
|
/* 0x04 */ u32 loopEnd; // numSamples position into the sample where the loop ends
|
||||||
/* 0x08 */ u32 count;
|
/* 0x08 */ u32 count; // The number of times the loop is played before the sound completes. Setting count to -1
|
||||||
/* 0x0C */ char unk_0C[0x4];
|
// indicates that the loop should play indefinitely.
|
||||||
/* 0x10 */ s16 state[16]; // only exists if count != 0. 8-byte aligned
|
/* 0x0C */ u32 sampleEnd; // total number of s16-samples in the sample audio clip
|
||||||
} AdpcmLoop; // size = 0x30 (or 0x10)
|
/* 0x10 */ s16 predictorState[16]; // only exists if count != 0. 8-byte aligned
|
||||||
|
} AdpcmLoop; // size = 0x30 (or 0x10)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x00 */ s32 order;
|
/* 0x00 */ s32 order;
|
||||||
|
@ -131,24 +137,23 @@ typedef struct {
|
||||||
/* 0x08 */ s16* book; // size 8 * order * npredictors. 8-byte aligned
|
/* 0x08 */ s16* book; // size 8 * order * npredictors. 8-byte aligned
|
||||||
} AdpcmBook; // size >= 0x8
|
} AdpcmBook; // size >= 0x8
|
||||||
|
|
||||||
typedef struct
|
typedef struct SoundFontSample {
|
||||||
{
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
/* 0x00 */ u32 codec : 4;
|
///* 0x0 */ u32 unk_0 : 1;
|
||||||
/* 0x00 */ u32 medium : 2;
|
/* 0x0 */ u32 codec : 4; // The state of compression or decompression, See `SampleCodec`
|
||||||
/* 0x00 */ u32 unk_bit26 : 1;
|
/* 0x0 */ u32 medium : 2; // Medium where sample is currently stored. See `SampleMedium`
|
||||||
/* 0x00 */ u32 unk_bit25 : 1; // this has been named isRelocated in zret
|
/* 0x0 */ u32 unk_bit26 : 1;
|
||||||
/* 0x01 */ u32 size : 24;
|
/* 0x0 */ u32 isRelocated : 1; // Has the sample header been relocated (offsets to pointers)
|
||||||
|
|
||||||
};
|
};
|
||||||
u32 asU32;
|
u32 asU32;
|
||||||
};
|
};
|
||||||
|
/* 0x1 */ u32 size; // Size of the sample
|
||||||
/* 0x04 */ u8* sampleAddr;
|
u32 fileSize;
|
||||||
/* 0x08 */ AdpcmLoop* loop;
|
/* 0x4 */ u8* sampleAddr; // Raw sample data. Offset from the start of the sample bank or absolute address to either rom or ram
|
||||||
/* 0x0C */ AdpcmBook* book;
|
/* 0x8 */ AdpcmLoop* loop; // Adpcm loop parameters used by the sample. Offset from the start of the sound font / pointer to ram
|
||||||
u32 sampleRateMagicValue; // For wav samples only...
|
/* 0xC */ AdpcmBook* book; // Adpcm book parameters used by the sample. Offset from the start of the sound font / pointer to ram
|
||||||
s32 sampleRate; // For wav samples only...
|
|
||||||
} SoundFontSample; // size = 0x10
|
} SoundFontSample; // size = 0x10
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -465,6 +470,8 @@ typedef struct {
|
||||||
/* 0x00F0 */ s16 dummyResampleState[0x10];
|
/* 0x00F0 */ s16 dummyResampleState[0x10];
|
||||||
} NoteSynthesisBuffers; // size = 0x110
|
} NoteSynthesisBuffers; // size = 0x110
|
||||||
|
|
||||||
|
struct OggOpusFile;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x00 */ u8 restart;
|
/* 0x00 */ u8 restart;
|
||||||
/* 0x01 */ u8 sampleDmaIndex;
|
/* 0x01 */ u8 sampleDmaIndex;
|
||||||
|
@ -483,6 +490,7 @@ typedef struct {
|
||||||
/* 0x1A */ u8 unk_1A;
|
/* 0x1A */ u8 unk_1A;
|
||||||
/* 0x1C */ u16 unk_1C;
|
/* 0x1C */ u16 unk_1C;
|
||||||
/* 0x1E */ u16 unk_1E;
|
/* 0x1E */ u16 unk_1E;
|
||||||
|
struct OggOpusFile* opusFile; // Only for streamed opus audio
|
||||||
} NoteSynthesisState; // size = 0x20
|
} NoteSynthesisState; // size = 0x20
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -917,7 +925,7 @@ typedef struct {
|
||||||
/* 0x3420 */ AudioPoolSplit3 persistentCommonPoolSplit;
|
/* 0x3420 */ AudioPoolSplit3 persistentCommonPoolSplit;
|
||||||
/* 0x342C */ AudioPoolSplit3 temporaryCommonPoolSplit;
|
/* 0x342C */ AudioPoolSplit3 temporaryCommonPoolSplit;
|
||||||
/* 0x3438 */ u8 sampleFontLoadStatus[0x30];
|
/* 0x3438 */ u8 sampleFontLoadStatus[0x30];
|
||||||
/* 0x3468 */ u8 fontLoadStatus[0x30];
|
/* 0x3468 */ u8* fontLoadStatus;
|
||||||
/* 0x3498 */ u8* seqLoadStatus;
|
/* 0x3498 */ u8* seqLoadStatus;
|
||||||
/* 0x3518 */ volatile u8 resetStatus;
|
/* 0x3518 */ volatile u8 resetStatus;
|
||||||
/* 0x3519 */ u8 audioResetSpecIdToLoad;
|
/* 0x3519 */ u8 audioResetSpecIdToLoad;
|
||||||
|
@ -1119,10 +1127,6 @@ typedef struct {
|
||||||
uint8_t fonts[16];
|
uint8_t fonts[16];
|
||||||
} SequenceData;
|
} SequenceData;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Audio_SetGameVolume(int player_id, f32 volume);
|
void Audio_SetGameVolume(int player_id, f32 volume);
|
||||||
float Audio_GetGameVolume(int player_id);
|
float Audio_GetGameVolume(int player_id);
|
||||||
|
|
||||||
|
|
|
@ -609,13 +609,13 @@ std::string Extractor::Mkdtemp() {
|
||||||
extern "C" int zapd_main(int argc, char** argv);
|
extern "C" int zapd_main(int argc, char** argv);
|
||||||
|
|
||||||
bool Extractor::CallZapd(std::string installPath, std::string exportdir) {
|
bool Extractor::CallZapd(std::string installPath, std::string exportdir) {
|
||||||
constexpr int argc = 18;
|
constexpr int argc = 22;
|
||||||
char xmlPath[1024];
|
char xmlPath[1024];
|
||||||
char confPath[1024];
|
char confPath[1024];
|
||||||
char portVersion[18]; // 5 digits for int16_max (x3) + separators + terminator
|
char portVersion[18]; // 5 digits for int16_max (x3) + separators + terminator
|
||||||
std::array<const char*, argc> argv;
|
std::array<const char*, argc> argv;
|
||||||
const char* version = GetZapdVerStr();
|
const char* version = GetZapdVerStr();
|
||||||
const char* otrFile = IsMasterQuest() ? "oot-mq.otr" : "oot.otr";
|
const char* otrFile = IsMasterQuest() ? "oot-mq.o2r" : "oot.o2r";
|
||||||
|
|
||||||
std::string romPath = std::filesystem::absolute(mCurrentRomPath).string();
|
std::string romPath = std::filesystem::absolute(mCurrentRomPath).string();
|
||||||
installPath = std::filesystem::absolute(installPath).string();
|
installPath = std::filesystem::absolute(installPath).string();
|
||||||
|
@ -632,8 +632,8 @@ bool Extractor::CallZapd(std::string installPath, std::string exportdir) {
|
||||||
|
|
||||||
std::filesystem::current_path(tempdir);
|
std::filesystem::current_path(tempdir);
|
||||||
|
|
||||||
snprintf(xmlPath, 1024, "assets/extractor/xmls/%s", version);
|
snprintf(xmlPath, 1024, "assets/xml/%s", version);
|
||||||
snprintf(confPath, 1024, "assets/extractor/Config_%s.xml", version);
|
snprintf(confPath, 1024, "assets/Config_%s.xml", version);
|
||||||
snprintf(portVersion, 18, "%d.%d.%d", gBuildVersionMajor, gBuildVersionMinor, gBuildVersionPatch);
|
snprintf(portVersion, 18, "%d.%d.%d", gBuildVersionMajor, gBuildVersionMinor, gBuildVersionPatch);
|
||||||
|
|
||||||
argv[0] = "ZAPD";
|
argv[0] = "ZAPD";
|
||||||
|
@ -643,9 +643,9 @@ bool Extractor::CallZapd(std::string installPath, std::string exportdir) {
|
||||||
argv[4] = "-b";
|
argv[4] = "-b";
|
||||||
argv[5] = romPath.c_str();
|
argv[5] = romPath.c_str();
|
||||||
argv[6] = "-fl";
|
argv[6] = "-fl";
|
||||||
argv[7] = "assets/extractor/filelists";
|
argv[7] = "assets/filelists";
|
||||||
argv[8] = "-gsf";
|
argv[8] = "-gsf";
|
||||||
argv[9] = "1";
|
argv[9] = "0";
|
||||||
argv[10] = "-rconf";
|
argv[10] = "-rconf";
|
||||||
argv[11] = confPath;
|
argv[11] = confPath;
|
||||||
argv[12] = "-se";
|
argv[12] = "-se";
|
||||||
|
@ -654,6 +654,10 @@ bool Extractor::CallZapd(std::string installPath, std::string exportdir) {
|
||||||
argv[15] = otrFile;
|
argv[15] = otrFile;
|
||||||
argv[16] = "--portVer";
|
argv[16] = "--portVer";
|
||||||
argv[17] = portVersion;
|
argv[17] = portVersion;
|
||||||
|
argv[18] = "-o";
|
||||||
|
argv[19] = "placeholder";
|
||||||
|
argv[20] = "-osf";
|
||||||
|
argv[21] = "placeholder";
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// Grab a handle to the command window.
|
// Grab a handle to the command window.
|
||||||
|
|
|
@ -263,15 +263,15 @@ const char* constCameraStrings[] = {
|
||||||
|
|
||||||
OTRGlobals::OTRGlobals() {
|
OTRGlobals::OTRGlobals() {
|
||||||
std::vector<std::string> OTRFiles;
|
std::vector<std::string> OTRFiles;
|
||||||
std::string mqPath = Ship::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName);
|
std::string mqPath = Ship::Context::LocateFileAcrossAppDirs("oot-mq.o2r", appShortName);
|
||||||
if (std::filesystem::exists(mqPath)) {
|
if (std::filesystem::exists(mqPath)) {
|
||||||
OTRFiles.push_back(mqPath);
|
OTRFiles.push_back(mqPath);
|
||||||
}
|
}
|
||||||
std::string ootPath = Ship::Context::LocateFileAcrossAppDirs("oot.otr", appShortName);
|
std::string ootPath = Ship::Context::LocateFileAcrossAppDirs("oot.o2r", appShortName);
|
||||||
if (std::filesystem::exists(ootPath)) {
|
if (std::filesystem::exists(ootPath)) {
|
||||||
OTRFiles.push_back(ootPath);
|
OTRFiles.push_back(ootPath);
|
||||||
}
|
}
|
||||||
std::string sohOtrPath = Ship::Context::GetPathRelativeToAppBundle("soh.otr");
|
std::string sohOtrPath = Ship::Context::GetPathRelativeToAppBundle("soh.o2r");
|
||||||
if (std::filesystem::exists(sohOtrPath)) {
|
if (std::filesystem::exists(sohOtrPath)) {
|
||||||
OTRFiles.push_back(sohOtrPath);
|
OTRFiles.push_back(sohOtrPath);
|
||||||
}
|
}
|
||||||
|
@ -403,12 +403,19 @@ OTRGlobals::OTRGlobals() {
|
||||||
static_cast<uint32_t>(SOH::ResourceType::SOH_Text), 0);
|
static_cast<uint32_t>(SOH::ResourceType::SOH_Text), 0);
|
||||||
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSampleV2>(), RESOURCE_FORMAT_BINARY,
|
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSampleV2>(), RESOURCE_FORMAT_BINARY,
|
||||||
"AudioSample", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSample), 2);
|
"AudioSample", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSample), 2);
|
||||||
|
|
||||||
|
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryXMLAudioSampleV0>(), RESOURCE_FORMAT_XML,
|
||||||
|
"Sample", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSample), 0);
|
||||||
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSoundFontV2>(),
|
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSoundFontV2>(),
|
||||||
RESOURCE_FORMAT_BINARY, "AudioSoundFont",
|
RESOURCE_FORMAT_BINARY, "AudioSoundFont",
|
||||||
static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSoundFont), 2);
|
static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSoundFont), 2);
|
||||||
|
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryXMLSoundFontV0>(), RESOURCE_FORMAT_XML,
|
||||||
|
"SoundFont", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSoundFont), 0);
|
||||||
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSequenceV2>(),
|
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSequenceV2>(),
|
||||||
RESOURCE_FORMAT_BINARY, "AudioSequence",
|
RESOURCE_FORMAT_BINARY, "AudioSequence",
|
||||||
static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSequence), 2);
|
static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSequence), 2);
|
||||||
|
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryXMLAudioSequenceV0>(), RESOURCE_FORMAT_XML,
|
||||||
|
"Sequence", static_cast<uint32_t>(SOH::ResourceType::SOH_AudioSequence), 0);
|
||||||
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryBackgroundV0>(), RESOURCE_FORMAT_BINARY,
|
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryBackgroundV0>(), RESOURCE_FORMAT_BINARY,
|
||||||
"Background", static_cast<uint32_t>(SOH::ResourceType::SOH_Background), 0);
|
"Background", static_cast<uint32_t>(SOH::ResourceType::SOH_Background), 0);
|
||||||
|
|
||||||
|
@ -601,6 +608,12 @@ extern "C" void OTRAudio_Init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" char** sequenceMap;
|
||||||
|
extern "C" size_t sequenceMapSize;
|
||||||
|
|
||||||
|
extern "C" char** fontMap;
|
||||||
|
extern "C" size_t fontMapSize;
|
||||||
|
|
||||||
extern "C" void OTRAudio_Exit() {
|
extern "C" void OTRAudio_Exit() {
|
||||||
// Tell the audio thread to stop
|
// Tell the audio thread to stop
|
||||||
{
|
{
|
||||||
|
@ -611,6 +624,19 @@ extern "C" void OTRAudio_Exit() {
|
||||||
|
|
||||||
// Wait until the audio thread quit
|
// Wait until the audio thread quit
|
||||||
audio.thread.join();
|
audio.thread.join();
|
||||||
|
#if 0
|
||||||
|
for (size_t i = 0; i < sequenceMapSize; i++) {
|
||||||
|
free(sequenceMap[i]);
|
||||||
|
}
|
||||||
|
free(sequenceMap);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < fontMapSize; i++) {
|
||||||
|
free(fontMap[i]);
|
||||||
|
}
|
||||||
|
free(fontMap);
|
||||||
|
free(gAudioContext.seqLoadStatus);
|
||||||
|
free(gAudioContext.fontLoadStatus);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void VanillaItemTable_Init() {
|
extern "C" void VanillaItemTable_Init() {
|
||||||
|
@ -945,7 +971,7 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) {
|
||||||
OTRVersion version = {};
|
OTRVersion version = {};
|
||||||
|
|
||||||
// Use a temporary archive instance to load the otr and read the version file
|
// Use a temporary archive instance to load the otr and read the version file
|
||||||
auto archive = std::make_shared<Ship::OtrArchive>(otrPath);
|
auto archive = std::make_shared<Ship::O2rArchive>(otrPath);
|
||||||
if (archive->Open()) {
|
if (archive->Open()) {
|
||||||
auto t = archive->LoadFile("portVersion");
|
auto t = archive->LoadFile("portVersion");
|
||||||
if (t != nullptr && t->IsLoaded) {
|
if (t != nullptr && t->IsLoaded) {
|
||||||
|
@ -963,7 +989,7 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that a soh.otr exists and matches the version of soh running
|
// Check that a soh.o2r exists and matches the version of soh running
|
||||||
// Otherwise show a message and exit
|
// Otherwise show a message and exit
|
||||||
void CheckSoHOTRVersion(std::string otrPath) {
|
void CheckSoHOTRVersion(std::string otrPath) {
|
||||||
std::string msg;
|
std::string msg;
|
||||||
|
@ -972,20 +998,20 @@ void CheckSoHOTRVersion(std::string otrPath) {
|
||||||
msg = "\x1b[4;2HPlease re-extract it from the download."
|
msg = "\x1b[4;2HPlease re-extract it from the download."
|
||||||
"\x1b[6;2HPress the Home button to exit...";
|
"\x1b[6;2HPress the Home button to exit...";
|
||||||
#elif defined(__WIIU__)
|
#elif defined(__WIIU__)
|
||||||
msg = "Please extract the soh.otr from the Ship of Harkinian download\nto your folder.\n\nPress and hold the power "
|
msg = "Please extract the soh.o2r from the Ship of Harkinian download\nto your folder.\n\nPress and hold the power "
|
||||||
"button to shutdown...";
|
"button to shutdown...";
|
||||||
#else
|
#else
|
||||||
msg = "Please extract the soh.otr from the Ship of Harkinian download to your folder.\n\nExiting...";
|
msg = "Please extract the soh.o2r from the Ship of Harkinian download to your folder.\n\nExiting...";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!std::filesystem::exists(otrPath)) {
|
if (!std::filesystem::exists(otrPath)) {
|
||||||
#if not defined(__SWITCH__) && not defined(__WIIU__)
|
#if not defined(__SWITCH__) && not defined(__WIIU__)
|
||||||
Extractor::ShowErrorBox("soh.otr file is missing", msg.c_str());
|
Extractor::ShowErrorBox("soh.o2r file is missing", msg.c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
#elif defined(__SWITCH__)
|
#elif defined(__SWITCH__)
|
||||||
Ship::Switch::PrintErrorMessageToScreen(("\x1b[2;2HYou are missing the soh.otr file." + msg).c_str());
|
Ship::Switch::PrintErrorMessageToScreen(("\x1b[2;2HYou are missing the soh.o2r file." + msg).c_str());
|
||||||
#elif defined(__WIIU__)
|
#elif defined(__WIIU__)
|
||||||
OSFatal(("You are missing the soh.otr file\n\n" + msg).c_str());
|
OSFatal(("You are missing the soh.o2r file\n\n" + msg).c_str());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -994,12 +1020,12 @@ void CheckSoHOTRVersion(std::string otrPath) {
|
||||||
if (otrVersion.major != gBuildVersionMajor || otrVersion.minor != gBuildVersionMinor ||
|
if (otrVersion.major != gBuildVersionMajor || otrVersion.minor != gBuildVersionMinor ||
|
||||||
otrVersion.patch != gBuildVersionPatch) {
|
otrVersion.patch != gBuildVersionPatch) {
|
||||||
#if not defined(__SWITCH__) && not defined(__WIIU__)
|
#if not defined(__SWITCH__) && not defined(__WIIU__)
|
||||||
Extractor::ShowErrorBox("soh.otr file version does not match", msg.c_str());
|
Extractor::ShowErrorBox("soh.o2r file version does not match", msg.c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
#elif defined(__SWITCH__)
|
#elif defined(__SWITCH__)
|
||||||
Ship::Switch::PrintErrorMessageToScreen(("\x1b[2;2HYou have an old soh.otr file." + msg).c_str());
|
Ship::Switch::PrintErrorMessageToScreen(("\x1b[2;2HYou have an old soh.o2r file." + msg).c_str());
|
||||||
#elif defined(__WIIU__)
|
#elif defined(__WIIU__)
|
||||||
OSFatal(("You have an old soh.otr file\n\n" + msg).c_str());
|
OSFatal(("You have an old soh.o2r file\n\n" + msg).c_str());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1040,10 +1066,10 @@ void DetectOTRVersion(std::string fileName, bool isMQ) {
|
||||||
|
|
||||||
if (Extractor::ShowYesNoBox("Old OTR File Found", msgBuf) == IDYES) {
|
if (Extractor::ShowYesNoBox("Old OTR File Found", msgBuf) == IDYES) {
|
||||||
std::string installPath = Ship::Context::GetAppBundlePath();
|
std::string installPath = Ship::Context::GetAppBundlePath();
|
||||||
if (!std::filesystem::exists(installPath + "/assets/extractor")) {
|
if (!std::filesystem::exists(installPath + "/assets")) {
|
||||||
Extractor::ShowErrorBox(
|
Extractor::ShowErrorBox(
|
||||||
"Extractor assets not found",
|
"Extractor assets not found",
|
||||||
"Unable to regenerate. Missing assets/extractor folder needed to generate OTR file.\n\nExiting...");
|
"Unable to regenerate. Missing assets/ folder needed to generate OTR file.\n\nExiting...");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1070,6 +1096,10 @@ void DetectOTRVersion(std::string fileName, bool isMQ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void Messagebox_ShowErrorBox(char* title, char* body) {
|
||||||
|
Extractor::ShowErrorBox(title, body);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsSubpath(const std::filesystem::path& path, const std::filesystem::path& base) {
|
bool IsSubpath(const std::filesystem::path& path, const std::filesystem::path& base) {
|
||||||
auto rel = std::filesystem::relative(path, base);
|
auto rel = std::filesystem::relative(path, base);
|
||||||
return !rel.empty() && rel.native()[0] != '.';
|
return !rel.empty() && rel.native()[0] != '.';
|
||||||
|
@ -1151,17 +1181,22 @@ extern "C" void InitOTR() {
|
||||||
CheckAndCreateModFolder();
|
CheckAndCreateModFolder();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CheckSoHOTRVersion(Ship::Context::GetPathRelativeToAppBundle("soh.otr"));
|
CheckSoHOTRVersion(Ship::Context::GetPathRelativeToAppBundle("soh.o2r"));
|
||||||
|
const bool ootO2RExists =
|
||||||
|
std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot-mq.o2r", appShortName)) ||
|
||||||
|
std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot.o2r", appShortName));
|
||||||
|
const bool ootOTRExists =
|
||||||
|
std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName)) ||
|
||||||
|
std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot.otr", appShortName));
|
||||||
|
|
||||||
if (!std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot-mq.otr", appShortName)) &&
|
if (!ootOTRExists && !ootO2RExists) {
|
||||||
!std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot.otr", appShortName))) {
|
|
||||||
|
|
||||||
#if not defined(__SWITCH__) && not defined(__WIIU__)
|
#if not defined(__SWITCH__) && not defined(__WIIU__)
|
||||||
std::string installPath = Ship::Context::GetAppBundlePath();
|
std::string installPath = Ship::Context::GetAppBundlePath();
|
||||||
if (!std::filesystem::exists(installPath + "/assets/extractor")) {
|
if (!std::filesystem::exists(installPath + "/assets")) {
|
||||||
Extractor::ShowErrorBox(
|
Extractor::ShowErrorBox(
|
||||||
"Extractor assets not found",
|
"Extractor assets not found",
|
||||||
"No OTR files found. Missing assets/extractor folder needed to generate OTR file.\n\nExiting...");
|
"No OTR files found. Missing assets/ folder needed to generate OTR file.\n\nExiting...");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1200,8 +1235,8 @@ extern "C" void InitOTR() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
DetectOTRVersion("oot.otr", false);
|
DetectOTRVersion("oot.o2r", false);
|
||||||
DetectOTRVersion("oot-mq.otr", true);
|
DetectOTRVersion("oot-mq.o2r", true);
|
||||||
|
|
||||||
OTRGlobals::Instance = new OTRGlobals();
|
OTRGlobals::Instance = new OTRGlobals();
|
||||||
CustomMessageManager::Instance = new CustomMessageManager();
|
CustomMessageManager::Instance = new CustomMessageManager();
|
||||||
|
|
|
@ -166,6 +166,7 @@ void CheckTracker_OnMessageClose();
|
||||||
|
|
||||||
GetItemID RetrieveGetItemIDFromItemID(ItemID itemID);
|
GetItemID RetrieveGetItemIDFromItemID(ItemID itemID);
|
||||||
RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID);
|
RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID);
|
||||||
|
void Messagebox_ShowErrorBox(char* title, char* body);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -429,11 +429,16 @@ extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path) {
|
||||||
return *sequence;
|
return *sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" SequenceData* ResourceMgr_LoadSeqPtrByName(const char* path) {
|
||||||
|
SequenceData* sequence = (SequenceData*)ResourceGetDataByName(path);
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" SoundFontSample* ResourceMgr_LoadAudioSample(const char* path) {
|
extern "C" SoundFontSample* ResourceMgr_LoadAudioSample(const char* path) {
|
||||||
return (SoundFontSample*)ResourceGetDataByName(path);
|
return (SoundFontSample*)ResourceGetDataByName(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path) {
|
extern "C" SoundFont* ResourceMgr_LoadAudioSoundFontByName(const char* path) {
|
||||||
return (SoundFont*)ResourceGetDataByName(path);
|
return (SoundFont*)ResourceGetDataByName(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,8 +51,9 @@ void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName);
|
||||||
char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path);
|
char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path);
|
||||||
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc);
|
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc);
|
||||||
Vtx* ResourceMgr_LoadVtxByName(char* path);
|
Vtx* ResourceMgr_LoadVtxByName(char* path);
|
||||||
SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path);
|
SoundFont* ResourceMgr_LoadAudioSoundFontByName(const char* path);
|
||||||
SequenceData ResourceMgr_LoadSeqByName(const char* path);
|
SequenceData ResourceMgr_LoadSeqByName(const char* path);
|
||||||
|
SequenceData* ResourceMgr_LoadSeqPtrByName(const char* path);
|
||||||
SoundFontSample* ResourceMgr_LoadAudioSample(const char* path);
|
SoundFontSample* ResourceMgr_LoadAudioSample(const char* path);
|
||||||
CollisionHeader* ResourceMgr_LoadColByName(const char* path);
|
CollisionHeader* ResourceMgr_LoadColByName(const char* path);
|
||||||
bool ResourceMgr_IsAltAssetsEnabled();
|
bool ResourceMgr_IsAltAssetsEnabled();
|
||||||
|
|
268
soh/soh/mixer.c
268
soh/soh/mixer.c
|
@ -1,9 +1,11 @@
|
||||||
|
//! This file is always optimized by a rule in the CMakeList. This is done because the SIMD functions are very large
|
||||||
|
//! when unoptimized and clang does not allow optimizing a single function.
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "mixer.h"
|
#include "mixer.h"
|
||||||
|
|
||||||
#ifndef __clang__
|
#ifndef __clang__
|
||||||
#pragma GCC optimize("unroll-loops")
|
#pragma GCC optimize("unroll-loops")
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,6 +16,7 @@
|
||||||
#define ROUND_UP_8(v) (((v) + 7) & ~7)
|
#define ROUND_UP_8(v) (((v) + 7) & ~7)
|
||||||
#define ROUND_DOWN_16(v) ((v) & ~0xf)
|
#define ROUND_DOWN_16(v) ((v) & ~0xf)
|
||||||
|
|
||||||
|
|
||||||
#define DMEM_BUF_SIZE (0x1000 - 0x3C0 - 0x40)
|
#define DMEM_BUF_SIZE (0x1000 - 0x3C0 - 0x40)
|
||||||
#define BUF_U8(a) (rspa.buf.as_u8 + ((a)-0x3C0))
|
#define BUF_U8(a) (rspa.buf.as_u8 + ((a)-0x3C0))
|
||||||
#define BUF_S16(a) (rspa.buf.as_s16 + ((a)-0x3C0) / sizeof(int16_t))
|
#define BUF_S16(a) (rspa.buf.as_s16 + ((a)-0x3C0) / sizeof(int16_t))
|
||||||
|
@ -35,7 +38,7 @@ static struct {
|
||||||
uint16_t filter_count;
|
uint16_t filter_count;
|
||||||
int16_t filter[8];
|
int16_t filter[8];
|
||||||
|
|
||||||
union {
|
__attribute__((aligned(16))) union {
|
||||||
int16_t as_s16[DMEM_BUF_SIZE / sizeof(int16_t)];
|
int16_t as_s16[DMEM_BUF_SIZE / sizeof(int16_t)];
|
||||||
uint8_t as_u8[DMEM_BUF_SIZE];
|
uint8_t as_u8[DMEM_BUF_SIZE];
|
||||||
} buf;
|
} buf;
|
||||||
|
@ -66,6 +69,9 @@ static int16_t resample_table[64][4] = {
|
||||||
{ 0xffdf, 0x0d46, 0x66ad, 0x0c39 }
|
{ 0xffdf, 0x0d46, 0x66ad, 0x0c39 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void aMixImplSSE2(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr);
|
||||||
|
static void aMixImplNEON(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr);
|
||||||
|
|
||||||
static inline int16_t clamp16(int32_t v) {
|
static inline int16_t clamp16(int32_t v) {
|
||||||
if (v < -0x8000) {
|
if (v < -0x8000) {
|
||||||
return -0x8000;
|
return -0x8000;
|
||||||
|
@ -99,6 +105,33 @@ void aLoadBufferImpl(const void* source_addr, uint16_t dest_addr, uint16_t nbyte
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <opus/opus.h>
|
||||||
|
#include <opusfile.h>
|
||||||
|
|
||||||
|
void aOPUSdecImpl(void* source_addr, uint16_t dest_addr, uint16_t nbytes, struct OggOpusFile** decState, int32_t pos,
|
||||||
|
uint32_t size) {
|
||||||
|
int readSamples = 0;
|
||||||
|
if (*decState == NULL) {
|
||||||
|
*decState = op_open_memory(source_addr, size, NULL);
|
||||||
|
}
|
||||||
|
op_pcm_seek(*decState, pos);
|
||||||
|
int ret = op_read(*decState, BUF_S16(dest_addr), nbytes / 2, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
readSamples += ret;
|
||||||
|
while (readSamples < nbytes / 2) {
|
||||||
|
ret = op_read(*decState, BUF_S16(dest_addr + readSamples * 2), (nbytes - readSamples * 2) / 2, NULL);
|
||||||
|
if (ret == 0)
|
||||||
|
break;
|
||||||
|
readSamples += ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void aOPUSFree(struct OggOpusFile* opusFile) {
|
||||||
|
op_free(opusFile);
|
||||||
|
}
|
||||||
|
|
||||||
void aSaveBufferImpl(uint16_t source_addr, int16_t* dest_addr, uint16_t nbytes) {
|
void aSaveBufferImpl(uint16_t source_addr, int16_t* dest_addr, uint16_t nbytes) {
|
||||||
memcpy(dest_addr, BUF_S16(source_addr), ROUND_DOWN_16(nbytes));
|
memcpy(dest_addr, BUF_S16(source_addr), ROUND_DOWN_16(nbytes));
|
||||||
}
|
}
|
||||||
|
@ -296,7 +329,7 @@ void aEnvMixerImpl(uint16_t in_addr, uint16_t n_samples, bool swap_reverb, bool
|
||||||
} while (n > 0);
|
} while (n > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr) {
|
static void aMixImplRef(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr) {
|
||||||
int nbytes = ROUND_UP_32(ROUND_DOWN_16(count << 4));
|
int nbytes = ROUND_UP_32(ROUND_DOWN_16(count << 4));
|
||||||
int16_t* in = BUF_S16(in_addr);
|
int16_t* in = BUF_S16(in_addr);
|
||||||
int16_t* out = BUF_S16(out_addr);
|
int16_t* out = BUF_S16(out_addr);
|
||||||
|
@ -323,6 +356,16 @@ void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void aMixImpl(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr) {
|
||||||
|
#if defined(__SSE2__) || defined(_M_AMD64)
|
||||||
|
aMixImplSSE2(count, gain, in_addr, out_addr);
|
||||||
|
#elif defined(__ARM_NEON)
|
||||||
|
aMixImplNEON(count, gain, in_addr, out_addr);
|
||||||
|
#else
|
||||||
|
aMixImplRef(count, gain, in_addr, out_addr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void aS8DecImpl(uint8_t flags, ADPCM_STATE state) {
|
void aS8DecImpl(uint8_t flags, ADPCM_STATE state) {
|
||||||
uint8_t* in = BUF_U8(rspa.in);
|
uint8_t* in = BUF_U8(rspa.in);
|
||||||
int16_t* out = BUF_S16(rspa.out);
|
int16_t* out = BUF_S16(rspa.out);
|
||||||
|
@ -555,3 +598,222 @@ void aUnkCmd19Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_add
|
||||||
nbytes -= 32 * sizeof(int16_t);
|
nbytes -= 32 * sizeof(int16_t);
|
||||||
} while (nbytes > 0);
|
} while (nbytes > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// From here on there are SIMD implementations of the various mixer functions.
|
||||||
|
// A note about FORCE_OPTIMIZE...
|
||||||
|
// Compilers don't handle SIMD code well when not optimizing. It is unlikely that this code will need to be debugged
|
||||||
|
// outside of specific audio issues. We can assume it should always be optimized.
|
||||||
|
|
||||||
|
// SIMD operations expect aligned data
|
||||||
|
#include "align_asset_macro.h"
|
||||||
|
|
||||||
|
#if defined(__SSE2__) || defined(_M_AMD64)
|
||||||
|
#include <immintrin.h>
|
||||||
|
|
||||||
|
static const ALIGN_ASSET(16) int16_t x7fff[8] = {
|
||||||
|
0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
|
||||||
|
};
|
||||||
|
static const ALIGN_ASSET(16) int32_t x4000[4] = {
|
||||||
|
0x4000,
|
||||||
|
0x4000,
|
||||||
|
0x4000,
|
||||||
|
0x4000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void aMixImplSSE2(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr) {
|
||||||
|
int nbytes = ROUND_UP_32(ROUND_DOWN_16(count << 4));
|
||||||
|
int16_t* in = BUF_S16(in_addr);
|
||||||
|
int16_t* out = BUF_S16(out_addr);
|
||||||
|
int i;
|
||||||
|
int32_t sample;
|
||||||
|
if (gain == -0x8000) {
|
||||||
|
while (nbytes > 0) {
|
||||||
|
for (unsigned int i = 0; i < 2; i++) {
|
||||||
|
__m128i outVec = _mm_loadu_si128((__m128i*)out);
|
||||||
|
__m128i inVec = _mm_loadu_si128((__m128i*)in);
|
||||||
|
__m128i subsVec = _mm_subs_epi16(outVec, inVec);
|
||||||
|
_mm_storeu_si128(out, subsVec);
|
||||||
|
nbytes -= 8 * sizeof(int16_t);
|
||||||
|
in += 8;
|
||||||
|
out += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Load constants into vectors from aligned memory.
|
||||||
|
__m128i x7fffVec = _mm_load_si128((__m128i*)x7fff);
|
||||||
|
__m128i x4000Vec = _mm_load_si128((__m128i*)x4000);
|
||||||
|
__m128i gainVec = _mm_set1_epi16(gain);
|
||||||
|
while (nbytes > 0) {
|
||||||
|
for (unsigned int i = 0; i < 2; i++) {
|
||||||
|
// Load input and output data into vectors
|
||||||
|
__m128i outVec = _mm_loadu_si128((__m128i*)out);
|
||||||
|
__m128i inVec = _mm_loadu_si128((__m128i*)in);
|
||||||
|
// Multiply `out` by `0x7FFF` producing 32 bit results, and store the upper and lower bits in each vector.
|
||||||
|
// Equivalent to `out[0..8] * 0x7FFF`
|
||||||
|
__m128i outx7fffLoVec = _mm_mullo_epi16(outVec, x7fffVec);
|
||||||
|
__m128i outx7fffHiVec = _mm_mulhi_epi16(outVec, x7fffVec);
|
||||||
|
// Same as above but for in and gain. Equivalent to `in[0..8] * gain`
|
||||||
|
__m128i inxGainLoVec = _mm_mullo_epi16(inVec, gainVec);
|
||||||
|
__m128i inxGainHiVec = _mm_mulhi_epi16(inVec, gainVec);
|
||||||
|
|
||||||
|
// Interleave the lo and hi bits into one 32 bit value for each vector element.
|
||||||
|
// So now we have 4 full elements in each vector instead of 8 half elements.
|
||||||
|
outx7fffLoVec = _mm_unpacklo_epi16(outx7fffLoVec, outx7fffHiVec);
|
||||||
|
outx7fffHiVec = _mm_unpackhi_epi16(outx7fffLoVec, outx7fffHiVec);
|
||||||
|
inxGainLoVec = _mm_unpacklo_epi16(inxGainLoVec, inxGainHiVec);
|
||||||
|
inxGainHiVec = _mm_unpackhi_epi16(inxGainLoVec, inxGainHiVec);
|
||||||
|
|
||||||
|
// Now we have 4 32 bit elements. Continue the calculaton per the reference implementation.
|
||||||
|
// We already did out + 0x7fff and in * gain.
|
||||||
|
// *out * 0x7fff + *in++ * gain is the final result of these two calculations.
|
||||||
|
__m128i addLoVec = _mm_add_epi32(outx7fffLoVec, inxGainLoVec);
|
||||||
|
__m128i addHiVec = _mm_add_epi32(outx7fffHiVec, inxGainHiVec);
|
||||||
|
// Add 0x4000 to each element
|
||||||
|
addLoVec = _mm_add_epi32(addLoVec, x4000Vec);
|
||||||
|
addHiVec = _mm_add_epi32(addHiVec, x4000Vec);
|
||||||
|
// Shift each element over by 15
|
||||||
|
__m128i shiftedLoVec = _mm_srai_epi32(addLoVec, 15);
|
||||||
|
__m128i shiftedHiVec = _mm_srai_epi32(addHiVec, 15);
|
||||||
|
// Convert each 32 bit element to 16 bit with saturation (clamp) and store in `outVec`
|
||||||
|
outVec = _mm_packs_epi32(shiftedLoVec, shiftedHiVec);
|
||||||
|
// Write the final vector back to memory
|
||||||
|
// The final calculation is ((out[0..8] * 0x7fff + in[0..8] * gain) + 0x4000) >> 15;
|
||||||
|
_mm_storeu_si128((__m128i*)out, outVec);
|
||||||
|
|
||||||
|
in += 8;
|
||||||
|
out += 8;
|
||||||
|
nbytes -= 8 * sizeof(int16_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(__ARM_NEON)
|
||||||
|
#include <arm_neon.h>
|
||||||
|
static const int32_t x4000Arr[4] = { 0x4000, 0x4000, 0x4000, 0x4000 };
|
||||||
|
void aMixImplNEON(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr) {
|
||||||
|
int nbytes = ROUND_UP_32(ROUND_DOWN_16(count << 4));
|
||||||
|
int16_t* in = BUF_S16(in_addr);
|
||||||
|
int16_t* out = BUF_S16(out_addr);
|
||||||
|
int i;
|
||||||
|
int32_t sample;
|
||||||
|
|
||||||
|
if (gain == -0x8000) {
|
||||||
|
while (nbytes > 0) {
|
||||||
|
for (unsigned int i = 0; i < 2; i++) {
|
||||||
|
int16x8_t outVec = vld1q_s16(out);
|
||||||
|
int16x8_t inVec = vld1q_s16(in);
|
||||||
|
int16x8_t subVec = vqsubq_s16(outVec, inVec);
|
||||||
|
vst1q_s16(out, subVec);
|
||||||
|
nbytes -= 8 * sizeof(int16_t);
|
||||||
|
out += 8;
|
||||||
|
in += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int16x8_t gainVec = vdupq_n_s16(gain);
|
||||||
|
int32x4_t x4000Vec = vld1q_s32(x4000Arr);
|
||||||
|
while (nbytes > 0) {
|
||||||
|
for (unsigned int i = 0; i < 2; i++) {
|
||||||
|
// for (i = 0; i < 16; i++) {
|
||||||
|
int16x8_t outVec = vld1q_s16(out);
|
||||||
|
int16x8_t inVec = vld1q_s16(in);
|
||||||
|
int16x4_t outLoVec = vget_low_s16(outVec);
|
||||||
|
int16x8_t outLoVec2 = vcombine_s16(outLoVec, outLoVec);
|
||||||
|
int16x4_t inLoVec = vget_low_s16(inVec);
|
||||||
|
int16x8_t inLoVec2 = vcombine_s16(inLoVec, inLoVec);
|
||||||
|
int32x4_t outX7fffHiVec = vmull_high_n_s16(outVec, 0x7FFF);
|
||||||
|
int32x4_t outX7fffLoVec = vmull_high_n_s16(outLoVec2, 0x7FFF);
|
||||||
|
|
||||||
|
int32x4_t inGainLoVec = vmull_high_s16(inLoVec2, gainVec);
|
||||||
|
int32x4_t inGainHiVec = vmull_high_s16(inVec, gainVec);
|
||||||
|
int32x4_t addVecLo = vaddq_s32(outX7fffLoVec, inGainLoVec);
|
||||||
|
int32x4_t addVecHi = vaddq_s32(outX7fffHiVec, inGainHiVec);
|
||||||
|
addVecHi = vaddq_s32(addVecHi, x4000Vec);
|
||||||
|
addVecLo = vaddq_s32(addVecLo, x4000Vec);
|
||||||
|
int32x4_t shiftVecHi = vshrq_n_s32(addVecHi, 15);
|
||||||
|
int32x4_t shiftVecLo = vshrq_n_s32(addVecLo, 15);
|
||||||
|
int16x4_t shiftedNarrowHiVec = vqmovn_s32(shiftVecHi);
|
||||||
|
int16x4_t shiftedNarrowLoVec = vqmovn_s32(shiftVecLo);
|
||||||
|
vst1_s16(out, shiftedNarrowLoVec);
|
||||||
|
out += 4;
|
||||||
|
vst1_s16(out, shiftedNarrowHiVec);
|
||||||
|
// int16x8_t finalVec = vcombine_s16(shiftedNarrowLoVec, shiftedNarrowHiVec);
|
||||||
|
// vst1q_s16(out, finalVec);
|
||||||
|
out += 4;
|
||||||
|
in += 8;
|
||||||
|
|
||||||
|
nbytes -= 8 * sizeof(int16_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static const ALIGN_ASSET(32) int16_t x7fff[16] = { 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,};
|
||||||
|
static const ALIGN_ASSET(32) int32_t x4000[8] = { 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000};
|
||||||
|
|
||||||
|
#pragma GCC target("avx2")
|
||||||
|
// AVX2 version of the SSE2 implementation above. AVX2 wasn't released until 2014 and I don't have a good way of checking for it at compile time.
|
||||||
|
void aMixImpl256(uint16_t count, int16_t gain, uint16_t in_addr, uint16_t out_addr) {
|
||||||
|
int nbytes = ROUND_UP_32(ROUND_DOWN_16(count << 4));
|
||||||
|
int16_t* in = BUF_S16(in_addr);
|
||||||
|
int16_t* out = BUF_S16(out_addr);
|
||||||
|
int i;
|
||||||
|
int32_t sample;
|
||||||
|
if (gain == -0x8000) {
|
||||||
|
while (nbytes > 0) {
|
||||||
|
__m256i outVec =_mm256_loadu_si256((__m256*)out);
|
||||||
|
__m256i inVec =_mm256_loadu_si256((__m256i*)in);
|
||||||
|
__m256i subsVec =_mm256_subs_epi16(outVec, inVec);
|
||||||
|
_mm256_storeu_si256(out, subsVec);
|
||||||
|
in += 16;
|
||||||
|
out += 16;
|
||||||
|
nbytes -= 16 * sizeof(int16_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Load constants into vectors from aligned memory.
|
||||||
|
__m256i x7fffVec = _mm256_load_si256((__m256i*)x7fff);
|
||||||
|
__m256i x4000Vec = _mm256_load_si256((__m256i*)x4000);
|
||||||
|
__m256i gainVec = _mm256_set1_epi16(gain);
|
||||||
|
while (nbytes > 0) {
|
||||||
|
// Load input and output data into vectors
|
||||||
|
__m256i outVec = _mm256_loadu_si256((__m256i*)out);
|
||||||
|
__m256i inVec = _mm256_loadu_si256((__m256i*)in);
|
||||||
|
// Multiply `out` by `0x7FFF` producing 32 bit results, and store the upper and lower bits in each vector.
|
||||||
|
// Equivalent to `out[0..16] * 0x7FFF`
|
||||||
|
__m256i outx7fffLoVec = _mm256_mullo_epi16(outVec, x7fffVec);
|
||||||
|
__m256i outx7fffHiVec = _mm256_mulhi_epi16(outVec, x7fffVec);
|
||||||
|
// Same as above but for in and gain. Equivalent to `in[0..16] * gain`
|
||||||
|
__m256i inxGainLoVec = _mm256_mullo_epi16(inVec, gainVec);
|
||||||
|
__m256i inxGainHiVec = _mm256_mulhi_epi16(inVec, gainVec);
|
||||||
|
|
||||||
|
// Interleave the lo and hi bits into one 32 bit value for each vector element.
|
||||||
|
// So now we have 8 full elements in each vector instead of 16 half elements.
|
||||||
|
outx7fffLoVec = _mm256_unpacklo_epi16(outx7fffLoVec, outx7fffHiVec);
|
||||||
|
outx7fffHiVec = _mm256_unpackhi_epi16(outx7fffLoVec, outx7fffHiVec);
|
||||||
|
inxGainLoVec = _mm256_unpacklo_epi16(inxGainLoVec, inxGainHiVec);
|
||||||
|
inxGainHiVec = _mm256_unpackhi_epi16(inxGainLoVec, inxGainHiVec);
|
||||||
|
|
||||||
|
// Now we have 8 32 bit elements. Continue the calculaton per the reference implementation.
|
||||||
|
// We already did out + 0x7fff and in * gain.
|
||||||
|
// *out * 0x7fff + *in++ * gain is the final result of these two calculations.
|
||||||
|
__m256i addLoVec = _mm256_add_epi32(outx7fffLoVec, inxGainLoVec);
|
||||||
|
__m256i addHiVec = _mm256_add_epi32(outx7fffHiVec, inxGainHiVec);
|
||||||
|
// Add 0x4000 to each element
|
||||||
|
addLoVec = _mm256_add_epi32(addLoVec, x4000Vec);
|
||||||
|
addHiVec = _mm256_add_epi32(addHiVec, x4000Vec);
|
||||||
|
// Shift each element over by 15
|
||||||
|
__m256i shiftedLoVec = _mm256_srai_epi32(addLoVec, 15);
|
||||||
|
__m256i shiftedHiVec = _mm256_srai_epi32(addHiVec, 15);
|
||||||
|
// Convert each 32 bit element to 16 bit with saturation (clamp) and store in `outVec`
|
||||||
|
outVec = _mm256_packs_epi32(shiftedLoVec, shiftedHiVec);
|
||||||
|
// Write the final vector back to memory
|
||||||
|
// The final calculation is ((out[0..16] * 0x7fff + in[0..16] * gain) + 0x4000) >> 15;
|
||||||
|
_mm256_storeu_si256((__m256i*)out, outVec);
|
||||||
|
|
||||||
|
in += 16;
|
||||||
|
out += 16;
|
||||||
|
nbytes -= 16 * sizeof(int16_t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -57,6 +57,11 @@ void aHiLoGainImpl(uint8_t g, uint16_t count, uint16_t addr);
|
||||||
void aUnkCmd3Impl(uint16_t a, uint16_t b, uint16_t c);
|
void aUnkCmd3Impl(uint16_t a, uint16_t b, uint16_t c);
|
||||||
void aUnkCmd19Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_addr);
|
void aUnkCmd19Impl(uint8_t f, uint16_t count, uint16_t out_addr, uint16_t in_addr);
|
||||||
|
|
||||||
|
struct OggOpusFile;
|
||||||
|
|
||||||
|
void aOPUSdecImpl(void* source_addr, uint16_t dest_addr, uint16_t nbytes, struct OggOpusFile** decState, int32_t pos,
|
||||||
|
uint32_t size);
|
||||||
|
|
||||||
#define aSegment(pkt, s, b) \
|
#define aSegment(pkt, s, b) \
|
||||||
do { \
|
do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "soh/resource/importer/AnimationFactory.h"
|
#include "soh/resource/importer/AnimationFactory.h"
|
||||||
#include "soh/resource/type/Animation.h"
|
#include "soh/resource/type/Animation.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "Context.h"
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
std::shared_ptr<Ship::IResource>
|
std::shared_ptr<Ship::IResource>
|
||||||
|
@ -80,7 +81,11 @@ ResourceFactoryBinaryAnimationV0::ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
animation->animationData.linkAnimationHeader.common.frameCount = reader->ReadInt16();
|
animation->animationData.linkAnimationHeader.common.frameCount = reader->ReadInt16();
|
||||||
|
|
||||||
// Read the segment pointer (always 32 bit, doesn't adjust for system pointer size)
|
// Read the segment pointer (always 32 bit, doesn't adjust for system pointer size)
|
||||||
animation->animationData.linkAnimationHeader.segment = (void*)reader->ReadUInt32();
|
std::string path = reader->ReadString();
|
||||||
|
const auto animData = std::static_pointer_cast<Animation>(
|
||||||
|
Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(path.c_str()));
|
||||||
|
|
||||||
|
animation->animationData.linkAnimationHeader.segment = animData->GetPointer();
|
||||||
} else if (animType == AnimationType::Legacy) {
|
} else if (animType == AnimationType::Legacy) {
|
||||||
SPDLOG_DEBUG("BEYTAH ANIMATION?!");
|
SPDLOG_DEBUG("BEYTAH ANIMATION?!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,191 @@
|
||||||
#include "soh/resource/importer/AudioSampleFactory.h"
|
#include "soh/resource/importer/AudioSampleFactory.h"
|
||||||
|
#include "soh/resource/importer/AudioSoundFontFactory.h"
|
||||||
#include "soh/resource/type/AudioSample.h"
|
#include "soh/resource/type/AudioSample.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "z64.h"
|
||||||
|
#include "z64audio.h"
|
||||||
|
#include "Context.h"
|
||||||
|
#include "resource/archive/Archive.h"
|
||||||
|
#define DR_WAV_IMPLEMENTATION
|
||||||
|
#include <dr_wav.h>
|
||||||
|
|
||||||
|
#define DR_MP3_IMPLEMENTATION
|
||||||
|
#include <dr_mp3.h>
|
||||||
|
|
||||||
|
#define DR_FLAC_IMPLEMENTATION
|
||||||
|
#include <dr_flac.h>
|
||||||
|
|
||||||
|
#include <ogg/ogg.h>
|
||||||
|
#include <vorbis/codec.h>
|
||||||
|
#include "vorbis/vorbisfile.h"
|
||||||
|
|
||||||
|
struct OggFileData {
|
||||||
|
void* data;
|
||||||
|
size_t pos;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum class OggType {
|
||||||
|
None = -1,
|
||||||
|
Vorbis,
|
||||||
|
Opus,
|
||||||
|
} OggType;
|
||||||
|
|
||||||
|
static size_t VorbisReadCallback(void* out, size_t size, size_t elems, void* src) {
|
||||||
|
OggFileData* data = static_cast<OggFileData*>(src);
|
||||||
|
size_t toRead = size * elems;
|
||||||
|
|
||||||
|
if (toRead > data->size - data->pos) {
|
||||||
|
toRead = data->size - data->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(out, static_cast<uint8_t*>(data->data) + data->pos, toRead);
|
||||||
|
data->pos += toRead;
|
||||||
|
|
||||||
|
return toRead / size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int VorbisSeekCallback(void* src, ogg_int64_t pos, int whence) {
|
||||||
|
OggFileData* data = static_cast<OggFileData*>(src);
|
||||||
|
size_t newPos;
|
||||||
|
|
||||||
|
switch (whence) {
|
||||||
|
case SEEK_SET:
|
||||||
|
newPos = pos;
|
||||||
|
break;
|
||||||
|
case SEEK_CUR:
|
||||||
|
newPos = data->pos + pos;
|
||||||
|
break;
|
||||||
|
case SEEK_END:
|
||||||
|
newPos = data->size + pos;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (newPos > data->size) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
data->pos = newPos;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int VorbisCloseCallback([[maybe_unused]] void* src) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long VorbisTellCallback(void* src) {
|
||||||
|
OggFileData* data = static_cast<OggFileData*>(src);
|
||||||
|
return data->pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const ov_callbacks vorbisCallbacks = {
|
||||||
|
VorbisReadCallback,
|
||||||
|
VorbisSeekCallback,
|
||||||
|
VorbisCloseCallback,
|
||||||
|
VorbisTellCallback,
|
||||||
|
};
|
||||||
|
|
||||||
|
static OggType GetOggType(OggFileData* data) {
|
||||||
|
ogg_sync_state oy;
|
||||||
|
ogg_stream_state os;
|
||||||
|
ogg_page og;
|
||||||
|
ogg_packet op;
|
||||||
|
OggType type;
|
||||||
|
// The first page as the header information, containing, among other things, what kind of data this ogg holds.
|
||||||
|
ogg_sync_init(&oy);
|
||||||
|
char* buffer = ogg_sync_buffer(&oy, 4096);
|
||||||
|
VorbisReadCallback(buffer, 4096, 1, data);
|
||||||
|
ogg_sync_wrote(&oy, 4096);
|
||||||
|
|
||||||
|
ogg_sync_pageout(&oy, &og);
|
||||||
|
ogg_stream_init(&os, ogg_page_serialno(&og));
|
||||||
|
ogg_stream_pagein(&os, &og);
|
||||||
|
ogg_stream_packetout(&os, &op);
|
||||||
|
|
||||||
|
// Can't use strmp because op.packet isn't a null terminated string.
|
||||||
|
if (memcmp((char*)op.packet, "\x01vorbis", 7) == 0) {
|
||||||
|
type = OggType::Vorbis;
|
||||||
|
} else if (memcmp((char*)op.packet, "OpusHead", 8) == 0) {
|
||||||
|
type = OggType::Opus;
|
||||||
|
} else {
|
||||||
|
type = OggType::None;
|
||||||
|
}
|
||||||
|
ogg_stream_clear(&os);
|
||||||
|
ogg_sync_clear(&oy);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Mp3DecoderWorker(std::shared_ptr<SOH::AudioSample> audioSample, std::shared_ptr<Ship::File> sampleFile) {
|
||||||
|
drmp3 mp3;
|
||||||
|
drwav_uint64 numFrames;
|
||||||
|
drmp3_bool32 ret =
|
||||||
|
drmp3_init_memory(&mp3, sampleFile->Buffer.get()->data(), sampleFile->Buffer.get()->size(), nullptr);
|
||||||
|
numFrames = drmp3_get_pcm_frame_count(&mp3);
|
||||||
|
drwav_uint64 channels = mp3.channels;
|
||||||
|
drwav_uint64 sampleRate = mp3.sampleRate;
|
||||||
|
|
||||||
|
audioSample->sample.sampleAddr = new uint8_t[numFrames * channels * 2];
|
||||||
|
drmp3_read_pcm_frames_s16(&mp3, numFrames, (int16_t*)audioSample->sample.sampleAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void FlacDecoderWorker(std::shared_ptr<SOH::AudioSample> audioSample, std::shared_ptr<Ship::File> sampleFile) {
|
||||||
|
drflac* flac = drflac_open_memory(sampleFile->Buffer.get()->data(), sampleFile->Buffer.get()->size(), nullptr);
|
||||||
|
drflac_uint64 numFrames = flac->totalPCMFrameCount;
|
||||||
|
audioSample->sample.sampleAddr = new uint8_t[numFrames * flac->channels * 2];
|
||||||
|
drflac_read_pcm_frames_s16(flac, numFrames, (int16_t*)audioSample->sample.sampleAddr);
|
||||||
|
drflac_close(flac);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OggDecoderWorker(std::shared_ptr<SOH::AudioSample> audioSample, std::shared_ptr<Ship::File> sampleFile,
|
||||||
|
std::shared_ptr<Ship::ResourceInitData> initData) {
|
||||||
|
OggVorbis_File vf;
|
||||||
|
char dataBuff[4096];
|
||||||
|
long read = 0;
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
OggFileData fileData = {
|
||||||
|
.data = sampleFile->Buffer.get()->data(),
|
||||||
|
.pos = 0,
|
||||||
|
.size = sampleFile->Buffer.get()->size(),
|
||||||
|
};
|
||||||
|
switch (GetOggType(&fileData)) {
|
||||||
|
case OggType::Vorbis: {
|
||||||
|
// Getting the type advanced the position. We are going to use a different library to decode the file which
|
||||||
|
// assumes the file starts at 0
|
||||||
|
fileData.pos = 0;
|
||||||
|
int ret = ov_open_callbacks(&fileData, &vf, nullptr, 0, vorbisCallbacks);
|
||||||
|
|
||||||
|
vorbis_info* vi = ov_info(&vf, -1);
|
||||||
|
|
||||||
|
uint64_t numFrames = ov_pcm_total(&vf, -1);
|
||||||
|
uint64_t sampleRate = vi->rate;
|
||||||
|
uint64_t numChannels = vi->channels;
|
||||||
|
int bitStream = 0;
|
||||||
|
size_t toRead = numFrames * numChannels * 2;
|
||||||
|
audioSample->sample.sampleAddr = new uint8_t[toRead];
|
||||||
|
do {
|
||||||
|
read = ov_read(&vf, dataBuff, 4096, 0, 2, 1, &bitStream);
|
||||||
|
memcpy(audioSample->sample.sampleAddr + pos, dataBuff, read);
|
||||||
|
pos += read;
|
||||||
|
} while (read != 0);
|
||||||
|
ov_clear(&vf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OggType::Opus: {
|
||||||
|
// OPUS encoded data is decoded by the audio driver.
|
||||||
|
audioSample->sample.codec = CODEC_OPUS;
|
||||||
|
audioSample->sample.sampleAddr = new uint8_t[sampleFile->Buffer.get()->size()];
|
||||||
|
memcpy(audioSample->sample.sampleAddr, sampleFile->Buffer.get()->data(), sampleFile->Buffer.get()->size());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case OggType::None: {
|
||||||
|
char buff[2048];
|
||||||
|
snprintf(buff, 2048, "Ogg file %s is not Vorbis or OPUS", initData->Path.c_str());
|
||||||
|
throw std::runtime_error(buff);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
std::shared_ptr<Ship::IResource>
|
std::shared_ptr<Ship::IResource>
|
||||||
|
@ -16,108 +201,155 @@ ResourceFactoryBinaryAudioSampleV2::ReadResource(std::shared_ptr<Ship::File> fil
|
||||||
audioSample->sample.codec = reader->ReadUByte();
|
audioSample->sample.codec = reader->ReadUByte();
|
||||||
audioSample->sample.medium = reader->ReadUByte();
|
audioSample->sample.medium = reader->ReadUByte();
|
||||||
audioSample->sample.unk_bit26 = reader->ReadUByte();
|
audioSample->sample.unk_bit26 = reader->ReadUByte();
|
||||||
audioSample->sample.unk_bit25 = reader->ReadUByte();
|
audioSample->sample.isRelocated = reader->ReadUByte();
|
||||||
audioSample->sample.size = reader->ReadUInt32();
|
audioSample->sample.size = reader->ReadUInt32();
|
||||||
|
|
||||||
audioSample->audioSampleData.reserve(audioSample->sample.size);
|
audioSample->sample.sampleAddr = new uint8_t[audioSample->sample.size];
|
||||||
for (uint32_t i = 0; i < audioSample->sample.size; i++) {
|
for (uint32_t i = 0; i < audioSample->sample.size; i++) {
|
||||||
audioSample->audioSampleData.push_back(reader->ReadUByte());
|
audioSample->sample.sampleAddr[i] = reader->ReadUByte();
|
||||||
}
|
}
|
||||||
audioSample->sample.sampleAddr = audioSample->audioSampleData.data();
|
|
||||||
|
|
||||||
audioSample->loop.start = reader->ReadUInt32();
|
audioSample->loop.start = reader->ReadUInt32();
|
||||||
audioSample->loop.end = reader->ReadUInt32();
|
audioSample->loop.end = reader->ReadUInt32();
|
||||||
audioSample->loop.count = reader->ReadUInt32();
|
audioSample->loop.count = reader->ReadUInt32();
|
||||||
|
|
||||||
audioSample->loopStateCount = reader->ReadUInt32();
|
// This always seems to be 16. Can it be removed in V3?
|
||||||
|
uint32_t loopStateCount = reader->ReadUInt32();
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
audioSample->loop.state[i] = 0;
|
audioSample->loop.state[i] = 0;
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < audioSample->loopStateCount; i++) {
|
for (uint32_t i = 0; i < loopStateCount; i++) {
|
||||||
audioSample->loop.state[i] = reader->ReadInt16();
|
audioSample->loop.state[i] = reader->ReadInt16();
|
||||||
}
|
}
|
||||||
audioSample->sample.loop = &audioSample->loop;
|
audioSample->sample.loop = &audioSample->loop;
|
||||||
|
|
||||||
audioSample->book.order = reader->ReadInt32();
|
audioSample->book.order = reader->ReadInt32();
|
||||||
audioSample->book.npredictors = reader->ReadInt32();
|
audioSample->book.npredictors = reader->ReadInt32();
|
||||||
audioSample->bookDataCount = reader->ReadUInt32();
|
uint32_t bookDataCount = reader->ReadUInt32();
|
||||||
|
|
||||||
audioSample->bookData.reserve(audioSample->bookDataCount);
|
audioSample->book.book = new int16_t[bookDataCount];
|
||||||
for (uint32_t i = 0; i < audioSample->bookDataCount; i++) {
|
|
||||||
audioSample->bookData.push_back(reader->ReadInt16());
|
for (uint32_t i = 0; i < bookDataCount; i++) {
|
||||||
|
audioSample->book.book[i] = reader->ReadInt16();
|
||||||
}
|
}
|
||||||
audioSample->book.book = audioSample->bookData.data();
|
|
||||||
audioSample->sample.book = &audioSample->book;
|
audioSample->sample.book = &audioSample->book;
|
||||||
|
|
||||||
return audioSample;
|
return audioSample;
|
||||||
}
|
}
|
||||||
} // namespace SOH
|
|
||||||
|
|
||||||
/*
|
std::shared_ptr<Ship::IResource>
|
||||||
in ResourceMgr_LoadAudioSample we used to have
|
ResourceFactoryXMLAudioSampleV0::ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
--------------
|
std::shared_ptr<Ship::ResourceInitData> initData) {
|
||||||
if (cachedCustomSFs.find(path) != cachedCustomSFs.end())
|
if (!FileHasValidFormatAndReader(file, initData)) {
|
||||||
return cachedCustomSFs[path];
|
|
||||||
|
|
||||||
SoundFontSample* cSample = ReadCustomSample(path);
|
|
||||||
|
|
||||||
if (cSample != nullptr)
|
|
||||||
return cSample;
|
|
||||||
--------------
|
|
||||||
before the rest of the standard sample reading, this is the ReadCustomSample code we used to have
|
|
||||||
|
|
||||||
extern "C" SoundFontSample* ReadCustomSample(const char* path) {
|
|
||||||
|
|
||||||
if (!ExtensionCache.contains(path))
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
ExtensionEntry entry = ExtensionCache[path];
|
|
||||||
|
|
||||||
auto sampleRaw = Ship::Context::GetInstance()->GetResourceManager()->LoadFile(entry.path);
|
|
||||||
uint32_t* strem = (uint32_t*)sampleRaw->Buffer.get();
|
|
||||||
uint8_t* strem2 = (uint8_t*)strem;
|
|
||||||
|
|
||||||
SoundFontSample* sampleC = new SoundFontSample;
|
|
||||||
|
|
||||||
if (entry.ext == "wav") {
|
|
||||||
drwav_uint32 channels;
|
|
||||||
drwav_uint32 sampleRate;
|
|
||||||
drwav_uint64 totalPcm;
|
|
||||||
drmp3_int16* pcmData =
|
|
||||||
drwav_open_memory_and_read_pcm_frames_s16(strem2, sampleRaw->BufferSize, &channels, &sampleRate, &totalPcm,
|
|
||||||
NULL); sampleC->size = totalPcm; sampleC->sampleAddr = (uint8_t*)pcmData; sampleC->codec = CODEC_S16;
|
|
||||||
|
|
||||||
sampleC->loop = new AdpcmLoop;
|
|
||||||
sampleC->loop->start = 0;
|
|
||||||
sampleC->loop->end = sampleC->size - 1;
|
|
||||||
sampleC->loop->count = 0;
|
|
||||||
sampleC->sampleRateMagicValue = 'RIFF';
|
|
||||||
sampleC->sampleRate = sampleRate;
|
|
||||||
|
|
||||||
cachedCustomSFs[path] = sampleC;
|
|
||||||
return sampleC;
|
|
||||||
} else if (entry.ext == "mp3") {
|
|
||||||
drmp3_config mp3Info;
|
|
||||||
drmp3_uint64 totalPcm;
|
|
||||||
drmp3_int16* pcmData =
|
|
||||||
drmp3_open_memory_and_read_pcm_frames_s16(strem2, sampleRaw->BufferSize, &mp3Info, &totalPcm, NULL);
|
|
||||||
|
|
||||||
sampleC->size = totalPcm * mp3Info.channels * sizeof(short);
|
|
||||||
sampleC->sampleAddr = (uint8_t*)pcmData;
|
|
||||||
sampleC->codec = CODEC_S16;
|
|
||||||
|
|
||||||
sampleC->loop = new AdpcmLoop;
|
|
||||||
sampleC->loop->start = 0;
|
|
||||||
sampleC->loop->end = sampleC->size;
|
|
||||||
sampleC->loop->count = 0;
|
|
||||||
sampleC->sampleRateMagicValue = 'RIFF';
|
|
||||||
sampleC->sampleRate = mp3Info.sampleRate;
|
|
||||||
|
|
||||||
cachedCustomSFs[path] = sampleC;
|
|
||||||
return sampleC;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
auto audioSample = std::make_shared<AudioSample>(initData);
|
||||||
|
auto child = std::get<std::shared_ptr<tinyxml2::XMLDocument>>(file->Reader)->FirstChildElement();
|
||||||
|
const char* customFormatStr = child->Attribute("CustomFormat");
|
||||||
|
memset(&audioSample->sample, 0, sizeof(audioSample->sample));
|
||||||
|
audioSample->sample.isRelocated = 0;
|
||||||
|
audioSample->sample.codec = CodecStrToInt(child->Attribute("Codec"), initData->Path.c_str());
|
||||||
|
audioSample->sample.medium =
|
||||||
|
ResourceFactoryXMLSoundFontV0::MediumStrToInt(child->Attribute("Medium"), initData->Path.c_str());
|
||||||
|
audioSample->sample.unk_bit26 = child->IntAttribute("bit26");
|
||||||
|
|
||||||
|
tinyxml2::XMLElement* loopRoot = child->FirstChildElement("ADPCMLoop");
|
||||||
|
if (loopRoot != nullptr) {
|
||||||
|
size_t i = 0;
|
||||||
|
audioSample->loop.start = loopRoot->UnsignedAttribute("Start");
|
||||||
|
audioSample->loop.end = loopRoot->UnsignedAttribute("End");
|
||||||
|
audioSample->loop.count = loopRoot->UnsignedAttribute("Count");
|
||||||
|
tinyxml2::XMLElement* predictor = loopRoot->FirstChildElement("Predictor");
|
||||||
|
while (predictor != nullptr) {
|
||||||
|
audioSample->loop.state[i++] = predictor->IntAttribute("State");
|
||||||
|
predictor = predictor->NextSiblingElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tinyxml2::XMLElement* bookRoot = child->FirstChildElement("ADPCMBook");
|
||||||
|
if (bookRoot != nullptr) {
|
||||||
|
size_t i = 0;
|
||||||
|
audioSample->book.npredictors = bookRoot->IntAttribute("Npredictors");
|
||||||
|
audioSample->book.order = bookRoot->IntAttribute("Order");
|
||||||
|
tinyxml2::XMLElement* book = bookRoot->FirstChildElement("Book");
|
||||||
|
size_t numBooks = audioSample->book.npredictors * audioSample->book.order * 8;
|
||||||
|
audioSample->book.book = new int16_t[numBooks];
|
||||||
|
while (book != nullptr) {
|
||||||
|
audioSample->book.book[i++] = book->IntAttribute("Page");
|
||||||
|
book = book->NextSiblingElement();
|
||||||
|
}
|
||||||
|
audioSample->sample.book = &audioSample->book;
|
||||||
|
}
|
||||||
|
|
||||||
|
audioSample->sample.loop = &audioSample->loop;
|
||||||
|
size_t size = child->Int64Attribute("Size");
|
||||||
|
audioSample->sample.size = size;
|
||||||
|
|
||||||
|
const char* path = child->Attribute("Path");
|
||||||
|
|
||||||
|
auto sampleFile = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFile(path);
|
||||||
|
audioSample->sample.fileSize = sampleFile->Buffer.get()->size();
|
||||||
|
if (customFormatStr != nullptr) {
|
||||||
|
// Compressed files can take a really long time to decode (~250ms per).
|
||||||
|
// This worked when we tested it (09/04/2024) (Works on my machine)
|
||||||
|
if (strcmp(customFormatStr, "wav") == 0) {
|
||||||
|
drwav wav;
|
||||||
|
drwav_uint64 numFrames;
|
||||||
|
|
||||||
|
drwav_bool32 ret =
|
||||||
|
drwav_init_memory(&wav, sampleFile->Buffer.get()->data(), sampleFile->Buffer.get()->size(), nullptr);
|
||||||
|
|
||||||
|
drwav_get_length_in_pcm_frames(&wav, &numFrames);
|
||||||
|
|
||||||
|
audioSample->tuning = (wav.sampleRate * wav.channels) / 32000.0f;
|
||||||
|
audioSample->sample.sampleAddr = new uint8_t[numFrames * wav.channels * 2];
|
||||||
|
|
||||||
|
drwav_read_pcm_frames_s16(&wav, numFrames, (int16_t*)audioSample->sample.sampleAddr);
|
||||||
|
return audioSample;
|
||||||
|
} else if (strcmp(customFormatStr, "mp3") == 0) {
|
||||||
|
std::thread fileDecoderThread = std::thread(Mp3DecoderWorker, audioSample, sampleFile);
|
||||||
|
fileDecoderThread.detach();
|
||||||
|
return audioSample;
|
||||||
|
} else if (strcmp(customFormatStr, "ogg") == 0) {
|
||||||
|
std::thread fileDecoderThread = std::thread(OggDecoderWorker, audioSample, sampleFile, initData);
|
||||||
|
fileDecoderThread.detach();
|
||||||
|
return audioSample;
|
||||||
|
} else if (strcmp(customFormatStr, "flac") == 0) {
|
||||||
|
std::thread fileDecoderThread = std::thread(FlacDecoderWorker, audioSample, sampleFile);
|
||||||
|
fileDecoderThread.detach();
|
||||||
|
return audioSample;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Not a normal streamed sample. Fallback to the original ADPCM sample to be decoded by the audio engine.
|
||||||
|
audioSample->sample.sampleAddr = new uint8_t[size];
|
||||||
|
// Can't use memcpy due to endianness issues.
|
||||||
|
for (uint32_t i = 0; i < size; i++) {
|
||||||
|
audioSample->sample.sampleAddr[i] = sampleFile->Buffer.get()->data()[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return audioSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
uint8_t ResourceFactoryXMLAudioSampleV0::CodecStrToInt(const char* str, const char* file) {
|
||||||
|
if (strcmp("ADPCM", str) == 0) {
|
||||||
|
return CODEC_ADPCM;
|
||||||
|
} else if (strcmp("S8", str) == 0) {
|
||||||
|
return CODEC_S8;
|
||||||
|
} else if (strcmp("S16MEM", str) == 0) {
|
||||||
|
return CODEC_S16_INMEMORY;
|
||||||
|
} else if (strcmp("ADPCMSMALL", str) == 0) {
|
||||||
|
return CODEC_SMALL_ADPCM;
|
||||||
|
} else if (strcmp("REVERB", str) == 0) {
|
||||||
|
return CODEC_REVERB;
|
||||||
|
} else if (strcmp("S16", str) == 0) {
|
||||||
|
return CODEC_S16;
|
||||||
|
} else {
|
||||||
|
char buff[2048];
|
||||||
|
snprintf(buff, 2048,
|
||||||
|
"Invalid codec in %s. Got %s, expected ADPCM, S8, S16MEM, ADPCMSMALL, REVERB, S16.", file,
|
||||||
|
str);
|
||||||
|
throw std::runtime_error(buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace SOH
|
||||||
|
|
|
@ -2,11 +2,22 @@
|
||||||
|
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
#include "ResourceFactoryBinary.h"
|
#include "ResourceFactoryBinary.h"
|
||||||
|
#include "ResourceFactoryXML.h"
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
class ResourceFactoryBinaryAudioSampleV2 : public Ship::ResourceFactoryBinary {
|
class ResourceFactoryBinaryAudioSampleV2 : public Ship::ResourceFactoryBinary {
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ResourceFactoryXMLAudioSampleV0 : public Ship::ResourceFactoryXML {
|
||||||
|
public:
|
||||||
|
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
|
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static uint8_t CodecStrToInt(const char* str, const char* file);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace SOH
|
} // namespace SOH
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
#include "soh/resource/importer/AudioSequenceFactory.h"
|
#include "soh/resource/importer/AudioSequenceFactory.h"
|
||||||
|
#include "soh/resource/importer/AudioSoundFontFactory.h"
|
||||||
#include "soh/resource/type/AudioSequence.h"
|
#include "soh/resource/type/AudioSequence.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
|
#include "Context.h"
|
||||||
|
#include "resource/archive/Archive.h"
|
||||||
|
#include "BinaryWriter.h"
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
std::shared_ptr<Ship::IResource>
|
std::shared_ptr<Ship::IResource>
|
||||||
ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr<Ship::File> file,
|
ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
|
@ -13,12 +19,11 @@ ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr<Ship::File> f
|
||||||
auto audioSequence = std::make_shared<AudioSequence>(initData);
|
auto audioSequence = std::make_shared<AudioSequence>(initData);
|
||||||
auto reader = std::get<std::shared_ptr<Ship::BinaryReader>>(file->Reader);
|
auto reader = std::get<std::shared_ptr<Ship::BinaryReader>>(file->Reader);
|
||||||
|
|
||||||
audioSequence->sequence.seqDataSize = reader->ReadInt32();
|
audioSequence->sequence.seqDataSize = reader->ReadUInt32();
|
||||||
audioSequence->sequenceData.reserve(audioSequence->sequence.seqDataSize);
|
audioSequence->sequence.seqData = new char[audioSequence->sequence.seqDataSize];
|
||||||
for (uint32_t i = 0; i < audioSequence->sequence.seqDataSize; i++) {
|
for (uint32_t i = 0; i < audioSequence->sequence.seqDataSize; i++) {
|
||||||
audioSequence->sequenceData.push_back(reader->ReadChar());
|
audioSequence->sequence.seqData[i] = reader->ReadChar();
|
||||||
}
|
}
|
||||||
audioSequence->sequence.seqData = audioSequence->sequenceData.data();
|
|
||||||
|
|
||||||
audioSequence->sequence.seqNumber = reader->ReadUByte();
|
audioSequence->sequence.seqNumber = reader->ReadUByte();
|
||||||
audioSequence->sequence.medium = reader->ReadUByte();
|
audioSequence->sequence.medium = reader->ReadUByte();
|
||||||
|
@ -34,4 +39,355 @@ ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr<Ship::File> f
|
||||||
|
|
||||||
return audioSequence;
|
return audioSequence;
|
||||||
}
|
}
|
||||||
} // namespace SOH
|
|
||||||
|
template <typename T> static void WriteInsnOneArg(Ship::BinaryWriter* writer, uint8_t opcode, T arg) {
|
||||||
|
static_assert(std::is_fundamental<T>::value);
|
||||||
|
writer->Write(opcode);
|
||||||
|
writer->Write(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
static void WriteInsnTwoArg(Ship::BinaryWriter* writer, uint8_t opcode, T1 arg1, T2 arg2) {
|
||||||
|
static_assert(std::is_fundamental<T1>::value && std::is_fundamental<T2>::value);
|
||||||
|
writer->Write(opcode);
|
||||||
|
writer->Write(arg1);
|
||||||
|
writer->Write(arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3>
|
||||||
|
static void WriteInsnThreeArg(Ship::BinaryWriter* writer, uint8_t opcode, T1 arg1, T2 arg2, T3 arg3) {
|
||||||
|
static_assert(std::is_fundamental<T1>::value && std::is_fundamental<T2>::value);
|
||||||
|
writer->Write(opcode);
|
||||||
|
writer->Write(arg1);
|
||||||
|
writer->Write(arg2);
|
||||||
|
writer->Write(arg3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteInsnNoArg(Ship::BinaryWriter* writer, uint8_t opcode) {
|
||||||
|
writer->Write(opcode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteLegato(Ship::BinaryWriter* writer) {
|
||||||
|
WriteInsnNoArg(writer, 0xC4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteNoLegato(Ship::BinaryWriter* writer) {
|
||||||
|
WriteInsnNoArg(writer, 0xC5);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteMuteBhv(Ship::BinaryWriter* writer, uint8_t arg) {
|
||||||
|
WriteInsnOneArg(writer, 0xD3, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteMuteScale(Ship::BinaryWriter* writer, uint8_t arg) {
|
||||||
|
WriteInsnOneArg(writer, 0xD5, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteInitchan(Ship::BinaryWriter* writer, uint16_t channels) {
|
||||||
|
WriteInsnOneArg(writer, 0xD7, channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteLdchan(Ship::BinaryWriter* writer, uint8_t channel, uint16_t offset) {
|
||||||
|
WriteInsnOneArg(writer, 0x90 | channel, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteVolSHeader(Ship::BinaryWriter* writer, uint8_t vol) {
|
||||||
|
WriteInsnOneArg(writer, 0xDB, vol);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteVolCHeader(Ship::BinaryWriter* writer, uint8_t vol) {
|
||||||
|
WriteInsnOneArg(writer, 0xDF, vol);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteTempo(Ship::BinaryWriter* writer, uint8_t tempo) {
|
||||||
|
WriteInsnOneArg(writer, 0xDD, tempo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteJump(Ship::BinaryWriter* writer, uint16_t offset) {
|
||||||
|
WriteInsnOneArg(writer, 0xFB, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteDisablecan(Ship::BinaryWriter* writer, uint16_t channels) {
|
||||||
|
WriteInsnOneArg(writer, 0xD6, channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteNoshort(Ship::BinaryWriter* writer) {
|
||||||
|
WriteInsnNoArg(writer, 0xC4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteLdlayer(Ship::BinaryWriter* writer, uint8_t layer, uint16_t offset) {
|
||||||
|
WriteInsnOneArg(writer, 0x88 | layer, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WritePan(Ship::BinaryWriter* writer, uint8_t pan) {
|
||||||
|
WriteInsnOneArg(writer, 0xDD, pan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteBend(Ship::BinaryWriter* writer, uint8_t bend) {
|
||||||
|
WriteInsnOneArg(writer, 0xD3, bend);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteInstrument(Ship::BinaryWriter* writer, uint8_t instrument) {
|
||||||
|
WriteInsnOneArg(writer, 0xC1, instrument);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteTranspose(Ship::BinaryWriter* writer, int8_t transpose) {
|
||||||
|
WriteInsnOneArg(writer, 0xC2, transpose);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteDelay(Ship::BinaryWriter* writer, uint16_t delay) {
|
||||||
|
if (delay > 0x7F) {
|
||||||
|
WriteInsnOneArg(writer, 0xFD, static_cast<uint16_t>(delay | 0x8000));
|
||||||
|
} else {
|
||||||
|
WriteInsnOneArg(writer, 0xFD, static_cast<uint8_t>(delay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> static void WriteLDelay(Ship::BinaryWriter* writer, T delay) {
|
||||||
|
WriteInsnOneArg(writer, 0xC0, delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> static void WriteNotedv(Ship::BinaryWriter* writer, uint8_t note, T delay, uint8_t velocity) {
|
||||||
|
WriteInsnTwoArg(writer, note, delay, velocity);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteNotedvg(Ship::BinaryWriter* writer, uint8_t note, uint16_t delay, uint8_t velocity, uint8_t gateTime) {
|
||||||
|
if (delay > 0x7F) {
|
||||||
|
WriteInsnThreeArg(writer, note, static_cast<uint16_t>(delay | 0x8000), velocity, gateTime);
|
||||||
|
} else {
|
||||||
|
WriteInsnThreeArg(writer, note, static_cast<uint8_t>(delay), velocity, gateTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteMonoSingleSeq(Ship::BinaryWriter* writer, uint16_t delay, uint8_t tempo, bool looped) {
|
||||||
|
uint16_t channelStart;
|
||||||
|
uint16_t channelPlaceholderOff;
|
||||||
|
uint16_t loopPoint;
|
||||||
|
uint16_t layerPlaceholderOff;
|
||||||
|
uint16_t layerStart;
|
||||||
|
if (looped) {
|
||||||
|
delay = 0x7FFF;
|
||||||
|
}
|
||||||
|
// Write seq header
|
||||||
|
|
||||||
|
// These two values are always the same in OOT and MM
|
||||||
|
WriteMuteBhv(writer, 0x20);
|
||||||
|
WriteMuteScale(writer, 0x32);
|
||||||
|
|
||||||
|
// We only have one channel
|
||||||
|
WriteInitchan(writer, 0b11);
|
||||||
|
// Store the current position so we can write the address of the channel when we are ready.
|
||||||
|
channelPlaceholderOff = writer->GetBaseAddress();
|
||||||
|
// Store the current position so we can loop here after the song ends.
|
||||||
|
loopPoint = writer->GetBaseAddress();
|
||||||
|
WriteLdchan(writer, 0, 0); // Fill in the actual address later
|
||||||
|
|
||||||
|
WriteVolSHeader(writer, 127); // Max volume
|
||||||
|
WriteTempo(writer, tempo);
|
||||||
|
|
||||||
|
WriteDelay(writer, delay);
|
||||||
|
if (looped) {
|
||||||
|
WriteJump(writer, loopPoint);
|
||||||
|
}
|
||||||
|
WriteDisablecan(writer, 0b11);
|
||||||
|
writer->Write(static_cast<uint8_t>(0xFF));
|
||||||
|
|
||||||
|
// Fill in the ldchan from before
|
||||||
|
channelStart = writer->GetBaseAddress();
|
||||||
|
writer->Seek(channelPlaceholderOff, Ship::SeekOffsetType::Start);
|
||||||
|
WriteLdchan(writer, 0, channelStart);
|
||||||
|
writer->Seek(channelStart, Ship::SeekOffsetType::Start);
|
||||||
|
|
||||||
|
// Channel header
|
||||||
|
layerPlaceholderOff = writer->GetBaseAddress();
|
||||||
|
WriteNoshort(writer);
|
||||||
|
WriteLdlayer(writer, 0, 0);
|
||||||
|
WritePan(writer, 64);
|
||||||
|
WriteVolCHeader(writer, 127); // Max volume
|
||||||
|
WriteBend(writer, 0);
|
||||||
|
WriteInstrument(writer, 0);
|
||||||
|
WriteDelay(writer, delay);
|
||||||
|
writer->Write(static_cast<uint8_t>(0xFF));
|
||||||
|
|
||||||
|
layerStart = writer->GetBaseAddress();
|
||||||
|
writer->Seek(layerPlaceholderOff, Ship::SeekOffsetType::Start);
|
||||||
|
WriteLdlayer(writer, 0, layerStart);
|
||||||
|
writer->Seek(layerStart, Ship::SeekOffsetType::Start);
|
||||||
|
|
||||||
|
// Note layer
|
||||||
|
WriteLegato(writer);
|
||||||
|
WriteNotedvg(writer, 39, 0x7FFF - 1, static_cast<uint8_t>(0x7F), static_cast<uint8_t>(1));
|
||||||
|
writer->Write(static_cast<uint8_t>(0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteStereoSingleSeq(Ship::BinaryWriter* writer, uint16_t delay, uint8_t tempo, bool looped) {
|
||||||
|
uint16_t lChannelStart;
|
||||||
|
uint16_t rChannelStart;
|
||||||
|
uint16_t channelPlaceholderOff;
|
||||||
|
uint16_t loopPoint;
|
||||||
|
uint16_t lLayerPlaceholderOff;
|
||||||
|
uint16_t rLayerPlaceholderOff;
|
||||||
|
uint16_t lLayerOffset;
|
||||||
|
uint16_t rLayerOffset;
|
||||||
|
|
||||||
|
uint16_t layerStart;
|
||||||
|
// Write seq header
|
||||||
|
if (looped) {
|
||||||
|
delay = 0x7FFF;
|
||||||
|
}
|
||||||
|
// These two values are always the same in OOT and MM
|
||||||
|
WriteMuteBhv(writer, 0x20);
|
||||||
|
WriteMuteScale(writer, 0x32);
|
||||||
|
|
||||||
|
// We only have one channel
|
||||||
|
WriteInitchan(writer, 0b11);
|
||||||
|
// Store the current position so we can write the address of the channel when we are ready.
|
||||||
|
channelPlaceholderOff = writer->GetBaseAddress();
|
||||||
|
// Store the current position so we can loop here after the song ends.
|
||||||
|
loopPoint = writer->GetBaseAddress();
|
||||||
|
// Left note channel
|
||||||
|
WriteLdchan(writer, 0, 0); // Fill in the actual address later
|
||||||
|
// Right note channel
|
||||||
|
WriteLdchan(writer, 1, 0); // Fill in the actual address later
|
||||||
|
|
||||||
|
WriteVolSHeader(writer, 127); // Max volume
|
||||||
|
WriteTempo(writer, tempo);
|
||||||
|
|
||||||
|
WriteDelay(writer, delay);
|
||||||
|
if (looped) {
|
||||||
|
WriteJump(writer, loopPoint);
|
||||||
|
}
|
||||||
|
WriteDisablecan(writer, 0b11);
|
||||||
|
writer->Write(static_cast<uint8_t>(0xFF));
|
||||||
|
|
||||||
|
lChannelStart = writer->GetBaseAddress();
|
||||||
|
// Left Channel header
|
||||||
|
WriteNoshort(writer);
|
||||||
|
lLayerPlaceholderOff = writer->GetBaseAddress();
|
||||||
|
WriteLdlayer(writer, 0, 0);
|
||||||
|
WritePan(writer, 0);
|
||||||
|
WriteVolCHeader(writer, 127); // Max volume
|
||||||
|
WriteBend(writer, 0);
|
||||||
|
WriteInstrument(writer, 0);
|
||||||
|
WriteDelay(writer, delay);
|
||||||
|
writer->Write(static_cast<uint8_t>(0xFF));
|
||||||
|
|
||||||
|
rChannelStart = writer->GetBaseAddress();
|
||||||
|
// Right Channel header
|
||||||
|
WriteNoshort(writer);
|
||||||
|
rLayerPlaceholderOff = writer->GetBaseAddress();
|
||||||
|
WriteLdlayer(writer, 1, 0);
|
||||||
|
WritePan(writer, 127);
|
||||||
|
WriteVolCHeader(writer, 127); // Max volume
|
||||||
|
WriteBend(writer, 0);
|
||||||
|
WriteInstrument(writer, 1);
|
||||||
|
WriteDelay(writer, delay);
|
||||||
|
writer->Write(static_cast<uint8_t>(0xFF));
|
||||||
|
uint16_t placeHolder = writer->GetBaseAddress();
|
||||||
|
writer->Seek(channelPlaceholderOff, Ship::SeekOffsetType::Start);
|
||||||
|
WriteLdchan(writer, 0, lChannelStart);
|
||||||
|
WriteLdchan(writer, 1, rChannelStart);
|
||||||
|
writer->Seek(placeHolder, Ship::SeekOffsetType::Start);
|
||||||
|
|
||||||
|
// Left Note layer
|
||||||
|
lLayerOffset = writer->GetBaseAddress();
|
||||||
|
WriteLegato(writer);
|
||||||
|
WriteNotedvg(writer, 39, 0x7FFF - 1, static_cast<uint8_t>(0x7F), static_cast<uint8_t>(1));
|
||||||
|
writer->Write(static_cast<uint8_t>(0xFF));
|
||||||
|
|
||||||
|
// Right Note layer
|
||||||
|
rLayerOffset = writer->GetBaseAddress();
|
||||||
|
WriteLegato(writer);
|
||||||
|
WriteNotedvg(writer, 39, 0x7FFF - 1, static_cast<uint8_t>(0x7F), static_cast<uint8_t>(1));
|
||||||
|
writer->Write(static_cast<uint8_t>(0xFF));
|
||||||
|
|
||||||
|
writer->Seek(lLayerPlaceholderOff, Ship::SeekOffsetType::Start);
|
||||||
|
WriteLdlayer(writer, 0, lLayerOffset);
|
||||||
|
writer->Seek(rLayerPlaceholderOff, Ship::SeekOffsetType::Start);
|
||||||
|
WriteLdlayer(writer, 1, rLayerOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Ship::IResource>
|
||||||
|
ResourceFactoryXMLAudioSequenceV0::ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
|
std::shared_ptr<Ship::ResourceInitData> initData) {
|
||||||
|
if (!FileHasValidFormatAndReader(file, initData)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sequence = std::make_shared<AudioSequence>(initData);
|
||||||
|
auto child = std::get<std::shared_ptr<tinyxml2::XMLDocument>>(file->Reader)->FirstChildElement();
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
sequence->sequence.medium =
|
||||||
|
ResourceFactoryXMLSoundFontV0::MediumStrToInt(child->Attribute("Medium"), initData->Path.c_str());
|
||||||
|
sequence->sequence.cachePolicy =
|
||||||
|
ResourceFactoryXMLSoundFontV0::CachePolicyToInt(child->Attribute("CachePolicy"), initData->Path.c_str());
|
||||||
|
sequence->sequence.seqDataSize = child->IntAttribute("Size");
|
||||||
|
sequence->sequence.seqNumber = child->IntAttribute("Index");
|
||||||
|
bool streamed = child->BoolAttribute("Streamed");
|
||||||
|
|
||||||
|
memset(sequence->sequence.fonts, 0, sizeof(sequence->sequence.fonts));
|
||||||
|
|
||||||
|
tinyxml2::XMLElement* fontsElement = child->FirstChildElement();
|
||||||
|
tinyxml2::XMLElement* fontElement = fontsElement->FirstChildElement();
|
||||||
|
while (fontElement != nullptr) {
|
||||||
|
sequence->sequence.fonts[i] = fontElement->IntAttribute("FontIdx");
|
||||||
|
fontElement = fontElement->NextSiblingElement();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
sequence->sequence.numFonts = i;
|
||||||
|
|
||||||
|
const char* path = child->Attribute("Path");
|
||||||
|
std::shared_ptr<Ship::File> seqFile;
|
||||||
|
if (path != nullptr) {
|
||||||
|
seqFile = Ship::Context::GetInstance()->GetResourceManager()->GetArchiveManager()->LoadFile(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!streamed) {
|
||||||
|
sequence->sequence.seqDataSize = seqFile->Buffer.get()->size();
|
||||||
|
sequence->sequence.seqData = new char[seqFile->Buffer.get()->size()];
|
||||||
|
memcpy(sequence->sequence.seqData, seqFile->Buffer.get()->data(), seqFile->Buffer.get()->size());
|
||||||
|
} else {
|
||||||
|
// setting numFonts to -1 tells the game's audio engine the sound font to used is CRC64 encoded in the font
|
||||||
|
// indicies.
|
||||||
|
sequence->sequence.numFonts = -1;
|
||||||
|
if (path != nullptr) {
|
||||||
|
sequence->sequence.seqDataSize = seqFile->Buffer.get()->size();
|
||||||
|
sequence->sequence.seqData = new char[seqFile->Buffer.get()->size()];
|
||||||
|
memcpy(sequence->sequence.seqData, seqFile->Buffer.get()->data(), seqFile->Buffer.get()->size());
|
||||||
|
} else {
|
||||||
|
unsigned int length = child->UnsignedAttribute("Length");
|
||||||
|
bool looped = child->BoolAttribute("Looped", true);
|
||||||
|
bool stereo = child->BoolAttribute("Stereo", false);
|
||||||
|
Ship::BinaryWriter writer = Ship::BinaryWriter();
|
||||||
|
writer.SetEndianness(Ship::Endianness::Big);
|
||||||
|
|
||||||
|
// 1 second worth of ticks can be found by using `ticks = 60 / (bpm * 48)`
|
||||||
|
// Get the number of ticks per second and then divide the length by this number to get the number of ticks
|
||||||
|
// for the song.
|
||||||
|
constexpr uint8_t TEMPO = 1;
|
||||||
|
constexpr float TEMPO_F = TEMPO;
|
||||||
|
// Use floats for this first calculation so we can round up
|
||||||
|
float delayF = length / (60.0f / (TEMPO_F * 48.0f));
|
||||||
|
// Convert to u16. This way this value is encoded changes depending on the value.
|
||||||
|
// It can be at most 0xFFFF so store it in a u16 for now.
|
||||||
|
uint16_t delay;
|
||||||
|
if (delayF >= 65535.0f) {
|
||||||
|
delay = 0x7FFF;
|
||||||
|
} else {
|
||||||
|
delay = delayF;
|
||||||
|
}
|
||||||
|
if (stereo) {
|
||||||
|
WriteStereoSingleSeq(&writer, delay, TEMPO, looped);
|
||||||
|
} else {
|
||||||
|
WriteMonoSingleSeq(&writer, delay, TEMPO, looped);
|
||||||
|
}
|
||||||
|
sequence->sequence.seqDataSize = writer.ToVector().size();
|
||||||
|
sequence->sequence.seqData = new char[sequence->sequence.seqDataSize];
|
||||||
|
memcpy(sequence->sequence.seqData, writer.ToVector().data(), sequence->sequence.seqDataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sequence;
|
||||||
|
}
|
||||||
|
} // namespace SOH
|
|
@ -2,11 +2,19 @@
|
||||||
|
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
#include "ResourceFactoryBinary.h"
|
#include "ResourceFactoryBinary.h"
|
||||||
|
#include "ResourceFactoryXML.h"
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
class ResourceFactoryBinaryAudioSequenceV2 : public Ship::ResourceFactoryBinary {
|
class ResourceFactoryBinaryAudioSequenceV2 : public Ship::ResourceFactoryBinary {
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ResourceFactoryXMLAudioSequenceV0 : public Ship::ResourceFactoryXML {
|
||||||
|
public:
|
||||||
|
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
|
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace SOH
|
} // namespace SOH
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#include "soh/resource/importer/AudioSoundFontFactory.h"
|
#include "soh/resource/importer/AudioSoundFontFactory.h"
|
||||||
#include "soh/resource/type/AudioSoundFont.h"
|
#include "soh/resource/type/AudioSoundFont.h"
|
||||||
#include "spdlog/spdlog.h"
|
#include "z64.h"
|
||||||
#include "libultraship/libultraship.h"
|
#include "z64audio.h"
|
||||||
|
#include "Context.h"
|
||||||
|
#include "resource/archive/Archive.h"
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
std::shared_ptr<Ship::IResource>
|
std::shared_ptr<Ship::IResource>
|
||||||
|
@ -35,117 +37,115 @@ ResourceFactoryBinaryAudioSoundFontV2::ReadResource(std::shared_ptr<Ship::File>
|
||||||
audioSoundFont->soundFont.numSfx = soundEffectCount;
|
audioSoundFont->soundFont.numSfx = soundEffectCount;
|
||||||
|
|
||||||
// 🥁 DRUMS 🥁
|
// 🥁 DRUMS 🥁
|
||||||
audioSoundFont->drums.reserve(audioSoundFont->soundFont.numDrums);
|
// audioSoundFont->drums.reserve(audioSoundFont->soundFont.numDrums);
|
||||||
audioSoundFont->drumAddresses.reserve(audioSoundFont->soundFont.numDrums);
|
audioSoundFont->drumAddresses.reserve(audioSoundFont->soundFont.numDrums);
|
||||||
for (uint32_t i = 0; i < audioSoundFont->soundFont.numDrums; i++) {
|
for (uint32_t i = 0; i < audioSoundFont->soundFont.numDrums; i++) {
|
||||||
Drum drum;
|
Drum* drum = new Drum;
|
||||||
drum.releaseRate = reader->ReadUByte();
|
drum->releaseRate = reader->ReadUByte();
|
||||||
drum.pan = reader->ReadUByte();
|
drum->pan = reader->ReadUByte();
|
||||||
drum.loaded = reader->ReadUByte();
|
drum->loaded = reader->ReadUByte();
|
||||||
drum.loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFont
|
drum->loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFontByName
|
||||||
|
|
||||||
uint32_t envelopeCount = reader->ReadUInt32();
|
uint32_t envelopeCount = reader->ReadUInt32();
|
||||||
audioSoundFont->drumEnvelopeCounts.push_back(envelopeCount);
|
drum->envelope = new AdsrEnvelope[envelopeCount];
|
||||||
std::vector<AdsrEnvelope> drumEnvelopes;
|
for (uint32_t j = 0; j < envelopeCount; j++) {
|
||||||
drumEnvelopes.reserve(audioSoundFont->drumEnvelopeCounts[i]);
|
|
||||||
for (uint32_t j = 0; j < audioSoundFont->drumEnvelopeCounts.back(); j++) {
|
|
||||||
AdsrEnvelope env;
|
|
||||||
|
|
||||||
int16_t delay = reader->ReadInt16();
|
int16_t delay = reader->ReadInt16();
|
||||||
int16_t arg = reader->ReadInt16();
|
int16_t arg = reader->ReadInt16();
|
||||||
|
|
||||||
env.delay = BE16SWAP(delay);
|
drum->envelope[j].delay = BE16SWAP(delay);
|
||||||
env.arg = BE16SWAP(arg);
|
drum->envelope[j].arg = BE16SWAP(arg);
|
||||||
|
|
||||||
drumEnvelopes.push_back(env);
|
|
||||||
}
|
}
|
||||||
audioSoundFont->drumEnvelopeArrays.push_back(drumEnvelopes);
|
|
||||||
drum.envelope = audioSoundFont->drumEnvelopeArrays.back().data();
|
|
||||||
|
|
||||||
bool hasSample = reader->ReadInt8();
|
bool hasSample = reader->ReadInt8();
|
||||||
std::string sampleFileName = reader->ReadString();
|
std::string sampleFileName = reader->ReadString();
|
||||||
drum.sound.tuning = reader->ReadFloat();
|
drum->sound.tuning = reader->ReadFloat();
|
||||||
|
|
||||||
if (sampleFileName.empty()) {
|
if (sampleFileName.empty()) {
|
||||||
drum.sound.sample = nullptr;
|
drum->sound.sample = nullptr;
|
||||||
} else {
|
} else {
|
||||||
auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
|
auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
|
||||||
drum.sound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
drum->sound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
audioSoundFont->drums.push_back(drum);
|
// audioSoundFont->drums.push_back(drum);
|
||||||
audioSoundFont->drumAddresses.push_back(&audioSoundFont->drums.back());
|
// BENTODO clean this up in V3.
|
||||||
|
if (drum->sound.sample == nullptr) {
|
||||||
|
delete[] drum->envelope;
|
||||||
|
delete drum;
|
||||||
|
audioSoundFont->drumAddresses.push_back(nullptr);
|
||||||
|
} else {
|
||||||
|
audioSoundFont->drumAddresses.push_back(drum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
audioSoundFont->soundFont.drums = audioSoundFont->drumAddresses.data();
|
audioSoundFont->soundFont.drums = audioSoundFont->drumAddresses.data();
|
||||||
|
|
||||||
// 🎺🎻🎷🎸🎹 INSTRUMENTS 🎹🎸🎷🎻🎺
|
// 🎺🎻🎷🎸🎹 INSTRUMENTS 🎹🎸🎷🎻🎺
|
||||||
audioSoundFont->instruments.reserve(audioSoundFont->soundFont.numInstruments);
|
|
||||||
for (uint32_t i = 0; i < audioSoundFont->soundFont.numInstruments; i++) {
|
for (uint32_t i = 0; i < audioSoundFont->soundFont.numInstruments; i++) {
|
||||||
Instrument instrument;
|
Instrument* instrument = new Instrument;
|
||||||
|
|
||||||
uint8_t isValidEntry = reader->ReadUByte();
|
uint8_t isValidEntry = reader->ReadUByte();
|
||||||
instrument.loaded = reader->ReadUByte();
|
instrument->loaded = reader->ReadUByte();
|
||||||
instrument.loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFont
|
instrument->loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFontByName
|
||||||
|
|
||||||
instrument.normalRangeLo = reader->ReadUByte();
|
instrument->normalRangeLo = reader->ReadUByte();
|
||||||
instrument.normalRangeHi = reader->ReadUByte();
|
instrument->normalRangeHi = reader->ReadUByte();
|
||||||
instrument.releaseRate = reader->ReadUByte();
|
instrument->releaseRate = reader->ReadUByte();
|
||||||
|
|
||||||
uint32_t envelopeCount = reader->ReadInt32();
|
uint32_t envelopeCount = reader->ReadInt32();
|
||||||
audioSoundFont->instrumentEnvelopeCounts.push_back(envelopeCount);
|
instrument->envelope = new AdsrEnvelope[envelopeCount];
|
||||||
std::vector<AdsrEnvelope> instrumentEnvelopes;
|
|
||||||
for (uint32_t j = 0; j < audioSoundFont->instrumentEnvelopeCounts.back(); j++) {
|
|
||||||
AdsrEnvelope env;
|
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < envelopeCount; j++) {
|
||||||
int16_t delay = reader->ReadInt16();
|
int16_t delay = reader->ReadInt16();
|
||||||
int16_t arg = reader->ReadInt16();
|
int16_t arg = reader->ReadInt16();
|
||||||
|
|
||||||
env.delay = BE16SWAP(delay);
|
instrument->envelope[j].delay = BE16SWAP(delay);
|
||||||
env.arg = BE16SWAP(arg);
|
instrument->envelope[j].arg = BE16SWAP(arg);
|
||||||
|
|
||||||
instrumentEnvelopes.push_back(env);
|
|
||||||
}
|
}
|
||||||
audioSoundFont->instrumentEnvelopeArrays.push_back(instrumentEnvelopes);
|
|
||||||
instrument.envelope = audioSoundFont->instrumentEnvelopeArrays.back().data();
|
|
||||||
|
|
||||||
bool hasLowNoteSoundFontEntry = reader->ReadInt8();
|
bool hasLowNoteSoundFontEntry = reader->ReadInt8();
|
||||||
if (hasLowNoteSoundFontEntry) {
|
if (hasLowNoteSoundFontEntry) {
|
||||||
bool hasSampleRef = reader->ReadInt8();
|
bool hasSampleRef = reader->ReadInt8();
|
||||||
std::string sampleFileName = reader->ReadString();
|
std::string sampleFileName = reader->ReadString();
|
||||||
instrument.lowNotesSound.tuning = reader->ReadFloat();
|
instrument->lowNotesSound.tuning = reader->ReadFloat();
|
||||||
auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
|
auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
|
||||||
instrument.lowNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
instrument->lowNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||||
} else {
|
} else {
|
||||||
instrument.lowNotesSound.sample = nullptr;
|
instrument->lowNotesSound.sample = nullptr;
|
||||||
instrument.lowNotesSound.tuning = 0;
|
instrument->lowNotesSound.tuning = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNormalNoteSoundFontEntry = reader->ReadInt8();
|
bool hasNormalNoteSoundFontEntry = reader->ReadInt8();
|
||||||
if (hasNormalNoteSoundFontEntry) {
|
if (hasNormalNoteSoundFontEntry) {
|
||||||
|
// BENTODO remove in V3
|
||||||
bool hasSampleRef = reader->ReadInt8();
|
bool hasSampleRef = reader->ReadInt8();
|
||||||
std::string sampleFileName = reader->ReadString();
|
std::string sampleFileName = reader->ReadString();
|
||||||
instrument.normalNotesSound.tuning = reader->ReadFloat();
|
instrument->normalNotesSound.tuning = reader->ReadFloat();
|
||||||
auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
|
auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
|
||||||
instrument.normalNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
instrument->normalNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||||
} else {
|
} else {
|
||||||
instrument.normalNotesSound.sample = nullptr;
|
instrument->normalNotesSound.sample = nullptr;
|
||||||
instrument.normalNotesSound.tuning = 0;
|
instrument->normalNotesSound.tuning = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasHighNoteSoundFontEntry = reader->ReadInt8();
|
bool hasHighNoteSoundFontEntry = reader->ReadInt8();
|
||||||
if (hasHighNoteSoundFontEntry) {
|
if (hasHighNoteSoundFontEntry) {
|
||||||
bool hasSampleRef = reader->ReadInt8();
|
bool hasSampleRef = reader->ReadInt8();
|
||||||
std::string sampleFileName = reader->ReadString();
|
std::string sampleFileName = reader->ReadString();
|
||||||
instrument.highNotesSound.tuning = reader->ReadFloat();
|
instrument->highNotesSound.tuning = reader->ReadFloat();
|
||||||
auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
|
auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleFileName.c_str());
|
||||||
instrument.highNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
instrument->highNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||||
} else {
|
} else {
|
||||||
instrument.highNotesSound.sample = nullptr;
|
instrument->highNotesSound.sample = nullptr;
|
||||||
instrument.highNotesSound.tuning = 0;
|
instrument->highNotesSound.tuning = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
audioSoundFont->instruments.push_back(instrument);
|
if (isValidEntry) {
|
||||||
audioSoundFont->instrumentAddresses.push_back(isValidEntry ? &audioSoundFont->instruments.back() : nullptr);
|
audioSoundFont->instrumentAddresses.push_back(instrument);
|
||||||
|
} else {
|
||||||
|
delete[] instrument->envelope;
|
||||||
|
delete instrument;
|
||||||
|
audioSoundFont->instrumentAddresses.push_back(nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
audioSoundFont->soundFont.instruments = audioSoundFont->instrumentAddresses.data();
|
audioSoundFont->soundFont.instruments = audioSoundFont->instrumentAddresses.data();
|
||||||
|
|
||||||
|
@ -169,4 +169,302 @@ ResourceFactoryBinaryAudioSoundFontV2::ReadResource(std::shared_ptr<Ship::File>
|
||||||
|
|
||||||
return audioSoundFont;
|
return audioSoundFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t ResourceFactoryXMLSoundFontV0::MediumStrToInt(const char* str, const char* file) {
|
||||||
|
if (!strcmp("Ram", str)) {
|
||||||
|
return MEDIUM_RAM;
|
||||||
|
} else if (!strcmp("Unk", str)) {
|
||||||
|
return MEDIUM_UNK;
|
||||||
|
} else if (!strcmp("Cart", str)) {
|
||||||
|
return MEDIUM_CART;
|
||||||
|
} else if (!strcmp("Disk", str)) {
|
||||||
|
return MEDIUM_DISK_DRIVE;
|
||||||
|
// 4 is skipped
|
||||||
|
} else {
|
||||||
|
char buff[2048];
|
||||||
|
snprintf(buff, 2048, "Bad medium value in %s. Got %s, expected Ram, Unk, Cart, or Disk.", file, str);
|
||||||
|
throw std::runtime_error(buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t ResourceFactoryXMLSoundFontV0::CachePolicyToInt(const char* str, const char* file) {
|
||||||
|
if (!strcmp("Temporary", str)) {
|
||||||
|
return CACHE_TEMPORARY;
|
||||||
|
} else if (!strcmp("Persistent", str)) {
|
||||||
|
return CACHE_PERSISTENT;
|
||||||
|
} else if (!strcmp("Either", str)) {
|
||||||
|
return CACHE_EITHER;
|
||||||
|
} else if (!strcmp("Permanent", str)) {
|
||||||
|
return CACHE_PERMANENT;
|
||||||
|
} else {
|
||||||
|
char buff[2048];
|
||||||
|
snprintf(buff, 2048,
|
||||||
|
"Bad cache policy value in %s. Got %s, expected Temporary, Persistent, Either, or Permanent.", file,
|
||||||
|
str);
|
||||||
|
throw std::runtime_error(buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceFactoryXMLSoundFontV0::ParseDrums(AudioSoundFont* soundFont, tinyxml2::XMLElement* element) {
|
||||||
|
element = element->FirstChildElement();
|
||||||
|
// No drums
|
||||||
|
if (element == nullptr) {
|
||||||
|
soundFont->soundFont.drums = nullptr;
|
||||||
|
soundFont->soundFont.numDrums = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
int patch = element->IntAttribute("Patches", -1);
|
||||||
|
Drum* drum;
|
||||||
|
if (patch != -1) {
|
||||||
|
drum = soundFont->drumAddresses[patch];
|
||||||
|
} else {
|
||||||
|
drum = new Drum;
|
||||||
|
}
|
||||||
|
std::vector<AdsrEnvelope> envelopes;
|
||||||
|
drum->releaseRate = element->IntAttribute("ReleaseRate");
|
||||||
|
drum->pan = element->IntAttribute("Pan");
|
||||||
|
drum->loaded = element->IntAttribute("Loaded");
|
||||||
|
drum->sound.tuning = element->FloatAttribute("Tuning");
|
||||||
|
const char* sampleStr = element->Attribute("SampleRef");
|
||||||
|
|
||||||
|
if (sampleStr != nullptr && sampleStr[0] != 0) {
|
||||||
|
auto res = Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleStr);
|
||||||
|
drum->sound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||||
|
} else {
|
||||||
|
drum->sound.sample = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
element = element->FirstChildElement();
|
||||||
|
if (!strcmp(element->Name(), "Envelopes")) {
|
||||||
|
// element = (tinyxml2::XMLElement*)element->FirstChildElement();
|
||||||
|
unsigned int envCount = 0;
|
||||||
|
envelopes = ParseEnvelopes(soundFont, element, &envCount);
|
||||||
|
element = (tinyxml2::XMLElement*)element->Parent();
|
||||||
|
soundFont->drumEnvelopeArrays.push_back(envelopes);
|
||||||
|
// If we are applying a patch the envelopes are already allocated
|
||||||
|
// TODO revert this if we enable editing envelopes in a patch
|
||||||
|
if (patch == -1) {
|
||||||
|
drum->envelope = new AdsrEnvelope[envelopes.size()];
|
||||||
|
}
|
||||||
|
memcpy(drum->envelope, envelopes.data(), envelopes.size() * sizeof(AdsrEnvelope));
|
||||||
|
} else {
|
||||||
|
drum->envelope = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drum->sound.sample == nullptr) {
|
||||||
|
soundFont->drumAddresses.push_back(nullptr);
|
||||||
|
} else {
|
||||||
|
soundFont->drumAddresses.push_back(drum);
|
||||||
|
}
|
||||||
|
|
||||||
|
element = element->NextSiblingElement();
|
||||||
|
} while (element != nullptr);
|
||||||
|
|
||||||
|
soundFont->soundFont.numDrums = soundFont->drumAddresses.size();
|
||||||
|
soundFont->soundFont.drums = soundFont->drumAddresses.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceFactoryXMLSoundFontV0::ParseInstruments(AudioSoundFont* soundFont, tinyxml2::XMLElement* element) {
|
||||||
|
element = element->FirstChildElement();
|
||||||
|
if (element == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
int patch = element->IntAttribute("Patches", -1);
|
||||||
|
Instrument* instrument;
|
||||||
|
// Same as drums, if applying a patch, don't re-allocate and clear.
|
||||||
|
if (patch != -1) {
|
||||||
|
instrument = soundFont->instrumentAddresses[patch];
|
||||||
|
} else {
|
||||||
|
instrument = new Instrument;
|
||||||
|
memset(instrument, 0, sizeof(Instrument));
|
||||||
|
}
|
||||||
|
unsigned int envCount = 0;
|
||||||
|
std::vector<AdsrEnvelope> envelopes;
|
||||||
|
|
||||||
|
int isValid = element->BoolAttribute("IsValid");
|
||||||
|
instrument->loaded = element->IntAttribute("Loaded");
|
||||||
|
instrument->normalRangeLo = element->IntAttribute("NormalRangeLo");
|
||||||
|
instrument->normalRangeHi = element->IntAttribute("NormalRangeHi");
|
||||||
|
instrument->releaseRate = element->IntAttribute("ReleaseRate");
|
||||||
|
tinyxml2::XMLElement* instrumentElement = element->FirstChildElement();
|
||||||
|
tinyxml2::XMLElement* instrumentElementCopy = instrumentElement;
|
||||||
|
|
||||||
|
if (instrumentElement != nullptr && !strcmp(instrumentElement->Name(), "Envelopes")) {
|
||||||
|
envelopes = ParseEnvelopes(soundFont, instrumentElement, &envCount);
|
||||||
|
if (patch == -1) {
|
||||||
|
instrument->envelope = new AdsrEnvelope[envelopes.size()];
|
||||||
|
}
|
||||||
|
memcpy(instrument->envelope, envelopes.data(), envelopes.size() * sizeof(AdsrEnvelope));
|
||||||
|
instrumentElement = instrumentElement->NextSiblingElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instrumentElement != nullptr && !strcmp("LowNotesSound", instrumentElement->Name())) {
|
||||||
|
instrument->lowNotesSound.tuning = instrumentElement->FloatAttribute("Tuning");
|
||||||
|
const char* sampleStr = instrumentElement->Attribute("SampleRef");
|
||||||
|
if (sampleStr != nullptr && sampleStr[0] != 0) {
|
||||||
|
std::shared_ptr<SOH::AudioSample> res = static_pointer_cast<SOH::AudioSample>(
|
||||||
|
Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleStr));
|
||||||
|
if (res->tuning != -1.0f) {
|
||||||
|
instrument->lowNotesSound.tuning = res->tuning;
|
||||||
|
}
|
||||||
|
instrument->lowNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||||
|
}
|
||||||
|
instrumentElement = instrumentElement->NextSiblingElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instrumentElement != nullptr && !strcmp("NormalNotesSound", instrumentElement->Name())) {
|
||||||
|
instrument->normalNotesSound.tuning = instrumentElement->FloatAttribute("Tuning");
|
||||||
|
const char* sampleStr = instrumentElement->Attribute("SampleRef");
|
||||||
|
if (sampleStr != nullptr && sampleStr[0] != 0) {
|
||||||
|
std::shared_ptr<SOH::AudioSample> res = static_pointer_cast<SOH::AudioSample>(
|
||||||
|
Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleStr));
|
||||||
|
if (res->tuning != -1.0f) {
|
||||||
|
instrument->normalNotesSound.tuning = res->tuning;
|
||||||
|
}
|
||||||
|
instrument->normalNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||||
|
}
|
||||||
|
instrumentElement = instrumentElement->NextSiblingElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instrumentElement != nullptr && !strcmp("HighNotesSound", instrumentElement->Name())) {
|
||||||
|
instrument->highNotesSound.tuning = instrumentElement->FloatAttribute("Tuning");
|
||||||
|
const char* sampleStr = instrumentElement->Attribute("SampleRef");
|
||||||
|
if (sampleStr != nullptr && sampleStr[0] != 0) {
|
||||||
|
std::shared_ptr<SOH::AudioSample> res = static_pointer_cast<SOH::AudioSample>(
|
||||||
|
Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleStr));
|
||||||
|
if (res->tuning != -1.0f) {
|
||||||
|
instrument->highNotesSound.tuning = res->tuning;
|
||||||
|
}
|
||||||
|
instrument->highNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||||
|
}
|
||||||
|
instrumentElement = instrumentElement->NextSiblingElement();
|
||||||
|
}
|
||||||
|
// Don't add it to the list if applying a patch
|
||||||
|
if (patch == -1) {
|
||||||
|
soundFont->instrumentAddresses.push_back(instrument);
|
||||||
|
}
|
||||||
|
element = instrumentElementCopy;
|
||||||
|
element = (tinyxml2::XMLElement*)element->Parent();
|
||||||
|
element = element->NextSiblingElement();
|
||||||
|
} while (element != nullptr);
|
||||||
|
|
||||||
|
soundFont->soundFont.instruments = soundFont->instrumentAddresses.data();
|
||||||
|
soundFont->soundFont.numInstruments = soundFont->instrumentAddresses.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceFactoryXMLSoundFontV0::ParseSfxTable(AudioSoundFont* soundFont, tinyxml2::XMLElement* element) {
|
||||||
|
size_t count = element->IntAttribute("Count");
|
||||||
|
|
||||||
|
element = element->FirstChildElement();
|
||||||
|
|
||||||
|
while (element != nullptr) {
|
||||||
|
int patch = element->IntAttribute("Patches", -1);
|
||||||
|
|
||||||
|
SoundFontSound sound = {};
|
||||||
|
|
||||||
|
const char* sampleStr = element->Attribute("SampleRef");
|
||||||
|
// Insert an empty sound effect. The game assumes the empty slots are
|
||||||
|
// filled so we can't just skip them
|
||||||
|
if (sampleStr == nullptr)
|
||||||
|
goto skip;
|
||||||
|
|
||||||
|
sound.tuning = element->FloatAttribute("Tuning");
|
||||||
|
if (sampleStr[0] != 0) {
|
||||||
|
auto res = static_pointer_cast<SOH::AudioSample>(
|
||||||
|
Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(sampleStr));
|
||||||
|
if (res->tuning != -1.0f) {
|
||||||
|
sound.tuning = res->tuning;
|
||||||
|
}
|
||||||
|
sound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||||
|
}
|
||||||
|
skip:
|
||||||
|
element = element->NextSiblingElement();
|
||||||
|
if (patch != -1) {
|
||||||
|
soundFont->soundEffects[patch] = sound;
|
||||||
|
} else {
|
||||||
|
soundFont->soundEffects.push_back(sound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
soundFont->soundFont.soundEffects = soundFont->soundEffects.data();
|
||||||
|
soundFont->soundFont.numSfx = soundFont->soundEffects.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<AdsrEnvelope> SOH::ResourceFactoryXMLSoundFontV0::ParseEnvelopes(AudioSoundFont* soundFont,
|
||||||
|
tinyxml2::XMLElement* element,
|
||||||
|
unsigned int* count) {
|
||||||
|
std::vector<AdsrEnvelope> envelopes;
|
||||||
|
unsigned int total = 0;
|
||||||
|
element = element->FirstChildElement("Envelope");
|
||||||
|
while (element != nullptr) {
|
||||||
|
AdsrEnvelope env = {
|
||||||
|
.delay = (s16)element->IntAttribute("Delay"),
|
||||||
|
.arg = (s16)element->IntAttribute("Arg"),
|
||||||
|
};
|
||||||
|
env.delay = BSWAP16(env.delay);
|
||||||
|
env.arg = BSWAP16(env.arg);
|
||||||
|
envelopes.emplace_back(env);
|
||||||
|
element = element->NextSiblingElement("Envelope");
|
||||||
|
total++;
|
||||||
|
}
|
||||||
|
*count = total;
|
||||||
|
return envelopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Ship::IResource>
|
||||||
|
ResourceFactoryXMLSoundFontV0::ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
|
std::shared_ptr<Ship::ResourceInitData> initData) {
|
||||||
|
if (!FileHasValidFormatAndReader(file, initData)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto child = std::get<std::shared_ptr<tinyxml2::XMLDocument>>(file->Reader)->FirstChildElement();
|
||||||
|
const char* patch = child->Attribute("Patches");
|
||||||
|
std::shared_ptr<Ship::IResource> sf;
|
||||||
|
std::shared_ptr<AudioSoundFont> audioSoundFont;
|
||||||
|
// If we are patching an existing SF, load the original, otherwise create and clear a new one.
|
||||||
|
if (patch != nullptr) {
|
||||||
|
std::string origName = "audio/fonts/";
|
||||||
|
origName += patch;
|
||||||
|
audioSoundFont = dynamic_pointer_cast<AudioSoundFont>(
|
||||||
|
Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(origName));
|
||||||
|
} else {
|
||||||
|
audioSoundFont = std::make_shared<AudioSoundFont>(initData);
|
||||||
|
memset(&audioSoundFont->soundFont, 0, sizeof(audioSoundFont->soundFont));
|
||||||
|
}
|
||||||
|
// Header data
|
||||||
|
audioSoundFont->soundFont.fntIndex = child->IntAttribute("Num", 0);
|
||||||
|
|
||||||
|
const char* mediumStr = child->Attribute("Medium");
|
||||||
|
audioSoundFont->medium = MediumStrToInt(mediumStr, initData->Path.c_str());
|
||||||
|
|
||||||
|
const char* cachePolicyStr = child->Attribute("CachePolicy");
|
||||||
|
audioSoundFont->cachePolicy = CachePolicyToInt(cachePolicyStr, initData->Path.c_str());
|
||||||
|
|
||||||
|
audioSoundFont->data1 = child->IntAttribute("Data1");
|
||||||
|
audioSoundFont->data2 = child->IntAttribute("Data2");
|
||||||
|
audioSoundFont->data3 = child->IntAttribute("Data3");
|
||||||
|
|
||||||
|
audioSoundFont->soundFont.sampleBankId1 = audioSoundFont->data1 >> 8;
|
||||||
|
audioSoundFont->soundFont.sampleBankId2 = audioSoundFont->data1 & 0xFF;
|
||||||
|
|
||||||
|
child = (tinyxml2::XMLElement*)child->FirstChildElement();
|
||||||
|
|
||||||
|
while (child != nullptr) {
|
||||||
|
const char* name = child->Name();
|
||||||
|
|
||||||
|
if (!strcmp(name, "Drums")) {
|
||||||
|
ParseDrums(audioSoundFont.get(), child);
|
||||||
|
} else if (!strcmp(name, "Instruments")) {
|
||||||
|
ParseInstruments(audioSoundFont.get(), child);
|
||||||
|
} else if (!strcmp(name, "SfxTable")) {
|
||||||
|
ParseSfxTable(audioSoundFont.get(), child);
|
||||||
|
}
|
||||||
|
child = child->NextSiblingElement();
|
||||||
|
}
|
||||||
|
return audioSoundFont;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SOH
|
} // namespace SOH
|
||||||
|
|
|
@ -2,11 +2,29 @@
|
||||||
|
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
#include "ResourceFactoryBinary.h"
|
#include "ResourceFactoryBinary.h"
|
||||||
|
#include "ResourceFactoryXML.h"
|
||||||
|
#include "soh/resource/type/AudioSoundFont.h"
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
class ResourceFactoryBinaryAudioSoundFontV2 : public Ship::ResourceFactoryBinary {
|
class ResourceFactoryBinaryAudioSoundFontV2 : public Ship::ResourceFactoryBinary {
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ResourceFactoryXMLSoundFontV0 : public Ship::ResourceFactoryXML {
|
||||||
|
public:
|
||||||
|
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||||
|
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
||||||
|
static int8_t MediumStrToInt(const char* str, const char* file);
|
||||||
|
static int8_t CachePolicyToInt(const char* str, const char* file);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ParseDrums(AudioSoundFont* soundFont, tinyxml2::XMLElement* element);
|
||||||
|
void ParseInstruments(AudioSoundFont* soundFont, tinyxml2::XMLElement* element);
|
||||||
|
void ParseSfxTable(AudioSoundFont* soundFont, tinyxml2::XMLElement* element);
|
||||||
|
std::vector<AdsrEnvelope> ParseEnvelopes(AudioSoundFont* soundFont, tinyxml2::XMLElement* element,
|
||||||
|
unsigned int* count);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace SOH
|
} // namespace SOH
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
#include "AudioSample.h"
|
#include "AudioSample.h"
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
Sample* AudioSample::GetPointer() {
|
AudioSample::~AudioSample() {
|
||||||
return &sample;
|
if (sample.book != nullptr && sample.book->book != nullptr) {
|
||||||
}
|
delete[] sample.book->book;
|
||||||
|
}
|
||||||
|
if (sample.sampleAddr != nullptr) {
|
||||||
|
delete[] sample.sampleAddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Sample* AudioSample::GetPointer() {
|
||||||
|
return &sample;
|
||||||
|
}
|
||||||
|
|
||||||
size_t AudioSample::GetPointerSize() {
|
size_t AudioSample::GetPointerSize() {
|
||||||
return sizeof(Sample);
|
return sizeof(Sample);
|
||||||
}
|
}
|
||||||
} // namespace SOH
|
} // namespace SOH
|
|
@ -1,62 +1,60 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
#include <libultraship/libultra/types.h>
|
#include <libultraship/libultra/types.h>
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x00 */ uintptr_t start;
|
/* 0x00 */ u32 start;
|
||||||
/* 0x04 */ uintptr_t end;
|
/* 0x04 */ u32 end;
|
||||||
/* 0x08 */ u32 count;
|
/* 0x08 */ u32 count;
|
||||||
/* 0x0C */ char unk_0C[0x4];
|
/* 0x0C */ char unk_0C[0x4];
|
||||||
/* 0x10 */ s16 state[16]; // only exists if count != 0. 8-byte aligned
|
/* 0x10 */ s16 state[16]; // only exists if count != 0. 8-byte aligned
|
||||||
} AdpcmLoop; // size = 0x30 (or 0x10)
|
} AdpcmLoop; // size = 0x30 (or 0x10)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x00 */ s32 order;
|
/* 0x00 */ s32 order;
|
||||||
/* 0x04 */ s32 npredictors;
|
/* 0x04 */ s32 npredictors;
|
||||||
/* 0x08 */ s16* book; // size 8 * order * npredictors. 8-byte aligned
|
/* 0x08 */ s16* book; // size 8 * order * npredictors. 8-byte aligned
|
||||||
} AdpcmBook; // s
|
} AdpcmBook; // s
|
||||||
|
|
||||||
typedef struct {
|
typedef struct Sample {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
/* 0x00 */ u32 codec : 4;
|
///* 0x0 */ u32 unk_0 : 1;
|
||||||
/* 0x00 */ u32 medium : 2;
|
/* 0x0 */ u32 codec : 4; // The state of compression or decompression, See `SampleCodec`
|
||||||
/* 0x00 */ u32 unk_bit26 : 1;
|
/* 0x0 */ u32 medium : 2; // Medium where sample is currently stored. See `SampleMedium`
|
||||||
/* 0x00 */ u32 unk_bit25 : 1; // this has been named isRelocated in zret
|
/* 0x0 */ u32 unk_bit26 : 1;
|
||||||
/* 0x01 */ u32 size : 24;
|
/* 0x0 */ u32 isRelocated : 1; // Has the sample header been relocated (offsets to pointers)
|
||||||
|
};
|
||||||
|
u32 asU32;
|
||||||
};
|
};
|
||||||
u32 asU32;
|
/* 0x1 */ u32 size; // Size of the sample
|
||||||
|
u32 fileSize;
|
||||||
|
/* 0x4 */ u8* sampleAddr; // Raw sample data. Offset from the start of the sample bank or absolute address to either
|
||||||
|
// rom or ram
|
||||||
|
/* 0x8 */ AdpcmLoop*
|
||||||
|
loop; // Adpcm loop parameters used by the sample. Offset from the start of the sound font / pointer to ram
|
||||||
|
/* 0xC */ AdpcmBook*
|
||||||
|
book; // Adpcm book parameters used by the sample. Offset from the start of the sound font / pointer to ram
|
||||||
|
} Sample; // size = 0x10
|
||||||
|
|
||||||
|
class AudioSample : public Ship::Resource<Sample> {
|
||||||
|
public:
|
||||||
|
using Resource::Resource;
|
||||||
|
|
||||||
|
AudioSample() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {
|
||||||
|
}
|
||||||
|
~AudioSample();
|
||||||
|
|
||||||
|
Sample* GetPointer();
|
||||||
|
size_t GetPointerSize();
|
||||||
|
|
||||||
|
Sample sample;
|
||||||
|
AdpcmLoop loop;
|
||||||
|
AdpcmBook book;
|
||||||
|
// Only applies to streamed audio
|
||||||
|
float tuning = -1.0f;
|
||||||
};
|
};
|
||||||
|
}; // namespace SOH
|
||||||
/* 0x04 */ u8* sampleAddr;
|
|
||||||
/* 0x08 */ AdpcmLoop* loop;
|
|
||||||
/* 0x0C */ AdpcmBook* book;
|
|
||||||
u32 sampleRateMagicValue; // For wav samples only...
|
|
||||||
s32 sampleRate; // For wav samples only...
|
|
||||||
} Sample; // size = 0x10
|
|
||||||
|
|
||||||
class AudioSample : public Ship::Resource<Sample> {
|
|
||||||
public:
|
|
||||||
using Resource::Resource;
|
|
||||||
|
|
||||||
AudioSample() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
Sample* GetPointer();
|
|
||||||
size_t GetPointerSize();
|
|
||||||
|
|
||||||
Sample sample;
|
|
||||||
std::vector<uint8_t> audioSampleData;
|
|
||||||
|
|
||||||
AdpcmLoop loop;
|
|
||||||
uint32_t loopStateCount;
|
|
||||||
|
|
||||||
AdpcmBook book;
|
|
||||||
uint32_t bookDataCount;
|
|
||||||
std::vector<int16_t> bookData;
|
|
||||||
};
|
|
||||||
}; // namespace SOH
|
|
|
@ -2,11 +2,17 @@
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
|
|
||||||
Sequence* AudioSequence::GetPointer() {
|
Sequence* AudioSequence::GetPointer() {
|
||||||
return &sequence;
|
return &sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AudioSequence::GetPointerSize() {
|
size_t AudioSequence::GetPointerSize() {
|
||||||
return sizeof(Sequence);
|
return sizeof(Sequence);
|
||||||
}
|
}
|
||||||
} // namespace SOH
|
|
||||||
|
AudioSequence::~AudioSequence() {
|
||||||
|
delete[] sequence.seqData;
|
||||||
|
sequence.seqData = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace SOH
|
|
@ -1,33 +1,31 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
#include <libultraship/libultra/types.h>
|
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* seqData;
|
char* seqData;
|
||||||
int32_t seqDataSize;
|
uint32_t seqDataSize;
|
||||||
uint16_t seqNumber;
|
uint16_t seqNumber;
|
||||||
uint8_t medium;
|
uint8_t medium;
|
||||||
uint8_t cachePolicy;
|
uint8_t cachePolicy;
|
||||||
int32_t numFonts;
|
uint32_t numFonts;
|
||||||
uint8_t fonts[16];
|
uint8_t fonts[16];
|
||||||
} Sequence;
|
} Sequence;
|
||||||
|
|
||||||
class AudioSequence : public Ship::Resource<Sequence> {
|
class AudioSequence : public Ship::Resource<Sequence> {
|
||||||
public:
|
public:
|
||||||
using Resource::Resource;
|
using Resource::Resource;
|
||||||
|
|
||||||
AudioSequence() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {
|
AudioSequence() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {
|
||||||
}
|
}
|
||||||
|
~AudioSequence();
|
||||||
|
|
||||||
Sequence* GetPointer();
|
Sequence* GetPointer();
|
||||||
size_t GetPointerSize();
|
size_t GetPointerSize();
|
||||||
|
|
||||||
Sequence sequence;
|
Sequence sequence;
|
||||||
std::vector<char> sequenceData;
|
};
|
||||||
};
|
}; // namespace SOH
|
||||||
}; // namespace SOH
|
|
|
@ -1,11 +1,28 @@
|
||||||
#include "AudioSoundFont.h"
|
#include "AudioSoundFont.h"
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
SoundFont* AudioSoundFont::GetPointer() {
|
|
||||||
return &soundFont;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t AudioSoundFont::GetPointerSize() {
|
AudioSoundFont::~AudioSoundFont() {
|
||||||
return sizeof(SoundFont);
|
for (auto i : instrumentAddresses) {
|
||||||
}
|
if (i != nullptr) {
|
||||||
} // namespace SOH
|
delete[] i->envelope;
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto d : drumAddresses) {
|
||||||
|
if (d != nullptr) {
|
||||||
|
delete[] d->envelope;
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SoundFont* AudioSoundFont::GetPointer() {
|
||||||
|
return &soundFont;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t AudioSoundFont::GetPointerSize() {
|
||||||
|
return sizeof(SoundFont);
|
||||||
|
}
|
||||||
|
} // namespace SOH
|
|
@ -8,78 +8,74 @@
|
||||||
|
|
||||||
namespace SOH {
|
namespace SOH {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x0 */ s16 delay;
|
/* 0x0 */ s16 delay;
|
||||||
/* 0x2 */ s16 arg;
|
/* 0x2 */ s16 arg;
|
||||||
} AdsrEnvelope; // size = 0x4
|
} AdsrEnvelope; // size = 0x4
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x00 */ Sample* sample;
|
/* 0x00 */ Sample* sample;
|
||||||
/* 0x04 */ union {
|
/* 0x04 */ union {
|
||||||
u32 tuningAsU32;
|
u32 tuningAsU32;
|
||||||
f32 tuning; // frequency scale factor
|
f32 tuning; // frequency scale factor
|
||||||
|
};
|
||||||
|
} SoundFontSound; // size = 0x8
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* 0x00 */ u8 loaded;
|
||||||
|
/* 0x01 */ u8 normalRangeLo;
|
||||||
|
/* 0x02 */ u8 normalRangeHi;
|
||||||
|
/* 0x03 */ u8 releaseRate;
|
||||||
|
/* 0x04 */ AdsrEnvelope* envelope;
|
||||||
|
/* 0x08 */ SoundFontSound lowNotesSound;
|
||||||
|
/* 0x10 */ SoundFontSound normalNotesSound;
|
||||||
|
/* 0x18 */ SoundFontSound highNotesSound;
|
||||||
|
} Instrument; // size = 0x20
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* 0x00 */ u8 releaseRate;
|
||||||
|
/* 0x01 */ u8 pan;
|
||||||
|
/* 0x02 */ u8 loaded;
|
||||||
|
/* 0x04 */ SoundFontSound sound;
|
||||||
|
/* 0x14 */ AdsrEnvelope* envelope;
|
||||||
|
} Drum; // size = 0x14
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* 0x00 */ u8 numInstruments;
|
||||||
|
/* 0x01 */ u8 numDrums;
|
||||||
|
/* 0x02 */ u8 sampleBankId1;
|
||||||
|
/* 0x03 */ u8 sampleBankId2;
|
||||||
|
/* 0x04 */ u16 numSfx;
|
||||||
|
/* 0x08 */ Instrument** instruments;
|
||||||
|
/* 0x0C */ Drum** drums;
|
||||||
|
/* 0x10 */ SoundFontSound* soundEffects;
|
||||||
|
s32 fntIndex;
|
||||||
|
} SoundFont; // size = 0x14
|
||||||
|
|
||||||
|
class AudioSoundFont : public Ship::Resource<SoundFont> {
|
||||||
|
public:
|
||||||
|
using Resource::Resource;
|
||||||
|
|
||||||
|
AudioSoundFont() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {
|
||||||
|
}
|
||||||
|
~AudioSoundFont();
|
||||||
|
|
||||||
|
SoundFont* GetPointer();
|
||||||
|
size_t GetPointerSize();
|
||||||
|
|
||||||
|
int8_t medium;
|
||||||
|
int8_t cachePolicy;
|
||||||
|
uint16_t data1;
|
||||||
|
uint16_t data2;
|
||||||
|
uint16_t data3;
|
||||||
|
|
||||||
|
std::vector<Drum*> drumAddresses;
|
||||||
|
std::vector<std::vector<AdsrEnvelope>> drumEnvelopeArrays;
|
||||||
|
|
||||||
|
std::vector<Instrument*> instrumentAddresses;
|
||||||
|
|
||||||
|
std::vector<SoundFontSound> soundEffects;
|
||||||
|
|
||||||
|
SoundFont soundFont;
|
||||||
};
|
};
|
||||||
} SoundFontSound; // size = 0x8
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* 0x00 */ u8 loaded;
|
|
||||||
/* 0x01 */ u8 normalRangeLo;
|
|
||||||
/* 0x02 */ u8 normalRangeHi;
|
|
||||||
/* 0x03 */ u8 releaseRate;
|
|
||||||
/* 0x04 */ AdsrEnvelope* envelope;
|
|
||||||
/* 0x08 */ SoundFontSound lowNotesSound;
|
|
||||||
/* 0x10 */ SoundFontSound normalNotesSound;
|
|
||||||
/* 0x18 */ SoundFontSound highNotesSound;
|
|
||||||
} Instrument; // size = 0x20
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* 0x00 */ u8 releaseRate;
|
|
||||||
/* 0x01 */ u8 pan;
|
|
||||||
/* 0x02 */ u8 loaded;
|
|
||||||
/* 0x04 */ SoundFontSound sound;
|
|
||||||
/* 0x14 */ AdsrEnvelope* envelope;
|
|
||||||
} Drum; // size = 0x14
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
/* 0x00 */ u8 numInstruments;
|
|
||||||
/* 0x01 */ u8 numDrums;
|
|
||||||
/* 0x02 */ u8 sampleBankId1;
|
|
||||||
/* 0x03 */ u8 sampleBankId2;
|
|
||||||
/* 0x04 */ u16 numSfx;
|
|
||||||
/* 0x08 */ Instrument** instruments;
|
|
||||||
/* 0x0C */ Drum** drums;
|
|
||||||
/* 0x10 */ SoundFontSound* soundEffects;
|
|
||||||
s32 fntIndex;
|
|
||||||
} SoundFont; // size = 0x14
|
|
||||||
|
|
||||||
class AudioSoundFont : public Ship::Resource<SoundFont> {
|
|
||||||
public:
|
|
||||||
using Resource::Resource;
|
|
||||||
|
|
||||||
AudioSoundFont() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundFont* GetPointer();
|
|
||||||
size_t GetPointerSize();
|
|
||||||
|
|
||||||
int8_t medium;
|
|
||||||
int8_t cachePolicy;
|
|
||||||
uint16_t data1;
|
|
||||||
uint16_t data2;
|
|
||||||
uint16_t data3;
|
|
||||||
|
|
||||||
std::vector<Drum> drums;
|
|
||||||
std::vector<Drum*> drumAddresses;
|
|
||||||
std::vector<uint32_t> drumEnvelopeCounts;
|
|
||||||
std::vector<std::vector<AdsrEnvelope>> drumEnvelopeArrays;
|
|
||||||
|
|
||||||
std::vector<Instrument> instruments;
|
|
||||||
std::vector<Instrument*> instrumentAddresses;
|
|
||||||
std::vector<uint32_t> instrumentEnvelopeCounts;
|
|
||||||
std::vector<std::vector<AdsrEnvelope>> instrumentEnvelopeArrays;
|
|
||||||
|
|
||||||
std::vector<SoundFontSound> soundEffects;
|
|
||||||
|
|
||||||
SoundFont soundFont;
|
|
||||||
};
|
|
||||||
}; // namespace SOH
|
}; // namespace SOH
|
||||||
|
|
|
@ -41,7 +41,7 @@ void func_800DDE3C(void) {
|
||||||
void AudioHeap_ResetLoadStatus(void) {
|
void AudioHeap_ResetLoadStatus(void) {
|
||||||
s32 i;
|
s32 i;
|
||||||
|
|
||||||
for (i = 0; i < 0x30; i++) {
|
for (i = 0; i < fontMapSize; i++) {
|
||||||
if (gAudioContext.fontLoadStatus[i] != 5) {
|
if (gAudioContext.fontLoadStatus[i] != 5) {
|
||||||
gAudioContext.fontLoadStatus[i] = 0;
|
gAudioContext.fontLoadStatus[i] = 0;
|
||||||
}
|
}
|
||||||
|
@ -940,7 +940,7 @@ void AudioHeap_Init(void) {
|
||||||
reverb->sample.sampleAddr = (u8*)reverb->leftRingBuf;
|
reverb->sample.sampleAddr = (u8*)reverb->leftRingBuf;
|
||||||
reverb->loop.start = 0;
|
reverb->loop.start = 0;
|
||||||
reverb->loop.count = 1;
|
reverb->loop.count = 1;
|
||||||
reverb->loop.end = reverb->windowSize;
|
reverb->loop.loopEnd = reverb->windowSize;
|
||||||
|
|
||||||
if (reverb->downsampleRate != 1) {
|
if (reverb->downsampleRate != 1) {
|
||||||
reverb->unk_0E = 0x8000 / reverb->downsampleRate;
|
reverb->unk_0E = 0x8000 / reverb->downsampleRate;
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
#include "soh/Enhancements/audio/AudioCollection.h"
|
#include "soh/Enhancements/audio/AudioCollection.h"
|
||||||
#include "soh/Enhancements/audio/AudioEditor.h"
|
#include "soh/Enhancements/audio/AudioEditor.h"
|
||||||
#include "soh/ResourceManagerHelpers.h"
|
#include "soh/ResourceManagerHelpers.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define strdup _strdup
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MK_ASYNC_MSG(retData, tableType, id, status) (((retData) << 24) | ((tableType) << 16) | ((id) << 8) | (status))
|
#define MK_ASYNC_MSG(retData, tableType, id, status) (((retData) << 24) | ((tableType) << 16) | ((id) << 8) | (status))
|
||||||
#define ASYNC_TBLTYPE(v) ((u8)(v >> 16))
|
#define ASYNC_TBLTYPE(v) ((u8)(v >> 16))
|
||||||
|
@ -82,7 +86,8 @@ char** sequenceMap;
|
||||||
size_t sequenceMapSize;
|
size_t sequenceMapSize;
|
||||||
// A map of authentic sequence IDs to their cache policies, for use with sequence swapping.
|
// A map of authentic sequence IDs to their cache policies, for use with sequence swapping.
|
||||||
u8 seqCachePolicyMap[MAX_AUTHENTIC_SEQID];
|
u8 seqCachePolicyMap[MAX_AUTHENTIC_SEQID];
|
||||||
char* fontMap[256];
|
size_t fontMapSize;
|
||||||
|
char** fontMap;
|
||||||
|
|
||||||
uintptr_t fontStart;
|
uintptr_t fontStart;
|
||||||
uint32_t fontOffsets[8192];
|
uint32_t fontOffsets[8192];
|
||||||
|
@ -419,7 +424,7 @@ void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1) {
|
||||||
s32 AudioLoad_SyncLoadSample(SoundFontSample* sample, s32 fontId) {
|
s32 AudioLoad_SyncLoadSample(SoundFontSample* sample, s32 fontId) {
|
||||||
void* sampleAddr;
|
void* sampleAddr;
|
||||||
|
|
||||||
if (sample->unk_bit25 == 1) {
|
if (sample->isRelocated == 1) {
|
||||||
if (sample->medium != MEDIUM_RAM) {
|
if (sample->medium != MEDIUM_RAM) {
|
||||||
sampleAddr = AudioHeap_AllocSampleCache(sample->size, fontId, (void*)sample->sampleAddr, sample->medium,
|
sampleAddr = AudioHeap_AllocSampleCache(sample->size, fontId, (void*)sample->sampleAddr, sample->medium,
|
||||||
CACHE_PERSISTENT);
|
CACHE_PERSISTENT);
|
||||||
|
@ -701,7 +706,7 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||||
|
|
||||||
sampleBankId1 = sf->sampleBankId1;
|
sampleBankId1 = sf->sampleBankId1;
|
||||||
sampleBankId2 = sf->sampleBankId2;
|
sampleBankId2 = sf->sampleBankId2;
|
||||||
|
@ -759,7 +764,7 @@ uintptr_t AudioLoad_SyncLoad(u32 tableType, u32 id, s32* didAllocate) {
|
||||||
cachePolicy = sData.cachePolicy;
|
cachePolicy = sData.cachePolicy;
|
||||||
romAddr = 0;
|
romAddr = 0;
|
||||||
} else if (tableType == FONT_TABLE) {
|
} else if (tableType == FONT_TABLE) {
|
||||||
fnt = ResourceMgr_LoadAudioSoundFont(fontMap[id]);
|
fnt = ResourceMgr_LoadAudioSoundFontByName(fontMap[id]);
|
||||||
size = sizeof(SoundFont);
|
size = sizeof(SoundFont);
|
||||||
medium = 2;
|
medium = 2;
|
||||||
cachePolicy = 0;
|
cachePolicy = 0;
|
||||||
|
@ -887,6 +892,7 @@ AudioTable* AudioLoad_GetLoadTable(s32 tableType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo) {
|
void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo) {
|
||||||
|
return;
|
||||||
uintptr_t reloc;
|
uintptr_t reloc;
|
||||||
uintptr_t reloc2;
|
uintptr_t reloc2;
|
||||||
Instrument* inst;
|
Instrument* inst;
|
||||||
|
@ -898,7 +904,7 @@ void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo
|
||||||
s32 numInstruments = 0;
|
s32 numInstruments = 0;
|
||||||
s32 numSfx = 0;
|
s32 numSfx = 0;
|
||||||
|
|
||||||
sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||||
numDrums = sf->numDrums;
|
numDrums = sf->numDrums;
|
||||||
numInstruments = sf->numInstruments;
|
numInstruments = sf->numInstruments;
|
||||||
numSfx = sf->numSfx;
|
numSfx = sf->numSfx;
|
||||||
|
@ -1247,12 +1253,13 @@ int strcmp_sort(const void* str1, const void* str2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioLoad_Init(void* heap, size_t heapSize) {
|
void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||||
char pad[0x48];
|
s32 pad1[9];
|
||||||
s32 numFonts;
|
s32 numFonts;
|
||||||
void* temp_v0_3;
|
s32 pad2[2];
|
||||||
|
u8* audioCtxPtr;
|
||||||
|
void* addr;
|
||||||
s32 i;
|
s32 i;
|
||||||
u64* heapP;
|
s32 j;
|
||||||
s16* u2974p;
|
|
||||||
|
|
||||||
D_801755D0 = NULL;
|
D_801755D0 = NULL;
|
||||||
gAudioContext.resetTimer = 0;
|
gAudioContext.resetTimer = 0;
|
||||||
|
@ -1266,10 +1273,12 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||||
gAudioContext.unk_2960 = 20.03042f;
|
gAudioContext.unk_2960 = 20.03042f;
|
||||||
gAudioContext.refreshRate = 50;
|
gAudioContext.refreshRate = 50;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OS_TV_MPAL:
|
case OS_TV_MPAL:
|
||||||
gAudioContext.unk_2960 = 16.546f;
|
gAudioContext.unk_2960 = 16.546f;
|
||||||
gAudioContext.refreshRate = 60;
|
gAudioContext.refreshRate = 60;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OS_TV_NTSC:
|
case OS_TV_NTSC:
|
||||||
default:
|
default:
|
||||||
gAudioContext.unk_2960 = 16.713f;
|
gAudioContext.unk_2960 = 16.713f;
|
||||||
|
@ -1278,7 +1287,7 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||||
|
|
||||||
Audio_InitMesgQueues();
|
Audio_InitMesgQueues();
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < ARRAY_COUNT(gAudioContext.aiBufLengths); i++) {
|
||||||
gAudioContext.aiBufLengths[i] = 0xA0;
|
gAudioContext.aiBufLengths[i] = 0xA0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1289,12 +1298,14 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||||
gAudioContext.currTask = NULL;
|
gAudioContext.currTask = NULL;
|
||||||
gAudioContext.rspTask[0].task.t.data_size = 0;
|
gAudioContext.rspTask[0].task.t.data_size = 0;
|
||||||
gAudioContext.rspTask[1].task.t.data_size = 0;
|
gAudioContext.rspTask[1].task.t.data_size = 0;
|
||||||
|
|
||||||
osCreateMesgQueue(&gAudioContext.syncDmaQueue, &gAudioContext.syncDmaMesg, 1);
|
osCreateMesgQueue(&gAudioContext.syncDmaQueue, &gAudioContext.syncDmaMesg, 1);
|
||||||
osCreateMesgQueue(&gAudioContext.currAudioFrameDmaQueue, gAudioContext.currAudioFrameDmaMesgBuf, 0x40);
|
osCreateMesgQueue(&gAudioContext.currAudioFrameDmaQueue, gAudioContext.currAudioFrameDmaMesgBuf,
|
||||||
|
ARRAY_COUNT(gAudioContext.currAudioFrameDmaMesgBuf));
|
||||||
osCreateMesgQueue(&gAudioContext.externalLoadQueue, gAudioContext.externalLoadMesgBuf,
|
osCreateMesgQueue(&gAudioContext.externalLoadQueue, gAudioContext.externalLoadMesgBuf,
|
||||||
ARRAY_COUNT(gAudioContext.externalLoadMesgBuf));
|
ARRAY_COUNT(gAudioContext.externalLoadMesgBuf));
|
||||||
osCreateMesgQueue(&gAudioContext.preloadSampleQueue, gAudioContext.preloadSampleMesgBuf,
|
osCreateMesgQueue(&gAudioContext.preloadSampleQueue, gAudioContext.preloadSampleMesgBuf,
|
||||||
ARRAY_COUNT(gAudioContext.externalLoadMesgBuf));
|
ARRAY_COUNT(gAudioContext.preloadSampleMesgBuf));
|
||||||
gAudioContext.curAudioFrameDmaCount = 0;
|
gAudioContext.curAudioFrameDmaCount = 0;
|
||||||
gAudioContext.sampleDmaCount = 0;
|
gAudioContext.sampleDmaCount = 0;
|
||||||
gAudioContext.cartHandle = osCartRomInit();
|
gAudioContext.cartHandle = osCartRomInit();
|
||||||
|
@ -1304,20 +1315,24 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||||
gAudioContext.audioHeapSize = D_8014A6C4.heapSize;
|
gAudioContext.audioHeapSize = D_8014A6C4.heapSize;
|
||||||
} else {
|
} else {
|
||||||
void** hp = &heap;
|
void** hp = &heap;
|
||||||
|
|
||||||
gAudioContext.audioHeap = *hp;
|
gAudioContext.audioHeap = *hp;
|
||||||
gAudioContext.audioHeapSize = heapSize;
|
gAudioContext.audioHeapSize = heapSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < gAudioContext.audioHeapSize / 8; i++) {
|
for (i = 0; i < ((s32)gAudioContext.audioHeapSize / (s32)sizeof(u64)); i++) {
|
||||||
((u64*)gAudioContext.audioHeap)[i] = 0;
|
((u64*)gAudioContext.audioHeap)[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Main Pool Split (split entirety of audio heap into initPool and sessionPool)
|
||||||
AudioHeap_InitMainPools(D_8014A6C4.initPoolSize);
|
AudioHeap_InitMainPools(D_8014A6C4.initPoolSize);
|
||||||
|
|
||||||
for (i = 0; i < 3; i++) {
|
// Initialize the audio interface buffers
|
||||||
|
for (i = 0; i < ARRAY_COUNT(gAudioContext.aiBuffers); i++) {
|
||||||
gAudioContext.aiBuffers[i] = AudioHeap_AllocZeroed(&gAudioContext.audioInitPool, AIBUF_LEN * sizeof(s16));
|
gAudioContext.aiBuffers[i] = AudioHeap_AllocZeroed(&gAudioContext.audioInitPool, AIBUF_LEN * sizeof(s16));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Connect audio tables to their tables in memory
|
||||||
// gAudioContext.sequenceTable = (AudioTable*)gSequenceTable;
|
// gAudioContext.sequenceTable = (AudioTable*)gSequenceTable;
|
||||||
// gAudioContext.soundFontTable = (AudioTable*)gSoundFontTable;
|
// gAudioContext.soundFontTable = (AudioTable*)gSoundFontTable;
|
||||||
// gAudioContext.sampleBankTable = (AudioTable*)gSampleBankTable;
|
// gAudioContext.sampleBankTable = (AudioTable*)gSampleBankTable;
|
||||||
|
@ -1325,31 +1340,60 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||||
// gAudioContext.numSequences = gAudioContext.sequenceTable->numEntries;
|
// gAudioContext.numSequences = gAudioContext.sequenceTable->numEntries;
|
||||||
|
|
||||||
gAudioContext.audioResetSpecIdToLoad = 0;
|
gAudioContext.audioResetSpecIdToLoad = 0;
|
||||||
gAudioContext.resetStatus = 1;
|
gAudioContext.resetStatus = 1; // Set reset to immediately initialize the audio heap
|
||||||
|
|
||||||
AudioHeap_ResetStep();
|
AudioHeap_ResetStep();
|
||||||
|
|
||||||
|
// Initialize audio tables
|
||||||
|
// AudioLoad_InitTable(gAudioContext.sequenceTable, SEGMENT_ROM_START(Audioseq), 0);
|
||||||
|
// AudioLoad_InitTable(gAudioContext.soundFontTable, SEGMENT_ROM_START(Audiobank), 0);
|
||||||
|
// AudioLoad_InitTable(gAudioContext.sampleBankTable, SEGMENT_ROM_START(Audiotable), 0);
|
||||||
|
|
||||||
|
// #region 2S2H [Port] Audio in the archive and custom sequences
|
||||||
|
// Only load the original sequences right now because custom songs may require data from sound fonts and samples
|
||||||
int seqListSize = 0;
|
int seqListSize = 0;
|
||||||
int customSeqListSize = 0;
|
int customSeqListSize = 0;
|
||||||
char** seqList = ResourceMgr_ListFiles("audio/sequences*", &seqListSize);
|
char** seqList = ResourceMgr_ListFiles("audio/sequences*", &seqListSize);
|
||||||
char** customSeqList = ResourceMgr_ListFiles("custom/music/*", &customSeqListSize);
|
char** customSeqList = ResourceMgr_ListFiles("custom/music/*", &customSeqListSize);
|
||||||
sequenceMapSize = (size_t)(AudioCollection_SequenceMapSize() + customSeqListSize);
|
sequenceMapSize = (size_t)(seqListSize + customSeqListSize );
|
||||||
sequenceMap = malloc(sequenceMapSize * sizeof(char*));
|
sequenceMap = malloc((sequenceMapSize + 0xF) * sizeof(char*));
|
||||||
gAudioContext.seqLoadStatus = malloc(sequenceMapSize * sizeof(char*));
|
|
||||||
|
|
||||||
|
gAudioContext.seqLoadStatus = malloc(sequenceMapSize);
|
||||||
|
memset(gAudioContext.seqLoadStatus, 5, sequenceMapSize);
|
||||||
for (size_t i = 0; i < seqListSize; i++) {
|
for (size_t i = 0; i < seqListSize; i++) {
|
||||||
SequenceData sDat = ResourceMgr_LoadSeqByName(seqList[i]);
|
SequenceData sDat = ResourceMgr_LoadSeqByName(seqList[i]);
|
||||||
|
sequenceMap[sDat.seqNumber] = strdup(seqList[i]);
|
||||||
char* str = malloc(strlen(seqList[i]) + 1);
|
|
||||||
strcpy(str, seqList[i]);
|
|
||||||
|
|
||||||
sequenceMap[sDat.seqNumber] = str;
|
|
||||||
seqCachePolicyMap[sDat.seqNumber] = sDat.cachePolicy;
|
seqCachePolicyMap[sDat.seqNumber] = sDat.cachePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(seqList);
|
free(seqList);
|
||||||
|
|
||||||
int startingSeqNum = MAX_AUTHENTIC_SEQID; // 109 is the highest vanilla sequence
|
// 2S2H [Streamed Audio] We need to load the custom songs after the fonts because streamed songs will use a hash to
|
||||||
|
// find its soundfont
|
||||||
|
int fntListSize = 0;
|
||||||
|
int customFntListSize = 0;
|
||||||
|
char** fntList = ResourceMgr_ListFiles("audio/fonts*", &fntListSize);
|
||||||
|
char** customFntList = ResourceMgr_ListFiles("custom/fonts/*", &customFntListSize);
|
||||||
|
|
||||||
|
gAudioContext.fontLoadStatus = malloc(customFntListSize + fntListSize);
|
||||||
|
fontMap = calloc(customFntListSize + fntListSize, sizeof(char*));
|
||||||
|
fontMapSize = customFntListSize + fntListSize;
|
||||||
|
for (int i = 0; i < fntListSize; i++) {
|
||||||
|
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fntList[i]);
|
||||||
|
fontMap[sf->fntIndex] = strdup(fntList[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fntList);
|
||||||
|
|
||||||
|
int customFontStart = fntListSize;
|
||||||
|
for (int i = customFontStart; i < customFntListSize + fntListSize; i++) {
|
||||||
|
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(customFntList[i - customFontStart]);
|
||||||
|
sf->fntIndex = i;
|
||||||
|
fontMap[i] = strdup(customFntList[i - customFontStart]);
|
||||||
|
}
|
||||||
|
free(customFntList);
|
||||||
|
|
||||||
|
// 2S2H Port I think we need to take use seqListSize because entry 0x7A is missing.
|
||||||
|
int startingSeqNum = seqListSize; // MAX_AUTHENTIC_SEQID; // 109 is the highest vanilla sequence
|
||||||
qsort(customSeqList, customSeqListSize, sizeof(char*), strcmp_sort);
|
qsort(customSeqList, customSeqListSize, sizeof(char*), strcmp_sort);
|
||||||
|
|
||||||
// Because AudioCollection's sequenceMap actually has more than sequences (including instruments from 130-135 and
|
// Because AudioCollection's sequenceMap actually has more than sequences (including instruments from 130-135 and
|
||||||
|
@ -1361,48 +1405,61 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||||
|
|
||||||
for (size_t i = startingSeqNum; i < startingSeqNum + customSeqListSize; i++) {
|
for (size_t i = startingSeqNum; i < startingSeqNum + customSeqListSize; i++) {
|
||||||
// ensure that what would be the next sequence number is actually unassigned in AudioCollection
|
// ensure that what would be the next sequence number is actually unassigned in AudioCollection
|
||||||
|
int j = i - startingSeqNum;
|
||||||
|
SequenceData* sDat = ResourceMgr_LoadSeqPtrByName(customSeqList[j]);
|
||||||
|
|
||||||
|
if (sDat->numFonts == -1) {
|
||||||
|
uint64_t crc;
|
||||||
|
|
||||||
|
memcpy(&crc, sDat->fonts, sizeof(uint64_t));
|
||||||
|
const char* res = ResourceGetNameByCrc(crc);
|
||||||
|
if (res == NULL) {
|
||||||
|
// Passing a null buffer and length of 0 to snprintf will return the required numbers of characters the
|
||||||
|
// buffer needs to be.
|
||||||
|
int len =
|
||||||
|
snprintf(NULL, 0, "Could not find sound font for sequence %s. It will not be in the audio editor.",
|
||||||
|
customSeqList[j]);
|
||||||
|
char* error = malloc(len + 1);
|
||||||
|
snprintf(error, len, "Could not find sound font for sequence %s. It will not be in the audio editor.",
|
||||||
|
customSeqList[j]);
|
||||||
|
LUSLOG_ERROR("%s", error);
|
||||||
|
Messagebox_ShowErrorBox("Invalid Sequence", error);
|
||||||
|
free(error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(res);
|
||||||
|
memset(&sDat->fonts[0], 0, sizeof(sDat->fonts));
|
||||||
|
sDat->fonts[0] = sf->fntIndex;
|
||||||
|
sDat->numFonts = 1;
|
||||||
|
}
|
||||||
|
|
||||||
while (AudioCollection_HasSequenceNum(seqNum)) {
|
while (AudioCollection_HasSequenceNum(seqNum)) {
|
||||||
seqNum++;
|
seqNum++;
|
||||||
}
|
}
|
||||||
int j = i - startingSeqNum;
|
|
||||||
AudioCollection_AddToCollection(customSeqList[j], seqNum);
|
AudioCollection_AddToCollection(customSeqList[j], seqNum);
|
||||||
SequenceData sDat = ResourceMgr_LoadSeqByName(customSeqList[j]);
|
|
||||||
sDat.seqNumber = seqNum;
|
|
||||||
|
|
||||||
char* str = malloc(strlen(customSeqList[j]) + 1);
|
sDat->seqNumber = seqNum;
|
||||||
strcpy(str, customSeqList[j]);
|
printf("%d\n", seqNum);
|
||||||
|
sequenceMap[sDat->seqNumber] = strdup(customSeqList[j]);
|
||||||
sequenceMap[sDat.seqNumber] = str;
|
|
||||||
seqNum++;
|
seqNum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(customSeqList);
|
free(customSeqList);
|
||||||
|
|
||||||
int fntListSize = 0;
|
|
||||||
char** fntList = ResourceMgr_ListFiles("audio/fonts*", &fntListSize);
|
|
||||||
|
|
||||||
for (int i = 0; i < fntListSize; i++) {
|
|
||||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fntList[i]);
|
|
||||||
|
|
||||||
char* str = malloc(strlen(fntList[i]) + 1);
|
|
||||||
strcpy(str, fntList[i]);
|
|
||||||
|
|
||||||
fontMap[sf->fntIndex] = str;
|
|
||||||
}
|
|
||||||
|
|
||||||
numFonts = fntListSize;
|
numFonts = fntListSize;
|
||||||
|
|
||||||
free(fntList);
|
// #end region
|
||||||
gAudioContext.soundFonts = AudioHeap_Alloc(&gAudioContext.audioInitPool, numFonts * sizeof(SoundFont));
|
gAudioContext.soundFonts = AudioHeap_Alloc(&gAudioContext.audioInitPool, numFonts * sizeof(SoundFont));
|
||||||
|
|
||||||
if (temp_v0_3 = AudioHeap_Alloc(&gAudioContext.audioInitPool, D_8014A6C4.permanentPoolSize), temp_v0_3 == NULL) {
|
if (addr = AudioHeap_Alloc(&gAudioContext.audioInitPool, D_8014A6C4.permanentPoolSize), addr == NULL) {
|
||||||
// cast away const from D_8014A6C4
|
// cast away const from D_8014A6C4
|
||||||
// *((u32*)&D_8014A6C4.permanentPoolSize) = 0;
|
*((u32*)&D_8014A6C4.permanentPoolSize) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioHeap_AllocPoolInit(&gAudioContext.permanentPool, temp_v0_3, D_8014A6C4.permanentPoolSize);
|
AudioHeap_AllocPoolInit(&gAudioContext.permanentPool, addr, D_8014A6C4.permanentPoolSize);
|
||||||
gAudioContextInitalized = true;
|
gAudioContextInitalized = true;
|
||||||
osSendMesg32(gAudioContext.taskStartQueueP, gAudioContext.totalTaskCnt, OS_MESG_NOBLOCK);
|
osSendMesg(gAudioContext.taskStartQueueP, OS_MESG_32(gAudioContext.totalTaskCnt), OS_MESG_NOBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioLoad_InitSlowLoads(void) {
|
void AudioLoad_InitSlowLoads(void) {
|
||||||
|
@ -2059,7 +2116,7 @@ void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, RelocInfo* relocInfo
|
||||||
|
|
||||||
gAudioContext.numUsedSamples = 0;
|
gAudioContext.numUsedSamples = 0;
|
||||||
|
|
||||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||||
|
|
||||||
numDrums = sf->numDrums;
|
numDrums = sf->numDrums;
|
||||||
numInstruments = sf->numInstruments;
|
numInstruments = sf->numInstruments;
|
||||||
|
@ -2188,7 +2245,7 @@ void AudioLoad_LoadPermanentSamples(void) {
|
||||||
fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioContext.permanentCache[i].id);
|
fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, gAudioContext.permanentCache[i].id);
|
||||||
// fontId = gAudioContext.permanentCache[i].id;
|
// fontId = gAudioContext.permanentCache[i].id;
|
||||||
|
|
||||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||||
relocInfo.sampleBankId1 = sf->sampleBankId1;
|
relocInfo.sampleBankId1 = sf->sampleBankId1;
|
||||||
relocInfo.sampleBankId2 = sf->sampleBankId2;
|
relocInfo.sampleBankId2 = sf->sampleBankId2;
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,7 @@ void Audio_NoteInit(Note* note) {
|
||||||
note->noteSubEu = gDefaultNoteSub;
|
note->noteSubEu = gDefaultNoteSub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void aOPUSFree(struct OggOpusFile* opusFile);
|
||||||
void Audio_NoteDisable(Note* note) {
|
void Audio_NoteDisable(Note* note) {
|
||||||
if (note->noteSubEu.bitField0.needsInit == true) {
|
if (note->noteSubEu.bitField0.needsInit == true) {
|
||||||
note->noteSubEu.bitField0.needsInit = false;
|
note->noteSubEu.bitField0.needsInit = false;
|
||||||
|
@ -159,6 +160,10 @@ void Audio_NoteDisable(Note* note) {
|
||||||
note->playbackState.prevParentLayer = NO_LAYER;
|
note->playbackState.prevParentLayer = NO_LAYER;
|
||||||
note->playbackState.adsr.action.s.state = ADSR_STATE_DISABLED;
|
note->playbackState.adsr.action.s.state = ADSR_STATE_DISABLED;
|
||||||
note->playbackState.adsr.current = 0;
|
note->playbackState.adsr.current = 0;
|
||||||
|
if (note->synthesisState.opusFile != NULL) {
|
||||||
|
aOPUSFree(note->synthesisState.opusFile);
|
||||||
|
note->synthesisState.opusFile = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio_ProcessNotes(void) {
|
void Audio_ProcessNotes(void) {
|
||||||
|
@ -293,13 +298,6 @@ void Audio_ProcessNotes(void) {
|
||||||
|
|
||||||
f32 resampRate = gAudioContext.audioBufferParameters.resampleRate;
|
f32 resampRate = gAudioContext.audioBufferParameters.resampleRate;
|
||||||
|
|
||||||
// CUSTOM SAMPLE CHECK
|
|
||||||
if (!noteSubEu2->bitField1.isSyntheticWave && noteSubEu2->sound.soundFontSound != NULL &&
|
|
||||||
noteSubEu2->sound.soundFontSound->sample != NULL &&
|
|
||||||
noteSubEu2->sound.soundFontSound->sample->sampleRateMagicValue == 'RIFF') {
|
|
||||||
resampRate = CALC_RESAMPLE_FREQ(noteSubEu2->sound.soundFontSound->sample->sampleRate);
|
|
||||||
}
|
|
||||||
|
|
||||||
subAttrs.frequency *= resampRate;
|
subAttrs.frequency *= resampRate;
|
||||||
|
|
||||||
subAttrs.velocity *= scale;
|
subAttrs.velocity *= scale;
|
||||||
|
@ -335,7 +333,7 @@ Instrument* Audio_GetInstrumentInner(s32 fontId, s32 instId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int instCnt = 0;
|
int instCnt = 0;
|
||||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||||
|
|
||||||
if (instId >= sf->numInstruments)
|
if (instId >= sf->numInstruments)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -362,7 +360,7 @@ Drum* Audio_GetDrum(s32 fontId, s32 drumId) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||||
if (drumId < sf->numDrums) {
|
if (drumId < sf->numDrums) {
|
||||||
drum = sf->drums[drumId];
|
drum = sf->drums[drumId];
|
||||||
}
|
}
|
||||||
|
@ -386,7 +384,7 @@ SoundFontSound* Audio_GetSfx(s32 fontId, s32 sfxId) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||||
if (sfxId < sf->numSfx) {
|
if (sfxId < sf->numSfx) {
|
||||||
sfx = &sf->soundEffects[sfxId];
|
sfx = &sf->soundEffects[sfxId];
|
||||||
}
|
}
|
||||||
|
|
|
@ -789,7 +789,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) {
|
||||||
layer->freqScale *= layer->unk_34;
|
layer->freqScale *= layer->unk_34;
|
||||||
if (layer->delay == 0) {
|
if (layer->delay == 0) {
|
||||||
if (layer->sound != NULL) {
|
if (layer->sound != NULL) {
|
||||||
time = (f32)layer->sound->sample->loop->end;
|
time = (f32)layer->sound->sample->loop->loopEnd;
|
||||||
} else {
|
} else {
|
||||||
time = 0.0f;
|
time = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -761,7 +761,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
|
||||||
audioFontSample = noteSubEu->sound.soundFontSound->sample;
|
audioFontSample = noteSubEu->sound.soundFontSound->sample;
|
||||||
|
|
||||||
loopInfo = audioFontSample->loop;
|
loopInfo = audioFontSample->loop;
|
||||||
loopEndPos = loopInfo->end;
|
loopEndPos = loopInfo->loopEnd;
|
||||||
sampleAddr = audioFontSample->sampleAddr;
|
sampleAddr = audioFontSample->sampleAddr;
|
||||||
resampledTempLen = 0;
|
resampledTempLen = 0;
|
||||||
|
|
||||||
|
@ -853,14 +853,28 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
|
||||||
s5 = samplesLenAdjusted;
|
s5 = samplesLenAdjusted;
|
||||||
goto skip;
|
goto skip;
|
||||||
case CODEC_S16:
|
case CODEC_S16:
|
||||||
AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, (samplesLenAdjusted * 2) + 0x20);
|
case CODEC_OPUS:
|
||||||
AudioSynth_LoadBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, ALIGN16(nSamplesToLoad * 2),
|
AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE,
|
||||||
audioFontSample->sampleAddr + (synthState->samplePosInt * 2));
|
(samplesLenAdjusted + 16) * 2);
|
||||||
|
flags = A_CONTINUE;
|
||||||
|
skipBytes = 0;
|
||||||
|
size_t bytesToRead;
|
||||||
|
nSamplesProcessed += samplesLenAdjusted;
|
||||||
|
|
||||||
|
if (((synthState->samplePosInt * 2) + (samplesLenAdjusted)*2) < audioFontSample->size) {
|
||||||
|
bytesToRead = (samplesLenAdjusted)*2;
|
||||||
|
} else {
|
||||||
|
bytesToRead = audioFontSample->size - (synthState->samplePosInt * 2);
|
||||||
|
}
|
||||||
|
// 2S2H [Port] [Custom audio] Handle decoding OPUS data
|
||||||
|
if (audioFontSample->codec == CODEC_OPUS) {
|
||||||
|
aOPUSdecImpl(sampleAddr, DMEM_UNCOMPRESSED_NOTE, bytesToRead, &synthState->opusFile,
|
||||||
|
synthState->samplePosInt, audioFontSample->fileSize);
|
||||||
|
} else {
|
||||||
|
aLoadBuffer(cmd++, sampleAddr + (synthState->samplePosInt * 2), DMEM_UNCOMPRESSED_NOTE,
|
||||||
|
bytesToRead);
|
||||||
|
}
|
||||||
|
|
||||||
flags = A_CONTINUE;
|
|
||||||
skipBytes = 0;
|
|
||||||
nSamplesProcessed = samplesLenAdjusted;
|
|
||||||
s5 = samplesLenAdjusted;
|
|
||||||
goto skip;
|
goto skip;
|
||||||
case CODEC_REVERB:
|
case CODEC_REVERB:
|
||||||
break;
|
break;
|
||||||
|
@ -886,6 +900,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
|
||||||
sampleDataStartPad = (uintptr_t)sampleData & 0xF;
|
sampleDataStartPad = (uintptr_t)sampleData & 0xF;
|
||||||
aligned = ALIGN16((nFramesToDecode * frameSize) + 16);
|
aligned = ALIGN16((nFramesToDecode * frameSize) + 16);
|
||||||
addr = DMEM_COMPRESSED_ADPCM_DATA - aligned;
|
addr = DMEM_COMPRESSED_ADPCM_DATA - aligned;
|
||||||
|
|
||||||
aLoadBuffer(cmd++, sampleData - sampleDataStartPad, addr, aligned);
|
aLoadBuffer(cmd++, sampleData - sampleDataStartPad, addr, aligned);
|
||||||
} else {
|
} else {
|
||||||
nSamplesToDecode = 0;
|
nSamplesToDecode = 0;
|
||||||
|
@ -893,7 +908,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
|
||||||
}
|
}
|
||||||
|
|
||||||
if (synthState->restart) {
|
if (synthState->restart) {
|
||||||
aSetLoop(cmd++, audioFontSample->loop->state);
|
aSetLoop(cmd++, audioFontSample->loop->predictorState);
|
||||||
flags = A_LOOP;
|
flags = A_LOOP;
|
||||||
synthState->restart = false;
|
synthState->restart = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -792,7 +792,7 @@ s32 func_800E6590(s32 playerIdx, s32 arg1, s32 arg2) {
|
||||||
if (sound == NULL) {
|
if (sound == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
loopEnd = sound->sample->loop->end;
|
loopEnd = sound->sample->loop->loopEnd;
|
||||||
samplePos = note->synthesisState.samplePosInt;
|
samplePos = note->synthesisState.samplePosInt;
|
||||||
return loopEnd - samplePos;
|
return loopEnd - samplePos;
|
||||||
}
|
}
|
||||||
|
|
|
@ -899,33 +899,25 @@ void AnimationContext_SetLoadFrame(PlayState* play, LinkAnimationHeader* animati
|
||||||
if (ResourceMgr_OTRSigCheck(animation) != 0)
|
if (ResourceMgr_OTRSigCheck(animation) != 0)
|
||||||
animation = ResourceMgr_LoadAnimByName(animation);
|
animation = ResourceMgr_LoadAnimByName(animation);
|
||||||
|
|
||||||
LinkAnimationHeader* linkAnimHeader = SEGMENTED_TO_VIRTUAL(animation);
|
LinkAnimationHeader* playerAnimHeader = animation;
|
||||||
Vec3s* ram = frameTable;
|
Vec3s* ram = frameTable;
|
||||||
|
|
||||||
osCreateMesgQueue(&entry->data.load.msgQueue, &entry->data.load.msg, 1);
|
// osCreateMesgQueue(&entry->data.load.msgQueue, &entry->data.load.msg, 1);
|
||||||
|
//
|
||||||
char animPath[2048];
|
// char animPath[2048];
|
||||||
|
//
|
||||||
snprintf(animPath, sizeof(animPath), "misc/link_animetion/gPlayerAnimData_%06X",
|
// snprintf(animPath, sizeof(animPath), "misc/link_animetion/gPlayerAnimData_%06X",
|
||||||
(((uintptr_t)linkAnimHeader->segment - 0x07000000)));
|
// (((uintptr_t)linkAnimHeader->segmentVoid - 0x07000000)));
|
||||||
|
//
|
||||||
// printf("Streaming %s, seg = %08X\n", animPath, linkAnimHeader->segment);
|
// printf("Streaming %s, seg = %08X\n", animPath, linkAnimHeader->segment);
|
||||||
|
|
||||||
s16* animData = ResourceMgr_LoadPlayerAnimByName(animPath);
|
s16* animData = /* ResourceMgr_LoadPlayerAnimByName*/ (animation->segment);
|
||||||
|
// 2S2H [Port] sometimes a HESS can set a negative frame value from a negative playback speed. When converted to
|
||||||
|
// a signed value this will cause a crash due to copying way much data.
|
||||||
|
if (frame < 0) {
|
||||||
|
frame = 0;
|
||||||
|
}
|
||||||
memcpy(ram, (uintptr_t)animData + (((sizeof(Vec3s) * limbCount + 2) * frame)), sizeof(Vec3s) * limbCount + 2);
|
memcpy(ram, (uintptr_t)animData + (((sizeof(Vec3s) * limbCount + 2) * frame)), sizeof(Vec3s) * limbCount + 2);
|
||||||
|
|
||||||
/*u32* ramPtr = (u32*)ram;
|
|
||||||
|
|
||||||
for (int i = 0; i < 1024; i++)
|
|
||||||
{
|
|
||||||
ramPtr[i] = i * 7;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// DmaMgr_SendRequest2(&entry->data.load.req, ram,
|
|
||||||
// LINK_ANIMATION_OFFSET(linkAnimHeader->segment, ((sizeof(Vec3s) * limbCount + 2) * frame)),
|
|
||||||
// sizeof(Vec3s) * limbCount + 2, 0, &entry->data.load.msgQueue, NULL, __FILE__,
|
|
||||||
//__LINE__);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue