21 Commits

Author SHA1 Message Date
RadiantDerg
c357062de8 Partial ratio text implementation 2025-01-19 04:22:12 -06:00
RadiantDerg
fc51d0e7ae Fix potential memory issue
Text/Line vectors could've been added to even if Reddog was never enabled, thus only ever expanding in size as they couldn't update.
2025-01-17 19:22:04 -06:00
Hyper
f4406cd8d0 Merge branch 'main' into debug-menu 2025-01-18 00:20:05 +00:00
RadiantDerg
2af11c8d2f Fix position text scaling with aspect ratio 2025-01-17 18:17:50 -06:00
Hyper
dd54867e58 Merge branch 'main' into debug-menu 2025-01-17 23:03:02 +00:00
Hyper
4b358d8e43 Rebase branch to main 2025-01-17 20:44:56 +00:00
Hyper
110f341af6 reddog_window: fix variable titlebar button positions 2025-01-17 20:17:59 +00:00
RadiantDerg
00e148b182 Draw position, Move patches to debug_patches.cpp 2025-01-17 20:17:56 +00:00
RadiantDerg
eb3225c2f7 SWA API mappings 2025-01-17 20:17:16 +00:00
Hyper
4ab26a1696 reddog: window improvements, added "welcome" message 2025-01-17 20:17:16 +00:00
Hyper
72a0a17e3a view_window: reordering and clean-up 2025-01-17 20:17:15 +00:00
Hyper
35b9361a91 api: use MmGetHostAddress for globals 2025-01-17 20:17:15 +00:00
Hyper
7788e36704 api: added globals struct 2025-01-17 20:17:15 +00:00
RadiantDerg
023fc0edf7 Added Vector mappings, Added DebugDraw class for drawing text on screen and in a popup
SWA API:
- Added CVector
- Added CVector4
- Combined CVectorX into one header

Reddog:
- Added toggle for visualizing the loaded GI Atlas Mipmap level
- Added toggles for rendering Havok collision
- Added toggles for Light Field
2025-01-17 20:17:12 +00:00
Hyper
d5ca843716 reddog: implemented FPS counter 2025-01-17 20:16:30 +00:00
Hyper
dbdf020218 reddog: improve button accuracy 2025-01-17 20:14:53 +00:00
Hyper
d5e947f520 reddog: improve window list accuracy 2025-01-17 20:14:52 +00:00
Hyper
a7e004fb60 reddog: improve window colour accuracy 2025-01-17 20:14:52 +00:00
Hyper
892e24f71e reddog: implemented custom button 2025-01-17 20:14:51 +00:00
Hyper
72a0507c66 Fix old header paths 2025-01-17 20:14:51 +00:00
Hyper
2f68ee5df2 Implemented mock reddog window manager
Requires micross.ttf font in game root and ENABLE_IM_FONT_ATLAS_SNAPSHOT undefined, not currently in the font atlas.
2025-01-17 20:14:50 +00:00
152 changed files with 3459 additions and 2525 deletions

View File

@@ -1,73 +0,0 @@
name: Build Project (Flatpak)
on:
workflow_dispatch:
env:
FLATPAK_ID: io.github.hedge_dev.unleashedrecomp
FREEDESKTOP_VERSION: 23.08
LLVM_VERSION: 18
jobs:
build-flatpak:
name: Build Flatpak
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ secrets.ORG_TOKEN }}
- name: Checkout private repository
uses: actions/checkout@v4
with:
repository: ${{ secrets.ASSET_REPO }}
token: ${{ secrets.ASSET_REPO_TOKEN }}
path: flatpak/private
- name: Install dependencies
run: |-
sudo apt update
sudo apt install -y flatpak-builder ccache
- name: Cache ccache directory
uses: actions/cache@v4
with:
path: /tmp/ccache
key: ccache-${{ runner.os }}
- name: Prepare Flatpak
run: |
flatpak --user remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak --user install -y flathub org.freedesktop.Sdk//${{ env.FREEDESKTOP_VERSION }}
flatpak --user install -y flathub org.freedesktop.Sdk.Extension.llvm${{ env.LLVM_VERSION }}//${{ env.FREEDESKTOP_VERSION }}
- name: Build Flatpak
run: |
echo "commit_message=$(git log -1 --pretty=%s)" >> $GITHUB_ENV
export CCACHE_DIR=/tmp/ccache
flatpak-builder --user --force-clean --install-deps-from=flathub --repo=repo --install --ccache builddir ./flatpak/${{ env.FLATPAK_ID }}.json
flatpak build-bundle repo ./${{ env.FLATPAK_ID }}.flatpak ${{ env.FLATPAK_ID }} --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo
# Uploads the built flatpak bundle to GitHub
# - name: Upload artifact
# uses: actions/upload-artifact@v4
# with:
# name: UnleashedRecomp-flatpak
# path: ./${{ env.FLATPAK_ID }}.flatpak
- name: Upload artifact to Discord
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
if: ${{ env.DISCORD_WEBHOOK != '' }}
uses: tsickert/discord-webhook@v6.0.0
with:
webhook-url: ${{ env.DISCORD_WEBHOOK }}
content: |
OS: Linux
Summary: ${{ env.commit_message }}
Commit: ${{ github.sha }}
Branch: ${{ github.ref_name }}
filename: ./${{ env.FLATPAK_ID }}.flatpak

View File

@@ -1,94 +0,0 @@
name: Build Project (Windows)
on:
workflow_dispatch:
env:
CMAKE_PRESET: x64-Clang-Release
jobs:
build:
name: Build Windows
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursive
token: ${{ secrets.ORG_TOKEN }}
- name: Checkout private repository
uses: actions/checkout@v4
with:
repository: ${{ secrets.ASSET_REPO }}
token: ${{ secrets.ASSET_REPO_TOKEN }}
path: .\private
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ccache-${{ runner.os }}
- name: Cache vcpkg
uses: actions/cache@v4
with:
path: |
./thirdparty/vcpkg/downloads
./thirdparty/vcpkg/packages
key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json') }}
restore-keys: |
vcpkg-${{ runner.os }}-
- name: Install dependencies
run: |
choco install ninja
Remove-Item -Path "C:\ProgramData\Chocolatey\bin\ccache.exe" -Force -ErrorAction SilentlyContinue
- name: Configure Developer Command Prompt
uses: ilammy/msvc-dev-cmd@v1
- name: Prepare Project
run: |
$commitMessage = git log -1 --pretty=%s
Add-Content -Path $env:GITHUB_ENV -Value "commit_message=$commitMessage"
copy .\private\* .\UnleashedRecompLib\private
- name: Configure Project
run: cmake . --preset ${{ env.CMAKE_PRESET }} -DSDL2MIXER_VORBIS=VORBISFILE -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache
- name: Build Project
run: cmake --build .\out\build\${{ env.CMAKE_PRESET }} --target UnleashedRecomp
- name: Pack Release
run: |
New-Item -ItemType Directory -Path .\release
New-Item -ItemType Directory -Path .\release\D3D12
Move-Item -Path ".\out\build\${{ env.CMAKE_PRESET }}\UnleashedRecomp\D3D12\D3D12Core.dll" -Destination ".\release\D3D12\D3D12Core.dll"
Move-Item -Path ".\out\build\${{ env.CMAKE_PRESET }}\UnleashedRecomp\dxcompiler.dll" -Destination ".\release\dxcompiler.dll"
Move-Item -Path ".\out\build\${{ env.CMAKE_PRESET }}\UnleashedRecomp\dxil.dll" -Destination ".\release\dxil.dll"
Move-Item -Path ".\out\build\${{ env.CMAKE_PRESET }}\UnleashedRecomp\UnleashedRecomp.exe" -Destination ".\release\UnleashedRecomp.exe"
Compress-Archive -Path .\release\* -DestinationPath .\UnleashedRecomp-Windows.zip
# Uploads the packed zip file to GitHub
# - name: Upload artifact
# uses: actions/upload-artifact@v4
# with:
# name: UnleashedRecomp-Windows
# path: .\UnleashedRecomp-Windows.zip
- name: Upload artifact to Discord
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
if: ${{ env.DISCORD_WEBHOOK != '' }}
uses: tsickert/discord-webhook@v6.0.0
with:
webhook-url: ${{ env.DISCORD_WEBHOOK }}
content: |
OS: Windows
Summary: ${{ env.commit_message }}
Commit: ${{ github.sha }}
Branch: ${{ github.ref_name }}
filename: .\UnleashedRecomp-Windows.zip

12
.gitmodules vendored
View File

@@ -1,12 +1,12 @@
[submodule "tools/XenonRecomp"]
path = tools/XenonRecomp
url = https://github.com/hedge-dev/XenonRecomp.git
[submodule "thirdparty/PowerRecomp"]
path = tools/PowerRecomp
url = https://github.com/hedge-dev/PowerRecomp
[submodule "thirdparty/ddspp"]
path = thirdparty/ddspp
url = https://github.com/redorav/ddspp.git
[submodule "tools/XenosRecomp"]
path = tools/XenosRecomp
url = https://github.com/hedge-dev/XenosRecomp.git
[submodule "thirdparty/ShaderRecomp"]
path = tools/ShaderRecomp
url = https://github.com/hedge-dev/ShaderRecomp.git
[submodule "thirdparty/libmspack"]
path = thirdparty/libmspack
url = https://github.com/kyz/libmspack

View File

@@ -5,8 +5,8 @@ if(NOT DEFINED ENV{VCPKG_ROOT})
endif()
include($ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
set(UNLEASHED_RECOMP_THIRDPARTY_ROOT ${CMAKE_SOURCE_DIR}/thirdparty)
set(UNLEASHED_RECOMP_TOOLS_ROOT ${CMAKE_SOURCE_DIR}/tools)
set(SWA_THIRDPARTY_ROOT ${CMAKE_SOURCE_DIR}/thirdparty)
set(SWA_TOOLS_ROOT ${CMAKE_SOURCE_DIR}/tools)
set(CMAKE_CXX_STANDARD 20)
set(BUILD_SHARED_LIBS OFF)
@@ -18,13 +18,8 @@ endif()
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
# Target Sandy Bridge for all projects
add_compile_options(
-march=sandybridge
)
add_subdirectory(${UNLEASHED_RECOMP_THIRDPARTY_ROOT})
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT})
add_subdirectory(${SWA_THIRDPARTY_ROOT})
add_subdirectory(${SWA_TOOLS_ROOT})
project("UnleashedRecomp-ALL")

View File

