Merge branch 'dev' into chore/ci-windows-test
This commit is contained in:
commit
c3668d02d4
|
@ -1,10 +1,10 @@
|
||||||
ARCH=$(uname -m)
|
ARCH=$(uname -m)
|
||||||
LINUX_DEPLOY_ARCH=$(uname -m)
|
LINUX_DEPLOY_ARCH=$(uname -m)
|
||||||
|
|
||||||
if [ "$ARCH" == "x86_64" ]; then
|
if [ "$ARCH" = "x86_64" ]; then
|
||||||
ARCH="x86_64"
|
ARCH="x86_64"
|
||||||
LINUX_DEPLOY_ARCH="x86_64"
|
LINUX_DEPLOY_ARCH="x86_64"
|
||||||
elif [ "$ARCH" == "aarch64" ]; then
|
elif [ "$ARCH" = "aarch64" ]; then
|
||||||
ARCH="arm_aarch64"
|
ARCH="arm_aarch64"
|
||||||
LINUX_DEPLOY_ARCH="aarch64"
|
LINUX_DEPLOY_ARCH="aarch64"
|
||||||
else
|
else
|
||||||
|
@ -14,11 +14,13 @@ fi
|
||||||
|
|
||||||
curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-$LINUX_DEPLOY_ARCH.AppImage"
|
curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-$LINUX_DEPLOY_ARCH.AppImage"
|
||||||
curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/raw/master/linuxdeploy-plugin-gtk.sh"
|
curl -sSfLO "https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/raw/master/linuxdeploy-plugin-gtk.sh"
|
||||||
|
|
||||||
chmod a+x linuxdeploy*
|
chmod a+x linuxdeploy*
|
||||||
|
|
||||||
mkdir -p AppDir/usr/bin
|
mkdir -p AppDir/usr/bin
|
||||||
cp Zelda64Recompiled AppDir/usr/bin/
|
cp Zelda64Recompiled AppDir/usr/bin/
|
||||||
cp -r assets/ AppDir/usr/bin/
|
cp -r assets/ AppDir/usr/bin/
|
||||||
|
cp gamecontrollerdb.txt AppDir/usr/bin/
|
||||||
cp icons/512.png AppDir/Zelda64Recompiled.png
|
cp icons/512.png AppDir/Zelda64Recompiled.png
|
||||||
cp .github/linux/Zelda64Recompiled.desktop AppDir/
|
cp .github/linux/Zelda64Recompiled.desktop AppDir/
|
||||||
|
|
||||||
|
@ -34,4 +36,10 @@ echo 'else' >> AppDir/AppRun
|
||||||
echo ' cd "$this_dir"/usr/bin/' >> AppDir/AppRun
|
echo ' cd "$this_dir"/usr/bin/' >> AppDir/AppRun
|
||||||
echo ' ./Zelda64Recompiled' >> AppDir/AppRun
|
echo ' ./Zelda64Recompiled' >> AppDir/AppRun
|
||||||
echo 'fi' >> AppDir/AppRun
|
echo 'fi' >> AppDir/AppRun
|
||||||
|
|
||||||
|
# Remove conflicting libraries
|
||||||
|
rm -rf AppDir/usr/lib/libgmodule*
|
||||||
|
rm -rf AppDir/usr/lib/gio/modules/*.so
|
||||||
|
rm -rf AppDir/usr/lib/libwayland*
|
||||||
|
|
||||||
./deploy/usr/bin/linuxdeploy-plugin-appimage --appdir=AppDir
|
./deploy/usr/bin/linuxdeploy-plugin-appimage --appdir=AppDir
|
||||||
|
|
|
@ -1,6 +1,19 @@
|
||||||
name: validate
|
name: validate
|
||||||
on:
|
on:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
SDL2_VERSION:
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
default: '2.28.5'
|
||||||
|
N64RECOMP_COMMIT:
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
default: '2a2df89349ff25a3afb3a09617deb3a166efe2f3'
|
||||||
|
DXC_CHECKSUM:
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
default: '4e6f4e52989aca69739880b40b9f988357f15d10ca03284377b81f1502463ff5'
|
||||||
secrets:
|
secrets:
|
||||||
ZRE_REPO_WITH_PAT:
|
ZRE_REPO_WITH_PAT:
|
||||||
required: true
|
required: true
|
||||||
|
@ -9,13 +22,90 @@ concurrency:
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
jobs:
|
jobs:
|
||||||
build-linux:
|
build-linux:
|
||||||
runs-on: ${{ matrix.arch == 'x64' && matrix.os || format('blaze/{0}', matrix.os) }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
container:
|
||||||
|
image: dcvz/n64recomp:0.0.1-ubuntu-18.04
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
type: [ Debug, Release ]
|
type: [ Debug, Release ]
|
||||||
os: [ ubuntu-22.04 ]
|
os: [ ubuntu-22.04 ]
|
||||||
arch: [ x64, arm64 ]
|
name: ubuntu-18.04 (x64, ${{ matrix.type }})
|
||||||
name: ${{ matrix.os }} (${{ matrix.arch }}, ${{ matrix.type }})
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha || github.ref }}
|
||||||
|
submodules: recursive
|
||||||
|
- name: ccache
|
||||||
|
uses: hendrikmuhs/ccache-action@v1.2.11
|
||||||
|
with:
|
||||||
|
key: ${{ matrix.os }}-z64re-ccache-${{ matrix.type }}-x64-${{ inputs.N64RECOMP_COMMIT }}
|
||||||
|
- name: Prepare Build
|
||||||
|
run: |-
|
||||||
|
git clone ${{ secrets.ZRE_REPO_WITH_PAT }}
|
||||||
|
unzip zre/files.zip > /dev/null 2>&1
|
||||||
|
- name: Build N64Recomp & RSPRecomp
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/Mr-Wiseguy/N64Recomp.git --recurse-submodules N64RecompSource
|
||||||
|
cd N64RecompSource
|
||||||
|
git checkout ${{ inputs.N64RECOMP_COMMIT }}
|
||||||
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
# enable ccache
|
||||||
|
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||||
|
|
||||||
|
# Build N64Recomp & RSPRecomp
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_C_COMPILER=gcc-11 -DCMAKE_MAKE_PROGRAM=ninja -G Ninja -S . -B cmake-build
|
||||||
|
cmake --build cmake-build --config Release --target N64Recomp -j $(nproc)
|
||||||
|
cmake --build cmake-build --config Release --target RSPRecomp -j $(nproc)
|
||||||
|
|
||||||
|
# Copy N64Recomp & RSPRecomp to root directory
|
||||||
|
cp cmake-build/N64Recomp ..
|
||||||
|
cp cmake-build/RSPRecomp ..
|
||||||
|
- name: Run N64Recomp & RSPRecomp
|
||||||
|
run: |
|
||||||
|
./N64Recomp us.rev1.toml
|
||||||
|
./RSPRecomp aspMain.us.rev1.toml
|
||||||
|
./RSPRecomp njpgdspMain.us.rev1.toml
|
||||||
|
- name: Hotpatch DXC into RT64's contrib
|
||||||
|
run: |
|
||||||
|
# check if dxc was updated before we replace it, to detect changes
|
||||||
|
echo ${{ inputs.DXC_CHECKSUM }} ./lib/rt64/src/contrib/dxc/bin/x64/dxc | sha256sum --status -c -
|
||||||
|
|
||||||
|
cp -v /usr/local/lib/libdxcompiler.so ./lib/rt64/src/contrib/dxc/lib/x64/libdxcompiler.so
|
||||||
|
cp -v /usr/local/bin/dxc ./lib/rt64/src/contrib/dxc/bin/x64/dxc
|
||||||
|
- name: Build ZeldaRecomp
|
||||||
|
run: |-
|
||||||
|
# enable ccache
|
||||||
|
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||||
|
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=${{ matrix.type }} -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER=clang++-17 -DCMAKE_C_COMPILER=clang-17 -DCMAKE_MAKE_PROGRAM=ninja -G Ninja -S . -B cmake-build -DPATCHES_C_COMPILER=clang-17 -DPATCHES_LD=ld.lld-17 -DPATCHES_OBJCOPY=llvm-objcopy-17
|
||||||
|
cmake --build cmake-build --config ${{ matrix.type }} --target Zelda64Recompiled -j $(nproc)
|
||||||
|
- name: Prepare Archive
|
||||||
|
run: |
|
||||||
|
mv cmake-build/Zelda64Recompiled Zelda64Recompiled
|
||||||
|
rm -rf assets/scss
|
||||||
|
tar -czf Zelda64Recompiled.tar.gz Zelda64Recompiled assets/ gamecontrollerdb.txt
|
||||||
|
- name: Archive Zelda64Recomp
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: Zelda64Recompiled-${{ runner.os }}-X64-${{ matrix.type }}
|
||||||
|
path: Zelda64Recompiled.tar.gz
|
||||||
|
- name: Build AppImage
|
||||||
|
run: |-
|
||||||
|
./.github/linux/appimage.sh
|
||||||
|
- name: Zelda64Recomp AppImage
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: Zelda64Recompiled-AppImage-X64-${{ matrix.type }}
|
||||||
|
path: Zelda64Recompiled-*.AppImage
|
||||||
|
build-linux-arm64:
|
||||||
|
runs-on: ${{ format('blaze/{0}', matrix.os) }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
type: [ Debug, Release ]
|
||||||
|
os: [ ubuntu-22.04 ]
|
||||||
|
name: ${{ matrix.os }} (arm64, ${{ matrix.type }})
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
@ -25,7 +115,7 @@ jobs:
|
||||||
- name: ccache
|
- name: ccache
|
||||||
uses: hendrikmuhs/ccache-action@v1.2
|
uses: hendrikmuhs/ccache-action@v1.2
|
||||||
with:
|
with:
|
||||||
key: ${{ matrix.os }}-z64re-ccache-${{ matrix.type }}-${{ matrix.arch }}
|
key: ${{ matrix.os }}-z64re-ccache-${{ matrix.type }}-arm64-${{ inputs.N64RECOMP_COMMIT }}
|
||||||
- name: Install Linux Dependencies
|
- name: Install Linux Dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
|
@ -37,13 +127,13 @@ jobs:
|
||||||
# Enable ccache
|
# Enable ccache
|
||||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||||
|
|
||||||
wget https://github.com/libsdl-org/SDL/releases/download/release-2.26.1/SDL2-2.26.1.tar.gz
|
wget https://github.com/libsdl-org/SDL/releases/download/release-${{ inputs.SDL2_VERSION }}/SDL2-${{ inputs.SDL2_VERSION }}.tar.gz
|
||||||
tar -xzf SDL2-2.26.1.tar.gz
|
tar -xzf SDL2-${{ inputs.SDL2_VERSION }}.tar.gz
|
||||||
cd SDL2-2.26.1
|
cd SDL2-${{ inputs.SDL2_VERSION }}
|
||||||
./configure
|
./configure
|
||||||
make -j 10
|
make -j 10
|
||||||
sudo make install
|
sudo make install
|
||||||
sudo cp -av /usr/local/lib/libSDL* /lib/x86_64-linux-gnu/
|
sudo cp -av /usr/local/lib/libSDL* /lib/aarch64-linux-gnu/
|
||||||
echo ::endgroup::
|
echo ::endgroup::
|
||||||
- name: Prepare Build
|
- name: Prepare Build
|
||||||
run: |-
|
run: |-
|
||||||
|
@ -54,7 +144,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
git clone https://github.com/Mr-Wiseguy/N64Recomp.git --recurse-submodules N64RecompSource
|
git clone https://github.com/Mr-Wiseguy/N64Recomp.git --recurse-submodules N64RecompSource
|
||||||
cd N64RecompSource
|
cd N64RecompSource
|
||||||
git checkout 2a2df89349ff25a3afb3a09617deb3a166efe2f3
|
git checkout ${{ inputs.N64RECOMP_COMMIT }}
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
|
||||||
# enable ccache
|
# enable ccache
|
||||||
|
@ -84,18 +174,18 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
mv cmake-build/Zelda64Recompiled Zelda64Recompiled
|
mv cmake-build/Zelda64Recompiled Zelda64Recompiled
|
||||||
rm -rf assets/scss
|
rm -rf assets/scss
|
||||||
tar -czf Zelda64Recompiled.tar.gz Zelda64Recompiled assets/
|
tar -czf Zelda64Recompiled.tar.gz Zelda64Recompiled assets/ gamecontrollerdb.txt
|
||||||
- name: Archive Zelda64Recomp
|
- name: Archive Zelda64Recomp
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Zelda64Recompiled-${{ runner.os }}-${{ runner.arch }}-${{ matrix.type }}
|
name: Zelda64Recompiled-${{ runner.os }}-ARM64-${{ matrix.type }}
|
||||||
path: Zelda64Recompiled.tar.gz
|
path: Zelda64Recompiled.tar.gz
|
||||||
- name: Prepare AppImage
|
- name: Prepare AppImage
|
||||||
run: ./.github/linux/appimage.sh
|
run: ./.github/linux/appimage.sh
|
||||||
- name: Zelda64Recomp AppImage
|
- name: Zelda64Recomp AppImage
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: Zelda64Recompiled-AppImage-${{ runner.arch }}-${{ matrix.type }}
|
name: Zelda64Recompiled-AppImage-ARM64-${{ matrix.type }}
|
||||||
path: Zelda64Recompiled-*.AppImage
|
path: Zelda64Recompiled-*.AppImage
|
||||||
build-windows:
|
build-windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
@ -128,7 +218,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
git clone https://github.com/Mr-Wiseguy/N64Recomp.git --recurse-submodules N64RecompSource
|
git clone https://github.com/Mr-Wiseguy/N64Recomp.git --recurse-submodules N64RecompSource
|
||||||
cd N64RecompSource
|
cd N64RecompSource
|
||||||
git checkout 2a2df89349ff25a3afb3a09617deb3a166efe2f3
|
git checkout ${{ inputs.N64RECOMP_COMMIT }}
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
|
||||||
# enable ccache
|
# enable ccache
|
||||||
|
@ -161,6 +251,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
CXXFLAGS: --target=amd64-pc-windows-msvc -fdiagnostics-absolute-paths
|
CXXFLAGS: --target=amd64-pc-windows-msvc -fdiagnostics-absolute-paths
|
||||||
CFLAGS: --target=amd64-pc-windows-msvc -fdiagnostics-absolute-paths
|
CFLAGS: --target=amd64-pc-windows-msvc -fdiagnostics-absolute-paths
|
||||||
|
SDL2_VERSION: ${{ inputs.SDL2_VERSION }}
|
||||||
- name: Prepare Archive
|
- name: Prepare Archive
|
||||||
run: |
|
run: |
|
||||||
Move-Item -Path "cmake-build/Zelda64Recompiled.exe" -Destination "Zelda64Recompiled.exe"
|
Move-Item -Path "cmake-build/Zelda64Recompiled.exe" -Destination "Zelda64Recompiled.exe"
|
||||||
|
@ -178,3 +269,4 @@ jobs:
|
||||||
dxil.dll
|
dxil.dll
|
||||||
SDL2.dll
|
SDL2.dll
|
||||||
assets/
|
assets/
|
||||||
|
gamecontrollerdb.txt
|
||||||
|
|
|
@ -58,3 +58,6 @@ node_modules/
|
||||||
# Recompiler Linux binary
|
# Recompiler Linux binary
|
||||||
N64Recomp
|
N64Recomp
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Controller mappings file
|
||||||
|
gamecontrollerdb.txt
|
||||||
|
|
|
@ -18,4 +18,4 @@
|
||||||
url = https://github.com/DLTcollab/sse2neon.git
|
url = https://github.com/DLTcollab/sse2neon.git
|
||||||
[submodule "lib/N64ModernRuntime"]
|
[submodule "lib/N64ModernRuntime"]
|
||||||
path = lib/N64ModernRuntime
|
path = lib/N64ModernRuntime
|
||||||
url = git@github.com:N64Recomp/N64ModernRuntime.git
|
url = https://github.com/N64Recomp/N64ModernRuntime.git
|
||||||
|
|
|
@ -80,8 +80,20 @@ target_sources(PatchesLib PRIVATE
|
||||||
set_source_files_properties(${CMAKE_SOURCE_DIR}/RecompiledPatches/patches.c PROPERTIES COMPILE_FLAGS -fno-strict-aliasing)
|
set_source_files_properties(${CMAKE_SOURCE_DIR}/RecompiledPatches/patches.c PROPERTIES COMPILE_FLAGS -fno-strict-aliasing)
|
||||||
|
|
||||||
# Build patches elf
|
# Build patches elf
|
||||||
|
if(NOT DEFINED PATCHES_C_COMPILER)
|
||||||
|
set(PATCHES_C_COMPILER clang)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED PATCHES_LD)
|
||||||
|
set(PATCHES_LD ld.lld)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT DEFINED PATCHES_OBJCOPY)
|
||||||
|
set(PATCHES_OBJCOPY llvm-objcopy)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_target(PatchesBin
|
add_custom_target(PatchesBin
|
||||||
COMMAND make
|
COMMAND ${CMAKE_COMMAND} -E env CC=${PATCHES_C_COMPILER} LD=${PATCHES_LD} OBJCOPY=${PATCHES_OBJCOPY} make
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/patches
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/patches
|
||||||
BYPRODUCTS ${CMAKE_SOURCE_DIR}/patches/patches.bin
|
BYPRODUCTS ${CMAKE_SOURCE_DIR}/patches/patches.bin
|
||||||
)
|
)
|
||||||
|
@ -103,8 +115,19 @@ add_custom_command(OUTPUT
|
||||||
DEPENDS ${CMAKE_SOURCE_DIR}/patches/patches.bin
|
DEPENDS ${CMAKE_SOURCE_DIR}/patches/patches.bin
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Download controller db file for controller support via SDL2
|
||||||
|
set(GAMECONTROLLERDB_COMMIT "b1e4090b3d4266e55feb0793efa35792e05faf66")
|
||||||
|
set(GAMECONTROLLERDB_URL "https://raw.githubusercontent.com/gabomdq/SDL_GameControllerDB/${GAMECONTROLLERDB_COMMIT}/gamecontrollerdb.txt")
|
||||||
|
|
||||||
|
file(DOWNLOAD ${GAMECONTROLLERDB_URL} ${CMAKE_SOURCE_DIR}/gamecontrollerdb.txt
|
||||||
|
TLS_VERIFY ON)
|
||||||
|
|
||||||
|
add_custom_target(DownloadGameControllerDB
|
||||||
|
DEPENDS ${CMAKE_SOURCE_DIR}/gamecontrollerdb.txt)
|
||||||
|
|
||||||
# Main executable
|
# Main executable
|
||||||
add_executable(Zelda64Recompiled)
|
add_executable(Zelda64Recompiled)
|
||||||
|
add_dependencies(Zelda64Recompiled DownloadGameControllerDB)
|
||||||
|
|
||||||
# Generate mm_shader_cache.c from the MM shader cache if it exists
|
# Generate mm_shader_cache.c from the MM shader cache if it exists
|
||||||
if (EXISTS ${CMAKE_SOURCE_DIR}/shadercache/mm_shader_cache.bin)
|
if (EXISTS ${CMAKE_SOURCE_DIR}/shadercache/mm_shader_cache.bin)
|
||||||
|
@ -120,6 +143,7 @@ set (SOURCES
|
||||||
${CMAKE_SOURCE_DIR}/src/main/main.cpp
|
${CMAKE_SOURCE_DIR}/src/main/main.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/main/register_overlays.cpp
|
${CMAKE_SOURCE_DIR}/src/main/register_overlays.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/main/register_patches.cpp
|
${CMAKE_SOURCE_DIR}/src/main/register_patches.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/main/rt64_render_context.cpp
|
||||||
|
|
||||||
${CMAKE_SOURCE_DIR}/src/game/input.cpp
|
${CMAKE_SOURCE_DIR}/src/game/input.cpp
|
||||||
${CMAKE_SOURCE_DIR}/src/game/controls.cpp
|
${CMAKE_SOURCE_DIR}/src/game/controls.cpp
|
||||||
|
@ -179,11 +203,17 @@ endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
if (DEFINED ENV{SDL2_VERSION})
|
||||||
|
set(SDL2_VERSION $ENV{SDL2_VERSION})
|
||||||
|
else()
|
||||||
|
set(SDL2_VERSION "2.30.3")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Fetch SDL2 on windows
|
# Fetch SDL2 on windows
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
sdl2
|
sdl2
|
||||||
URL https://github.com/libsdl-org/SDL/releases/download/release-2.28.5/SDL2-devel-2.28.5-VC.zip
|
URL https://github.com/libsdl-org/SDL/releases/download/release-${SDL2_VERSION}/SDL2-devel-${SDL2_VERSION}-VC.zip
|
||||||
URL_HASH MD5=d8173db078e54040c666f411c5a6afff
|
|
||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(sdl2)
|
FetchContent_MakeAvailable(sdl2)
|
||||||
target_include_directories(Zelda64Recompiled PRIVATE
|
target_include_directories(Zelda64Recompiled PRIVATE
|
||||||
|
@ -281,15 +311,12 @@ if (${WIN32})
|
||||||
set (DXC "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/x64/dxc.exe")
|
set (DXC "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/x64/dxc.exe")
|
||||||
add_compile_definitions(NOMINMAX)
|
add_compile_definitions(NOMINMAX)
|
||||||
else()
|
else()
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|AMD64")
|
|
||||||
if (APPLE)
|
|
||||||
set (DXC "DYLD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/x64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/x64/dxc")
|
|
||||||
else()
|
|
||||||
set (DXC "LD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/x64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/x64/dxc")
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
|
# Apple's binary is universal, so it'll work on both x86_64 and arm64
|
||||||
set (DXC "DYLD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/arm64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/arm64/dxc-macos")
|
set (DXC "DYLD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/arm64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/arm64/dxc-macos")
|
||||||
|
else()
|
||||||
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|AMD64")
|
||||||
|
set (DXC "LD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/x64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/x64/dxc")
|
||||||
else()
|
else()
|
||||||
set (DXC "LD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/arm64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/arm64/dxc-linux")
|
set (DXC "LD_LIBRARY_PATH=${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/lib/arm64" "${PROJECT_SOURCE_DIR}/lib/rt64/src/contrib/dxc/bin/arm64/dxc-linux")
|
||||||
endif()
|
endif()
|
||||||
|
@ -297,7 +324,7 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
build_vertex_shader(Zelda64Recompiled "shaders/InterfaceVS.hlsl" "shaders/InterfaceVS.hlsl")
|
build_vertex_shader(Zelda64Recompiled "shaders/InterfaceVS.hlsl" "shaders/InterfaceVS.hlsl")
|
||||||
build_pixel_shader (Zelda64Recompiled "shaders/InterfacePS.hlsl" "shaders/InterfacePS.hlsl")
|
build_pixel_shader(Zelda64Recompiled "shaders/InterfacePS.hlsl" "shaders/InterfacePS.hlsl")
|
||||||
|
|
||||||
target_sources(Zelda64Recompiled PRIVATE ${SOURCES})
|
target_sources(Zelda64Recompiled PRIVATE ${SOURCES})
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
|
#include "ultramodern/input.hpp"
|
||||||
|
|
||||||
#include "json/json.hpp"
|
#include "json/json.hpp"
|
||||||
|
|
||||||
namespace recomp {
|
namespace recomp {
|
||||||
|
@ -150,11 +152,13 @@ namespace recomp {
|
||||||
InputField& get_input_binding(GameInput input, size_t binding_index, InputDevice device);
|
InputField& get_input_binding(GameInput input, size_t binding_index, InputDevice device);
|
||||||
void set_input_binding(GameInput input, size_t binding_index, InputDevice device, InputField value);
|
void set_input_binding(GameInput input, size_t binding_index, InputDevice device, InputField value);
|
||||||
|
|
||||||
void get_n64_input(uint16_t* buttons_out, float* x_out, float* y_out);
|
bool get_n64_input(int controller_num, uint16_t* buttons_out, float* x_out, float* y_out);
|
||||||
void set_rumble(bool);
|
void set_rumble(int controller_num, bool);
|
||||||
void update_rumble();
|
void update_rumble();
|
||||||
void handle_events();
|
void handle_events();
|
||||||
|
|
||||||
|
ultramodern::input::connected_device_info_t get_connected_device_info(int controller_num);
|
||||||
|
|
||||||
// Rumble strength ranges from 0 to 100.
|
// Rumble strength ranges from 0 to 100.
|
||||||
int get_rumble_strength();
|
int get_rumble_strength();
|
||||||
void set_rumble_strength(int strength);
|
void set_rumble_strength(int strength);
|
||||||
|
|
|
@ -120,6 +120,8 @@ namespace recompui {
|
||||||
void activate_mouse();
|
void activate_mouse();
|
||||||
|
|
||||||
void message_box(const char* msg);
|
void message_box(const char* msg);
|
||||||
|
|
||||||
|
void set_render_hooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef __ZELDA_RENDER_H__
|
||||||
|
#define __ZELDA_RENDER_H__
|
||||||
|
|
||||||
|
#include "common/rt64_user_configuration.h"
|
||||||
|
#include "ultramodern/renderer_context.hpp"
|
||||||
|
|
||||||
|
namespace RT64 {
|
||||||
|
struct Application;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace zelda64 {
|
||||||
|
namespace renderer {
|
||||||
|
class RT64Context : public ultramodern::renderer::RendererContext {
|
||||||
|
public:
|
||||||
|
~RT64Context() override;
|
||||||
|
RT64Context(uint8_t *rdram, ultramodern::renderer::WindowHandle window_handle, bool developer_mode);
|
||||||
|
|
||||||
|
bool valid() override { return static_cast<bool>(app); }
|
||||||
|
|
||||||
|
bool update_config(const ultramodern::renderer::GraphicsConfig &old_config, const ultramodern::renderer::GraphicsConfig &new_config) override;
|
||||||
|
|
||||||
|
void enable_instant_present() override;
|
||||||
|
void send_dl(const OSTask *task) override;
|
||||||
|
void update_screen(uint32_t vi_origin) override;
|
||||||
|
void shutdown() override;
|
||||||
|
uint32_t get_display_framerate() const override;
|
||||||
|
float get_resolution_scale() const override;
|
||||||
|
void load_shader_cache(std::span<const char> cache_binary) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::unique_ptr<RT64::Application> app;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<ultramodern::renderer::RendererContext> create_render_context(uint8_t *rdram, ultramodern::renderer::WindowHandle window_handle, bool developer_mode);
|
||||||
|
|
||||||
|
RT64::UserConfiguration::Antialiasing RT64MaxMSAA();
|
||||||
|
bool RT64SamplePositionsSupported();
|
||||||
|
bool RT64HighPrecisionFBEnabled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -1 +1 @@
|
||||||
Subproject commit ec7e81b45d9a622cb3e45865ce5d7d3536b26534
|
Subproject commit 0c1811ca6f8291c6608f1d6626a73e863902ece9
|
|
@ -1,8 +1,8 @@
|
||||||
TARGET = patches.elf
|
TARGET = patches.elf
|
||||||
|
|
||||||
CC := clang
|
CC ?= clang
|
||||||
LD := ld.lld
|
LD ?= ld.lld
|
||||||
OBJCOPY := llvm-objcopy
|
OBJCOPY ?= llvm-objcopy
|
||||||
|
|
||||||
CFLAGS := -target mips -mips2 -mabi=32 -O2 -G0 -mno-abicalls -mno-odd-spreg -mno-check-zero-division \
|
CFLAGS := -target mips -mips2 -mabi=32 -O2 -G0 -mno-abicalls -mno-odd-spreg -mno-check-zero-division \
|
||||||
-fomit-frame-pointer -ffast-math -fno-unsafe-math-optimizations -fno-builtin-memset \
|
-fomit-frame-pointer -ffast-math -fno-unsafe-math-optimizations -fno-builtin-memset \
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "zelda_config.h"
|
#include "zelda_config.h"
|
||||||
#include "recomp_input.h"
|
#include "recomp_input.h"
|
||||||
#include "zelda_sound.h"
|
#include "zelda_sound.h"
|
||||||
|
#include "zelda_render.h"
|
||||||
#include "ultramodern/config.hpp"
|
#include "ultramodern/config.hpp"
|
||||||
#include "librecomp/files.hpp"
|
#include "librecomp/files.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
@ -20,21 +21,21 @@ constexpr std::u8string_view controls_filename = u8"controls.json";
|
||||||
constexpr std::u8string_view sound_filename = u8"sound.json";
|
constexpr std::u8string_view sound_filename = u8"sound.json";
|
||||||
constexpr std::u8string_view program_id = u8"Zelda64Recompiled";
|
constexpr std::u8string_view program_id = u8"Zelda64Recompiled";
|
||||||
|
|
||||||
constexpr auto res_default = ultramodern::Resolution::Auto;
|
constexpr auto res_default = ultramodern::renderer::Resolution::Auto;
|
||||||
constexpr auto hr_default = ultramodern::HUDRatioMode::Clamp16x9;
|
constexpr auto hr_default = ultramodern::renderer::HUDRatioMode::Clamp16x9;
|
||||||
constexpr auto api_default = ultramodern::GraphicsApi::Auto;
|
constexpr auto api_default = ultramodern::renderer::GraphicsApi::Auto;
|
||||||
constexpr auto ar_default = RT64::UserConfiguration::AspectRatio::Expand;
|
constexpr auto ar_default = ultramodern::renderer::AspectRatio::Expand;
|
||||||
constexpr auto msaa_default = RT64::UserConfiguration::Antialiasing::MSAA2X;
|
constexpr auto msaa_default = ultramodern::renderer::Antialiasing::MSAA2X;
|
||||||
constexpr auto rr_default = RT64::UserConfiguration::RefreshRate::Display;
|
constexpr auto rr_default = ultramodern::renderer::RefreshRate::Display;
|
||||||
constexpr auto hpfb_default = ultramodern::HighPrecisionFramebuffer::Auto;
|
constexpr auto hpfb_default = ultramodern::renderer::HighPrecisionFramebuffer::Auto;
|
||||||
constexpr int ds_default = 1;
|
constexpr int ds_default = 1;
|
||||||
constexpr int rr_manual_default = 60;
|
constexpr int rr_manual_default = 60;
|
||||||
constexpr bool developer_mode_default = false;
|
constexpr bool developer_mode_default = false;
|
||||||
|
|
||||||
static bool is_steam_deck = false;
|
static bool is_steam_deck = false;
|
||||||
|
|
||||||
ultramodern::WindowMode wm_default() {
|
ultramodern::renderer::WindowMode wm_default() {
|
||||||
return is_steam_deck ? ultramodern::WindowMode::Fullscreen : ultramodern::WindowMode::Windowed;
|
return is_steam_deck ? ultramodern::renderer::WindowMode::Fullscreen : ultramodern::renderer::WindowMode::Windowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __gnu_linux__
|
#ifdef __gnu_linux__
|
||||||
|
@ -86,7 +87,7 @@ void call_if_key_exists(void (*func)(T), const json& j, const std::string& key)
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ultramodern {
|
namespace ultramodern {
|
||||||
void to_json(json& j, const GraphicsConfig& config) {
|
void to_json(json& j, const renderer::GraphicsConfig& config) {
|
||||||
j = json{
|
j = json{
|
||||||
{"res_option", config.res_option},
|
{"res_option", config.res_option},
|
||||||
{"wm_option", config.wm_option},
|
{"wm_option", config.wm_option},
|
||||||
|
@ -102,7 +103,7 @@ namespace ultramodern {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void from_json(const json& j, GraphicsConfig& config) {
|
void from_json(const json& j, renderer::GraphicsConfig& config) {
|
||||||
config.res_option = from_or_default(j, "res_option", res_default);
|
config.res_option = from_or_default(j, "res_option", res_default);
|
||||||
config.wm_option = from_or_default(j, "wm_option", wm_default());
|
config.wm_option = from_or_default(j, "wm_option", wm_default());
|
||||||
config.hr_option = from_or_default(j, "hr_option", hr_default);
|
config.hr_option = from_or_default(j, "hr_option", hr_default);
|
||||||
|
@ -302,7 +303,7 @@ void zelda64::reset_kb_input_bindings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset_graphics_options() {
|
void reset_graphics_options() {
|
||||||
ultramodern::GraphicsConfig new_config{};
|
ultramodern::renderer::GraphicsConfig new_config{};
|
||||||
new_config.res_option = res_default;
|
new_config.res_option = res_default;
|
||||||
new_config.wm_option = wm_default();
|
new_config.wm_option = wm_default();
|
||||||
new_config.hr_option = hr_default;
|
new_config.hr_option = hr_default;
|
||||||
|
@ -313,12 +314,12 @@ void reset_graphics_options() {
|
||||||
new_config.hpfb_option = hpfb_default;
|
new_config.hpfb_option = hpfb_default;
|
||||||
new_config.rr_manual_value = rr_manual_default;
|
new_config.rr_manual_value = rr_manual_default;
|
||||||
new_config.developer_mode = developer_mode_default;
|
new_config.developer_mode = developer_mode_default;
|
||||||
ultramodern::set_graphics_config(new_config);
|
ultramodern::renderer::set_graphics_config(new_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool save_graphics_config(const std::filesystem::path& path) {
|
bool save_graphics_config(const std::filesystem::path& path) {
|
||||||
nlohmann::json config_json{};
|
nlohmann::json config_json{};
|
||||||
ultramodern::to_json(config_json, ultramodern::get_graphics_config());
|
ultramodern::to_json(config_json, ultramodern::renderer::get_graphics_config());
|
||||||
return save_json_with_backups(path, config_json);
|
return save_json_with_backups(path, config_json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,9 +329,9 @@ bool load_graphics_config(const std::filesystem::path& path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ultramodern::GraphicsConfig new_config{};
|
ultramodern::renderer::GraphicsConfig new_config{};
|
||||||
ultramodern::from_json(config_json, new_config);
|
ultramodern::from_json(config_json, new_config);
|
||||||
ultramodern::set_graphics_config(new_config);
|
ultramodern::renderer::set_graphics_config(new_config);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,11 +75,15 @@ void recomp::set_input_binding(recomp::GameInput input, size_t binding_index, re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void recomp::get_n64_input(uint16_t* buttons_out, float* x_out, float* y_out) {
|
bool recomp::get_n64_input(int controller_num, uint16_t* buttons_out, float* x_out, float* y_out) {
|
||||||
uint16_t cur_buttons = 0;
|
uint16_t cur_buttons = 0;
|
||||||
float cur_x = 0.0f;
|
float cur_x = 0.0f;
|
||||||
float cur_y = 0.0f;
|
float cur_y = 0.0f;
|
||||||
|
|
||||||
|
if (controller_num != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!recomp::game_input_disabled()) {
|
if (!recomp::game_input_disabled()) {
|
||||||
for (size_t i = 0; i < n64_button_values.size(); i++) {
|
for (size_t i = 0; i < n64_button_values.size(); i++) {
|
||||||
size_t input_index = (size_t)GameInput::N64_BUTTON_START + i;
|
size_t input_index = (size_t)GameInput::N64_BUTTON_START + i;
|
||||||
|
@ -107,4 +111,6 @@ void recomp::get_n64_input(uint16_t* buttons_out, float* x_out, float* y_out) {
|
||||||
*buttons_out = cur_buttons;
|
*buttons_out = cur_buttons;
|
||||||
*x_out = std::clamp(cur_x, -1.0f, 1.0f);
|
*x_out = std::clamp(cur_x, -1.0f, 1.0f);
|
||||||
*y_out = std::clamp(cur_y, -1.0f, 1.0f);
|
*y_out = std::clamp(cur_y, -1.0f, 1.0f);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,8 +446,25 @@ void recomp::poll_inputs() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void recomp::set_rumble(bool on) {
|
void recomp::set_rumble(int controller_num, bool on) {
|
||||||
|
if (controller_num == 0) {
|
||||||
InputState.rumble_active = on;
|
InputState.rumble_active = on;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ultramodern::input::connected_device_info_t recomp::get_connected_device_info(int controller_num) {
|
||||||
|
switch (controller_num) {
|
||||||
|
case 0:
|
||||||
|
return ultramodern::input::connected_device_info_t {
|
||||||
|
.connected_device = ultramodern::input::Device::Controller,
|
||||||
|
.connected_pak = ultramodern::input::Pak::RumblePak,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return ultramodern::input::connected_device_info_t {
|
||||||
|
.connected_device = ultramodern::input::Device::None,
|
||||||
|
.connected_pak = ultramodern::input::Pak::None,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static float smoothstep(float from, float to, float amount) {
|
static float smoothstep(float from, float to, float amount) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "zelda_config.h"
|
#include "zelda_config.h"
|
||||||
#include "recomp_input.h"
|
#include "recomp_input.h"
|
||||||
#include "recomp_ui.h"
|
#include "recomp_ui.h"
|
||||||
|
#include "zelda_render.h"
|
||||||
#include "zelda_sound.h"
|
#include "zelda_sound.h"
|
||||||
#include "librecomp/helpers.hpp"
|
#include "librecomp/helpers.hpp"
|
||||||
#include "../patches/input.h"
|
#include "../patches/input.h"
|
||||||
|
@ -12,7 +13,6 @@
|
||||||
#include "../patches/sound.h"
|
#include "../patches/sound.h"
|
||||||
#include "ultramodern/ultramodern.hpp"
|
#include "ultramodern/ultramodern.hpp"
|
||||||
#include "ultramodern/config.hpp"
|
#include "ultramodern/config.hpp"
|
||||||
#include "ultramodern/rt64_layer.hpp"
|
|
||||||
|
|
||||||
extern "C" void recomp_update_inputs(uint8_t* rdram, recomp_context* ctx) {
|
extern "C" void recomp_update_inputs(uint8_t* rdram, recomp_context* ctx) {
|
||||||
recomp::poll_inputs();
|
recomp::poll_inputs();
|
||||||
|
@ -59,17 +59,17 @@ extern "C" void recomp_get_target_framerate(uint8_t* rdram, recomp_context* ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void recomp_get_aspect_ratio(uint8_t* rdram, recomp_context* ctx) {
|
extern "C" void recomp_get_aspect_ratio(uint8_t* rdram, recomp_context* ctx) {
|
||||||
ultramodern::GraphicsConfig graphics_config = ultramodern::get_graphics_config();
|
ultramodern::renderer::GraphicsConfig graphics_config = ultramodern::renderer::get_graphics_config();
|
||||||
float original = _arg<0, float>(rdram, ctx);
|
float original = _arg<0, float>(rdram, ctx);
|
||||||
int width, height;
|
int width, height;
|
||||||
recompui::get_window_size(width, height);
|
recompui::get_window_size(width, height);
|
||||||
|
|
||||||
switch (graphics_config.ar_option) {
|
switch (graphics_config.ar_option) {
|
||||||
case RT64::UserConfiguration::AspectRatio::Original:
|
case ultramodern::renderer::AspectRatio::Original:
|
||||||
default:
|
default:
|
||||||
_return(ctx, original);
|
_return(ctx, original);
|
||||||
return;
|
return;
|
||||||
case RT64::UserConfiguration::AspectRatio::Expand:
|
case ultramodern::renderer::AspectRatio::Expand:
|
||||||
_return(ctx, std::max(static_cast<float>(width) / height, original));
|
_return(ctx, std::max(static_cast<float>(width) / height, original));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ extern "C" void recomp_load_overlays(uint8_t * rdram, recomp_context * ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void recomp_high_precision_fb_enabled(uint8_t * rdram, recomp_context * ctx) {
|
extern "C" void recomp_high_precision_fb_enabled(uint8_t * rdram, recomp_context * ctx) {
|
||||||
_return(ctx, static_cast<s32>(ultramodern::RT64HighPrecisionFBEnabled()));
|
_return(ctx, static_cast<s32>(zelda64::renderer::RT64HighPrecisionFBEnabled()));
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void recomp_get_resolution_scale(uint8_t* rdram, recomp_context* ctx) {
|
extern "C" void recomp_get_resolution_scale(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "recomp_input.h"
|
#include "recomp_input.h"
|
||||||
#include "zelda_config.h"
|
#include "zelda_config.h"
|
||||||
#include "zelda_sound.h"
|
#include "zelda_sound.h"
|
||||||
|
#include "zelda_render.h"
|
||||||
#include "ovl_patches.hpp"
|
#include "ovl_patches.hpp"
|
||||||
#include "librecomp/game.hpp"
|
#include "librecomp/game.hpp"
|
||||||
|
|
||||||
|
@ -40,9 +41,6 @@
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "../../lib/rt64/src/contrib/stb/stb_image.h"
|
#include "../../lib/rt64/src/contrib/stb/stb_image.h"
|
||||||
|
|
||||||
extern "C" void init();
|
|
||||||
/*extern "C"*/ void start(ultramodern::WindowHandle window_handle, const ultramodern::audio_callbacks_t* audio_callbacks, const ultramodern::input_callbacks_t* input_callbacks);
|
|
||||||
|
|
||||||
template<typename... Ts>
|
template<typename... Ts>
|
||||||
void exit_error(const char* str, Ts ...args) {
|
void exit_error(const char* str, Ts ...args) {
|
||||||
// TODO pop up an error
|
// TODO pop up an error
|
||||||
|
@ -121,11 +119,11 @@ bool SetImageAsIcon(const char* filename, SDL_Window* window)
|
||||||
|
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
|
|
||||||
ultramodern::WindowHandle create_window(ultramodern::gfx_callbacks_t::gfx_data_t) {
|
ultramodern::renderer::WindowHandle create_window(ultramodern::gfx_callbacks_t::gfx_data_t) {
|
||||||
window = SDL_CreateWindow("Zelda 64: Recompiled", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1600, 960, SDL_WINDOW_RESIZABLE );
|
window = SDL_CreateWindow("Zelda 64: Recompiled", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1600, 960, SDL_WINDOW_RESIZABLE );
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
SetImageAsIcon("icons/512.png",window);
|
SetImageAsIcon("icons/512.png",window);
|
||||||
if (ultramodern::get_graphics_config().wm_option == ultramodern::WindowMode::Fullscreen) { // TODO: Remove once RT64 gets native fullscreen support on Linux
|
if (ultramodern::renderer::get_graphics_config().wm_option == ultramodern::renderer::WindowMode::Fullscreen) { // TODO: Remove once RT64 gets native fullscreen support on Linux
|
||||||
SDL_SetWindowFullscreen(window,SDL_WINDOW_FULLSCREEN_DESKTOP);
|
SDL_SetWindowFullscreen(window,SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||||
} else {
|
} else {
|
||||||
SDL_SetWindowFullscreen(window,0);
|
SDL_SetWindowFullscreen(window,0);
|
||||||
|
@ -141,7 +139,7 @@ ultramodern::WindowHandle create_window(ultramodern::gfx_callbacks_t::gfx_data_t
|
||||||
SDL_GetWindowWMInfo(window, &wmInfo);
|
SDL_GetWindowWMInfo(window, &wmInfo);
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return ultramodern::WindowHandle{ wmInfo.info.win.window, GetCurrentThreadId() };
|
return ultramodern::renderer::WindowHandle{ wmInfo.info.win.window, GetCurrentThreadId() };
|
||||||
#elif defined(__ANDROID__)
|
#elif defined(__ANDROID__)
|
||||||
static_assert(false && "Unimplemented");
|
static_assert(false && "Unimplemented");
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
|
@ -149,7 +147,7 @@ ultramodern::WindowHandle create_window(ultramodern::gfx_callbacks_t::gfx_data_t
|
||||||
exit_error("Unsupported SDL2 video driver \"%s\". Only X11 is supported on Linux.\n", SDL_GetCurrentVideoDriver());
|
exit_error("Unsupported SDL2 video driver \"%s\". Only X11 is supported on Linux.\n", SDL_GetCurrentVideoDriver());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ultramodern::WindowHandle{ wmInfo.info.x11.display, wmInfo.info.x11.window };
|
return ultramodern::renderer::WindowHandle{ wmInfo.info.x11.display, wmInfo.info.x11.window };
|
||||||
#else
|
#else
|
||||||
static_assert(false && "Unimplemented");
|
static_assert(false && "Unimplemented");
|
||||||
#endif
|
#endif
|
||||||
|
@ -375,6 +373,11 @@ int main(int argc, char** argv) {
|
||||||
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||||
reset_audio(48000);
|
reset_audio(48000);
|
||||||
|
|
||||||
|
// Source controller mappings file
|
||||||
|
if (SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt") < 0) {
|
||||||
|
fprintf(stderr, "Failed to load controller mappings: %s\n", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
// Register supported games and patches
|
// Register supported games and patches
|
||||||
for (const auto& game : supported_games) {
|
for (const auto& game : supported_games) {
|
||||||
recomp::register_game(game);
|
recomp::register_game(game);
|
||||||
|
@ -390,6 +393,10 @@ int main(int argc, char** argv) {
|
||||||
.get_rsp_microcode = get_rsp_microcode,
|
.get_rsp_microcode = get_rsp_microcode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ultramodern::renderer::callbacks_t renderer_callbacks{
|
||||||
|
.create_render_context = zelda64::renderer::create_render_context,
|
||||||
|
};
|
||||||
|
|
||||||
ultramodern::gfx_callbacks_t gfx_callbacks{
|
ultramodern::gfx_callbacks_t gfx_callbacks{
|
||||||
.create_gfx = create_gfx,
|
.create_gfx = create_gfx,
|
||||||
.create_window = create_window,
|
.create_window = create_window,
|
||||||
|
@ -402,10 +409,11 @@ int main(int argc, char** argv) {
|
||||||
.set_frequency = set_frequency,
|
.set_frequency = set_frequency,
|
||||||
};
|
};
|
||||||
|
|
||||||
ultramodern::input_callbacks_t input_callbacks{
|
ultramodern::input::callbacks_t input_callbacks{
|
||||||
.poll_input = recomp::poll_inputs,
|
.poll_input = recomp::poll_inputs,
|
||||||
.get_input = recomp::get_n64_input,
|
.get_input = recomp::get_n64_input,
|
||||||
.set_rumble = recomp::set_rumble,
|
.set_rumble = recomp::set_rumble,
|
||||||
|
.get_connected_device_info = recomp::get_connected_device_info,
|
||||||
};
|
};
|
||||||
|
|
||||||
ultramodern::events::callbacks_t thread_callbacks{
|
ultramodern::events::callbacks_t thread_callbacks{
|
||||||
|
@ -417,7 +425,7 @@ int main(int argc, char** argv) {
|
||||||
.message_box = recompui::message_box,
|
.message_box = recompui::message_box,
|
||||||
};
|
};
|
||||||
|
|
||||||
recomp::start({}, rsp_callbacks, audio_callbacks, input_callbacks, gfx_callbacks, thread_callbacks, error_handling_callbacks);
|
recomp::start({}, rsp_callbacks, renderer_callbacks, audio_callbacks, input_callbacks, gfx_callbacks, thread_callbacks, error_handling_callbacks);
|
||||||
|
|
||||||
NFD_Quit();
|
NFD_Quit();
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,16 @@
|
||||||
#include "librecomp/overlays.hpp"
|
#include "librecomp/overlays.hpp"
|
||||||
|
|
||||||
void zelda64::register_overlays() {
|
void zelda64::register_overlays() {
|
||||||
recomp::overlay_section_table_data_t sections {
|
recomp::overlays::overlay_section_table_data_t sections {
|
||||||
.code_sections = section_table,
|
.code_sections = section_table,
|
||||||
.num_code_sections = ARRLEN(section_table),
|
.num_code_sections = ARRLEN(section_table),
|
||||||
.total_num_sections = num_sections,
|
.total_num_sections = num_sections,
|
||||||
};
|
};
|
||||||
|
|
||||||
recomp::overlays_by_index_t overlays {
|
recomp::overlays::overlays_by_index_t overlays {
|
||||||
.table = overlay_sections_by_index,
|
.table = overlay_sections_by_index,
|
||||||
.len = ARRLEN(overlay_sections_by_index),
|
.len = ARRLEN(overlay_sections_by_index),
|
||||||
};
|
};
|
||||||
|
|
||||||
recomp::register_overlays(sections, overlays);
|
recomp::overlays::register_overlays(sections, overlays);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,5 @@
|
||||||
#include "librecomp/game.hpp"
|
#include "librecomp/game.hpp"
|
||||||
|
|
||||||
void zelda64::register_patches() {
|
void zelda64::register_patches() {
|
||||||
// TODO: This is a bit awful, maybe provide only one functions that does both in librecomp?
|
recomp::overlays::register_patches(mm_patches_bin, sizeof(mm_patches_bin), section_table);
|
||||||
recomp::register_patch(mm_patches_bin, sizeof(mm_patches_bin));
|
|
||||||
recomp::register_patch_section(section_table);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,378 @@
|
||||||
|
#include <memory>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#define HLSL_CPU
|
||||||
|
#include "hle/rt64_application.h"
|
||||||
|
#include "rt64_render_hooks.h"
|
||||||
|
|
||||||
|
#include "ultramodern/ultramodern.hpp"
|
||||||
|
#include "ultramodern/config.hpp"
|
||||||
|
|
||||||
|
#include "zelda_render.h"
|
||||||
|
#include "recomp_ui.h"
|
||||||
|
|
||||||
|
static RT64::UserConfiguration::Antialiasing device_max_msaa = RT64::UserConfiguration::Antialiasing::None;
|
||||||
|
static bool sample_positions_supported = false;
|
||||||
|
static bool high_precision_fb_enabled = false;
|
||||||
|
|
||||||
|
static uint8_t DMEM[0x1000];
|
||||||
|
static uint8_t IMEM[0x1000];
|
||||||
|
|
||||||
|
unsigned int MI_INTR_REG = 0;
|
||||||
|
|
||||||
|
unsigned int DPC_START_REG = 0;
|
||||||
|
unsigned int DPC_END_REG = 0;
|
||||||
|
unsigned int DPC_CURRENT_REG = 0;
|
||||||
|
unsigned int DPC_STATUS_REG = 0;
|
||||||
|
unsigned int DPC_CLOCK_REG = 0;
|
||||||
|
unsigned int DPC_BUFBUSY_REG = 0;
|
||||||
|
unsigned int DPC_PIPEBUSY_REG = 0;
|
||||||
|
unsigned int DPC_TMEM_REG = 0;
|
||||||
|
|
||||||
|
unsigned int VI_STATUS_REG = 0;
|
||||||
|
unsigned int VI_ORIGIN_REG = 0;
|
||||||
|
unsigned int VI_WIDTH_REG = 0;
|
||||||
|
unsigned int VI_INTR_REG = 0;
|
||||||
|
unsigned int VI_V_CURRENT_LINE_REG = 0;
|
||||||
|
unsigned int VI_TIMING_REG = 0;
|
||||||
|
unsigned int VI_V_SYNC_REG = 0;
|
||||||
|
unsigned int VI_H_SYNC_REG = 0;
|
||||||
|
unsigned int VI_LEAP_REG = 0;
|
||||||
|
unsigned int VI_H_START_REG = 0;
|
||||||
|
unsigned int VI_V_START_REG = 0;
|
||||||
|
unsigned int VI_V_BURST_REG = 0;
|
||||||
|
unsigned int VI_X_SCALE_REG = 0;
|
||||||
|
unsigned int VI_Y_SCALE_REG = 0;
|
||||||
|
|
||||||
|
void dummy_check_interrupts() {}
|
||||||
|
|
||||||
|
RT64::UserConfiguration::Antialiasing compute_max_supported_aa(RT64::RenderSampleCounts bits) {
|
||||||
|
if (bits & RT64::RenderSampleCount::Bits::COUNT_2) {
|
||||||
|
if (bits & RT64::RenderSampleCount::Bits::COUNT_4) {
|
||||||
|
if (bits & RT64::RenderSampleCount::Bits::COUNT_8) {
|
||||||
|
return RT64::UserConfiguration::Antialiasing::MSAA8X;
|
||||||
|
}
|
||||||
|
return RT64::UserConfiguration::Antialiasing::MSAA4X;
|
||||||
|
}
|
||||||
|
return RT64::UserConfiguration::Antialiasing::MSAA2X;
|
||||||
|
};
|
||||||
|
return RT64::UserConfiguration::Antialiasing::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
RT64::UserConfiguration::AspectRatio to_rt64(ultramodern::renderer::AspectRatio option) {
|
||||||
|
switch (option) {
|
||||||
|
case ultramodern::renderer::AspectRatio::Original:
|
||||||
|
return RT64::UserConfiguration::AspectRatio::Original;
|
||||||
|
case ultramodern::renderer::AspectRatio::Expand:
|
||||||
|
return RT64::UserConfiguration::AspectRatio::Expand;
|
||||||
|
case ultramodern::renderer::AspectRatio::Manual:
|
||||||
|
return RT64::UserConfiguration::AspectRatio::Manual;
|
||||||
|
case ultramodern::renderer::AspectRatio::OptionCount:
|
||||||
|
return RT64::UserConfiguration::AspectRatio::OptionCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RT64::UserConfiguration::Antialiasing to_rt64(ultramodern::renderer::Antialiasing option) {
|
||||||
|
switch (option) {
|
||||||
|
case ultramodern::renderer::Antialiasing::None:
|
||||||
|
return RT64::UserConfiguration::Antialiasing::None;
|
||||||
|
case ultramodern::renderer::Antialiasing::MSAA2X:
|
||||||
|
return RT64::UserConfiguration::Antialiasing::MSAA2X;
|
||||||
|
case ultramodern::renderer::Antialiasing::MSAA4X:
|
||||||
|
return RT64::UserConfiguration::Antialiasing::MSAA4X;
|
||||||
|
case ultramodern::renderer::Antialiasing::MSAA8X:
|
||||||
|
return RT64::UserConfiguration::Antialiasing::MSAA8X;
|
||||||
|
case ultramodern::renderer::Antialiasing::OptionCount:
|
||||||
|
return RT64::UserConfiguration::Antialiasing::OptionCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RT64::UserConfiguration::RefreshRate to_rt64(ultramodern::renderer::RefreshRate option) {
|
||||||
|
switch (option) {
|
||||||
|
case ultramodern::renderer::RefreshRate::Original:
|
||||||
|
return RT64::UserConfiguration::RefreshRate::Original;
|
||||||
|
case ultramodern::renderer::RefreshRate::Display:
|
||||||
|
return RT64::UserConfiguration::RefreshRate::Display;
|
||||||
|
case ultramodern::renderer::RefreshRate::Manual:
|
||||||
|
return RT64::UserConfiguration::RefreshRate::Manual;
|
||||||
|
case ultramodern::renderer::RefreshRate::OptionCount:
|
||||||
|
return RT64::UserConfiguration::RefreshRate::OptionCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RT64::UserConfiguration::InternalColorFormat to_rt64(ultramodern::renderer::HighPrecisionFramebuffer option) {
|
||||||
|
switch (option) {
|
||||||
|
case ultramodern::renderer::HighPrecisionFramebuffer::Off:
|
||||||
|
return RT64::UserConfiguration::InternalColorFormat::Standard;
|
||||||
|
case ultramodern::renderer::HighPrecisionFramebuffer::On:
|
||||||
|
return RT64::UserConfiguration::InternalColorFormat::High;
|
||||||
|
case ultramodern::renderer::HighPrecisionFramebuffer::Auto:
|
||||||
|
return RT64::UserConfiguration::InternalColorFormat::Automatic;
|
||||||
|
case ultramodern::renderer::HighPrecisionFramebuffer::OptionCount:
|
||||||
|
return RT64::UserConfiguration::InternalColorFormat::OptionCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_application_user_config(RT64::Application* application, const ultramodern::renderer::GraphicsConfig& config) {
|
||||||
|
switch (config.res_option) {
|
||||||
|
default:
|
||||||
|
case ultramodern::renderer::Resolution::Auto:
|
||||||
|
application->userConfig.resolution = RT64::UserConfiguration::Resolution::WindowIntegerScale;
|
||||||
|
application->userConfig.downsampleMultiplier = 1;
|
||||||
|
break;
|
||||||
|
case ultramodern::renderer::Resolution::Original:
|
||||||
|
application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual;
|
||||||
|
application->userConfig.resolutionMultiplier = std::max(config.ds_option, 1);
|
||||||
|
application->userConfig.downsampleMultiplier = std::max(config.ds_option, 1);
|
||||||
|
break;
|
||||||
|
case ultramodern::renderer::Resolution::Original2x:
|
||||||
|
application->userConfig.resolution = RT64::UserConfiguration::Resolution::Manual;
|
||||||
|
application->userConfig.resolutionMultiplier = 2.0 * std::max(config.ds_option, 1);
|
||||||
|
application->userConfig.downsampleMultiplier = std::max(config.ds_option, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (config.hr_option) {
|
||||||
|
default:
|
||||||
|
case ultramodern::renderer::HUDRatioMode::Original:
|
||||||
|
application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Original;
|
||||||
|
break;
|
||||||
|
case ultramodern::renderer::HUDRatioMode::Clamp16x9:
|
||||||
|
application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Manual;
|
||||||
|
application->userConfig.extAspectTarget = 16.0/9.0;
|
||||||
|
break;
|
||||||
|
case ultramodern::renderer::HUDRatioMode::Full:
|
||||||
|
application->userConfig.extAspectRatio = RT64::UserConfiguration::AspectRatio::Expand;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
application->userConfig.aspectRatio = to_rt64(config.ar_option);
|
||||||
|
application->userConfig.antialiasing = to_rt64(config.msaa_option);
|
||||||
|
application->userConfig.refreshRate = to_rt64(config.rr_option);
|
||||||
|
application->userConfig.refreshRateTarget = config.rr_manual_value;
|
||||||
|
application->userConfig.internalColorFormat = to_rt64(config.hpfb_option);
|
||||||
|
}
|
||||||
|
|
||||||
|
ultramodern::renderer::SetupResult map_setup_result(RT64::Application::SetupResult rt64_result) {
|
||||||
|
switch (rt64_result) {
|
||||||
|
case RT64::Application::SetupResult::Success:
|
||||||
|
return ultramodern::renderer::SetupResult::Success;
|
||||||
|
case RT64::Application::SetupResult::DynamicLibrariesNotFound:
|
||||||
|
return ultramodern::renderer::SetupResult::DynamicLibrariesNotFound;
|
||||||
|
case RT64::Application::SetupResult::InvalidGraphicsAPI:
|
||||||
|
return ultramodern::renderer::SetupResult::InvalidGraphicsAPI;
|
||||||
|
case RT64::Application::SetupResult::GraphicsAPINotFound:
|
||||||
|
return ultramodern::renderer::SetupResult::GraphicsAPINotFound;
|
||||||
|
case RT64::Application::SetupResult::GraphicsDeviceNotFound:
|
||||||
|
return ultramodern::renderer::SetupResult::GraphicsDeviceNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Unhandled `RT64::Application::SetupResult` ?\n");
|
||||||
|
assert(false);
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
zelda64::renderer::RT64Context::RT64Context(uint8_t* rdram, ultramodern::renderer::WindowHandle window_handle, bool debug) {
|
||||||
|
static unsigned char dummy_rom_header[0x40];
|
||||||
|
recompui::set_render_hooks();
|
||||||
|
|
||||||
|
// Set up the RT64 application core fields.
|
||||||
|
RT64::Application::Core appCore{};
|
||||||
|
#if defined(_WIN32)
|
||||||
|
appCore.window = window_handle.window;
|
||||||
|
#elif defined(__ANDROID__)
|
||||||
|
assert(false && "Unimplemented");
|
||||||
|
#elif defined(__linux__)
|
||||||
|
appCore.window.display = window_handle.display;
|
||||||
|
appCore.window.window = window_handle.window;
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
appCore.window.window = window_handle.window;
|
||||||
|
appCore.window.view = window_handle.view;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
appCore.checkInterrupts = dummy_check_interrupts;
|
||||||
|
|
||||||
|
appCore.HEADER = dummy_rom_header;
|
||||||
|
appCore.RDRAM = rdram;
|
||||||
|
appCore.DMEM = DMEM;
|
||||||
|
appCore.IMEM = IMEM;
|
||||||
|
|
||||||
|
appCore.MI_INTR_REG = &MI_INTR_REG;
|
||||||
|
|
||||||
|
appCore.DPC_START_REG = &DPC_START_REG;
|
||||||
|
appCore.DPC_END_REG = &DPC_END_REG;
|
||||||
|
appCore.DPC_CURRENT_REG = &DPC_CURRENT_REG;
|
||||||
|
appCore.DPC_STATUS_REG = &DPC_STATUS_REG;
|
||||||
|
appCore.DPC_CLOCK_REG = &DPC_CLOCK_REG;
|
||||||
|
appCore.DPC_BUFBUSY_REG = &DPC_BUFBUSY_REG;
|
||||||
|
appCore.DPC_PIPEBUSY_REG = &DPC_PIPEBUSY_REG;
|
||||||
|
appCore.DPC_TMEM_REG = &DPC_TMEM_REG;
|
||||||
|
|
||||||
|
appCore.VI_STATUS_REG = &VI_STATUS_REG;
|
||||||
|
appCore.VI_ORIGIN_REG = &VI_ORIGIN_REG;
|
||||||
|
appCore.VI_WIDTH_REG = &VI_WIDTH_REG;
|
||||||
|
appCore.VI_INTR_REG = &VI_INTR_REG;
|
||||||
|
appCore.VI_V_CURRENT_LINE_REG = &VI_V_CURRENT_LINE_REG;
|
||||||
|
appCore.VI_TIMING_REG = &VI_TIMING_REG;
|
||||||
|
appCore.VI_V_SYNC_REG = &VI_V_SYNC_REG;
|
||||||
|
appCore.VI_H_SYNC_REG = &VI_H_SYNC_REG;
|
||||||
|
appCore.VI_LEAP_REG = &VI_LEAP_REG;
|
||||||
|
appCore.VI_H_START_REG = &VI_H_START_REG;
|
||||||
|
appCore.VI_V_START_REG = &VI_V_START_REG;
|
||||||
|
appCore.VI_V_BURST_REG = &VI_V_BURST_REG;
|
||||||
|
appCore.VI_X_SCALE_REG = &VI_X_SCALE_REG;
|
||||||
|
appCore.VI_Y_SCALE_REG = &VI_Y_SCALE_REG;
|
||||||
|
|
||||||
|
// Set up the RT64 application configuration fields.
|
||||||
|
RT64::ApplicationConfiguration appConfig;
|
||||||
|
appConfig.useConfigurationFile = false;
|
||||||
|
|
||||||
|
// Create the RT64 application.
|
||||||
|
app = std::make_unique<RT64::Application>(appCore, appConfig);
|
||||||
|
|
||||||
|
// Set initial user config settings based on the current settings.
|
||||||
|
auto& cur_config = ultramodern::renderer::get_graphics_config();
|
||||||
|
set_application_user_config(app.get(), cur_config);
|
||||||
|
app->userConfig.developerMode = debug;
|
||||||
|
// Force gbi depth branches to prevent LODs from kicking in.
|
||||||
|
app->enhancementConfig.f3dex.forceBranch = true;
|
||||||
|
// Scale LODs based on the output resolution.
|
||||||
|
app->enhancementConfig.textureLOD.scale = true;
|
||||||
|
// Pick an API if the user has set an override.
|
||||||
|
switch (cur_config.api_option) {
|
||||||
|
case ultramodern::renderer::GraphicsApi::D3D12:
|
||||||
|
app->userConfig.graphicsAPI = RT64::UserConfiguration::GraphicsAPI::D3D12;
|
||||||
|
break;
|
||||||
|
case ultramodern::renderer::GraphicsApi::Vulkan:
|
||||||
|
app->userConfig.graphicsAPI = RT64::UserConfiguration::GraphicsAPI::Vulkan;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case ultramodern::renderer::GraphicsApi::Auto:
|
||||||
|
// Don't override if auto is selected.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the RT64 application.
|
||||||
|
uint32_t thread_id = 0;
|
||||||
|
#ifdef _WIN32
|
||||||
|
thread_id = window_handle.thread_id;
|
||||||
|
#endif
|
||||||
|
setup_result = map_setup_result(app->setup(thread_id));
|
||||||
|
if (setup_result != ultramodern::renderer::SetupResult::Success) {
|
||||||
|
app = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the application's fullscreen state.
|
||||||
|
app->setFullScreen(cur_config.wm_option == ultramodern::renderer::WindowMode::Fullscreen);
|
||||||
|
|
||||||
|
// Check if the selected device actually supports MSAA sample positions and MSAA for for the formats that will be used
|
||||||
|
// and downgrade the configuration accordingly.
|
||||||
|
if (app->device->getCapabilities().sampleLocations) {
|
||||||
|
RT64::RenderSampleCounts color_sample_counts = app->device->getSampleCountsSupported(RT64::RenderFormat::R8G8B8A8_UNORM);
|
||||||
|
RT64::RenderSampleCounts depth_sample_counts = app->device->getSampleCountsSupported(RT64::RenderFormat::D32_FLOAT);
|
||||||
|
RT64::RenderSampleCounts common_sample_counts = color_sample_counts & depth_sample_counts;
|
||||||
|
device_max_msaa = compute_max_supported_aa(common_sample_counts);
|
||||||
|
sample_positions_supported = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
device_max_msaa = RT64::UserConfiguration::Antialiasing::None;
|
||||||
|
sample_positions_supported = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
high_precision_fb_enabled = app->shaderLibrary->usesHDR;
|
||||||
|
}
|
||||||
|
|
||||||
|
zelda64::renderer::RT64Context::~RT64Context() = default;
|
||||||
|
|
||||||
|
void zelda64::renderer::RT64Context::send_dl(const OSTask* task) {
|
||||||
|
app->state->rsp->reset();
|
||||||
|
app->interpreter->loadUCodeGBI(task->t.ucode & 0x3FFFFFF, task->t.ucode_data & 0x3FFFFFF, true);
|
||||||
|
app->processDisplayLists(app->core.RDRAM, task->t.data_ptr & 0x3FFFFFF, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void zelda64::renderer::RT64Context::update_screen(uint32_t vi_origin) {
|
||||||
|
VI_ORIGIN_REG = vi_origin;
|
||||||
|
|
||||||
|
app->updateScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
void zelda64::renderer::RT64Context::shutdown() {
|
||||||
|
if (app != nullptr) {
|
||||||
|
app->end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool zelda64::renderer::RT64Context::update_config(const ultramodern::renderer::GraphicsConfig& old_config, const ultramodern::renderer::GraphicsConfig& new_config) {
|
||||||
|
if (old_config == new_config) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_config.wm_option != old_config.wm_option) {
|
||||||
|
app->setFullScreen(new_config.wm_option == ultramodern::renderer::WindowMode::Fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
set_application_user_config(app.get(), new_config);
|
||||||
|
|
||||||
|
app->updateUserConfig(true);
|
||||||
|
|
||||||
|
if (new_config.msaa_option != old_config.msaa_option) {
|
||||||
|
app->updateMultisampling();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zelda64::renderer::RT64Context::enable_instant_present() {
|
||||||
|
// Enable the present early presentation mode for minimal latency.
|
||||||
|
app->enhancementConfig.presentation.mode = RT64::EnhancementConfiguration::Presentation::Mode::PresentEarly;
|
||||||
|
|
||||||
|
app->updateEnhancementConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t zelda64::renderer::RT64Context::get_display_framerate() const {
|
||||||
|
return app->presentQueue->ext.sharedResources->swapChainRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
float zelda64::renderer::RT64Context::get_resolution_scale() const {
|
||||||
|
constexpr int ReferenceHeight = 240;
|
||||||
|
switch (app->userConfig.resolution) {
|
||||||
|
case RT64::UserConfiguration::Resolution::WindowIntegerScale:
|
||||||
|
if (app->sharedQueueResources->swapChainHeight > 0) {
|
||||||
|
return std::max(float((app->sharedQueueResources->swapChainHeight + ReferenceHeight - 1) / ReferenceHeight), 1.0f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
case RT64::UserConfiguration::Resolution::Manual:
|
||||||
|
return float(app->userConfig.resolutionMultiplier);
|
||||||
|
case RT64::UserConfiguration::Resolution::Original:
|
||||||
|
default:
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void zelda64::renderer::RT64Context::load_shader_cache(std::span<const char> cache_binary) {
|
||||||
|
// TODO figure out how to avoid a copy here.
|
||||||
|
std::istringstream cache_stream{std::string{cache_binary.data(), cache_binary.size()}};
|
||||||
|
|
||||||
|
if (!app->rasterShaderCache->loadOfflineList(cache_stream)) {
|
||||||
|
printf("Failed to preload shader cache!\n");
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RT64::UserConfiguration::Antialiasing zelda64::renderer::RT64MaxMSAA() {
|
||||||
|
return device_max_msaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ultramodern::renderer::RendererContext> zelda64::renderer::create_render_context(uint8_t* rdram, ultramodern::renderer::WindowHandle window_handle, bool developer_mode) {
|
||||||
|
return std::make_unique<zelda64::renderer::RT64Context>(rdram, window_handle, developer_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool zelda64::renderer::RT64SamplePositionsSupported() {
|
||||||
|
return sample_positions_supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool zelda64::renderer::RT64HighPrecisionFBEnabled() {
|
||||||
|
return high_precision_fb_enabled;
|
||||||
|
}
|
|
@ -3,13 +3,13 @@
|
||||||
#include "zelda_sound.h"
|
#include "zelda_sound.h"
|
||||||
#include "zelda_config.h"
|
#include "zelda_config.h"
|
||||||
#include "zelda_debug.h"
|
#include "zelda_debug.h"
|
||||||
|
#include "zelda_render.h"
|
||||||
#include "promptfont.h"
|
#include "promptfont.h"
|
||||||
#include "ultramodern/config.hpp"
|
#include "ultramodern/config.hpp"
|
||||||
#include "ultramodern/ultramodern.hpp"
|
#include "ultramodern/ultramodern.hpp"
|
||||||
#include "RmlUi/Core.h"
|
#include "RmlUi/Core.h"
|
||||||
#include "ultramodern/rt64_layer.hpp"
|
|
||||||
|
|
||||||
ultramodern::GraphicsConfig new_options;
|
ultramodern::renderer::GraphicsConfig new_options;
|
||||||
Rml::DataModelHandle nav_help_model_handle;
|
Rml::DataModelHandle nav_help_model_handle;
|
||||||
Rml::DataModelHandle general_model_handle;
|
Rml::DataModelHandle general_model_handle;
|
||||||
Rml::DataModelHandle controls_model_handle;
|
Rml::DataModelHandle controls_model_handle;
|
||||||
|
@ -214,9 +214,9 @@ extern SDL_Window* window;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void apply_graphics_config(void) {
|
void apply_graphics_config(void) {
|
||||||
ultramodern::set_graphics_config(new_options);
|
ultramodern::renderer::set_graphics_config(new_options);
|
||||||
#if defined(__linux__) // TODO: Remove once RT64 gets native fullscreen support on Linux
|
#if defined(__linux__) // TODO: Remove once RT64 gets native fullscreen support on Linux
|
||||||
if (new_options.wm_option == ultramodern::WindowMode::Fullscreen) {
|
if (new_options.wm_option == ultramodern::renderer::WindowMode::Fullscreen) {
|
||||||
SDL_SetWindowFullscreen(window,SDL_WINDOW_FULLSCREEN_DESKTOP);
|
SDL_SetWindowFullscreen(window,SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||||
} else {
|
} else {
|
||||||
SDL_SetWindowFullscreen(window,0);
|
SDL_SetWindowFullscreen(window,0);
|
||||||
|
@ -225,7 +225,7 @@ void apply_graphics_config(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void close_config_menu() {
|
void close_config_menu() {
|
||||||
if (ultramodern::get_graphics_config() != new_options) {
|
if (ultramodern::renderer::get_graphics_config() != new_options) {
|
||||||
prompt_context.open_prompt(
|
prompt_context.open_prompt(
|
||||||
"Graphics options have changed",
|
"Graphics options have changed",
|
||||||
"Would you like to apply or discard the changes?",
|
"Would you like to apply or discard the changes?",
|
||||||
|
@ -237,7 +237,7 @@ void close_config_menu() {
|
||||||
close_config_menu_impl();
|
close_config_menu_impl();
|
||||||
},
|
},
|
||||||
[]() {
|
[]() {
|
||||||
new_options = ultramodern::get_graphics_config();
|
new_options = ultramodern::renderer::get_graphics_config();
|
||||||
graphics_model_handle.DirtyAllVariables();
|
graphics_model_handle.DirtyAllVariables();
|
||||||
close_config_menu_impl();
|
close_config_menu_impl();
|
||||||
},
|
},
|
||||||
|
@ -612,7 +612,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
ultramodern::sleep_milliseconds(50);
|
ultramodern::sleep_milliseconds(50);
|
||||||
new_options = ultramodern::get_graphics_config();
|
new_options = ultramodern::renderer::get_graphics_config();
|
||||||
bind_config_list_events(constructor);
|
bind_config_list_events(constructor);
|
||||||
|
|
||||||
constructor.BindFunc("res_option",
|
constructor.BindFunc("res_option",
|
||||||
|
@ -639,7 +639,7 @@ public:
|
||||||
});
|
});
|
||||||
constructor.BindFunc("ds_option",
|
constructor.BindFunc("ds_option",
|
||||||
[](Rml::Variant& out) {
|
[](Rml::Variant& out) {
|
||||||
if (new_options.res_option == ultramodern::Resolution::Auto) {
|
if (new_options.res_option == ultramodern::renderer::Resolution::Auto) {
|
||||||
out = 1;
|
out = 1;
|
||||||
} else {
|
} else {
|
||||||
out = new_options.ds_option;
|
out = new_options.ds_option;
|
||||||
|
@ -658,23 +658,23 @@ public:
|
||||||
|
|
||||||
constructor.BindFunc("options_changed",
|
constructor.BindFunc("options_changed",
|
||||||
[](Rml::Variant& out) {
|
[](Rml::Variant& out) {
|
||||||
out = (ultramodern::get_graphics_config() != new_options);
|
out = (ultramodern::renderer::get_graphics_config() != new_options);
|
||||||
});
|
});
|
||||||
constructor.BindFunc("ds_info",
|
constructor.BindFunc("ds_info",
|
||||||
[](Rml::Variant& out) {
|
[](Rml::Variant& out) {
|
||||||
switch (new_options.res_option) {
|
switch (new_options.res_option) {
|
||||||
default:
|
default:
|
||||||
case ultramodern::Resolution::Auto:
|
case ultramodern::renderer::Resolution::Auto:
|
||||||
out = "Downsampling is not available at auto resolution";
|
out = "Downsampling is not available at auto resolution";
|
||||||
return;
|
return;
|
||||||
case ultramodern::Resolution::Original:
|
case ultramodern::renderer::Resolution::Original:
|
||||||
if (new_options.ds_option == 2) {
|
if (new_options.ds_option == 2) {
|
||||||
out = "Rendered in 480p and scaled to 240p";
|
out = "Rendered in 480p and scaled to 240p";
|
||||||
} else if (new_options.ds_option == 4) {
|
} else if (new_options.ds_option == 4) {
|
||||||
out = "Rendered in 960p and scaled to 240p";
|
out = "Rendered in 960p and scaled to 240p";
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case ultramodern::Resolution::Original2x:
|
case ultramodern::renderer::Resolution::Original2x:
|
||||||
if (new_options.ds_option == 2) {
|
if (new_options.ds_option == 2) {
|
||||||
out = "Rendered in 960p and scaled to 480p";
|
out = "Rendered in 960p and scaled to 480p";
|
||||||
} else if (new_options.ds_option == 4) {
|
} else if (new_options.ds_option == 4) {
|
||||||
|
@ -1000,18 +1000,18 @@ void zelda64::set_debug_mode_enabled(bool enabled) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void recompui::update_supported_options() {
|
void recompui::update_supported_options() {
|
||||||
msaa2x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA2X;
|
msaa2x_supported = zelda64::renderer::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA2X;
|
||||||
msaa4x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA4X;
|
msaa4x_supported = zelda64::renderer::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA4X;
|
||||||
msaa8x_supported = ultramodern::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA8X;
|
msaa8x_supported = zelda64::renderer::RT64MaxMSAA() >= RT64::UserConfiguration::Antialiasing::MSAA8X;
|
||||||
sample_positions_supported = ultramodern::RT64SamplePositionsSupported();
|
sample_positions_supported = zelda64::renderer::RT64SamplePositionsSupported();
|
||||||
|
|
||||||
new_options = ultramodern::get_graphics_config();
|
new_options = ultramodern::renderer::get_graphics_config();
|
||||||
|
|
||||||
graphics_model_handle.DirtyAllVariables();
|
graphics_model_handle.DirtyAllVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
void recompui::toggle_fullscreen() {
|
void recompui::toggle_fullscreen() {
|
||||||
new_options.wm_option = (new_options.wm_option == ultramodern::WindowMode::Windowed) ? ultramodern::WindowMode::Fullscreen : ultramodern::WindowMode::Windowed;
|
new_options.wm_option = (new_options.wm_option == ultramodern::renderer::WindowMode::Windowed) ? ultramodern::renderer::WindowMode::Fullscreen : ultramodern::renderer::WindowMode::Windowed;
|
||||||
apply_graphics_config();
|
apply_graphics_config();
|
||||||
graphics_model_handle.DirtyVariable("wm_option");
|
graphics_model_handle.DirtyVariable("wm_option");
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
#include "concurrentqueue.h"
|
#include "concurrentqueue.h"
|
||||||
|
|
||||||
#include "ultramodern/rt64_layer.hpp"
|
|
||||||
#include "rt64_render_hooks.h"
|
#include "rt64_render_hooks.h"
|
||||||
#include "rt64_render_interface_builders.h"
|
#include "rt64_render_interface_builders.h"
|
||||||
|
|
||||||
|
@ -1458,7 +1457,7 @@ void deinit_hook() {
|
||||||
ui_context.reset();
|
ui_context.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_rt64_hooks() {
|
void recompui::set_render_hooks() {
|
||||||
RT64::SetRenderHooks(init_hook, draw_hook, deinit_hook);
|
RT64::SetRenderHooks(init_hook, draw_hook, deinit_hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue