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 ..
|
||||
make
|
||||
sudo make install
|
||||
- name: Generate soh.otr
|
||||
- name: Generate soh.o2r
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||
cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release
|
||||
cmake --build build-cmake --config Release --target GenerateSohOtr -j3
|
||||
- name: Upload soh.otr
|
||||
- name: Upload soh.o2r
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: soh.otr
|
||||
path: soh.otr
|
||||
name: soh.o2r
|
||||
path: soh.o2r
|
||||
retention-days: 3
|
||||
|
||||
build-macos:
|
||||
|
@ -122,10 +122,10 @@ jobs:
|
|||
brew uninstall --ignore-dependencies libpng
|
||||
sudo port install $(cat .github/workflows/macports-deps.txt)
|
||||
brew install ninja
|
||||
- name: Download soh.otr
|
||||
- name: Download soh.o2r
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: soh.otr
|
||||
name: soh.o2r
|
||||
path: build-cmake/soh
|
||||
- name: Build SoH
|
||||
run: |
|
||||
|
@ -233,10 +233,10 @@ jobs:
|
|||
make
|
||||
sudo make install
|
||||
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
|
||||
with:
|
||||
name: soh.otr
|
||||
name: soh.o2r
|
||||
path: build-cmake/soh
|
||||
- name: Build SoH
|
||||
run: |
|
||||
|
@ -298,10 +298,10 @@ jobs:
|
|||
path: vcpkg
|
||||
- name: Configure Developer Command Prompt
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Download soh.otr
|
||||
- name: Download soh.o2r
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: soh.otr
|
||||
name: soh.o2r
|
||||
path: build-windows/soh
|
||||
- name: Build SoH
|
||||
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) => {
|
||||
if (item.name === "soh.otr") return acc;
|
||||
if (item.name === "soh.o2r") return acc;
|
||||
acc += `
|
||||
- [${item.name}.zip](https://nightly.link/${context.repo.owner}/${context.repo.repo}/actions/artifacts/${item.id}.zip)`;
|
||||
return acc;
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -412,6 +412,7 @@ ReleaseObj/*
|
|||
.tags
|
||||
tags
|
||||
*.otr
|
||||
*.o2r
|
||||
*.sav
|
||||
shipofharkinian.ini
|
||||
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)
|
||||
|
||||
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")
|
||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
|
||||
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)
|
||||
set(GBI_UCODE F3DEX_GBI_2)
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake")
|
||||
|
||||
################################################################################
|
||||
# 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")
|
||||
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(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/extractor COMPONENT extractor)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/extractor/xmls 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)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets COMPONENT extractor)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml COMPONENT extractor)
|
||||
endif()
|
||||
|
||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/extractor COMPONENT ship)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/extractor/xmls 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)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/ COMPONENT ship)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml COMPONENT ship)
|
||||
endif()
|
||||
|
||||
find_package(Python3 COMPONENTS Interpreter)
|
||||
|
@ -198,42 +190,42 @@ find_package(Python3 COMPONENTS Interpreter)
|
|||
# Target to generate OTRs
|
||||
add_custom_target(
|
||||
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
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -r -f ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/libultraship/src/graphic/Fast3D/shaders/ ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/
|
||||
|
||||
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --non-interactive --xml-root ../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
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh
|
||||
COMMENT "Running asset extraction..."
|
||||
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
|
||||
add_custom_target(
|
||||
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
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
|
||||
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}/soh
|
||||
COMMENT "Generating asset headers..."
|
||||
DEPENDS ZAPD
|
||||
)
|
||||
|
||||
# Target to generate only soh.otr
|
||||
# Target to generate only soh.o2r
|
||||
add_custom_target(
|
||||
GenerateSohOtr
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f soh.otr
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -f soh.o2r
|
||||
|
||||
# copy LUS default shaders into assets/custom
|
||||
COMMAND ${CMAKE_COMMAND} -E rm -r -f ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/libultraship/src/graphic/Fast3D/shaders/ ${CMAKE_CURRENT_SOURCE_DIR}/soh/assets/custom/shaders/
|
||||
|
||||
COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter/extract_assets.py -z "$<TARGET_FILE:ZAPD>" --norom --custom-otr-file soh.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
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/OTRExporter
|
||||
COMMENT "Generating soh.otr..."
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/soh
|
||||
COMMENT "Generating soh.o2r..."
|
||||
DEPENDS ZAPD
|
||||
)
|
||||
|
||||
|
@ -266,16 +258,12 @@ add_custom_target(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)
|
||||
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/extractor)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/extractor/xmls)
|
||||
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_SOURCE_DIR}/soh/assets/extractor/" DESTINATION ./assets/)
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/soh/assets/xml/" DESTINATION ./assets/xml)
|
||||
|
||||
install(DIRECTORY ${CMAKE_BINARY_DIR}/assets
|
||||
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...")
|
||||
|
||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot.otr)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${SOURCE_DIR})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${BINARY_DIR}/soh/)
|
||||
message(STATUS "Copied oot.otr")
|
||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot.o2r)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.o2r ${SOURCE_DIR})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.o2r ${BINARY_DIR}/soh/)
|
||||
message(STATUS "Copied oot.o2r")
|
||||
endif()
|
||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot-mq.otr)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.otr ${SOURCE_DIR})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.otr ${BINARY_DIR}/soh/)
|
||||
message(STATUS "Copied oot-mq.otr")
|
||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot-mq.o2r)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.o2r ${SOURCE_DIR})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.o2r ${BINARY_DIR}/soh/)
|
||||
message(STATUS "Copied oot-mq.o2r")
|
||||
endif()
|
||||
if(EXISTS ${SOURCE_DIR}/OTRExporter/soh.otr)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.otr ${SOURCE_DIR})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.otr ${BINARY_DIR}/soh/)
|
||||
message(STATUS "Copied soh.otr")
|
||||
if(EXISTS ${SOURCE_DIR}/soh/soh.o2r)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.o2r ${SOURCE_DIR})
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.o2r ${BINARY_DIR}/soh/)
|
||||
message(STATUS "Copied soh.o2r")
|
||||
endif()
|
||||
|
||||
# Additionally for Windows, copy the otrs to the target dir, side by side with soh.exe
|
||||
if(SYSTEM_NAME MATCHES "Windows")
|
||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot.otr)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.otr ${TARGET_DIR})
|
||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot.o2r)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot.o2r ${TARGET_DIR})
|
||||
endif()
|
||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/OTRExporter/oot-mq.otr)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.otr ${TARGET_DIR})
|
||||
if(NOT ONLYSOHOTR AND EXISTS ${SOURCE_DIR}/soh/oot-mq.o2r)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy oot-mq.o2r ${TARGET_DIR})
|
||||
endif()
|
||||
if(EXISTS ${SOURCE_DIR}/OTRExporter/soh.otr)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.otr ${TARGET_DIR})
|
||||
if(EXISTS ${SOURCE_DIR}/soh/soh.o2r)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E copy soh.o2r ${TARGET_DIR})
|
||||
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.")
|
||||
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.")
|
||||
endif()
|
||||
|
|
|
@ -278,6 +278,14 @@ endif()
|
|||
# Find/download Boost
|
||||
################################################################################
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
dr_libs
|
||||
GIT_REPOSITORY https://github.com/mackron/dr_libs.git
|
||||
GIT_TAG da35f9d6c7374a95353fd1df1d394d44ab66cf01
|
||||
)
|
||||
FetchContent_MakeAvailable(dr_libs)
|
||||
|
||||
FetchContent_Declare(
|
||||
Boost
|
||||
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}
|
||||
${BOOST-INCLUDE}
|
||||
${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-int-conversion
|
||||
-Wno-implicit-int
|
||||
# -fsanitize=address
|
||||
$<$<COMPILE_LANGUAGE:C>:
|
||||
-Werror-implicit-function-declaration
|
||||
-Wno-incompatible-pointer-types
|
||||
|
@ -601,6 +611,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang")
|
|||
|
||||
target_link_options(${PROJECT_NAME} PRIVATE
|
||||
-pthread
|
||||
#-fsanitize=address
|
||||
-Wl,-export-dynamic
|
||||
)
|
||||
endif()
|
||||
|
@ -618,11 +629,7 @@ if(NOT CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
|
|||
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/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 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}
|
||||
)
|
||||
endif()
|
||||
|
@ -640,6 +647,15 @@ endif()
|
|||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
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")
|
||||
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
||||
"libultraship;"
|
||||
|
@ -653,6 +669,12 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
|||
"imm32;"
|
||||
"version;"
|
||||
"setupapi"
|
||||
"Ogg::ogg"
|
||||
"Opus::opus"
|
||||
"Vorbis::vorbis"
|
||||
"Vorbis::vorbisenc"
|
||||
"Vorbis::vorbisfile"
|
||||
"OpusFile::opusfile"
|
||||
)
|
||||
elseif("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32")
|
||||
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
||||
|
@ -693,10 +715,21 @@ else()
|
|||
find_package(SDL2)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
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
|
||||
"libultraship;"
|
||||
"ZAPDLib;"
|
||||
SDL2::SDL2
|
||||
"Ogg::ogg"
|
||||
"Vorbis::vorbis"
|
||||
"Vorbis::vorbisenc"
|
||||
"Vorbis::vorbisfile"
|
||||
"Opus::opus"
|
||||
"Opusfile::Opusfile"
|
||||
"$<$<BOOL:${BUILD_REMOTE_CONTROL}>:SDL2_net::SDL2_net>"
|
||||
${CMAKE_DL_LIBS}
|
||||
Threads::Threads
|
||||
|
@ -709,7 +742,7 @@ endif()
|
|||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
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()
|
||||
|
||||
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)
|
||||
INSTALL(TARGETS soh 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")
|
||||
INSTALL(FILES ${CMAKE_BINARY_DIR}/gamecontrollerdb.txt DESTINATION . COMPONENT ship)
|
||||
endif()
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_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"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_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"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_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"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_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"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_D/"/>
|
||||
<ExternalXMLFolder Path="assets/xml/GC_NMQ_D/"/>
|
||||
<TexturePool File="TexturePool.xml"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_NTSC_J/"/>
|
||||
<ExternalXMLFolder Path="assets/xml/GC_NMQ_NTSC_J/"/>
|
||||
<TexturePool File="TexturePool.xml"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_NTSC_J_CE/"/>
|
||||
<ExternalXMLFolder Path="assets/xml/GC_NMQ_NTSC_J_CE/"/>
|
||||
<TexturePool File="TexturePool.xml"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_NTSC_U/"/>
|
||||
<ExternalXMLFolder Path="assets/xml/GC_NMQ_NTSC_U/"/>
|
||||
<TexturePool File="TexturePool.xml"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_OoTMqDbg.txt"/>
|
||||
<ObjectList File="symbols/ObjectList_OoTMqDbg.txt"/>
|
||||
<ExternalXMLFolder Path="assets/extractor/xmls/GC_NMQ_PAL_F/"/>
|
||||
<ExternalXMLFolder Path="assets/xml/GC_NMQ_PAL_F/"/>
|
||||
<TexturePool File="TexturePool.xml"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_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"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_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"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_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"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_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"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</Root>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<SymbolMap File="symbols/SymbolMap_OoTMqDbg.txt"/>
|
||||
<ActorList File="symbols/ActorList_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"/>
|
||||
<ExternalFile XmlPath="objects/gameplay_keep.xml" OutPath="objects/gameplay_keep/"/>
|
||||
</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>
|
||||
|
||||
#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
|
||||
#define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#ifndef Z64_AUDIO_H
|
||||
#define Z64_AUDIO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <endianness.h>
|
||||
|
||||
#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
|
||||
extern size_t sequenceMapSize;
|
||||
|
||||
extern char* fontMap[256];
|
||||
extern size_t fontMapSize;
|
||||
extern char** fontMap;
|
||||
|
||||
#define MAX_AUTHENTIC_SEQID 110
|
||||
|
||||
|
@ -54,7 +58,8 @@ typedef enum {
|
|||
/* 2 */ CODEC_S16_INMEMORY,
|
||||
/* 3 */ CODEC_SMALL_ADPCM,
|
||||
/* 4 */ CODEC_REVERB,
|
||||
/* 5 */ CODEC_S16
|
||||
/* 5 */ CODEC_S16,
|
||||
/* 6 */ CODEC_OPUS,
|
||||
} SampleCodec;
|
||||
|
||||
typedef enum {
|
||||
|
@ -117,13 +122,14 @@ typedef struct {
|
|||
/* 0x2 */ s16 arg;
|
||||
} AdsrEnvelope; // size = 0x4
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ uintptr_t start;
|
||||
/* 0x04 */ uintptr_t end;
|
||||
/* 0x08 */ u32 count;
|
||||
/* 0x0C */ char unk_0C[0x4];
|
||||
/* 0x10 */ s16 state[16]; // only exists if count != 0. 8-byte aligned
|
||||
} AdpcmLoop; // size = 0x30 (or 0x10)
|
||||
typedef struct AdpcmLoop {
|
||||
/* 0x00 */ u32 start;
|
||||
/* 0x04 */ u32 loopEnd; // numSamples position into the sample where the loop ends
|
||||
/* 0x08 */ u32 count; // The number of times the loop is played before the sound completes. Setting count to -1
|
||||
// indicates that the loop should play indefinitely.
|
||||
/* 0x0C */ u32 sampleEnd; // total number of s16-samples in the sample audio clip
|
||||
/* 0x10 */ s16 predictorState[16]; // only exists if count != 0. 8-byte aligned
|
||||
} AdpcmLoop; // size = 0x30 (or 0x10)
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ s32 order;
|
||||
|
@ -131,24 +137,23 @@ typedef struct {
|
|||
/* 0x08 */ s16* book; // size 8 * order * npredictors. 8-byte aligned
|
||||
} AdpcmBook; // size >= 0x8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct SoundFontSample {
|
||||
union {
|
||||
struct {
|
||||
/* 0x00 */ u32 codec : 4;
|
||||
/* 0x00 */ u32 medium : 2;
|
||||
/* 0x00 */ u32 unk_bit26 : 1;
|
||||
/* 0x00 */ u32 unk_bit25 : 1; // this has been named isRelocated in zret
|
||||
/* 0x01 */ u32 size : 24;
|
||||
///* 0x0 */ u32 unk_0 : 1;
|
||||
/* 0x0 */ u32 codec : 4; // The state of compression or decompression, See `SampleCodec`
|
||||
/* 0x0 */ u32 medium : 2; // Medium where sample is currently stored. See `SampleMedium`
|
||||
/* 0x0 */ u32 unk_bit26 : 1;
|
||||
/* 0x0 */ u32 isRelocated : 1; // Has the sample header been relocated (offsets to pointers)
|
||||
|
||||
};
|
||||
u32 asU32;
|
||||
};
|
||||
|
||||
/* 0x04 */ u8* sampleAddr;
|
||||
/* 0x08 */ AdpcmLoop* loop;
|
||||
/* 0x0C */ AdpcmBook* book;
|
||||
u32 sampleRateMagicValue; // For wav samples only...
|
||||
s32 sampleRate; // For wav samples only...
|
||||
/* 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
|
||||
} SoundFontSample; // size = 0x10
|
||||
|
||||
typedef struct {
|
||||
|
@ -465,6 +470,8 @@ typedef struct {
|
|||
/* 0x00F0 */ s16 dummyResampleState[0x10];
|
||||
} NoteSynthesisBuffers; // size = 0x110
|
||||
|
||||
struct OggOpusFile;
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ u8 restart;
|
||||
/* 0x01 */ u8 sampleDmaIndex;
|
||||
|
@ -483,6 +490,7 @@ typedef struct {
|
|||
/* 0x1A */ u8 unk_1A;
|
||||
/* 0x1C */ u16 unk_1C;
|
||||
/* 0x1E */ u16 unk_1E;
|
||||
struct OggOpusFile* opusFile; // Only for streamed opus audio
|
||||
} NoteSynthesisState; // size = 0x20
|
||||
|
||||
typedef struct {
|
||||
|
@ -917,7 +925,7 @@ typedef struct {
|
|||
/* 0x3420 */ AudioPoolSplit3 persistentCommonPoolSplit;
|
||||
/* 0x342C */ AudioPoolSplit3 temporaryCommonPoolSplit;
|
||||
/* 0x3438 */ u8 sampleFontLoadStatus[0x30];
|
||||
/* 0x3468 */ u8 fontLoadStatus[0x30];
|
||||
/* 0x3468 */ u8* fontLoadStatus;
|
||||
/* 0x3498 */ u8* seqLoadStatus;
|
||||
/* 0x3518 */ volatile u8 resetStatus;
|
||||
/* 0x3519 */ u8 audioResetSpecIdToLoad;
|
||||
|
@ -1119,10 +1127,6 @@ typedef struct {
|
|||
uint8_t fonts[16];
|
||||
} SequenceData;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void Audio_SetGameVolume(int player_id, f32 volume);
|
||||
float Audio_GetGameVolume(int player_id);
|
||||
|
||||
|
|
|
@ -609,13 +609,13 @@ std::string Extractor::Mkdtemp() {
|
|||
extern "C" int zapd_main(int argc, char** argv);
|
||||
|
||||
bool Extractor::CallZapd(std::string installPath, std::string exportdir) {
|
||||
constexpr int argc = 18;
|
||||
constexpr int argc = 22;
|
||||
char xmlPath[1024];
|
||||
char confPath[1024];
|
||||
char portVersion[18]; // 5 digits for int16_max (x3) + separators + terminator
|
||||
std::array<const char*, argc> argv;
|
||||
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();
|
||||
installPath = std::filesystem::absolute(installPath).string();
|
||||
|
@ -632,8 +632,8 @@ bool Extractor::CallZapd(std::string installPath, std::string exportdir) {
|
|||
|
||||
std::filesystem::current_path(tempdir);
|
||||
|
||||
snprintf(xmlPath, 1024, "assets/extractor/xmls/%s", version);
|
||||
snprintf(confPath, 1024, "assets/extractor/Config_%s.xml", version);
|
||||
snprintf(xmlPath, 1024, "assets/xml/%s", version);
|
||||
snprintf(confPath, 1024, "assets/Config_%s.xml", version);
|
||||
snprintf(portVersion, 18, "%d.%d.%d", gBuildVersionMajor, gBuildVersionMinor, gBuildVersionPatch);
|
||||
|
||||
argv[0] = "ZAPD";
|
||||
|
@ -643,9 +643,9 @@ bool Extractor::CallZapd(std::string installPath, std::string exportdir) {
|
|||
argv[4] = "-b";
|
||||
argv[5] = romPath.c_str();
|
||||
argv[6] = "-fl";
|
||||
argv[7] = "assets/extractor/filelists";
|
||||
argv[7] = "assets/filelists";
|
||||
argv[8] = "-gsf";
|
||||
argv[9] = "1";
|
||||
argv[9] = "0";
|
||||
argv[10] = "-rconf";
|
||||
argv[11] = confPath;
|
||||
argv[12] = "-se";
|
||||
|
@ -654,6 +654,10 @@ bool Extractor::CallZapd(std::string installPath, std::string exportdir) {
|
|||
argv[15] = otrFile;
|
||||
argv[16] = "--portVer";
|
||||
argv[17] = portVersion;
|
||||
argv[18] = "-o";
|
||||
argv[19] = "placeholder";
|
||||
argv[20] = "-osf";
|
||||
argv[21] = "placeholder";
|
||||
|
||||
#ifdef _WIN32
|
||||
// Grab a handle to the command window.
|
||||
|
|
|
@ -263,15 +263,15 @@ const char* constCameraStrings[] = {
|
|||
|
||||
OTRGlobals::OTRGlobals() {
|
||||
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)) {
|
||||
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)) {
|
||||
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)) {
|
||||
OTRFiles.push_back(sohOtrPath);
|
||||
}
|
||||
|
@ -403,12 +403,19 @@ OTRGlobals::OTRGlobals() {
|
|||
static_cast<uint32_t>(SOH::ResourceType::SOH_Text), 0);
|
||||
loader->RegisterResourceFactory(std::make_shared<SOH::ResourceFactoryBinaryAudioSampleV2>(), RESOURCE_FORMAT_BINARY,
|
||||
"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>(),
|
||||
RESOURCE_FORMAT_BINARY, "AudioSoundFont",
|
||||
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>(),
|
||||
RESOURCE_FORMAT_BINARY, "AudioSequence",
|
||||
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,
|
||||
"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() {
|
||||
// Tell the audio thread to stop
|
||||
{
|
||||
|
@ -611,6 +624,19 @@ extern "C" void OTRAudio_Exit() {
|
|||
|
||||
// Wait until the audio thread quit
|
||||
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() {
|
||||
|
@ -945,7 +971,7 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) {
|
|||
OTRVersion version = {};
|
||||
|
||||
// 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()) {
|
||||
auto t = archive->LoadFile("portVersion");
|
||||
if (t != nullptr && t->IsLoaded) {
|
||||
|
@ -963,7 +989,7 @@ OTRVersion ReadPortVersionFromOTR(std::string otrPath) {
|
|||
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
|
||||
void CheckSoHOTRVersion(std::string otrPath) {
|
||||
std::string msg;
|
||||
|
@ -972,20 +998,20 @@ void CheckSoHOTRVersion(std::string otrPath) {
|
|||
msg = "\x1b[4;2HPlease re-extract it from the download."
|
||||
"\x1b[6;2HPress the Home button to exit...";
|
||||
#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...";
|
||||
#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
|
||||
|
||||
if (!std::filesystem::exists(otrPath)) {
|
||||
#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);
|
||||
#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__)
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -994,12 +1020,12 @@ void CheckSoHOTRVersion(std::string otrPath) {
|
|||
if (otrVersion.major != gBuildVersionMajor || otrVersion.minor != gBuildVersionMinor ||
|
||||
otrVersion.patch != gBuildVersionPatch) {
|
||||
#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);
|
||||
#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__)
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -1040,10 +1066,10 @@ void DetectOTRVersion(std::string fileName, bool isMQ) {
|
|||
|
||||
if (Extractor::ShowYesNoBox("Old OTR File Found", msgBuf) == IDYES) {
|
||||
std::string installPath = Ship::Context::GetAppBundlePath();
|
||||
if (!std::filesystem::exists(installPath + "/assets/extractor")) {
|
||||
if (!std::filesystem::exists(installPath + "/assets")) {
|
||||
Extractor::ShowErrorBox(
|
||||
"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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
auto rel = std::filesystem::relative(path, base);
|
||||
return !rel.empty() && rel.native()[0] != '.';
|
||||
|
@ -1151,17 +1181,22 @@ extern "C" void InitOTR() {
|
|||
CheckAndCreateModFolder();
|
||||
#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)) &&
|
||||
!std::filesystem::exists(Ship::Context::LocateFileAcrossAppDirs("oot.otr", appShortName))) {
|
||||
if (!ootOTRExists && !ootO2RExists) {
|
||||
|
||||
#if not defined(__SWITCH__) && not defined(__WIIU__)
|
||||
std::string installPath = Ship::Context::GetAppBundlePath();
|
||||
if (!std::filesystem::exists(installPath + "/assets/extractor")) {
|
||||
if (!std::filesystem::exists(installPath + "/assets")) {
|
||||
Extractor::ShowErrorBox(
|
||||
"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);
|
||||
}
|
||||
|
||||
|
@ -1200,8 +1235,8 @@ extern "C" void InitOTR() {
|
|||
#endif
|
||||
}
|
||||
|
||||
DetectOTRVersion("oot.otr", false);
|
||||
DetectOTRVersion("oot-mq.otr", true);
|
||||
DetectOTRVersion("oot.o2r", false);
|
||||
DetectOTRVersion("oot-mq.o2r", true);
|
||||
|
||||
OTRGlobals::Instance = new OTRGlobals();
|
||||
CustomMessageManager::Instance = new CustomMessageManager();
|
||||
|
|
|
@ -166,6 +166,7 @@ void CheckTracker_OnMessageClose();
|
|||
|
||||
GetItemID RetrieveGetItemIDFromItemID(ItemID itemID);
|
||||
RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID);
|
||||
void Messagebox_ShowErrorBox(char* title, char* body);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -429,11 +429,16 @@ extern "C" SequenceData ResourceMgr_LoadSeqByName(const char* path) {
|
|||
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) {
|
||||
return (SoundFontSample*)ResourceGetDataByName(path);
|
||||
}
|
||||
|
||||
extern "C" SoundFont* ResourceMgr_LoadAudioSoundFont(const char* path) {
|
||||
extern "C" SoundFont* ResourceMgr_LoadAudioSoundFontByName(const char* path) {
|
||||
return (SoundFont*)ResourceGetDataByName(path);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,8 +51,9 @@ void ResourceMgr_UnpatchGfxByName(const char* path, const char* patchName);
|
|||
char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path);
|
||||
Vtx* ResourceMgr_LoadVtxByCRC(uint64_t crc);
|
||||
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_LoadSeqPtrByName(const char* path);
|
||||
SoundFontSample* ResourceMgr_LoadAudioSample(const char* path);
|
||||
CollisionHeader* ResourceMgr_LoadColByName(const char* path);
|
||||
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 <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "mixer.h"
|
||||
|
||||
#ifndef __clang__
|
||||
#pragma GCC optimize("unroll-loops")
|
||||
#endif
|
||||
|
@ -14,6 +16,7 @@
|
|||
#define ROUND_UP_8(v) (((v) + 7) & ~7)
|
||||
#define ROUND_DOWN_16(v) ((v) & ~0xf)
|
||||
|
||||
|
||||
#define DMEM_BUF_SIZE (0x1000 - 0x3C0 - 0x40)
|
||||
#define BUF_U8(a) (rspa.buf.as_u8 + ((a)-0x3C0))
|
||||
#define BUF_S16(a) (rspa.buf.as_s16 + ((a)-0x3C0) / sizeof(int16_t))
|
||||
|
@ -35,7 +38,7 @@ static struct {
|
|||
uint16_t filter_count;
|
||||
int16_t filter[8];
|
||||
|
||||
union {
|
||||
__attribute__((aligned(16))) union {
|
||||
int16_t as_s16[DMEM_BUF_SIZE / sizeof(int16_t)];
|
||||
uint8_t as_u8[DMEM_BUF_SIZE];
|
||||
} buf;
|
||||
|
@ -66,6 +69,9 @@ static int16_t resample_table[64][4] = {
|
|||
{ 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) {
|
||||
if (v < -0x8000) {
|
||||
return -0x8000;
|
||||
|
@ -99,6 +105,33 @@ void aLoadBufferImpl(const void* source_addr, uint16_t dest_addr, uint16_t nbyte
|
|||
#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) {
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
int16_t* in = BUF_S16(in_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) {
|
||||
uint8_t* in = BUF_U8(rspa.in);
|
||||
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);
|
||||
} 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 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) \
|
||||
do { \
|
||||
} while (0)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "soh/resource/importer/AnimationFactory.h"
|
||||
#include "soh/resource/type/Animation.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "Context.h"
|
||||
|
||||
namespace SOH {
|
||||
std::shared_ptr<Ship::IResource>
|
||||
|
@ -80,7 +81,11 @@ ResourceFactoryBinaryAnimationV0::ReadResource(std::shared_ptr<Ship::File> file,
|
|||
animation->animationData.linkAnimationHeader.common.frameCount = reader->ReadInt16();
|
||||
|
||||
// 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) {
|
||||
SPDLOG_DEBUG("BEYTAH ANIMATION?!");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,191 @@
|
|||
#include "soh/resource/importer/AudioSampleFactory.h"
|
||||
#include "soh/resource/importer/AudioSoundFontFactory.h"
|
||||
#include "soh/resource/type/AudioSample.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 {
|
||||
std::shared_ptr<Ship::IResource>
|
||||
|
@ -16,108 +201,155 @@ ResourceFactoryBinaryAudioSampleV2::ReadResource(std::shared_ptr<Ship::File> fil
|
|||
audioSample->sample.codec = reader->ReadUByte();
|
||||
audioSample->sample.medium = 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->audioSampleData.reserve(audioSample->sample.size);
|
||||
audioSample->sample.sampleAddr = new uint8_t[audioSample->sample.size];
|
||||
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.end = 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++) {
|
||||
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->sample.loop = &audioSample->loop;
|
||||
|
||||
audioSample->book.order = reader->ReadInt32();
|
||||
audioSample->book.npredictors = reader->ReadInt32();
|
||||
audioSample->bookDataCount = reader->ReadUInt32();
|
||||
uint32_t bookDataCount = reader->ReadUInt32();
|
||||
|
||||
audioSample->bookData.reserve(audioSample->bookDataCount);
|
||||
for (uint32_t i = 0; i < audioSample->bookDataCount; i++) {
|
||||
audioSample->bookData.push_back(reader->ReadInt16());
|
||||
audioSample->book.book = new int16_t[bookDataCount];
|
||||
|
||||
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;
|
||||
|
||||
return audioSample;
|
||||
}
|
||||
} // namespace SOH
|
||||
|
||||
/*
|
||||
in ResourceMgr_LoadAudioSample we used to have
|
||||
--------------
|
||||
if (cachedCustomSFs.find(path) != cachedCustomSFs.end())
|
||||
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))
|
||||
std::shared_ptr<Ship::IResource>
|
||||
ResourceFactoryXMLAudioSampleV0::ReadResource(std::shared_ptr<Ship::File> file,
|
||||
std::shared_ptr<Ship::ResourceInitData> initData) {
|
||||
if (!FileHasValidFormatAndReader(file, initData)) {
|
||||
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 "ResourceFactoryBinary.h"
|
||||
#include "ResourceFactoryXML.h"
|
||||
|
||||
namespace SOH {
|
||||
class ResourceFactoryBinaryAudioSampleV2 : public Ship::ResourceFactoryBinary {
|
||||
public:
|
||||
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
||||
};
|
||||
class ResourceFactoryBinaryAudioSampleV2 : public Ship::ResourceFactoryBinary {
|
||||
public:
|
||||
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||
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
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
#include "soh/resource/importer/AudioSequenceFactory.h"
|
||||
#include "soh/resource/importer/AudioSoundFontFactory.h"
|
||||
#include "soh/resource/type/AudioSequence.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
|
||||
#include "Context.h"
|
||||
#include "resource/archive/Archive.h"
|
||||
#include "BinaryWriter.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace SOH {
|
||||
std::shared_ptr<Ship::IResource>
|
||||
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 reader = std::get<std::shared_ptr<Ship::BinaryReader>>(file->Reader);
|
||||
|
||||
audioSequence->sequence.seqDataSize = reader->ReadInt32();
|
||||
audioSequence->sequenceData.reserve(audioSequence->sequence.seqDataSize);
|
||||
audioSequence->sequence.seqDataSize = reader->ReadUInt32();
|
||||
audioSequence->sequence.seqData = new char[audioSequence->sequence.seqDataSize];
|
||||
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.medium = reader->ReadUByte();
|
||||
|
@ -34,4 +39,355 @@ ResourceFactoryBinaryAudioSequenceV2::ReadResource(std::shared_ptr<Ship::File> f
|
|||
|
||||
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 "ResourceFactoryBinary.h"
|
||||
#include "ResourceFactoryXML.h"
|
||||
|
||||
namespace SOH {
|
||||
class ResourceFactoryBinaryAudioSequenceV2 : public Ship::ResourceFactoryBinary {
|
||||
public:
|
||||
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
||||
};
|
||||
class ResourceFactoryBinaryAudioSequenceV2 : public Ship::ResourceFactoryBinary {
|
||||
public:
|
||||
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||
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
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "soh/resource/importer/AudioSoundFontFactory.h"
|
||||
#include "soh/resource/type/AudioSoundFont.h"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "libultraship/libultraship.h"
|
||||
#include "z64.h"
|
||||
#include "z64audio.h"
|
||||
#include "Context.h"
|
||||
#include "resource/archive/Archive.h"
|
||||
|
||||
namespace SOH {
|
||||
std::shared_ptr<Ship::IResource>
|
||||
|
@ -35,117 +37,115 @@ ResourceFactoryBinaryAudioSoundFontV2::ReadResource(std::shared_ptr<Ship::File>
|
|||
audioSoundFont->soundFont.numSfx = soundEffectCount;
|
||||
|
||||
// 🥁 DRUMS 🥁
|
||||
audioSoundFont->drums.reserve(audioSoundFont->soundFont.numDrums);
|
||||
// audioSoundFont->drums.reserve(audioSoundFont->soundFont.numDrums);
|
||||
audioSoundFont->drumAddresses.reserve(audioSoundFont->soundFont.numDrums);
|
||||
for (uint32_t i = 0; i < audioSoundFont->soundFont.numDrums; i++) {
|
||||
Drum drum;
|
||||
drum.releaseRate = reader->ReadUByte();
|
||||
drum.pan = reader->ReadUByte();
|
||||
drum.loaded = reader->ReadUByte();
|
||||
drum.loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFont
|
||||
Drum* drum = new Drum;
|
||||
drum->releaseRate = reader->ReadUByte();
|
||||
drum->pan = reader->ReadUByte();
|
||||
drum->loaded = reader->ReadUByte();
|
||||
drum->loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFontByName
|
||||
|
||||
uint32_t envelopeCount = reader->ReadUInt32();
|
||||
audioSoundFont->drumEnvelopeCounts.push_back(envelopeCount);
|
||||
std::vector<AdsrEnvelope> drumEnvelopes;
|
||||
drumEnvelopes.reserve(audioSoundFont->drumEnvelopeCounts[i]);
|
||||
for (uint32_t j = 0; j < audioSoundFont->drumEnvelopeCounts.back(); j++) {
|
||||
AdsrEnvelope env;
|
||||
|
||||
drum->envelope = new AdsrEnvelope[envelopeCount];
|
||||
for (uint32_t j = 0; j < envelopeCount; j++) {
|
||||
int16_t delay = reader->ReadInt16();
|
||||
int16_t arg = reader->ReadInt16();
|
||||
|
||||
env.delay = BE16SWAP(delay);
|
||||
env.arg = BE16SWAP(arg);
|
||||
|
||||
drumEnvelopes.push_back(env);
|
||||
drum->envelope[j].delay = BE16SWAP(delay);
|
||||
drum->envelope[j].arg = BE16SWAP(arg);
|
||||
}
|
||||
audioSoundFont->drumEnvelopeArrays.push_back(drumEnvelopes);
|
||||
drum.envelope = audioSoundFont->drumEnvelopeArrays.back().data();
|
||||
|
||||
bool hasSample = reader->ReadInt8();
|
||||
std::string sampleFileName = reader->ReadString();
|
||||
drum.sound.tuning = reader->ReadFloat();
|
||||
drum->sound.tuning = reader->ReadFloat();
|
||||
|
||||
if (sampleFileName.empty()) {
|
||||
drum.sound.sample = nullptr;
|
||||
drum->sound.sample = nullptr;
|
||||
} else {
|
||||
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->drumAddresses.push_back(&audioSoundFont->drums.back());
|
||||
// audioSoundFont->drums.push_back(drum);
|
||||
// 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();
|
||||
|
||||
// 🎺🎻🎷🎸🎹 INSTRUMENTS 🎹🎸🎷🎻🎺
|
||||
audioSoundFont->instruments.reserve(audioSoundFont->soundFont.numInstruments);
|
||||
for (uint32_t i = 0; i < audioSoundFont->soundFont.numInstruments; i++) {
|
||||
Instrument instrument;
|
||||
Instrument* instrument = new Instrument;
|
||||
|
||||
uint8_t isValidEntry = reader->ReadUByte();
|
||||
instrument.loaded = reader->ReadUByte();
|
||||
instrument.loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFont
|
||||
instrument->loaded = reader->ReadUByte();
|
||||
instrument->loaded = 0; // this was always getting set to zero in ResourceMgr_LoadAudioSoundFontByName
|
||||
|
||||
instrument.normalRangeLo = reader->ReadUByte();
|
||||
instrument.normalRangeHi = reader->ReadUByte();
|
||||
instrument.releaseRate = reader->ReadUByte();
|
||||
instrument->normalRangeLo = reader->ReadUByte();
|
||||
instrument->normalRangeHi = reader->ReadUByte();
|
||||
instrument->releaseRate = reader->ReadUByte();
|
||||
|
||||
uint32_t envelopeCount = reader->ReadInt32();
|
||||
audioSoundFont->instrumentEnvelopeCounts.push_back(envelopeCount);
|
||||
std::vector<AdsrEnvelope> instrumentEnvelopes;
|
||||
for (uint32_t j = 0; j < audioSoundFont->instrumentEnvelopeCounts.back(); j++) {
|
||||
AdsrEnvelope env;
|
||||
instrument->envelope = new AdsrEnvelope[envelopeCount];
|
||||
|
||||
for (uint32_t j = 0; j < envelopeCount; j++) {
|
||||
int16_t delay = reader->ReadInt16();
|
||||
int16_t arg = reader->ReadInt16();
|
||||
|
||||
env.delay = BE16SWAP(delay);
|
||||
env.arg = BE16SWAP(arg);
|
||||
|
||||
instrumentEnvelopes.push_back(env);
|
||||
instrument->envelope[j].delay = BE16SWAP(delay);
|
||||
instrument->envelope[j].arg = BE16SWAP(arg);
|
||||
}
|
||||
audioSoundFont->instrumentEnvelopeArrays.push_back(instrumentEnvelopes);
|
||||
instrument.envelope = audioSoundFont->instrumentEnvelopeArrays.back().data();
|
||||
|
||||
bool hasLowNoteSoundFontEntry = reader->ReadInt8();
|
||||
if (hasLowNoteSoundFontEntry) {
|
||||
bool hasSampleRef = reader->ReadInt8();
|
||||
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());
|
||||
instrument.lowNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||
instrument->lowNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||
} else {
|
||||
instrument.lowNotesSound.sample = nullptr;
|
||||
instrument.lowNotesSound.tuning = 0;
|
||||
instrument->lowNotesSound.sample = nullptr;
|
||||
instrument->lowNotesSound.tuning = 0;
|
||||
}
|
||||
|
||||
bool hasNormalNoteSoundFontEntry = reader->ReadInt8();
|
||||
if (hasNormalNoteSoundFontEntry) {
|
||||
// BENTODO remove in V3
|
||||
bool hasSampleRef = reader->ReadInt8();
|
||||
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());
|
||||
instrument.normalNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||
instrument->normalNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||
} else {
|
||||
instrument.normalNotesSound.sample = nullptr;
|
||||
instrument.normalNotesSound.tuning = 0;
|
||||
instrument->normalNotesSound.sample = nullptr;
|
||||
instrument->normalNotesSound.tuning = 0;
|
||||
}
|
||||
|
||||
bool hasHighNoteSoundFontEntry = reader->ReadInt8();
|
||||
if (hasHighNoteSoundFontEntry) {
|
||||
bool hasSampleRef = reader->ReadInt8();
|
||||
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());
|
||||
instrument.highNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||
instrument->highNotesSound.sample = static_cast<Sample*>(res ? res->GetRawPointer() : nullptr);
|
||||
} else {
|
||||
instrument.highNotesSound.sample = nullptr;
|
||||
instrument.highNotesSound.tuning = 0;
|
||||
instrument->highNotesSound.sample = nullptr;
|
||||
instrument->highNotesSound.tuning = 0;
|
||||
}
|
||||
|
||||
audioSoundFont->instruments.push_back(instrument);
|
||||
audioSoundFont->instrumentAddresses.push_back(isValidEntry ? &audioSoundFont->instruments.back() : nullptr);
|
||||
if (isValidEntry) {
|
||||
audioSoundFont->instrumentAddresses.push_back(instrument);
|
||||
} else {
|
||||
delete[] instrument->envelope;
|
||||
delete instrument;
|
||||
audioSoundFont->instrumentAddresses.push_back(nullptr);
|
||||
}
|
||||
}
|
||||
audioSoundFont->soundFont.instruments = audioSoundFont->instrumentAddresses.data();
|
||||
|
||||
|
@ -169,4 +169,302 @@ ResourceFactoryBinaryAudioSoundFontV2::ReadResource(std::shared_ptr<Ship::File>
|
|||
|
||||
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
|
||||
|
|
|
@ -2,11 +2,29 @@
|
|||
|
||||
#include "Resource.h"
|
||||
#include "ResourceFactoryBinary.h"
|
||||
#include "ResourceFactoryXML.h"
|
||||
#include "soh/resource/type/AudioSoundFont.h"
|
||||
|
||||
namespace SOH {
|
||||
class ResourceFactoryBinaryAudioSoundFontV2 : public Ship::ResourceFactoryBinary {
|
||||
public:
|
||||
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||
std::shared_ptr<Ship::ResourceInitData> initData) override;
|
||||
};
|
||||
class ResourceFactoryBinaryAudioSoundFontV2 : public Ship::ResourceFactoryBinary {
|
||||
public:
|
||||
std::shared_ptr<Ship::IResource> ReadResource(std::shared_ptr<Ship::File> file,
|
||||
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
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
#include "AudioSample.h"
|
||||
|
||||
namespace SOH {
|
||||
Sample* AudioSample::GetPointer() {
|
||||
return &sample;
|
||||
}
|
||||
AudioSample::~AudioSample() {
|
||||
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() {
|
||||
return sizeof(Sample);
|
||||
}
|
||||
size_t AudioSample::GetPointerSize() {
|
||||
return sizeof(Sample);
|
||||
}
|
||||
} // namespace SOH
|
|
@ -1,62 +1,60 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "Resource.h"
|
||||
#include <libultraship/libultra/types.h>
|
||||
|
||||
namespace SOH {
|
||||
typedef struct {
|
||||
/* 0x00 */ uintptr_t start;
|
||||
/* 0x04 */ uintptr_t end;
|
||||
/* 0x08 */ u32 count;
|
||||
/* 0x0C */ char unk_0C[0x4];
|
||||
/* 0x10 */ s16 state[16]; // only exists if count != 0. 8-byte aligned
|
||||
} AdpcmLoop; // size = 0x30 (or 0x10)
|
||||
typedef struct {
|
||||
/* 0x00 */ u32 start;
|
||||
/* 0x04 */ u32 end;
|
||||
/* 0x08 */ u32 count;
|
||||
/* 0x0C */ char unk_0C[0x4];
|
||||
/* 0x10 */ s16 state[16]; // only exists if count != 0. 8-byte aligned
|
||||
} AdpcmLoop; // size = 0x30 (or 0x10)
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ s32 order;
|
||||
/* 0x04 */ s32 npredictors;
|
||||
/* 0x08 */ s16* book; // size 8 * order * npredictors. 8-byte aligned
|
||||
} AdpcmBook; // s
|
||||
typedef struct {
|
||||
/* 0x00 */ s32 order;
|
||||
/* 0x04 */ s32 npredictors;
|
||||
/* 0x08 */ s16* book; // size 8 * order * npredictors. 8-byte aligned
|
||||
} AdpcmBook; // s
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
struct {
|
||||
/* 0x00 */ u32 codec : 4;
|
||||
/* 0x00 */ u32 medium : 2;
|
||||
/* 0x00 */ u32 unk_bit26 : 1;
|
||||
/* 0x00 */ u32 unk_bit25 : 1; // this has been named isRelocated in zret
|
||||
/* 0x01 */ u32 size : 24;
|
||||
typedef struct Sample {
|
||||
union {
|
||||
struct {
|
||||
///* 0x0 */ u32 unk_0 : 1;
|
||||
/* 0x0 */ u32 codec : 4; // The state of compression or decompression, See `SampleCodec`
|
||||
/* 0x0 */ u32 medium : 2; // Medium where sample is currently stored. See `SampleMedium`
|
||||
/* 0x0 */ u32 unk_bit26 : 1;
|
||||
/* 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;
|
||||
};
|
||||
|
||||
/* 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
|
||||
}; // namespace SOH
|
|
@ -2,11 +2,17 @@
|
|||
|
||||
namespace SOH {
|
||||
|
||||
Sequence* AudioSequence::GetPointer() {
|
||||
return &sequence;
|
||||
}
|
||||
Sequence* AudioSequence::GetPointer() {
|
||||
return &sequence;
|
||||
}
|
||||
|
||||
size_t AudioSequence::GetPointerSize() {
|
||||
return sizeof(Sequence);
|
||||
}
|
||||
} // namespace SOH
|
||||
size_t AudioSequence::GetPointerSize() {
|
||||
return sizeof(Sequence);
|
||||
}
|
||||
|
||||
AudioSequence::~AudioSequence() {
|
||||
delete[] sequence.seqData;
|
||||
sequence.seqData = nullptr;
|
||||
}
|
||||
|
||||
} // namespace SOH
|
|
@ -1,33 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "Resource.h"
|
||||
#include <libultraship/libultra/types.h>
|
||||
|
||||
namespace SOH {
|
||||
|
||||
typedef struct {
|
||||
char* seqData;
|
||||
int32_t seqDataSize;
|
||||
uint16_t seqNumber;
|
||||
uint8_t medium;
|
||||
uint8_t cachePolicy;
|
||||
int32_t numFonts;
|
||||
uint8_t fonts[16];
|
||||
} Sequence;
|
||||
typedef struct {
|
||||
char* seqData;
|
||||
uint32_t seqDataSize;
|
||||
uint16_t seqNumber;
|
||||
uint8_t medium;
|
||||
uint8_t cachePolicy;
|
||||
uint32_t numFonts;
|
||||
uint8_t fonts[16];
|
||||
} Sequence;
|
||||
|
||||
class AudioSequence : public Ship::Resource<Sequence> {
|
||||
public:
|
||||
using Resource::Resource;
|
||||
class AudioSequence : public Ship::Resource<Sequence> {
|
||||
public:
|
||||
using Resource::Resource;
|
||||
|
||||
AudioSequence() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {
|
||||
}
|
||||
AudioSequence() : Resource(std::shared_ptr<Ship::ResourceInitData>()) {
|
||||
}
|
||||
~AudioSequence();
|
||||
|
||||
Sequence* GetPointer();
|
||||
size_t GetPointerSize();
|
||||
Sequence* GetPointer();
|
||||
size_t GetPointerSize();
|
||||
|
||||
Sequence sequence;
|
||||
std::vector<char> sequenceData;
|
||||
};
|
||||
}; // namespace SOH
|
||||
Sequence sequence;
|
||||
};
|
||||
}; // namespace SOH
|
|
@ -1,11 +1,28 @@
|
|||
#include "AudioSoundFont.h"
|
||||
|
||||
namespace SOH {
|
||||
SoundFont* AudioSoundFont::GetPointer() {
|
||||
return &soundFont;
|
||||
}
|
||||
|
||||
size_t AudioSoundFont::GetPointerSize() {
|
||||
return sizeof(SoundFont);
|
||||
}
|
||||
} // namespace SOH
|
||||
AudioSoundFont::~AudioSoundFont() {
|
||||
for (auto i : instrumentAddresses) {
|
||||
if (i != nullptr) {
|
||||
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 {
|
||||
|
||||
typedef struct {
|
||||
/* 0x0 */ s16 delay;
|
||||
/* 0x2 */ s16 arg;
|
||||
} AdsrEnvelope; // size = 0x4
|
||||
typedef struct {
|
||||
/* 0x0 */ s16 delay;
|
||||
/* 0x2 */ s16 arg;
|
||||
} AdsrEnvelope; // size = 0x4
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ Sample* sample;
|
||||
/* 0x04 */ union {
|
||||
u32 tuningAsU32;
|
||||
f32 tuning; // frequency scale factor
|
||||
typedef struct {
|
||||
/* 0x00 */ Sample* sample;
|
||||
/* 0x04 */ union {
|
||||
u32 tuningAsU32;
|
||||
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
|
||||
|
|
|
@ -41,7 +41,7 @@ void func_800DDE3C(void) {
|
|||
void AudioHeap_ResetLoadStatus(void) {
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < 0x30; i++) {
|
||||
for (i = 0; i < fontMapSize; i++) {
|
||||
if (gAudioContext.fontLoadStatus[i] != 5) {
|
||||
gAudioContext.fontLoadStatus[i] = 0;
|
||||
}
|
||||
|
@ -940,7 +940,7 @@ void AudioHeap_Init(void) {
|
|||
reverb->sample.sampleAddr = (u8*)reverb->leftRingBuf;
|
||||
reverb->loop.start = 0;
|
||||
reverb->loop.count = 1;
|
||||
reverb->loop.end = reverb->windowSize;
|
||||
reverb->loop.loopEnd = reverb->windowSize;
|
||||
|
||||
if (reverb->downsampleRate != 1) {
|
||||
reverb->unk_0E = 0x8000 / reverb->downsampleRate;
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
#include "soh/Enhancements/audio/AudioCollection.h"
|
||||
#include "soh/Enhancements/audio/AudioEditor.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 ASYNC_TBLTYPE(v) ((u8)(v >> 16))
|
||||
|
@ -82,7 +86,8 @@ char** sequenceMap;
|
|||
size_t sequenceMapSize;
|
||||
// A map of authentic sequence IDs to their cache policies, for use with sequence swapping.
|
||||
u8 seqCachePolicyMap[MAX_AUTHENTIC_SEQID];
|
||||
char* fontMap[256];
|
||||
size_t fontMapSize;
|
||||
char** fontMap;
|
||||
|
||||
uintptr_t fontStart;
|
||||
uint32_t fontOffsets[8192];
|
||||
|
@ -419,7 +424,7 @@ void AudioLoad_SyncLoadSeqParts(s32 seqId, s32 arg1) {
|
|||
s32 AudioLoad_SyncLoadSample(SoundFontSample* sample, s32 fontId) {
|
||||
void* sampleAddr;
|
||||
|
||||
if (sample->unk_bit25 == 1) {
|
||||
if (sample->isRelocated == 1) {
|
||||
if (sample->medium != MEDIUM_RAM) {
|
||||
sampleAddr = AudioHeap_AllocSampleCache(sample->size, fontId, (void*)sample->sampleAddr, sample->medium,
|
||||
CACHE_PERSISTENT);
|
||||
|
@ -701,7 +706,7 @@ SoundFontData* AudioLoad_SyncLoadFont(u32 fontId) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||
|
||||
sampleBankId1 = sf->sampleBankId1;
|
||||
sampleBankId2 = sf->sampleBankId2;
|
||||
|
@ -759,7 +764,7 @@ uintptr_t AudioLoad_SyncLoad(u32 tableType, u32 id, s32* didAllocate) {
|
|||
cachePolicy = sData.cachePolicy;
|
||||
romAddr = 0;
|
||||
} else if (tableType == FONT_TABLE) {
|
||||
fnt = ResourceMgr_LoadAudioSoundFont(fontMap[id]);
|
||||
fnt = ResourceMgr_LoadAudioSoundFontByName(fontMap[id]);
|
||||
size = sizeof(SoundFont);
|
||||
medium = 2;
|
||||
cachePolicy = 0;
|
||||
|
@ -887,6 +892,7 @@ AudioTable* AudioLoad_GetLoadTable(s32 tableType) {
|
|||
}
|
||||
|
||||
void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo) {
|
||||
return;
|
||||
uintptr_t reloc;
|
||||
uintptr_t reloc2;
|
||||
Instrument* inst;
|
||||
|
@ -898,7 +904,7 @@ void AudioLoad_RelocateFont(s32 fontId, SoundFontData* mem, RelocInfo* relocInfo
|
|||
s32 numInstruments = 0;
|
||||
s32 numSfx = 0;
|
||||
|
||||
sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
||||
sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||
numDrums = sf->numDrums;
|
||||
numInstruments = sf->numInstruments;
|
||||
numSfx = sf->numSfx;
|
||||
|
@ -1247,12 +1253,13 @@ int strcmp_sort(const void* str1, const void* str2) {
|
|||
}
|
||||
|
||||
void AudioLoad_Init(void* heap, size_t heapSize) {
|
||||
char pad[0x48];
|
||||
s32 pad1[9];
|
||||
s32 numFonts;
|
||||
void* temp_v0_3;
|
||||
s32 pad2[2];
|
||||
u8* audioCtxPtr;
|
||||
void* addr;
|
||||
s32 i;
|
||||
u64* heapP;
|
||||
s16* u2974p;
|
||||
s32 j;
|
||||
|
||||
D_801755D0 = NULL;
|
||||
gAudioContext.resetTimer = 0;
|
||||
|
@ -1266,10 +1273,12 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
|||
gAudioContext.unk_2960 = 20.03042f;
|
||||
gAudioContext.refreshRate = 50;
|
||||
break;
|
||||
|
||||
case OS_TV_MPAL:
|
||||
gAudioContext.unk_2960 = 16.546f;
|
||||
gAudioContext.refreshRate = 60;
|
||||
break;
|
||||
|
||||
case OS_TV_NTSC:
|
||||
default:
|
||||
gAudioContext.unk_2960 = 16.713f;
|
||||
|
@ -1278,7 +1287,7 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
|||
|
||||
Audio_InitMesgQueues();
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i = 0; i < ARRAY_COUNT(gAudioContext.aiBufLengths); i++) {
|
||||
gAudioContext.aiBufLengths[i] = 0xA0;
|
||||
}
|
||||
|
||||
|
@ -1289,12 +1298,14 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
|||
gAudioContext.currTask = NULL;
|
||||
gAudioContext.rspTask[0].task.t.data_size = 0;
|
||||
gAudioContext.rspTask[1].task.t.data_size = 0;
|
||||
|
||||
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,
|
||||
ARRAY_COUNT(gAudioContext.externalLoadMesgBuf));
|
||||
osCreateMesgQueue(&gAudioContext.preloadSampleQueue, gAudioContext.preloadSampleMesgBuf,
|
||||
ARRAY_COUNT(gAudioContext.externalLoadMesgBuf));
|
||||
ARRAY_COUNT(gAudioContext.preloadSampleMesgBuf));
|
||||
gAudioContext.curAudioFrameDmaCount = 0;
|
||||
gAudioContext.sampleDmaCount = 0;
|
||||
gAudioContext.cartHandle = osCartRomInit();
|
||||
|
@ -1304,20 +1315,24 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
|||
gAudioContext.audioHeapSize = D_8014A6C4.heapSize;
|
||||
} else {
|
||||
void** hp = &heap;
|
||||
|
||||
gAudioContext.audioHeap = *hp;
|
||||
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;
|
||||
}
|
||||
|
||||
// Main Pool Split (split entirety of audio heap into initPool and sessionPool)
|
||||
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));
|
||||
}
|
||||
|
||||
// Connect audio tables to their tables in memory
|
||||
// gAudioContext.sequenceTable = (AudioTable*)gSequenceTable;
|
||||
// gAudioContext.soundFontTable = (AudioTable*)gSoundFontTable;
|
||||
// gAudioContext.sampleBankTable = (AudioTable*)gSampleBankTable;
|
||||
|
@ -1325,31 +1340,60 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
|
|||
// gAudioContext.numSequences = gAudioContext.sequenceTable->numEntries;
|
||||
|
||||
gAudioContext.audioResetSpecIdToLoad = 0;
|
||||
gAudioContext.resetStatus = 1;
|
||||
|
||||
gAudioContext.resetStatus = 1; // Set reset to immediately initialize the audio heap
|
||||
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 customSeqListSize = 0;
|
||||
char** seqList = ResourceMgr_ListFiles("audio/sequences*", &seqListSize);
|
||||
char** customSeqList = ResourceMgr_ListFiles("custom/music/*", &customSeqListSize);
|
||||
sequenceMapSize = (size_t)(AudioCollection_SequenceMapSize() + customSeqListSize);
|
||||
sequenceMap = malloc(sequenceMapSize * sizeof(char*));
|
||||
gAudioContext.seqLoadStatus = malloc(sequenceMapSize * sizeof(char*));
|
||||
sequenceMapSize = (size_t)(seqListSize + customSeqListSize );
|
||||
sequenceMap = malloc((sequenceMapSize + 0xF) * sizeof(char*));
|
||||
|
||||
gAudioContext.seqLoadStatus = malloc(sequenceMapSize);
|
||||
memset(gAudioContext.seqLoadStatus, 5, sequenceMapSize);
|
||||
for (size_t i = 0; i < seqListSize; i++) {
|
||||
SequenceData sDat = ResourceMgr_LoadSeqByName(seqList[i]);
|
||||
|
||||
char* str = malloc(strlen(seqList[i]) + 1);
|
||||
strcpy(str, seqList[i]);
|
||||
|
||||
sequenceMap[sDat.seqNumber] = str;
|
||||
sequenceMap[sDat.seqNumber] = strdup(seqList[i]);
|
||||
seqCachePolicyMap[sDat.seqNumber] = sDat.cachePolicy;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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++) {
|
||||
// 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)) {
|
||||
seqNum++;
|
||||
}
|
||||
int j = i - startingSeqNum;
|
||||
|
||||
AudioCollection_AddToCollection(customSeqList[j], seqNum);
|
||||
SequenceData sDat = ResourceMgr_LoadSeqByName(customSeqList[j]);
|
||||
sDat.seqNumber = seqNum;
|
||||
|
||||
char* str = malloc(strlen(customSeqList[j]) + 1);
|
||||
strcpy(str, customSeqList[j]);
|
||||
|
||||
sequenceMap[sDat.seqNumber] = str;
|
||||
sDat->seqNumber = seqNum;
|
||||
printf("%d\n", seqNum);
|
||||
sequenceMap[sDat->seqNumber] = strdup(customSeqList[j]);
|
||||
seqNum++;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
free(fntList);
|
||||
// #end region
|
||||
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
|
||||
// *((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;
|
||||
osSendMesg32(gAudioContext.taskStartQueueP, gAudioContext.totalTaskCnt, OS_MESG_NOBLOCK);
|
||||
osSendMesg(gAudioContext.taskStartQueueP, OS_MESG_32(gAudioContext.totalTaskCnt), OS_MESG_NOBLOCK);
|
||||
}
|
||||
|
||||
void AudioLoad_InitSlowLoads(void) {
|
||||
|
@ -2059,7 +2116,7 @@ void AudioLoad_PreloadSamplesForFont(s32 fontId, s32 async, RelocInfo* relocInfo
|
|||
|
||||
gAudioContext.numUsedSamples = 0;
|
||||
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||
|
||||
numDrums = sf->numDrums;
|
||||
numInstruments = sf->numInstruments;
|
||||
|
@ -2188,7 +2245,7 @@ void AudioLoad_LoadPermanentSamples(void) {
|
|||
fontId = AudioLoad_GetRealTableIndex(FONT_TABLE, 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.sampleBankId2 = sf->sampleBankId2;
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ void Audio_NoteInit(Note* note) {
|
|||
note->noteSubEu = gDefaultNoteSub;
|
||||
}
|
||||
|
||||
extern void aOPUSFree(struct OggOpusFile* opusFile);
|
||||
void Audio_NoteDisable(Note* note) {
|
||||
if (note->noteSubEu.bitField0.needsInit == true) {
|
||||
note->noteSubEu.bitField0.needsInit = false;
|
||||
|
@ -159,6 +160,10 @@ void Audio_NoteDisable(Note* note) {
|
|||
note->playbackState.prevParentLayer = NO_LAYER;
|
||||
note->playbackState.adsr.action.s.state = ADSR_STATE_DISABLED;
|
||||
note->playbackState.adsr.current = 0;
|
||||
if (note->synthesisState.opusFile != NULL) {
|
||||
aOPUSFree(note->synthesisState.opusFile);
|
||||
note->synthesisState.opusFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void Audio_ProcessNotes(void) {
|
||||
|
@ -293,13 +298,6 @@ void Audio_ProcessNotes(void) {
|
|||
|
||||
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.velocity *= scale;
|
||||
|
@ -335,7 +333,7 @@ Instrument* Audio_GetInstrumentInner(s32 fontId, s32 instId) {
|
|||
}
|
||||
|
||||
int instCnt = 0;
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||
|
||||
if (instId >= sf->numInstruments)
|
||||
return NULL;
|
||||
|
@ -362,7 +360,7 @@ Drum* Audio_GetDrum(s32 fontId, s32 drumId) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||
if (drumId < sf->numDrums) {
|
||||
drum = sf->drums[drumId];
|
||||
}
|
||||
|
@ -386,7 +384,7 @@ SoundFontSound* Audio_GetSfx(s32 fontId, s32 sfxId) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFont(fontMap[fontId]);
|
||||
SoundFont* sf = ResourceMgr_LoadAudioSoundFontByName(fontMap[fontId]);
|
||||
if (sfxId < sf->numSfx) {
|
||||
sfx = &sf->soundEffects[sfxId];
|
||||
}
|
||||
|
|
|
@ -789,7 +789,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) {
|
|||
layer->freqScale *= layer->unk_34;
|
||||
if (layer->delay == 0) {
|
||||
if (layer->sound != NULL) {
|
||||
time = (f32)layer->sound->sample->loop->end;
|
||||
time = (f32)layer->sound->sample->loop->loopEnd;
|
||||
} else {
|
||||
time = 0.0f;
|
||||
}
|
||||
|
|
|
@ -761,7 +761,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
|
|||
audioFontSample = noteSubEu->sound.soundFontSound->sample;
|
||||
|
||||
loopInfo = audioFontSample->loop;
|
||||
loopEndPos = loopInfo->end;
|
||||
loopEndPos = loopInfo->loopEnd;
|
||||
sampleAddr = audioFontSample->sampleAddr;
|
||||
resampledTempLen = 0;
|
||||
|
||||
|
@ -853,14 +853,28 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
|
|||
s5 = samplesLenAdjusted;
|
||||
goto skip;
|
||||
case CODEC_S16:
|
||||
AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, (samplesLenAdjusted * 2) + 0x20);
|
||||
AudioSynth_LoadBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, ALIGN16(nSamplesToLoad * 2),
|
||||
audioFontSample->sampleAddr + (synthState->samplePosInt * 2));
|
||||
case CODEC_OPUS:
|
||||
AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE,
|
||||
(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;
|
||||
case CODEC_REVERB:
|
||||
break;
|
||||
|
@ -886,6 +900,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
|
|||
sampleDataStartPad = (uintptr_t)sampleData & 0xF;
|
||||
aligned = ALIGN16((nFramesToDecode * frameSize) + 16);
|
||||
addr = DMEM_COMPRESSED_ADPCM_DATA - aligned;
|
||||
|
||||
aLoadBuffer(cmd++, sampleData - sampleDataStartPad, addr, aligned);
|
||||
} else {
|
||||
nSamplesToDecode = 0;
|
||||
|
@ -893,7 +908,7 @@ Acmd* AudioSynth_ProcessNote(s32 noteIndex, NoteSubEu* noteSubEu, NoteSynthesisS
|
|||
}
|
||||
|
||||
if (synthState->restart) {
|
||||
aSetLoop(cmd++, audioFontSample->loop->state);
|
||||
aSetLoop(cmd++, audioFontSample->loop->predictorState);
|
||||
flags = A_LOOP;
|
||||
synthState->restart = false;
|
||||
}
|
||||
|
|
|
@ -792,7 +792,7 @@ s32 func_800E6590(s32 playerIdx, s32 arg1, s32 arg2) {
|
|||
if (sound == NULL) {
|
||||
return 0;
|
||||
}
|
||||
loopEnd = sound->sample->loop->end;
|
||||
loopEnd = sound->sample->loop->loopEnd;
|
||||
samplePos = note->synthesisState.samplePosInt;
|
||||
return loopEnd - samplePos;
|
||||
}
|
||||
|
|
|
@ -899,33 +899,25 @@ void AnimationContext_SetLoadFrame(PlayState* play, LinkAnimationHeader* animati
|
|||
if (ResourceMgr_OTRSigCheck(animation) != 0)
|
||||
animation = ResourceMgr_LoadAnimByName(animation);
|
||||
|
||||
LinkAnimationHeader* linkAnimHeader = SEGMENTED_TO_VIRTUAL(animation);
|
||||
LinkAnimationHeader* playerAnimHeader = animation;
|
||||
Vec3s* ram = frameTable;
|
||||
|
||||
osCreateMesgQueue(&entry->data.load.msgQueue, &entry->data.load.msg, 1);
|
||||
|
||||
char animPath[2048];
|
||||
|
||||
snprintf(animPath, sizeof(animPath), "misc/link_animetion/gPlayerAnimData_%06X",
|
||||
(((uintptr_t)linkAnimHeader->segment - 0x07000000)));
|
||||
|
||||
// osCreateMesgQueue(&entry->data.load.msgQueue, &entry->data.load.msg, 1);
|
||||
//
|
||||
// char animPath[2048];
|
||||
//
|
||||
// snprintf(animPath, sizeof(animPath), "misc/link_animetion/gPlayerAnimData_%06X",
|
||||
// (((uintptr_t)linkAnimHeader->segmentVoid - 0x07000000)));
|
||||
//
|
||||
// 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);
|
||||
|
||||
/*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