@@ -23,7 +23,8 @@
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
"toolset": "ClangCL"
},
{
"name": "x64-Clang-Debug",

View File

@@ -1,13 +1,16 @@
project("UnleashedRecomp")
set(TARGET_NAME "SWA")
if (WIN32)
option(UNLEASHED_RECOMP_D3D12 "Add D3D12 support for rendering" ON)
option(SWA_D3D12 "Add D3D12 support for rendering" ON)
endif()
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
option(UNLEASHED_RECOMP_FLATPAK "Configure the build for Flatpak compatibility." OFF)
option(SWA_FLATPAK "Configure the build for Flatpak compatibility." OFF)
endif()
option(SWA_XAUDIO2 "Use XAudio2 for audio playback" OFF)
function(BIN2C)
cmake_parse_arguments(BIN2C_ARGS "" "TARGET_OBJ;SOURCE_FILE;DEST_FILE;ARRAY_NAME;COMPRESSION_TYPE" "" ${ARGN})
@@ -39,7 +42,9 @@ function(BIN2C)
endfunction()
add_compile_options(
-march=sandybridge
-fno-strict-aliasing
-Wno-switch
-Wno-unused-function
-Wno-unused-variable
@@ -59,15 +64,16 @@ else()
endif()
add_compile_definitions(
SWA_IMPL
SDL_MAIN_HANDLED
_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR # Microsoft wtf?
_CRT_SECURE_NO_WARNINGS)
set(UNLEASHED_RECOMP_PRECOMPILED_HEADERS
set(SWA_PRECOMPILED_HEADERS
"stdafx.h"
)
set(UNLEASHED_RECOMP_KERNEL_CXX_SOURCES
set(SWA_KERNEL_CXX_SOURCES
"kernel/imports.cpp"
"kernel/xdm.cpp"
"kernel/heap.cpp"
@@ -76,13 +82,21 @@ set(UNLEASHED_RECOMP_KERNEL_CXX_SOURCES
"kernel/io/file_system.cpp"
)
set(UNLEASHED_RECOMP_LOCALE_CXX_SOURCES
set(SWA_LOCALE_CXX_SOURCES
"locale/config_locale.cpp"
"locale/locale.cpp"
)
set(SWA_OS_CXX_SOURCES
"os/logger.cpp"
"os/media.cpp"
"os/process.cpp"
"os/user.cpp"
"os/version.cpp"
)
if (WIN32)
set(UNLEASHED_RECOMP_OS_CXX_SOURCES
list(APPEND SWA_OS_CXX_SOURCES
"os/win32/logger_win32.cpp"
"os/win32/media_win32.cpp"
"os/win32/process_win32.cpp"
@@ -90,7 +104,7 @@ if (WIN32)
"os/win32/version_win32.cpp"
)
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
set(UNLEASHED_RECOMP_OS_CXX_SOURCES
list(APPEND SWA_OS_CXX_SOURCES
"os/linux/logger_linux.cpp"
"os/linux/media_linux.cpp"
"os/linux/process_linux.cpp"
@@ -99,11 +113,11 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
)
endif()
set(UNLEASHED_RECOMP_CPU_CXX_SOURCES
set(SWA_CPU_CXX_SOURCES
"cpu/guest_thread.cpp"
)
set(UNLEASHED_RECOMP_GPU_CXX_SOURCES
set(SWA_GPU_CXX_SOURCES
"gpu/video.cpp"
"gpu/imgui/imgui_common.cpp"
"gpu/imgui/imgui_font_builder.cpp"
@@ -111,24 +125,29 @@ set(UNLEASHED_RECOMP_GPU_CXX_SOURCES
"gpu/rhi/plume_vulkan.cpp"
)
if (UNLEASHED_RECOMP_D3D12)
list(APPEND UNLEASHED_RECOMP_GPU_CXX_SOURCES
if (SWA_D3D12)
list(APPEND SWA_GPU_CXX_SOURCES
"gpu/rhi/plume_d3d12.cpp"
)
endif()
set(UNLEASHED_RECOMP_APU_CXX_SOURCES
set(SWA_APU_CXX_SOURCES
"apu/audio.cpp"
"apu/embedded_player.cpp"
"apu/driver/sdl2_driver.cpp"
"apu/embedded_player.cpp"
)
set(UNLEASHED_RECOMP_HID_CXX_SOURCES
if (SWA_XAUDIO2)
list(APPEND SWA_APU_CXX_SOURCES "apu/driver/xaudio_driver.cpp")
else()
list(APPEND SWA_APU_CXX_SOURCES "apu/driver/sdl2_driver.cpp")
endif()
set(SWA_HID_CXX_SOURCES
"hid/hid.cpp"
"hid/driver/sdl_hid.cpp"
)
set(UNLEASHED_RECOMP_PATCHES_CXX_SOURCES
set(SWA_PATCHES_CXX_SOURCES
"patches/ui/CHudPause_patches.cpp"
"patches/ui/CTitleStateIntro_patches.cpp"
"patches/ui/CTitleStateMenu_patches.cpp"
@@ -136,9 +155,8 @@ set(UNLEASHED_RECOMP_PATCHES_CXX_SOURCES
"patches/aspect_ratio_patches.cpp"
"patches/audio_patches.cpp"
"patches/camera_patches.cpp"
"patches/CGameModeStageTitle_patches.cpp"
"patches/debug_patches.cpp"
"patches/fps_patches.cpp"
"patches/input_patches.cpp"
"patches/inspire_patches.cpp"
"patches/misc_patches.cpp"
"patches/object_patches.cpp"
@@ -147,7 +165,16 @@ set(UNLEASHED_RECOMP_PATCHES_CXX_SOURCES
"patches/video_patches.cpp"
)
set(UNLEASHED_RECOMP_UI_CXX_SOURCES
set(SWA_UI_CXX_SOURCES
"ui/reddog/windows/counter_window.cpp"
"ui/reddog/windows/exports_window.cpp"
"ui/reddog/windows/view_window.cpp"
"ui/reddog/windows/welcome_window.cpp"
"ui/reddog/windows/window_list.cpp"
"ui/reddog/reddog_controls.cpp"
"ui/reddog/reddog_manager.cpp"
"ui/reddog/reddog_window.cpp"
"ui/reddog/debug_draw.cpp"
"ui/achievement_menu.cpp"
"ui/achievement_overlay.cpp"
"ui/installer_wizard.cpp"
@@ -160,7 +187,7 @@ set(UNLEASHED_RECOMP_UI_CXX_SOURCES
"ui/game_window.cpp"
)
set(UNLEASHED_RECOMP_INSTALL_CXX_SOURCES
set(SWA_INSTALL_CXX_SOURCES
"install/installer.cpp"
"install/iso_file_system.cpp"
"install/memory_mapped_file.cpp"
@@ -176,56 +203,56 @@ set(UNLEASHED_RECOMP_INSTALL_CXX_SOURCES
"install/hashes/update.cpp"
)
set(UNLEASHED_RECOMP_USER_CXX_SOURCES
set(SWA_USER_CXX_SOURCES
"user/achievement_data.cpp"
"user/config.cpp"
)
set(UNLEASHED_RECOMP_MOD_CXX_SOURCES
set(SWA_MOD_CXX_SOURCES
"mod/mod_loader.cpp"
)
set(UNLEASHED_RECOMP_THIRDPARTY_SOURCES
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/imgui/backends/imgui_impl_sdl2.cpp"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/imgui/imgui.cpp"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/imgui/imgui_demo.cpp"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/imgui/imgui_draw.cpp"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/imgui/imgui_tables.cpp"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/imgui/imgui_widgets.cpp"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/implot/implot.cpp"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/implot/implot_demo.cpp"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/implot/implot_items.cpp"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/libmspack/libmspack/mspack/lzxd.c"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/tiny-AES-c/aes.c"
"${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp/thirdparty/smol-v/source/smolv.cpp"
set(SWA_THIRDPARTY_SOURCES
"${SWA_THIRDPARTY_ROOT}/imgui/backends/imgui_impl_sdl2.cpp"
"${SWA_THIRDPARTY_ROOT}/imgui/imgui.cpp"
"${SWA_THIRDPARTY_ROOT}/imgui/imgui_demo.cpp"
"${SWA_THIRDPARTY_ROOT}/imgui/imgui_draw.cpp"
"${SWA_THIRDPARTY_ROOT}/imgui/imgui_tables.cpp"
"${SWA_THIRDPARTY_ROOT}/imgui/imgui_widgets.cpp"
"${SWA_THIRDPARTY_ROOT}/implot/implot.cpp"
"${SWA_THIRDPARTY_ROOT}/implot/implot_demo.cpp"
"${SWA_THIRDPARTY_ROOT}/implot/implot_items.cpp"
"${SWA_THIRDPARTY_ROOT}/libmspack/libmspack/mspack/lzxd.c"
"${SWA_THIRDPARTY_ROOT}/tiny-AES-c/aes.c"
"${SWA_TOOLS_ROOT}/ShaderRecomp/thirdparty/smol-v/source/smolv.cpp"
)
set(UNLEASHED_RECOMP_THIRDPARTY_INCLUDES
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/concurrentqueue"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/ddspp"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/imgui"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/implot"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/libmspack/libmspack/mspack"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/magic_enum/include"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/stb"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/tiny-AES-c"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/TinySHA1"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/unordered_dense/include"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/volk"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/Vulkan-Headers/include"
"${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/VulkanMemoryAllocator/include"
"${UNLEASHED_RECOMP_TOOLS_ROOT}/bc_diff"
"${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp/thirdparty/smol-v/source"
set(SWA_THIRDPARTY_INCLUDES
"${SWA_THIRDPARTY_ROOT}/concurrentqueue"
"${SWA_THIRDPARTY_ROOT}/ddspp"
"${SWA_THIRDPARTY_ROOT}/imgui"
"${SWA_THIRDPARTY_ROOT}/implot"
"${SWA_THIRDPARTY_ROOT}/libmspack/libmspack/mspack"
"${SWA_THIRDPARTY_ROOT}/magic_enum/include"
"${SWA_THIRDPARTY_ROOT}/stb"
"${SWA_THIRDPARTY_ROOT}/tiny-AES-c"
"${SWA_THIRDPARTY_ROOT}/TinySHA1"
"${SWA_THIRDPARTY_ROOT}/unordered_dense/include"
"${SWA_THIRDPARTY_ROOT}/volk"
"${SWA_THIRDPARTY_ROOT}/Vulkan-Headers/include"
"${SWA_THIRDPARTY_ROOT}/VulkanMemoryAllocator/include"
"${SWA_TOOLS_ROOT}/bc_diff"
"${SWA_TOOLS_ROOT}/ShaderRecomp/thirdparty/smol-v/source"
)
if (UNLEASHED_RECOMP_D3D12)
list(APPEND UNLEASHED_RECOMP_THIRDPARTY_INCLUDES "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/D3D12MemoryAllocator/include")
list(APPEND UNLEASHED_RECOMP_THIRDPARTY_SOURCES "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/D3D12MemoryAllocator/src/D3D12MemAlloc.cpp")
if (SWA_D3D12)
list(APPEND SWA_THIRDPARTY_INCLUDES "${SWA_THIRDPARTY_ROOT}/D3D12MemoryAllocator/include")
list(APPEND SWA_THIRDPARTY_SOURCES "${SWA_THIRDPARTY_ROOT}/D3D12MemoryAllocator/src/D3D12MemAlloc.cpp")
endif()
set_source_files_properties(${UNLEASHED_RECOMP_THIRDPARTY_SOURCES} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
set_source_files_properties(${SWA_THIRDPARTY_SOURCES} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
set(UNLEASHED_RECOMP_CXX_SOURCES
set(SWA_CXX_SOURCES
"app.cpp"
"exports.cpp"
"main.cpp"
@@ -233,38 +260,40 @@ set(UNLEASHED_RECOMP_CXX_SOURCES
"stdafx.cpp"
"version.cpp"
${UNLEASHED_RECOMP_KERNEL_CXX_SOURCES}
${UNLEASHED_RECOMP_LOCALE_CXX_SOURCES}
${UNLEASHED_RECOMP_OS_CXX_SOURCES}
${UNLEASHED_RECOMP_CPU_CXX_SOURCES}
${UNLEASHED_RECOMP_GPU_CXX_SOURCES}
${UNLEASHED_RECOMP_APU_CXX_SOURCES}
${UNLEASHED_RECOMP_HID_CXX_SOURCES}
${UNLEASHED_RECOMP_PATCHES_CXX_SOURCES}
${UNLEASHED_RECOMP_UI_CXX_SOURCES}
${UNLEASHED_RECOMP_INSTALL_CXX_SOURCES}
${UNLEASHED_RECOMP_USER_CXX_SOURCES}
${UNLEASHED_RECOMP_MOD_CXX_SOURCES}
${UNLEASHED_RECOMP_THIRDPARTY_SOURCES}
${SWA_KERNEL_CXX_SOURCES}
${SWA_LOCALE_CXX_SOURCES}
${SWA_OS_CXX_SOURCES}
${SWA_CPU_CXX_SOURCES}
${SWA_GPU_CXX_SOURCES}
${SWA_APU_CXX_SOURCES}
${SWA_HID_CXX_SOURCES}
${SWA_PATCHES_CXX_SOURCES}
${SWA_UI_CXX_SOURCES}
${SWA_INSTALL_CXX_SOURCES}
${SWA_USER_CXX_SOURCES}
${SWA_MOD_CXX_SOURCES}
${SWA_THIRDPARTY_SOURCES}
)
if (WIN32)
# Set up Win32 resources for application icon.
set(ICON_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources/images/game_icon.ico")
configure_file("res/win32/res.rc.template" "${CMAKE_BINARY_DIR}/res.rc" @ONLY)
add_executable(UnleashedRecomp ${UNLEASHED_RECOMP_CXX_SOURCES} "${CMAKE_BINARY_DIR}/res.rc")
add_executable(UnleashedRecomp ${SWA_CXX_SOURCES} "${CMAKE_BINARY_DIR}/res.rc")
else()
add_executable(UnleashedRecomp ${UNLEASHED_RECOMP_CXX_SOURCES})
add_executable(UnleashedRecomp ${SWA_CXX_SOURCES})
endif()
if (UNLEASHED_RECOMP_FLATPAK)
set_target_properties(UnleashedRecomp PROPERTIES OUTPUT_NAME ${TARGET_NAME})
if (SWA_FLATPAK)
target_compile_definitions(UnleashedRecomp PRIVATE "GAME_INSTALL_DIRECTORY=\"/var/data\"")
endif()
if (UNLEASHED_RECOMP_D3D12)
if (SWA_D3D12)
find_package(directx-headers CONFIG REQUIRED)
find_package(directx12-agility CONFIG REQUIRED)
target_compile_definitions(UnleashedRecomp PRIVATE UNLEASHED_RECOMP_D3D12)
target_compile_definitions(UnleashedRecomp PRIVATE SWA_D3D12)
endif()
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
@@ -273,7 +302,7 @@ endif()
find_package(directx-dxc REQUIRED)
if (UNLEASHED_RECOMP_D3D12)
if (SWA_D3D12)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/D3D12)
add_custom_command(TARGET UnleashedRecomp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:Microsoft::DirectX12-Core,IMPORTED_LOCATION_RELEASE> ${CMAKE_CURRENT_BINARY_DIR}/D3D12
@@ -311,7 +340,7 @@ target_link_libraries(UnleashedRecomp PRIVATE
msdf-atlas-gen::msdf-atlas-gen
nfd::nfd
o1heap
XenonUtils
PowerUtils
SDL2::SDL2-static
SDL2_mixer
tomlplusplus::tomlplusplus
@@ -322,7 +351,7 @@ target_link_libraries(UnleashedRecomp PRIVATE
target_include_directories(UnleashedRecomp PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
"${CMAKE_CURRENT_SOURCE_DIR}/api"
${UNLEASHED_RECOMP_THIRDPARTY_INCLUDES}
${SWA_THIRDPARTY_INCLUDES}
)
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
@@ -331,12 +360,12 @@ if (CMAKE_SYSTEM_NAME MATCHES "Linux")
target_link_libraries(UnleashedRecomp PRIVATE ${X11_LIBRARIES})
endif()
target_precompile_headers(UnleashedRecomp PUBLIC ${UNLEASHED_RECOMP_PRECOMPILED_HEADERS})
target_precompile_headers(UnleashedRecomp PUBLIC ${SWA_PRECOMPILED_HEADERS})
function(compile_shader FILE_PATH TARGET_NAME)
set(FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gpu/shader/${FILE_PATH}.hlsl)
cmake_path(GET FILE_PATH STEM VARIABLE_NAME)
if (UNLEASHED_RECOMP_D3D12)
if (SWA_D3D12)
add_custom_command(
OUTPUT ${FILE_PATH}.dxil.h
COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -Wno-ignored-attributes -Fh ${FILE_PATH}.dxil.h ${FILE_PATH} -Vn g_${VARIABLE_NAME}_dxil
@@ -408,9 +437,9 @@ generate_aggregate_header(
)
# Only show build type if not Release.
set(SHOW_GIT_INFO_AND_BUILD_TYPE 0)
set(IS_BUILD_TYPE_IN_VER_STRING 0)
if (NOT ${CMAKE_BUILD_TYPE} MATCHES "Release")
set(SHOW_GIT_INFO_AND_BUILD_TYPE 1)
set(IS_BUILD_TYPE_IN_VER_STRING 1)
endif()
include("version.cmake")
@@ -420,8 +449,8 @@ GenerateVersionSources(
H_TEMPLATE "${PROJECT_SOURCE_DIR}/res/version.h.template"
CXX_TEMPLATE "${PROJECT_SOURCE_DIR}/res/version.cpp.template"
BUILD_TYPE ${CMAKE_BUILD_TYPE}
SHOW_GIT_INFO ${SHOW_GIT_INFO_AND_BUILD_TYPE}
SHOW_BUILD_TYPE ${SHOW_GIT_INFO_AND_BUILD_TYPE}
IS_BUILD_TYPE_IN_VER_STRING ${IS_BUILD_TYPE_IN_VER_STRING}
IS_GIT_REPO 1
)
set(RESOURCES_SOURCE_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources")
@@ -437,6 +466,24 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/co
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/kbm.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/kbm.dds" ARRAY_NAME "g_kbm" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_fade.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_fade.dds" ARRAY_NAME "g_select_fade" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select_fill.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select_fill.dds" ARRAY_NAME "g_select_fill" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_close_1.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_close_1.dds" ARRAY_NAME "g_button_close_1")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_close_2.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_close_2.dds" ARRAY_NAME "g_button_close_2")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_minimum_1.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_minimum_1.dds" ARRAY_NAME "g_button_minimum_1")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_minimum_2.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_minimum_2.dds" ARRAY_NAME "g_button_minimum_2")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_pin_1.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_pin_1.dds" ARRAY_NAME "g_button_pin_1")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/button_pin_2.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/button_pin_2.dds" ARRAY_NAME "g_button_pin_2")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/checkbox_1.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/checkbox_1.dds" ARRAY_NAME "g_checkbox_1")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/checkbox_2.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/checkbox_2.dds" ARRAY_NAME "g_checkbox_2")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/common_button_1.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/common_button_1.dds" ARRAY_NAME "g_common_button_1")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/common_button_2.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/common_button_2.dds" ARRAY_NAME "g_common_button_2")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/common_icon.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/common_icon.dds" ARRAY_NAME "g_common_icon")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/debug_icon.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/debug_icon.dds" ARRAY_NAME "g_debug_icon")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/mouse_cursor.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/mouse_cursor.bmp" ARRAY_NAME "g_mouse_cursor")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/mouse_cursor_h.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/mouse_cursor_h.bmp" ARRAY_NAME "g_mouse_cursor_h")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/mouse_cursor_slant_l.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/mouse_cursor_slant_l.bmp" ARRAY_NAME "g_mouse_cursor_slant_l")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/mouse_cursor_slant_r.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/mouse_cursor_slant_r.bmp" ARRAY_NAME "g_mouse_cursor_slant_r")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/mouse_cursor_v.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/mouse_cursor_v.bmp" ARRAY_NAME "g_mouse_cursor_v")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/reddog/title_bar.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/reddog/title_bar.dds" ARRAY_NAME "g_title_bar")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/arrow_circle.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/arrow_circle.dds" ARRAY_NAME "g_arrow_circle" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_001.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_001.dds" ARRAY_NAME "g_install_001" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_002.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_002.dds" ARRAY_NAME "g_install_002" COMPRESSION_TYPE "zstd")
@@ -450,6 +497,7 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/in
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/pulse_install.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/pulse_install.dds" ARRAY_NAME "g_pulse_install" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/achievement_notifications.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/achievement_notifications.dds" ARRAY_NAME "g_achievement_notifications" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/allow_background_input.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/allow_background_input.dds" ARRAY_NAME "g_allow_background_input" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/allow_dpad_movement.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/allow_dpad_movement.dds" ARRAY_NAME "g_allow_dpad_movement" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/antialiasing.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/antialiasing.dds" ARRAY_NAME "g_antialiasing" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/aspect_ratio.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/aspect_ratio.dds" ARRAY_NAME "g_aspect_ratio" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/battle_theme.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/battle_theme.dds" ARRAY_NAME "g_battle_theme" COMPRESSION_TYPE "zstd")
@@ -491,7 +539,8 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/op
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vibration.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vibration.dds" ARRAY_NAME "g_vibration" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/vsync.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/vsync.dds" ARRAY_NAME "g_vsync" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/window_size.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/window_size.dds" ARRAY_NAME "g_window_size" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/xbox_color_correction.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/xbox_color_correction.dds" ARRAY_NAME "g_xbox_color_correction" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/xbox_color_correction_false.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/xbox_color_correction_false.dds" ARRAY_NAME "g_xbox_color_correction_false" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/xbox_color_correction_true.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/xbox_color_correction_true.dds" ARRAY_NAME "g_xbox_color_correction_true" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/miles_electric.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/miles_electric.dds" ARRAY_NAME "g_miles_electric" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon.bmp" ARRAY_NAME "g_game_icon")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/game_icon_night.bmp" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/game_icon_night.bmp" ARRAY_NAME "g_game_icon_night")

View File

@@ -9,41 +9,41 @@ namespace Chao::CSD
inline void CNode::SetText(const char* in_pText)
{
GuestToHostFunction<int>(sub_830BF640, this, in_pText);
GuestToHostFunction<int>(0x830BF640, this, in_pText);
}
inline void CNode::SetText(const wchar_t* in_pText)
{
GuestToHostFunction<int>(sub_830BF640, this, in_pText);
GuestToHostFunction<int>(0x830BF640, this, in_pText);
}
inline void CNode::GetPosition(Hedgehog::Math::CVector2& out_rResult) const
{
GuestToHostFunction<void>(sub_830BF008, &out_rResult, this);
GuestToHostFunction<void>(0x830BF008, &out_rResult, this);
}
inline void CNode::SetPosition(float in_X, float in_Y)
{
GuestToHostFunction<int>(sub_830BF078, this, in_X, in_Y);
GuestToHostFunction<int>(0x830BF078, this, in_X, in_Y);
}
inline void CNode::SetHideFlag(uint32_t in_HideFlag)
{
GuestToHostFunction<int>(sub_830BF080, this, in_HideFlag);
GuestToHostFunction<int>(0x830BF080, this, in_HideFlag);
}
inline void CNode::SetRotation(float in_Rotation)
{
GuestToHostFunction<int>(sub_830BF088, this, in_Rotation);
GuestToHostFunction<int>(0x830BF088, this, in_Rotation);
}
inline void CNode::SetScale(float in_X, float in_Y)
{
GuestToHostFunction<int>(sub_830BF090, this, in_X, in_Y);
GuestToHostFunction<int>(0x830BF090, this, in_X, in_Y);
}
inline void CNode::SetPatternIndex(uint32_t in_PatternIndex)
{
GuestToHostFunction<int>(sub_830BF300, this, in_PatternIndex);
GuestToHostFunction<int>(0x830BF300, this, in_PatternIndex);
}
}

View File

@@ -5,20 +5,20 @@ namespace Chao::CSD
inline RCPtr<CScene> CProject::CreateScene(const char* in_pName) const
{
RCPtr<CScene> rcScene;
GuestToHostFunction<void>(sub_830BEE00, this, rcScene, in_pName, nullptr);
GuestToHostFunction<void>(0x830BEE00, this, rcScene, in_pName, nullptr);
return rcScene;
}
inline RCPtr<CScene> CProject::CreateScene(const char* in_pName, const char* in_pMotionName) const
{
RCPtr<CScene> rcScene;
GuestToHostFunction<void>(sub_830BECE0, this, rcScene, in_pName, in_pMotionName, nullptr);
GuestToHostFunction<void>(0x830BECE0, this, rcScene, in_pName, in_pMotionName, nullptr);
return rcScene;
}
inline void CProject::DestroyScene(CScene* in_pScene)
{
GuestToHostFunction<void>(sub_830BE298, this, in_pScene);
GuestToHostFunction<void>(0x830BE298, this, in_pScene);
}
inline void CProject::DestroyScene(RCPtr<CScene>& inout_rcScene)

View File

@@ -30,6 +30,6 @@ namespace Chao::CSD
inline void RCPtrAbs::RCObject::Release()
{
GuestToHostFunction<void>(sub_830BA068, this);
GuestToHostFunction<void>(0x830BA068, this);
}
}

View File

@@ -27,12 +27,12 @@ namespace Chao::CSD
inline void RCPtrAbs::AttachAbs(void* in_pMemory)
{
GuestToHostFunction<void>(sub_830BA298, this, in_pMemory);
GuestToHostFunction<void>(0x830BA298, this, in_pMemory);
}
inline void RCPtrAbs::SetAbs(const RCPtrAbs& in_rPtr)
{
GuestToHostFunction<void>(sub_830BA328, this, in_rPtr);
GuestToHostFunction<void>(0x830BA328, this, in_rPtr);
}
inline void* RCPtrAbs::operator*() const

View File

@@ -22,7 +22,7 @@ namespace Chao::CSD
inline bool CScene::SetMotion(const char* in_pName)
{
return GuestToHostFunction<bool>(sub_830BA760, this, in_pName);
return GuestToHostFunction<bool>(0x830BA760, this, in_pName);
}
inline void CScene::SetMotionFrame(float in_MotionFrame)
@@ -33,21 +33,21 @@ namespace Chao::CSD
inline void CScene::SetPosition(float in_X, float in_Y)
{
GuestToHostFunction<void>(sub_830BB550, this, in_X, in_Y);
GuestToHostFunction<void>(0x830BB550, this, in_X, in_Y);
}
inline void CScene::SetHideFlag(uint32_t in_HideFlag)
{
GuestToHostFunction<void>(sub_830BB378, this, in_HideFlag);
GuestToHostFunction<void>(0x830BB378, this, in_HideFlag);
}
inline void CScene::SetRotation(float in_Angle)
{
GuestToHostFunction<void>(sub_830BB5F8, this, in_Angle);
GuestToHostFunction<void>(0x830BB5F8, this, in_Angle);
}
inline void CScene::SetScale(float in_X, float in_Y)
{
GuestToHostFunction<void>(sub_830BB650, this, in_X, in_Y);
GuestToHostFunction<void>(0x830BB650, this, in_X, in_Y);
}
}

View File

@@ -0,0 +1,19 @@
#pragma once
#include <SWA.inl>
namespace Hedgehog::Math
{
class CAabb // Eigen::AlignedBox3f
{
public:
Hedgehog::Math::CVector min;
Hedgehog::Math::CVector max;
CVector Center() const;
};
SWA_ASSERT_SIZEOF(CAabb, 0x18);
}
#include "Aabb.inl"

View File

@@ -0,0 +1,12 @@
namespace Hedgehog::Math
{
inline CVector Hedgehog::Math::CAabb::Center() const
{
// return (min + max) / 2;
Hedgehog::Math::CVector result;
result.X = (max.X + min.X) * 0.5f;
result.Y = (max.Y + min.Y) * 0.5f;
result.Z = 0.5f * (max.Z + min.Z);
return result;
}
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include <SWA.inl>
namespace Hedgehog::Math
{
class CMatrix
{
public:
be<float> data[16]; // Eigen::Affine3f
};
class CMatrix44
{
public:
be<float> data[16]; // Eigen::Matrix4f
};
SWA_ASSERT_SIZEOF(CMatrix, 0x40);
SWA_ASSERT_SIZEOF(CMatrix44, 0x40);
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <SWA.inl>
namespace Hedgehog::Math
{
class CQuaternion //Eigen::Quaternionf;
{
public:
be<float> X;
be<float> Y;
be<float> Z;
be<float> W;
};
SWA_ASSERT_SIZEOF(CQuaternion, 0x10);
}

View File

@@ -17,7 +17,6 @@ namespace Hedgehog::Math
be<float> X;
be<float> Y;
be<float> Z;
be<float> W;
};
class CVector4
@@ -29,3 +28,5 @@ namespace Hedgehog::Math
be<float> W;
};
}
#include "Vector.inl"

View File

@@ -0,0 +1,4 @@
namespace Hedgehog::Math
{
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include <SWA.inl>
namespace Hedgehog::Mirage
{
class CCamera : Base::CObject
{
public:
Math::CMatrix m_View;
Math::CMatrix44 m_Projection;
Math::CVector m_Position;
Math::CVector m_Direction;
be<float> m_AspectRatio;
be<float> m_Near;
be<float> m_Far;
};
}

View File

@@ -1,32 +0,0 @@
#pragma once
#include <SWA.inl>
#include <Hedgehog/Base/hhObject.h>
#include <Hedgehog/Universe/Engine/hhMessageProcess.h>
#include <Hedgehog/Universe/Engine/hhStateMachineMessageReceiver.h>
namespace Hedgehog::Universe
{
class CStateMachineBase : public IStateMachineMessageReceiver, public Base::CObject
{
public:
class CStateBase : public IMessageProcess
{
public:
SWA_INSERT_PADDING(0x08);
xpointer<void> m_pContext;
xpointer<CStateMachineBase> m_pStateMachine;
be<float> m_Time;
SWA_INSERT_PADDING(0x4C);
void* GetContextBase() const;
template<typename T>
T* GetContextBase() const;
};
SWA_INSERT_PADDING(0x60);
};
}
#include <Hedgehog/Universe/Engine/hhStateMachineBase.inl>

View File

@@ -1,13 +0,0 @@
namespace Hedgehog::Universe
{
inline void* CStateMachineBase::CStateBase::GetContextBase() const
{
return m_pContext;
}
template<typename T>
inline T* CStateMachineBase::CStateBase::GetContextBase() const
{
return (T*)m_pContext.get();
}
}

View File

@@ -1,12 +0,0 @@
#pragma once
#include <SWA.inl>
namespace Hedgehog::Universe
{
class IStateMachineMessageReceiver
{
public:
IStateMachineMessageReceiver(const swa_null_ctor&) {}
};
}

View File

@@ -27,7 +27,11 @@
#include "Hedgehog/Base/Type/hhSharedString.h"
#include "Hedgehog/Base/hhObject.h"
#include "Hedgehog/Database/System/hhDatabaseData.h"
#include "Hedgehog/Math/Aabb.h"
#include "Hedgehog/Math/Matrix.h"
#include "Hedgehog/Math/Quaternion.h"
#include "Hedgehog/Math/Vector.h"
#include "Hedgehog/MirageCore/Camera/hhCamera.h"
#include "Hedgehog/MirageCore/Misc/hhVertexDeclarationPtr.h"
#include "Hedgehog/MirageCore/RenderData/hhMaterialData.h"
#include "Hedgehog/MirageCore/RenderData/hhMeshData.h"
@@ -47,8 +51,6 @@
#include "Hedgehog/Sparkle/hhParticleMaterial.h"
#include "Hedgehog/Universe/Engine/hhMessageActor.h"
#include "Hedgehog/Universe/Engine/hhMessageProcess.h"
#include "Hedgehog/Universe/Engine/hhStateMachineBase.h"
#include "Hedgehog/Universe/Engine/hhStateMachineMessageReceiver.h"
#include "Hedgehog/Universe/Engine/hhUpdateInfo.h"
#include "Hedgehog/Universe/Engine/hhUpdateUnit.h"
#include "Hedgehog/Universe/Thread/hhParallelJob.h"
@@ -59,8 +61,7 @@
#include "SWA/CSD/CsdTexListMirage.h"
#include "SWA/CSD/GameObjectCSD.h"
#include "SWA/Camera/Camera.h"
#include "SWA/Camera/CameraController.h"
#include "SWA/CharacterUtility/CharacterProxy.h"
#include "SWA/Globals.h"
#include "SWA/HUD/GeneralWindow/GeneralWindow.h"
#include "SWA/HUD/Loading/Loading.h"
#include "SWA/HUD/Pause/HudPause.h"
@@ -75,9 +76,10 @@
#include "SWA/Inspire/InspireTextureAnimationInfo.h"
#include "SWA/Inspire/InspireTextureOverlay.h"
#include "SWA/Inspire/InspireTextureOverlayInfo.h"
#include "SWA/Menu/MenuWindowBase.h"
#include "SWA/Movie/MovieDisplayer.h"
#include "SWA/Movie/MovieManager.h"
#include "SWA/Path/PathController.h"
#include "SWA/Path/Animation/PathAnimation.h"
#include "SWA/Player/Character/EvilSonic/EvilSonic.h"
#include "SWA/Player/Character/EvilSonic/EvilSonicContext.h"
#include "SWA/Player/Character/EvilSonic/Hud/EvilHudGuide.h"
@@ -96,18 +98,14 @@
#include "SWA/System/GameMode/GameMode.h"
#include "SWA/System/GameMode/GameModeStage.h"
#include "SWA/System/GameMode/GameModeStageMovie.h"
#include "SWA/System/GameMode/GameModeStageTitle.h"
#include "SWA/System/GameMode/Title/TitleMenu.h"
#include "SWA/System/GameMode/Title/TitleStateBase.h"
#include "SWA/System/GameMode/Title/TitleStateIntro.h"
#include "SWA/System/GameMode/Title/TitleStateWorldMap.h"
#include "SWA/System/GameMode/WorldMap/WorldMapCamera.h"
#include "SWA/System/GameMode/WorldMap/WorldMapCursor.h"
#include "SWA/System/GameObject.h"
#include "SWA/System/GameParameter.h"
#include "SWA/System/GammaController.h"
#include "SWA/System/InputState.h"
#include "SWA/System/PadState.h"
#include "SWA/System/StageManager.h"
#include "SWA/System/World.h"
#include "boost/smart_ptr/make_shared_object.h"
#include "boost/smart_ptr/shared_ptr.h"

View File

@@ -3,7 +3,7 @@ namespace SWA
inline boost::shared_ptr<CCsdProject> CCsdDatabaseWrapper::GetCsdProject(const Hedgehog::Base::CSharedString& in_rName)
{
boost::shared_ptr<CCsdProject> spCsdProject;
GuestToHostFunction<void>(sub_825E2B40, &in_rName, this, &spCsdProject, 0);
GuestToHostFunction<void>(0x825E2B40, &in_rName, this, &spCsdProject, 0);
return spCsdProject;
}
}

View File

@@ -9,7 +9,8 @@ namespace SWA
{
public:
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0xC4);
// SWA::CCamera::MyCamera
SWA_INSERT_PADDING(0xC4);
be<float> m_VertAspectRatio;
SWA_INSERT_PADDING(0x48);
be<float> m_HorzAspectRatio;

View File

@@ -1,17 +0,0 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CCameraController : public Hedgehog::Universe::CStateMachineBase::CStateBase
{
public:
SWA_INSERT_PADDING(0x04);
be<float> m_FieldOfView;
SWA_INSERT_PADDING(0x68);
};
SWA_ASSERT_OFFSETOF(CCameraController, m_FieldOfView, 0x64);
SWA_ASSERT_SIZEOF(CCameraController, 0xD0);
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <Hedgehog/Math/Vector.h>
namespace SWA
{
class CCharacterProxy
{
public:
SWA_INSERT_PADDING(0x120);
Hedgehog::Math::CVector m_Position;
Hedgehog::Math::CVector m_Velocity;
};
}

View File

@@ -0,0 +1,69 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
struct SGlobals
{
// ms_DrawLightFieldSamplingPoint: サンプリング点をデバッグ表示
static inline bool* ms_DrawLightFieldSamplingPoint;
// ms_IgnoreLightFieldData: データを無視する
static inline bool* ms_IgnoreLightFieldData;
// IsCollisionRender
static inline bool* ms_IsCollisionRender;
// N/A
static inline bool* ms_IsLoading;
// IsObjectCollisionRender
static inline bool* ms_IsObjectCollisionRender;
// ms_IsRenderDebugDraw: デバッグ描画
static inline bool* ms_IsRenderDebugDraw;
// ms_IsRenderDebugDrawText: デバッグ文字描画
static inline bool* ms_IsRenderDebugDrawText;
// ms_IsRenderDebugPositionDraw: デバッグ位置描画
static inline bool* ms_IsRenderDebugPositionDraw;
// ms_IsRenderGameMainHud: ゲームメインHUD 描画
static inline bool* ms_IsRenderGameMainHud;
// ms_IsRenderHud: 全 HUD 描画
static inline bool* ms_IsRenderHud;
// ms_IsRenderHudPause: ポーズメニュー 描画
static inline bool* ms_IsRenderHudPause;
// IsTriggerRender
static inline bool* ms_IsTriggerRender;
// ms_LightFieldDebug: 値をデバッグ表示
static inline bool* ms_LightFieldDebug;
// VisualizeLoadedLevel: ミップレベルを視覚化 赤=0, 緑=1, 青=2, 黄=未ロード
static inline bool* ms_VisualizeLoadedLevel;
static void Init()
{
ms_DrawLightFieldSamplingPoint = (bool*)MmGetHostAddress(0x83367BCE);
ms_IgnoreLightFieldData = (bool*)MmGetHostAddress(0x83367BCF);
ms_IsCollisionRender = (bool*)MmGetHostAddress(0x833678A6);
ms_IsLoading = (bool*)MmGetHostAddress(0x83367A4C);
ms_IsObjectCollisionRender = (bool*)MmGetHostAddress(0x83367905);
ms_IsRenderDebugDraw = (bool*)MmGetHostAddress(0x8328BB23);
ms_IsRenderDebugDrawText = (bool*)MmGetHostAddress(0x8328BB25);
ms_IsRenderDebugPositionDraw = (bool*)MmGetHostAddress(0x8328BB24);
ms_IsRenderGameMainHud = (bool*)MmGetHostAddress(0x8328BB27);
ms_IsRenderHud = (bool*)MmGetHostAddress(0x8328BB26);
ms_IsRenderHudPause = (bool*)MmGetHostAddress(0x8328BB28);
ms_IsTriggerRender = (bool*)MmGetHostAddress(0x83367904);
ms_LightFieldDebug = (bool*)MmGetHostAddress(0x83367BCD);
ms_VisualizeLoadedLevel = (bool*)MmGetHostAddress(0x833678C1);
}
};
}

View File

@@ -1,12 +0,0 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CMenuWindowBase
{
public:
SWA_INSERT_PADDING(0x10);
};
}

View File

@@ -0,0 +1,22 @@
#pragma once
namespace SWA::PathAnimation
{
class Entity
{
public:
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0x18);
};
class Controller
{
public:
xpointer<void> m_pVftable;
SWA_INSERT_PADDING(0x1C);
be<float> m_DistanceAlongPath;
};
SWA_ASSERT_OFFSETOF(Controller, m_DistanceAlongPath, 0x20);
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include "Animation/PathAnimation.h"
namespace SWA
{
class CPathController
{
public:
be<uint32_t> m_Field000;
be<uint32_t> m_Field004;
boost::shared_ptr<PathAnimation::Controller> m_spPathAnimationController;
};
}

View File

@@ -29,7 +29,8 @@ namespace SWA
SWA_INSERT_PADDING(0x10);
};
SWA_INSERT_PADDING(0x1C);
SWA_INSERT_PADDING(0x10);
hh::map<Hedgehog::Base::CSharedString, boost::shared_ptr<SWA::CWorld>> m_Worlds;
boost::shared_ptr<Hedgehog::Database::CDatabase> m_spDatabase;
SWA_INSERT_PADDING(0x88);
Hedgehog::Base::CSharedString m_StageName;

View File

@@ -4,9 +4,10 @@
namespace SWA
{
class CGameMode : public Hedgehog::Universe::CStateMachineBase::CStateBase
class CGameMode // : Hedgehog::Universe::TStateMachine<SWA::CGame>::TState
{
public:
SWA_INSERT_PADDING(0x60); // base
SWA_INSERT_PADDING(0x08);
};
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CGameModeStageTitle : public CGameModeStage
{
public:
SWA_INSERT_PADDING(0x0E);
bool m_IsPlayingAdvertiseMovie;
be<float> m_AdvertiseMovieWaitTime;
};
}

View File

@@ -4,14 +4,19 @@
namespace SWA
{
class CTitleStateBase : public Hedgehog::Universe::CStateMachineBase::CStateBase
class CTitleStateBase // : Hedgehog::Universe::TStateMachine<SWA::CTitleManager>::TState
{
public:
class CTitleStateContext
class CMember
{
public:
SWA_INSERT_PADDING(0x1E8);
xpointer<CTitleMenu> m_pTitleMenu;
};
SWA_INSERT_PADDING(0x08);
xpointer<CMember> m_pMember;
SWA_INSERT_PADDING(0x5C);
be<uint32_t> m_State;
};
}

View File

@@ -1,8 +0,0 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CTitleStateIntro : public CTitleStateBase {};
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <SWA.inl>
#include <SWA/System/GameMode/WorldMap/WorldMapCursor.h>
namespace SWA
{
class CTitleStateWorldMap : public CTitleStateBase
{
public:
SWA_INSERT_PADDING(0x08);
xpointer<CWorldMapCursor> m_pWorldMapCursor;
};
}

View File

@@ -1,26 +0,0 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CWorldMapCamera : public CCameraController
{
public:
be<float> m_Pitch;
be<float> m_Yaw;
be<float> m_Distance;
be<float> m_RotationSpeed;
SWA_INSERT_PADDING(0x08);
bool m_CanMove;
SWA_INSERT_PADDING(0x34);
be<float> m_TiltToEarthTransitionSpeed;
};
SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_Pitch, 0xD0);
SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_Yaw, 0xD4);
SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_Distance, 0xD8);
SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_RotationSpeed, 0xDC);
SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_CanMove, 0xE8);
SWA_ASSERT_OFFSETOF(CWorldMapCamera, m_TiltToEarthTransitionSpeed, 0x120);
}

View File

@@ -1,24 +0,0 @@
#pragma once
#include <SWA.inl>
namespace SWA
{
class CWorldMapCursor : public CMenuWindowBase
{
public:
SWA_INSERT_PADDING(0x24);
be<float> m_LeftStickVertical;
be<float> m_LeftStickHorizontal;
bool m_IsCursorMoving;
SWA_INSERT_PADDING(0x07);
be<float> m_CursorY;
be<float> m_CursorX;
};
SWA_ASSERT_OFFSETOF(CWorldMapCursor, m_LeftStickVertical, 0x34);
SWA_ASSERT_OFFSETOF(CWorldMapCursor, m_LeftStickHorizontal, 0x38);
SWA_ASSERT_OFFSETOF(CWorldMapCursor, m_IsCursorMoving, 0x3C);
SWA_ASSERT_OFFSETOF(CWorldMapCursor, m_CursorY, 0x44);
SWA_ASSERT_OFFSETOF(CWorldMapCursor, m_CursorX, 0x48);
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include "SWA.inl"
#include "Hedgehog/Base/Thread/hhSynchronizedObject.h"
#include "Hedgehog/Universe/Engine/hhMessageActor.h"
#include "SWA/System/GameObject.h"
namespace SWA
{
class CStageManager //: public SWA::CGameObject, public Hedgehog::Base::CSynchronizedObject
{
public:
SWA_INSERT_PADDING(0xC4);
boost::shared_ptr<SWA::CPathController> m_spStageGuidePathController; //xpointer<SWA::CPathController> m_pStageGuidePathController;
SWA_INSERT_PADDING(0x4);
Hedgehog::Math::CVector m_PlayerPosition;
be<float> m_Field0DC; // Sonic's air distance from path??
SWA_INSERT_PADDING(0x3C);
be<float> m_StageGuidePathRatio; // Not updated in retail
be<float> m_StageGuidePathLength;
SWA_INSERT_PADDING(0x9C);
};
SWA_ASSERT_OFFSETOF(CStageManager, m_spStageGuidePathController, 0xC4);
SWA_ASSERT_OFFSETOF(CStageManager, m_PlayerPosition, 0xD0);
SWA_ASSERT_OFFSETOF(CStageManager, m_StageGuidePathRatio, 0x11C);
SWA_ASSERT_OFFSETOF(CStageManager, m_StageGuidePathLength, 0x120);
SWA_ASSERT_SIZEOF(CStageManager, 0x1C0);
}

View File

@@ -12,9 +12,21 @@ namespace SWA
class CMember
{
public:
SWA_INSERT_PADDING(0x80);
//boost::shared_ptr<Hedgehog::Mirage::CRenderScene> m_spRenderScene;
//Hedgehog::Base::CSharedString m_Name;
SWA_INSERT_PADDING(0xC);
boost::shared_ptr<CCamera> m_spCamera;
boost::shared_ptr<CCamera> m_spOverrideCamera;
SWA_INSERT_PADDING(0x64);
};
xpointer<CMember> m_pMember;
boost::shared_ptr<CCamera> GetCamera() const;
};
//SWA_ASSERT_OFFSETOF(CWorld::CMember, m_spCamera, 0xC);
//SWA_ASSERT_SIZEOF(CWorld::CMember, 0x80);
}
#include "World.inl"

View File

@@ -0,0 +1,7 @@
namespace SWA
{
inline boost::shared_ptr<CCamera> CWorld::GetCamera() const
{
return m_pMember->m_spOverrideCamera ? m_pMember->m_spOverrideCamera : m_pMember->m_spCamera;
}
}

View File

@@ -1,4 +1,5 @@
#include <app.h>
#include <api/SWA.h>
#include <gpu/video.h>
#include <install/installer.h>
#include <kernel/function.h>
@@ -7,7 +8,6 @@
#include <patches/inspire_patches.h>
#include <ui/game_window.h>
#include <user/config.h>
#include <user/paths.h>
void App::Restart(std::vector<std::string> restartArgs)
{
@@ -34,6 +34,8 @@ PPC_FUNC(sub_824EB490)
App::s_isMissingDLC = !Installer::checkAllDLC(GetGamePath());
App::s_language = Config::Language;
SWA::SGlobals::Init();
__imp__sub_824EB490(ctx, base);
}

View File

@@ -9,7 +9,6 @@ public:
static inline bool s_isMissingDLC;
static inline bool s_isLoading;
static inline bool s_isWerehog;
static inline bool s_isSaveDataCorrupt;
static inline ELanguage s_language;

View File

@@ -7,10 +7,11 @@
// Number of samples in a frame
#define XAUDIO_NUM_SAMPLES 256
#ifdef SWA_IMPL
void XAudioInitializeSystem();
void XAudioRegisterClient(PPCFunc* callback, uint32_t param);
void XAudioSubmitFrame(void* samples);
void XAudioConfigValueChangedCallback(class IConfigDef* configDef);
#endif
uint32_t XAudioRegisterRenderDriverClient(be<uint32_t>* callback, be<uint32_t>* driver);
uint32_t XAudioUnregisterRenderDriverClient(uint32_t driver);

View File

@@ -1,29 +1,26 @@
#include <apu/audio.h>
#include "sdl2_driver.h"
#include <cpu/guest_thread.h>
#include <kernel/heap.h>
#include <user/config.h>
static PPCFunc* g_clientCallback{};
static uint32_t g_clientCallbackParam{}; // pointer in guest memory
static SDL_AudioDeviceID g_audioDevice{};
static bool g_downMixToStereo;
static void CreateAudioDevice()
void XAudioInitializeSystem()
{
if (g_audioDevice != NULL)
SDL_CloseAudioDevice(g_audioDevice);
bool surround = Config::ChannelConfiguration == EChannelConfiguration::Surround;
int allowedChanges = surround ? SDL_AUDIO_ALLOW_CHANNELS_CHANGE : 0;
SDL_SetHint(SDL_HINT_AUDIO_CATEGORY, "playback");
SDL_SetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME, "Unleashed Recompiled");
SDL_InitSubSystem(SDL_INIT_AUDIO);
SDL_AudioSpec desired{}, obtained{};
desired.freq = XAUDIO_SAMPLES_HZ;
desired.format = AUDIO_F32SYS;
desired.channels = surround ? XAUDIO_NUM_CHANNELS : 2;
desired.channels = XAUDIO_NUM_CHANNELS;
desired.samples = XAUDIO_NUM_SAMPLES;
g_audioDevice = SDL_OpenAudioDevice(nullptr, 0, &desired, &obtained, allowedChanges);
g_audioDevice = SDL_OpenAudioDevice(nullptr, 0, &desired, &obtained, SDL_AUDIO_ALLOW_CHANNELS_CHANGE);
if (obtained.channels != 2 && obtained.channels != XAUDIO_NUM_CHANNELS) // This check may fail only when surround sound is enabled.
if (obtained.channels != 2 && obtained.channels != XAUDIO_NUM_CHANNELS)
{
SDL_CloseAudioDevice(g_audioDevice);
g_audioDevice = SDL_OpenAudioDevice(nullptr, 0, &desired, &obtained, 0);
@@ -32,16 +29,7 @@ static void CreateAudioDevice()
g_downMixToStereo = (obtained.channels == 2);
}
void XAudioInitializeSystem()
{
SDL_SetHint(SDL_HINT_AUDIO_CATEGORY, "playback");
SDL_SetHint(SDL_HINT_AUDIO_DEVICE_APP_NAME, "Unleashed Recompiled");
SDL_InitSubSystem(SDL_INIT_AUDIO);
CreateAudioDevice();
}
static std::unique_ptr<std::thread> g_audioThread;
static volatile bool g_audioThreadShouldExit;
static void AudioThread()
{
@@ -51,7 +39,7 @@ static void AudioThread()
size_t channels = g_downMixToStereo ? 2 : XAUDIO_NUM_CHANNELS;
while (!g_audioThreadShouldExit)
while (true)
{
uint32_t queuedAudioSize = SDL_GetQueuedAudioSize(g_audioDevice);
constexpr size_t MAX_LATENCY = 10;
@@ -74,13 +62,6 @@ static void AudioThread()
}
}
static void CreateAudioThread()
{
SDL_PauseAudioDevice(g_audioDevice, 0);
g_audioThreadShouldExit = false;
g_audioThread = std::make_unique<std::thread>(AudioThread);
}
void XAudioRegisterClient(PPCFunc* callback, uint32_t param)
{
auto* pClientParam = static_cast<uint32_t*>(g_userHeap.Alloc(sizeof(param)));
@@ -89,7 +70,8 @@ void XAudioRegisterClient(PPCFunc* callback, uint32_t param)
g_clientCallbackParam = g_memory.MapVirtual(pClientParam);
g_clientCallback = callback;
CreateAudioThread();
SDL_PauseAudioDevice(g_audioDevice, 0);
g_audioThread = std::make_unique<std::thread>(AudioThread);
}
void XAudioSubmitFrame(void* samples)
@@ -137,18 +119,3 @@ void XAudioSubmitFrame(void* samples)
SDL_QueueAudio(g_audioDevice, &audioFrames, sizeof(audioFrames));
}
}
void XAudioConfigValueChangedCallback(IConfigDef* configDef)
{
if (configDef == &Config::ChannelConfiguration)
{
if (g_audioThread->joinable())
{
g_audioThreadShouldExit = true;
g_audioThread->join();
}
CreateAudioDevice();
CreateAudioThread();
}
}

View File

@@ -0,0 +1,3 @@
#pragma once
#include <apu/audio.h>

View File

@@ -0,0 +1,121 @@
#include <stdafx.h>
#include "xaudio_driver.h"
#include <xaudio2.h>
#include <cpu/guest_thread.h>
#include <cpu/ppc_context.h>
#include <kernel/heap.h>
#define XAUDIO_DRIVER_KEY (uint32_t)('XAUD')
PPCFunc* volatile g_clientCallback{};
DWORD g_clientCallbackParam{}; // pointer in guest memory
DWORD g_driverThread{};
// TODO: Should use a counted ptr
IXAudio2* g_audio{};
IXAudio2MasteringVoice* g_masteringVoice{};
IXAudio2SourceVoice* g_sourceVoice{};
constexpr uint32_t g_semaphoreCount = 16;
constexpr uint32_t g_audioFrameSize = 256 * 6;
HANDLE g_audioSemaphore{ CreateSemaphoreA(nullptr, g_semaphoreCount, g_semaphoreCount, nullptr) };
uint32_t g_audioFrames[g_audioFrameSize * g_semaphoreCount];
uint32_t g_audioFrameIndex = 0;
class VoiceCallback : public IXAudio2VoiceCallback
{
STDMETHOD_(void, OnVoiceProcessingPassStart)(UINT32 BytesRequired) override {}
STDMETHOD_(void, OnVoiceProcessingPassEnd)() override {}
STDMETHOD_(void, OnBufferStart)(void* pBufferContext) override {}
STDMETHOD_(void, OnBufferEnd)(void* pBufferContext) override
{
ReleaseSemaphore(g_audioSemaphore, 1, nullptr);
}
STDMETHOD_(void, OnStreamEnd)() override {}
STDMETHOD_(void, OnLoopEnd)(void* pBufferContext) override {}
STDMETHOD_(void, OnVoiceError)(void* pBufferContext, HRESULT Error) override {}
} gVoiceCallback;
PPC_FUNC(DriverLoop)
{
GuestThread::SetThreadName(GetCurrentThreadId(), "Audio Driver");
while (true)
{
if (!g_clientCallback)
{
continue;
}
WaitForSingleObject(g_audioSemaphore, INFINITE);
ctx.r3.u64 = g_clientCallbackParam;
g_clientCallback(ctx, g_memory.base);
}
}
void XAudioInitializeSystem()
{
if (g_audio)
{
return;
}
//reinterpret_cast<decltype(&XAudio2Create)>(
// GetProcAddress(LoadLibraryA("XAudio2_8.dll"), "XAudio2Create"))(&gAudio, 0, 1);
XAudio2Create(&g_audio);
g_audio->CreateMasteringVoice(&g_masteringVoice);
WAVEFORMATIEEEFLOATEX format{};
format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
format.Format.cbSize = sizeof(format) - sizeof(format.Format);
format.Format.nChannels = XAUDIO_NUM_CHANNELS;
format.Format.nSamplesPerSec = XAUDIO_SAMPLES_HZ;
format.Format.wBitsPerSample = XAUDIO_SAMPLE_BITS;
format.Format.nBlockAlign = (format.Format.nChannels * format.Format.wBitsPerSample) / 8;
format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec * format.Format.nBlockAlign;
format.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
format.Samples.wValidBitsPerSample = format.Format.wBitsPerSample;
format.dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_CENTER | SPEAKER_FRONT_RIGHT |
SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT;
g_audio->CreateSourceVoice(&g_sourceVoice, &format.Format, 0, 1024, &gVoiceCallback);
g_sourceVoice->Start();
KeInsertHostFunction(XAUDIO_DRIVER_KEY, DriverLoop);
GuestThread::Start({ XAUDIO_DRIVER_KEY, 0, 0 }, nullptr);
}
void XAudioRegisterClient(PPCFunc* callback, uint32_t param)
{
auto* pClientParam = static_cast<uint32_t*>(g_userHeap.Alloc(sizeof(param)));
ByteSwapInplace(param);
*pClientParam = param;
g_clientCallbackParam = g_memory.MapVirtual(pClientParam);
g_clientCallback = callback;
}
void XAudioSubmitFrame(void* samples)
{
uint32_t* audioFrame = &g_audioFrames[g_audioFrameSize * g_audioFrameIndex];
g_audioFrameIndex = (g_audioFrameIndex + 1) % g_semaphoreCount;
for (size_t i = 0; i < XAUDIO_NUM_SAMPLES; i++)
{
for (size_t j = 0; j < 6; j++)
audioFrame[i * XAUDIO_NUM_CHANNELS + j] = ByteSwap(((uint32_t*)samples)[j * XAUDIO_NUM_SAMPLES + i]);
}
XAUDIO2_BUFFER buffer{};
buffer.pAudioData = (BYTE*)audioFrame;
buffer.AudioBytes = XAUDIO_NUM_SAMPLES * XAUDIO_NUM_CHANNELS * sizeof(float);
buffer.PlayLength = XAUDIO_NUM_SAMPLES;
g_sourceVoice->SubmitSourceBuffer(&buffer);
}

View File

@@ -0,0 +1,2 @@
#pragma once
#include <apu/audio.h>

View File

@@ -22,7 +22,6 @@ enum class ImGuiCallback : int32_t
SetOutline = -6,
SetProceduralOrigin = -7,
// -8 is ImDrawCallback_ResetRenderState, don't use!
SetAdditive = -9
};
union ImGuiCallbackData
@@ -65,11 +64,6 @@ union ImGuiCallbackData
{
float proceduralOrigin[2];
} setProceduralOrigin;
struct
{
bool enabled;
} setAdditive;
};
extern ImGuiCallbackData* AddImGuiCallback(ImGuiCallback callback);

View File

@@ -1127,7 +1127,7 @@ namespace plume {
desc.srcBlend = RenderBlend::SRC_ALPHA;
desc.dstBlend = RenderBlend::INV_SRC_ALPHA;
desc.blendOp = RenderBlendOperation::ADD;
desc.srcBlendAlpha = RenderBlend::SRC_ALPHA;
desc.srcBlendAlpha = RenderBlend::ONE;
desc.dstBlendAlpha = RenderBlend::INV_SRC_ALPHA;
desc.blendOpAlpha = RenderBlendOperation::ADD;
return desc;
@@ -1269,9 +1269,9 @@ namespace plume {
RenderFilter minFilter = RenderFilter::LINEAR;
RenderFilter magFilter = RenderFilter::LINEAR;
RenderMipmapMode mipmapMode = RenderMipmapMode::LINEAR;
RenderTextureAddressMode addressU = RenderTextureAddressMode::CLAMP;
RenderTextureAddressMode addressV = RenderTextureAddressMode::CLAMP;
RenderTextureAddressMode addressW = RenderTextureAddressMode::CLAMP;
RenderTextureAddressMode addressU = RenderTextureAddressMode::WRAP;
RenderTextureAddressMode addressV = RenderTextureAddressMode::WRAP;
RenderTextureAddressMode addressW = RenderTextureAddressMode::WRAP;
float mipLODBias = 0.0f;
uint32_t maxAnisotropy = 16;
bool anisotropyEnabled = false;

View File

@@ -1,4 +1,4 @@
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
#include "../../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
#ifdef __spirv__

View File

@@ -1,4 +1,4 @@
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
#include "../../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
#ifdef __spirv__

View File

@@ -1,4 +1,4 @@
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
#include "../../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
#ifdef __spirv__

View File

@@ -1,4 +1,4 @@
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
#include "../../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
#ifdef __spirv__

View File

@@ -1,4 +1,4 @@
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
#include "../../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
#ifdef __spirv__

View File

@@ -1,4 +1,4 @@
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
#include "../../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
#ifdef __spirv__

View File

@@ -1,6 +1,6 @@
#pragma once
#include "../../../tools/XenosRecomp/XenosRecomp/shader_common.h"
#include "../../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
#ifdef __spirv__

View File

@@ -10,13 +10,14 @@
#include <decompressor.h>
#include <kernel/function.h>
#include <kernel/heap.h>
#include <hid/hid.h>
#include <hid/hid_detail.h>
#include <kernel/memory.h>
#include <kernel/xdbf.h>
#include <res/bc_diff/button_bc_diff.bin.h>
#include <res/font/im_font_atlas.dds.h>
#include <shader/shader_cache.h>
#include <SWA.h>
#include <ui/reddog/reddog_manager.h>
#include <ui/achievement_menu.h>
#include <ui/achievement_overlay.h>
#include <ui/button_guide.h>
@@ -26,6 +27,7 @@
#include <ui/options_menu.h>
#include <ui/sdl_listener.h>
#include <ui/game_window.h>
#include <ui/imgui_utils.h>
#include <patches/aspect_ratio_patches.h>
#include <user/config.h>
#include <xxHashMap.h>
@@ -34,9 +36,9 @@
#include <magic_enum/magic_enum.hpp>
#endif
#include "../../tools/XenosRecomp/XenosRecomp/shader_common.h"
#include "../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
#ifdef UNLEASHED_RECOMP_D3D12
#ifdef SWA_D3D12
#include "shader/copy_vs.hlsl.dxil.h"
#include "shader/csd_filter_ps.hlsl.dxil.h"
#include "shader/csd_no_tex_vs.hlsl.dxil.h"
@@ -84,7 +86,7 @@ extern "C"
namespace plume
{
#ifdef UNLEASHED_RECOMP_D3D12
#ifdef SWA_D3D12
extern std::unique_ptr<RenderInterface> CreateD3D12Interface();
#endif
#ifdef SDL_VULKAN_ENABLED
@@ -198,7 +200,7 @@ static void SetDirtyValue(bool& dirtyState, T& dest, const T& src)
}
}
#ifdef UNLEASHED_RECOMP_D3D12
#ifdef SWA_D3D12
static bool g_vulkan = false;
#else
static constexpr bool g_vulkan = true;
@@ -619,7 +621,7 @@ static void LoadEmbeddedResources()
g_shaderCache = std::make_unique<uint8_t[]>(g_spirvCacheDecompressedSize);
ZSTD_decompress(g_shaderCache.get(), g_spirvCacheDecompressedSize, g_compressedSpirvCache, g_spirvCacheCompressedSize);
}
#ifdef UNLEASHED_RECOMP_D3D12
#ifdef SWA_D3D12
else
{
g_shaderCache = std::make_unique<uint8_t[]>(g_dxilCacheDecompressedSize);
@@ -1111,7 +1113,7 @@ static GuestShader* g_csdShader;
static std::unique_ptr<GuestShader> g_enhancedMotionBlurShader;
#ifdef UNLEASHED_RECOMP_D3D12
#ifdef SWA_D3D12
#define CREATE_SHADER(NAME) \
g_device->createShader( \
@@ -1123,7 +1125,7 @@ static std::unique_ptr<GuestShader> g_enhancedMotionBlurShader;
#else
#define CREATE_SHADER(NAME) \
g_device->createShader(g_##NAME##_spirv, sizeof(g_##NAME##_spirv), "main", RenderShaderFormat::SPIRV)
g_device->createShader(g_##NAME##_spirv, sizeof(g_##NAME##_spirv), "main", RenderShaderFormat::SPIRV);
#endif
@@ -1141,7 +1143,6 @@ static constexpr size_t SAMPLER_DESCRIPTOR_SIZE = 1024;
static std::unique_ptr<GuestTexture> g_imFontTexture;
static std::unique_ptr<RenderPipelineLayout> g_imPipelineLayout;
static std::unique_ptr<RenderPipeline> g_imPipeline;
static std::unique_ptr<RenderPipeline> g_imAdditivePipeline;
template<typename T>
static void ExecuteCopyCommandList(const T& function)
@@ -1193,9 +1194,16 @@ static void CreateImGuiBackend()
AchievementMenu::Init();
AchievementOverlay::Init();
ButtonGuide::Init();
InstallerWizard::Init();
MessageWindow::Init();
OptionsMenu::Init();
InstallerWizard::Init();
#if !_DEBUG
if (Config::Debug)
#endif
{
Reddog::Manager::Init();
}
ImGui_ImplSDL2_InitForOther(GameWindow::s_pWindow);
@@ -1310,9 +1318,6 @@ static void CreateImGuiBackend()
pipelineDesc.inputSlotsCount = 1;
g_imPipeline = g_device->createGraphicsPipeline(pipelineDesc);
pipelineDesc.renderTargetBlend[0].dstBlend = RenderBlend::ONE;
g_imAdditivePipeline = g_device->createGraphicsPipeline(pipelineDesc);
#ifndef ENABLE_IM_FONT_ATLAS_SNAPSHOT
ImFontAtlasSnapshot snapshot;
snapshot.Snap();
@@ -1359,8 +1364,16 @@ static void CheckSwapChain()
if (g_needsResize)
Video::ComputeViewportDimensions();
g_backBuffer->width = Video::s_viewportWidth;
g_backBuffer->height = Video::s_viewportHeight;
if (g_aspectRatio >= NARROW_ASPECT_RATIO)
{
g_backBuffer->width = Video::s_viewportWidth * 720 / Video::s_viewportHeight;
g_backBuffer->height = 720;
}
else
{
g_backBuffer->width = 960;
g_backBuffer->height = Video::s_viewportHeight * 960 / Video::s_viewportWidth;
}
}
static void BeginCommandList()
@@ -1444,7 +1457,7 @@ void Video::CreateHostDevice(const char *sdlVideoDriver)
GameWindow::Init(sdlVideoDriver);
#ifdef UNLEASHED_RECOMP_D3D12
#ifdef SWA_D3D12
g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan;
#endif
@@ -1456,7 +1469,7 @@ void Video::CreateHostDevice(const char *sdlVideoDriver)
#else
g_interface = CreateVulkanInterface();
#endif
#ifdef UNLEASHED_RECOMP_D3D12
#ifdef SWA_D3D12
else
g_interface = CreateD3D12Interface();
#endif
@@ -1961,82 +1974,77 @@ static double g_applicationValues[PROFILER_VALUE_COUNT];
static Profiler g_presentProfiler;
static Profiler g_renderDirectorProfiler;
static bool g_profilerVisible;
static bool g_profilerWasToggled;
static void DrawProfiler()
void Video::DrawCounter()
{
bool toggleProfiler = SDL_GetKeyboardState(nullptr)[SDL_SCANCODE_F1] != 0;
g_applicationValues[g_profilerValueIndex] = App::s_deltaTime * 1000.0;
if (!g_profilerWasToggled && toggleProfiler)
g_profilerVisible = !g_profilerVisible;
const double applicationAvg = std::accumulate(g_applicationValues, g_applicationValues + PROFILER_VALUE_COUNT, 0.0) / PROFILER_VALUE_COUNT;
double presentAvg = g_presentProfiler.UpdateAndReturnAverage();
double renderDirectorAvg = g_renderDirectorProfiler.UpdateAndReturnAverage();
g_profilerWasToggled = toggleProfiler;
if (ImPlot::BeginPlot("Frame Time"))
{
ImPlot::SetupAxisLimits(ImAxis_Y1, 0.0, 20.0);
ImPlot::SetupAxis(ImAxis_Y1, "ms", ImPlotAxisFlags_None);
ImPlot::PlotLine<double>("Application", g_applicationValues, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
ImPlot::PlotLine<double>("Present", g_presentProfiler.values, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
ImPlot::PlotLine<double>("Render Director", g_renderDirectorProfiler.values, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
ImPlot::EndPlot();
}
if (!g_profilerVisible)
g_profilerValueIndex = (g_profilerValueIndex + 1) % PROFILER_VALUE_COUNT;
ImGui::Text("Current Application: %g ms (%g FPS)", App::s_deltaTime * 1000.0, 1.0 / App::s_deltaTime);
ImGui::Text("Current Present: %g ms (%g FPS)", g_presentProfiler.value.load(), 1000.0 / g_presentProfiler.value.load());
ImGui::Text("Current Render Director: %g ms (%g FPS)", g_renderDirectorProfiler.value.load(), 1000.0 / g_renderDirectorProfiler.value.load());
ImGui::NewLine();
ImGui::Text("Average Application: %g ms (%g FPS)", applicationAvg, 1000.0 / applicationAvg);
ImGui::Text("Average Present: %g ms (%g FPS)", presentAvg, 1000.0 / presentAvg);
ImGui::Text("Average Render Director: %g ms (%g FPS)", renderDirectorAvg, 1000.0 / renderDirectorAvg);
ImGui::NewLine();
O1HeapDiagnostics diagnostics, physicalDiagnostics;
{
std::lock_guard lock(g_userHeap.mutex);
diagnostics = o1heapGetDiagnostics(g_userHeap.heap);
}
{
std::lock_guard lock(g_userHeap.physicalMutex);
physicalDiagnostics = o1heapGetDiagnostics(g_userHeap.physicalHeap);
}
ImGui::Text("Heap Allocated: %d MB", int32_t(diagnostics.allocated / (1024 * 1024)));
ImGui::Text("Physical Heap Allocated: %d MB", int32_t(physicalDiagnostics.allocated / (1024 * 1024)));
ImGui::NewLine();
auto capabilities = g_device->getCapabilities();
ImGui::Text("Present Wait: %s", capabilities.presentWait ? "Supported" : "Unsupported");
ImGui::Text("Triangle Fan: %s", capabilities.triangleFan ? "Supported" : "Unsupported");
ImGui::NewLine();
const char* sdlVideoDriver = SDL_GetCurrentVideoDriver();
if (sdlVideoDriver != nullptr)
ImGui::Text("SDL Video Driver: %s", sdlVideoDriver);
}
void Video::DrawFPS(ImFont* font)
{
if (!Config::ShowFPS)
return;
ImFont* font = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
float defaultScale = font->Scale;
font->Scale = ImGui::GetDefaultFont()->FontSize / font->FontSize;
ImGui::PushFont(font);
auto drawList = ImGui::GetBackgroundDrawList();
if (ImGui::Begin("Profiler", &g_profilerVisible))
{
g_applicationValues[g_profilerValueIndex] = App::s_deltaTime * 1000.0;
auto fmt = fmt::format("FPS: {:.2f}", 1000.0 / g_presentProfiler.value.load());
auto fontSize = Scale(12.0f);
auto textSize = font->CalcTextSizeA(fontSize, FLT_MAX, 0, fmt.c_str());
const double applicationAvg = std::accumulate(g_applicationValues, g_applicationValues + PROFILER_VALUE_COUNT, 0.0) / PROFILER_VALUE_COUNT;
double presentAvg = g_presentProfiler.UpdateAndReturnAverage();
double renderDirectorAvg = g_renderDirectorProfiler.UpdateAndReturnAverage();
ImVec2 min = { Scale(40), Scale(30) };
ImVec2 max = { min.x + std::max(Scale(75), textSize.x + Scale(10)), min.y + Scale(15) };
ImVec2 textPos = { min.x + Scale(2), CENTRE_TEXT_VERT(min, max, textSize) - Scale(0.5f) };
if (ImPlot::BeginPlot("Frame Time"))
{
ImPlot::SetupAxisLimits(ImAxis_Y1, 0.0, 20.0);
ImPlot::SetupAxis(ImAxis_Y1, "ms", ImPlotAxisFlags_None);
ImPlot::PlotLine<double>("Application", g_applicationValues, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
ImPlot::PlotLine<double>("Present", g_presentProfiler.values, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
ImPlot::PlotLine<double>("Render Director", g_renderDirectorProfiler.values, PROFILER_VALUE_COUNT, 1.0, 0.0, ImPlotLineFlags_None, g_profilerValueIndex);
ImPlot::EndPlot();
}
g_profilerValueIndex = (g_profilerValueIndex + 1) % PROFILER_VALUE_COUNT;
ImGui::Text("Current Application: %g ms (%g FPS)", App::s_deltaTime * 1000.0, 1.0 / App::s_deltaTime);
ImGui::Text("Current Present: %g ms (%g FPS)", g_presentProfiler.value.load(), 1000.0 / g_presentProfiler.value.load());
ImGui::Text("Current Render Director: %g ms (%g FPS)", g_renderDirectorProfiler.value.load(), 1000.0 / g_renderDirectorProfiler.value.load());
ImGui::NewLine();
ImGui::Text("Average Application: %g ms (%g FPS)", applicationAvg, 1000.0 / applicationAvg);
ImGui::Text("Average Present: %g ms (%g FPS)", presentAvg, 1000.0 / presentAvg);
ImGui::Text("Average Render Director: %g ms (%g FPS)", renderDirectorAvg, 1000.0 / renderDirectorAvg);
ImGui::NewLine();
O1HeapDiagnostics diagnostics, physicalDiagnostics;
{
std::lock_guard lock(g_userHeap.mutex);
diagnostics = o1heapGetDiagnostics(g_userHeap.heap);
}
{
std::lock_guard lock(g_userHeap.physicalMutex);
physicalDiagnostics = o1heapGetDiagnostics(g_userHeap.physicalHeap);
}
ImGui::Text("Heap Allocated: %d MB", int32_t(diagnostics.allocated / (1024 * 1024)));
ImGui::Text("Physical Heap Allocated: %d MB", int32_t(physicalDiagnostics.allocated / (1024 * 1024)));
ImGui::NewLine();
ImGui::Text("Present Wait: %s", g_capabilities.presentWait ? "Supported" : "Unsupported");
ImGui::Text("Triangle Fan: %s", g_capabilities.triangleFan ? "Supported" : "Unsupported");
ImGui::NewLine();
const char* sdlVideoDriver = SDL_GetCurrentVideoDriver();
if (sdlVideoDriver != nullptr)
ImGui::Text("SDL Video Driver: %s", sdlVideoDriver);
}
ImGui::End();
ImGui::PopFont();
font->Scale = defaultScale;
drawList->AddRectFilled(min, max, IM_COL32(0, 0, 0, 255));
drawList->AddText(font, fontSize, textPos, IM_COL32_WHITE, fmt.c_str());
}
static void DrawImGui()
@@ -2072,7 +2080,12 @@ static void DrawImGui()
ButtonGuide::Draw();
Fader::Draw();
DrawProfiler();
#if !_DEBUG
if (Config::Debug)
#endif
{
Reddog::Manager::Draw();
}
ImGui::Render();
@@ -2095,10 +2108,9 @@ static void ProcDrawImGui(const RenderCommand& cmd)
SetFramebuffer(g_backBuffer, nullptr, false);
auto& commandList = g_commandLists[g_frame];
auto pipeline = g_imPipeline.get();
commandList->setGraphicsPipelineLayout(g_imPipelineLayout.get());
commandList->setPipeline(pipeline);
commandList->setPipeline(g_imPipeline.get());
commandList->setGraphicsDescriptorSet(g_textureDescriptorSet.get(), 0);
commandList->setGraphicsDescriptorSet(g_samplerDescriptorSet.get(), 1);
@@ -2172,16 +2184,6 @@ static void ProcDrawImGui(const RenderCommand& cmd)
case ImGuiCallback::SetProceduralOrigin:
setPushConstants(&pushConstants.proceduralOrigin, &callbackData->setProceduralOrigin, sizeof(callbackData->setProceduralOrigin));
break;
case ImGuiCallback::SetAdditive:
{
auto pipelineToSet = callbackData->setAdditive.enabled ? g_imAdditivePipeline.get() : g_imPipeline.get();
if (pipeline != pipelineToSet)
{
commandList->setPipeline(pipelineToSet);
pipeline = pipelineToSet;
}
break;
}
default:
assert(false && "Unknown ImGui callback type.");
break;
@@ -2463,6 +2465,11 @@ static GuestSurface* GetBackBuffer()
return g_backBuffer;
}
GuestSurface* Video::GetBackBuffer()
{
return g_backBuffer;
}
void Video::ComputeViewportDimensions()
{
uint32_t width = g_swapChain->getWidth();
@@ -2665,6 +2672,9 @@ static GuestSurface* CreateSurface(uint32_t width, uint32_t height, uint32_t for
static void FlushViewport()
{
bool renderingToBackBuffer = g_renderTarget == g_backBuffer &&
g_backBuffer->texture != g_backBuffer->textureHolder.get();
auto& commandList = g_commandLists[g_frame];
if (g_dirtyStates.viewport)
@@ -2676,6 +2686,17 @@ static void FlushViewport()
viewport.y += 0.5f;
}
if (renderingToBackBuffer)
{
float width = Video::s_viewportWidth;
float height = Video::s_viewportHeight;
viewport.x *= width / g_backBuffer->width;
viewport.y *= height / g_backBuffer->height;
viewport.width *= width / g_backBuffer->width;
viewport.height *= height / g_backBuffer->height;
}
if (viewport.minDepth > viewport.maxDepth)
std::swap(viewport.minDepth, viewport.maxDepth);
@@ -2692,6 +2713,17 @@ static void FlushViewport()
g_viewport.x + g_viewport.width,
g_viewport.y + g_viewport.height);
if (renderingToBackBuffer)
{
uint32_t width = Video::s_viewportWidth;
uint32_t height = Video::s_viewportHeight;
scissorRect.left = scissorRect.left * width / g_backBuffer->width;
scissorRect.top = scissorRect.top * height / g_backBuffer->height;
scissorRect.right = scissorRect.right * width / g_backBuffer->width;
scissorRect.bottom = scissorRect.bottom * height / g_backBuffer->height;
}
commandList->setScissors(scissorRect);
g_dirtyStates.scissorRect = false;
@@ -2795,10 +2827,7 @@ static void ProcStretchRect(const RenderCommand& cmd)
g_dirtyStates.pipelineState = true;
if (g_vulkan)
{
g_dirtyStates.depthBias = true; // Static depth bias in MSAA pipeline invalidates dynamic depth bias.
g_dirtyStates.vertexShaderConstants = true;
}
SetHalfPixel(oldHalfPixel);
}
@@ -3032,7 +3061,7 @@ static void SetTexture(GuestDevice* device, uint32_t index, GuestTexture* textur
auto isPlayStation = Config::ControllerIcons == EControllerIcons::PlayStation;
if (Config::ControllerIcons == EControllerIcons::Auto)
isPlayStation = hid::g_inputDeviceController == hid::EInputDevice::PlayStation;
isPlayStation = hid::detail::g_inputDeviceController == hid::detail::EInputDevice::PlayStation;
if (isPlayStation && texture != nullptr && texture->patchedTexture != nullptr)
texture = texture->patchedTexture.get();
@@ -3123,7 +3152,7 @@ static RenderShader* GetOrLinkShader(GuestShader* guestShader, uint32_t specCons
shader = guestShader->linkedShaders[specConstants].get();
}
#ifdef UNLEASHED_RECOMP_D3D12
#ifdef SWA_D3D12
if (shader == nullptr)
{
static Mutex g_compiledSpecConstantLibraryBlobMutex;
@@ -3375,7 +3404,7 @@ static RenderPipeline* CreateGraphicsPipelineInRenderThread(PipelineState pipeli
pipeline = CreateGraphicsPipeline(pipelineState);
#ifdef ASYNC_PSO_DEBUG
bool loading = *reinterpret_cast<bool*>(g_memory.Translate(0x83367A4C));
bool loading = *SWA::SGlobals::ms_IsLoading;
if (loading)
++g_pipelinesCreatedAsynchronously;
@@ -4367,33 +4396,16 @@ static void ProcSetPixelShader(const RenderCommand& cmd)
default:
{
if (g_aspectRatio >= WIDE_ASPECT_RATIO)
{
size_t height = round(Video::s_viewportHeight * Config::ResolutionScale);
size_t height = round(Video::s_viewportHeight * Config::ResolutionScale);
if (height > 1440)
shaderIndex = GAUSSIAN_BLUR_9X9;
else if (height > 1080)
shaderIndex = GAUSSIAN_BLUR_7X7;
else if (height > 720)
shaderIndex = GAUSSIAN_BLUR_5X5;
else
shaderIndex = GAUSSIAN_BLUR_3X3;
}
if (height > 1440)
shaderIndex = GAUSSIAN_BLUR_9X9;
else if (height > 1080)
shaderIndex = GAUSSIAN_BLUR_7X7;
else if (height > 720)
shaderIndex = GAUSSIAN_BLUR_5X5;
else
{
// Narrow aspect ratios should check for width to account for VERT+.
size_t width = round(Video::s_viewportWidth * Config::ResolutionScale);
if (width > 2560)
shaderIndex = GAUSSIAN_BLUR_9X9;
else if (width > 1920)
shaderIndex = GAUSSIAN_BLUR_7X7;
else if (width > 1280)
shaderIndex = GAUSSIAN_BLUR_5X5;
else
shaderIndex = GAUSSIAN_BLUR_3X3;
}
shaderIndex = GAUSSIAN_BLUR_3X3;
break;
}
@@ -5121,40 +5133,23 @@ PPC_FUNC(sub_8258CAE0)
g_renderDirectorProfiler.End();
}
// World map disables VERT+, so scaling by width does not work for it.
static uint32_t g_forceCheckHeightForPostProcessFix;
// SWA::CWorldMapCamera::CWorldMapCamera
PPC_FUNC_IMPL(__imp__sub_824860E0);
PPC_FUNC(sub_824860E0)
{
++g_forceCheckHeightForPostProcessFix;
__imp__sub_824860E0(ctx, base);
}
// SWA::CCameraController::~CCameraController
PPC_FUNC_IMPL(__imp__sub_824831D0);
PPC_FUNC(sub_824831D0)
{
if (PPC_LOAD_U32(ctx.r3.u32) == 0x8202BF1C) // SWA::CWorldMapCamera
--g_forceCheckHeightForPostProcessFix;
__imp__sub_824831D0(ctx, base);
}
void PostProcessResolutionFix(PPCRegister& r4, PPCRegister& f1, PPCRegister& f2)
{
auto device = reinterpret_cast<be<uint32_t>*>(g_memory.Translate(r4.u32));
uint32_t width = device[46].get();
uint32_t height = device[47].get();
double aspectRatio = double(width) / double(height);
#if 0
// TODO: Figure out why this breaks for height > weight
double factor;
if ((aspectRatio >= WIDE_ASPECT_RATIO) || (g_forceCheckHeightForPostProcessFix != 0))
if (width > height)
factor = 720.0 / double(height);
else
factor = 1280.0 / double(width);
#else
double factor = 720.0 / double(height);
#endif
f1.f64 *= factor;
f2.f64 *= factor;

View File

@@ -23,6 +23,9 @@ struct Video
static void Present();
static void StartPipelinePrecompilation();
static void WaitForGPU();
static void DrawCounter();
static void DrawFPS(ImFont* font);
static struct GuestSurface* GetBackBuffer();
static void ComputeViewportDimensions();
};
@@ -285,7 +288,7 @@ struct GuestShader : GuestResource
std::unique_ptr<RenderShader> shader;
struct ShaderCacheEntry* shaderCacheEntry = nullptr;
ankerl::unordered_dense::map<uint32_t, std::unique_ptr<RenderShader>> linkedShaders;
#ifdef UNLEASHED_RECOMP_D3D12
#ifdef SWA_D3D12
std::vector<ComPtr<IDxcBlob>> shaderBlobs;
ComPtr<IDxcBlobEncoding> libraryBlob;
#endif

View File

@@ -1,8 +1,7 @@
#include <stdafx.h>
#include <SDL.h>
#include <user/config.h>
#include <hid/hid.h>
#include <os/logger.h>
#include <hid/hid_detail.h>
#include <ui/game_window.h>
#include <kernel/xdm.h>
#include <app.h>
@@ -41,17 +40,17 @@ public:
return SDL_GameControllerTypeForIndex(index);
}
hid::EInputDevice GetInputDevice() const
hid::detail::EInputDevice GetInputDevice() const
{
switch (GetControllerType())
{
case SDL_CONTROLLER_TYPE_PS3:
case SDL_CONTROLLER_TYPE_PS4:
case SDL_CONTROLLER_TYPE_PS5:
return hid::EInputDevice::PlayStation;
return hid::detail::EInputDevice::PlayStation;
}
return hid::EInputDevice::Xbox;
return hid::detail::EInputDevice::Xbox;
}
void Close()
@@ -169,17 +168,8 @@ static void SetControllerInputDevice(Controller* controller)
if (App::s_isLoading)
return;
hid::g_inputDevice = controller->GetInputDevice();
hid::g_inputDeviceController = hid::g_inputDevice;
auto controllerType = (hid::EInputDeviceExplicit)controller->GetControllerType();
if (hid::g_inputDeviceExplicit != controllerType)
{
hid::g_inputDeviceExplicit = controllerType;
LOGFN("Detected controller: {}", hid::GetInputDeviceName());
}
hid::detail::g_inputDevice = controller->GetInputDevice();
hid::detail::g_inputDeviceController = hid::detail::g_inputDevice;
}
int HID_OnSDLEvent(void*, SDL_Event* event)
@@ -209,7 +199,6 @@ int HID_OnSDLEvent(void*, SDL_Event* event)
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
case SDL_CONTROLLERAXISMOTION:
case SDL_CONTROLLERTOUCHPADDOWN:
{
auto* controller = FindController(event->cdevice.which);
@@ -235,13 +224,13 @@ int HID_OnSDLEvent(void*, SDL_Event* event)
case SDL_KEYDOWN:
case SDL_KEYUP:
hid::g_inputDevice = hid::EInputDevice::Keyboard;
hid::detail::g_inputDevice = hid::detail::EInputDevice::Keyboard;
break;
case SDL_MOUSEMOTION:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
hid::g_inputDevice = hid::EInputDevice::Mouse;
hid::detail::g_inputDevice = hid::detail::EInputDevice::Mouse;
break;
case SDL_WINDOWEVENT:
@@ -277,7 +266,7 @@ int HID_OnSDLEvent(void*, SDL_Event* event)
return 0;
}
void hid::Init()
void hid::detail::Init()
{
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS3, "1");
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1");
@@ -293,7 +282,7 @@ void hid::Init()
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
}
uint32_t hid::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState)
uint32_t hid::detail::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState)
{
static uint32_t packet;
@@ -312,7 +301,7 @@ uint32_t hid::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState)
return ERROR_SUCCESS;
}
uint32_t hid::SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration)
uint32_t hid::detail::SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration)
{
if (!pVibration)
return ERROR_BAD_ARGUMENTS;
@@ -325,7 +314,7 @@ uint32_t hid::SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration)
return ERROR_SUCCESS;
}
uint32_t hid::GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps)
uint32_t hid::detail::GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps)
{
if (!pCaps)
return ERROR_BAD_ARGUMENTS;

View File

@@ -1,74 +1,39 @@
#include <stdafx.h>
#include "hid.h"
#include "hid_detail.h"
hid::EInputDevice hid::g_inputDevice;
hid::EInputDevice hid::g_inputDeviceController;
hid::EInputDeviceExplicit hid::g_inputDeviceExplicit;
hid::detail::EInputDevice hid::detail::g_inputDevice;
hid::detail::EInputDevice hid::detail::g_inputDeviceController;
uint16_t hid::g_prohibitedButtons;
uint16_t hid::detail::g_prohibitedButtons;
void hid::Init()
{
detail::Init();
}
void hid::SetProhibitedButtons(uint16_t wButtons)
{
hid::g_prohibitedButtons = wButtons;
hid::detail::g_prohibitedButtons = wButtons;
}
bool hid::IsInputDeviceController()
uint32_t hid::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState)
{
return hid::g_inputDevice != hid::EInputDevice::Keyboard &&
hid::g_inputDevice != hid::EInputDevice::Mouse;
return detail::GetState(dwUserIndex, pState);
}
std::string hid::GetInputDeviceName()
uint32_t hid::SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration)
{
switch (g_inputDevice)
{
case EInputDevice::Keyboard:
return "Keyboard";
case EInputDevice::Mouse:
return "Mouse";
}
switch (g_inputDeviceExplicit)
{
case EInputDeviceExplicit::Xbox360:
return "Xbox 360";
case EInputDeviceExplicit::XboxOne:
return "Xbox One";
case EInputDeviceExplicit::DualShock3:
return "DualShock 3";
case EInputDeviceExplicit::DualShock4:
return "DualShock 4";
case EInputDeviceExplicit::SwitchPro:
return "Nintendo Switch Pro";
case EInputDeviceExplicit::Virtual:
return "Virtual";
case EInputDeviceExplicit::DualSense:
return "DualSense";
case EInputDeviceExplicit::Luna:
return "Amazon Luna";
case EInputDeviceExplicit::Stadia:
return "Google Stadia";
case EInputDeviceExplicit::NvShield:
return "NVIDIA Shield";
case EInputDeviceExplicit::SwitchJCLeft:
return "Nintendo Switch Joy-Con (Left)";
case EInputDeviceExplicit::SwitchJCRight:
return "Nintendo Switch Joy-Con (Right)";
case EInputDeviceExplicit::SwitchJCPair:
return "Nintendo Switch Joy-Con (Pair)";
}
return "Unknown";
return detail::SetState(dwUserIndex, pVibration);
}
uint32_t hid::GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps)
{
return detail::GetCapabilities(dwUserIndex, pCaps);
}
bool hid::detail::IsInputDeviceController()
{
return hid::detail::g_inputDevice != hid::detail::EInputDevice::Keyboard &&
hid::detail::g_inputDevice != hid::detail::EInputDevice::Mouse;
}

View File

@@ -1,46 +1,13 @@
#pragma once
union SDL_Event;
namespace hid
{
enum class EInputDevice
{
Keyboard,
Mouse,
Xbox,
PlayStation
};
enum class EInputDeviceExplicit
{
Unknown,
Xbox360,
XboxOne,
DualShock3,
DualShock4,
SwitchPro,
Virtual,
DualSense,
Luna,
Stadia,
NvShield,
SwitchJCLeft,
SwitchJCRight,
SwitchJCPair
};
extern EInputDevice g_inputDevice;
extern EInputDevice g_inputDeviceController;
extern EInputDeviceExplicit g_inputDeviceExplicit;
extern uint16_t g_prohibitedButtons;
void Init();
void SetProhibitedButtons(uint16_t wButtons);
uint32_t GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState);
uint32_t SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration);
uint32_t GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps);
bool IsInputDeviceController();
std::string GetInputDeviceName();
}

View File

@@ -0,0 +1,25 @@
#pragma once
namespace hid::detail
{
enum class EInputDevice
{
Keyboard,
Mouse,
Xbox,
PlayStation
};
extern EInputDevice g_inputDevice;
extern EInputDevice g_inputDeviceController;
extern uint16_t g_prohibitedButtons;
void Init();
uint32_t GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState);
uint32_t SetState(uint32_t dwUserIndex, XAMINPUT_VIBRATION* pVibration);
uint32_t GetCapabilities(uint32_t dwUserIndex, XAMINPUT_CAPABILITIES* pCaps);
bool IsInputDeviceController();
}

View File

@@ -2,6 +2,7 @@
#include "xam.h"
#include "xdm.h"
#include <hid/hid.h>
#include <hid/hid_detail.h>
#include <ui/game_window.h>
#include <cpu/guest_thread.h>
#include <ranges>
@@ -10,6 +11,12 @@
#include <user/paths.h>
#include <SDL.h>
#ifdef _WIN32
#include <CommCtrl.h>
// Needed for commctrl
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif
struct XamListener : KernelObject
{
uint32_t id{};
@@ -201,15 +208,11 @@ bool XNotifyGetNext(uint32_t hNotification, uint32_t dwMsgFilter, be<uint32_t>*
uint32_t XamShowMessageBoxUI(uint32_t dwUserIndex, be<uint16_t>* wszTitle, be<uint16_t>* wszText, uint32_t cButtons,
xpointer<be<uint16_t>>* pwszButtons, uint32_t dwFocusButton, uint32_t dwFlags, be<uint32_t>* pResult, XXOVERLAPPED* pOverlapped)
{
*pResult = cButtons ? cButtons - 1 : 0;
int button{};
#if _DEBUG
assert("XamShowMessageBoxUI encountered!" && false);
#elif _WIN32
// This code is Win32-only as it'll most likely crash, misbehave or
// cause corruption due to using a different type of memory than what
// wchar_t is on Linux. Windows uses 2 bytes while Linux uses 4 bytes.
#ifdef _WIN32
std::vector<std::wstring> texts{};
std::vector<TASKDIALOG_BUTTON> buttons{};
texts.emplace_back(reinterpret_cast<wchar_t*>(wszTitle));
texts.emplace_back(reinterpret_cast<wchar_t*>(wszText));
@@ -223,27 +226,23 @@ uint32_t XamShowMessageBoxUI(uint32_t dwUserIndex, be<uint16_t>* wszTitle, be<ui
ByteSwapInplace(text[i]);
}
wprintf(L"[XamShowMessageBoxUI] !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
wprintf(L"[XamShowMessageBoxUI] If you are encountering this message and the game has ceased functioning,\n");
wprintf(L"[XamShowMessageBoxUI] please create an issue at https://github.com/hedge-dev/UnleashedRecomp/issues.\n");
wprintf(L"[XamShowMessageBoxUI] !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
wprintf(L"[XamShowMessageBoxUI] %ls\n", texts[0].c_str());
wprintf(L"[XamShowMessageBoxUI] %ls\n", texts[1].c_str());
wprintf(L"[XamShowMessageBoxUI] ");
for (size_t i = 0; i < cButtons; i++)
{
wprintf(L"%ls", texts[2 + i].c_str());
buttons.emplace_back(i, texts[2 + i].c_str());
if (i != cButtons - 1)
wprintf(L" | ");
}
XamNotifyEnqueueEvent(9, 1);
wprintf(L"\n");
wprintf(L"[XamShowMessageBoxUI] Defaulted to button: %d\n", pResult->get());
wprintf(L"[XamShowMessageBoxUI] !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
TASKDIALOGCONFIG config{};
config.cbSize = sizeof(config);
config.pszWindowTitle = texts[0].c_str();
config.pszContent = texts[1].c_str();
config.cButtons = cButtons;
config.pButtons = buttons.data();
TaskDialogIndirect(&config, &button, nullptr, nullptr);
#endif
*pResult = button;
if (pOverlapped)
{
pOverlapped->dwCompletionContext = GuestThread::GetCurrentThreadId();
@@ -454,7 +453,7 @@ uint32_t XamInputGetState(uint32_t userIndex, uint32_t flags, XAMINPUT_STATE* st
state->Gamepad.wButtons |= XAMINPUT_GAMEPAD_Y;
}
state->Gamepad.wButtons &= ~hid::g_prohibitedButtons;
state->Gamepad.wButtons &= ~hid::detail::g_prohibitedButtons;
ByteSwapInplace(state->Gamepad.wButtons);
ByteSwapInplace(state->Gamepad.sThumbLX);
@@ -467,7 +466,7 @@ uint32_t XamInputGetState(uint32_t userIndex, uint32_t flags, XAMINPUT_STATE* st
uint32_t XamInputSetState(uint32_t userIndex, uint32_t flags, XAMINPUT_VIBRATION* vibration)
{
if (!hid::IsInputDeviceController() || !Config::Vibration)
if (!hid::detail::IsInputDeviceController() || !Config::Vibration)
return ERROR_SUCCESS;
ByteSwapInplace(vibration->wLeftMotorSpeed);

View File

@@ -19,10 +19,10 @@
*/
#define CONFIG_DEFINE_LOCALE(name) \
CONFIG_LOCALE g_##name##_locale =
CONFIG_LOCALE Config::g_##name##_locale =
#define CONFIG_DEFINE_ENUM_LOCALE(type) \
CONFIG_ENUM_LOCALE(type) g_##type##_locale =
CONFIG_ENUM_LOCALE(type) Config::g_##type##_locale =
CONFIG_DEFINE_LOCALE(Language)
{
@@ -117,6 +117,11 @@ CONFIG_DEFINE_LOCALE(AllowBackgroundInput)
{ ELanguage::English, { "Allow Background Input", "Allow controller input whilst the game window is unfocused." } }
};
CONFIG_DEFINE_LOCALE(AllowDPadMovement)
{
{ ELanguage::English, { "Allow D-Pad Movement", "Allow the player to also be controlled using the directional pad." } }
};
CONFIG_DEFINE_LOCALE(MasterVolume)
{
{ ELanguage::English, { "Master Volume", "Adjust the overall volume." } }
@@ -137,22 +142,6 @@ CONFIG_DEFINE_LOCALE(MusicAttenuation)
{ ELanguage::English, { "Music Attenuation", "Fade out the game's music when external media is playing." } }
};
CONFIG_DEFINE_LOCALE(ChannelConfiguration)
{
{ ELanguage::English, { "Channel Configuration", "" } }
};
CONFIG_DEFINE_ENUM_LOCALE(EChannelConfiguration)
{
{
ELanguage::English,
{
{ EChannelConfiguration::Stereo, { "STEREO", "" } },
{ EChannelConfiguration::Surround, { "SURROUND", "" } }
}
}
};
CONFIG_DEFINE_LOCALE(VoiceLanguage)
{
{ ELanguage::English, { "Voice Language", "Change the language used for character voices." } }

View File

@@ -342,20 +342,6 @@ std::unordered_map<std::string, std::unordered_map<ELanguage, std::string>> g_lo
{ ELanguage::Italian, "Sei sicuro di voler uscire?" }
}
},
{
// Notes: message appears when the SYS-DATA is corrupted (mismatching file size).
// To make this occur, open the file in any editor and just remove a large chunk of data.
// Do not localise this unless absolutely necessary, these strings are from the XEX.
"Title_Message_SaveDataCorrupt",
{
{ ELanguage::English, "The save file appears to be\ncorrupted and cannot be loaded." },
{ ELanguage::Japanese, "ゲームデータの読み込みに失敗しました。\nこのまま続けるとゲームデータをセーブすることはできません" },
{ ELanguage::German, "Diese Speicherdatei ist beschädigt\nund kann nicht geladen werden." },
{ ELanguage::French, "Le fichier de sauvegarde semble être\nendommagé et ne peut être chargé." },
{ ELanguage::Spanish, "El archivo parece estar dañado\ny no se puede cargar." },
{ ELanguage::Italian, "I file di salvataggio sembrano danneggiati\ne non possono essere caricati." }
}
},
{
"Common_On",
{

View File

@@ -26,6 +26,9 @@ static std::vector<Mod> g_mods;
std::filesystem::path ModLoader::ResolvePath(std::string_view path)
{
if (g_mods.empty())
return {};
std::string_view root;
size_t sepIndex = path.find(":\\");
@@ -48,9 +51,6 @@ std::filesystem::path ModLoader::ResolvePath(std::string_view path)
return {};
}
if (g_mods.empty())
return {};
thread_local xxHashMap<std::filesystem::path> s_cache;
XXH64_hash_t hash = XXH3_64bits(path.data(), path.size());

View File

@@ -1,10 +1,10 @@
#include <os/logger.h>
#include <os/logger_detail.h>
void os::logger::Init()
void os::logger::detail::Init()
{
}
void os::logger::Log(const std::string_view str, ELogType type, const char* func)
void os::logger::detail::Log(const std::string_view str, detail::ELogType type, const char* func)
{
if (func)
{

View File

@@ -1,6 +1,6 @@
#include <os/media.h>
#include <os/media_detail.h>
bool os::media::IsExternalMediaPlaying()
bool os::media::detail::IsExternalMediaPlaying()
{
// This functionality is not supported in Linux.
return false;

View File

@@ -1,8 +1,8 @@
#include <os/process.h>
#include <os/process_detail.h>
#include <signal.h>
std::filesystem::path os::process::GetExecutablePath()
std::filesystem::path os::process::detail::GetExecutablePath()
{
char exePath[PATH_MAX] = {};
if (readlink("/proc/self/exe", exePath, PATH_MAX) > 0)
@@ -15,7 +15,7 @@ std::filesystem::path os::process::GetExecutablePath()
}
}
std::filesystem::path os::process::GetWorkingDirectory()
std::filesystem::path os::process::detail::GetWorkingDirectory()
{
char cwd[PATH_MAX] = {};
char *res = getcwd(cwd, sizeof(cwd));
@@ -29,7 +29,7 @@ std::filesystem::path os::process::GetWorkingDirectory()
}
}
bool os::process::StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work)
bool os::process::detail::StartProcess(const std::filesystem::path path, const std::vector<std::string> args, std::filesystem::path work)
{
pid_t pid = fork();
if (pid < 0)

View File

@@ -1,6 +1,6 @@
#include <os/user.h>
#include <os/user_detail.h>
bool os::user::IsDarkTheme()
bool os::user::detail::IsDarkTheme()
{
return false;
}

View File

@@ -1,7 +1,7 @@
#include <os/version.h>
#include <os/version_detail.h>
os::version::OSVersion os::version::GetOSVersion()
os::version::detail::OSVersion os::version::detail::GetOSVersion()
{
assert(false && "Unimplemented.");
return os::version::OSVersion();
return os::version::detail::OSVersion();
}

View File

@@ -0,0 +1,12 @@
#include <os/logger.h>
#include <os/logger_detail.h>
void os::logger::Init()
{
detail::Init();
}
void os::logger::Log(const std::string_view str, detail::ELogType type, const char* func)
{
detail::Log(str, type, func);
}

View File

@@ -1,9 +1,9 @@
#pragma once
#include <source_location>
#include <os/logger_detail.h>
#define LOG_IMPL(type, func, str) os::logger::Log(str, os::logger::ELogType::type, func)
#define LOGF_IMPL(type, func, str, ...) os::logger::Log(fmt::format(str, __VA_ARGS__), os::logger::ELogType::type, func)
#define LOG_IMPL(type, func, str) os::logger::Log(str, os::logger::detail::ELogType::type, func)
#define LOGF_IMPL(type, func, str, ...) os::logger::Log(fmt::format(str, __VA_ARGS__), os::logger::detail::ELogType::type, func)
// Function-specific logging.
@@ -51,14 +51,6 @@
namespace os::logger
{
enum class ELogType
{
None,
Utility,
Warning,
Error
};
void Init();
void Log(const std::string_view str, ELogType type = ELogType::None, const char* func = nullptr);
void Log(const std::string_view str, detail::ELogType type = detail::ELogType::None, const char* func = nullptr);
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <source_location>
namespace os::logger::detail
{
enum class ELogType
{
None,
Utility,
Warning,
Error
};
void Init();
void Log(const std::string_view str, ELogType type = ELogType::None, const char* func = nullptr);
}

View File

@@ -0,0 +1,7 @@
#include <os/media.h>
#include <os/media_detail.h>
bool os::media::IsExternalMediaPlaying()
{
return detail::IsExternalMediaPlaying();
}

View File

@@ -0,0 +1,6 @@
#pragma once
namespace os::media::detail
{
bool IsExternalMediaPlaying();
}

View File

@@ -0,0 +1,17 @@
#include <os/process.h>
#include <os/process_detail.h>
std::filesystem::path os::process::GetExecutablePath()
{
return detail::GetExecutablePath();
}
std::filesystem::path os::process::GetWorkingDirectory()
{
return detail::GetWorkingDirectory();
}
bool os::process::StartProcess(const std::filesystem::path path, const std::vector<std::string> args, std::filesystem::path work)
{
return detail::StartProcess(path, args, work);
}

View File

@@ -4,5 +4,5 @@ namespace os::process
{
std::filesystem::path GetExecutablePath();
std::filesystem::path GetWorkingDirectory();
bool StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work = {});
bool StartProcess(const std::filesystem::path path, const std::vector<std::string> args, std::filesystem::path work = {});
}

View File

@@ -0,0 +1,8 @@
#pragma once
namespace os::process::detail
{
std::filesystem::path GetExecutablePath();
std::filesystem::path GetWorkingDirectory();
bool StartProcess(const std::filesystem::path path, const std::vector<std::string> args, std::filesystem::path work = {});
}

View File

@@ -0,0 +1,7 @@
#include <os/user.h>
#include <os/user_detail.h>
bool os::user::IsDarkTheme()
{
return detail::IsDarkTheme();
}

View File

@@ -0,0 +1,6 @@
#pragma once
namespace os::user::detail
{
bool IsDarkTheme();
}

View File

@@ -0,0 +1,7 @@
#include <os/version.h>
#include <os/version_detail.h>
os::version::detail::OSVersion os::version::GetOSVersion()
{
return detail::GetOSVersion();
}

View File

@@ -1,13 +1,8 @@
#pragma once
#include <os/version_detail.h>
namespace os::version
{
struct OSVersion
{
uint32_t Major{};
uint32_t Minor{};
uint32_t Build{};
};
OSVersion GetOSVersion();
detail::OSVersion GetOSVersion();
}

View File

@@ -0,0 +1,13 @@
#pragma once
namespace os::version::detail
{
struct OSVersion
{
uint32_t Major{};
uint32_t Minor{};
uint32_t Build{};
};
OSVersion GetOSVersion();
}

View File

@@ -1,16 +1,17 @@
#include <os/logger.h>
#include <os/logger_detail.h>
#include <print>
#define FOREGROUND_WHITE (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
#define FOREGROUND_YELLOW (FOREGROUND_RED | FOREGROUND_GREEN)
HANDLE g_hStandardOutput;
void os::logger::Init()
void os::logger::detail::Init()
{
g_hStandardOutput = GetStdHandle(STD_OUTPUT_HANDLE);
}
void os::logger::Log(const std::string_view str, ELogType type, const char* func)
void os::logger::detail::Log(const std::string_view str, detail::ELogType type, const char* func)
{
switch (type)
{

View File

@@ -1,4 +1,4 @@
#include <os/media.h>
#include <os/media_detail.h>
#include <os/logger.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Media.Control.h>
@@ -62,7 +62,7 @@ static GlobalSystemMediaTransportControlsSessionPlaybackInfo GetPlaybackInfo()
}
}
bool os::media::IsExternalMediaPlaying()
bool os::media::detail::IsExternalMediaPlaying()
{
auto playbackInfo = GetPlaybackInfo();

View File

@@ -1,6 +1,6 @@
#include <os/process.h>
#include <os/process_detail.h>
std::filesystem::path os::process::GetExecutablePath()
std::filesystem::path os::process::detail::GetExecutablePath()
{
WCHAR exePath[MAX_PATH];
@@ -10,7 +10,7 @@ std::filesystem::path os::process::GetExecutablePath()
return std::filesystem::path(exePath);
}
std::filesystem::path os::process::GetWorkingDirectory()
std::filesystem::path os::process::detail::GetWorkingDirectory()
{
WCHAR workPath[MAX_PATH];
@@ -20,7 +20,7 @@ std::filesystem::path os::process::GetWorkingDirectory()
return std::filesystem::path(workPath);
}
bool os::process::StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work)
bool os::process::detail::StartProcess(const std::filesystem::path path, const std::vector<std::string> args, std::filesystem::path work)
{
if (path.empty())
return false;

View File

@@ -1,6 +1,6 @@
#include <os/user.h>
#include <os/user_detail.h>
bool os::user::IsDarkTheme()
bool os::user::detail::IsDarkTheme()
{
HKEY hKey;

View File

@@ -1,10 +1,10 @@
#include <os/version.h>
#include <os/version_detail.h>
LIB_FUNCTION(LONG, "ntdll.dll", RtlGetVersion, PRTL_OSVERSIONINFOW);
os::version::OSVersion os::version::GetOSVersion()
os::version::detail::OSVersion os::version::detail::GetOSVersion()
{
auto result = os::version::OSVersion{};
auto result = os::version::detail::OSVersion{};
OSVERSIONINFOEXW osvi = { 0 };
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);

View File

@@ -1,14 +0,0 @@
#include <api/SWA.h>
#include <patches/ui/CTitleStateIntro_patches.h>
// SWA::CGameModeStageTitle::Update
PPC_FUNC_IMPL(__imp__sub_825518B8);
PPC_FUNC(sub_825518B8)
{
auto pGameModeStageTitle = (SWA::CGameModeStageTitle*)g_memory.Translate(ctx.r3.u32);
__imp__sub_825518B8(ctx, base);
if (g_quitMessageOpen)
pGameModeStageTitle->m_AdvertiseMovieWaitTime = 0;
}

View File

@@ -185,13 +185,13 @@ void AspectRatioPatches::ComputeOffsets()
float height = Video::s_viewportHeight;
g_aspectRatio = width / height;
g_aspectRatioGameplayScale = 1.0f;
g_aspectRatioScale = 1.0f;
if (g_aspectRatio >= NARROW_ASPECT_RATIO)
{
g_aspectRatioOffsetX = (width - height * WIDE_ASPECT_RATIO) / 2.0f;
// height is locked to 720 in this case
g_aspectRatioOffsetX = 0.5f * (g_aspectRatio * 720.0f - 1280.0f);
g_aspectRatioOffsetY = 0.0f;
g_aspectRatioScale = height / 720.0f;
// keep same scale above Steam Deck aspect ratio
if (g_aspectRatio < WIDE_ASPECT_RATIO)
@@ -201,29 +201,20 @@ void AspectRatioPatches::ComputeOffsets()
float narrowScale = ComputeScale(NARROW_ASPECT_RATIO);
float lerpFactor = std::clamp((g_aspectRatio - NARROW_ASPECT_RATIO) / (STEAM_DECK_ASPECT_RATIO - NARROW_ASPECT_RATIO), 0.0f, 1.0f);
g_aspectRatioGameplayScale = narrowScale + (steamDeckScale - narrowScale) * lerpFactor;
g_aspectRatioScale = narrowScale + (steamDeckScale - narrowScale) * lerpFactor;
}
}
else
{
// 4:3 crop
g_aspectRatioOffsetX = (width - width * NARROW_ASPECT_RATIO) / 2.0f;
g_aspectRatioOffsetY = (height - width / NARROW_ASPECT_RATIO) / 2.0f;
g_aspectRatioScale = width / 960.0f;
g_aspectRatioGameplayScale = ComputeScale(NARROW_ASPECT_RATIO);
// width is locked to 960 in this case to have 4:3 crop
g_aspectRatioOffsetX = 0.5f * (960.0f - 1280.0f);
g_aspectRatioOffsetY = 0.5f * (960.0f / g_aspectRatio - 720.0f);
g_aspectRatioScale = ComputeScale(NARROW_ASPECT_RATIO);
}
g_aspectRatioNarrowScale = std::clamp((g_aspectRatio - NARROW_ASPECT_RATIO) / (WIDE_ASPECT_RATIO - NARROW_ASPECT_RATIO), 0.0f, 1.0f);
g_narrowOffsetScale = std::clamp((g_aspectRatio - NARROW_ASPECT_RATIO) / (WIDE_ASPECT_RATIO - NARROW_ASPECT_RATIO), 0.0f, 1.0f);
}
static void GetViewport(void* application, be<uint32_t>* width, be<uint32_t>* height)
{
*width = 1280;
*height = 720;
}
GUEST_FUNCTION_HOOK(sub_82E169B8, GetViewport);
// SWA::CGameDocument::ComputeScreenPosition
PPC_FUNC_IMPL(__imp__sub_8250FC70);
PPC_FUNC(sub_8250FC70)
@@ -231,15 +222,14 @@ PPC_FUNC(sub_8250FC70)
__imp__sub_8250FC70(ctx, base);
auto position = reinterpret_cast<be<float>*>(base + ctx.r3.u32);
position[0] = (position[0] / 1280.0f * Video::s_viewportWidth - g_aspectRatioOffsetX) / g_aspectRatioScale;
position[1] = (position[1] / 720.0f * Video::s_viewportHeight - g_aspectRatioOffsetY) / g_aspectRatioScale;
position[0] = position[0] - g_aspectRatioOffsetX;
position[1] = position[1] - g_aspectRatioOffsetY;
}
void ComputeScreenPositionMidAsmHook(PPCRegister& f1, PPCRegister& f2)
{
f1.f64 = (f1.f64 / 1280.0 * Video::s_viewportWidth - g_aspectRatioOffsetX) / g_aspectRatioScale;
f2.f64 = (f2.f64 / 720.0 * Video::s_viewportHeight - g_aspectRatioOffsetY) / g_aspectRatioScale;
f1.f64 -= g_aspectRatioOffsetX;
f2.f64 -= g_aspectRatioOffsetY;
}
void WorldMapInfoMidAsmHook(PPCRegister& r4)
@@ -268,11 +258,11 @@ PPC_FUNC(sub_8258B558)
if (scene != NULL)
{
ctx.r3.u32 = scene;
ctx.f1.f64 = offsetX + g_aspectRatioNarrowScale * 140.0f;
ctx.f1.f64 = offsetX + g_narrowOffsetScale * 140.0f;
ctx.f2.f64 = offsetY;
if (Config::UIScaleMode == EUIScaleMode::Edge && g_aspectRatioNarrowScale >= 1.0f)
ctx.f1.f64 += g_aspectRatioOffsetX / g_aspectRatioScale;
if (Config::UIScaleMode == EUIScaleMode::Edge && g_narrowOffsetScale >= 1.0f)
ctx.f1.f64 += g_aspectRatioOffsetX;
sub_830BB3D0(ctx, base);
}
@@ -292,9 +282,9 @@ PPC_FUNC(sub_8258B558)
uint32_t textBox = PPC_LOAD_U32(menuTextBox + 0x4);
if (textBox != NULL)
{
float value = 708.0f + g_aspectRatioNarrowScale * 140.0f;
if (Config::UIScaleMode == EUIScaleMode::Edge && g_aspectRatioNarrowScale >= 1.0f)
value += g_aspectRatioOffsetX / g_aspectRatioScale;
float value = 708.0f + g_narrowOffsetScale * 140.0f;
if (Config::UIScaleMode == EUIScaleMode::Edge && g_narrowOffsetScale >= 1.0f)
value += g_aspectRatioOffsetX;
PPC_STORE_U32(textBox + 0x38, reinterpret_cast<uint32_t&>(value));
}
@@ -750,6 +740,8 @@ static void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t str
modifier.flags &= ~(ALIGN_LEFT | ALIGN_RIGHT);
}
auto backBuffer = Video::GetBackBuffer();
uint32_t size = ctx.r5.u32 * stride;
ctx.r1.u32 -= size;
@@ -763,12 +755,10 @@ static void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t str
if ((modifier.flags & STRETCH_HORIZONTAL) != 0)
{
scaleX = Video::s_viewportWidth / 1280.0f;
scaleX = backBuffer->width / 1280.0f;
}
else
{
scaleX = g_aspectRatioScale;
if ((modifier.flags & ALIGN_RIGHT) != 0)
offsetX = g_aspectRatioOffsetX * 2.0f;
else if ((modifier.flags & ALIGN_LEFT) == 0)
@@ -776,29 +766,27 @@ static void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t str
if ((modifier.flags & SCALE) != 0)
{
scaleX *= g_aspectRatioGameplayScale;
scaleX = g_aspectRatioScale;
if ((modifier.flags & ALIGN_RIGHT) != 0)
offsetX += 1280.0f * (1.0f - g_aspectRatioGameplayScale) * g_aspectRatioScale;
offsetX += 1280.0f * (1.0f - scaleX);
else if ((modifier.flags & ALIGN_LEFT) == 0)
offsetX += 640.0f * (1.0f - g_aspectRatioGameplayScale) * g_aspectRatioScale;
offsetX += 640.0f * (1.0f - scaleX);
}
if ((modifier.flags & WORLD_MAP) != 0)
{
if ((modifier.flags & ALIGN_LEFT) != 0)
offsetX += (1.0f - g_aspectRatioNarrowScale) * g_aspectRatioScale * -20.0f;
offsetX += (1.0f - g_narrowOffsetScale) * -20.0f;
}
}
if ((modifier.flags & STRETCH_VERTICAL) != 0)
{
scaleY = Video::s_viewportHeight / 720.0f;
scaleY = backBuffer->height / 720.0f;
}
else
{
scaleY = g_aspectRatioScale;
if ((modifier.flags & ALIGN_BOTTOM) != 0)
offsetY = g_aspectRatioOffsetY * 2.0f;
else if ((modifier.flags & ALIGN_TOP) == 0)
@@ -806,12 +794,12 @@ static void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t str
if ((modifier.flags & SCALE) != 0)
{
scaleY *= g_aspectRatioGameplayScale;
scaleY = g_aspectRatioScale;
if ((modifier.flags & ALIGN_BOTTOM) != 0)
offsetY += 720.0f * (1.0f - g_aspectRatioGameplayScale) * g_aspectRatioScale;
offsetY += 720.0f * (1.0f - scaleY);
else if ((modifier.flags & ALIGN_TOP) == 0)
offsetY += 360.0f * (1.0f - g_aspectRatioGameplayScale) * g_aspectRatioScale;
offsetY += 360.0f * (1.0f - scaleY);
}
}
@@ -848,7 +836,7 @@ static void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t str
if ((offsetScaleModifier.flags & OFFSET_SCALE_LEFT) != 0)
offsetX *= corner / offsetScaleModifier.cornerMax;
else if ((offsetScaleModifier.flags & OFFSET_SCALE_RIGHT) != 0)
offsetX = Video::s_viewportWidth - (Video::s_viewportWidth - offsetX) * (1280.0f - corner) / (1280.0f - offsetScaleModifier.cornerMax);
offsetX = 1280.0f - (1280.0f - offsetX) * (1280.0f - corner) / (1280.0f - offsetScaleModifier.cornerMax);
}
for (size_t i = 0; i < ctx.r5.u32; i++)
@@ -864,11 +852,11 @@ static void Draw(PPCContext& ctx, uint8_t* base, PPCFunc* original, uint32_t str
}
else if ((modifier.flags & EXTEND_RIGHT) != 0 && (i == 2 || i == 3))
{
x = std::max(x, float(Video::s_viewportWidth));
x = std::max(x, float(backBuffer->width));
}
position[0] = round(x);
position[1] = round(y);
position[0] = round(x / backBuffer->width * Video::s_viewportWidth) / Video::s_viewportWidth * backBuffer->width;
position[1] = round(y / backBuffer->height * Video::s_viewportHeight) / Video::s_viewportHeight * backBuffer->height;
}
ctx.r4.u32 = ctx.r1.u32;
@@ -894,12 +882,13 @@ PPC_FUNC(sub_825E2E88)
PPC_FUNC_IMPL(__imp__sub_82E16C70);
PPC_FUNC(sub_82E16C70)
{
auto backBuffer = Video::GetBackBuffer();
auto scissorRect = reinterpret_cast<GuestRect*>(base + ctx.r4.u32);
scissorRect->left = scissorRect->left * g_aspectRatioScale + g_aspectRatioOffsetX;
scissorRect->top = scissorRect->top * g_aspectRatioScale + g_aspectRatioOffsetY;
scissorRect->right = scissorRect->right * g_aspectRatioScale + g_aspectRatioOffsetX;
scissorRect->bottom = scissorRect->bottom * g_aspectRatioScale + g_aspectRatioOffsetY;
scissorRect->left = scissorRect->left + g_aspectRatioOffsetX;
scissorRect->top = scissorRect->top + g_aspectRatioOffsetY;
scissorRect->right = scissorRect->right + g_aspectRatioOffsetX;
scissorRect->bottom = scissorRect->bottom + g_aspectRatioOffsetY;
__imp__sub_82E16C70(ctx, base);
}
@@ -937,77 +926,66 @@ PPC_FUNC(sub_830D1EF0)
__imp__sub_830D1EF0(ctx, base);
struct Vertex
if (!PPC_LOAD_U8(r3.u32 + PRIMITIVE_2D_PADDING_OFFSET))
{
be<float> x;
be<float> y;
be<float> z;
be<float> w;
be<uint32_t> color;
be<float> u;
be<float> v;
};
auto backBuffer = Video::GetBackBuffer();
auto vertex = reinterpret_cast<Vertex*>(base + ctx.r4.u32);
for (size_t i = 0; i < 4; i++)
{
float x = vertex[i].x * 640.0f + 640.0f;
float y = vertex[i].y * -360.0f + 360.0f;
if (PPC_LOAD_U8(r3.u32 + PRIMITIVE_2D_PADDING_OFFSET))
struct Vertex
{
// Stretch
x = ((x + 0.5f) / 1280.0f) * Video::s_viewportWidth;
y = ((y + 0.5f) / 720.0f) * Video::s_viewportHeight;
}
else
be<float> x;
be<float> y;
be<float> z;
be<float> w;
be<uint32_t> color;
be<float> u;
be<float> v;
};
auto vertex = reinterpret_cast<Vertex*>(base + ctx.r4.u32);
for (size_t i = 0; i < 4; i++)
{
// Center
x = g_aspectRatioOffsetX + (x + 0.5f) * g_aspectRatioScale;
y = g_aspectRatioOffsetY + (y + 0.5f) * g_aspectRatioScale;
vertex[i].x = vertex[i].x * 1280.0f / backBuffer->width;
vertex[i].y = vertex[i].y * 720.0f / backBuffer->height;
}
vertex[i].x = ((x - 0.5f) / Video::s_viewportWidth) * 2.0f - 1.0f;
vertex[i].y = ((y - 0.5f) / Video::s_viewportHeight) * -2.0f + 1.0f;
}
bool letterboxTop = PPC_LOAD_U8(r3.u32 + PRIMITIVE_2D_PADDING_OFFSET + 0x1);
bool letterboxBottom = PPC_LOAD_U8(r3.u32 + PRIMITIVE_2D_PADDING_OFFSET + 0x2);
bool letterboxTop = PPC_LOAD_U8(r3.u32 + PRIMITIVE_2D_PADDING_OFFSET + 0x1);
bool letterboxBottom = PPC_LOAD_U8(r3.u32 + PRIMITIVE_2D_PADDING_OFFSET + 0x2);
if (letterboxTop || letterboxBottom)
{
float halfPixelX = 1.0f / Video::s_viewportWidth;
float halfPixelY = 1.0f / Video::s_viewportHeight;
if (letterboxTop)
if (letterboxTop || letterboxBottom)
{
vertex[0].x = -1.0f - halfPixelX;
vertex[0].y = 1.0f + halfPixelY;
float halfPixelX = 1.0f / backBuffer->width;
float halfPixelY = 1.0f / backBuffer->height;
vertex[1].x = 1.0f - halfPixelX;
vertex[1].y = 1.0f + halfPixelY;
if (letterboxTop)
{
vertex[0].x = -1.0f - halfPixelX;
vertex[0].y = 1.0f + halfPixelY;
vertex[1].x = 1.0f - halfPixelX;
vertex[1].y = 1.0f + halfPixelY;
vertex[2].x = -1.0f - halfPixelX;
// vertex[2].y untouched
vertex[2].x = -1.0f - halfPixelX;
// vertex[2].y untouched
vertex[3].x = 1.0f - halfPixelX;
// vertex[3].y untouched
}
else if (letterboxBottom)
{
vertex[0].x = -1.0f - halfPixelX;
// vertex[0].y untouched
vertex[3].x = 1.0f - halfPixelX;
// vertex[3].y untouched
}
else if (letterboxBottom)
{
vertex[0].x = -1.0f - halfPixelX;
// vertex[0].y untouched
vertex[1].x = 1.0f - halfPixelX;
// vertex[1].y untouched
vertex[1].x = 1.0f - halfPixelX;
// vertex[1].y untouched
vertex[2].x = -1.0f - halfPixelX;
vertex[2].y = -1.0f + halfPixelY;
vertex[2].x = -1.0f - halfPixelX;
vertex[2].y = -1.0f + halfPixelY;
vertex[3].x = 1.0f - halfPixelX;
vertex[3].y = -1.0f + halfPixelY;
}
vertex[3].x = 1.0f - halfPixelX;
vertex[3].y = -1.0f + halfPixelY;
}
}
}
}
@@ -1040,9 +1018,8 @@ static double ComputeObjGetItemX(uint32_t type)
x = 1058.0;
x *= g_aspectRatioScale;
x *= g_aspectRatioGameplayScale;
double scaleOffset = (1280.0 * (1.0 - g_aspectRatioGameplayScale)) * g_aspectRatioScale;
double scaleOffset = (1280.0 * (1.0 - g_aspectRatioScale));
if (Config::UIScaleMode == EUIScaleMode::Edge)
{
@@ -1054,7 +1031,8 @@ static double ComputeObjGetItemX(uint32_t type)
x += g_aspectRatioOffsetX + scaleOffset;
}
return (x - (0.5 * Video::s_viewportWidth)) / (0.5 * Video::s_viewportHeight) * OBJ_GET_ITEM_TANGENT;
auto backBuffer = Video::GetBackBuffer();
return (x - (0.5 * backBuffer->width)) / (0.5 * backBuffer->height) * OBJ_GET_ITEM_TANGENT;
}
return 0.0;
@@ -1088,10 +1066,10 @@ static double ComputeObjGetItemY(uint32_t type)
y = 582.0;
y *= g_aspectRatioScale;
y *= g_aspectRatioGameplayScale;
y += g_aspectRatioOffsetY * 2.0 + 720.0 * (1.0 - g_aspectRatioGameplayScale) * g_aspectRatioScale;
y += g_aspectRatioOffsetY * 2.0 + 720.0 * (1.0 - g_aspectRatioScale);
return ((0.5 * Video::s_viewportHeight) - y) / (0.5 * Video::s_viewportHeight) * OBJ_GET_ITEM_TANGENT;
auto backBuffer = Video::GetBackBuffer();
return ((0.5 * backBuffer->height) - y) / (0.5 * backBuffer->height) * OBJ_GET_ITEM_TANGENT;
}
return 0.25;
@@ -1155,12 +1133,12 @@ PPC_FUNC(sub_82B8AA40)
PPC_STORE_U8(ctx.r3.u32, shouldDrawLetterbox);
if (shouldDrawLetterbox)
{
float aspectRatio = std::max(NARROW_ASPECT_RATIO, g_aspectRatio);
uint32_t width = aspectRatio * 720;
auto backBuffer = Video::GetBackBuffer();
uint32_t height = std::min(720u, backBuffer->height);
PPC_STORE_U32(ctx.r3.u32 + 0xC, width);
PPC_STORE_U32(ctx.r3.u32 + 0x10, 720);
PPC_STORE_U32(ctx.r3.u32 + 0x14, (720 - width * 9 / 16) / 2);
PPC_STORE_U32(ctx.r3.u32 + 0xC, backBuffer->width);
PPC_STORE_U32(ctx.r3.u32 + 0x10, height);
PPC_STORE_U32(ctx.r3.u32 + 0x14, (height - backBuffer->width * 9 / 16) / 2);
}
__imp__sub_82B8AA40(ctx, base);
@@ -1183,5 +1161,5 @@ void InspireSubtitleMidAsmHook(PPCRegister& r3)
constexpr float NARROW_OFFSET = 485.0f;
constexpr float WIDE_OFFSET = 560.0f;
*reinterpret_cast<be<float>*>(g_memory.base + r3.u32 + 0x3C) = NARROW_OFFSET + (WIDE_OFFSET - NARROW_OFFSET) * g_aspectRatioNarrowScale;
*reinterpret_cast<be<float>*>(g_memory.base + r3.u32 + 0x3C) = NARROW_OFFSET + (WIDE_OFFSET - NARROW_OFFSET) * g_narrowOffsetScale;
}

View File

@@ -8,8 +8,7 @@ inline float g_aspectRatio;
inline float g_aspectRatioOffsetX;
inline float g_aspectRatioOffsetY;
inline float g_aspectRatioScale;
inline float g_aspectRatioGameplayScale;
inline float g_aspectRatioNarrowScale;
inline float g_narrowOffsetScale;
struct AspectRatioPatches
{

View File

@@ -0,0 +1,97 @@
#include <api/SWA.h>
#include <ui/game_window.h>
#include <user/config.h>
#include <ui/reddog/debug_draw.h>
#include <ui/imgui_utils.h>
#include <patches/aspect_ratio_patches.h>
// boost::~::SWA::CDebugDraw::CMember::SDrawLine
PPC_FUNC_IMPL(__imp__sub_822C9398);
PPC_FUNC(sub_822C9398)
{
auto a2 = (Hedgehog::Math::CVector*)g_memory.Translate(ctx.r4.u32);
auto a3 = (Hedgehog::Math::CVector*)g_memory.Translate(ctx.r5.u32);
auto a4 = (be<unsigned int>*)g_memory.Translate(ctx.r6.u32);
Reddog::Vector3 start(a2->X, a2->Y, a2->Z);
Reddog::Vector3 end(a3->X, a3->Y, a3->Z);
const Reddog::SDrawLine line{
start, end, a4->value
};
Reddog::DebugDraw::DrawLine(line);
__imp__sub_822C9398(ctx, base);
}
// SWA::CStageManager::UpdateParallel
//PPC_FUNC_IMPL(__imp__sub_82521C68);
//PPC_FUNC(sub_82521C68)
//{
// __imp__sub_82521C68(ctx, base);
//}
// SWA::CStageManager::UpdateSerial
PPC_FUNC_IMPL(__imp__sub_82522040);
PPC_FUNC(sub_82522040)
{
auto a1 = static_cast<SWA::CStageManager*>(g_memory.Translate(ctx.r3.u32));
__imp__sub_82522040(ctx, base);
// Draw player position
if (Reddog::DebugDraw::GetIsDrawPosition())
{
// TODO (RadiantDerg): Reimplement SWA::CStageManager ability to draw progress ratio
// NOTE: Currently does not work, is the API mapping horribly misaligned/misunderstood?
if (a1->m_spStageGuidePathController)
{
if (a1->m_spStageGuidePathController->m_spPathAnimationController)
{
auto PAC = a1->m_spStageGuidePathController->m_spPathAnimationController;
//Reddog::DebugDraw::DrawTextLog(fmt::format("m_DistanceAlongPath = {:.2f}", PAC->m_DistanceAlongPath.get()).c_str());
}
// Ratio
if (a1->m_StageGuidePathLength.get() > 0.0f)
{
//float distance = 0; // GetDistanceAlongPath(a1->m_StageGuidePathController)
//a1->m_StageGuidePathRatio = distance / a1->m_StageGuidePathLength;
const Reddog::SDrawText ratioText{
{Scale(g_aspectRatioOffsetX + 720), Scale(g_aspectRatioOffsetY + 36)},
fmt::format("{:.1f}m [{:.1f}/100.0]", a1->m_StageGuidePathLength.get(), a1->m_StageGuidePathRatio.get()),
0,
3.25f,
0xFFFFFFFF,
Reddog::eDrawTextFlags_NoShadow
};
Reddog::DebugDraw::DrawText2D(ratioText);
}
}
// Position
const Reddog::SDrawText positionText{
{Scale(g_aspectRatioOffsetX + 750), Scale(g_aspectRatioOffsetY + 120)},
fmt::format("( {:.2f}, {:.2f}, {:.2f} )", a1->m_PlayerPosition.X.get(), a1->m_PlayerPosition.Y.get(), a1->m_PlayerPosition.Z.get()),
0,
2.0f,
0xFFFFFFFF,
Reddog::eDrawTextFlags_NoShadow
};
Reddog::DebugDraw::DrawText2D(positionText);
}
}
// GetIsDebugRenderForGameObject()
//PPC_FUNC(sub_82512BF8)
//{
// ctx.r3.u8 = 1; // Always return true
//}

View File

@@ -94,8 +94,7 @@ bool LoadingUpdateMidAsmHook(PPCRegister& r31)
g_ppcContext->f1.f64 = deltaTime;
g_memory.FindFunction(update)(*g_ppcContext, base);
bool loading = PPC_LOAD_U8(0x83367A4C);
if (loading)
if (*SWA::SGlobals::ms_IsLoading)
{
now = std::chrono::steady_clock::now();
constexpr auto INTERVAL = 1000000000ns / 30;
@@ -104,7 +103,7 @@ bool LoadingUpdateMidAsmHook(PPCRegister& r31)
std::this_thread::sleep_until(next);
}
return loading;
return *SWA::SGlobals::ms_IsLoading;
}
// ADXM_WaitVsync

View File

@@ -1,348 +0,0 @@
#include <api/SWA.h>
#include <hid/hid.h>
#include <ui/sdl_listener.h>
#include <app.h>
#include <exports.h>
class WorldMapTouchParams
{
public:
float CancelDeadzone{ 0.31f };
float Damping{ 0.99f };
float FlickAccelX{ 0.25f };
float FlickAccelY{ 0.1f };
float FlickTerminalVelocity{ 40.0f };
float FlickThreshold{ 2.25f };
float SensitivityX{};
float SensitivityY{};
float Smoothing{ 0.8f };
};
class WorldMapTouchParamsProspero : public WorldMapTouchParams
{
public:
WorldMapTouchParamsProspero()
{
SensitivityX = 1.15f;
SensitivityY = 1.05f;
}
}
g_worldMapTouchParamsProspero;
class WorldMapTouchParamsOrbis : public WorldMapTouchParams
{
public:
WorldMapTouchParamsOrbis()
{
SensitivityX = 0.95f;
SensitivityY = 1.0f;
}
}
g_worldMapTouchParamsOrbis;
WorldMapTouchParams g_worldMapTouchParams{};
static bool g_isTouchActive;
static float g_worldMapTouchVelocityX;
static float g_worldMapTouchVelocityY;
class SDLEventListenerForInputPatches : public SDLEventListener
{
static inline int ms_touchpadFingerCount;
static inline float ms_touchpadX;
static inline float ms_touchpadY;
static inline float ms_touchpadDeltaX;
static inline float ms_touchpadDeltaY;
static inline float ms_touchpadPrevX;
static inline float ms_touchpadPrevY;
public:
static void Update(float deltaTime)
{
/* NOTE (Hyper): this code was written at 144Hz and was
discovered later to be faulty at any other frame rate,
so this is here to account for that without changing
all the constants that I had tuned. */
constexpr auto referenceDeltaTime = 1.0f / 144.0f;
if (g_isTouchActive)
{
auto dxNorm = ms_touchpadDeltaX / referenceDeltaTime;
auto dyNorm = ms_touchpadDeltaY / referenceDeltaTime;
auto dxSens = dxNorm * g_worldMapTouchParams.SensitivityX;
auto dySens = dyNorm * g_worldMapTouchParams.SensitivityY;
auto smoothing = powf(g_worldMapTouchParams.Smoothing, deltaTime / referenceDeltaTime);
g_worldMapTouchVelocityX = smoothing * g_worldMapTouchVelocityX + (1.0f - smoothing) * dxSens;
g_worldMapTouchVelocityY = smoothing * g_worldMapTouchVelocityY + (1.0f - smoothing) * dySens;
auto flickThreshold = g_worldMapTouchParams.FlickThreshold;
if (fabs(dxSens) > flickThreshold || fabs(dySens) > flickThreshold)
{
g_worldMapTouchVelocityX += dxNorm * g_worldMapTouchParams.FlickAccelX * (deltaTime / referenceDeltaTime);
g_worldMapTouchVelocityY += dyNorm * g_worldMapTouchParams.FlickAccelY * (deltaTime / referenceDeltaTime);
}
auto terminalVelocity = g_worldMapTouchParams.FlickTerminalVelocity;
g_worldMapTouchVelocityX = std::clamp(g_worldMapTouchVelocityX, -terminalVelocity, terminalVelocity);
g_worldMapTouchVelocityY = std::clamp(g_worldMapTouchVelocityY, -terminalVelocity, terminalVelocity);
}
else
{
auto dampingFactor = powf(g_worldMapTouchParams.Damping, deltaTime / referenceDeltaTime);
g_worldMapTouchVelocityX *= dampingFactor;
g_worldMapTouchVelocityY *= dampingFactor;
}
}
void OnSDLEvent(SDL_Event* event) override
{
switch (event->type)
{
case SDL_CONTROLLERTOUCHPADMOTION:
{
g_isTouchActive = true;
if (ms_touchpadFingerCount > 1)
{
g_isTouchActive = false;
break;
}
ms_touchpadX = event->ctouchpad.x;
ms_touchpadY = event->ctouchpad.y;
ms_touchpadDeltaX = ms_touchpadX - ms_touchpadPrevX;
ms_touchpadDeltaY = ms_touchpadY - ms_touchpadPrevY;
ms_touchpadPrevX = ms_touchpadX;
ms_touchpadPrevY = ms_touchpadY;
break;
}
case SDL_CONTROLLERTOUCHPADDOWN:
{
g_worldMapTouchParams = hid::g_inputDeviceExplicit == hid::EInputDeviceExplicit::DualSense
? (WorldMapTouchParams)g_worldMapTouchParamsProspero
: (WorldMapTouchParams)g_worldMapTouchParamsOrbis;
ms_touchpadFingerCount++;
ms_touchpadPrevX = event->ctouchpad.x;
ms_touchpadPrevY = event->ctouchpad.y;
break;
}
case SDL_CONTROLLERTOUCHPADUP:
g_isTouchActive = false;
ms_touchpadFingerCount--;
break;
}
}
}
g_sdlEventListenerForInputPatches;
// -------------- COMMON --------------- //
static bool IsDPadActive(SWA::SPadState* pPadState)
{
return pPadState->IsDown(SWA::eKeyState_DpadUp) ||
pPadState->IsDown(SWA::eKeyState_DpadDown) ||
pPadState->IsDown(SWA::eKeyState_DpadLeft) ||
pPadState->IsDown(SWA::eKeyState_DpadRight);
}
static void SetDPadAnalogDirectionX(PPCRegister& pPadState, PPCRegister& x, bool invert, float max = 1.0f)
{
auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32);
if (pGuestPadState->IsDown(SWA::eKeyState_DpadLeft))
x.f64 = invert ? max : -max;
if (pGuestPadState->IsDown(SWA::eKeyState_DpadRight))
x.f64 = invert ? -max : max;
}
static void SetDPadAnalogDirectionY(PPCRegister& pPadState, PPCRegister& y, bool invert, float max = 1.0f)
{
auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32);
if (pGuestPadState->IsDown(SWA::eKeyState_DpadUp))
y.f64 = invert ? -max : max;
if (pGuestPadState->IsDown(SWA::eKeyState_DpadDown))
y.f64 = invert ? max : -max;
}
// -------------- PLAYER --------------- //
void PostureDPadSupportMidAsmHook(PPCRegister& pPadState, PPCRegister& x, PPCRegister& y)
{
SetDPadAnalogDirectionX(pPadState, x, false);
SetDPadAnalogDirectionY(pPadState, y, false);
}
void PostureDPadSupportInvertYMidAsmHook(PPCRegister& pPadState, PPCRegister& x, PPCRegister& y)
{
SetDPadAnalogDirectionX(pPadState, x, false);
SetDPadAnalogDirectionY(pPadState, y, true);
}
void PostureDPadSupportXMidAsmHook(PPCRegister& pPadState, PPCRegister& x)
{
SetDPadAnalogDirectionX(pPadState, x, false);
}
void PostureDPadSupportYMidAsmHook(PPCRegister& pPadState, PPCRegister& y)
{
SetDPadAnalogDirectionY(pPadState, y, false);
}
void PostureSpaceHurrierDPadSupportXMidAsmHook(PPCRegister& pPadState, PPCVRegister& vector)
{
auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32);
if (pGuestPadState->IsDown(SWA::eKeyState_DpadLeft))
vector.f32[3] = -1.0f;
if (pGuestPadState->IsDown(SWA::eKeyState_DpadRight))
vector.f32[3] = 1.0f;
}
void PostureSpaceHurrierDPadSupportYMidAsmHook(PPCRegister& pPadState, PPCVRegister& vector)
{
auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32);
if (pGuestPadState->IsDown(SWA::eKeyState_DpadUp))
vector.f32[3] = 1.0f;
if (pGuestPadState->IsDown(SWA::eKeyState_DpadDown))
vector.f32[3] = -1.0f;
}
// ------------- WORLD MAP ------------- //
bool WorldMapTouchSupportMidAsmHook()
{
SDLEventListenerForInputPatches::Update(App::s_deltaTime);
auto vxAbs = fabs(g_worldMapTouchVelocityX);
auto vyAbs = fabs(g_worldMapTouchVelocityY);
/* Reduce touch noise if the player has
their finger resting on the touchpad,
but allow much precise values without
touch for proper interpolation to zero. */
if (vxAbs < 0.05f || vyAbs < 0.05f)
return !g_isTouchActive;
return vxAbs > 0 || vyAbs > 0;
}
bool WorldMapTouchMagnetismSupportMidAsmHook(PPCRegister& f0)
{
return fabs(g_worldMapTouchVelocityX) > f0.f64 || fabs(g_worldMapTouchVelocityY) > f0.f64;
}
void TouchAndDPadSupportWorldMapXMidAsmHook(PPCRegister& pPadState, PPCRegister& x)
{
auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32);
if (fabs(pGuestPadState->LeftStickHorizontal) > g_worldMapTouchParams.CancelDeadzone ||
fabs(pGuestPadState->LeftStickVertical) > g_worldMapTouchParams.CancelDeadzone)
{
g_worldMapTouchVelocityX = 0;
}
if (IsDPadActive(pGuestPadState))
{
g_worldMapTouchVelocityX = 0;
SetDPadAnalogDirectionX(pPadState, x, false);
}
else
{
if (fabs(g_worldMapTouchVelocityX) > 0)
x.f64 = -g_worldMapTouchVelocityX;
}
}
void TouchAndDPadSupportWorldMapYMidAsmHook(PPCRegister& pPadState, PPCRegister& y)
{
auto pGuestPadState = (SWA::SPadState*)g_memory.Translate(pPadState.u32);
if (fabs(pGuestPadState->LeftStickHorizontal) > g_worldMapTouchParams.CancelDeadzone ||
fabs(pGuestPadState->LeftStickVertical) > g_worldMapTouchParams.CancelDeadzone)
{
g_worldMapTouchVelocityY = 0;
}
if (IsDPadActive(pGuestPadState))
{
g_worldMapTouchVelocityY = 0;
SetDPadAnalogDirectionY(pPadState, y, false);
}
else
{
if (fabs(g_worldMapTouchVelocityY) > 0)
y.f64 = g_worldMapTouchVelocityY;
}
}
// SWA::CWorldMapCamera::Update
PPC_FUNC_IMPL(__imp__sub_82486968);
PPC_FUNC(sub_82486968)
{
auto pWorldMapCamera = (SWA::CWorldMapCamera*)g_memory.Translate(ctx.r3.u32);
// Reset vertical velocity if maximum pitch reached.
if (fabs(pWorldMapCamera->m_Pitch) >= 80.0f)
g_worldMapTouchVelocityY = 0;
__imp__sub_82486968(ctx, base);
}
// World Map cursor move hook.
PPC_FUNC(sub_8256C938)
{
auto pWorldMapCursor = (SWA::CWorldMapCursor*)g_memory.Translate(ctx.r3.u32);
pWorldMapCursor->m_IsCursorMoving = g_isTouchActive;
if (ctx.r4.u8)
{
pWorldMapCursor->m_LeftStickVertical = 0;
pWorldMapCursor->m_LeftStickHorizontal = 0;
}
else if (auto pInputState = SWA::CInputState::GetInstance())
{
auto& rPadState = pInputState->GetPadState();
pWorldMapCursor->m_LeftStickVertical = rPadState.LeftStickVertical;
pWorldMapCursor->m_LeftStickHorizontal = rPadState.LeftStickHorizontal;
if (rPadState.IsDown(SWA::eKeyState_DpadUp))
pWorldMapCursor->m_LeftStickVertical = 1.0f;
if (rPadState.IsDown(SWA::eKeyState_DpadDown))
pWorldMapCursor->m_LeftStickVertical = -1.0f;
if (rPadState.IsDown(SWA::eKeyState_DpadLeft))
pWorldMapCursor->m_LeftStickHorizontal = -1.0f;
if (rPadState.IsDown(SWA::eKeyState_DpadRight))
pWorldMapCursor->m_LeftStickHorizontal = 1.0f;
if (sqrtf((pWorldMapCursor->m_LeftStickHorizontal * pWorldMapCursor->m_LeftStickHorizontal) +
(pWorldMapCursor->m_LeftStickVertical * pWorldMapCursor->m_LeftStickVertical)) > 0.7f)
{
pWorldMapCursor->m_IsCursorMoving = true;
}
}
}

