diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 5c1930ede..ec0676de8 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -7,7 +7,7 @@ concurrency: cancel-in-progress: true jobs: generate-soh-otr: - runs-on: ${{ (vars.LINUX_RUNNER && fromJSON(vars.LINUX_RUNNER)) || 'ubuntu-latest' }} + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 with: @@ -20,7 +20,6 @@ jobs: ${{ runner.os }}-otr-ccache-${{ github.ref }} ${{ runner.os }}-otr-ccache- - name: Install dependencies - if: ${{ !vars.LINUX_RUNNER }} run: | sudo apt-get update sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) @@ -35,7 +34,6 @@ jobs: build-cmake SDL2-2.28.5 - name: Install latest SDL - if: ${{ !vars.LINUX_RUNNER }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" if [ ! -d "SDL2-2.28.5" ]; then @@ -73,47 +71,44 @@ jobs: retention-days: 1 build-macos: needs: generate-soh-otr - runs-on: ${{ (vars.MAC_RUNNER && fromJSON(vars.MAC_RUNNER)) || 'macos-12' }} + runs-on: macos-14 steps: - uses: actions/checkout@v3 with: submodules: true - name: ccache - uses: hendrikmuhs/ccache-action@v1.2.11 + uses: hendrikmuhs/ccache-action@v1.2.13 with: - key: ${{ runner.os }}-ccache-${{ github.ref }}-${{ github.sha }} + create-symlink: true + key: ${{ runner.os }}-14-ccache-${{ github.ref }}-${{ github.sha }} restore-keys: | - ${{ runner.os }}-ccache-${{ github.ref }} - ${{ runner.os }}-ccache- + ${{ runner.os }}-14-ccache-${{ github.ref }} + ${{ runner.os }}-14-ccache- - name: Install gtar wrapper - if: ${{ !vars.MAC_RUNNER }} run: | - sudo mv /usr/local/bin/gtar /usr/local/bin/gtar.orig - sudo cp .github/workflows//gtar /usr/local/bin/gtar - sudo chmod +x /usr/local/bin/gtar + sudo mv /opt/homebrew/bin/gtar /opt/homebrew/bin/gtar.orig + sudo cp .github/workflows//gtar /opt/homebrew/bin/gtar + sudo chmod +x /opt/homebrew/bin/gtar - name: Cache MacPorts id: cache-macports - if: ${{ !vars.MAC_RUNNER }} uses: actions/cache@v2 with: path: /opt/local/ - key: ${{ runner.os }}-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }} + key: ${{ runner.os }}-14-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }} restore-keys: | - ${{ runner.os }}-macports- + ${{ runner.os }}-14-macports- - name: Install MacPorts (if necessary) - if: ${{ !vars.MAC_RUNNER }} run: | if [ -d /opt/local/ ]; then echo "MacPorts already installed" else - wget https://github.com/macports/macports-base/releases/download/v2.9.3/MacPorts-2.9.3-12-Monterey.pkg - sudo installer -pkg ./MacPorts-2.9.3-12-Monterey.pkg -target / + wget https://github.com/macports/macports-base/releases/download/v2.9.3/MacPorts-2.9.3-14-Sonoma.pkg + sudo installer -pkg ./MacPorts-2.9.3-14-Sonoma.pkg -target / fi echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH - name: Install dependencies - if: ${{ !vars.MAC_RUNNER }} run: | - brew uninstall --ignore-dependencies libpng libzip + brew uninstall --ignore-dependencies libpng sudo port install $(cat .github/workflows/macports-deps.txt) brew install ninja - name: Download soh.otr @@ -122,7 +117,6 @@ jobs: name: soh.otr - name: Build SoH run: | - export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" -DBUILD_REMOTE_CONTROL=1 cmake --build build-cmake --config Release --parallel 10 mv soh.otr build-cmake/soh @@ -139,45 +133,33 @@ jobs: readme.txt build-linux: needs: generate-soh-otr - strategy: - fail-fast: true - matrix: - include: - - os: ubuntu-20.04 - gcc: 10 - archive-suffix: compatibility - - os: ubuntu-22.04 - gcc: 12 - archive-suffix: performance - runs-on: ${{ (matrix.os == 'ubuntu-20.04' && ((vars.LINUX_COMPATIBILITY_RUNNER && fromJSON(vars.LINUX_COMPATIBILITY_RUNNER)) || matrix.os)) || (matrix.os == 'ubuntu-22.04' && ((vars.LINUX_PERFORMANCE_RUNNER && fromJSON(vars.LINUX_PERFORMANCE_RUNNER)) || matrix.os)) }} + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 with: submodules: true - name: Install dependencies - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | sudo apt-get update sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) - name: ccache uses: hendrikmuhs/ccache-action@v1.2.11 with: - key: ${{ matrix.os }}-ccache-${{ github.ref }}-${{ github.sha }} + key: linux-ccache-${{ github.ref }}-${{ github.sha }} restore-keys: | - ${{ matrix.os }}-ccache-${{ github.ref }} - ${{ matrix.os }}-ccache- + linux-ccache-${{ github.ref }} + linux-ccache- - name: Cache build folders uses: actions/cache@v4 with: - key: ${{ matrix.os }}-build-${{ github.ref }}-${{ github.sha }} + key: linux-build-${{ github.ref }}-${{ github.sha }} restore-keys: | - ${{ matrix.os }}-build-${{ github.ref }} - ${{ matrix.os }}-build- + linux-build-${{ github.ref }} + linux-build- path: | SDL2-2.28.5 SDL2_net-2.2.0 - name: Install latest SDL - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" if [ ! -d "SDL2-2.28.5" ]; then @@ -189,38 +171,7 @@ jobs: make -j 10 sudo make install sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/ - - name: Install latest libzip - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) }} - run: | - sudo apt-get remove libzip-dev zipcmp zipmerge ziptool - export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - if [ ! -d "libzip-1.10.1" ]; then - wget https://libzip.org/download/libzip-1.10.1.tar.gz - tar -xzvf libzip-1.10.1.tar.gz - fi - cd libzip-1.10.1 - mkdir build - cd build - cmake .. - make - sudo make install - - name: Install latest nlohmann - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) }} - run: | - sudo apt-get remove nlohmann-json3-dev - export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" - if [ ! -d "json-3.11.3" ]; then - wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz - tar -xzvf v3.11.3.tar.gz - fi - cd json-3.11.3 - mkdir build - cd build - cmake .. - make - sudo make install - name: Install latest tinyxml2 - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | sudo apt-get remove libtinyxml2-dev export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" @@ -235,7 +186,6 @@ jobs: make sudo make install - name: Install latest SDL_net - if: ${{ (matrix.os == 'ubuntu-20.04' && !vars.LINUX_COMPATIBILITY_RUNNER) || (matrix.os == 'ubuntu-22.04' && !vars.LINUX_PERFORMANCE_RUNNER) }} run: | export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" if [ ! -d "SDL2_net-2.2.0" ]; then @@ -261,12 +211,12 @@ jobs: mv README.md readme.txt mv build-cmake/*.appimage soh.appimage env: - CC: gcc-${{ matrix.gcc }} - CXX: g++-${{ matrix.gcc }} + CC: gcc-12 + CXX: g++-12 - name: Upload build uses: actions/upload-artifact@v4 with: - name: soh-linux-${{ matrix.archive-suffix }} + name: soh-linux path: | soh.appimage readme.txt diff --git a/.github/workflows/gtar b/.github/workflows/gtar index 5814696d1..cf64d0281 100644 --- a/.github/workflows/gtar +++ b/.github/workflows/gtar @@ -1,2 +1,2 @@ #!/bin/sh -exec sudo /usr/local/bin/gtar.orig "$@" +exec sudo /opt/homebrew/bin/gtar.orig "$@" diff --git a/.github/workflows/test-builds-on-distros.yml b/.github/workflows/test-builds-on-distros.yml index 36bbc67a9..e2029be78 100644 --- a/.github/workflows/test-builds-on-distros.yml +++ b/.github/workflows/test-builds-on-distros.yml @@ -1,8 +1,3 @@ -# todo: -# nlohmann -# tinyxml2 -# spdlog - name: test-builds-on-distros on: workflow_dispatch: # by request @@ -28,31 +23,42 @@ jobs: if: ${{ matrix.image == 'archlinux:base' }} run: | echo arch - echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost + echo pacman -S ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost pacman -Syu --noconfirm - pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost + pacman -S --noconfirm ${{ matrix.cc }} git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost - name: Install dependencies (dnf) if: ${{ matrix.image == 'fedora:39' }} run: | echo fedora - echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel + echo dnf install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} wget git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools tinyxml2-devel spdlog-devel boost-devel dnf -y upgrade - dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel + dnf -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} wget git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools tinyxml2-devel spdlog-devel boost-devel - name: Install dependencies (apt) if: ${{ matrix.image == 'ubuntu:mantic' || matrix.image == 'debian:bookworm' }} run: | echo debian based - echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev + echo apt-get install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev apt-get update apt-get -y full-upgrade - apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev + apt-get -y install ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'g++') || '' }} git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev - name: Install dependencies (zypper) if: ${{ matrix.image == 'opensuse/tumbleweed:latest' }} run: | echo openSUSE - echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools + echo zypper in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel zypper --non-interactive dup - zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools + zypper --non-interactive in ${{ matrix.cc }} ${{ (matrix.cxx == 'g++' && 'gcc-c++') || '' }} ${{ matrix.cc == 'clang' && 'libstdc++-devel' || '' }} git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel + - name: Install latest nlohmann + if: ${{ matrix.image == 'fedora:39' }} + run: | + wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz + tar -xzvf v3.11.3.tar.gz + cd json-3.11.3 + mkdir build + cd build + cmake .. + make + sudo make install - uses: actions/checkout@v3 with: submodules: true diff --git a/CMake/lus-cvars.cmake b/CMake/lus-cvars.cmake index e7376cfe2..dee8f8c08 100644 --- a/CMake/lus-cvars.cmake +++ b/CMake/lus-cvars.cmake @@ -16,7 +16,6 @@ set(CVAR_STATS_WINDOW_OPEN "${CVAR_PREFIX_WINDOW}.Stats" CACHE STRING "") set(CVAR_ENABLE_MULTI_VIEWPORTS "${CVAR_PREFIX_SETTING}.EnableMultiViewports" CACHE STRING "") set(CVAR_LOW_RES_MODE "${CVAR_PREFIX_SETTING}.LowResMode" CACHE STRING "") set(CVAR_SIMULATED_INPUT_LAG "${CVAR_PREFIX_SETTING}.SimulatedInputLag" CACHE STRING "") -set(CVAR_ALT_ASSETS "${CVAR_PREFIX_ENHANCEMENT}.AltAssets" CACHE STRING "") set(CVAR_GAME_OVERLAY_FONT "${CVAR_PREFIX_SETTING}.OverlayFont" CACHE STRING "") set(CVAR_MENU_BAR_OPEN "${CVAR_PREFIX_SETTING}.OpenMenuBar" CACHE STRING "") set(CVAR_PREFIX_CONTROLLERS "${CVAR_PREFIX_SETTING}.Controllers" CACHE STRING "") diff --git a/CMakeLists.txt b/CMakeLists.txt index 891d6ad26..2d200a2d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,11 +5,11 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") -project(Ship VERSION 8.0.5 LANGUAGES C CXX) +project(Ship VERSION 8.0.6 LANGUAGES C CXX) include(CMake/soh-cvars.cmake) include(CMake/lus-cvars.cmake) -set(PROJECT_BUILD_NAME "MacReady Foxtrot" CACHE STRING "") -set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "") +set(PROJECT_BUILD_NAME "MacReady Golf" CACHE STRING "" FORCE) +set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "" FORCE) set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh) add_compile_options($<$:/MP>) @@ -84,6 +84,12 @@ include(CMake/GlobalSettingsInclude.cmake OPTIONAL) ################################################################################ set_property(GLOBAL PROPERTY USE_FOLDERS ON) +################################################################################ +# Set GBI version +################################################################################ + +set(GBI_UCODE F3DEX_GBI_2) + ################################################################################ # Sub-projects ################################################################################ diff --git a/OTRExporter b/OTRExporter index 3cea9ee7c..2cfdb3960 160000 --- a/OTRExporter +++ b/OTRExporter @@ -1 +1 @@ -Subproject commit 3cea9ee7c017d842aa4d9ceeb8d3ffbf29c6effb +Subproject commit 2cfdb3960900ba059f570b2ded2fed3494a96a9b diff --git a/README.md b/README.md index ad80f7f2f..233ef86d9 100644 --- a/README.md +++ b/README.md @@ -91,10 +91,7 @@ If you want to playtest a continuous integration build, you can find them at the * [Windows](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-windows.zip) * [macOS](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-mac.zip) -* [Linux (performance)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-performance.zip) _(requires `glibc 2.35` or newer, but will be more performant than the compatibility build.)_ -* [Linux (compatibility)](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux-compatibility.zip) _(compatible with most Linux distributions, but may not be as performant as the performance build.)_ -* [Switch](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-switch.zip) -* [Wii U](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-wiiu.zip) +* [Linux](https://nightly.link/HarbourMasters/Shipwright/workflows/generate-builds/develop/soh-linux.zip) diff --git a/ZAPDTR b/ZAPDTR index f38a9c92e..04d42249d 160000 --- a/ZAPDTR +++ b/ZAPDTR @@ -1 +1 @@ -Subproject commit f38a9c92eb99368c0607acf356d5651ebdc96f51 +Subproject commit 04d42249d2c15c3b442a0282a90bc8b7bda25b03 diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 6c9222242..eb5a6a336 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -88,34 +88,34 @@ cd "build/x64" #### Debian/Ubuntu ```sh # using gcc -apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev +apt-get install gcc g++ git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev # or using clang -apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool libboost-dev libopengl-dev +apt-get install clang git cmake ninja-build lsb-release libsdl2-dev libpng-dev libsdl2-net-dev libzip-dev zipcmp zipmerge ziptool nlohmann-json3-dev libtinyxml2-dev libspdlog-dev libboost-dev libopengl-dev ``` #### Arch ```sh # using gcc -pacman -S gcc git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost +pacman -S gcc git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost # or using clang -pacman -S clang git cmake ninja lsb-release sdl2 libpng libzip sdl2_net boost +pacman -S clang git cmake ninja lsb-release sdl2 libpng libzip nlohmann-json tinyxml2 spdlog sdl2_net boost ``` #### Fedora ```sh # using gcc -dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel +dnf install gcc gcc-c++ git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools nlohmann-json-devel tinyxml2-devel spdlog-devel boost-devel # or using clang -dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools boost-devel +dnf install clang git cmake ninja-build lsb_release SDL2-devel libpng-devel libzip-devel libzip-tools nlohmann-json-devel tinyxml2-devel spdlog-devel boost-devel ``` #### openSUSE ```sh # using gcc -zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools +zypper in gcc gcc-c++ git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel # or using clang -zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools +zypper in clang libstdc++-devel git cmake ninja SDL2-devel libpng16-devel libzip-devel libzip-tools nlohmann_json-devel tinyxml2-devel spdlog-devel ``` ### Build diff --git a/libultraship b/libultraship index 0da318c0f..31e9b009f 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit 0da318c0f4e431313565cad546fc469b8e850388 +Subproject commit 31e9b009f94e7074a847c7954926cba354cd7c72 diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 3f086bcac..6984291d3 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -407,6 +407,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") ">" "$<$:ENABLE_REMOTE_CONTROL>" "INCLUDE_GAME_PRINTF;" + "F3DEX_GBI_2" "UNICODE;" "_UNICODE" STORMLIB_NO_AUTO_LINK @@ -425,6 +426,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") "NDEBUG;" ">" "INCLUDE_GAME_PRINTF;" + "F3DEX_GBI_2" "WIN32;" "UNICODE;" "_UNICODE" @@ -440,6 +442,7 @@ elseif (CMAKE_SYSTEM_NAME STREQUAL "CafeOS") "$<$:" "NDEBUG" ">" + "F3DEX_GBI_2" "SPDLOG_ACTIVE_LEVEL=3;" "SPDLOG_NO_THREAD_ID;" "SPDLOG_NO_TLS;" @@ -453,6 +456,7 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|AppleClang") "$<$:" "NDEBUG" ">" + "F3DEX_GBI_2" "$<$:ENABLE_REMOTE_CONTROL>" "SPDLOG_ACTIVE_LEVEL=0;" "_CONSOLE;" diff --git a/soh/assets/custom/scenes/nonmq/syotes_scene/syotes_room_0 b/soh/assets/custom/scenes/shared/syotes_scene/syotes_room_0 similarity index 100% rename from soh/assets/custom/scenes/nonmq/syotes_scene/syotes_room_0 rename to soh/assets/custom/scenes/shared/syotes_scene/syotes_room_0 diff --git a/soh/assets/custom/textures/buttons/Mod1.png b/soh/assets/custom/textures/buttons/Mod1.png new file mode 100644 index 000000000..69496db6a Binary files /dev/null and b/soh/assets/custom/textures/buttons/Mod1.png differ diff --git a/soh/assets/custom/textures/buttons/Mod1Outline.png b/soh/assets/custom/textures/buttons/Mod1Outline.png new file mode 100644 index 000000000..0149bf0f5 Binary files /dev/null and b/soh/assets/custom/textures/buttons/Mod1Outline.png differ diff --git a/soh/assets/custom/textures/buttons/Mod2.png b/soh/assets/custom/textures/buttons/Mod2.png new file mode 100644 index 000000000..afb0576d1 Binary files /dev/null and b/soh/assets/custom/textures/buttons/Mod2.png differ diff --git a/soh/assets/custom/textures/buttons/Mod2Outline.png b/soh/assets/custom/textures/buttons/Mod2Outline.png new file mode 100644 index 000000000..06464c553 Binary files /dev/null and b/soh/assets/custom/textures/buttons/Mod2Outline.png differ diff --git a/soh/assets/xml/GC_MQ_D/code/sys_matrix.xml b/soh/assets/xml/GC_MQ_D/code/sys_matrix.xml new file mode 100644 index 000000000..b39033d59 --- /dev/null +++ b/soh/assets/xml/GC_MQ_D/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan.xml b/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan.xml index 18d39d57b..9eb1ee61a 100644 --- a/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/GC_MQ_D/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_MQ_PAL_F/code/sys_matrix.xml b/soh/assets/xml/GC_MQ_PAL_F/code/sys_matrix.xml new file mode 100644 index 000000000..a3fed368b --- /dev/null +++ b/soh/assets/xml/GC_MQ_PAL_F/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan.xml b/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan.xml index 18d39d57b..9eb1ee61a 100644 --- a/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/GC_MQ_PAL_F/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_NMQ_D/code/sys_matrix.xml b/soh/assets/xml/GC_NMQ_D/code/sys_matrix.xml new file mode 100644 index 000000000..ed2a859c6 --- /dev/null +++ b/soh/assets/xml/GC_NMQ_D/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan.xml b/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan.xml index 41c009d7d..a9e520f4c 100644 --- a/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/GC_NMQ_D/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_NMQ_PAL_F/code/sys_matrix.xml b/soh/assets/xml/GC_NMQ_PAL_F/code/sys_matrix.xml new file mode 100644 index 000000000..d2143f4e4 --- /dev/null +++ b/soh/assets/xml/GC_NMQ_PAL_F/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan.xml b/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan.xml index 41c009d7d..a9e520f4c 100644 --- a/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/GC_NMQ_PAL_F/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/N64_PAL_10/code/sys_matrix.xml b/soh/assets/xml/N64_PAL_10/code/sys_matrix.xml new file mode 100644 index 000000000..706c249d4 --- /dev/null +++ b/soh/assets/xml/N64_PAL_10/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan.xml b/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan.xml index 41c009d7d..a9e520f4c 100644 --- a/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/N64_PAL_10/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/N64_PAL_11/code/sys_matrix.xml b/soh/assets/xml/N64_PAL_11/code/sys_matrix.xml new file mode 100644 index 000000000..97b57a57c --- /dev/null +++ b/soh/assets/xml/N64_PAL_11/code/sys_matrix.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan.xml b/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan.xml index 41c009d7d..a9e520f4c 100644 --- a/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan.xml +++ b/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan.xml @@ -1,4 +1,5 @@ + diff --git a/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan_boss.xml b/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan_boss.xml index b88d6eb03..9fccf2c30 100644 --- a/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan_boss.xml +++ b/soh/assets/xml/N64_PAL_11/scenes/dungeons/bdan_boss.xml @@ -1,4 +1,5 @@ + diff --git a/soh/include/functions.h b/soh/include/functions.h index f6f3aedac..82b03e637 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -22,12 +22,10 @@ extern "C" void gSPSegment(void* value, int segNum, uintptr_t target); void gSPSegmentLoadRes(void* value, int segNum, uintptr_t target); -void gDPSetTextureImage(Gfx* pkt, u32 f, u32 s, u32 w, uintptr_t i); void gSPDisplayList(Gfx* pkt, Gfx* dl); void gSPDisplayListOffset(Gfx* pkt, Gfx* dl, int offset); void gSPVertex(Gfx* pkt, uintptr_t v, int n, int v0); void gSPInvalidateTexCache(Gfx* pkt, uintptr_t texAddr); -void gDPSetTextureImageFB(Gfx* pkt, u32 format, u32 size, u32 width, int fb); void cleararena(void); @@ -1261,6 +1259,8 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dListIndex); void SkelAnime_DrawSkeletonOpa(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, void* arg); +Gfx* SkelAnime_DrawSkeleton2(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw, + PostLimbDrawOpa postLimbDraw, void* arg, Gfx* gfx); void SkelAnime_DrawOpa(PlayState* play, void** skeleton, Vec3s* jointTable, OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, void* arg); void SkelAnime_DrawFlexOpa(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dListCount, @@ -2466,6 +2466,8 @@ void Message_DrawText(PlayState* play, Gfx** gfxP); void Interface_CreateQuadVertexGroup(Vtx* vtxList, s32 xStart, s32 yStart, s32 width, s32 height, u8 flippedH); void Interface_RandoRestoreSwordless(void); +s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw, + bool* shouldUpdate); //Pause Warp void PauseWarp_HandleSelection(); diff --git a/soh/include/z64.h b/soh/include/z64.h index bad2e1ca7..97f68341d 100644 --- a/soh/include/z64.h +++ b/soh/include/z64.h @@ -841,6 +841,9 @@ typedef enum { #define PAUSE_CURSOR_PAGE_LEFT 10 #define PAUSE_CURSOR_PAGE_RIGHT 11 +#define PAUSE_EQUIP_PLAYER_WIDTH 64 +#define PAUSE_EQUIP_PLAYER_HEIGHT 112 + typedef enum { /* 0x00 */ PAUSE_ITEM, /* 0x01 */ PAUSE_MAP, @@ -1481,6 +1484,8 @@ typedef struct PlayState { /* 0x1242B */ u8 unk_1242B; /* 0x1242C */ SceneTableEntry* loadedScene; /* 0x12430 */ char unk_12430[0xE8]; + // SOH [Custom Models] MTX tracker for flex based skeletons + Mtx** flexLimbOverrideMTX; } PlayState; // size = 0x12518 typedef struct { diff --git a/soh/soh/ActorDB.cpp b/soh/soh/ActorDB.cpp index ea8450ac4..de2538888 100644 --- a/soh/soh/ActorDB.cpp +++ b/soh/soh/ActorDB.cpp @@ -16,7 +16,7 @@ ActorDB* ActorDB::Instance; #undef DEFINE_ACTOR_UNSET struct AddPair { - std::string name; + const char* name; ActorInit& init; }; @@ -24,7 +24,7 @@ struct AddPair { #define DEFINE_ACTOR(name, _1, allocType) { #name, name##_InitVars }, #define DEFINE_ACTOR_UNSET(_0) -static const std::vector initialActorTable = { +static constexpr AddPair initialActorTable[] = { #include "tables/actor_table.h" }; @@ -33,7 +33,7 @@ static const std::vector initialActorTable = { #undef DEFINE_ACTOR // https://wiki.cloudmodding.com/oot/Actor_List_(Variables) -static std::unordered_map actorDescriptions = { +static constexpr std::pair actorDescriptionData[] = { { ACTOR_PLAYER, "Link" }, { ACTOR_EN_TEST, "Stalfos" }, { ACTOR_EN_GIRLA, "Shop Items" }, @@ -464,6 +464,7 @@ static std::unordered_map actorDescriptions = { { ACTOR_BG_JYA_BLOCK, "Silver Block (Child Era)" }, { ACTOR_OBJ_WARP2BLOCK, "Navi Infospot (Green, Time Block)" } }; +static std::unordered_map actorDescriptions = std::unordered_map(std::begin(actorDescriptionData), std::end(actorDescriptionData)); ActorDB::ActorDB() { db.reserve(ACTOR_NUMBER_MAX); // reserve size for all initial entries so we don't do it for each diff --git a/soh/soh/Enhancements/controls/InputViewer.cpp b/soh/soh/Enhancements/controls/InputViewer.cpp index 93727b5fa..106a08b53 100644 --- a/soh/soh/Enhancements/controls/InputViewer.cpp +++ b/soh/soh/Enhancements/controls/InputViewer.cpp @@ -20,6 +20,8 @@ static ImVec4 range2Color = ImVec4(0, 1.0f, 0, 1.0f); static const char* buttonOutlineOptions[4] = { "Always Shown", "Shown Only While Not Pressed", "Shown Only While Pressed", "Always Hidden" }; +static const char* buttonOutlineOptionsVerbose[4] = { "Outline Always Shown", "Outline Shown Only While Not Pressed", + "Outline Shown Only While Pressed", "Outline Always Hidden" }; static const char* stickModeOptions[3] = { "Always", "While In Use", "Never" }; @@ -85,6 +87,8 @@ void InputViewer::DrawElement() { Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Up", "textures/buttons/DPadUp.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down", "textures/buttons/DPadDown.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1", "textures/buttons/Mod1.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2", "textures/buttons/Mod2.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick", "textures/buttons/RightStick.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("A-Btn Outline", @@ -117,6 +121,10 @@ void InputViewer::DrawElement() { "textures/buttons/DPadUpOutline.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Dpad-Down Outline", "textures/buttons/DPadDownOutline.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-1 Outline", + "textures/buttons/Mod1Outline.png"); + Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Modifier-2 Outline", + "textures/buttons/Mod2Outline.png"); Ship::Context::GetInstance()->GetWindow()->GetGui()->LoadTextureFromRawImage("Right-Stick Outline", "textures/buttons/RightStickOutline.png"); sButtonTexturesLoaded = true; @@ -132,17 +140,19 @@ void InputViewer::DrawElement() { #endif const int showAnalogAngles = CVarGetInteger(CVAR_INPUT_VIEWER("AnalogAngles.Enabled"), 0); const int buttonOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED); + const bool useGlobalOutlineMode = CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); ImVec2 bgSize = Ship::Context::GetInstance()->GetWindow()->GetGui()->GetTextureSize("Input-Viewer-Background"); ImVec2 scaledBGSize = ImVec2(bgSize.x * scale, bgSize.y * scale); - ImGui::SetNextWindowSize(ImVec2( - scaledBGSize.x + 20, - scaledBGSize.y + - (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) + 20)); + ImGui::SetNextWindowSize( + ImVec2(scaledBGSize.x + 20, scaledBGSize.y + + (showAnalogAngles ? ImGui::CalcTextSize("X").y : 0) * scale * + CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f) + + 20)); ImGui::SetNextWindowContentSize( ImVec2(scaledBGSize.x, scaledBGSize.y + (showAnalogAngles ? 15 : 0) * scale * - CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f))); + CVarGetFloat(CVAR_INPUT_VIEWER("AnalogAngles.Scale"), 1.0f))); ImGui::SetNextWindowPos( ImVec2(mainPos.x + size.x - scaledBGSize.x - 30, mainPos.y + size.y - scaledBGSize.y - 30), ImGuiCond_FirstUseEver); @@ -176,52 +186,78 @@ void InputViewer::DrawElement() { if (CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, buttonOutlineMode); + RenderButton("B-Btn", "B-Btn Outline", pads[0].button & BTN_B, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("BBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, buttonOutlineMode); + RenderButton("A-Btn", "A-Btn Outline", pads[0].button & BTN_A, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("ABtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } // C buttons if (CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, buttonOutlineMode); + RenderButton("C-Up", "C-Up Outline", pads[0].button & BTN_CUP, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CUpOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, buttonOutlineMode); + RenderButton("C-Left", "C-Left Outline", pads[0].button & BTN_CLEFT, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CLeftOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("C-Right", "C-Right Outline", pads[0].button & BTN_CRIGHT, scaledBGSize, - buttonOutlineMode); + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CRightOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, buttonOutlineMode); + RenderButton("C-Down", "C-Down Outline", pads[0].button & BTN_CDOWN, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("CDownOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } // L/R/Z if (CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, buttonOutlineMode); + RenderButton("L-Btn", "L-Btn Outline", pads[0].button & BTN_L, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("LBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, buttonOutlineMode); + RenderButton("R-Btn", "R-Btn Outline", pads[0].button & BTN_R, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("RBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } if (CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, buttonOutlineMode); + RenderButton("Z-Btn", "Z-Btn Outline", pads[0].button & BTN_Z, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } // Start @@ -229,7 +265,9 @@ void InputViewer::DrawElement() { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Start-Btn", "Start-Btn Outline", pads[0].button & BTN_START, scaledBGSize, - buttonOutlineMode); + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } // Dpad @@ -237,18 +275,46 @@ void InputViewer::DrawElement() { ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Dpad-Left", "Dpad-Left Outline", pads[0].button & BTN_DLEFT, scaledBGSize, - buttonOutlineMode); + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Dpad-Right", "Dpad-Right Outline", pads[0].button & BTN_DRIGHT, scaledBGSize, - buttonOutlineMode); + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); - RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, buttonOutlineMode); + RenderButton("Dpad-Up", "Dpad-Up Outline", pads[0].button & BTN_DUP, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); ImGui::SetNextItemAllowOverlap(); ImGui::SetCursorPos(aPos); RenderButton("Dpad-Down", "Dpad-Down Outline", pads[0].button & BTN_DDOWN, scaledBGSize, - buttonOutlineMode); + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("DpadOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + + // Modifier 1 + if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Modifier-1", "Modifier-1 Outline", pads[0].button & BTN_MODIFIER1, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("Mod1OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); + } + // Modifier 2 + if (CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { + ImGui::SetNextItemAllowOverlap(); + ImGui::SetCursorPos(aPos); + RenderButton("Modifier-2", "Modifier-2 Outline", pads[0].button & BTN_MODIFIER2, scaledBGSize, + useGlobalOutlineMode + ? buttonOutlineMode + : CVarGetInteger(CVAR_INPUT_VIEWER("Mod2OutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); } const bool analogStickIsInDeadzone = !pads[0].stick_x && !pads[0].stick_y; @@ -359,9 +425,9 @@ InputViewerSettingsWindow::~InputViewerSettingsWindow() { } void InputViewerSettingsWindow::DrawElement() { - ImGui::SetNextWindowSize(ImVec2(450, 525), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(500, 525), ImGuiCond_FirstUseEver); - if (ImGui::Begin("Input Viewer Settings", &mIsVisible)) { + if (ImGui::Begin("Input Viewer Settings", &mIsVisible, ImGuiWindowFlags_HorizontalScrollbar)) { // gInputViewer.Scale UIWidgets::EnhancementSliderFloat("Input Viewer Scale: %.2f", "##Input", CVAR_INPUT_VIEWER("Scale"), 0.1f, 5.0f, "", @@ -381,48 +447,143 @@ void InputViewerSettingsWindow::DrawElement() { UIWidgets::PaddedSeparator(true, true); if (ImGui::CollapsingHeader("Buttons")) { - // gInputViewer.ABtn - UIWidgets::EnhancementCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.BBtn - UIWidgets::EnhancementCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.CUp - UIWidgets::EnhancementCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.CRight - UIWidgets::EnhancementCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.CDown - UIWidgets::EnhancementCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.CLeft - UIWidgets::EnhancementCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.LBtn - UIWidgets::EnhancementCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.RBtn - UIWidgets::EnhancementCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.ZBtn - UIWidgets::EnhancementCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.StartBtn - UIWidgets::EnhancementCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, true); - // gInputViewer.Dpad - UIWidgets::EnhancementCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"), false, "", - UIWidgets::CheckboxGraphics::Checkmark, false); // gInputViewer.ButtonOutlineMode UIWidgets::PaddedText("Button Outlines/Backgrounds", true, false); - UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions, - BUTTON_OUTLINE_NOT_PRESSED); + UIWidgets::EnhancementCombobox( + CVAR_INPUT_VIEWER("ButtonOutlineMode"), buttonOutlineOptions, BUTTON_OUTLINE_NOT_PRESSED, + !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1), "", + CVarGetInteger(CVAR_INPUT_VIEWER("ButtonOutlineMode"), BUTTON_OUTLINE_NOT_PRESSED)); UIWidgets::Tooltip( "Sets the desired visibility behavior for the button outline/background layers. Useful for " "custom input viewers."); + // gInputViewer.UseGlobalButtonOutlineMode + UIWidgets::EnhancementCheckbox("Use for all buttons", CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + + UIWidgets::PaddedSeparator(); + + bool useIndividualOutlines = !CVarGetInteger(CVAR_INPUT_VIEWER("UseGlobalButtonOutlineMode"), 1); + + // gInputViewer.ABtn + UIWidgets::EnhancementCheckbox("Show A-Button Layers", CVAR_INPUT_VIEWER("ABtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ABtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("ABtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.BBtn + UIWidgets::EnhancementCheckbox("Show B-Button Layers", CVAR_INPUT_VIEWER("BBtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("BBtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("BBtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.CUp + UIWidgets::EnhancementCheckbox("Show C-Up Layers", CVAR_INPUT_VIEWER("CUp"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CUp"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CUpOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.CRight + UIWidgets::EnhancementCheckbox("Show C-Right Layers", CVAR_INPUT_VIEWER("CRight"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CRight"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CRightOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.CDown + UIWidgets::EnhancementCheckbox("Show C-Down Layers", CVAR_INPUT_VIEWER("CDown"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CDown"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CDownOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.CLeft + UIWidgets::EnhancementCheckbox("Show C-Left Layers", CVAR_INPUT_VIEWER("CLeft"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("CLeft"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("CLeftOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.LBtn + UIWidgets::EnhancementCheckbox("Show L-Button Layers", CVAR_INPUT_VIEWER("LBtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("LBtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("LBtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.RBtn + UIWidgets::EnhancementCheckbox("Show R-Button Layers", CVAR_INPUT_VIEWER("RBtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("RBtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("RBtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.ZBtn + UIWidgets::EnhancementCheckbox("Show Z-Button Layers", CVAR_INPUT_VIEWER("ZBtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("ZBtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("ZBtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.StartBtn + UIWidgets::EnhancementCheckbox("Show Start Button Layers", CVAR_INPUT_VIEWER("StartBtn"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, true); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("StartBtn"), 1)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("StartBtnOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.Dpad + UIWidgets::EnhancementCheckbox("Show D-Pad Layers", CVAR_INPUT_VIEWER("Dpad"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, false); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Dpad"), 0)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("DpadOutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.Mod1 + UIWidgets::EnhancementCheckbox("Show Modifier Button 1 Layers", CVAR_INPUT_VIEWER("Mod1"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, false); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod1"), 0)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("Mod1OutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + // gInputViewer.Mod2 + UIWidgets::EnhancementCheckbox("Show Modifier Button 2 Layers", CVAR_INPUT_VIEWER("Mod2"), false, "", + UIWidgets::CheckboxGraphics::Checkmark, false); + if (useIndividualOutlines && CVarGetInteger(CVAR_INPUT_VIEWER("Mod2"), 0)) { + ImGui::Indent(); + UIWidgets::EnhancementCombobox(CVAR_INPUT_VIEWER("Mod2OutlineMode"), buttonOutlineOptionsVerbose, + BUTTON_OUTLINE_NOT_PRESSED); + ImGui::Unindent(); + } + UIWidgets::PaddedSeparator(true, true); } @@ -517,4 +678,4 @@ void InputViewerSettingsWindow::DrawElement() { ImGui::End(); } -} \ No newline at end of file +} diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp index 667d96c18..a5c1364b8 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.cpp @@ -38,6 +38,13 @@ void SohInputEditorWindow::InitElement() { addButtonName(BTN_DLEFT, "D-pad left"); addButtonName(BTN_DRIGHT, "D-pad right"); addButtonName(0, "None"); + + mDeviceIndexVisiblity.clear(); + mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard] = true; + mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Blue] = true; + for (auto index = 1; index < Ship::ShipDeviceIndex::Max; index++) { + mDeviceIndexVisiblity[static_cast(index)] = false; + } } #define INPUT_EDITOR_WINDOW_GAME_INPUT_BLOCK_ID 95237929 @@ -251,6 +258,9 @@ void SohInputEditorWindow::DrawButtonLineEditMappingButton(uint8_t port, uint16_ if (mapping == nullptr) { return; } + if (!mDeviceIndexVisiblity[mapping->GetShipDeviceIndex()]) { + return; + } ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f)); std::string icon = ""; @@ -521,6 +531,9 @@ void SohInputEditorWindow::DrawStickDirectionLineEditMappingButton(uint8_t port, if (mapping == nullptr) { return; } + if (!mDeviceIndexVisiblity[mapping->GetShipDeviceIndex()]) { + return; + } ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0f, 0.5f)); std::string icon = ""; @@ -1705,11 +1718,75 @@ void SohInputEditorWindow::DrawMiscControlPanel() { Ship::GuiWindow::EndGroupPanel(0); } +void SohInputEditorWindow::DrawDeviceVisibilityButtons() { + std::map> indexMappings; + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() + ->GetControlDeck() + ->GetDeviceIndexMappingManager() + ->GetAllDeviceIndexMappingsFromConfig()) { + auto sdlIndexMapping = std::static_pointer_cast(mapping); + if (sdlIndexMapping == nullptr) { + continue; + } + + indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), -1 }; + } + + for (auto [lusIndex, mapping] : Ship::Context::GetInstance() + ->GetControlDeck() + ->GetDeviceIndexMappingManager() + ->GetAllDeviceIndexMappings()) { + auto sdlIndexMapping = std::static_pointer_cast(mapping); + if (sdlIndexMapping == nullptr) { + continue; + } + + indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), sdlIndexMapping->GetSDLDeviceIndex() }; + } + + auto keyboardButtonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); + auto keyboardButtonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); + GetButtonColorsForLUSDeviceIndex(Ship::ShipDeviceIndex::Keyboard, keyboardButtonColor, keyboardButtonHoveredColor); + ImGui::PushStyleColor(ImGuiCol_Button, keyboardButtonColor); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, keyboardButtonHoveredColor); + bool keyboardVisible = mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard]; + if(ImGui::Button( + StringHelper::Sprintf("%s %s Keyboard", keyboardVisible ? ICON_FA_EYE : ICON_FA_EYE_SLASH, ICON_FA_KEYBOARD_O) + .c_str())) { + mDeviceIndexVisiblity[Ship::ShipDeviceIndex::Keyboard] = !keyboardVisible; + } + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + + + for (auto [lusIndex, info] : indexMappings) { + auto [name, sdlIndex] = info; + bool connected = sdlIndex != -1; + + auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); + auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); + GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor); + + ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); + bool visible = mDeviceIndexVisiblity[lusIndex]; + if(ImGui::Button( + StringHelper::Sprintf("%s %s %s (%s)", visible ? ICON_FA_EYE : ICON_FA_EYE_SLASH, connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN, name.c_str(), + connected ? StringHelper::Sprintf("SDL %d", sdlIndex).c_str() : "Disconnected") + .c_str())) { + mDeviceIndexVisiblity[lusIndex] = !visible; + } + ImGui::PopStyleColor(); + ImGui::PopStyleColor(); + } +} + void SohInputEditorWindow::DrawLinkTab() { uint8_t portIndex = 0; if (ImGui::BeginTabItem(StringHelper::Sprintf("Link (P1)###port%d", portIndex).c_str())) { DrawClearAllButton(portIndex); DrawSetDefaultsButton(portIndex); + DrawDeviceVisibilityButtons(); UpdateBitmaskToMappingIds(portIndex); UpdateStickDirectionToMappingIds(portIndex); @@ -1848,6 +1925,7 @@ void SohInputEditorWindow::DrawIvanTab() { if (ImGui::BeginTabItem(StringHelper::Sprintf("Ivan (P2)###port%d", portIndex).c_str())) { DrawClearAllButton(portIndex); DrawSetDefaultsButton(portIndex); + DrawDeviceVisibilityButtons(); UpdateBitmaskToMappingIds(portIndex); UpdateStickDirectionToMappingIds(portIndex); @@ -1903,6 +1981,7 @@ void SohInputEditorWindow::DrawDebugPortTab(uint8_t portIndex, std::string custo : customName.c_str())) { DrawClearAllButton(portIndex); DrawSetDefaultsButton(portIndex); + DrawDeviceVisibilityButtons(); UpdateBitmaskToMappingIds(portIndex); UpdateStickDirectionToMappingIds(portIndex); @@ -1972,133 +2051,6 @@ void SohInputEditorWindow::DrawClearAllButton(uint8_t portIndex) { } } -#ifdef __WIIU__ -void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { - ImGui::SameLine(); - ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(1.0f, 0.5f)); - auto popupId = StringHelper::Sprintf("setDefaultsPopup##%d", portIndex); - if (ImGui::Button(StringHelper::Sprintf("Set defaults...##%d", portIndex).c_str())) { - ImGui::OpenPopup(popupId.c_str()); - } - ImGui::PopStyleVar(); - - if (ImGui::BeginPopup(popupId.c_str())) { - std::map> indexMappings; - for (auto [lusIndex, mapping] : Ship::Context::GetInstance() - ->GetControlDeck() - ->GetDeviceIndexMappingManager() - ->GetAllDeviceIndexMappings()) { - auto wiiuIndexMapping = std::static_pointer_cast(mapping); - if (wiiuIndexMapping == nullptr) { - continue; - } - - indexMappings[lusIndex] = { wiiuIndexMapping->GetWiiUControllerName(), - wiiuIndexMapping->IsWiiUGamepad() ? INT32_MAX - : wiiuIndexMapping->GetDeviceChannel() }; - } - - bool shouldClose = false; - for (auto [lusIndex, info] : indexMappings) { - auto [name, wiiuChannel] = info; - bool isGamepad = wiiuChannel == INT32_MAX; - - auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); - auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor); - ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoveredColor); - - auto fancyName = StringHelper::Sprintf( - "%s%s", name.c_str(), isGamepad ? "" : StringHelper::Sprintf(" (%d)", wiiuChannel).c_str()); - if (ImGui::Button(StringHelper::Sprintf("%s %s", ICON_FA_GAMEPAD, fancyName.c_str()).c_str())) { - ImGui::OpenPopup(StringHelper::Sprintf("Set Defaults for %s", name.c_str()).c_str()); - } - ImGui::PopStyleColor(); - ImGui::PopStyleColor(); - if (ImGui::BeginPopupModal(StringHelper::Sprintf("Set Defaults for %s", name.c_str()).c_str(), NULL, - ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::Text("This will clear all existing mappings for\n%s on port %d.\n\nContinue?", fancyName.c_str(), - portIndex + 1); - if (ImGui::Button("Cancel")) { - shouldClose = true; - ImGui::CloseCurrentPopup(); - } - if (ImGui::Button("Set defaults")) { - Ship::Context::GetInstance() - ->GetControlDeck() - ->GetControllerByPort(portIndex) - ->ClearAllMappingsForDevice(lusIndex); - Ship::Context::GetInstance()->GetControlDeck()->GetControllerByPort(portIndex)->AddDefaultMappings( - lusIndex); - shouldClose = true; - ImGui::CloseCurrentPopup(); - } - ImGui::EndPopup(); - } - } - - if (ImGui::Button("Cancel") || shouldClose) { - ImGui::CloseCurrentPopup(); - } - - ImGui::EndPopup(); - } -} - -void SohInputEditorWindow::DrawDevicesTab() { - if (ImGui::BeginTabItem("Devices")) { - std::map> indexMappings; - for (auto [lusIndex, mapping] : Ship::Context::GetInstance() - ->GetControlDeck() - ->GetDeviceIndexMappingManager() - ->GetAllDeviceIndexMappingsFromConfig()) { - auto wiiuIndexMapping = std::static_pointer_cast(mapping); - if (wiiuIndexMapping == nullptr) { - continue; - } - - indexMappings[lusIndex] = { wiiuIndexMapping->GetWiiUControllerName(), -1 }; - } - - for (auto [lusIndex, mapping] : Ship::Context::GetInstance() - ->GetControlDeck() - ->GetDeviceIndexMappingManager() - ->GetAllDeviceIndexMappings()) { - auto wiiuIndexMapping = std::static_pointer_cast(mapping); - if (wiiuIndexMapping == nullptr) { - continue; - } - - indexMappings[lusIndex] = { wiiuIndexMapping->GetWiiUControllerName(), - wiiuIndexMapping->IsWiiUGamepad() ? INT32_MAX - : wiiuIndexMapping->GetDeviceChannel() }; - } - - for (auto [lusIndex, info] : indexMappings) { - auto [name, wiiuChannel] = info; - bool connected = wiiuChannel != -1; - bool isGamepad = wiiuChannel == INT32_MAX; - - auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); - auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor); - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); - ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); - ImGui::Button(StringHelper::Sprintf("%s %s%s", connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN, - name.c_str(), - !connected ? " (Disconnected)" - : isGamepad ? "" - : StringHelper::Sprintf(" (%d)", wiiuChannel).c_str()) - .c_str()); - ImGui::PopStyleColor(); - ImGui::PopItemFlag(); - } - - ImGui::EndTabItem(); - } -} -#else void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { ImGui::SameLine(); auto popupId = StringHelper::Sprintf("setDefaultsPopup##%d", portIndex); @@ -2192,55 +2144,6 @@ void SohInputEditorWindow::DrawSetDefaultsButton(uint8_t portIndex) { } } -void SohInputEditorWindow::DrawDevicesTab() { - if (ImGui::BeginTabItem("Devices")) { - std::map> indexMappings; - for (auto [lusIndex, mapping] : Ship::Context::GetInstance() - ->GetControlDeck() - ->GetDeviceIndexMappingManager() - ->GetAllDeviceIndexMappingsFromConfig()) { - auto sdlIndexMapping = std::static_pointer_cast(mapping); - if (sdlIndexMapping == nullptr) { - continue; - } - - indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), -1 }; - } - - for (auto [lusIndex, mapping] : Ship::Context::GetInstance() - ->GetControlDeck() - ->GetDeviceIndexMappingManager() - ->GetAllDeviceIndexMappings()) { - auto sdlIndexMapping = std::static_pointer_cast(mapping); - if (sdlIndexMapping == nullptr) { - continue; - } - - indexMappings[lusIndex] = { sdlIndexMapping->GetSDLControllerName(), sdlIndexMapping->GetSDLDeviceIndex() }; - } - - for (auto [lusIndex, info] : indexMappings) { - auto [name, sdlIndex] = info; - bool connected = sdlIndex != -1; - - auto buttonColor = ImGui::GetStyleColorVec4(ImGuiCol_Button); - auto buttonHoveredColor = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered); - GetButtonColorsForLUSDeviceIndex(lusIndex, buttonColor, buttonHoveredColor); - ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true); - ImGui::PushStyleColor(ImGuiCol_Button, buttonColor); - ImGui::Button( - StringHelper::Sprintf("%s %s (%s)", connected ? ICON_FA_GAMEPAD : ICON_FA_CHAIN_BROKEN, name.c_str(), - connected ? StringHelper::Sprintf("SDL %d", sdlIndex).c_str() : "Disconnected") - .c_str()); - ImGui::PopStyleColor(); - ImGui::PopItemFlag(); - } - - ImGui::EndTabItem(); - } -} -#endif - void SohInputEditorWindow::DrawElement() { ImGui::Begin("Controller Configuration###sohControllerConfigWindowV1", &mIsVisible); ImGui::BeginTabBar("##ControllerConfigPortTabs"); @@ -2250,7 +2153,6 @@ void SohInputEditorWindow::DrawElement() { DrawDebugPortTab(2); DrawDebugPortTab(3); } - DrawDevicesTab(); ImGui::EndTabBar(); ImGui::End(); } diff --git a/soh/soh/Enhancements/controls/SohInputEditorWindow.h b/soh/soh/Enhancements/controls/SohInputEditorWindow.h index b418a041e..aa2c3f4f4 100644 --- a/soh/soh/Enhancements/controls/SohInputEditorWindow.h +++ b/soh/soh/Enhancements/controls/SohInputEditorWindow.h @@ -92,7 +92,6 @@ class SohInputEditorWindow : public Ship::GuiWindow { void DrawLinkTab(); void DrawIvanTab(); void DrawDebugPortTab(uint8_t portIndex, std::string customName = ""); - void DrawDevicesTab(); std::set mButtonsBitmasks; std::set mDpadBitmasks; std::set mModifierButtonsBitmasks; @@ -104,4 +103,7 @@ class SohInputEditorWindow : public Ship::GuiWindow { bool mInputEditorPopupOpen; void DrawSetDefaultsButton(uint8_t portIndex); void DrawClearAllButton(uint8_t portIndex); + + std::map mDeviceIndexVisiblity; + void DrawDeviceVisibilityButtons(); }; diff --git a/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp b/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp index f31eedd2c..6b74769c1 100644 --- a/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp +++ b/soh/soh/Enhancements/cosmetics/authenticGfxPatches.cpp @@ -9,7 +9,6 @@ extern "C" { #include "objects/object_gi_soldout/object_gi_soldout.h" #include "objects/object_ik/object_ik.h" #include "objects/object_link_child/object_link_child.h" -#include "objects/object_ru2/object_ru2.h" uint32_t ResourceMgr_GameHasMasterQuest(); uint32_t ResourceMgr_GameHasOriginal(); @@ -189,25 +188,10 @@ void PatchIronKnuckleTextureOverflow() { } } -void PatchPrincessRutoEaring() { - // FAST3D: This is a hack for the issue of both TEXEL0 and TEXEL1 using the same texture with different settings. - // Ruto's earring uses both TEXEL0 and TEXEL1 to render. The issue is that it never loads anything into TEXEL1, so - // it reuses whatever happens to be there, which is the water temple brick texture. It just so happens that the - // earring texture loads into the same place in TMEM as the brick texture, so when it comes to rendering, TEXEL1 - // uses the earring texture with different clamp settings, and it displays without noticeable error. However, both - // texel samplers are not intended to be used for the same texture with different settings, so this misuse confuses - // our texture cache, and we load the wrong settings for the earrings texture. This patch is a hack that replaces - // TEXEL1 with TEXEL0, which is most likely the original intention, and all is well. - ResourceMgr_PatchGfxByName(gAdultRutoHeadDL, "RutoEaringTileFix", 162, - gsDPSetCombineLERP(TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, ENVIRONMENT, 0, 0, 0, 0, COMBINED, - TEXEL0, 0, PRIM_LOD_FRAC, COMBINED)); -} - void ApplyAuthenticGfxPatches() { PatchDekuStickTextureOverflow(); PatchFreezardTextureOverflow(); PatchIronKnuckleTextureOverflow(); - PatchPrincessRutoEaring(); } // Patches the Sold Out GI DL to render the texture in the mirror boundary diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp index 660bda7d8..0017f9f7d 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.cpp +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.cpp @@ -782,7 +782,7 @@ void DrawFlagTableArray16(const FlagTable& flagTable, uint16_t row, uint16_t& fl ImGui::PopStyleColor(); if (ImGui::IsItemHovered() && hasDescription) { ImGui::BeginTooltip(); - ImGui::Text("%s", UIWidgets::WrappedText(flagTable.flagDescriptions.at(row * 16 + flagIndex), 60)); + ImGui::Text("%s", UIWidgets::WrappedText(flagTable.flagDescriptions.at(row * 16 + flagIndex), 60).c_str()); ImGui::EndTooltip(); } ImGui::PopID(); diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index 05307af6d..da6279e80 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -200,6 +200,10 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("OcarinaGame.RoundOneNotes"), CVAR_ENHANCEMENT("OcarinaGame.RoundTwoNotes"), CVAR_ENHANCEMENT("OcarinaGame.RoundThreeNotes"), + CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), + CVAR_ENHANCEMENT("InstantFrogsGameWin"), + CVAR_ENHANCEMENT("FrogsUnlimitedFailTime"), + CVAR_ENHANCEMENT("FrogsModifyFailTime"), CVAR_ENHANCEMENT("CreditsFix"), CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), CVAR_ENHANCEMENT("StaticExplosionRadius"), @@ -222,6 +226,8 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("DisableLOD"), CVAR_ENHANCEMENT("DisableDrawDistance"), CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), + CVAR_ENHANCEMENT("WidescreenActorCulling"), + CVAR_ENHANCEMENT("ExtendedCullingExcludeGlitchActors"), CVAR_LOW_RES_MODE, CVAR_ENHANCEMENT("DrawLineupTick"), CVAR_ENHANCEMENT("QuickBongoKill"), diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.h b/soh/soh/Enhancements/randomizer/randomizer_check_objects.h index ab7e5538a..bf9cc98f7 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.h @@ -6,7 +6,9 @@ #include #include -#define TWO_ACTOR_PARAMS(a, b) (abs(a) << 16) | abs(b) +// ABS macro to use since `std::abs` is not constexpr yet +#define ABS(x) ((x) < 0 ? -(x) : (x)) +#define TWO_ACTOR_PARAMS(a, b) (ABS(a) << 16) | ABS(b) namespace RandomizerCheckObjects { bool AreaIsDungeon(RandomizerCheckArea area); diff --git a/soh/soh/Enhancements/savestates.cpp b/soh/soh/Enhancements/savestates.cpp index 4d051911e..4797c27a3 100644 --- a/soh/soh/Enhancements/savestates.cpp +++ b/soh/soh/Enhancements/savestates.cpp @@ -5,7 +5,6 @@ #include // std::sprintf #include -#include #include #include @@ -25,19 +24,6 @@ extern "C" PlayState* gPlayState; -template <> struct fmt::formatter { - constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); } - - template - auto format(const RequestType& type, FormatContext& ctx) { - switch (type) { - case RequestType::SAVE: return fmt::format_to(ctx.out(), "Save"); - case RequestType::LOAD: return fmt::format_to(ctx.out(), "Load"); - default: return fmt::format_to(ctx.out(), "Unknown"); - } - } -}; - // FROM z_lights.c // I didn't feel like moving it into a header file. #define LIGHTS_BUFFER_SIZE 32 @@ -862,11 +848,11 @@ void SaveStateMgr::ProcessSaveStateRequests(void) { this->states[request.slot]->Load(); Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "loaded state %u", request.slot); } else { - SPDLOG_ERROR("Invalid SaveState slot: {}", request.type); + SPDLOG_ERROR("Invalid SaveState slot: {}", request.slot); } break; [[unlikely]] default: - SPDLOG_ERROR("Invalid SaveState request type: {}", request.type); + SPDLOG_ERROR("Invalid SaveState request type: Unknown ({})", static_cast(request.type)); break; } this->requests.pop(); @@ -889,12 +875,12 @@ SaveStateReturn SaveStateMgr::AddRequest(const SaveStateRequest request) { requests.push(request); return SaveStateReturn::SUCCESS; } else { - SPDLOG_ERROR("Invalid SaveState slot: {}", request.type); + SPDLOG_ERROR("Invalid SaveState slot: {}", request.slot); Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(1.0f, true, "state slot %u empty", request.slot); return SaveStateReturn::FAIL_INVALID_SLOT; } [[unlikely]] default: - SPDLOG_ERROR("Invalid SaveState request type: {}", request.type); + SPDLOG_ERROR("Invalid SaveState request type: Unknown ({})", static_cast(request.type)); return SaveStateReturn::FAIL_BAD_REQUEST; } } diff --git a/soh/soh/GbiWrap.cpp b/soh/soh/GbiWrap.cpp index 2399051f5..2dad29e60 100644 --- a/soh/soh/GbiWrap.cpp +++ b/soh/soh/GbiWrap.cpp @@ -66,15 +66,6 @@ extern "C" void gSPSegmentLoadRes(void* value, int segNum, uintptr_t target) { __gSPSegment(value, segNum, target); } -extern "C" void gDPSetTextureImage(Gfx* pkt, u32 format, u32 size, u32 width, uintptr_t i) { - __gDPSetTextureImage(pkt, format, size, width, i); -} - -extern "C" void gDPSetTextureImageFB(Gfx* pkt, u32 format, u32 size, u32 width, int fb) -{ - __gDPSetTextureImageFB(pkt, format, size, width, fb); -} - extern "C" void gSPDisplayList(Gfx* pkt, Gfx* dl) { char* imgData = (char*)dl; diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 43f3e2f00..bd61fd823 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -22,7 +22,6 @@ #else #include #endif -#include #include #include "Enhancements/speechsynthesizer/SpeechSynthesizer.h" #include "Enhancements/controls/SohInputEditorWindow.h" @@ -110,12 +109,12 @@ GameInteractorSail* GameInteractorSail::Instance; #include "soh/resource/type/Skeleton.h" #include "soh/resource/type/SkeletonLimb.h" #include "soh/resource/type/Text.h" -#include "resource/factory/ArrayFactory.h" #include "resource/factory/BlobFactory.h" #include "resource/factory/DisplayListFactory.h" #include "resource/factory/MatrixFactory.h" #include "resource/factory/TextureFactory.h" #include "resource/factory/VertexFactory.h" +#include "soh/resource/importer/ArrayFactory.h" #include "soh/resource/importer/AnimationFactory.h" #include "soh/resource/importer/AudioSampleFactory.h" #include "soh/resource/importer/AudioSequenceFactory.h" @@ -155,6 +154,8 @@ Color_RGB8 zoraColor = { 0x00, 0xEC, 0x64 }; float previousImGuiScale; +bool prevAltAssets = false; + // Same as NaviColor type from OoT src (z_actor.c), but modified to be sans alpha channel for Controller LED. typedef struct { Color_RGB8 inner; @@ -326,6 +327,8 @@ OTRGlobals::OTRGlobals() { // tell LUS to reserve 3 SoH specific threads (Game, Audio, Save) context->InitResourceManager(OTRFiles, {}, 3); + prevAltAssets = CVarGetInteger(CVAR_ENHANCEMENT("AltAssets"), 0); + context->GetResourceManager()->SetAltAssetsEnabled(prevAltAssets); context->InitControlDeck({BTN_MODIFIER1, BTN_MODIFIER2}); context->GetControlDeck()->SetSinglePlayerMappingMode(true); @@ -353,8 +356,8 @@ OTRGlobals::OTRGlobals() { loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "DisplayList", static_cast(LUS::ResourceType::DisplayList), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, "DisplayList", static_cast(LUS::ResourceType::DisplayList), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Matrix", static_cast(LUS::ResourceType::Matrix), 0); - loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Array", static_cast(LUS::ResourceType::Array), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Blob", static_cast(LUS::ResourceType::Blob), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Array", static_cast(SOH::ResourceType::SOH_Array), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Animation", static_cast(SOH::ResourceType::SOH_Animation), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "PlayerAnimation", static_cast(SOH::ResourceType::SOH_PlayerAnimation), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Room", static_cast(SOH::ResourceType::SOH_Room), 0); // Is room scene? maybe? @@ -479,7 +482,7 @@ bool OTRGlobals::HasOriginal() { } uint32_t OTRGlobals::GetInterpolationFPS() { - if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { return CVarGetInteger(CVAR_SETTING("InterpolationFPS"), 20); } @@ -495,9 +498,6 @@ struct ExtensionEntry { std::string ext; }; -extern uintptr_t clearMtx; -extern "C" Mtx gMtxClear; -extern "C" MtxF gMtxFClear; extern "C" void OTRMessage_Init(); extern "C" void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples); extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len); @@ -1156,7 +1156,6 @@ extern "C" void InitOTR() { GameInteractorSail::Instance = new GameInteractorSail(); #endif - clearMtx = (uintptr_t)&gMtxClear; OTRMessage_Init(); OTRAudio_Init(); OTRExtScanner(); @@ -1265,8 +1264,6 @@ extern "C" uint64_t GetUnixTimestamp() { return (uint64_t)millis.count(); } -extern bool ToggleAltAssetsAtEndOfFrame; - extern "C" void Graph_StartFrame() { #ifndef __WIIU__ using Ship::KbScancode; @@ -1348,7 +1345,7 @@ extern "C" void Graph_StartFrame() { } #endif case KbScancode::LUS_KB_TAB: { - ToggleAltAssetsAtEndOfFrame = true; + CVarSetInteger(CVAR_ENHANCEMENT("AltAssets"), !CVarGetInteger(CVAR_ENHANCEMENT("AltAssets"), 0)); break; } } @@ -1431,11 +1428,10 @@ extern "C" void Graph_ProcessGfxCommands(Gfx* commands) { } } - if (ToggleAltAssetsAtEndOfFrame) { - ToggleAltAssetsAtEndOfFrame = false; - - // Actually update the CVar now before runing the alt asset update listeners - CVarSetInteger(CVAR_ALT_ASSETS, !CVarGetInteger(CVAR_ALT_ASSETS, 0)); + bool curAltAssets = CVarGetInteger(CVAR_ENHANCEMENT("AltAssets"), 0); + if (prevAltAssets != curAltAssets) { + prevAltAssets = curAltAssets; + Ship::Context::GetInstance()->GetResourceManager()->SetAltAssetsEnabled(curAltAssets); gfx_texture_cache_clear(); SOH::SkeletonPatcher::UpdateSkeletons(); GameInteractor::Instance->ExecuteHooks(); @@ -1622,10 +1618,14 @@ extern "C" uint8_t ResourceMgr_FileAltExists(const char* filePath) { return ExtensionCache.contains(path); } +extern "C" bool ResourceMgr_IsAltAssetsEnabled() { + return Ship::Context::GetInstance()->GetResourceManager()->IsAltAssetsEnabled(); +} + // Unloads a resource if an alternate version exists when alt assets are enabled // The resource is only removed from the internal cache to prevent it from used in the next resource lookup extern "C" void ResourceMgr_UnloadOriginalWhenAltExists(const char* resName) { - if (CVarGetInteger(CVAR_ALT_ASSETS, 0) && ResourceMgr_FileAltExists((char*) resName)) { + if (ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileAltExists((char*)resName)) { ResourceMgr_UnloadResource((char*) resName); } } @@ -1708,8 +1708,8 @@ extern "C" char* ResourceMgr_LoadTexOrDListByName(const char* filePath) { if (res->GetInitData()->Type == static_cast(LUS::ResourceType::DisplayList)) return (char*)&((std::static_pointer_cast(res))->Instructions[0]); - else if (res->GetInitData()->Type == static_cast(LUS::ResourceType::Array)) - return (char*)(std::static_pointer_cast(res))->Vertices.data(); + else if (res->GetInitData()->Type == static_cast(SOH::ResourceType::SOH_Array)) + return (char*)(std::static_pointer_cast(res))->Vertices.data(); else { return (char*)GetResourceDataByNameHandlingMQ(filePath); } @@ -1844,13 +1844,14 @@ extern "C" void ResourceMgr_UnpatchGfxByName(const char* path, const char* patch extern "C" char* ResourceMgr_LoadArrayByName(const char* path) { - auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(path)); + auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(path)); return (char*)res->Scalars.data(); } +// Return of LoadArrayByNameAsVec3s must be freed by the caller extern "C" char* ResourceMgr_LoadArrayByNameAsVec3s(const char* path) { - auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(path)); + auto res = std::static_pointer_cast(GetResourceByNameHandlingMQ(path)); // if (res->CachedGameAsset != nullptr) // return (char*)res->CachedGameAsset; @@ -1981,7 +1982,7 @@ extern "C" SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, Skel pathStr = pathStr.substr(sOtr.length()); } - bool isAlt = CVarGetInteger(CVAR_ALT_ASSETS, 0); + bool isAlt = ResourceMgr_IsAltAssetsEnabled(); if (isAlt) { pathStr = Ship::IResource::gAltAssetPrefix + pathStr; diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 3ea1b9c23..e392af4be 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -139,6 +139,7 @@ void Ctx_ReadSaveFile(uintptr_t addr, void* dramAddr, size_t size); void Ctx_WriteSaveFile(uintptr_t addr, void* dramAddr, size_t size); uint64_t GetPerfCounter(); +bool ResourceMgr_IsAltAssetsEnabled(); struct SkeletonHeader* ResourceMgr_LoadSkeletonByName(const char* path, SkelAnime* skelAnime); void ResourceMgr_UnregisterSkeleton(SkelAnime* skelAnime); void ResourceMgr_ClearSkeletons(); diff --git a/soh/soh/SohGui.cpp b/soh/soh/SohGui.cpp index 696825ec8..e0c9847eb 100644 --- a/soh/soh/SohGui.cpp +++ b/soh/soh/SohGui.cpp @@ -43,7 +43,6 @@ #include "Enhancements/resolution-editor/ResolutionEditor.h" #include "Enhancements/debugger/MessageViewer.h" -bool ToggleAltAssetsAtEndOfFrame = false; bool isBetaQuestEnabled = false; extern "C" { @@ -210,6 +209,9 @@ namespace SohGui { } void Destroy() { + auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui(); + gui->RemoveAllGuiWindows(); + mModalWindow = nullptr; mAdvancedResolutionSettingsWindow = nullptr; mRandomizerSettingsWindow = nullptr; diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 8adeaa429..cda689fd6 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -42,7 +42,6 @@ // they don't work how I expect them to so I added that because it looked good when I eyeballed it #define FA_ICON_BUTTON_FRAME_PADDING_X(icon) (((optionsButtonSize.x - ImGui::CalcTextSize(icon).x) / 2) + 2.0f) -extern bool ToggleAltAssetsAtEndOfFrame; extern bool isBetaQuestEnabled; extern "C" PlayState* gPlayState; @@ -57,6 +56,12 @@ std::string GetWindowButtonText(const char* text, bool menuOpen) { return buttonText; } +static std::unordered_map windowBackendNames = { + { Ship::WindowBackend::FAST3D_DXGI_DX11, "DirectX" }, + { Ship::WindowBackend::FAST3D_SDL_OPENGL, "OpenGL" }, + { Ship::WindowBackend::FAST3D_SDL_METAL, "Metal" }, +}; + static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large" }; static const char* filters[3] = { @@ -110,6 +115,24 @@ extern "C" SaveContext gSaveContext; namespace SohGui { +std::unordered_map availableWindowBackendsMap; +Ship::WindowBackend configWindowBackend; + +void UpdateWindowBackendObjects() { + Ship::WindowBackend runningWindowBackend = Ship::Context::GetInstance()->GetWindow()->GetWindowBackend(); + int32_t configWindowBackendId = Ship::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1); + if (Ship::Context::GetInstance()->GetWindow()->IsAvailableWindowBackend(configWindowBackendId)) { + configWindowBackend = static_cast(configWindowBackendId); + } else { + configWindowBackend = runningWindowBackend; + } + + auto availableWindowBackends = Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends(); + for (auto& backend : *availableWindowBackends) { + availableWindowBackendsMap[backend] = windowBackendNames[backend]; + } +} + void DrawMenuBarIcon() { static bool gameIconLoaded = false; if (!gameIconLoaded) { @@ -325,7 +348,7 @@ void DrawSettingsMenu() { { // FPS Slider const int minFps = 20; static int maxFps; - if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { maxFps = 360; } else { maxFps = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); @@ -393,12 +416,12 @@ void DrawSettingsMenu() { Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesOnNextTick(); #else bool matchingRefreshRate = - CVarGetInteger(CVAR_SETTING("MatchRefreshRate"), 0) && Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() != Ship::WindowBackend::DX11; + CVarGetInteger(CVAR_SETTING("MatchRefreshRate"), 0) && Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() != Ship::WindowBackend::FAST3D_DXGI_DX11; UIWidgets::PaddedEnhancementSliderInt( (currentFps == 20) ? "Frame Rate: Original (20 fps)" : "Frame Rate: %d fps", "##FPSInterpolation", CVAR_SETTING("InterpolationFPS"), minFps, maxFps, "", 20, true, true, false, matchingRefreshRate); #endif - if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { UIWidgets::Tooltip( "Uses Matrix Interpolation to create extra frames, resulting in smoother graphics.\n" "This is purely visual and does not impact game logic, execution of glitches etc.\n" @@ -413,7 +436,7 @@ void DrawSettingsMenu() { } } // END FPS Slider - if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { UIWidgets::Spacer(0); if (ImGui::Button("Match Frame Rate to Refresh Rate")) { int hz = Ship::Context::GetInstance()->GetWindow()->GetCurrentRefreshRate(); @@ -427,7 +450,7 @@ void DrawSettingsMenu() { } UIWidgets::Tooltip("Matches interpolation value to the game window's current refresh rate."); - if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::DX11) { + if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) { UIWidgets::PaddedEnhancementSliderInt(CVarGetInteger(CVAR_SETTING("ExtraLatencyThreshold"), 80) == 0 ? "Jitter fix: Off" : "Jitter fix: >= %d FPS", "##ExtraLatencyThreshold", CVAR_SETTING("ExtraLatencyThreshold"), 0, 360, "", 80, true, true, false); UIWidgets::Tooltip( @@ -448,40 +471,24 @@ void DrawSettingsMenu() { UIWidgets::Tooltip("Changes the scaling of the ImGui menu elements."); UIWidgets::PaddedSeparator(true, true, 3.0f, 3.0f); - - static std::unordered_map windowBackendNames = { - { Ship::WindowBackend::DX11, "DirectX" }, - { Ship::WindowBackend::SDL_OPENGL, "OpenGL"}, - { Ship::WindowBackend::SDL_METAL, "Metal" }, - { Ship::WindowBackend::GX2, "GX2"} - }; ImGui::Text("Renderer API (Needs reload)"); - Ship::WindowBackend runningWindowBackend = Ship::Context::GetInstance()->GetWindow()->GetWindowBackend(); - Ship::WindowBackend configWindowBackend; - int configWindowBackendId = Ship::Context::GetInstance()->GetConfig()->GetInt("Window.Backend.Id", -1); - if (configWindowBackendId != -1 && configWindowBackendId < static_cast(Ship::WindowBackend::BACKEND_COUNT)) { - configWindowBackend = static_cast(configWindowBackendId); - } else { - configWindowBackend = runningWindowBackend; - } - if (Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) { + if (availableWindowBackendsMap.size() <= 1) { UIWidgets::DisableComponent(ImGui::GetStyle().Alpha * 0.5f); } - if (ImGui::BeginCombo("##RApi", windowBackendNames[configWindowBackend])) { - for (size_t i = 0; i < Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size(); i++) { - auto backend = Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->data()[i]; - if (ImGui::Selectable(windowBackendNames[backend], backend == configWindowBackend)) { - Ship::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast(backend)); - Ship::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name", - windowBackendNames[backend]); + if (ImGui::BeginCombo("##RApi", availableWindowBackendsMap[configWindowBackend])) { + for (auto backend : availableWindowBackendsMap) { + if (ImGui::Selectable(backend.second, backend.first == configWindowBackend)) { + Ship::Context::GetInstance()->GetConfig()->SetInt("Window.Backend.Id", static_cast(backend.first)); + Ship::Context::GetInstance()->GetConfig()->SetString("Window.Backend.Name", backend.second); Ship::Context::GetInstance()->GetConfig()->Save(); + UpdateWindowBackendObjects(); } } ImGui::EndCombo(); } - if (Ship::Context::GetInstance()->GetWindow()->GetAvailableWindowBackends()->size() <= 1) { + if (availableWindowBackendsMap.size() <= 1) { UIWidgets::ReEnableComponent(""); } @@ -984,6 +991,32 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); + if (ImGui::BeginMenu("Frogs Ocarina Game")) { + UIWidgets::EnhancementCheckbox("Customize Behavior", CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame")); + UIWidgets::Tooltip("Turn on/off changes to the frogs ocarina game behavior"); + bool disabled = !CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0); + static const char* disabledTooltip = + "This option is disabled because \"Customize Behavior\" is turned off"; + UIWidgets::PaddedEnhancementCheckbox("Instant Win", CVAR_ENHANCEMENT("InstantFrogsGameWin"), true, false, disabled, disabledTooltip); + UIWidgets::Tooltip("Skips the frogs ocarina game"); + UIWidgets::PaddedEnhancementCheckbox("Unlimited Playback Time", CVAR_ENHANCEMENT("FrogsUnlimitedFailTime"), true, false, disabled, disabledTooltip); + UIWidgets::Tooltip("Removes the timer to play back the song"); + bool disabledFrog = 0; + static const char* disabledFrogTooltip = + "This option is disabled because \"Customize Behavior\" is turned off or \"Unlimited Playback Time\" is on"; + if (!CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0) || CVarGetInteger(CVAR_ENHANCEMENT("FrogsUnlimitedFailTime"), 0)) { + disabledFrog = 1; + } else { + disabledFrog = 0; + } + UIWidgets::PaddedEnhancementSliderInt("Modify note timer: %dx", "##FrogsFailTimer", CVAR_ENHANCEMENT("FrogsModifyFailTime"), 1, 5, "", 1, true, true, false, + disabledFrog, disabledFrogTooltip); + UIWidgets::Tooltip("Adjusts the time allowed for playback before failing"); + ImGui::EndMenu(); + } + + UIWidgets::Spacer(0); + UIWidgets::PaddedEnhancementCheckbox("Delete File On Death", CVAR_ENHANCEMENT("DeleteFileOnDeath"), true, false); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.0f, 0.0f, 1.0f)); UIWidgets::Tooltip("Dying will delete your file\n\n " ICON_FA_EXCLAMATION_TRIANGLE " WARNING " ICON_FA_EXCLAMATION_TRIANGLE "\nTHIS IS NOT REVERSABLE\nUSE AT YOUR OWN RISK!"); @@ -1153,12 +1186,7 @@ void DrawEnhancementsMenu() { if (ImGui::BeginMenu("Graphics")) { if (ImGui::BeginMenu("Mods")) { - if (UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", CVAR_ALT_ASSETS, false, false)) { - // The checkbox will flip the alt asset CVar, but we instead want it to change at the end of the game frame - // We toggle it back while setting the flag to update the CVar later - CVarSetInteger(CVAR_ALT_ASSETS, !CVarGetInteger(CVAR_ALT_ASSETS, 0)); - ToggleAltAssetsAtEndOfFrame = true; - } + UIWidgets::PaddedEnhancementCheckbox("Use Alternate Assets", CVAR_ENHANCEMENT("AltAssets"), false, false); UIWidgets::Tooltip("Toggle between standard assets and alternate assets. Usually mods will indicate if this setting has to be used or not."); UIWidgets::PaddedEnhancementCheckbox("Disable Bomb Billboarding", CVAR_ENHANCEMENT("DisableBombBillboarding"), true, false); UIWidgets::Tooltip("Disables bombs always rotating to face the camera. To be used in conjunction with mods that want to replace bombs with 3D objects."); @@ -1221,26 +1249,42 @@ void DrawEnhancementsMenu() { UIWidgets::Spacer(0); UIWidgets::PaddedEnhancementCheckbox("Disable LOD", CVAR_ENHANCEMENT("DisableLOD"), true, false); - UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); - if (UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", CVAR_ENHANCEMENT("DisableDrawDistance"), true, false)) { - if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) == 0) { + UIWidgets::Tooltip( + "Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); + if (UIWidgets::EnhancementSliderInt("Increase Actor Draw Distance: %dx", "##IncreaseActorDrawDistance", + CVAR_ENHANCEMENT("DisableDrawDistance"), 1, 5, "", 1, true, false)) { + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1) <= 1) { CVarSetInteger(CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), 0); } } - UIWidgets::Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); - if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) == 1) { - UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), true, false); - UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); + UIWidgets::Tooltip("Increases the range in which actors/objects are drawn"); + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1) > 1) { + UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", + CVAR_ENHANCEMENT("DisableKokiriDrawDistance"), true, false); + UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this " + "will remove their draw distance"); } - if (UIWidgets::PaddedEnhancementCheckbox("Show Age-Dependent Equipment", CVAR_ENHANCEMENT("EquimentAlwaysVisible"), true, - false)) { - UpdatePatchHand(); - } - UIWidgets::Tooltip("Makes all equipment visible, regardless of Age."); - if (CVarGetInteger(CVAR_ENHANCEMENT("EquimentAlwaysVisible"), 0) == 1) { - UIWidgets::PaddedEnhancementCheckbox("Scale Adult Equipment as Child", CVAR_ENHANCEMENT("ScaleAdultEquimentAsChild"), true, false); - UIWidgets::Tooltip("Scales all of the Adult Equipment, as well and moving some a bit, to fit on Child Link Better. May not work properly with some mods."); - } + UIWidgets::PaddedEnhancementCheckbox("Widescreen Actor Culling", CVAR_ENHANCEMENT("WidescreenActorCulling"), + true, false); + UIWidgets::Tooltip("Adjusts the horizontal culling plane to account for widescreen resolutions"); + UIWidgets::PaddedEnhancementCheckbox( + "Cull Glitch Useful Actors", CVAR_ENHANCEMENT("ExtendedCullingExcludeGlitchActors"), true, false, + !CVarGetInteger(CVAR_ENHANCEMENT("WidescreenActorCulling"), 0) && + CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1) <= 1, + "Requires Actor Draw Distance to be increased or Widescreen Actor Culling enabled"); + UIWidgets::Tooltip( + "Exclude actors that are useful for glitches from the extended culling ranges.\n" + "Some actors may still draw in the extended ranges, but will not \"update\" so that certain " + "glitches that leverage the original culling requirements will still work.\n" + "\n" + "The following actors are excluded:\n" + "- White clothed Gerudos\n" + "- King Zora\n" + "- Gossip Stones\n" + "- Boulders\n" + "- Blue Warps\n" + "- Darunia\n" + "- Gold Skulltulas"); UIWidgets::PaddedEnhancementCheckbox("N64 Mode", CVAR_LOW_RES_MODE, true, false); UIWidgets::Tooltip("Sets aspect ratio to 4:3 and lowers resolution to 240p, the N64's native resolution"); UIWidgets::PaddedEnhancementCheckbox("Glitch line-up tick", CVAR_ENHANCEMENT("DrawLineupTick"), true, false); @@ -2141,6 +2185,10 @@ void DrawRandomizerMenu() { } } +void SohMenuBar::InitElement() { + UpdateWindowBackendObjects(); +} + void SohMenuBar::DrawElement() { if (ImGui::BeginMenuBar()) { DrawMenuBarIcon(); diff --git a/soh/soh/SohMenuBar.h b/soh/soh/SohMenuBar.h index 99fb8a0ae..b90960e2c 100644 --- a/soh/soh/SohMenuBar.h +++ b/soh/soh/SohMenuBar.h @@ -10,7 +10,7 @@ class SohMenuBar : public Ship::GuiMenuBar { using Ship::GuiMenuBar::GuiMenuBar; protected: void DrawElement() override; - void InitElement() override {}; + void InitElement() override; void UpdateElement() override {}; }; } // namespace SohGui \ No newline at end of file diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index 5ceaa0012..c47ae91f7 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -24,7 +24,7 @@ namespace UIWidgets { // Automatically adds newlines to break up text longer than a specified number of characters // Manually included newlines will still be respected and reset the line length // If line is midword when it hits the limit, text should break at the last encountered space - char* WrappedText(const char* text, unsigned int charactersPerLine) { + std::string WrappedText(const char* text, unsigned int charactersPerLine) { std::string newText(text); const size_t tipLength = newText.length(); int lastSpace = -1; @@ -46,17 +46,17 @@ namespace UIWidgets { currentLineLength++; } - return strdup(newText.c_str()); + return newText; } - char* WrappedText(const std::string& text, unsigned int charactersPerLine) { + std::string WrappedText(const std::string& text, unsigned int charactersPerLine) { return WrappedText(text.c_str(), charactersPerLine); } void SetLastItemHoverText(const std::string& text) { if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("%s", WrappedText(text, 60)); + ImGui::Text("%s", WrappedText(text, 60).c_str()); ImGui::EndTooltip(); } } @@ -64,7 +64,7 @@ namespace UIWidgets { void SetLastItemHoverText(const char* text) { if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("%s", WrappedText(text, 60)); + ImGui::Text("%s", WrappedText(text, 60).c_str()); ImGui::EndTooltip(); } } @@ -75,7 +75,7 @@ namespace UIWidgets { ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?"); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("%s", WrappedText(text, 60)); + ImGui::Text("%s", WrappedText(text, 60).c_str()); ImGui::EndTooltip(); } } @@ -85,7 +85,7 @@ namespace UIWidgets { ImGui::TextColored(ImVec4(0.7f, 0.7f, 0.7f, 1.0f), "?"); if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::Text("%s", WrappedText(text, 60)); + ImGui::Text("%s", WrappedText(text, 60).c_str()); ImGui::EndTooltip(); } } @@ -95,7 +95,7 @@ namespace UIWidgets { void Tooltip(const char* text) { if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("%s", WrappedText(text)); + ImGui::SetTooltip("%s", WrappedText(text).c_str()); } } diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp index 809c4dd2d..c52802d52 100644 --- a/soh/soh/UIWidgets.hpp +++ b/soh/soh/UIWidgets.hpp @@ -54,8 +54,8 @@ namespace UIWidgets { constexpr float sliderButtonWidth = 30.0f; #endif - char* WrappedText(const char* text, unsigned int charactersPerLine = 60); - char* WrappedText(const std::string& text, unsigned int charactersPerLine); + std::string WrappedText(const char* text, unsigned int charactersPerLine = 60); + std::string WrappedText(const std::string& text, unsigned int charactersPerLine); void SetLastItemHoverText(const std::string& text); void SetLastItemHoverText(const char* text); diff --git a/soh/soh/mixer.c b/soh/soh/mixer.c index 2e80ffb16..ba6a01bc1 100644 --- a/soh/soh/mixer.c +++ b/soh/soh/mixer.c @@ -99,8 +99,14 @@ void aClearBufferImpl(uint16_t addr, int nbytes) { memset(BUF_U8(addr), 0, nbytes); } -void aLoadBufferImpl(const void *source_addr, uint16_t dest_addr, uint16_t nbytes) { +void aLoadBufferImpl(const void* source_addr, uint16_t dest_addr, uint16_t nbytes) { +#if __SANITIZE_ADDRESS__ + for (size_t i = 0; i < ROUND_DOWN_16(nbytes); i++) { + BUF_U8(dest_addr)[i] = ((const unsigned char*)source_addr)[i]; + } +#else memcpy(BUF_U8(dest_addr), source_addr, ROUND_DOWN_16(nbytes)); +#endif } void aSaveBufferImpl(uint16_t source_addr, int16_t *dest_addr, uint16_t nbytes) { diff --git a/soh/soh/resource/importer/ArrayFactory.cpp b/soh/soh/resource/importer/ArrayFactory.cpp new file mode 100644 index 000000000..39be7c093 --- /dev/null +++ b/soh/soh/resource/importer/ArrayFactory.cpp @@ -0,0 +1,64 @@ +#include "soh/resource/importer/ArrayFactory.h" +#include "soh/resource/type/Array.h" +#include "spdlog/spdlog.h" +#include "graphic/Fast3D/lus_gbi.h" + +namespace SOH { +std::shared_ptr ResourceFactoryBinaryArrayV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto array = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + array->ArrayType = (ArrayResourceType)reader->ReadUInt32(); + array->ArrayCount = reader->ReadUInt32(); + + for (uint32_t i = 0; i < array->ArrayCount; i++) { + if (array->ArrayType == ArrayResourceType::Vertex) { + // OTRTODO: Implement Vertex arrays as just a vertex resource. + F3DVtx data; + data.v.ob[0] = reader->ReadInt16(); + data.v.ob[1] = reader->ReadInt16(); + data.v.ob[2] = reader->ReadInt16(); + data.v.flag = reader->ReadUInt16(); + data.v.tc[0] = reader->ReadInt16(); + data.v.tc[1] = reader->ReadInt16(); + data.v.cn[0] = reader->ReadUByte(); + data.v.cn[1] = reader->ReadUByte(); + data.v.cn[2] = reader->ReadUByte(); + data.v.cn[3] = reader->ReadUByte(); + array->Vertices.push_back(data); + } else { + array->ArrayScalarType = (ScalarType)reader->ReadUInt32(); + + int iter = 1; + + if (array->ArrayType == ArrayResourceType::Vector) { + iter = reader->ReadUInt32(); + } + + for (int k = 0; k < iter; k++) { + ScalarData data; + + switch (array->ArrayScalarType) { + case ScalarType::ZSCALAR_S16: + data.s16 = reader->ReadInt16(); + break; + case ScalarType::ZSCALAR_U16: + data.u16 = reader->ReadUInt16(); + break; + default: + // OTRTODO: IMPLEMENT OTHER TYPES! + break; + } + + array->Scalars.push_back(data); + } + } + } + + return array; +} +} // namespace LUS diff --git a/soh/soh/resource/importer/ArrayFactory.h b/soh/soh/resource/importer/ArrayFactory.h new file mode 100644 index 000000000..b9f5ca75b --- /dev/null +++ b/soh/soh/resource/importer/ArrayFactory.h @@ -0,0 +1,11 @@ +#pragma once + +#include "resource/Resource.h" +#include "resource/ResourceFactoryBinary.h" + +namespace SOH { +class ResourceFactoryBinaryArrayV0 : public Ship::ResourceFactoryBinary { + public: + std::shared_ptr ReadResource(std::shared_ptr file) override; +}; +} // namespace LUS diff --git a/soh/soh/resource/importer/PathFactory.cpp b/soh/soh/resource/importer/PathFactory.cpp index 00807b75a..f0f92be02 100644 --- a/soh/soh/resource/importer/PathFactory.cpp +++ b/soh/soh/resource/importer/PathFactory.cpp @@ -1,5 +1,6 @@ #include "soh/resource/importer/PathFactory.h" #include "soh/resource/type/Path.h" +#include "soh/resource/logging/PathLogger.h" #include "spdlog/spdlog.h" namespace SOH { @@ -35,6 +36,60 @@ std::shared_ptr ResourceFactoryBinaryPathV0::ReadResource(std:: path->pathData.push_back(pathDataEntry); } + if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { + LogPathAsXML(path); + } + return path; } + +std::shared_ptr ResourceFactoryXMLPathV0::ReadResource(std::shared_ptr file) { + if (!FileHasValidFormatAndReader(file)) { + return nullptr; + } + + auto path = std::make_shared(file->InitData); + auto reader = std::get>(file->Reader); + + auto pathElement = reader->RootElement(); + + //path->numPaths = pathElement->IntAttribute("NumPaths"); + //path->paths.reserve(path->numPaths); + + auto pathDataElement = pathElement->FirstChildElement(); + + while (pathDataElement != nullptr) { + std::vector points; + //uint32_t pointCount = pathDataElement->IntAttribute("NumPoints"); + //points.reserve(pointCount); + + auto pointElement = pathDataElement->FirstChildElement(); + + while (pointElement != nullptr) { + Vec3s point; + point.x = pointElement->IntAttribute("X"); + point.y = pointElement->IntAttribute("Y"); + point.z = pointElement->IntAttribute("Z"); + + points.push_back(point); + + pointElement = pointElement->NextSiblingElement(); + } + + PathData pathDataEntry; + //pathDataEntry.count = pointCount; + pathDataEntry.count = points.size(); + + path->paths.push_back(points); + pathDataEntry.points = path->paths.back().data(); + + path->pathData.push_back(pathDataEntry); + + pathDataElement = pathDataElement->NextSiblingElement(); + } + + path->numPaths = path->paths.size(); + + return path; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/PathFactory.h b/soh/soh/resource/importer/PathFactory.h index ddbee772d..9dd73b110 100644 --- a/soh/soh/resource/importer/PathFactory.h +++ b/soh/soh/resource/importer/PathFactory.h @@ -2,10 +2,16 @@ #include "Resource.h" #include "ResourceFactoryBinary.h" +#include "ResourceFactoryXML.h" namespace SOH { class ResourceFactoryBinaryPathV0 : public Ship::ResourceFactoryBinary { public: std::shared_ptr ReadResource(std::shared_ptr file) override; }; + +class ResourceFactoryXMLPathV0 : public Ship::ResourceFactoryXML { + public: + std::shared_ptr ReadResource(std::shared_ptr file) override; +}; } // namespace SOH diff --git a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp index c04f717c3..f5ac8914e 100644 --- a/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetAlternateHeadersFactory.cpp @@ -17,6 +17,7 @@ std::shared_ptr SetAlternateHeadersFactory::ReadResource(std::s auto headerName = reader->ReadString(); if (!headerName.empty()) { setAlternateHeaders->headers.push_back(std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); + setAlternateHeaders->headerFileNames.push_back(headerName); } else { setAlternateHeaders->headers.push_back(nullptr); } @@ -41,7 +42,7 @@ std::shared_ptr SetAlternateHeadersFactoryXML::ReadResource(std std::string childName = child->Name(); if (childName == "AlternateHeader") { for (uint32_t i = 0; i < setAlternateHeaders->numHeaders; i++) { - auto headerName = std::string(child->Attribute("HeaderName")); + auto headerName = std::string(child->Attribute("Path")); if (!headerName.empty()) { setAlternateHeaders->headers.push_back(std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(headerName.c_str()))); } else { diff --git a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp index 65af2e0de..ed3681235 100644 --- a/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp +++ b/soh/soh/resource/importer/scenecommand/SetPathwaysFactory.cpp @@ -17,6 +17,7 @@ SetPathwaysFactory::ReadResource(std::shared_ptr initDat std::string pathFileName = reader->ReadString(); auto path = std::static_pointer_cast(Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(pathFileName.c_str())); setPathways->paths.push_back(path->GetPointer()); + setPathways->pathFileNames.push_back(pathFileName); } if (CVarGetInteger(CVAR_DEVELOPER_TOOLS("ResourceLogging"), 0)) { diff --git a/soh/soh/resource/logging/PathLogger.cpp b/soh/soh/resource/logging/PathLogger.cpp new file mode 100644 index 000000000..5c216c9ff --- /dev/null +++ b/soh/soh/resource/logging/PathLogger.cpp @@ -0,0 +1,33 @@ +#include "soh/resource/type/Path.h" +#include "spdlog/spdlog.h" + +namespace SOH { + void LogPathAsXML(std::shared_ptr resource) { + std::shared_ptr path = std::static_pointer_cast(resource); + + tinyxml2::XMLDocument doc; + tinyxml2::XMLElement* root = doc.NewElement("Path"); + doc.InsertFirstChild(root); + + for (size_t i = 0; i < path->paths.size(); i += 1) { + tinyxml2::XMLElement* pathData = doc.NewElement("PathData"); + + for (size_t j = 0; j < path->paths[i].size(); j += 1) { + tinyxml2::XMLElement* pathPoint = doc.NewElement("PathPoint"); + + pathPoint->SetAttribute("X", path->paths[i][j].x); + pathPoint->SetAttribute("Y", path->paths[i][j].y); + pathPoint->SetAttribute("Z", path->paths[i][j].z); + + pathData->InsertEndChild(pathPoint); + } + + root->InsertEndChild(pathData); + } + + tinyxml2::XMLPrinter printer; + doc.Accept(&printer); + + SPDLOG_INFO("{}: {}", resource->GetInitData()->Path, printer.CStr()); + } +} \ No newline at end of file diff --git a/soh/soh/resource/logging/PathLogger.h b/soh/soh/resource/logging/PathLogger.h new file mode 100644 index 000000000..a5e42aeaf --- /dev/null +++ b/soh/soh/resource/logging/PathLogger.h @@ -0,0 +1,6 @@ +#include "Resource.h" +#include "soh/OTRGlobals.h" + +namespace SOH { + void LogPathAsXML(std::shared_ptr resource); +} \ No newline at end of file diff --git a/soh/soh/resource/logging/SceneCommandLoggers.cpp b/soh/soh/resource/logging/SceneCommandLoggers.cpp index 7c55bcaf0..805de9be0 100644 --- a/soh/soh/resource/logging/SceneCommandLoggers.cpp +++ b/soh/soh/resource/logging/SceneCommandLoggers.cpp @@ -73,6 +73,12 @@ void LogAlternateHeadersAsXML(std::shared_ptr resource) { tinyxml2::XMLElement* root = doc.NewElement("SetAlternateHeaders"); doc.InsertFirstChild(root); + for (size_t i = 0; i < setAlternateHeaders->headerFileNames.size(); i++) { + tinyxml2::XMLElement* entry = doc.NewElement("Header"); + entry->SetAttribute("Path", setAlternateHeaders->headerFileNames[i].c_str()); + root->InsertEndChild(entry); + } + tinyxml2::XMLPrinter printer; doc.Accept(&printer); diff --git a/soh/soh/resource/type/Array.cpp b/soh/soh/resource/type/Array.cpp new file mode 100644 index 000000000..70d5d42ba --- /dev/null +++ b/soh/soh/resource/type/Array.cpp @@ -0,0 +1,45 @@ +#include "Array.h" +#include "graphic/Fast3D/lus_gbi.h" +namespace SOH { +Array::Array() : Resource(std::shared_ptr()) { +} + +void* Array::GetPointer() { + void* dataPointer = nullptr; + switch (ArrayType) { + case ArrayResourceType::Vertex: + dataPointer = Vertices.data(); + break; + case ArrayResourceType::Scalar: + default: + dataPointer = Scalars.data(); + break; + } + + return dataPointer; +} + +size_t Array::GetPointerSize() { + size_t typeSize = 0; + switch (ArrayType) { + case ArrayResourceType::Vertex: + typeSize = sizeof(F3DVtx); + break; + case ArrayResourceType::Scalar: + default: + switch (ArrayScalarType) { + case ScalarType::ZSCALAR_S16: + typeSize = sizeof(int16_t); + break; + case ScalarType::ZSCALAR_U16: + typeSize = sizeof(uint16_t); + break; + default: + // OTRTODO: IMPLEMENT OTHER TYPES! + break; + } + break; + } + return ArrayCount * typeSize; +} +} // namespace LUS diff --git a/soh/soh/resource/type/Array.h b/soh/soh/resource/type/Array.h new file mode 100644 index 000000000..ba41ec049 --- /dev/null +++ b/soh/soh/resource/type/Array.h @@ -0,0 +1,85 @@ +#pragma once + +#include "resource/Resource.h" + +union F3DVtx; +namespace SOH { +typedef union ScalarData { + uint8_t u8; + int8_t s8; + uint16_t u16; + int16_t s16; + uint32_t u32; + int32_t s32; + uint64_t u64; + int64_t s64; + float f32; + double f64; +} ScalarData; + +enum class ScalarType { + ZSCALAR_NONE, + ZSCALAR_S8, + ZSCALAR_U8, + ZSCALAR_X8, + ZSCALAR_S16, + ZSCALAR_U16, + ZSCALAR_X16, + ZSCALAR_S32, + ZSCALAR_U32, + ZSCALAR_X32, + ZSCALAR_S64, + ZSCALAR_U64, + ZSCALAR_X64, + ZSCALAR_F32, + ZSCALAR_F64 +}; + +// OTRTODO: Replace this with something that can be shared between the exporter and importer... +enum class ArrayResourceType { + Error, + Animation, + Array, + AltHeader, + Background, + Blob, + CollisionHeader, + Cutscene, + DisplayList, + Limb, + LimbTable, + Mtx, + Path, + PlayerAnimationData, + Room, + RoomCommand, + Scalar, + Scene, + Skeleton, + String, + Symbol, + Texture, + TextureAnimation, + TextureAnimationParams, + Vector, + Vertex, + Audio +}; + +class Array : public Ship::Resource { + public: + using Resource::Resource; + + Array(); + + void* GetPointer() override; + size_t GetPointerSize() override; + + ArrayResourceType ArrayType; + ScalarType ArrayScalarType; + size_t ArrayCount; + // OTRTODO: Should be a vector of resource pointers... + std::vector Scalars; + std::vector Vertices; +}; +} // namespace LUS diff --git a/soh/soh/resource/type/Skeleton.cpp b/soh/soh/resource/type/Skeleton.cpp index 8ac676c55..057f24b65 100644 --- a/soh/soh/resource/type/Skeleton.cpp +++ b/soh/soh/resource/type/Skeleton.cpp @@ -65,12 +65,11 @@ void SkeletonPatcher::ClearSkeletons() } void SkeletonPatcher::UpdateSkeletons() { - bool isHD = CVarGetInteger(CVAR_ALT_ASSETS, 0); + auto resourceMgr = Ship::Context::GetInstance()->GetResourceManager(); + bool isHD = resourceMgr->IsAltAssetsEnabled(); for (auto skel : skeletons) { Skeleton* newSkel = - (Skeleton*)Ship::Context::GetInstance()->GetResourceManager() - ->LoadResource((isHD ? Ship::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true) - .get(); + (Skeleton*)resourceMgr->LoadResource((isHD ? Ship::IResource::gAltAssetPrefix : "") + skel.vanillaSkeletonPath, true).get(); if (newSkel != nullptr) { skel.skelAnime->skeleton = newSkel->skeletonData.skeletonHeader.segment; diff --git a/soh/soh/resource/type/SohResourceType.h b/soh/soh/resource/type/SohResourceType.h index fdf39031e..6455c28c7 100644 --- a/soh/soh/resource/type/SohResourceType.h +++ b/soh/soh/resource/type/SohResourceType.h @@ -2,6 +2,7 @@ namespace SOH { enum class ResourceType { + SOH_Array = 0x4F415252, // OARR SOH_Animation = 0x4F414E4D, // OANM SOH_PlayerAnimation = 0x4F50414D, // OPAM SOH_Room = 0x4F524F4D, // OROM diff --git a/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h b/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h index fdddee3f8..596e0a22e 100644 --- a/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h +++ b/soh/soh/resource/type/scenecommand/SetAlternateHeaders.h @@ -21,6 +21,7 @@ class SetAlternateHeaders : public SceneCommand { size_t GetPointerSize(); uint32_t numHeaders; + std::vector headerFileNames; std::vector> headers; }; }; // namespace LUS diff --git a/soh/src/code/game.c b/soh/src/code/game.c index f0988c7c3..e1974ed98 100644 --- a/soh/src/code/game.c +++ b/soh/src/code/game.c @@ -239,16 +239,15 @@ void GameState_ReqPadData(GameState* gameState) { PadMgr_RequestPadData(&gPadMgr, &gameState->input[0], 1); } -// OTRTODO -int fbTest = -1; +// Framebuffer for the Link preview on the pause menu equipment sub-screen +int gPauseLinkFrameBuffer = -1; void GameState_Update(GameState* gameState) { GraphicsContext* gfxCtx = gameState->gfxCtx; - if (fbTest == -1) - { - fbTest = gfx_create_framebuffer(64, 112, SCREEN_WIDTH, SCREEN_HEIGHT, true); - //fbTest = gfx_create_framebuffer(256, 512); + if (gPauseLinkFrameBuffer == -1) { + gPauseLinkFrameBuffer = gfx_create_framebuffer(PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT, + PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT, true); } GameState_SetFrameBuffer(gfxCtx); @@ -467,7 +466,7 @@ void GameState_Destroy(GameState* gameState) { // Performing clear skeletons before unload resources fixes an actor heap corruption crash due to the skeleton patching system. ResourceMgr_ClearSkeletons(); - if (CVarGetInteger(CVAR_ALT_ASSETS, 0)) { + if (ResourceMgr_IsAltAssetsEnabled()) { ResourceUnloadDirectory("alt/*"); gfx_texture_cache_clear(); } diff --git a/soh/src/code/gfxprint.c b/soh/src/code/gfxprint.c index 1717e46b3..6d8686074 100644 --- a/soh/src/code/gfxprint.c +++ b/soh/src/code/gfxprint.c @@ -141,7 +141,7 @@ static const ALIGN_ASSET(2) char rGfxPrintFontDataAlt[] = drGfxPrintFontDataAlt; // https://github.com/HarbourMasters/Shipwright/issues/2762 typedef enum {hardcoded, otrDefault, otrAlt} font_texture_t; font_texture_t GfxPrint_TextureToUse() { - if (CVarGetInteger(CVAR_ALT_ASSETS, 0) && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) { + if (ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileExists(rGfxPrintFontDataAlt)) { // If we have alt assets enabled, and we have alt prefixed font texture, use that return otrAlt; } else if (ResourceMgr_FileExists(rGfxPrintFontData)) { diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 98e414d55..5b8aa1eca 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1228,14 +1228,6 @@ void Actor_Init(Actor* actor, PlayState* play) { actor->uncullZoneForward = 1000.0f; actor->uncullZoneScale = 350.0f; actor->uncullZoneDownward = 700.0f; - if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room - && actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence - && actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning - && (play->sceneNum != SCENE_DODONGOS_CAVERN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room - actor->uncullZoneForward = 32767.0f; - actor->uncullZoneScale = 32767.0f; - actor->uncullZoneDownward = 32767.0f; - } CollisionCheck_InitInfo(&actor->colChkInfo); actor->floorBgId = BGCHECK_SCENE; ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f); @@ -2897,34 +2889,93 @@ s32 func_800314B0(PlayState* play, Actor* actor) { s32 func_800314D4(PlayState* play, Actor* actor, Vec3f* arg2, f32 arg3) { f32 var; - if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0 && actor->id != ACTOR_EN_TORCH2 && actor->id != ACTOR_EN_BLKOBJ // Extra check for Dark Link and his room - && actor->id != ACTOR_EN_HORSE // Check for Epona, else if we call her she will spawn at the other side of the map + we can hear her during the title screen sequence - && actor->id != ACTOR_EN_HORSE_GANON && actor->id != ACTOR_EN_HORSE_ZELDA // check for Zelda's and Ganondorf's horses that will always be scene during cinematic whith camera paning - && (play->sceneNum != SCENE_DODONGOS_CAVERN && actor->id != ACTOR_EN_ZF)) { // Check for DC and Lizalfos for the case where the miniboss music would still play under certains conditions and changing room - return true; - } - if ((arg2->z > -actor->uncullZoneScale) && (arg2->z < (actor->uncullZoneForward + actor->uncullZoneScale))) { var = (arg3 < 1.0f) ? 1.0f : 1.0f / arg3; - // #region SoH [Widescreen support] - // Doors will cull quite noticeably on wider screens. For these actors the zone is increased - f32 limit = 1.0f; - if (((actor->id == ACTOR_EN_DOOR) || (actor->id == ACTOR_DOOR_SHUTTER)) && CVarGetInteger(CVAR_GENERAL("IncreaseDoorUncullZones"), 1)) { - limit = 2.0f; - } - - if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < limit) && - (((arg2->y + actor->uncullZoneDownward) * var) > -limit) && - (((arg2->y - actor->uncullZoneScale) * var) < limit)) { + if ((((fabsf(arg2->x) - actor->uncullZoneScale) * var) < 1.0f) && + (((arg2->y + actor->uncullZoneDownward) * var) > -1.0f) && + (((arg2->y - actor->uncullZoneScale) * var) < 1.0f)) { return true; } - // #endregion } return false; } +// #region SOH [Enhancements] Allows us to increase the draw and update distance independently, +// mostly a modified version of the function above and additional tweaks for some specfic actors +s32 Ship_CalcShouldDrawAndUpdate(PlayState* play, Actor* actor, Vec3f* projectedPos, f32 projectedW, bool* shouldDraw, + bool* shouldUpdate) { + f32 clampedProjectedW; + + // Check if the actor passes its original/vanilla culling requirements + if (func_800314D4(play, actor, projectedPos, projectedW)) { + *shouldUpdate = true; + *shouldDraw = true; + return true; + } + + // Skip cutscne actors that depend on culling to hide from camera pans + if (actor->id == ACTOR_EN_VIEWER) { + return false; + } + + s32 multiplier = CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1); + multiplier = MAX(multiplier, 1); + + // Some actors have a really short forward value, so we need to add to it before the multiplier to increase the + // final strength of the forward culling + f32 adder = (actor->uncullZoneForward < 500) ? 1000.0f : 0.0f; + + if ((projectedPos->z > -actor->uncullZoneScale) && + (projectedPos->z < (((actor->uncullZoneForward + adder) * multiplier) + actor->uncullZoneScale))) { + clampedProjectedW = (projectedW < 1.0f) ? 1.0f : 1.0f / projectedW; + + f32 ratioAdjusted = 1.0f; + + if (CVarGetInteger(CVAR_ENHANCEMENT("WidescreenActorCulling"), 0)) { + f32 originalAspectRatio = 4.0f / 3.0f; + f32 currentAspectRatio = OTRGetAspectRatio(); + ratioAdjusted = MAX(currentAspectRatio / originalAspectRatio, 1.0f); + } + + if ((((fabsf(projectedPos->x) - actor->uncullZoneScale) * (clampedProjectedW / ratioAdjusted)) < 1.0f) && + (((projectedPos->y + actor->uncullZoneDownward) * clampedProjectedW) > -1.0f) && + (((projectedPos->y - actor->uncullZoneScale) * clampedProjectedW) < 1.0f)) { + + if (CVarGetInteger(CVAR_ENHANCEMENT("ExtendedCullingExcludeGlitchActors"), 0)) { + // These actors are safe to draw without impacting glitches + if ((actor->id == ACTOR_OBJ_BOMBIWA || actor->id == ACTOR_OBJ_HAMISHI || + actor->id == ACTOR_EN_ISHI) || // Boulders (hookshot through collision) + actor->id == ACTOR_EN_GS || // Gossip stones (text delay) + actor->id == ACTOR_EN_GE1 || // White gerudos (gate clip/archery room transition) + actor->id == ACTOR_EN_KZ || // King Zora (unfreeze glitch) + actor->id == ACTOR_EN_DU || // Darunia (Fire temple BK skip) + actor->id == ACTOR_DOOR_WARP1 // Blue warps (wrong warps) + ) { + *shouldDraw = true; + return true; + } + + // Skip these actors entirely as their draw funcs impacts glitches + if ((actor->id == ACTOR_EN_SW && + (((actor->params & 0xE000) >> 0xD) == 1 || + ((actor->params & 0xE000) >> 0xD) == 2)) // Gold Skulltulas (hitbox at 0,0) + ) { + return false; + } + } + + *shouldDraw = true; + *shouldUpdate = true; + return true; + } + } + + return false; +} +// #endregion + void func_800315AC(PlayState* play, ActorContext* actorCtx) { s32 invisibleActorCounter; Actor* invisibleActors[INVISIBLE_ACTOR_MAX]; @@ -2960,18 +3011,35 @@ void func_800315AC(PlayState* play, ActorContext* actorCtx) { } } + // #region SOH [Enhancement] Extended culling updates + bool shipShouldDraw = false; + bool shipShouldUpdate = false; if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(70) == 0)) { - if (func_800314B0(play, actor)) { - actor->flags |= ACTOR_FLAG_ACTIVE; + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1) > 1 || + CVarGetInteger(CVAR_ENHANCEMENT("WidescreenActorCulling"), 0)) { + Ship_CalcShouldDrawAndUpdate(play, actor, &actor->projectedPos, actor->projectedW, &shipShouldDraw, + &shipShouldUpdate); + + if (shipShouldUpdate) { + actor->flags |= ACTOR_FLAG_ACTIVE; + } else { + actor->flags &= ~ACTOR_FLAG_ACTIVE; + } } else { - actor->flags &= ~ACTOR_FLAG_ACTIVE; + if (func_800314B0(play, actor)) { + actor->flags |= ACTOR_FLAG_ACTIVE; + } else { + actor->flags &= ~ACTOR_FLAG_ACTIVE; + } } } actor->isDrawn = false; if ((HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(71) == 0)) { - if ((actor->init == NULL) && (actor->draw != NULL) && (actor->flags & (ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_ACTIVE))) { + if ((actor->init == NULL) && (actor->draw != NULL) && + ((actor->flags & (ACTOR_FLAG_DRAW_WHILE_CULLED | ACTOR_FLAG_ACTIVE)) || shipShouldDraw)) { + // #endregion if ((actor->flags & ACTOR_FLAG_LENS) && ((play->roomCtx.curRoom.lensMode == LENS_MODE_HIDE_ACTORS) || play->actorCtx.lensActive || (actor->room != play->roomCtx.curRoom.num))) { diff --git a/soh/src/code/z_fcurve_data_skelanime.c b/soh/src/code/z_fcurve_data_skelanime.c index 91b6dc90c..c75450be2 100644 --- a/soh/src/code/z_fcurve_data_skelanime.c +++ b/soh/src/code/z_fcurve_data_skelanime.c @@ -131,10 +131,6 @@ void SkelCurve_DrawLimb(PlayState* play, s32 limbIndex, SkelAnimeCurve* skelCurv Matrix_TranslateRotateZYX(&pos, &rot); Matrix_Scale(scale.x, scale.y, scale.z, MTXMODE_APPLY); - if (CVarGetInteger(CVAR_ENHANCEMENT("DisableLOD"), 0)) { - lod = 0; - } - if (lod == 0) { s32 pad1; diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 4847bb47e..8da747dd5 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1116,7 +1116,7 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) { } } if (msgCtx->textDelayTimer == 0) { - msgCtx->textDrawPos = i + CVarGetInteger(CVAR_ENHANCEMENT("TextSpeed"), 2); + msgCtx->textDrawPos = i + CVarGetInteger(CVAR_ENHANCEMENT("TextSpeed"), 1); msgCtx->textDelayTimer = msgCtx->textDelay; } else { msgCtx->textDelayTimer--; diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index f5c529a66..94538c229 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -2079,10 +2079,12 @@ void Pause_DrawTriforceSpot(PlayState* play, s32 showLightColumn) { rotation += 0x03E8; } -void Player_DrawPauseImpl(PlayState* play, void* seg04, void* seg06, SkelAnime* skelAnime, Vec3f* pos, Vec3s* rot, - f32 scale, s32 sword, s32 tunic, s32 shield, s32 boots, s32 width, s32 height, Vec3f* eye, Vec3f* at, - f32 fovy, void* img1, void* img2) { - static Vp viewport = { 128, 224, 511, 0, 128, 224, 511, 0 }; +void Player_DrawPauseImpl(PlayState* play, void* gameplayKeep, void* linkObject, SkelAnime* skelAnime, Vec3f* pos, + Vec3s* rot, f32 scale, s32 sword, s32 tunic, s32 shield, s32 boots, s32 width, s32 height, + Vec3f* eye, Vec3f* at, f32 fovy, void* colorFrameBuffer, void* depthFrameBuffer) { + // Note: the viewport x and y values are overwritten below, before usage + static Vp viewport = { (PAUSE_EQUIP_PLAYER_WIDTH / 2) << 2, (PAUSE_EQUIP_PLAYER_HEIGHT / 2) << 2, G_MAXZ / 2, 0, + (PAUSE_EQUIP_PLAYER_WIDTH / 2) << 2, (PAUSE_EQUIP_PLAYER_HEIGHT / 2) << 2, G_MAXZ / 2, 0 }; static Lights1 lights1 = gdSPDefLights1(80, 80, 80, 255, 255, 255, 84, 84, 172); static Vec3f lightDir = { 89.8f, 0.0f, 89.8f }; u8 playerSwordAndShield[2]; @@ -2110,6 +2112,24 @@ void Player_DrawPauseImpl(PlayState* play, void* seg04, void* seg06, SkelAnime* gDPSetScissor(POLY_OPA_DISP++, G_SC_NON_INTERLACE, 0, 0, width, height); gSPClipRatio(POLY_OPA_DISP++, FRUSTRATIO_1); + gDPSetColorImage(POLY_OPA_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, depthFrameBuffer); + gDPSetCycleType(POLY_OPA_DISP++, G_CYC_FILL); + gDPSetRenderMode(POLY_OPA_DISP++, G_RM_NOOP, G_RM_NOOP2); + gDPSetFillColor(POLY_OPA_DISP++, (GPACK_ZDZ(G_MAXFBZ, 0) << 16) | GPACK_ZDZ(G_MAXFBZ, 0)); + gDPFillRectangle(POLY_OPA_DISP++, 0, 0, width - 1, height - 1); + + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetColorImage(POLY_OPA_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, colorFrameBuffer); + gDPSetCycleType(POLY_OPA_DISP++, G_CYC_FILL); + gDPSetRenderMode(POLY_OPA_DISP++, G_RM_NOOP, G_RM_NOOP2); + gDPSetFillColor(POLY_OPA_DISP++, (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1)); + gDPFillRectangle(POLY_OPA_DISP++, 0, 0, width - 1, height - 1); + + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetDepthImage(POLY_OPA_DISP++, depthFrameBuffer); + viewport.vp.vscale[0] = viewport.vp.vtrans[0] = width * 2; viewport.vp.vscale[1] = viewport.vp.vtrans[1] = height * 2; gSPViewport(POLY_OPA_DISP++, &viewport); @@ -2130,8 +2150,8 @@ void Player_DrawPauseImpl(PlayState* play, void* seg04, void* seg06, SkelAnime* pos->y - (CVarGetInteger(CVAR_GENERAL("PauseTriforce"), 0) ? 16 : 0), pos->z, rot); Matrix_Scale(scale * (CVarGetInteger(CVAR_ENHANCEMENT("MirroredWorld"), 0) ? -1 : 1), scale, scale, MTXMODE_APPLY); - gSPSegment(POLY_OPA_DISP++, 0x04, seg04); - gSPSegment(POLY_OPA_DISP++, 0x06, seg06); + gSPSegment(POLY_OPA_DISP++, 0x04, gameplayKeep); + gSPSegment(POLY_OPA_DISP++, 0x06, linkObject); gSPSetLights1(POLY_OPA_DISP++, lights1); @@ -2399,14 +2419,16 @@ void Player_DrawPause(PlayState* play, u8* segment, SkelAnime* skelAnime, Vec3f* } srcTable = ResourceMgr_LoadArrayByNameAsVec3s(srcTable); + Vec3s* ogSrcTable = srcTable; destTable = skelAnime->jointTable; for (i = 0; i < skelAnime->limbCount; i++) { *destTable++ = *srcTable++; } + free(ogSrcTable); } - Player_DrawPauseImpl(play, segment + 0x3800, segment + 0x8800, skelAnime, pos, rot, scale, sword, tunic, shield, - boots, 64, 112, &eye, &at, 60.0f, play->state.gfxCtx->curFrameBuffer, - play->state.gfxCtx->curFrameBuffer + 0x1C00); + boots, PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT, &eye, &at, 60.0f, + play->state.gfxCtx->curFrameBuffer, + play->state.gfxCtx->curFrameBuffer + (PAUSE_EQUIP_PLAYER_WIDTH * PAUSE_EQUIP_PLAYER_HEIGHT)); } diff --git a/soh/src/code/z_rcp.c b/soh/src/code/z_rcp.c index adfa946e7..978c04d3c 100644 --- a/soh/src/code/z_rcp.c +++ b/soh/src/code/z_rcp.c @@ -1539,7 +1539,7 @@ void Gfx_SetupFrame(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b) { gDPSetCycleType(POLY_OPA_DISP++, G_CYC_FILL); gDPSetRenderMode(POLY_OPA_DISP++, G_RM_NOOP, G_RM_NOOP2); gDPSetFillColor(POLY_OPA_DISP++, (GPACK_ZDZ(G_MAXFBZ, 0) << 16) | GPACK_ZDZ(G_MAXFBZ, 0)); - gDPFillRectangle(POLY_OPA_DISP++, 0, letterboxSize, gScreenWidth - 1, gScreenHeight - letterboxSize - 1); + gDPFillWideRectangle(POLY_OPA_DISP++, OTRGetRectDimensionFromLeftEdge(0), letterboxSize, OTRGetRectDimensionFromRightEdge(gScreenWidth - 1), gScreenHeight - letterboxSize - 1); gDPPipeSync(POLY_OPA_DISP++); // Fill the whole screen with the base color @@ -1548,7 +1548,7 @@ void Gfx_SetupFrame(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b) { gDPSetCycleType(POLY_OPA_DISP++, G_CYC_FILL); gDPSetRenderMode(POLY_OPA_DISP++, G_RM_NOOP, G_RM_NOOP2); gDPSetFillColor(POLY_OPA_DISP++, (GPACK_RGBA5551(r, g, b, 1) << 16) | GPACK_RGBA5551(r, g, b, 1)); - gDPFillRectangle(POLY_OPA_DISP++, 0, letterboxSize, gScreenWidth - 1, gScreenHeight - letterboxSize - 1); + gDPFillWideRectangle(POLY_OPA_DISP++, OTRGetRectDimensionFromLeftEdge(0), letterboxSize, OTRGetRectDimensionFromRightEdge(gScreenWidth - 1), gScreenHeight - letterboxSize - 1); gDPPipeSync(POLY_OPA_DISP++); // Draw the letterbox if applicable (uses the same color as the screen base) @@ -1557,8 +1557,8 @@ void Gfx_SetupFrame(GraphicsContext* gfxCtx, u8 r, u8 g, u8 b) { gDPSetCycleType(OVERLAY_DISP++, G_CYC_FILL); gDPSetRenderMode(OVERLAY_DISP++, G_RM_NOOP, G_RM_NOOP2); gDPSetFillColor(OVERLAY_DISP++, (GPACK_RGBA5551(r, g, b, 1) << 16) | GPACK_RGBA5551(r, g, b, 1)); - gDPFillRectangle(OVERLAY_DISP++, 0, 0, gScreenWidth - 1, letterboxSize - 1); - gDPFillRectangle(OVERLAY_DISP++, 0, gScreenHeight - letterboxSize, gScreenWidth - 1, gScreenHeight - 1); + gDPFillWideRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromLeftEdge(0), 0, OTRGetRectDimensionFromRightEdge(gScreenWidth - 1), letterboxSize - 1); + gDPFillWideRectangle(OVERLAY_DISP++, OTRGetRectDimensionFromLeftEdge(0), gScreenHeight - letterboxSize, OTRGetRectDimensionFromRightEdge(gScreenWidth - 1), gScreenHeight - 1); gDPPipeSync(OVERLAY_DISP++); } } diff --git a/soh/src/code/z_skelanime.c b/soh/src/code/z_skelanime.c index 3df8a26a5..0bcf39236 100644 --- a/soh/src/code/z_skelanime.c +++ b/soh/src/code/z_skelanime.c @@ -148,6 +148,8 @@ void SkelAnime_DrawFlexLimbLod(PlayState* play, s32 limbIndex, void** skeleton, newDList = limbDList = limb->dLists[lod]; + play->flexLimbOverrideMTX = mtx; + if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &newDList, &pos, &rot, arg)) { Matrix_TranslateRotateZYX(&pos, &rot); if (newDList != NULL) { @@ -220,6 +222,8 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable, newDList = limbDList = rootLimb->dLists[lod]; + play->flexLimbOverrideMTX = &mtx; + if ((overrideLimbDraw == 0) || !overrideLimbDraw(play, 1, &newDList, &pos, &rot, arg)) { Matrix_TranslateRotateZYX(&pos, &rot); if (newDList != NULL) { @@ -306,6 +310,20 @@ void SkelAnime_DrawSkeletonOpa(PlayState* play, SkelAnime* skelAnime, OverrideLi } } +Gfx* SkelAnime_DrawSkeleton2(PlayState* play, SkelAnime* skelAnime, OverrideLimbDrawOpa overrideLimbDraw, + PostLimbDrawOpa postLimbDraw, void* arg, Gfx* gfx) +{ + if (skelAnime->skeletonHeader->skeletonType == SKELANIME_TYPE_NORMAL) { + return SkelAnime_Draw(play, skelAnime->skeleton, skelAnime->jointTable, overrideLimbDraw, postLimbDraw, arg, gfx); + } else if (skelAnime->skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + FlexSkeletonHeader* flexHeader = (FlexSkeletonHeader*)skelAnime->skeletonHeader; + return SkelAnime_DrawFlex(play, skelAnime->skeleton, skelAnime->jointTable, flexHeader->dListCount, + overrideLimbDraw, postLimbDraw, arg, gfx); + } + + return gfx; +} + /** * Draw all limbs of type `StandardLimb` in a given skeleton to the polyOpa buffer */ @@ -383,6 +401,8 @@ void SkelAnime_DrawFlexLimbOpa(PlayState* play, s32 limbIndex, void** skeleton, newDList = limbDList = limb->dList; + play->flexLimbOverrideMTX = limbMatricies; + if ((overrideLimbDraw == NULL) || !overrideLimbDraw(play, limbIndex, &newDList, &pos, &rot, arg)) { Matrix_TranslateRotateZYX(&pos, &rot); if (newDList != NULL) { diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c index a825f67d7..d3f279575 100644 --- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c +++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c @@ -1288,6 +1288,10 @@ block_1: if (*dList != NULL) { OPEN_DISPS(play->state.gfxCtx); + if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + MATRIX_TOMTX(*play->flexLimbOverrideMTX); + } + mtxScaleZ = 1.0f; mtxScaleY = 1.0f; @@ -1308,11 +1312,20 @@ block_1: Matrix_RotateX(-(this->unk_25C[limbIndex] * 0.115f), MTXMODE_APPLY); } - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD); + } else { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + } + gSPDisplayList(POLY_OPA_DISP++, *dList); Matrix_Pop(); + if (this->skelAnime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + (*play->flexLimbOverrideMTX)++; + } + CLOSE_DISPS(play->state.gfxCtx); } { s32 pad; } // Required to match diff --git a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c index e05b73650..842ec0fab 100644 --- a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c +++ b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c @@ -2015,12 +2015,26 @@ s32 BossGoma_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f Matrix_TranslateRotateZYX(pos, rot); if (*dList != NULL) { + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + MATRIX_TOMTX(*play->flexLimbOverrideMTX); + } + Matrix_Push(); Matrix_Scale(this->eyeIrisScaleX, this->eyeIrisScaleY, 1.0f, MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD); + } else { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + } + gSPDisplayList(POLY_OPA_DISP++, *dList); Matrix_Pop(); + + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + (*play->flexLimbOverrideMTX)++; + } } doNotDrawLimb = true; @@ -2034,14 +2048,28 @@ s32 BossGoma_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f Matrix_TranslateRotateZYX(pos, rot); if (*dList != NULL) { + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + MATRIX_TOMTX(*play->flexLimbOverrideMTX); + } + Matrix_Push(); Matrix_Scale(this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4], this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4], this->tailLimbsScale[limbIndex - BOSSGOMA_LIMB_TAIL4], MTXMODE_APPLY); - gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), - G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + gSPMatrix(POLY_OPA_DISP++, *play->flexLimbOverrideMTX, G_MTX_LOAD); + } else { + gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + } + gSPDisplayList(POLY_OPA_DISP++, *dList); Matrix_Pop(); + + if (this->skelanime.skeletonHeader->skeletonType == SKELANIME_TYPE_FLEX) { + (*play->flexLimbOverrideMTX)++; + } } doNotDrawLimb = true; diff --git a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c index ff55bf65f..00509500f 100644 --- a/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c +++ b/soh/src/overlays/actors/ovl_Door_Warp1/z_door_warp1.c @@ -961,7 +961,7 @@ void DoorWarp1_DrawBlueCrystal(DoorWarp1* this, PlayState* play) { gDPSetPrimColor(POLY_XLU_DISP++, 0xFF, 0xFF, 200, 255, 255, (u8)this->crystalAlpha); gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, (u8)this->crystalAlpha); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, NULL, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, NULL, NULL, &this->actor, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); @@ -985,7 +985,7 @@ void DoorWarp1_DrawPurpleCrystal(DoorWarp1* this, PlayState* play) { gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)this->crystalAlpha); gDPSetEnvColor(POLY_XLU_DISP++, 150, 0, 100, (u8)this->crystalAlpha); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, NULL, NULL, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, NULL, NULL, &this->actor, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Bili/z_en_bili.c b/soh/src/overlays/actors/ovl_En_Bili/z_en_bili.c index 74f89cbe3..a50dabe01 100644 --- a/soh/src/overlays/actors/ovl_En_Bili/z_en_bili.c +++ b/soh/src/overlays/actors/ovl_En_Bili/z_en_bili.c @@ -768,7 +768,7 @@ void EnBili_Draw(Actor* thisx, PlayState* play) { gSPSegment(POLY_XLU_DISP++, 0x09, D_809C1700); } - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnBili_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index 29eb6dc94..41234d54f 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -895,7 +895,7 @@ void EnBox_Draw(Actor* thisx, PlayState* play) { gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); gSPSegment(POLY_OPA_DISP++, 0x08, EnBox_EmptyDList(play->state.gfxCtx)); Gfx_SetupDL_25Opa(play->state.gfxCtx); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, NULL, + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, NULL, EnBox_PostLimbDraw, this, POLY_OPA_DISP); } else if (this->alpha != 0) { gDPPipeSync(POLY_XLU_DISP++); @@ -906,7 +906,7 @@ void EnBox_Draw(Actor* thisx, PlayState* play) { } else { gSPSegment(POLY_XLU_DISP++, 0x08, func_809CA4A0(play->state.gfxCtx)); } - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, NULL, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, NULL, EnBox_PostLimbDraw, this, POLY_XLU_DISP); } diff --git a/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c b/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c index 2a6fdb4fd..501c7ec9e 100644 --- a/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c +++ b/soh/src/overlays/actors/ovl_En_Bw/z_en_bw.c @@ -856,7 +856,7 @@ void EnBw_Draw(Actor* thisx, PlayState* play2) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gDPSetEnvColor(POLY_OPA_DISP++, this->color1.r, this->color1.g, this->color1.b, this->color1.a); gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnBw_OverrideLimbDraw, NULL, this, POLY_OPA_DISP); } else { Gfx_SetupDL_25Xlu(play->state.gfxCtx); @@ -864,7 +864,7 @@ void EnBw_Draw(Actor* thisx, PlayState* play2) { gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 0, 0, 0, this->color1.a); gDPSetEnvColor(POLY_XLU_DISP++, this->color1.r, this->color1.g, this->color1.b, this->color1.a); gSPSegment(POLY_XLU_DISP++, 0x08, &D_80116280[0]); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnBw_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); } diff --git a/soh/src/overlays/actors/ovl_En_Eiyer/z_en_eiyer.c b/soh/src/overlays/actors/ovl_En_Eiyer/z_en_eiyer.c index 049570716..7340d9cf5 100644 --- a/soh/src/overlays/actors/ovl_En_Eiyer/z_en_eiyer.c +++ b/soh/src/overlays/actors/ovl_En_Eiyer/z_en_eiyer.c @@ -708,14 +708,14 @@ void EnEiyer_Draw(Actor* thisx, PlayState* play) { gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]); gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, EnEiyer_OverrideLimbDraw, NULL, this, POLY_OPA_DISP); } else { Gfx_SetupDL_25Xlu(play->state.gfxCtx); gSPSegment(POLY_XLU_DISP++, 0x08, D_80116280); gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->actor.shape.shadowAlpha); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelanime.skeleton, this->skelanime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelanime, EnEiyer_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); } CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c index 2c1bd0983..f6f82f5c7 100644 --- a/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/soh/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -1540,7 +1540,7 @@ void EnElf_Draw(Actor* thisx, PlayState* play) { gSPEndDisplayList(dListHead++); gDPSetEnvColor(POLY_XLU_DISP++, (u8)this->outerColor.r, (u8)this->outerColor.g, (u8)this->outerColor.b, (u8)(envAlpha * alphaScale)); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnElf_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c index 6c8afb6d7..7797cba9c 100644 --- a/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c +++ b/soh/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c @@ -839,8 +839,9 @@ void EnFirefly_Draw(Actor* thisx, PlayState* play) { gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255); } - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, - EnFirefly_OverrideLimbDraw, EnFirefly_PostLimbDraw, &this->actor, POLY_OPA_DISP); + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnFirefly_OverrideLimbDraw, EnFirefly_PostLimbDraw, + &this->actor, POLY_OPA_DISP); + CLOSE_DISPS(play->state.gfxCtx); } @@ -856,7 +857,7 @@ void EnFirefly_DrawInvisible(Actor* thisx, PlayState* play) { gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, 255); } - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnFirefly_OverrideLimbDraw, EnFirefly_PostLimbDraw, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c index 8af56cd79..4d41bb1f8 100644 --- a/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c +++ b/soh/src/overlays/actors/ovl_En_Fr/z_en_fr.c @@ -817,12 +817,28 @@ void EnFr_SetupFrogSong(EnFr* this, PlayState* play) { if (this->frogSongTimer != 0) { this->frogSongTimer--; } else { - this->frogSongTimer = 40; - this->ocarinaNoteIndex = 0; - func_8010BD58(play, OCARINA_ACTION_FROGS); - this->ocarinaNote = EnFr_GetNextNoteFrogSong(this->ocarinaNoteIndex); - EnFr_CheckOcarinaInputFrogSong(this->ocarinaNote); - this->actionFunc = EnFr_ContinueFrogSong; + // #region SOH [Enhancement] + if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0)) { + this->frogSongTimer = 40 * CVarGetInteger(CVAR_ENHANCEMENT("FrogsModifyFailTime"), 1); + if (CVarGetInteger(CVAR_ENHANCEMENT("InstantFrogsGameWin"), 0)) { + this->actor.textId = 0x40AC; + EnFr_SetupReward(this, play, false); + } else { + this->ocarinaNoteIndex = 0; + func_8010BD58(play, OCARINA_ACTION_FROGS); + this->ocarinaNote = EnFr_GetNextNoteFrogSong(this->ocarinaNoteIndex); + EnFr_CheckOcarinaInputFrogSong(this->ocarinaNote); + this->actionFunc = EnFr_ContinueFrogSong; + } + // #endregion + } else { + this->frogSongTimer = 40; + this->ocarinaNoteIndex = 0; + func_8010BD58(play, OCARINA_ACTION_FROGS); + this->ocarinaNote = EnFr_GetNextNoteFrogSong(this->ocarinaNoteIndex); + EnFr_CheckOcarinaInputFrogSong(this->ocarinaNote); + this->actionFunc = EnFr_ContinueFrogSong; + } } } @@ -844,7 +860,13 @@ s32 EnFr_IsFrogSongComplete(EnFr* this, PlayState* play) { ocarinaNote = EnFr_GetNextNoteFrogSong(ocarinaNoteIndex); this->ocarinaNote = ocarinaNote; EnFr_CheckOcarinaInputFrogSong(ocarinaNote); - this->frogSongTimer = sTimerFrogSong[index]; + // #region SOH [Enhancement] + if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0)) { + this->frogSongTimer = sTimerFrogSong[index] * CVarGetInteger(CVAR_ENHANCEMENT("FrogsModifyFailTime"), 1); + // #endregion + } else { + this->frogSongTimer = sTimerFrogSong[index]; + } } return false; } @@ -867,7 +889,12 @@ void EnFr_ContinueFrogSong(EnFr* this, PlayState* play) { if (this->frogSongTimer == 0) { EnFr_OcarinaMistake(this, play); } else { - this->frogSongTimer--; + // #region SOH [Enhancement] - Don't decrement timer + if (!CVarGetInteger(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame"), 0) || + !CVarGetInteger(CVAR_ENHANCEMENT("FrogsUnlimitedFailTime"), 0)) { + // #endregion + this->frogSongTimer--; + } if (play->msgCtx.msgMode == MSGMODE_FROGS_PLAYING) { counter = 0; for (i = 0; i < ARRAY_COUNT(sEnFrPointers.frogs); i++) { diff --git a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c index de7bddf82..0c30fcf17 100644 --- a/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c +++ b/soh/src/overlays/actors/ovl_En_Partner/z_en_partner.c @@ -880,7 +880,7 @@ void EnPartner_Draw(Actor* thisx, PlayState* play) { gSPEndDisplayList(dListHead++); gDPSetEnvColor(POLY_XLU_DISP++, (u8)this->outerColor.r, (u8)this->outerColor.g, (u8)this->outerColor.b, (u8)(envAlpha * alphaScale)); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPartner_OverrideLimbDraw, NULL, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Po_Desert/z_en_po_desert.c b/soh/src/overlays/actors/ovl_En_Po_Desert/z_en_po_desert.c index 55155226b..2c00b284b 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Desert/z_en_po_desert.c +++ b/soh/src/overlays/actors/ovl_En_Po_Desert/z_en_po_desert.c @@ -267,7 +267,7 @@ void EnPoDesert_Draw(Actor* thisx, PlayState* play) { } else { gSPSegment(POLY_XLU_DISP++, 0x0C, D_80116280 + 2); } - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoDesert_OverrideLimbDraw, EnPoDesert_PostLimbDraw, &this->actor, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); } diff --git a/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c b/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c index 3f109863c..d391840ba 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c +++ b/soh/src/overlays/actors/ovl_En_Po_Field/z_en_po_field.c @@ -944,15 +944,14 @@ void EnPoField_Draw(Actor* thisx, PlayState* play) { this->lightColor.a)); gSPSegment(POLY_OPA_DISP++, 0x0C, D_80116280 + 2); POLY_OPA_DISP = - SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoField_OverrideLimbDraw2, EnPoField_PostLimDraw2, &this->actor, POLY_OPA_DISP); } else { gSPSegment(POLY_XLU_DISP++, 0x08, Gfx_EnvColor(play->state.gfxCtx, this->lightColor.r, this->lightColor.g, this->lightColor.b, this->lightColor.a)); gSPSegment(POLY_XLU_DISP++, 0x0C, D_80116280); - POLY_XLU_DISP = - SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoField_OverrideLimbDraw2, EnPoField_PostLimDraw2, &this->actor, POLY_XLU_DISP); } gDPPipeSync(POLY_OPA_DISP++); diff --git a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c index 280640efd..e1a1d1f31 100644 --- a/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c +++ b/soh/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c @@ -1362,14 +1362,12 @@ void EnPoSisters_Draw(Actor* thisx, PlayState* play) { if (this->unk_22E.a == 255 || this->unk_22E.a == 0) { gDPSetEnvColor(POLY_OPA_DISP++, this->unk_22E.r, this->unk_22E.g, this->unk_22E.b, this->unk_22E.a); gSPSegment(POLY_OPA_DISP++, 0x09, D_80116280 + 2); - POLY_OPA_DISP = - SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, - EnPoSisters_OverrideLimbDraw, EnPoSisters_PostLimbDraw, &this->actor, POLY_OPA_DISP); + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoSisters_OverrideLimbDraw, + EnPoSisters_PostLimbDraw, &this->actor, POLY_OPA_DISP); } else { gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->unk_22E.a); gSPSegment(POLY_XLU_DISP++, 0x09, D_80116280); - POLY_XLU_DISP = - SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoSisters_OverrideLimbDraw, EnPoSisters_PostLimbDraw, &this->actor, POLY_XLU_DISP); } if (!(this->unk_199 & 0x80)) { diff --git a/soh/src/overlays/actors/ovl_En_Poh/z_en_poh.c b/soh/src/overlays/actors/ovl_En_Poh/z_en_poh.c index 809150fe6..2c7e90416 100644 --- a/soh/src/overlays/actors/ovl_En_Poh/z_en_poh.c +++ b/soh/src/overlays/actors/ovl_En_Poh/z_en_poh.c @@ -1085,12 +1085,12 @@ void EnPoh_DrawRegular(Actor* thisx, PlayState* play) { if (this->lightColor.a == 255 || this->lightColor.a == 0) { gDPSetEnvColor(POLY_OPA_DISP++, this->lightColor.r, this->lightColor.g, this->lightColor.b, this->lightColor.a); gSPSegment(POLY_OPA_DISP++, 0x08, D_80116280 + 2); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoh_OverrideLimbDraw, EnPoh_PostLimbDraw, &this->actor, POLY_OPA_DISP); } else { gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->lightColor.a); gSPSegment(POLY_XLU_DISP++, 0x08, D_80116280); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnPoh_OverrideLimbDraw, EnPoh_PostLimbDraw, &this->actor, POLY_XLU_DISP); } gDPPipeSync(POLY_OPA_DISP++); diff --git a/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c b/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c index 9b6154a8b..11772cd90 100644 --- a/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c +++ b/soh/src/overlays/actors/ovl_En_Vali/z_en_vali.c @@ -814,7 +814,7 @@ void EnVali_Draw(Actor* thisx, PlayState* play) { EnVali_DrawBody(this, play); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnVali_OverrideLimbDraw, EnVali_PostLimbDraw, this, POLY_XLU_DISP); CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_En_Weiyer/z_en_weiyer.c b/soh/src/overlays/actors/ovl_En_Weiyer/z_en_weiyer.c index 4a267b001..e3f19a3ed 100644 --- a/soh/src/overlays/actors/ovl_En_Weiyer/z_en_weiyer.c +++ b/soh/src/overlays/actors/ovl_En_Weiyer/z_en_weiyer.c @@ -640,13 +640,13 @@ void EnWeiyer_Draw(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); gSPSegment(POLY_OPA_DISP++, 0x08, &D_80116280[2]); gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, - EnWeiyer_OverrideLimbDraw, NULL, &this->actor, POLY_OPA_DISP); + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnWeiyer_OverrideLimbDraw, NULL, &this->actor, + POLY_OPA_DISP); } else { Gfx_SetupDL_25Xlu(play->state.gfxCtx); gSPSegment(POLY_XLU_DISP++, 0x08, &D_80116280[0]); gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, this->actor.shape.shadowAlpha); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnWeiyer_OverrideLimbDraw, NULL, &this->actor, POLY_XLU_DISP); } diff --git a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c index 2b0d6c126..eb6a77e24 100644 --- a/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c +++ b/soh/src/overlays/actors/ovl_En_Wood02/z_en_wood02.c @@ -101,13 +101,19 @@ static f32 sSpawnSin; s32 EnWood02_SpawnZoneCheck(EnWood02* this, PlayState* play, Vec3f* pos) { f32 phi_f12; - if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0) { - return true; - } - SkinMatrix_Vec3fMtxFMultXYZW(&play->viewProjectionMtxF, pos, &this->actor.projectedPos, &this->actor.projectedW); + // #region SOH [Enhancement] Use the extended culling calculation + if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1) > 1 || + CVarGetInteger(CVAR_ENHANCEMENT("WidescreenActorCulling"), 0)) { + bool shipShouldDraw = false; + bool shipShouldUpdate = false; + return Ship_CalcShouldDrawAndUpdate(play, &this->actor, &this->actor.projectedPos, this->actor.projectedW, + &shipShouldDraw, &shipShouldUpdate); + } + // #endregion + phi_f12 = ((this->actor.projectedW == 0.0f) ? 1000.0f : fabsf(1.0f / this->actor.projectedW)); if ((-this->actor.uncullZoneScale < this->actor.projectedPos.z) && diff --git a/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c b/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c index 98180605e..03fb95bd3 100644 --- a/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c +++ b/soh/src/overlays/actors/ovl_En_Zf/z_en_zf.c @@ -2252,7 +2252,7 @@ void EnZf_Draw(Actor* thisx, PlayState* play) { gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, this->alpha); gSPSegment(POLY_OPA_DISP++, 0x09, &D_80116280[2]); - POLY_OPA_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_OPA_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnZf_OverrideLimbDraw, EnZf_PostLimbDraw, this, POLY_OPA_DISP); if (this->iceTimer != 0) { @@ -2271,7 +2271,7 @@ void EnZf_Draw(Actor* thisx, PlayState* play) { gDPPipeSync(POLY_XLU_DISP++); gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->alpha); gSPSegment(POLY_XLU_DISP++, 0x09, &D_80116280[0]); - POLY_XLU_DISP = SkelAnime_Draw(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + POLY_XLU_DISP = SkelAnime_DrawSkeleton2(play, &this->skelAnime, EnZf_OverrideLimbDraw, EnZf_PostLimbDraw, this, POLY_XLU_DISP); } CLOSE_DISPS(play->state.gfxCtx); diff --git a/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c b/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c index 519035081..94c1d468b 100644 --- a/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c +++ b/soh/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c @@ -275,7 +275,12 @@ void ObjMure_InitialAction(ObjMure* this, PlayState* play) { } void ObjMure_CulledState(ObjMure* this, PlayState* play) { - if (fabsf(this->actor.projectedPos.z) < sZClip[this->type] || CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0) { + // #region SOH [Enhancements] Extended draw distance + s32 distanceMultiplier = CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1); + distanceMultiplier = MAX(distanceMultiplier, 1); + + if (fabsf(this->actor.projectedPos.z) < sZClip[this->type] * distanceMultiplier) { + // #endregion this->actionFunc = ObjMure_ActiveState; this->actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure_SpawnActors(this, play); @@ -398,8 +403,13 @@ static ObjMureActionFunc sTypeGroupBehaviorFunc[] = { void ObjMure_ActiveState(ObjMure* this, PlayState* play) { ObjMure_CheckChildren(this, play); - if (sZClip[this->type] + 40.0f <= fabsf(this->actor.projectedPos.z) && - CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1) != 0) { + + // #region SOH [Enhancements] Extended draw distance + s32 distanceMultiplier = CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1); + distanceMultiplier = MAX(distanceMultiplier, 1); + + if ((sZClip[this->type] + 40.0f) * distanceMultiplier <= fabsf(this->actor.projectedPos.z)) { + // #endregion this->actionFunc = ObjMure_CulledState; this->actor.flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure_KillActors(this, play); diff --git a/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c b/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c index 0aad27c04..5b1eecbd4 100644 --- a/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c +++ b/soh/src/overlays/actors/ovl_Obj_Mure2/z_obj_mure2.c @@ -190,8 +190,7 @@ void func_80B9A658(ObjMure2* this) { void func_80B9A668(ObjMure2* this, PlayState* play) { if (Math3D_Dist1DSq(this->actor.projectedPos.x, this->actor.projectedPos.z) < - (sDistSquared1[this->actor.params & 3] * this->unk_184) || - CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0) { + (sDistSquared1[this->actor.params & 3] * this->unk_184)) { this->actor.flags |= ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure2_SpawnActors(this, play); func_80B9A6E8(this); @@ -205,12 +204,8 @@ void func_80B9A6E8(ObjMure2* this) { void func_80B9A6F8(ObjMure2* this, PlayState* play) { func_80B9A534(this); - if (CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 0) != 0) { - return; - } - if ((sDistSquared2[this->actor.params & 3] * this->unk_184) <= - Math3D_Dist1DSq(this->actor.projectedPos.x, this->actor.projectedPos.z)) { + Math3D_Dist1DSq(this->actor.projectedPos.x, this->actor.projectedPos.z)) { this->actor.flags &= ~ACTOR_FLAG_UPDATE_WHILE_CULLED; ObjMure2_CleanupAndDie(this, play); func_80B9A658(this); @@ -225,5 +220,20 @@ void ObjMure2_Update(Actor* thisx, PlayState* play) { } else { this->unk_184 = 4.0f; } + + // SOH [Enhancements] Extended draw distance + s32 distanceMultiplier = CVarGetInteger(CVAR_ENHANCEMENT("DisableDrawDistance"), 1); + if (CVarGetInteger(CVAR_ENHANCEMENT("WidescreenActorCulling"), 0) || distanceMultiplier > 1) { + f32 originalAspectRatio = 4.0f / 3.0f; + f32 currentAspectRatio = OTRGetAspectRatio(); + // Adjust ratio difference based on field of view testing + f32 ratioAdjusted = 1.0f + (MAX(currentAspectRatio / originalAspectRatio, 1.0f) / 1.5f); + // Distance multiplier is squared due to the checks above for squared distances + distanceMultiplier = SQ(MAX(distanceMultiplier, 1)); + + // Prefer the largest of the three values + this->unk_184 = MAX(MAX((f32)distanceMultiplier, ratioAdjusted), this->unk_184); + } + this->actionFunc(this, play); } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 3dfb2dbeb..c5d1a65bd 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11895,10 +11895,6 @@ void Player_Draw(Actor* thisx, PlayState* play2) { lod = 1; } - if (CVarGetInteger(CVAR_ENHANCEMENT("DisableLOD"), 0)) { - lod = 0; - } - func_80093C80(play); Gfx_SetupDL_25Xlu(play->state.gfxCtx); @@ -12119,7 +12115,8 @@ void func_8084AEEC(Player* this, f32* arg1, f32 arg2, s16 arg3) { } else if (gWalkSpeedToggle2) { swimMod *= CVarGetFloat(CVAR_SETTING("WalkModifier.SwimMapping2"), 1.0f); } - } else { + // sControlInput is NULL to prevent inputs while surfacing after obtaining an underwater item so we want to ignore it for that case + } else if (sControlInput != NULL) { if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER1)) { swimMod *= CVarGetFloat(CVAR_SETTING("WalkModifier.SwimMapping1"), 1.0f); } else if (CHECK_BTN_ALL(sControlInput->cur.button, BTN_MODIFIER2)) { diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c index 99ba5df72..116ad0c3c 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_equipment.c @@ -27,6 +27,8 @@ static Vtx sStrengthAButtonVtx[] = { static s16 sEquipTimer = 0; +extern int gPauseLinkFrameBuffer; + void KaleidoScope_DrawEquipmentImage(PlayState* play, void* source, u32 width, u32 height) { PauseContext* pauseCtx = &play->pauseCtx; u8* curTexture; @@ -70,13 +72,12 @@ void KaleidoScope_DrawEquipmentImage(PlayState* play, void* source, u32 width, u for (i = 0; i < textureCount; i++) { gSPVertex(POLY_KAL_DISP++, &pauseCtx->equipVtx[vtxIndex], 4, 0); - extern int fbTest; gDPSetTextureImage(POLY_KAL_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, curTexture); gDPLoadSync(POLY_KAL_DISP++); gDPLoadTile(POLY_KAL_DISP++, G_TX_LOADTILE, 0, 0, (width - 1) << 2, (textureHeight - 1) << 2); - gDPSetTextureImageFB(POLY_KAL_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, fbTest); + gDPSetTextureImageFB(POLY_KAL_DISP++, G_IM_FMT_RGBA, G_IM_SIZ_16b, width, gPauseLinkFrameBuffer); gSP1Quadrangle(POLY_KAL_DISP++, 0, 2, 3, 1, 0); curTexture += textureSize; @@ -185,8 +186,7 @@ void KaleidoScope_DrawPlayerWork(PlayState* play) { link_kaleido_rot.x = 0; - extern int fbTest; - gsSPSetFB(play->state.gfxCtx->polyOpa.p++, fbTest); + gsSPSetFB(play->state.gfxCtx->polyOpa.p++, gPauseLinkFrameBuffer); Player_DrawPause(play, pauseCtx->playerSegment, &pauseCtx->playerSkelAnime, &pos, &link_kaleido_rot, scale, SWORD_EQUIP_TO_PLAYER(CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD)), TUNIC_EQUIP_TO_PLAYER(CUR_EQUIP_VALUE(EQUIP_TYPE_TUNIC)), @@ -852,7 +852,7 @@ void KaleidoScope_DrawEquipment(PlayState* play) { //gSPSegment(POLY_KAL_DISP++, 0x0C, pauseCtx->iconItemAltSegment); Gfx_SetupDL_42Kal(play->state.gfxCtx); - KaleidoScope_DrawEquipmentImage(play, pauseCtx->playerSegment, 64, 112); + KaleidoScope_DrawEquipmentImage(play, pauseCtx->playerSegment, PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT); if (gUpgradeMasks[0]) {} diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 424c823d6..a8b7536f0 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -929,7 +929,6 @@ static void* sPromptChoiceTexs[][2] = { static u8 sButtonStatusSave[ARRAY_COUNT(gSaveContext.buttonStatus)]; static PreRender sPlayerPreRender; static void* sPreRenderCvg; -extern int fbTest; void KaleidoScope_ProcessPlayerPreRender(void) { PreRender_Calc(&sPlayerPreRender); @@ -3725,7 +3724,8 @@ void KaleidoScope_Update(PlayState* play) sPreRenderCvg = (void*)(((uintptr_t)pauseCtx->nameSegment + 0x400 + 0xA00 + 0xF) & ~0xF); PreRender_Init(&sPlayerPreRender); - PreRender_SetValuesSave(&sPlayerPreRender, 64, 112, pauseCtx->playerSegment, NULL, sPreRenderCvg); + PreRender_SetValuesSave(&sPlayerPreRender, PAUSE_EQUIP_PLAYER_WIDTH, PAUSE_EQUIP_PLAYER_HEIGHT, + pauseCtx->playerSegment, NULL, sPreRenderCvg); KaleidoScope_DrawPlayerWork(play); //KaleidoScope_SetupPlayerPreRender(play);