View File

@@ -1,4 +1,5 @@
#include <api/SWA.h>
#include <ui/reddog/debug_draw.h>
#include <ui/game_window.h>
#include <user/achievement_data.h>
#include <user/config.h>
@@ -49,6 +50,8 @@ void WerehogBattleMusicMidAsmHook(PPCRegister& r11)
r11.u8 = 3;
}
void StorageDevicePromptMidAsmHook() {}
/* Hook function that gets the game region
and force result to zero for Japanese
to display the correct logos. */

View File

@@ -1,6 +1,3 @@
#include <user/config.h>
#include <SWA/CharacterUtility/CharacterProxy.h>
// CObjFlame::CObjFlame
// A field is not zero initialized,
// causing collisions to constantly get created
@@ -11,59 +8,3 @@ PPC_FUNC(sub_82608E60)
memset(base + ctx.r3.u32, 0, 0x154);
__imp__sub_82608E60(ctx, base);
}
// The barrel gets stuck at a slope at high frame rates and softlocks the player.
// We can update the character proxy at 30 FPS, and interpolate the visuals to work around this issue.
static constexpr size_t OBJ_BIG_BARREL_SIZE = 0x1A0;
struct ObjBigBarrelEx
{
float elapsedTime{};
bool interpolate{};
};
void ObjBigBarrelAllocMidAsmHook(PPCRegister& r3)
{
r3.u32 += sizeof(ObjBigBarrelEx);
}
// CObjBigBarrel::CObjBigBarrel
PPC_FUNC_IMPL(__imp__sub_8271AC08);
PPC_FUNC(sub_8271AC08)
{
new (base + ctx.r3.u32 + OBJ_BIG_BARREL_SIZE) ObjBigBarrelEx();
__imp__sub_8271AC08(ctx, base);
}
// CObjBigBarrel::Integrate
PPC_FUNC_IMPL(__imp__sub_8271AA30);
PPC_FUNC(sub_8271AA30)
{
auto objBigBarrelEx = reinterpret_cast<ObjBigBarrelEx*>(base + ctx.r3.u32 + OBJ_BIG_BARREL_SIZE);
objBigBarrelEx->interpolate = ctx.f1.f64 < (1.0 / 30.0);
objBigBarrelEx->elapsedTime += ctx.f1.f64;
if (!objBigBarrelEx->interpolate || objBigBarrelEx->elapsedTime >= (1.0f / 30.0f))
{
ctx.f1.f64 = objBigBarrelEx->elapsedTime;
__imp__sub_8271AA30(ctx, base);
objBigBarrelEx->elapsedTime = 0.0f;
}
}
void ObjBigBarrelSetPositionMidAsmHook(PPCRegister& r3, PPCRegister& r4)
{
uint8_t* base = g_memory.base;
auto objBigBarrelEx = reinterpret_cast<ObjBigBarrelEx*>(base + r3.u32 + OBJ_BIG_BARREL_SIZE);
if (objBigBarrelEx->interpolate)
{
auto characterProxy = reinterpret_cast<SWA::CCharacterProxy*>(base + PPC_LOAD_U32(r3.u32 + 0x100));
auto position = reinterpret_cast<Hedgehog::Math::CVector*>(base + r4.u32);
float factor = (1.0f / 30.0f) - objBigBarrelEx->elapsedTime;
position->X = position->X - characterProxy->m_Velocity.X * factor;
position->Y = position->Y - characterProxy->m_Velocity.Y * factor;
position->Z = position->Z - characterProxy->m_Velocity.Z * factor;
}
}

View File

@@ -10,6 +10,26 @@ static uint32_t g_lastTrickScore;
static float g_lastDarkGaiaEnergy;
static bool g_isUnleashCancelled;
void PostureDPadSupportMidAsmHook(PPCRegister& r3)
{
if (!Config::AllowDPadMovement)
return;
auto pPadState = (SWA::SPadState*)g_memory.Translate(r3.u32);
if (pPadState->IsDown(SWA::eKeyState_DpadUp))
pPadState->LeftStickVertical = 1.0f;
if (pPadState->IsDown(SWA::eKeyState_DpadDown))
pPadState->LeftStickVertical = -1.0f;
if (pPadState->IsDown(SWA::eKeyState_DpadLeft))
pPadState->LeftStickHorizontal = -1.0f;
if (pPadState->IsDown(SWA::eKeyState_DpadRight))
pPadState->LeftStickHorizontal = 1.0f;
}
/* Hook function for when checkpoints are activated
to preserve the current checkpoint score. */
PPC_FUNC_IMPL(__imp__sub_82624308);

View File

@@ -2,7 +2,7 @@
#include <user/config.h>
#include <api/SWA.h>
#include <os/logger.h>
#include <hid/hid.h>
#include <hid/hid_detail.h>
#include <app.h>
bool m_isSavedAchievementData = false;
@@ -69,8 +69,6 @@ PPC_FUNC(sub_824E5170)
if (pSaveIcon->m_IsVisible)
{
App::s_isSaveDataCorrupt = false;
if (!m_isSavedAchievementData)
{
LOGN("Saving achievements...");
@@ -133,7 +131,7 @@ void LoadingScreenControllerMidAsmHook()
auto isPlayStation = Config::ControllerIcons == EControllerIcons::PlayStation;
if (Config::ControllerIcons == EControllerIcons::Auto)
isPlayStation = hid::g_inputDeviceController == hid::EInputDevice::PlayStation;
isPlayStation = hid::detail::g_inputDeviceController == hid::detail::EInputDevice::PlayStation;
const char* prefix = isPlayStation ? "ps3" : "360";

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