Compiling and running on Linux. (#49)

* Current work trying to get it to compile.

* Update vcpkg.json baseline.

* vcpkg, memory mapped file.

* Bitscan forward.

* Fix localtime_s.

* FPS patches high res clock.

* Rename Window to GameWindow. Fix guest pointers.

* GetCurrentThreadID gone.

* Code cache pointers, RenderWindow type.

* Add Linux stubs.

* Refactor Config.

* Fix paths.

* Add linux-release config.

* FS fixes.

* Fix Windows compilation errors & unicode converter crash.

* Rename physical memory allocation functions to not clash with X11.

* Fix NULL character being added on RtlMultiByteToUnicodeN.

* Use std::exit.

* Add protection to memory on Linux.

* Convert majority of dependencies to submodules. (#48)

* Convert majority of dependencies to submodules.

* Don't compile header-only libraries.

* Fix a few incorrect data types.

* Fix config directory.

* Unicode fixes & sizeof asserts.

* Change the exit function to not call static destructors.

* Fix files picker.

* Add RelWithDebInfo preset for Linux.

* Implement OS Restart on Linux. (#50)

---------

Co-authored-by: Dario <dariosamo@gmail.com>
This commit is contained in:
Skyth (Asilkan) 2024-12-17 18:10:17 +00:00 committed by GitHub
parent 2bcaa61d42
commit 999fe3c4eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
78 changed files with 1723 additions and 1499 deletions

42
.gitmodules vendored
View file

@ -22,3 +22,45 @@
[submodule "thirdparty/vcpkg"]
path = thirdparty/vcpkg
url = https://github.com/microsoft/vcpkg
[submodule "thirdparty/volk"]
path = thirdparty/volk
url = https://github.com/zeux/volk
[submodule "thirdparty/SDL"]
path = thirdparty/SDL
url = https://github.com/libsdl-org/SDL.git
[submodule "thirdparty/Vulkan-Headers"]
path = thirdparty/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git
[submodule "thirdparty/VulkanMemoryAllocator"]
path = thirdparty/VulkanMemoryAllocator
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
[submodule "thirdparty/D3D12MemoryAllocator"]
path = thirdparty/D3D12MemoryAllocator
url = https://github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git
[submodule "thirdparty/stb"]
path = thirdparty/stb
url = https://github.com/nothings/stb.git
[submodule "thirdparty/concurrentqueue"]
path = thirdparty/concurrentqueue
url = https://github.com/cameron314/concurrentqueue.git
[submodule "thirdparty/tiny-AES-c"]
path = thirdparty/tiny-AES-c
url = https://github.com/kokke/tiny-AES-c.git
[submodule "thirdparty/magic_enum"]
path = thirdparty/magic_enum
url = https://github.com/Neargye/magic_enum.git
[submodule "thirdparty/nativefiledialog-extended"]
path = thirdparty/nativefiledialog-extended
url = https://github.com/btzy/nativefiledialog-extended.git
[submodule "thirdparty/imgui"]
path = thirdparty/imgui
url = https://github.com/ocornut/imgui.git
[submodule "thirdparty/unordered_dense"]
path = thirdparty/unordered_dense
url = https://github.com/martinus/unordered_dense.git
[submodule "thirdparty/vorbis"]
path = thirdparty/vorbis
url = https://gitlab.xiph.org/xiph/vorbis.git
[submodule "thirdparty/ogg"]
path = thirdparty/ogg
url = https://gitlab.xiph.org/xiph/ogg.git

View file

@ -16,6 +16,9 @@
"type": "FILEPATH"
}
},
"environment": {
"VCPKG_ROOT": "${sourceDir}/thirdparty/vcpkg"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
@ -57,14 +60,12 @@
}
},
{
"name": "linux-debug",
"displayName": "Linux Debug",
"description": "Target the Windows Subsystem for Linux (WSL) or a remote Linux system.",
"name": "linux-base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_TOOLCHAIN_FILE": {
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"type": "FILEPATH"
@ -88,6 +89,31 @@
"remoteSourceRootDir": "$env{HOME}/.vs/$ms{projectDirName}"
}
}
},
{
"name": "linux-debug",
"displayName": "Linux-Debug",
"inherits": "linux-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "linux-relwithdebinfo",
"displayName": "Linux-RelWithDebInfo",
"inherits": "linux-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
},
{
"name": "linux-release",
"displayName": "Linux-Release",
"inherits": "linux-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": true
}
}
]
}

View file

@ -1,465 +1,476 @@
project("UnleashedRecomp")
set(TARGET_NAME "SWA")
if (WIN32)
option(SWA_D3D12 "Add D3D12 support for rendering" ON)
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})
if(NOT BIN2C_ARGS_TARGET_OBJ)
message(FATAL_ERROR "TARGET_OBJ not specified.")
endif()
if(NOT BIN2C_ARGS_SOURCE_FILE)
message(FATAL_ERROR "SOURCE_FILE not specified.")
endif()
if(NOT BIN2C_ARGS_DEST_FILE)
set(BIN2C_ARGS_DEST_FILE "${BIN2C_ARGS_SOURCE_FILE}")
endif()
if(NOT BIN2C_ARGS_COMPRESSION_TYPE)
set(BIN2C_ARGS_COMPRESSION_TYPE "none")
endif()
add_custom_command(OUTPUT "${BIN2C_ARGS_DEST_FILE}.c"
COMMAND file_to_c "${BIN2C_ARGS_SOURCE_FILE}" "${BIN2C_ARGS_ARRAY_NAME}" "${BIN2C_ARGS_COMPRESSION_TYPE}" "${BIN2C_ARGS_DEST_FILE}.c" "${BIN2C_ARGS_DEST_FILE}.h"
DEPENDS "${BIN2C_ARGS_SOURCE_FILE}" file_to_c
BYPRODUCTS "${BIN2C_ARGS_DEST_FILE}.h"
COMMENT "Generating binary header for ${BIN2C_ARGS_SOURCE_FILE}..."
)
set_source_files_properties(${BIN2C_ARGS_DEST_FILE}.c PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
target_sources(${BIN2C_ARGS_TARGET_OBJ} PRIVATE ${BIN2C_ARGS_DEST_FILE}.c)
endfunction()
add_compile_options(
/fp:strict
-march=sandybridge
-fno-strict-aliasing
-Wno-switch
-Wno-unused-function
-Wno-unused-variable
-Wno-unused-but-set-variable
-Wno-void-pointer-to-int-cast
-Wno-int-to-void-pointer-cast
-Wno-invalid-offsetof
)
add_compile_definitions(
SWA_IMPL
SDL_MAIN_HANDLED
_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR # Microsoft wtf?
_CRT_SECURE_NO_WARNINGS)
set(SWA_PRECOMPILED_HEADERS
"stdafx.h"
)
set(SWA_KERNEL_CXX_SOURCES
"kernel/imports.cpp"
"kernel/xdm.cpp"
"kernel/heap.cpp"
"kernel/memory.cpp"
"kernel/xam.cpp"
"kernel/io/file_system.cpp"
)
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/version.cpp"
project("UnleashedRecomp")
set(TARGET_NAME "SWA")
if (WIN32)
option(SWA_D3D12 "Add D3D12 support for rendering" ON)
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})
if(NOT BIN2C_ARGS_TARGET_OBJ)
message(FATAL_ERROR "TARGET_OBJ not specified.")
endif()
if(NOT BIN2C_ARGS_SOURCE_FILE)
message(FATAL_ERROR "SOURCE_FILE not specified.")
endif()
if(NOT BIN2C_ARGS_DEST_FILE)
set(BIN2C_ARGS_DEST_FILE "${BIN2C_ARGS_SOURCE_FILE}")
endif()
if(NOT BIN2C_ARGS_COMPRESSION_TYPE)
set(BIN2C_ARGS_COMPRESSION_TYPE "none")
endif()
add_custom_command(OUTPUT "${BIN2C_ARGS_DEST_FILE}.c"
COMMAND $<TARGET_FILE:file_to_c> "${BIN2C_ARGS_SOURCE_FILE}" "${BIN2C_ARGS_ARRAY_NAME}" "${BIN2C_ARGS_COMPRESSION_TYPE}" "${BIN2C_ARGS_DEST_FILE}.c" "${BIN2C_ARGS_DEST_FILE}.h"
DEPENDS "${BIN2C_ARGS_SOURCE_FILE}"
BYPRODUCTS "${BIN2C_ARGS_DEST_FILE}.h"
COMMENT "Generating binary header for ${BIN2C_ARGS_SOURCE_FILE}..."
)
set_source_files_properties(${BIN2C_ARGS_DEST_FILE}.c PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
target_sources(${BIN2C_ARGS_TARGET_OBJ} PRIVATE ${BIN2C_ARGS_DEST_FILE}.c)
endfunction()
add_compile_options(
-march=sandybridge
-fno-strict-aliasing
-Wno-switch
-Wno-unused-function
-Wno-unused-variable
-Wno-unused-but-set-variable
-Wno-void-pointer-to-int-cast
-Wno-int-to-void-pointer-cast
-Wno-invalid-offsetof
-Wno-null-arithmetic
-Wno-null-conversion
-Wno-tautological-undefined-compare
)
if (WIN32)
list(APPEND SWA_OS_CXX_SOURCES
"os/win32/logger_win32.cpp"
"os/win32/media_win32.cpp"
"os/win32/process_win32.cpp"
"os/win32/version_win32.cpp"
)
endif()
set(SWA_CPU_CXX_SOURCES
"cpu/guest_thread.cpp"
"cpu/code_cache.cpp"
add_compile_options(/fp:strict)
else()
add_compile_options(-ffp-model=strict)
endif()
add_compile_definitions(
SWA_IMPL
SDL_MAIN_HANDLED
_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR # Microsoft wtf?
_CRT_SECURE_NO_WARNINGS)
set(SWA_PRECOMPILED_HEADERS
"stdafx.h"
)
set(SWA_KERNEL_CXX_SOURCES
"kernel/imports.cpp"
"kernel/xdm.cpp"
"kernel/heap.cpp"
"kernel/memory.cpp"
"kernel/xam.cpp"
"kernel/io/file_system.cpp"
)
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/version.cpp"
)
if (WIN32)
list(APPEND SWA_OS_CXX_SOURCES
"os/win32/logger_win32.cpp"
"os/win32/media_win32.cpp"
"os/win32/process_win32.cpp"
"os/win32/version_win32.cpp"
)
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
list(APPEND SWA_OS_CXX_SOURCES
"os/linux/logger_linux.cpp"
"os/linux/media_linux.cpp"
"os/linux/process_linux.cpp"
"os/linux/version_linux.cpp"
)
endif()
set(SWA_CPU_CXX_SOURCES
"cpu/guest_thread.cpp"
"cpu/code_cache.cpp"
)
set(SWA_GPU_CXX_SOURCES
"gpu/video.cpp"
"gpu/imgui/imgui_common.cpp"
"gpu/imgui/imgui_font_builder.cpp"
"gpu/imgui/imgui_snapshot.cpp"
"gpu/rhi/plume_vulkan.cpp"
)
if (SWA_D3D12)
list(APPEND SWA_GPU_CXX_SOURCES
"gpu/rhi/plume_d3d12.cpp"
)
endif()
set(SWA_APU_CXX_SOURCES
"apu/audio.cpp"
"apu/embedded_player.cpp"
)
if (SWA_XAUDIO2)
list(APPEND SWA_APU_CXX_SOURCES "apu/driver/xaudio_driver.cpp")
else()
list(APPEND SWA_APU_CXX_SOURCES "apu/driver/miniaudio_driver.cpp")
endif()
set(SWA_HID_CXX_SOURCES
"hid/hid.cpp"
"hid/driver/sdl_hid.cpp"
)
set(SWA_PATCHES_CXX_SOURCES
"patches/ui/CHudPause_patches.cpp"
"patches/ui/CTitleStateIntro_patches.cpp"
"patches/ui/CTitleStateMenu_patches.cpp"
"patches/ui/frontend_listener.cpp"
"patches/audio_patches.cpp"
"patches/camera_patches.cpp"
"patches/fps_patches.cpp"
"patches/misc_patches.cpp"
"patches/object_patches.cpp"
"patches/player_patches.cpp"
"patches/resident_patches.cpp"
"patches/video_patches.cpp"
)
set(SWA_UI_CXX_SOURCES
"ui/achievement_menu.cpp"
"ui/achievement_overlay.cpp"
"ui/installer_wizard.cpp"
"ui/button_guide.cpp"
"ui/fader.cpp"
"ui/message_window.cpp"
"ui/options_menu_thumbnails.cpp"
"ui/options_menu.cpp"
"ui/sdl_listener.cpp"
"ui/game_window.cpp"
)
set(SWA_INSTALL_CXX_SOURCES
"install/installer.cpp"
"install/iso_file_system.cpp"
"install/memory_mapped_file.cpp"
"install/xcontent_file_system.cpp"
"install/xex_patcher.cpp"
"install/hashes/apotos_shamar.cpp"
"install/hashes/chunnan.cpp"
"install/hashes/empire_city_adabat.cpp"
"install/hashes/game.cpp"
"install/hashes/holoska.cpp"
"install/hashes/mazuri.cpp"
"install/hashes/spagonia.cpp"
"install/hashes/update.cpp"
)
set(SWA_GPU_CXX_SOURCES
"gpu/video.cpp"
"gpu/imgui/imgui_common.cpp"
"gpu/imgui/imgui_font_builder.cpp"
"gpu/imgui/imgui_snapshot.cpp"
"gpu/rhi/plume_vulkan.cpp"
set(SWA_USER_CXX_SOURCES
"user/achievement_data.cpp"
"user/config.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}/libmspack/libmspack/mspack/lzxd.c"
"${SWA_THIRDPARTY_ROOT}/tiny-AES-c/aes.c"
"${SWA_TOOLS_ROOT}/ShaderRecomp/thirdparty/smol-v/source/smolv.cpp"
)
set(SWA_THIRDPARTY_INCLUDES
"${SWA_THIRDPARTY_ROOT}/concurrentqueue"
"${SWA_THIRDPARTY_ROOT}/ddspp"
"${SWA_THIRDPARTY_ROOT}/imgui"
"${SWA_THIRDPARTY_ROOT}/libmspack/libmspack/mspack"
"${SWA_THIRDPARTY_ROOT}/magic_enum/include"
"${SWA_THIRDPARTY_ROOT}/miniaudio"
"${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 (SWA_D3D12)
list(APPEND SWA_GPU_CXX_SOURCES
"gpu/rhi/plume_d3d12.cpp"
)
endif()
set(SWA_APU_CXX_SOURCES
"apu/audio.cpp"
"apu/embedded_player.cpp"
)
if (SWA_XAUDIO2)
list(APPEND SWA_APU_CXX_SOURCES "apu/driver/xaudio_driver.cpp")
else()
list(APPEND SWA_APU_CXX_SOURCES "apu/driver/miniaudio_driver.cpp")
endif()
set(SWA_HID_CXX_SOURCES
"hid/hid.cpp"
"hid/driver/sdl_hid.cpp"
)
set(SWA_PATCHES_CXX_SOURCES
"patches/ui/CHudPause_patches.cpp"
"patches/ui/CTitleStateIntro_patches.cpp"
"patches/ui/CTitleStateMenu_patches.cpp"
"patches/ui/frontend_listener.cpp"
"patches/audio_patches.cpp"
"patches/camera_patches.cpp"
"patches/fps_patches.cpp"
"patches/misc_patches.cpp"
"patches/object_patches.cpp"
"patches/player_patches.cpp"
"patches/resident_patches.cpp"
"patches/video_patches.cpp"
)
set(SWA_UI_CXX_SOURCES
"ui/achievement_menu.cpp"
"ui/achievement_overlay.cpp"
"ui/installer_wizard.cpp"
"ui/button_guide.cpp"
"ui/fader.cpp"
"ui/message_window.cpp"
"ui/options_menu_thumbnails.cpp"
"ui/options_menu.cpp"
"ui/sdl_listener.cpp"
"ui/window.cpp"
)
set(SWA_INSTALL_CXX_SOURCES
"install/installer.cpp"
"install/iso_file_system.cpp"
"install/memory_mapped_file.cpp"
"install/xcontent_file_system.cpp"
"install/xex_patcher.cpp"
"install/hashes/apotos_shamar.cpp"
"install/hashes/chunnan.cpp"
"install/hashes/empire_city_adabat.cpp"
"install/hashes/game.cpp"
"install/hashes/holoska.cpp"
"install/hashes/mazuri.cpp"
"install/hashes/spagonia.cpp"
"install/hashes/update.cpp"
)
set(LIBMSPACK_PATH ${SWA_THIRDPARTY_ROOT}/libmspack/libmspack/mspack)
set(LIBMSPACK_C_SOURCES
${LIBMSPACK_PATH}/lzxd.c
)
set_source_files_properties(${LIBMSPACK_C_SOURCES} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
set(SMOLV_SOURCE_DIR "${SWA_TOOLS_ROOT}/ShaderRecomp/thirdparty/smol-v/source")
set(BC_DIFF_SOURCE_DIR "${SWA_TOOLS_ROOT}/bc_diff")
set(MINIAUDIO_INCLUDE_DIRS "${SWA_THIRDPARTY_ROOT}/miniaudio")
set(SWA_USER_CXX_SOURCES
"user/achievement_data.cpp"
"user/config.cpp"
"user/config_detail.cpp"
)
set(SWA_CXX_SOURCES
"app.cpp"
"exports.cpp"
"main.cpp"
"misc_impl.cpp"
"stdafx.cpp"
${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}
${LIBMSPACK_C_SOURCES}
"${SMOLV_SOURCE_DIR}/smolv.cpp"
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(${SWA_THIRDPARTY_SOURCES} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
set(SWA_CXX_SOURCES
"app.cpp"
"exports.cpp"
"main.cpp"
"misc_impl.cpp"
"stdafx.cpp"
${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}
)
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" "${CMAKE_BINARY_DIR}/res.rc" @ONLY)
add_executable(UnleashedRecomp ${SWA_CXX_SOURCES} "${CMAKE_BINARY_DIR}/res.rc")
else()
add_executable(UnleashedRecomp ${SWA_CXX_SOURCES})
endif()
set_target_properties(UnleashedRecomp PROPERTIES OUTPUT_NAME ${TARGET_NAME})
if (SWA_D3D12)
find_package(directx-headers CONFIG REQUIRED)
find_package(directx12-agility CONFIG REQUIRED)
find_package(d3d12-memory-allocator CONFIG REQUIRED)
target_compile_definitions(UnleashedRecomp PRIVATE SWA_D3D12)
endif()
find_package(SDL2 CONFIG REQUIRED)
find_package(unordered_dense CONFIG REQUIRED)
find_package(VulkanHeaders CONFIG)
find_package(volk CONFIG REQUIRED)
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
find_package(xxHash CONFIG REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus)
${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" "${CMAKE_BINARY_DIR}/res.rc" @ONLY)
add_executable(UnleashedRecomp ${SWA_CXX_SOURCES} "${CMAKE_BINARY_DIR}/res.rc")
else()
add_executable(UnleashedRecomp ${SWA_CXX_SOURCES})
endif()
set_target_properties(UnleashedRecomp PROPERTIES OUTPUT_NAME ${TARGET_NAME})
if (SWA_D3D12)
find_package(directx-headers CONFIG REQUIRED)
find_package(directx12-agility CONFIG REQUIRED)
target_compile_definitions(UnleashedRecomp PRIVATE SWA_D3D12)
endif()
find_package(directx-dxc REQUIRED)
find_package(zstd CONFIG REQUIRED)
find_package(Stb REQUIRED)
find_package(unofficial-concurrentqueue REQUIRED)
find_package(imgui CONFIG REQUIRED)
find_package(magic_enum CONFIG REQUIRED)
find_package(unofficial-tiny-aes-c CONFIG REQUIRED)
find_package(nfd CONFIG REQUIRED)
find_package(Vorbis CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)
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
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:Microsoft::DirectX12-Layers,IMPORTED_LOCATION_DEBUG> ${CMAKE_CURRENT_BINARY_DIR}/D3D12
COMMAND_EXPAND_LISTS
)
file(COPY ${PACKAGE_PREFIX_DIR}/bin/dxil.dll DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(UnleashedRecomp PRIVATE
Microsoft::DirectX-Headers
Microsoft::DirectX-Guids
Microsoft::DirectX12-Agility
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
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_PROPERTY:Microsoft::DirectX12-Layers,IMPORTED_LOCATION_DEBUG> ${CMAKE_CURRENT_BINARY_DIR}/D3D12
COMMAND_EXPAND_LISTS
)
file(COPY ${PACKAGE_PREFIX_DIR}/bin/dxil.dll DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(UnleashedRecomp PRIVATE
Microsoft::DirectX-Headers
Microsoft::DirectX-Guids
Microsoft::DirectX12-Agility
Microsoft::DirectXShaderCompiler
unofficial::D3D12MemoryAllocator
dxgi
)
endif()
if (WIN32)
target_link_libraries(UnleashedRecomp PRIVATE
comctl32
ntdll
winmm
Synchronization
)
endif()
target_link_libraries(UnleashedRecomp PRIVATE
Vulkan::Headers
volk::volk
volk::volk_headers
GPUOpen::VulkanMemoryAllocator
o1heap
PowerUtils
SDL2::SDL2-static
UnleashedRecompLib
unordered_dense::unordered_dense
xxHash::xxhash
PkgConfig::tomlplusplus
zstd::libzstd_static
unofficial::concurrentqueue::concurrentqueue
imgui::imgui
magic_enum::magic_enum
unofficial::tiny-aes-c::tiny-aes-c
nfd::nfd
msdf-atlas-gen::msdf-atlas-gen
Vorbis::vorbisfile
Microsoft::DXIL
dxgi
)
endif()
file(CHMOD ${DIRECTX_DXC_TOOL} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE)
if (WIN32)
target_link_libraries(UnleashedRecomp PRIVATE
comctl32
ntdll
winmm
Synchronization
)
endif()
target_link_libraries(UnleashedRecomp PRIVATE
fmt::fmt
)
target_include_directories(UnleashedRecomp PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/api
${SWA_THIRDPARTY_ROOT}/ddspp
${SWA_THIRDPARTY_ROOT}/TinySHA1
${LIBMSPACK_PATH}
${Stb_INCLUDE_DIR}
${SMOLV_SOURCE_DIR}
${MINIAUDIO_INCLUDE_DIRS}
${BC_DIFF_SOURCE_DIR}
)
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 (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
DEPENDS ${FILE_PATH}
)
target_sources(UnleashedRecomp PRIVATE ${FILE_PATH}.dxil.h)
endif()
add_custom_command(
OUTPUT ${FILE_PATH}.spirv.h
COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -spirv -fvk-use-dx-layout ${ARGN} -Fh ${FILE_PATH}.spirv.h ${FILE_PATH} -Vn g_${VARIABLE_NAME}_spirv
DEPENDS ${FILE_PATH}
)
target_sources(UnleashedRecomp PRIVATE ${FILE_PATH}.spirv.h)
endfunction()
function(compile_vertex_shader FILE_PATH)
compile_shader(${FILE_PATH} vs_6_0 -fvk-invert-y)
endfunction()
function(compile_pixel_shader FILE_PATH)
compile_shader(${FILE_PATH} ps_6_0)
endfunction()
compile_vertex_shader(copy_vs)
compile_pixel_shader(csd_filter_ps)
compile_pixel_shader(enhanced_motion_blur_ps)
compile_pixel_shader(gaussian_blur_3x3)
compile_pixel_shader(gaussian_blur_5x5)
compile_pixel_shader(gaussian_blur_7x7)
compile_pixel_shader(gaussian_blur_9x9)
compile_pixel_shader(gamma_correction_ps)
compile_pixel_shader(imgui_ps)
compile_vertex_shader(imgui_vs)
compile_pixel_shader(movie_ps)
compile_vertex_shader(movie_vs)
compile_pixel_shader(resolve_msaa_depth_2x)
compile_pixel_shader(resolve_msaa_depth_4x)
compile_pixel_shader(resolve_msaa_depth_8x)
function(generate_aggregate_header INPUT_DIRECTORY OUTPUT_FILE)
get_filename_component(ABS_OUTPUT_FILE "${OUTPUT_FILE}" ABSOLUTE)
file(GLOB_RECURSE HEADER_FILES "${INPUT_DIRECTORY}/*.h")
set(HEADER_CONTENT "#pragma once\n\n")
foreach(HEADER_FILE IN LISTS HEADER_FILES)
get_filename_component(ABS_HEADER_FILE "${HEADER_FILE}" ABSOLUTE)
if (ABS_HEADER_FILE STREQUAL ABS_OUTPUT_FILE)
continue()
endif()
file(RELATIVE_PATH RELATIVE_HEADER_FILE "${INPUT_DIRECTORY}" "${HEADER_FILE}")
string(APPEND HEADER_CONTENT "#include \"${RELATIVE_HEADER_FILE}\"\n")
endforeach()
if (EXISTS "${OUTPUT_FILE}")
file(READ "${OUTPUT_FILE}" EXISTING_CONTENT)
if (EXISTING_CONTENT STREQUAL HEADER_CONTENT)
return()
endif()
endif()
file(WRITE "${OUTPUT_FILE}" "${HEADER_CONTENT}")
endfunction()
generate_aggregate_header(
libzstd_static
msdf-atlas-gen::msdf-atlas-gen
nfd::nfd
o1heap
PowerUtils
SDL2::SDL2-static
tomlplusplus::tomlplusplus
UnleashedRecompLib
Vorbis::vorbisfile
xxHash::xxhash )
target_include_directories(UnleashedRecomp PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
"${CMAKE_CURRENT_SOURCE_DIR}/api"
"${CMAKE_CURRENT_SOURCE_DIR}/api/SWA.h"
)
set(RESOURCES_SOURCE_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources")
set(RESOURCES_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/res")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/bc_diff/button_bc_diff.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/bc_diff/button_bc_diff.bin" ARRAY_NAME "g_button_bc_diff" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/font/im_font_atlas.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/font/im_font_atlas.bin" ARRAY_NAME "g_im_font_atlas" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/font/im_font_atlas.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/font/im_font_atlas.dds" ARRAY_NAME "g_im_font_atlas_texture" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/achievements_menu/trophy.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/achievements_menu/trophy.dds" ARRAY_NAME "g_trophy" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/controller.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/controller.dds" ARRAY_NAME "g_controller" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/general_window.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/general_window.dds" ARRAY_NAME "g_general_window" COMPRESSION_TYPE "zstd")
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/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")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_003.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_003.dds" ARRAY_NAME "g_install_003" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_004.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_004.dds" ARRAY_NAME "g_install_004" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_005.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_005.dds" ARRAY_NAME "g_install_005" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_006.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_006.dds" ARRAY_NAME "g_install_006" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_007.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_007.dds" ARRAY_NAME "g_install_007" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_008.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_008.dds" ARRAY_NAME "g_install_008" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/miles_electric_icon.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/miles_electric_icon.dds" ARRAY_NAME "g_miles_electric_icon" COMPRESSION_TYPE "zstd")
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")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/brightness.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/brightness.dds" ARRAY_NAME "g_brightness" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/control_tutorial.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/control_tutorial.dds" ARRAY_NAME "g_control_tutorial" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/controller_icons.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/controller_icons.dds" ARRAY_NAME "g_controller_icons" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/default.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/default.dds" ARRAY_NAME "g_default" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/effects_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/effects_volume.dds" ARRAY_NAME "g_effects_volume" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/fps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/fps.dds" ARRAY_NAME "g_fps" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/fullscreen.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/fullscreen.dds" ARRAY_NAME "g_fullscreen" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bilinear.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bilinear.dds" ARRAY_NAME "g_gi_texture_filtering_bilinear" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bicubic.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bicubic.dds" ARRAY_NAME "g_gi_texture_filtering_bicubic" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/hints.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/hints.dds" ARRAY_NAME "g_hints" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/invert_camera_x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/invert_camera_x.dds" ARRAY_NAME "g_invert_camera_x" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/invert_camera_y.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/invert_camera_y.dds" ARRAY_NAME "g_invert_camera_y" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/language.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/language.dds" ARRAY_NAME "g_language" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/monitor.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/monitor.dds" ARRAY_NAME "g_monitor" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_off.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_off.dds" ARRAY_NAME "g_motion_blur_off" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_original.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_original.dds" ARRAY_NAME "g_motion_blur_original" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_enhanced.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_enhanced.dds" ARRAY_NAME "g_motion_blur_enhanced" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/movie_scale_mode.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/movie_scale_mode.dds" ARRAY_NAME "g_movie_scale_mode" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/music_attenuation.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/music_attenuation.dds" ARRAY_NAME "g_music_attenuation" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/music_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/music_volume.dds" ARRAY_NAME "g_music_volume" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/resolution_scale.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/resolution_scale.dds" ARRAY_NAME "g_resolution_scale" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_original.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_original.dds" ARRAY_NAME "g_shadow_resolution_original" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x512.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x512.dds" ARRAY_NAME "g_shadow_resolution_x512" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x1024.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x1024.dds" ARRAY_NAME "g_shadow_resolution_x1024" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x2048.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x2048.dds" ARRAY_NAME "g_shadow_resolution_x2048" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x4096.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x4096.dds" ARRAY_NAME "g_shadow_resolution_x4096" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x8192.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x8192.dds" ARRAY_NAME "g_shadow_resolution_x8192" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/subtitles.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/subtitles.dds" ARRAY_NAME "g_subtitles" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/time_of_day_transition_xbox.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/time_of_day_transition_xbox.dds" ARRAY_NAME "g_time_of_day_transition_xbox" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/time_of_day_transition_playstation.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/time_of_day_transition_playstation.dds" ARRAY_NAME "g_time_of_day_transition_playstation" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" ARRAY_NAME "g_transparency_antialiasing_false" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" ARRAY_NAME "g_transparency_antialiasing_true" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_scale_mode.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_scale_mode.dds" ARRAY_NAME "g_ui_scale_mode" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/voice_language.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/voice_language.dds" ARRAY_NAME "g_voice_language" 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_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/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")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_worldmap_cursor.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_worldmap_cursor.ogg" ARRAY_NAME "g_sys_worldmap_cursor")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_worldmap_finaldecide.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_worldmap_finaldecide.ogg" ARRAY_NAME "g_sys_worldmap_finaldecide")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausecansel.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausecansel.ogg" ARRAY_NAME "g_sys_actstg_pausecansel")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausecursor.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausecursor.ogg" ARRAY_NAME "g_sys_actstg_pausecursor")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausedecide.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausedecide.ogg" ARRAY_NAME "g_sys_actstg_pausedecide")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausewinclose.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausewinclose.ogg" ARRAY_NAME "g_sys_actstg_pausewinclose")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausewinopen.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausewinopen.ogg" ARRAY_NAME "g_sys_actstg_pausewinopen")
${SWA_THIRDPARTY_INCLUDES}
)
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
find_package(X11 REQUIRED)
target_include_directories(UnleashedRecomp PRIVATE ${X11_INCLUDE_DIR})
target_link_libraries(UnleashedRecomp PRIVATE ${X11_LIBRARIES})
endif()
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 (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
DEPENDS ${FILE_PATH}
)
target_sources(UnleashedRecomp PRIVATE ${FILE_PATH}.dxil.h)
endif()
add_custom_command(
OUTPUT ${FILE_PATH}.spirv.h
COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -spirv -fvk-use-dx-layout ${ARGN} -Fh ${FILE_PATH}.spirv.h ${FILE_PATH} -Vn g_${VARIABLE_NAME}_spirv
DEPENDS ${FILE_PATH}
)
target_sources(UnleashedRecomp PRIVATE ${FILE_PATH}.spirv.h)
endfunction()
function(compile_vertex_shader FILE_PATH)
compile_shader(${FILE_PATH} vs_6_0 -fvk-invert-y)
endfunction()
function(compile_pixel_shader FILE_PATH)
compile_shader(${FILE_PATH} ps_6_0)
endfunction()
compile_vertex_shader(copy_vs)
compile_pixel_shader(csd_filter_ps)
compile_pixel_shader(enhanced_motion_blur_ps)
compile_pixel_shader(gaussian_blur_3x3)
compile_pixel_shader(gaussian_blur_5x5)
compile_pixel_shader(gaussian_blur_7x7)
compile_pixel_shader(gaussian_blur_9x9)
compile_pixel_shader(gamma_correction_ps)
compile_pixel_shader(imgui_ps)
compile_vertex_shader(imgui_vs)
compile_pixel_shader(movie_ps)
compile_vertex_shader(movie_vs)
compile_pixel_shader(resolve_msaa_depth_2x)
compile_pixel_shader(resolve_msaa_depth_4x)
compile_pixel_shader(resolve_msaa_depth_8x)
function(generate_aggregate_header INPUT_DIRECTORY OUTPUT_FILE)
get_filename_component(ABS_OUTPUT_FILE "${OUTPUT_FILE}" ABSOLUTE)
file(GLOB_RECURSE HEADER_FILES "${INPUT_DIRECTORY}/*.h")
set(HEADER_CONTENT "#pragma once\n\n")
foreach(HEADER_FILE IN LISTS HEADER_FILES)
get_filename_component(ABS_HEADER_FILE "${HEADER_FILE}" ABSOLUTE)
if (ABS_HEADER_FILE STREQUAL ABS_OUTPUT_FILE)
continue()
endif()
file(RELATIVE_PATH RELATIVE_HEADER_FILE "${INPUT_DIRECTORY}" "${HEADER_FILE}")
string(APPEND HEADER_CONTENT "#include \"${RELATIVE_HEADER_FILE}\"\n")
endforeach()
if (EXISTS "${OUTPUT_FILE}")
file(READ "${OUTPUT_FILE}" EXISTING_CONTENT)
if (EXISTING_CONTENT STREQUAL HEADER_CONTENT)
return()
endif()
endif()
file(WRITE "${OUTPUT_FILE}" "${HEADER_CONTENT}")
endfunction()
generate_aggregate_header(
"${CMAKE_CURRENT_SOURCE_DIR}/api"
"${CMAKE_CURRENT_SOURCE_DIR}/api/SWA.h"
)
set(RESOURCES_SOURCE_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources")
set(RESOURCES_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/res")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/bc_diff/button_bc_diff.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/bc_diff/button_bc_diff.bin" ARRAY_NAME "g_button_bc_diff" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/font/im_font_atlas.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/font/im_font_atlas.bin" ARRAY_NAME "g_im_font_atlas" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/font/im_font_atlas.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/font/im_font_atlas.dds" ARRAY_NAME "g_im_font_atlas_texture" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/achievements_menu/trophy.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/achievements_menu/trophy.dds" ARRAY_NAME "g_trophy" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/controller.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/controller.dds" ARRAY_NAME "g_controller" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/general_window.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/general_window.dds" ARRAY_NAME "g_general_window" COMPRESSION_TYPE "zstd")
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/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")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_003.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_003.dds" ARRAY_NAME "g_install_003" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_004.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_004.dds" ARRAY_NAME "g_install_004" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_005.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_005.dds" ARRAY_NAME "g_install_005" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_006.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_006.dds" ARRAY_NAME "g_install_006" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_007.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_007.dds" ARRAY_NAME "g_install_007" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_008.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_008.dds" ARRAY_NAME "g_install_008" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/miles_electric_icon.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/miles_electric_icon.dds" ARRAY_NAME "g_miles_electric_icon" COMPRESSION_TYPE "zstd")
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")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/brightness.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/brightness.dds" ARRAY_NAME "g_brightness" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/control_tutorial.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/control_tutorial.dds" ARRAY_NAME "g_control_tutorial" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/controller_icons.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/controller_icons.dds" ARRAY_NAME "g_controller_icons" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/default.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/default.dds" ARRAY_NAME "g_default" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/effects_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/effects_volume.dds" ARRAY_NAME "g_effects_volume" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/fps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/fps.dds" ARRAY_NAME "g_fps" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/fullscreen.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/fullscreen.dds" ARRAY_NAME "g_fullscreen" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bilinear.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bilinear.dds" ARRAY_NAME "g_gi_texture_filtering_bilinear" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bicubic.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/gi_texture_filtering_bicubic.dds" ARRAY_NAME "g_gi_texture_filtering_bicubic" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/hints.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/hints.dds" ARRAY_NAME "g_hints" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/invert_camera_x.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/invert_camera_x.dds" ARRAY_NAME "g_invert_camera_x" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/invert_camera_y.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/invert_camera_y.dds" ARRAY_NAME "g_invert_camera_y" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/language.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/language.dds" ARRAY_NAME "g_language" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/monitor.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/monitor.dds" ARRAY_NAME "g_monitor" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_off.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_off.dds" ARRAY_NAME "g_motion_blur_off" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_original.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_original.dds" ARRAY_NAME "g_motion_blur_original" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/motion_blur_enhanced.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/motion_blur_enhanced.dds" ARRAY_NAME "g_motion_blur_enhanced" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/movie_scale_mode.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/movie_scale_mode.dds" ARRAY_NAME "g_movie_scale_mode" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/music_attenuation.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/music_attenuation.dds" ARRAY_NAME "g_music_attenuation" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/music_volume.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/music_volume.dds" ARRAY_NAME "g_music_volume" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/resolution_scale.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/resolution_scale.dds" ARRAY_NAME "g_resolution_scale" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_original.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_original.dds" ARRAY_NAME "g_shadow_resolution_original" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x512.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x512.dds" ARRAY_NAME "g_shadow_resolution_x512" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x1024.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x1024.dds" ARRAY_NAME "g_shadow_resolution_x1024" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x2048.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x2048.dds" ARRAY_NAME "g_shadow_resolution_x2048" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x4096.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x4096.dds" ARRAY_NAME "g_shadow_resolution_x4096" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/shadow_resolution_x8192.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/shadow_resolution_x8192.dds" ARRAY_NAME "g_shadow_resolution_x8192" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/subtitles.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/subtitles.dds" ARRAY_NAME "g_subtitles" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/time_of_day_transition_xbox.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/time_of_day_transition_xbox.dds" ARRAY_NAME "g_time_of_day_transition_xbox" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/time_of_day_transition_playstation.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/time_of_day_transition_playstation.dds" ARRAY_NAME "g_time_of_day_transition_playstation" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_false.dds" ARRAY_NAME "g_transparency_antialiasing_false" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/transparency_antialiasing_true.dds" ARRAY_NAME "g_transparency_antialiasing_true" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/ui_scale_mode.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/ui_scale_mode.dds" ARRAY_NAME "g_ui_scale_mode" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/voice_language.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/voice_language.dds" ARRAY_NAME "g_voice_language" 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_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/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")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_worldmap_cursor.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_worldmap_cursor.ogg" ARRAY_NAME "g_sys_worldmap_cursor")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_worldmap_finaldecide.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_worldmap_finaldecide.ogg" ARRAY_NAME "g_sys_worldmap_finaldecide")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausecansel.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausecansel.ogg" ARRAY_NAME "g_sys_actstg_pausecansel")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausecursor.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausecursor.ogg" ARRAY_NAME "g_sys_actstg_pausecursor")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausedecide.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausedecide.ogg" ARRAY_NAME "g_sys_actstg_pausedecide")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausewinclose.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausewinclose.ogg" ARRAY_NAME "g_sys_actstg_pausewinclose")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/sounds/sys_actstg_pausewinopen.ogg" DEST_FILE "${RESOURCES_OUTPUT_PATH}/sounds/sys_actstg_pausewinopen.ogg" ARRAY_NAME "g_sys_actstg_pausewinopen")

View file

@ -1,7 +1,7 @@
#include <app.h>
#include <install/installer.h>
#include <kernel/function.h>
#include <ui/window.h>
#include <ui/game_window.h>
#include <patches/audio_patches.h>
#include <user/config.h>
#include <os/process.h>
@ -15,10 +15,7 @@ void App::Restart(std::vector<std::string> restartArgs)
void App::Exit()
{
Config::Save();
#if _WIN32
ExitProcess(0);
#endif
std::_Exit(0);
}
// CApplication::Ctor
@ -41,7 +38,7 @@ PPC_FUNC(sub_822C1130)
SDL_PumpEvents();
SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
Window::Update();
GameWindow::Update();
AudioPatches::Update(App::s_deltaTime);
__imp__sub_822C1130(ctx, base);

View file

@ -1,6 +1,6 @@
#pragma once
#include <user/config_detail.h>
#include <user/config.h>
class App
{

View file

@ -14,7 +14,7 @@
std::ofstream g_audioDumpStream;
#endif
uint32_t XAudioRegisterRenderDriverClient(XLPDWORD callback, XLPDWORD driver)
uint32_t XAudioRegisterRenderDriverClient(be<uint32_t>* callback, be<uint32_t>* driver)
{
#ifdef AUDIO_DUMP_SAMPLES_PATH
g_audioDumpStream.open(AUDIO_DUMP_SAMPLES_PATH, std::ios::binary);
@ -25,7 +25,7 @@ uint32_t XAudioRegisterRenderDriverClient(XLPDWORD callback, XLPDWORD driver)
return 0;
}
uint32_t XAudioUnregisterRenderDriverClient(DWORD driver)
uint32_t XAudioUnregisterRenderDriverClient(uint32_t driver)
{
return 0;
}

View file

@ -13,6 +13,6 @@ void XAudioRegisterClient(PPCFunc* callback, uint32_t param);
void XAudioSubmitFrame(void* samples);
#endif
uint32_t XAudioRegisterRenderDriverClient(XLPDWORD callback, XLPDWORD driver);
uint32_t XAudioUnregisterRenderDriverClient(DWORD driver);
uint32_t XAudioRegisterRenderDriverClient(be<uint32_t>* callback, be<uint32_t>* driver);
uint32_t XAudioUnregisterRenderDriverClient(uint32_t driver);
uint32_t XAudioSubmitRenderDriverFrame(uint32_t driver, void* samples);

View file

@ -5,7 +5,7 @@
#include <kernel/heap.h>
static PPCFunc* g_clientCallback{};
static DWORD g_clientCallbackParam{}; // pointer in guest memory
static uint32_t g_clientCallbackParam{}; // pointer in guest memory
static ma_device g_audioDevice{};
static std::unique_ptr<GuestThreadContext> g_audioCtx;
static uint32_t* g_audioOutput;

View file

@ -9,7 +9,7 @@ CodeCache::CodeCache()
assert(bucket != nullptr);
#else
bucket = (char*)mmap(NULL, 0x200000000, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
assert(bucket != (char *)MAP_FAILED)
assert(bucket != (char*)MAP_FAILED);
#endif
}
@ -36,12 +36,12 @@ void CodeCache::Init()
}
}
void CodeCache::Insert(uint32_t guest, const void* host)
void CodeCache::Insert(uint32_t guest, PPCFunc* host)
{
#ifdef _WIN32
VirtualAlloc(bucket + static_cast<uint64_t>(guest) * 2, sizeof(void*), MEM_COMMIT, PAGE_READWRITE);
#endif
*reinterpret_cast<const void**>(bucket + static_cast<uint64_t>(guest) * 2) = host;
*reinterpret_cast<PPCFunc**>(bucket + static_cast<uint64_t>(guest) * 2) = host;
}
void* CodeCache::Find(uint32_t guest) const
@ -56,5 +56,5 @@ SWA_API PPCFunc* KeFindHostFunction(uint32_t guest)
SWA_API void KeInsertHostFunction(uint32_t guest, PPCFunc* function)
{
g_codeCache.Insert(guest, (const void*)function);
g_codeCache.Insert(guest, function);
}

View file

@ -8,7 +8,7 @@ struct CodeCache
~CodeCache();
void Init();
void Insert(uint32_t guest, const void* host);
void Insert(uint32_t guest, PPCFunc* host);
void* Find(uint32_t guest) const;
};

View file

@ -4,7 +4,7 @@
#include <kernel/memory.h>
#include <cpu/guest_stack_var.h>
#include <ui/installer_wizard.h>
#include <ui/window.h>
#include <ui/game_window.h>
#include <api/boost/smart_ptr/shared_ptr.h>
SWA_API void Game_PlaySound(const char* pName)
@ -31,5 +31,5 @@ SWA_API void Game_PlaySound(const char* pName)
SWA_API void Window_SetFullscreen(bool isEnabled)
{
Window::SetFullscreen(isEnabled);
GameWindow::SetFullscreen(isEnabled);
}

View file

@ -4,8 +4,9 @@
#define SWA_DLLEXPORT __declspec(dllexport)
#define SWA_DLLIMPORT __declspec(dllimport)
#else
#define SWA_DLLEXPORT __attribute__((dllexport))
#define SWA_DLLIMPORT __attribute__((dllimport))
// TODO
#define SWA_DLLEXPORT
#define SWA_DLLIMPORT
#endif
#ifdef SWA_IMPL
@ -33,19 +34,6 @@ inline T RoundDown(const T& in_rValue, uint32_t in_round)
return in_rValue & ~(in_round - 1);
}
inline bool FileExists(const char* path)
{
const auto attributes = GetFileAttributesA(path);
return attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY);
}
inline bool DirectoryExists(const char* path)
{
const auto attributes = GetFileAttributesA(path);
return attributes != INVALID_FILE_ATTRIBUTES && !!(attributes & FILE_ATTRIBUTE_DIRECTORY);
}
inline size_t StringHash(const std::string_view& str)
{
return XXH3_64bits(str.data(), str.size());

View file

@ -196,7 +196,7 @@ void ImFontAtlasSnapshot::GenerateGlyphRanges()
{
std::vector<std::string_view> localeStrings;
for (auto& config : Config::Definitions)
for (auto& config : g_configDefinitions)
config->GetLocaleStrings(localeStrings);
std::set<ImWchar> glyphs;

View file

@ -22,9 +22,18 @@
#define VK_USE_PLATFORM_XLIB_KHR
#endif
#include "volk.h"
#include <volk.h>
#include "vk_mem_alloc.h"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnullability-completeness"
#endif
#include <vk_mem_alloc.h>
#ifdef __clang__
#pragma clang diagnostic pop
#endif
namespace plume {
struct VulkanCommandQueue;

View file

@ -26,12 +26,12 @@
#include <ui/message_window.h>
#include <ui/options_menu.h>
#include <ui/sdl_listener.h>
#include <ui/window.h>
#include <ui/game_window.h>
#include <user/config.h>
#include <xxHashMap.h>
#if defined(ASYNC_PSO_DEBUG) || defined(PSO_CACHING)
#include <magic_enum.hpp>
#include <magic_enum/magic_enum.hpp>
#endif
#include "../../tools/ShaderRecomp/ShaderRecomp/shader_common.h"
@ -70,11 +70,13 @@
#include "shader/resolve_msaa_depth_4x.hlsl.spirv.h"
#include "shader/resolve_msaa_depth_8x.hlsl.spirv.h"
#ifdef _WIN32
extern "C"
{
__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}
#endif
namespace plume
{
@ -171,7 +173,7 @@ struct DirtyStates
static DirtyStates g_dirtyStates(true);
template<typename T>
static FORCEINLINE void SetDirtyValue(bool& dirtyState, T& dest, const T& src)
static void SetDirtyValue(bool& dirtyState, T& dest, const T& src)
{
if (dest != src)
{
@ -556,7 +558,7 @@ static void DestructTempResources()
g_tempBuffers[g_frame].clear();
}
static uint32_t g_mainThreadId;
static std::thread::id g_mainThreadId;
static ankerl::unordered_dense::map<RenderTexture*, RenderTextureLayout> g_barrierMap;
@ -1039,7 +1041,7 @@ static void ProcSetRenderState(const RenderCommand& cmd)
}
}
static const std::pair<GuestRenderState, void*> g_setRenderStateFunctions[] =
static const std::pair<GuestRenderState, PPCFunc*> g_setRenderStateFunctions[] =
{
{ D3DRS_ZENABLE, HostToGuestFunction<SetRenderState<D3DRS_ZENABLE>> },
{ D3DRS_ZWRITEENABLE, HostToGuestFunction<SetRenderState<D3DRS_ZWRITEENABLE>> },
@ -1094,11 +1096,13 @@ static std::unique_ptr<GuestShader> g_enhancedMotionBlurShader;
#endif
#ifdef _WIN32
static bool DetectWine()
{
HMODULE dllHandle = GetModuleHandle("ntdll.dll");
return dllHandle != nullptr && GetProcAddress(dllHandle, "wine_get_version") != nullptr;
}
#endif
static constexpr size_t TEXTURE_DESCRIPTOR_SIZE = 65536;
static constexpr size_t SAMPLER_DESCRIPTOR_SIZE = 1024;
@ -1161,7 +1165,7 @@ static void CreateImGuiBackend()
OptionsMenu::Init();
InstallerWizard::Init();
ImGui_ImplSDL2_InitForOther(Window::s_pWindow);
ImGui_ImplSDL2_InitForOther(GameWindow::s_pWindow);
#ifdef ENABLE_IM_FONT_ATLAS_SNAPSHOT
g_imFontTexture = LoadTexture(
@ -1311,7 +1315,7 @@ void Video::CreateHostDevice()
IMGUI_CHECKVERSION();
ImGui::CreateContext();
Window::Init();
GameWindow::Init();
#ifdef SWA_D3D12
g_vulkan = DetectWine() || Config::GraphicsAPI == EGraphicsAPI::Vulkan;
@ -1356,7 +1360,7 @@ void Video::CreateHostDevice()
break;
}
g_swapChain = g_queue->createSwapChain(Window::s_handle, bufferCount, BACKBUFFER_FORMAT);
g_swapChain = g_queue->createSwapChain(GameWindow::s_renderWindow, bufferCount, BACKBUFFER_FORMAT);
g_swapChain->setVsyncEnabled(Config::VSync);
g_swapChainValid = !g_swapChain->needsResize();
@ -1366,7 +1370,7 @@ void Video::CreateHostDevice()
for (auto& renderSemaphore : g_renderSemaphores)
renderSemaphore = g_device->createCommandSemaphore();
g_mainThreadId = GetCurrentThreadId();
g_mainThreadId = std::this_thread::get_id();
RenderPipelineLayoutBuilder pipelineLayoutBuilder;
pipelineLayoutBuilder.begin(false, true);
@ -1658,9 +1662,9 @@ static uint32_t CreateDevice(uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
memset(device, 0, sizeof(*device));
uint32_t functionOffset = 0x443344; // D3D
g_codeCache.Insert(functionOffset, reinterpret_cast<void*>(HostToGuestFunction<SetRenderStateUnimplemented>));
g_codeCache.Insert(functionOffset, HostToGuestFunction<SetRenderStateUnimplemented>);
for (size_t i = 0; i < _countof(device->setRenderStateFunctions); i++)
for (size_t i = 0; i < std::size(device->setRenderStateFunctions); i++)
device->setRenderStateFunctions[i] = functionOffset;
for (auto& [state, function] : g_setRenderStateFunctions)
@ -1670,7 +1674,7 @@ static uint32_t CreateDevice(uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4,
device->setRenderStateFunctions[state / 4] = functionOffset;
}
for (size_t i = 0; i < _countof(device->setSamplerStateFunctions); i++)
for (size_t i = 0; i < std::size(device->setSamplerStateFunctions); i++)
device->setSamplerStateFunctions[i] = *reinterpret_cast<uint32_t*>(g_memory.Translate(0x8330F3DC + i * 0xC));
device->viewport.width = 1280.0f;
@ -1795,7 +1799,7 @@ static void UnlockBuffer(GuestBuffer* buffer)
{
if (!buffer->lockedReadOnly)
{
if (GetCurrentThreadId() == g_mainThreadId)
if (std::this_thread::get_id() == g_mainThreadId)
{
RenderCommand cmd;
cmd.type = (sizeof(T) == 2) ? RenderCommandType::UnlockBuffer16 : RenderCommandType::UnlockBuffer32;

View file

@ -2,7 +2,8 @@
#include <SDL.h>
#include <user/config.h>
#include <hid/hid_detail.h>
#include <ui/window.h>
#include <ui/game_window.h>
#include <kernel/xdm.h>
#define TRANSLATE_INPUT(S, X) SDL_GameControllerGetButton(controller, S) << FirstBitLow(X)
#define VIBRATION_TIMEOUT_MS 5000
@ -65,7 +66,7 @@ public:
bool CanPoll()
{
return controller && (Window::s_isFocused || Config::AllowBackgroundInput);
return controller && (GameWindow::s_isFocused || Config::AllowBackgroundInput);
}
void PollAxis()
@ -128,7 +129,7 @@ public:
std::array<Controller, 4> g_controllers;
Controller* g_activeController;
inline Controller* EnsureController(DWORD dwUserIndex)
inline Controller* EnsureController(uint32_t dwUserIndex)
{
if (!g_controllers[dwUserIndex].controller)
return nullptr;
@ -260,7 +261,7 @@ void hid::detail::Init()
uint32_t hid::detail::GetState(uint32_t dwUserIndex, XAMINPUT_STATE* pState)
{
static DWORD packet;
static uint32_t packet;
if (!pState)
return ERROR_BAD_ARGUMENTS;

View file

@ -97,7 +97,7 @@ bool MemoryMappedFile::open(const std::filesystem::path &path)
if (fileSize == (off_t)(-1))
{
fprintf(stderr, "lseek failed with error %s.\n", strerror(errno));
close(fileHandle);
::close(fileHandle);
fileHandle = -1;
return false;
}
@ -106,7 +106,7 @@ bool MemoryMappedFile::open(const std::filesystem::path &path)
if (fileView == MAP_FAILED)
{
fprintf(stderr, "mmap failed with error %s.\n", strerror(errno));
close(fileHandle);
::close(fileHandle);
fileHandle = -1;
return false;
}
@ -140,7 +140,7 @@ void MemoryMappedFile::close()
if (fileHandle != -1)
{
close(fileHandle);
::close(fileHandle);
}
#endif
}

View file

@ -308,14 +308,14 @@ inline bool bitScanForward(uint64_t v, uint32_t *outFirstSetIndex)
inline bool bitScanForward(uint32_t v, uint32_t *outFirstSetIndex)
{
int i = ffs(v);
*out_first_set_index = i - 1;
*outFirstSetIndex = i - 1;
return i != 0;
}
inline bool bitScanForward(uint64_t v, uint32_t *outFirstSetIndex)
{
int i = __builtin_ffsll(v);
*out_first_set_index = i - 1;
*outFirstSetIndex = i - 1;
return i != 0;
}
#endif

View file

@ -39,7 +39,7 @@ std::enable_if_t<(I < sizeof...(TArgs)), void> _tuple_for(std::tuple<TArgs...>&
struct ArgTranslator
{
FORCEINLINE constexpr static uint64_t GetIntegerArgumentValue(const PPCContext& ctx, uint8_t* base, size_t arg) noexcept
constexpr static uint64_t GetIntegerArgumentValue(const PPCContext& ctx, uint8_t* base, size_t arg) noexcept
{
if (arg <= 7)
{
@ -57,10 +57,10 @@ struct ArgTranslator
}
}
return *reinterpret_cast<XLPDWORD>(base + ctx.r1.u32 + 0x54 + ((arg - 8) * 8));
return *reinterpret_cast<be<uint32_t>*>(base + ctx.r1.u32 + 0x54 + ((arg - 8) * 8));
}
FORCEINLINE static double GetPrecisionArgumentValue(const PPCContext& ctx, uint8_t* base, size_t arg) noexcept
static double GetPrecisionArgumentValue(const PPCContext& ctx, uint8_t* base, size_t arg) noexcept
{
switch (arg)
{
@ -84,7 +84,7 @@ struct ArgTranslator
return 0;
}
FORCEINLINE constexpr static void SetIntegerArgumentValue(PPCContext& ctx, uint8_t* base, size_t arg, uint64_t value) noexcept
constexpr static void SetIntegerArgumentValue(PPCContext& ctx, uint8_t* base, size_t arg, uint64_t value) noexcept
{
if (arg <= 7)
{
@ -105,7 +105,7 @@ struct ArgTranslator
assert(arg < 7 && "Pushing to stack memory is not yet supported.");
}
FORCEINLINE static void SetPrecisionArgumentValue(PPCContext& ctx, uint8_t* base, size_t arg, double value) noexcept
static void SetPrecisionArgumentValue(PPCContext& ctx, uint8_t* base, size_t arg, double value) noexcept
{
switch (arg)
{
@ -129,7 +129,7 @@ struct ArgTranslator
}
template<typename T>
FORCEINLINE constexpr static std::enable_if_t<!std::is_pointer_v<T>, T> GetValue(PPCContext& ctx, uint8_t* base, size_t idx) noexcept
constexpr static std::enable_if_t<!std::is_pointer_v<T>, T> GetValue(PPCContext& ctx, uint8_t* base, size_t idx) noexcept
{
if constexpr (is_precise_v<T>)
{
@ -142,7 +142,7 @@ struct ArgTranslator
}
template<typename T>
FORCEINLINE constexpr static std::enable_if_t<std::is_pointer_v<T>, T> GetValue(PPCContext& ctx, uint8_t* base, size_t idx) noexcept
constexpr static std::enable_if_t<std::is_pointer_v<T>, T> GetValue(PPCContext& ctx, uint8_t* base, size_t idx) noexcept
{
const auto v = GetIntegerArgumentValue(ctx, base, idx);
if (!v)
@ -154,7 +154,7 @@ struct ArgTranslator
}
template<typename T>
FORCEINLINE constexpr static std::enable_if_t<!std::is_pointer_v<T>, void> SetValue(PPCContext& ctx, uint8_t* base, size_t idx, T value) noexcept
constexpr static std::enable_if_t<!std::is_pointer_v<T>, void> SetValue(PPCContext& ctx, uint8_t* base, size_t idx, T value) noexcept
{
if constexpr (is_precise_v<T>)
{
@ -175,7 +175,7 @@ struct ArgTranslator
}
template<typename T>
FORCEINLINE constexpr static std::enable_if_t<std::is_pointer_v<T>, void> SetValue(PPCContext& ctx, uint8_t* base, size_t idx, T value) noexcept
constexpr static std::enable_if_t<std::is_pointer_v<T>, void> SetValue(PPCContext& ctx, uint8_t* base, size_t idx, T value) noexcept
{
const auto v = g_memory.MapVirtual((void*)value);
if (!v)
@ -240,13 +240,13 @@ struct arg_ordinal_t
};
template<auto Func, int I = 0, typename ...TArgs>
FORCEINLINE void _translate_args_to_host(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>&) noexcept
void _translate_args_to_host(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>&) noexcept
requires (I >= sizeof...(TArgs))
{
}
template <auto Func, int I = 0, typename ...TArgs>
FORCEINLINE std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args_to_host(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>& tpl) noexcept
std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args_to_host(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>& tpl) noexcept
{
using T = std::tuple_element_t<I, std::remove_reference_t<decltype(tpl)>>;
std::get<I>(tpl) = ArgTranslator::GetValue<T>(ctx, base, arg_ordinal_t<Func, I>::value);
@ -255,13 +255,13 @@ FORCEINLINE std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args_to_ho
}
template<int I = 0, typename ...TArgs>
FORCEINLINE void _translate_args_to_guest(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>&) noexcept
void _translate_args_to_guest(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>&) noexcept
requires (I >= sizeof...(TArgs))
{
}
template <int I = 0, typename ...TArgs>
FORCEINLINE std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args_to_guest(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>& tpl) noexcept
std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args_to_guest(PPCContext& ctx, uint8_t* base, std::tuple<TArgs...>& tpl) noexcept
{
using T = std::tuple_element_t<I, std::remove_reference_t<decltype(tpl)>>;
ArgTranslator::SetValue<T>(ctx, base, GatherFunctionArguments(std::tuple<TArgs...>{})[I].ordinal, std::get<I>(tpl));
@ -270,7 +270,7 @@ FORCEINLINE std::enable_if_t<(I < sizeof...(TArgs)), void> _translate_args_to_gu
}
template<auto Func>
FORCEINLINE PPC_FUNC(HostToGuestFunction)
PPC_FUNC(HostToGuestFunction)
{
using ret_t = decltype(std::apply(Func, function_args(Func)));
@ -293,7 +293,7 @@ FORCEINLINE PPC_FUNC(HostToGuestFunction)
}
else
{
ctx.r3.u64 = NULL;
ctx.r3.u64 = 0;
}
}
else if constexpr (is_precise_v<ret_t>)
@ -308,7 +308,7 @@ FORCEINLINE PPC_FUNC(HostToGuestFunction)
}
template<typename T, typename TFunction, typename... TArgs>
FORCEINLINE T GuestToHostFunction(const TFunction& func, TArgs&&... argv)
T GuestToHostFunction(const TFunction& func, TArgs&&... argv)
{
auto args = std::make_tuple(std::forward<TArgs>(argv)...);
auto& currentCtx = *GetPPCContext();
@ -331,11 +331,7 @@ FORCEINLINE T GuestToHostFunction(const TFunction& func, TArgs&&... argv)
currentCtx.fpscr = newCtx.fpscr;
SetPPCContext(currentCtx);
if constexpr (std::is_void_v<T>)
{
return;
}
else if constexpr (std::is_pointer_v<T>)
if constexpr (std::is_pointer_v<T>)
{
return reinterpret_cast<T>((uint64_t)g_memory.Translate(newCtx.r3.u32));
}
@ -349,7 +345,7 @@ FORCEINLINE T GuestToHostFunction(const TFunction& func, TArgs&&... argv)
}
else
{
static_assert(false, "Unsupported return type.");
static_assert(std::is_void_v<T>, "Unsupported return type.");
}
}

View file

@ -103,7 +103,7 @@ uint32_t RtlSizeHeap(uint32_t heapHandle, uint32_t flags, uint32_t memoryPointer
return 0;
}
SWA_API uint32_t XAlloc(uint32_t size, uint32_t flags)
SWA_API uint32_t XAllocMem(uint32_t size, uint32_t flags)
{
void* ptr = (flags & 0x80000000) != 0 ?
g_userHeap.AllocPhysical(size, (1ull << ((flags >> 24) & 0xF))) :
@ -116,7 +116,7 @@ SWA_API uint32_t XAlloc(uint32_t size, uint32_t flags)
return g_memory.MapVirtual(ptr);
}
SWA_API void XFree(uint32_t baseAddress, uint32_t flags)
SWA_API void XFreeMem(uint32_t baseAddress, uint32_t flags)
{
if (baseAddress != NULL)
g_userHeap.Free(g_memory.Translate(baseAddress));
@ -130,6 +130,5 @@ GUEST_FUNCTION_HOOK(sub_82BD8600, RtlFreeHeap);
GUEST_FUNCTION_HOOK(sub_82BD88F0, RtlReAllocateHeap);
GUEST_FUNCTION_HOOK(sub_82BD6FD0, RtlSizeHeap);
// Seems like these handle allocation of virtual and physical pages
GUEST_FUNCTION_HOOK(sub_831CC9C8, XAlloc);
GUEST_FUNCTION_HOOK(sub_831CCA60, XFree);
GUEST_FUNCTION_HOOK(sub_831CC9C8, XAllocMem);
GUEST_FUNCTION_HOOK(sub_831CCA60, XFreeMem);

View file

@ -10,11 +10,12 @@
#include <memory>
#include "xam.h"
#include "xdm.h"
#include <timeapi.h>
#include <user/config.h>
#include <os/logger.h>
#ifdef _WIN32
#include <ntstatus.h>
#endif
struct Event final : KernelObject, HostObject<XKEVENT>
{
@ -149,7 +150,7 @@ inline void CloseKernelObject(XDISPATCHER_HEADER& header)
DestroyKernelObject(header.WaitListHead.Blink);
}
DWORD GuestTimeoutToMilliseconds(XLPQWORD timeout)
uint32_t GuestTimeoutToMilliseconds(be<int64_t>* timeout)
{
return timeout ? (*timeout * -1) / 10000 : INFINITE;
}
@ -207,7 +208,7 @@ uint32_t XGetGameRegion()
return 0x03FF;
}
uint32_t XMsgStartIORequest(DWORD App, DWORD Message, XXOVERLAPPED* lpOverlapped, void* Buffer, DWORD szBuffer)
uint32_t XMsgStartIORequest(uint32_t App, uint32_t Message, XXOVERLAPPED* lpOverlapped, void* Buffer, uint32_t szBuffer)
{
return STATUS_SUCCESS;
}
@ -227,8 +228,7 @@ void XamContentDelete()
LOG_UTILITY("!!! STUB !!!");
}
uint32_t XamContentGetCreator(DWORD userIndex, const XCONTENT_DATA* contentData, PBOOL isCreator, XLPQWORD xuid, XXOVERLAPPED* overlapped)
uint32_t XamContentGetCreator(uint32_t userIndex, const XCONTENT_DATA* contentData, be<uint32_t>* isCreator, be<uint64_t>* xuid, XXOVERLAPPED* overlapped)
{
if (isCreator)
*isCreator = true;
@ -269,7 +269,7 @@ uint32_t XamShowDeviceSelectorUI
uint32_t contentType,
uint32_t contentFlags,
uint64_t totalRequested,
XDWORD* deviceId,
be<uint32_t>* deviceId,
XXOVERLAPPED* overlapped
)
{
@ -337,10 +337,10 @@ void RtlInitAnsiString(XANSI_STRING* destination, char* source)
destination->Buffer = source;
}
DWORD NtCreateFile
uint32_t NtCreateFile
(
XLPDWORD FileHandle,
DWORD DesiredAccess,
be<uint32_t>* FileHandle,
uint32_t DesiredAccess,
XOBJECT_ATTRIBUTES* Attributes,
XIO_STATUS_BLOCK* IoStatusBlock,
uint64_t* AllocationSize,
@ -363,8 +363,11 @@ uint32_t NtClose(uint32_t handle)
DestroyKernelObject(handle);
return 0;
}
return CloseHandle((HANDLE)handle) ? 0 : 0xFFFFFFFF;
else
{
assert(false && "Unrecognized kernel object.");
return 0xFFFFFFFF;
}
}
void NtSetInformationFile()
@ -377,7 +380,7 @@ uint32_t FscSetCacheElementCount()
return 0;
}
DWORD NtWaitForSingleObjectEx(DWORD Handle, DWORD WaitMode, DWORD Alertable, XLPQWORD Timeout)
uint32_t NtWaitForSingleObjectEx(uint32_t Handle, uint32_t WaitMode, uint32_t Alertable, be<int64_t>* Timeout)
{
uint32_t timeout = GuestTimeoutToMilliseconds(Timeout);
assert(timeout == 0 || timeout == INFINITE);
@ -404,7 +407,7 @@ void vsprintf_x()
LOG_UTILITY("!!! STUB !!!");
}
uint32_t ExGetXConfigSetting(uint16_t Category, uint16_t Setting, void* Buffer, uint16_t SizeOfBuffer, XLPDWORD RequiredSize)
uint32_t ExGetXConfigSetting(uint16_t Category, uint16_t Setting, void* Buffer, uint16_t SizeOfBuffer, be<uint32_t>* RequiredSize)
{
uint32_t data[4]{};
@ -517,9 +520,9 @@ void XexGetModuleSection()
LOG_UTILITY("!!! STUB !!!");
}
NTSTATUS RtlUnicodeToMultiByteN(PCHAR MultiByteString, DWORD MaxBytesInMultiByteString, XLPDWORD BytesInMultiByteString, PCWCH UnicodeString, ULONG BytesInUnicodeString)
uint32_t RtlUnicodeToMultiByteN(char* MultiByteString, uint32_t MaxBytesInMultiByteString, be<uint32_t>* BytesInMultiByteString, const be<uint16_t>* UnicodeString, uint32_t BytesInUnicodeString)
{
const auto reqSize = BytesInUnicodeString / sizeof(wchar_t);
const auto reqSize = BytesInUnicodeString / sizeof(uint16_t);
if (BytesInMultiByteString)
*BytesInMultiByteString = reqSize;
@ -529,7 +532,7 @@ NTSTATUS RtlUnicodeToMultiByteN(PCHAR MultiByteString, DWORD MaxBytesInMultiByte
for (size_t i = 0; i < reqSize; i++)
{
const auto c = ByteSwap(UnicodeString[i]);
const auto c = UnicodeString[i].get();
MultiByteString[i] = c < 256 ? c : '?';
}
@ -537,7 +540,7 @@ NTSTATUS RtlUnicodeToMultiByteN(PCHAR MultiByteString, DWORD MaxBytesInMultiByte
return STATUS_SUCCESS;
}
DWORD KeDelayExecutionThread(DWORD WaitMode, bool Alertable, XLPQWORD Timeout)
uint32_t KeDelayExecutionThread(uint32_t WaitMode, bool Alertable, be<int64_t>* Timeout)
{
// We don't do async file reads.
if (Alertable)
@ -614,7 +617,7 @@ void KeSetBasePriorityThread(GuestThreadHandle* hThread, int priority)
#endif
}
uint32_t ObReferenceObjectByHandle(uint32_t handle, uint32_t objectType, XLPDWORD object)
uint32_t ObReferenceObjectByHandle(uint32_t handle, uint32_t objectType, be<uint32_t>* object)
{
*object = handle;
return 0;
@ -635,7 +638,7 @@ uint32_t NtSuspendThread(GuestThreadHandle* hThread, uint32_t* suspendCount)
return S_OK;
}
uint32_t KeSetAffinityThread(DWORD Thread, DWORD Affinity, XLPDWORD lpPreviousAffinity)
uint32_t KeSetAffinityThread(uint32_t Thread, uint32_t Affinity, be<uint32_t>* lpPreviousAffinity)
{
if (lpPreviousAffinity)
*lpPreviousAffinity = 2;
@ -693,7 +696,7 @@ void RtlFillMemoryUlong()
void KeBugCheckEx()
{
__debugbreak();
__builtin_debugtrap();
}
uint32_t KeGetCurrentProcessType()
@ -949,7 +952,7 @@ void VdEnableDisableClockGating()
void KeBugCheck()
{
__debugbreak();
__builtin_debugtrap();
}
void KeLockL2()
@ -962,7 +965,7 @@ void KeUnlockL2()
LOG_UTILITY("!!! STUB !!!");
}
bool KeSetEvent(XKEVENT* pEvent, DWORD Increment, bool Wait)
bool KeSetEvent(XKEVENT* pEvent, uint32_t Increment, bool Wait)
{
bool result = QueryKernelObject<Event>(*pEvent)->Set();
@ -977,7 +980,7 @@ bool KeResetEvent(XKEVENT* pEvent)
return QueryKernelObject<Event>(*pEvent)->Reset();
}
DWORD KeWaitForSingleObject(XDISPATCHER_HEADER* Object, DWORD WaitReason, DWORD WaitMode, bool Alertable, XLPQWORD Timeout)
uint32_t KeWaitForSingleObject(XDISPATCHER_HEADER* Object, uint32_t WaitReason, uint32_t WaitMode, bool Alertable, be<int64_t>* Timeout)
{
const uint32_t timeout = GuestTimeoutToMilliseconds(Timeout);
assert(timeout == INFINITE);
@ -1019,18 +1022,18 @@ static uint32_t& KeTlsGetValueRef(size_t index)
return s_tlsValues[index];
}
uint32_t KeTlsGetValue(DWORD dwTlsIndex)
uint32_t KeTlsGetValue(uint32_t dwTlsIndex)
{
return KeTlsGetValueRef(dwTlsIndex);
}
BOOL KeTlsSetValue(DWORD dwTlsIndex, DWORD lpTlsValue)
uint32_t KeTlsSetValue(uint32_t dwTlsIndex, uint32_t lpTlsValue)
{
KeTlsGetValueRef(dwTlsIndex) = lpTlsValue;
return TRUE;
}
DWORD KeTlsAlloc()
uint32_t KeTlsAlloc()
{
std::lock_guard<Mutex> lock(g_tlsAllocationMutex);
if (!g_tlsFreeIndices.empty())
@ -1043,14 +1046,14 @@ DWORD KeTlsAlloc()
return g_tlsNextIndex++;
}
BOOL KeTlsFree(DWORD dwTlsIndex)
uint32_t KeTlsFree(uint32_t dwTlsIndex)
{
std::lock_guard<Mutex> lock(g_tlsAllocationMutex);
g_tlsFreeIndices.push_back(dwTlsIndex);
return TRUE;
}
DWORD XMsgInProcessCall(uint32_t app, uint32_t message, XDWORD* param1, XDWORD* param2)
uint32_t XMsgInProcessCall(uint32_t app, uint32_t message, be<uint32_t>* param1, be<uint32_t>* param2)
{
if (message == 0x7001B)
{
@ -1070,7 +1073,7 @@ void XamUserReadProfileSettings
uint64_t* xuids,
uint32_t settingCount,
uint32_t* settingIds,
XDWORD* bufferSize,
be<uint32_t>* bufferSize,
void* buffer,
void* overlapped
)
@ -1251,19 +1254,15 @@ void NtQueryFullAttributesFile()
LOG_UTILITY("!!! STUB !!!");
}
NTSTATUS RtlMultiByteToUnicodeN(PWCH UnicodeString, ULONG MaxBytesInUnicodeString, XLPDWORD BytesInUnicodeString, const CHAR* MultiByteString, ULONG BytesInMultiByteString)
uint32_t RtlMultiByteToUnicodeN(be<uint16_t>* UnicodeString, uint32_t MaxBytesInUnicodeString, be<uint32_t>* BytesInUnicodeString, const char* MultiByteString, uint32_t BytesInMultiByteString)
{
// i am lazy
const auto n = MultiByteToWideChar(CP_UTF8, 0, MultiByteString, BytesInMultiByteString, UnicodeString, MaxBytesInUnicodeString);
uint32_t length = std::min(MaxBytesInUnicodeString / 2, BytesInMultiByteString);
if (BytesInUnicodeString)
*BytesInUnicodeString = n * sizeof(wchar_t);
for (size_t i = 0; i < length; i++)
UnicodeString[i] = MultiByteString[i];
if (n)
{
for (size_t i = 0; i < n; i++)
UnicodeString[i] = ByteSwap(UnicodeString[i]);
}
if (BytesInUnicodeString != nullptr)
*BytesInUnicodeString = length * 2;
return STATUS_SUCCESS;
}
@ -1300,13 +1299,13 @@ uint32_t NtSetEvent(Event* handle, uint32_t* previousState)
return 0;
}
NTSTATUS NtCreateSemaphore(XLPDWORD Handle, XOBJECT_ATTRIBUTES* ObjectAttributes, DWORD InitialCount, DWORD MaximumCount)
uint32_t NtCreateSemaphore(be<uint32_t>* Handle, XOBJECT_ATTRIBUTES* ObjectAttributes, uint32_t InitialCount, uint32_t MaximumCount)
{
*Handle = GetKernelHandle(CreateKernelObject<Semaphore>(InitialCount, MaximumCount));
return STATUS_SUCCESS;
}
NTSTATUS NtReleaseSemaphore(Semaphore* Handle, DWORD ReleaseCount, LONG* PreviousCount)
uint32_t NtReleaseSemaphore(Semaphore* Handle, uint32_t ReleaseCount, int32_t* PreviousCount)
{
uint32_t previousCount;
Handle->Release(ReleaseCount, &previousCount);
@ -1347,11 +1346,17 @@ void NtFlushBuffersFile()
LOG_UTILITY("!!! STUB !!!");
}
void KeQuerySystemTime(uint64_t* time)
void KeQuerySystemTime(be<uint64_t>* time)
{
FILETIME t;
GetSystemTimeAsFileTime(&t);
*time = ByteSwap((uint64_t(t.dwHighDateTime) << 32) | t.dwLowDateTime);
constexpr int64_t FILETIME_EPOCH_DIFFERENCE = 116444736000000000LL;
auto now = std::chrono::system_clock::now();
auto timeSinceEpoch = now.time_since_epoch();
int64_t currentTime100ns = std::chrono::duration_cast<std::chrono::duration<int64_t, std::ratio<1, 10000000>>>(timeSinceEpoch).count();
currentTime100ns += FILETIME_EPOCH_DIFFERENCE;
*time = ((currentTime100ns & 0xFFFFFFFF) << 32) | (currentTime100ns & 0xFFFFFFFF);
}
void RtlTimeToTimeFields()
@ -1379,7 +1384,7 @@ void ExTerminateThread()
LOG_UTILITY("!!! STUB !!!");
}
uint32_t ExCreateThread(XLPDWORD handle, uint32_t stackSize, XLPDWORD threadId, uint32_t xApiThreadStartup, uint32_t startAddress, uint32_t startContext, uint32_t creationFlags)
uint32_t ExCreateThread(be<uint32_t>* handle, uint32_t stackSize, be<uint32_t>* threadId, uint32_t xApiThreadStartup, uint32_t startAddress, uint32_t startContext, uint32_t creationFlags)
{
LOGF_UTILITY("0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}",
(intptr_t)handle, stackSize, (intptr_t)threadId, xApiThreadStartup, startAddress, startContext, creationFlags);
@ -1464,7 +1469,7 @@ void NetDll_XNetGetTitleXnAddr()
LOG_UTILITY("!!! STUB !!!");
}
DWORD KeWaitForMultipleObjects(DWORD Count, xpointer<XDISPATCHER_HEADER>* Objects, DWORD WaitType, DWORD WaitReason, DWORD WaitMode, DWORD Alertable, XLPQWORD Timeout)
uint32_t KeWaitForMultipleObjects(uint32_t Count, xpointer<XDISPATCHER_HEADER>* Objects, uint32_t WaitType, uint32_t WaitReason, uint32_t WaitMode, uint32_t Alertable, be<int64_t>* Timeout)
{
// FIXME: This function is only accounting for events.
@ -1492,7 +1497,7 @@ DWORD KeWaitForMultipleObjects(DWORD Count, xpointer<XDISPATCHER_HEADER>* Object
{
if (s_events[i]->Wait(0) == STATUS_SUCCESS)
{
return WAIT_OBJECT_0 + i;
return STATUS_WAIT_0 + i;
}
}
@ -1522,7 +1527,7 @@ void XAudioGetVoiceCategoryVolume()
LOG_UTILITY("!!! STUB !!!");
}
DWORD XAudioGetVoiceCategoryVolumeChangeMask(DWORD Driver, XLPDWORD Mask)
uint32_t XAudioGetVoiceCategoryVolumeChangeMask(uint32_t Driver, be<uint32_t>* Mask)
{
*Mask = 0;
return 0;
@ -1556,7 +1561,7 @@ void XMACreateContext()
LOG_UTILITY("!!! STUB !!!");
}
// uint32_t XAudioRegisterRenderDriverClient(XLPDWORD callback, XLPDWORD driver)
// uint32_t XAudioRegisterRenderDriverClient(be<uint32_t>* callback, be<uint32_t>* driver)
// {
// //printf("XAudioRegisterRenderDriverClient(): %x %x\n");
//

View file

@ -14,10 +14,11 @@ struct FileHandle : KernelObject
struct FindHandle : KernelObject
{
std::error_code ec;
std::filesystem::path searchPath;
std::filesystem::directory_iterator iterator;
void fillFindData(LPWIN32_FIND_DATAA lpFindFileData)
void fillFindData(WIN32_FIND_DATAA* lpFindFileData)
{
if (iterator->is_directory())
lpFindFileData->dwFileAttributes = ByteSwap(FILE_ATTRIBUTE_DIRECTORY);
@ -25,7 +26,7 @@ struct FindHandle : KernelObject
lpFindFileData->dwFileAttributes = ByteSwap(FILE_ATTRIBUTE_NORMAL);
std::u8string pathU8Str = iterator->path().lexically_relative(searchPath).u8string();
uint64_t fileSize = iterator->file_size();
uint64_t fileSize = iterator->file_size(ec);
strncpy(lpFindFileData->cFileName, (const char *)(pathU8Str.c_str()), sizeof(lpFindFileData->cFileName));
lpFindFileData->nFileSizeLow = ByteSwap(uint32_t(fileSize >> 32U));
lpFindFileData->nFileSizeHigh = ByteSwap(uint32_t(fileSize));
@ -37,12 +38,12 @@ struct FindHandle : KernelObject
SWA_API FileHandle* XCreateFileA
(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes
const char* lpFileName,
uint32_t dwDesiredAccess,
uint32_t dwShareMode,
void* lpSecurityAttributes,
uint32_t dwCreationDisposition,
uint32_t dwFlagsAndAttributes
)
{
assert(((dwDesiredAccess & ~(GENERIC_READ | GENERIC_WRITE | FILE_READ_DATA)) == 0) && "Unknown desired access bits.");
@ -77,7 +78,7 @@ SWA_API FileHandle* XCreateFileA
return fileHandle;
}
static DWORD XGetFileSizeA(FileHandle* hFile, LPDWORD lpFileSizeHigh)
static uint32_t XGetFileSizeA(FileHandle* hFile, be<uint32_t>* lpFileSizeHigh)
{
std::error_code ec;
auto fileSize = std::filesystem::file_size(hFile->path, ec);
@ -85,16 +86,16 @@ static DWORD XGetFileSizeA(FileHandle* hFile, LPDWORD lpFileSizeHigh)
{
if (lpFileSizeHigh != nullptr)
{
*lpFileSizeHigh = ByteSwap(DWORD(fileSize >> 32U));
*lpFileSizeHigh = uint32_t(fileSize >> 32U);
}
return (DWORD)(fileSize);
return (uint32_t)(fileSize);
}
return INVALID_FILE_SIZE;
}
BOOL XGetFileSizeExA(FileHandle* hFile, PLARGE_INTEGER lpFileSize)
uint32_t XGetFileSizeExA(FileHandle* hFile, LARGE_INTEGER* lpFileSize)
{
std::error_code ec;
auto fileSize = std::filesystem::file_size(hFile->path, ec);
@ -111,16 +112,16 @@ BOOL XGetFileSizeExA(FileHandle* hFile, PLARGE_INTEGER lpFileSize)
return FALSE;
}
BOOL XReadFile
uint32_t XReadFile
(
FileHandle* hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
XLPDWORD lpNumberOfBytesRead,
void* lpBuffer,
uint32_t nNumberOfBytesToRead,
be<uint32_t>* lpNumberOfBytesRead,
XOVERLAPPED* lpOverlapped
)
{
BOOL result = FALSE;
uint32_t result = FALSE;
if (lpOverlapped != nullptr)
{
std::streamoff streamOffset = lpOverlapped->Offset + (std::streamoff(lpOverlapped->OffsetHigh.get()) << 32U);
@ -132,11 +133,11 @@ BOOL XReadFile
}
}
DWORD numberOfBytesRead;
uint32_t numberOfBytesRead;
hFile->stream.read((char *)(lpBuffer), nNumberOfBytesToRead);
if (!hFile->stream.bad())
{
numberOfBytesRead = DWORD(hFile->stream.gcount());
numberOfBytesRead = uint32_t(hFile->stream.gcount());
result = TRUE;
}
@ -146,9 +147,6 @@ BOOL XReadFile
{
lpOverlapped->Internal = 0;
lpOverlapped->InternalHigh = numberOfBytesRead;
if (lpOverlapped->hEvent != NULL)
SetEvent((HANDLE)lpOverlapped->hEvent.get());
}
else if (lpNumberOfBytesRead != nullptr)
{
@ -159,9 +157,9 @@ BOOL XReadFile
return result;
}
DWORD XSetFilePointer(FileHandle* hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
uint32_t XSetFilePointer(FileHandle* hFile, int32_t lDistanceToMove, be<int32_t>* lpDistanceToMoveHigh, uint32_t dwMoveMethod)
{
LONG distanceToMoveHigh = lpDistanceToMoveHigh ? ByteSwap(*lpDistanceToMoveHigh) : 0;
int32_t distanceToMoveHigh = lpDistanceToMoveHigh ? lpDistanceToMoveHigh->get() : 0;
std::streamoff streamOffset = lDistanceToMove + (std::streamoff(distanceToMoveHigh) << 32U);
std::fstream::seekdir streamSeekDir = {};
switch (dwMoveMethod)
@ -189,12 +187,12 @@ DWORD XSetFilePointer(FileHandle* hFile, LONG lDistanceToMove, PLONG lpDistanceT
std::streampos streamPos = hFile->stream.tellg();
if (lpDistanceToMoveHigh != nullptr)
*lpDistanceToMoveHigh = ByteSwap(LONG(streamPos >> 32U));
*lpDistanceToMoveHigh = int32_t(streamPos >> 32U);
return DWORD(streamPos);
return uint32_t(streamPos);
}
BOOL XSetFilePointerEx(FileHandle* hFile, LONG lDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
uint32_t XSetFilePointerEx(FileHandle* hFile, int32_t lDistanceToMove, LARGE_INTEGER* lpNewFilePointer, uint32_t dwMoveMethod)
{
std::fstream::seekdir streamSeekDir = {};
switch (dwMoveMethod)
@ -222,13 +220,13 @@ BOOL XSetFilePointerEx(FileHandle* hFile, LONG lDistanceToMove, PLARGE_INTEGER l
if (lpNewFilePointer != nullptr)
{
lpNewFilePointer->QuadPart = ByteSwap(LONGLONG(hFile->stream.tellg()));
lpNewFilePointer->QuadPart = ByteSwap(int64_t(hFile->stream.tellg()));
}
return TRUE;
}
FindHandle* XFindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
FindHandle* XFindFirstFileA(const char* lpFileName, WIN32_FIND_DATAA* lpFindFileData)
{
const char *transformedPath = FileSystem::TransformPath(lpFileName);
size_t transformedPathLength = strlen(transformedPath);
@ -236,11 +234,11 @@ FindHandle* XFindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData
return (FindHandle*)GUEST_INVALID_HANDLE_VALUE;
std::filesystem::path dirPath;
if (strstr(transformedPath, "\\*") == (&transformedPath[transformedPathLength - 2]))
if (strstr(transformedPath, "\\*") == (&transformedPath[transformedPathLength - 2]) || strstr(transformedPath, "/*") == (&transformedPath[transformedPathLength - 2]))
{
dirPath = std::u8string_view((const char8_t*)(transformedPath), transformedPathLength - 2);
}
else if (strstr(transformedPath, "\\*.*") == (&transformedPath[transformedPathLength - 4]))
else if (strstr(transformedPath, "\\*.*") == (&transformedPath[transformedPathLength - 4]) || strstr(transformedPath, "/*.*") == (&transformedPath[transformedPathLength - 4]))
{
dirPath = std::u8string_view((const char8_t *)(transformedPath), transformedPathLength - 4);
}
@ -264,7 +262,7 @@ FindHandle* XFindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData
return findHandle;
}
BOOL XFindNextFileA(FindHandle* Handle, LPWIN32_FIND_DATAA lpFindFileData)
uint32_t XFindNextFileA(FindHandle* Handle, WIN32_FIND_DATAA* lpFindFileData)
{
Handle->iterator++;
@ -279,10 +277,10 @@ BOOL XFindNextFileA(FindHandle* Handle, LPWIN32_FIND_DATAA lpFindFileData)
}
}
BOOL XReadFileEx(FileHandle* hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, XOVERLAPPED* lpOverlapped, uint32_t lpCompletionRoutine)
uint32_t XReadFileEx(FileHandle* hFile, void* lpBuffer, uint32_t nNumberOfBytesToRead, XOVERLAPPED* lpOverlapped, uint32_t lpCompletionRoutine)
{
BOOL result = FALSE;
DWORD numberOfBytesRead;
uint32_t result = FALSE;
uint32_t numberOfBytesRead;
std::streamoff streamOffset = lpOverlapped->Offset + (std::streamoff(lpOverlapped->OffsetHigh.get()) << 32U);
hFile->stream.clear();
hFile->stream.seekg(streamOffset, std::ios::beg);
@ -292,7 +290,7 @@ BOOL XReadFileEx(FileHandle* hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
hFile->stream.read((char *)(lpBuffer), nNumberOfBytesToRead);
if (!hFile->stream.bad())
{
numberOfBytesRead = DWORD(hFile->stream.gcount());
numberOfBytesRead = uint32_t(hFile->stream.gcount());
result = TRUE;
}
@ -300,15 +298,12 @@ BOOL XReadFileEx(FileHandle* hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
{
lpOverlapped->Internal = 0;
lpOverlapped->InternalHigh = numberOfBytesRead;
if (lpOverlapped->hEvent != NULL)
SetEvent((HANDLE)lpOverlapped->hEvent.get());
}
return result;
}
DWORD XGetFileAttributesA(LPCSTR lpFileName)
uint32_t XGetFileAttributesA(const char* lpFileName)
{
std::filesystem::path filePath(std::u8string_view((const char8_t*)(FileSystem::TransformPath(lpFileName))));
if (std::filesystem::is_directory(filePath))
@ -319,7 +314,7 @@ DWORD XGetFileAttributesA(LPCSTR lpFileName)
return INVALID_FILE_ATTRIBUTES;
}
BOOL XWriteFile(FileHandle* hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
uint32_t XWriteFile(FileHandle* hFile, const void* lpBuffer, uint32_t nNumberOfBytesToWrite, be<uint32_t>* lpNumberOfBytesWritten, void* lpOverlapped)
{
assert(lpOverlapped == nullptr && "Overlapped not implemented.");
@ -328,16 +323,28 @@ BOOL XWriteFile(FileHandle* hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite
return FALSE;
if (lpNumberOfBytesWritten != nullptr)
*lpNumberOfBytesWritten = DWORD(hFile->stream.gcount());
*lpNumberOfBytesWritten = uint32_t(hFile->stream.gcount());
return TRUE;
}
static void fixSlashes(char *path)
{
while (*path != 0)
{
if (*path == '\\')
{
*path = '/';
}
path++;
}
}
const char* FileSystem::TransformPath(const char* path)
{
thread_local char builtPath[2048]{};
const char* relativePath = strstr(path, ":\\");
if (relativePath != nullptr)
{
// rooted folder, handle direction
@ -349,12 +356,19 @@ const char* FileSystem::TransformPath(const char* path)
strncpy(builtPath, newRoot.data(), newRoot.size());
builtPath[newRoot.size()] = '\\';
strcpy(builtPath + newRoot.size() + 1, relativePath + 2);
return builtPath;
}
else
{
strncpy(builtPath, relativePath + 2, sizeof(builtPath));
}
}
else
{
strncpy(builtPath, path, sizeof(builtPath));
}
return relativePath != nullptr ? relativePath + 2 : path;
fixSlashes(builtPath);
return builtPath;
}
SWA_API const char* XExpandFilePathA(const char* path)

View file

@ -13,6 +13,8 @@ Memory::Memory(void* address, size_t size) : size(size)
if (base == (char*)MAP_FAILED)
base = (char*)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
mprotect(base, 4096, PROT_NONE);
#endif
}

View file

@ -1,5 +1,10 @@
#pragma once
#ifndef _WIN32
#define MEM_COMMIT 0x00001000
#define MEM_RESERVE 0x00002000
#endif
class Memory
{
public:

View file

@ -2,23 +2,25 @@
#include "xam.h"
#include "xdm.h"
#include <hid/hid.h>
#include <ui/window.h>
#include <ui/game_window.h>
#include <cpu/guest_thread.h>
#include <ranges>
#include <unordered_set>
#include <CommCtrl.h>
#include "xxHashMap.h"
#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{};
uint64_t areas{};
std::vector<std::tuple<DWORD, DWORD>> notifications;
std::vector<std::tuple<uint32_t, uint32_t>> notifications;
XamListener(const XamListener&) = delete;
XamListener& operator=(const XamListener&) = delete;
@ -116,7 +118,7 @@ XamListener::~XamListener()
gListeners.erase(this);
}
XCONTENT_DATA XamMakeContent(DWORD type, const std::string_view& name)
XCONTENT_DATA XamMakeContent(uint32_t type, const std::string_view& name)
{
XCONTENT_DATA data{ 1, type };
@ -132,7 +134,7 @@ void XamRegisterContent(const XCONTENT_DATA& data, const std::string_view& root)
gContentRegistry[idx].emplace(StringHash(data.szFileName), XHOSTCONTENT_DATA{ data }).first->second.szRoot = root;
}
void XamRegisterContent(DWORD type, const std::string_view name, const std::string_view& root)
void XamRegisterContent(uint32_t type, const std::string_view name, const std::string_view& root)
{
XCONTENT_DATA data{ 1, type, {}, "" };
@ -141,7 +143,7 @@ void XamRegisterContent(DWORD type, const std::string_view name, const std::stri
XamRegisterContent(data, root);
}
SWA_API DWORD XamNotifyCreateListener(uint64_t qwAreas)
SWA_API uint32_t XamNotifyCreateListener(uint64_t qwAreas)
{
auto* listener = CreateKernelObject<XamListener>();
@ -150,7 +152,7 @@ SWA_API DWORD XamNotifyCreateListener(uint64_t qwAreas)
return GetKernelHandle(listener);
}
SWA_API void XamNotifyEnqueueEvent(DWORD dwId, DWORD dwParam)
SWA_API void XamNotifyEnqueueEvent(uint32_t dwId, uint32_t dwParam)
{
for (const auto& listener : gListeners)
{
@ -161,7 +163,7 @@ SWA_API void XamNotifyEnqueueEvent(DWORD dwId, DWORD dwParam)
}
}
SWA_API bool XNotifyGetNext(DWORD hNotification, DWORD dwMsgFilter, XDWORD* pdwId, XDWORD* pParam)
SWA_API bool XNotifyGetNext(uint32_t hNotification, uint32_t dwMsgFilter, be<uint32_t>* pdwId, be<uint32_t>* pParam)
{
auto& listener = *GetKernelObject<XamListener>(hNotification);
@ -202,9 +204,12 @@ SWA_API bool XNotifyGetNext(DWORD hNotification, DWORD dwMsgFilter, XDWORD* pdwI
return false;
}
SWA_API uint32_t XamShowMessageBoxUI(DWORD dwUserIndex, XWORD* wszTitle, XWORD* wszText, DWORD cButtons,
xpointer<XWORD>* pwszButtons, DWORD dwFocusButton, DWORD dwFlags, XLPDWORD pResult, XXOVERLAPPED* pOverlapped)
SWA_API 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)
{
int button{};
#ifdef _WIN32
std::vector<std::wstring> texts{};
std::vector<TASKDIALOG_BUTTON> buttons{};
@ -227,20 +232,19 @@ SWA_API uint32_t XamShowMessageBoxUI(DWORD dwUserIndex, XWORD* wszTitle, XWORD*
TASKDIALOGCONFIG config{};
config.cbSize = sizeof(config);
// config.hwndParent = Window::s_hWnd;
config.pszWindowTitle = texts[0].c_str();
config.pszContent = texts[1].c_str();
config.cButtons = cButtons;
config.pButtons = buttons.data();
int button{};
TaskDialogIndirect(&config, &button, nullptr, nullptr);
#endif
*pResult = button;
if (pOverlapped)
{
pOverlapped->dwCompletionContext = GetCurrentThreadId();
pOverlapped->dwCompletionContext = GuestThread::GetCurrentThreadId();
pOverlapped->Error = 0;
pOverlapped->Length = -1;
}
@ -250,8 +254,8 @@ SWA_API uint32_t XamShowMessageBoxUI(DWORD dwUserIndex, XWORD* wszTitle, XWORD*
return 0;
}
SWA_API uint32_t XamContentCreateEnumerator(DWORD dwUserIndex, DWORD DeviceID, DWORD dwContentType,
DWORD dwContentFlags, DWORD cItem, XLPDWORD pcbBuffer, XLPDWORD phEnum)
SWA_API uint32_t XamContentCreateEnumerator(uint32_t dwUserIndex, uint32_t DeviceID, uint32_t dwContentType,
uint32_t dwContentFlags, uint32_t cItem, be<uint32_t>* pcbBuffer, be<uint32_t>* phEnum)
{
if (dwUserIndex != 0)
{
@ -271,7 +275,7 @@ SWA_API uint32_t XamContentCreateEnumerator(DWORD dwUserIndex, DWORD DeviceID, D
return 0;
}
SWA_API uint32_t XamEnumerate(uint32_t hEnum, DWORD dwFlags, PVOID pvBuffer, DWORD cbBuffer, XLPDWORD pcItemsReturned, XXOVERLAPPED* pOverlapped)
SWA_API uint32_t XamEnumerate(uint32_t hEnum, uint32_t dwFlags, void* pvBuffer, uint32_t cbBuffer, be<uint32_t>* pcItemsReturned, XXOVERLAPPED* pOverlapped)
{
auto* enumerator = GetKernelObject<XamEnumeratorBase>(hEnum);
const auto count = enumerator->Next(pvBuffer);
@ -285,9 +289,9 @@ SWA_API uint32_t XamEnumerate(uint32_t hEnum, DWORD dwFlags, PVOID pvBuffer, DWO
return ERROR_SUCCESS;
}
SWA_API uint32_t XamContentCreateEx(DWORD dwUserIndex, LPCSTR szRootName, const XCONTENT_DATA* pContentData,
DWORD dwContentFlags, XLPDWORD pdwDisposition, XLPDWORD pdwLicenseMask,
DWORD dwFileCacheSize, uint64_t uliContentSize, PXXOVERLAPPED pOverlapped)
SWA_API uint32_t XamContentCreateEx(uint32_t dwUserIndex, const char* szRootName, const XCONTENT_DATA* pContentData,
uint32_t dwContentFlags, be<uint32_t>* pdwDisposition, be<uint32_t>* pdwLicenseMask,
uint32_t dwFileCacheSize, uint64_t uliContentSize, PXXOVERLAPPED pOverlapped)
{
const auto& registry = gContentRegistry[pContentData->dwContentType - 1];
const auto exists = registry.contains(StringHash(pContentData->szFileName));
@ -309,7 +313,7 @@ SWA_API uint32_t XamContentCreateEx(DWORD dwUserIndex, LPCSTR szRootName, const
}
else if (pContentData->dwContentType == XCONTENTTYPE_DLC)
{
root = ".\\dlc";
root = "./dlc";
}
else
{
@ -354,13 +358,13 @@ SWA_API uint32_t XamContentCreateEx(DWORD dwUserIndex, LPCSTR szRootName, const
return ERROR_PATH_NOT_FOUND;
}
SWA_API uint32_t XamContentClose(LPCSTR szRootName, XXOVERLAPPED* pOverlapped)
SWA_API uint32_t XamContentClose(const char* szRootName, XXOVERLAPPED* pOverlapped)
{
gRootMap.erase(StringHash(szRootName));
return 0;
}
SWA_API uint32_t XamContentGetDeviceData(DWORD DeviceID, XDEVICE_DATA* pDeviceData)
SWA_API uint32_t XamContentGetDeviceData(uint32_t DeviceID, XDEVICE_DATA* pDeviceData)
{
pDeviceData->DeviceID = DeviceID;
pDeviceData->DeviceType = XCONTENTDEVICETYPE_HDD;
@ -401,7 +405,7 @@ SWA_API uint32_t XamInputGetState(uint32_t userIndex, uint32_t flags, XAMINPUT_S
uint32_t result = hid::GetState(userIndex, state);
if (Window::s_isFocused)
if (GameWindow::s_isFocused)
{
auto keyboardState = SDL_GetKeyboardState(NULL);

View file

@ -1,32 +1,32 @@
#pragma once
#include <xbox.h>
#define MSGID(Area, Number) (DWORD)((WORD)(Area) << 16 | (WORD)(Number))
#define MSGID(Area, Number) (uint32_t)((uint16_t)(Area) << 16 | (uint16_t)(Number))
#define MSG_AREA(msgid) (((msgid) >> 16) & 0xFFFF)
#define MSG_NUMBER(msgid) ((msgid) & 0xFFFF)
XCONTENT_DATA XamMakeContent(DWORD type, const std::string_view& name);
XCONTENT_DATA XamMakeContent(uint32_t type, const std::string_view& name);
void XamRegisterContent(const XCONTENT_DATA& data, const std::string_view& root);
std::string_view XamGetRootPath(const std::string_view& root);
void XamRootCreate(const std::string_view& root, const std::string_view& path);
SWA_API DWORD XamNotifyCreateListener(uint64_t qwAreas);
SWA_API void XamNotifyEnqueueEvent(DWORD dwId, DWORD dwParam); // i made it the fuck up
SWA_API bool XNotifyGetNext(DWORD hNotification, DWORD dwMsgFilter, XDWORD* pdwId, XDWORD* pParam);
SWA_API uint32_t XamNotifyCreateListener(uint64_t qwAreas);
SWA_API void XamNotifyEnqueueEvent(uint32_t dwId, uint32_t dwParam); // i made it the fuck up
SWA_API bool XNotifyGetNext(uint32_t hNotification, uint32_t dwMsgFilter, be<uint32_t>* pdwId, be<uint32_t>* pParam);
SWA_API uint32_t XamShowMessageBoxUI(DWORD dwUserIndex, XWORD* wszTitle, XWORD* wszText, DWORD cButtons,
xpointer<XWORD>* pwszButtons, DWORD dwFocusButton, DWORD dwFlags, XLPDWORD pResult, XXOVERLAPPED* pOverlapped);
SWA_API 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);
SWA_API uint32_t XamContentCreateEnumerator(DWORD dwUserIndex, DWORD DeviceID, DWORD dwContentType,
DWORD dwContentFlags, DWORD cItem, XLPDWORD pcbBuffer, XLPDWORD phEnum);
SWA_API uint32_t XamEnumerate(uint32_t hEnum, DWORD dwFlags, PVOID pvBuffer, DWORD cbBuffer, XLPDWORD pcItemsReturned, XXOVERLAPPED* pOverlapped);
SWA_API uint32_t XamContentCreateEnumerator(uint32_t dwUserIndex, uint32_t DeviceID, uint32_t dwContentType,
uint32_t dwContentFlags, uint32_t cItem, be<uint32_t>* pcbBuffer, be<uint32_t>* phEnum);
SWA_API uint32_t XamEnumerate(uint32_t hEnum, uint32_t dwFlags, void* pvBuffer, uint32_t cbBuffer, be<uint32_t>* pcItemsReturned, XXOVERLAPPED* pOverlapped);
SWA_API uint32_t XamContentCreateEx(DWORD dwUserIndex, LPCSTR szRootName, const XCONTENT_DATA* pContentData,
DWORD dwContentFlags, XLPDWORD pdwDisposition, XLPDWORD pdwLicenseMask,
DWORD dwFileCacheSize, uint64_t uliContentSize, PXXOVERLAPPED pOverlapped);
SWA_API uint32_t XamContentGetDeviceData(DWORD DeviceID, XDEVICE_DATA* pDeviceData);
SWA_API uint32_t XamContentClose(LPCSTR szRootName, XXOVERLAPPED* pOverlapped);
SWA_API uint32_t XamContentCreateEx(uint32_t dwUserIndex, const char* szRootName, const XCONTENT_DATA* pContentData,
uint32_t dwContentFlags, be<uint32_t>* pdwDisposition, be<uint32_t>* pdwLicenseMask,
uint32_t dwFileCacheSize, uint64_t uliContentSize, PXXOVERLAPPED pOverlapped);
SWA_API uint32_t XamContentGetDeviceData(uint32_t DeviceID, XDEVICE_DATA* pDeviceData);
SWA_API uint32_t XamContentClose(const char* szRootName, XXOVERLAPPED* pOverlapped);
SWA_API uint32_t XamInputGetCapabilities(uint32_t unk, uint32_t userIndex, uint32_t flags, XAMINPUT_CAPABILITIES* caps);
SWA_API uint32_t XamInputGetState(uint32_t userIndex, uint32_t flags, XAMINPUT_STATE* state);

View file

@ -3,9 +3,84 @@
#include "heap.h"
#include "memory.h"
#define OBJECT_SIGNATURE (DWORD)'XBOX'
#define OBJECT_SIGNATURE (uint32_t)'XBOX'
#define GUEST_INVALID_HANDLE_VALUE 0xFFFFFFFF
#ifndef _WIN32
#define S_OK 0x00000000
#define FALSE 0x00000000
#define TRUE 0x00000001
#define STATUS_SUCCESS 0x00000000
#define STATUS_WAIT_0 0x00000000
#define STATUS_USER_APC 0x000000C0
#define STATUS_TIMEOUT 0x00000102
#define STATUS_FAIL_CHECK 0xC0000229
#define INFINITE 0xFFFFFFFF
#define FILE_ATTRIBUTE_DIRECTORY 0x00000010
#define FILE_ATTRIBUTE_NORMAL 0x00000080
#define GENERIC_READ 0x80000000
#define GENERIC_WRITE 0x40000000
#define FILE_READ_DATA 0x0001
#define FILE_SHARE_READ 0x00000001
#define FILE_SHARE_WRITE 0x00000002
#define CREATE_NEW 1
#define CREATE_ALWAYS 2
#define OPEN_EXISTING 3
#define INVALID_FILE_SIZE 0xFFFFFFFF
#define INVALID_SET_FILE_POINTER 0xFFFFFFFF
#define INVALID_FILE_ATTRIBUTES 0xFFFFFFFF
#define FILE_BEGIN 0
#define FILE_CURRENT 1
#define FILE_END 2
#define ERROR_NO_MORE_FILES 0x12
#define ERROR_NO_SUCH_USER 0x525
#define ERROR_SUCCESS 0x0
#define ERROR_PATH_NOT_FOUND 0x3
#define ERROR_BAD_ARGUMENTS 0xA0
#define ERROR_DEVICE_NOT_CONNECTED 0x48F
#define PAGE_READWRITE 0x04
typedef union _LARGE_INTEGER {
struct {
uint32_t LowPart;
int32_t HighPart;
};
struct {
uint32_t LowPart;
int32_t HighPart;
} u;
int64_t QuadPart;
} LARGE_INTEGER;
static_assert(sizeof(LARGE_INTEGER) == 8);
typedef struct _FILETIME
{
uint32_t dwLowDateTime;
uint32_t dwHighDateTime;
} FILETIME;
static_assert(sizeof(FILETIME) == 8);
typedef struct _WIN32_FIND_DATAA
{
uint32_t dwFileAttributes;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
uint32_t nFileSizeHigh;
uint32_t nFileSizeLow;
uint32_t dwReserved0;
uint32_t dwReserved1;
char cFileName[260];
char cAlternateFileName[14];
} WIN32_FIND_DATAA;
static_assert(sizeof(WIN32_FIND_DATAA) == 320);
#endif
struct KernelObject
{
virtual ~KernelObject()

View file

@ -1,5 +1,4 @@
#include <user/config.h>
#include <user/config_detail.h>
#define CONFIG_DEFINE_LOCALE(name) \
CONFIG_LOCALE Config::g_##name##_locale =

View file

@ -1,3 +1,4 @@
#include <user/config.h>
#include <locale/locale.h>
std::unordered_map<std::string, std::unordered_map<ELanguage, std::string>> g_locale =

View file

@ -1,6 +1,14 @@
#pragma once
#include <user/config.h>
enum class ELanguage : uint32_t
{
English = 1,
Japanese,
German,
French,
Spanish,
Italian
};
inline std::string g_localeMissing = "<missing string>";

View file

@ -50,8 +50,8 @@ void KiSystemStartup()
{
const auto gameContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Game");
const auto updateContent = XamMakeContent(XCONTENTTYPE_RESERVED, "Update");
XamRegisterContent(gameContent, DirectoryExists(".\\game") ? ".\\game" : ".");
XamRegisterContent(updateContent, ".\\update");
XamRegisterContent(gameContent, std::filesystem::exists("./game") ? "./game" : ".");
XamRegisterContent(updateContent, "./update");
const auto savePath = GetSavePath();
const auto saveName = "SYS-DATA";
@ -69,27 +69,6 @@ void KiSystemStartup()
// OS mounts game data to D:
XamContentCreateEx(0, "D", &gameContent, OPEN_EXISTING, nullptr, nullptr, 0, 0, nullptr);
WIN32_FIND_DATAA fdata;
const auto findHandle = FindFirstFileA(".\\dlc\\*.*", &fdata);
if (findHandle != INVALID_HANDLE_VALUE)
{
char strBuf[256];
do
{
if (strcmp(fdata.cFileName, ".") == 0 || strcmp(fdata.cFileName, "..") == 0)
{
continue;
}
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
snprintf(strBuf, sizeof(strBuf), ".\\dlc\\%s", fdata.cFileName);
XamRegisterContent(XamMakeContent(XCONTENTTYPE_DLC, fdata.cFileName), strBuf);
}
} while (FindNextFileA(findHandle, &fdata));
FindClose(findHandle);
}
XAudioInitializeSystem();
}

View file

@ -1,22 +1,23 @@
#include "stdafx.h"
#include <kernel/function.h>
#include <kernel/xdm.h>
BOOL QueryPerformanceCounterImpl(LARGE_INTEGER* lpPerformanceCount)
uint32_t QueryPerformanceCounterImpl(LARGE_INTEGER* lpPerformanceCount)
{
lpPerformanceCount->QuadPart = ByteSwap(std::chrono::steady_clock::now().time_since_epoch().count());
return TRUE;
}
BOOL QueryPerformanceFrequencyImpl(LARGE_INTEGER* lpFrequency)
uint32_t QueryPerformanceFrequencyImpl(LARGE_INTEGER* lpFrequency)
{
constexpr auto Frequency = std::chrono::steady_clock::period::den / std::chrono::steady_clock::period::num;
lpFrequency->QuadPart = ByteSwap(Frequency);
return TRUE;
}
DWORD GetTickCountImpl()
uint32_t GetTickCountImpl()
{
return DWORD(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count());
return uint32_t(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count());
}
void GlobalMemoryStatusImpl(XLPMEMORYSTATUS lpMemoryStatus)
@ -42,7 +43,11 @@ GUEST_FUNCTION_HOOK(sub_831B5E00, memmove);
GUEST_FUNCTION_HOOK(sub_831B0BA0, memset);
GUEST_FUNCTION_HOOK(sub_831CCAA0, memset);
#ifdef _WIN32
GUEST_FUNCTION_HOOK(sub_82BD4CA8, OutputDebugStringA);
#else
GUEST_FUNCTION_STUB(sub_82BD4CA8);
#endif
GUEST_FUNCTION_HOOK(sub_82BD4AC8, QueryPerformanceCounterImpl);
GUEST_FUNCTION_HOOK(sub_831CD040, QueryPerformanceFrequencyImpl);

View file

@ -1,5 +1,7 @@
#pragma once
#ifdef _WIN32
struct Mutex : CRITICAL_SECTION
{
Mutex()
@ -20,4 +22,10 @@ struct Mutex : CRITICAL_SECTION
{
LeaveCriticalSection(this);
}
};
};
#else
using Mutex = std::mutex;
#endif

View file

@ -0,0 +1,17 @@
#include <os/logger_detail.h>
void os::logger::detail::Init()
{
}
void os::logger::detail::Log(const std::string_view str, detail::ELogType type, const char* func)
{
if (func)
{
fmt::println("[{}] {}", func, str);
}
else
{
fmt::println("{}", str);
}
}

View file

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

View file

@ -0,0 +1,57 @@
#include <os/process_detail.h>
#include <signal.h>
std::filesystem::path os::process::detail::GetExecutablePath()
{
char exePath[PATH_MAX] = {};
if (readlink("/proc/self/exe", exePath, PATH_MAX) > 0)
{
return std::filesystem::path(std::u8string_view((const char8_t*)(exePath)));
}
else
{
return std::filesystem::path();
}
}
std::filesystem::path os::process::detail::GetWorkingDirectory()
{
char cwd[PATH_MAX] = {};
char *res = getcwd(cwd, sizeof(cwd));
if (res != nullptr)
{
return std::filesystem::path(std::u8string_view((const char8_t*)(cwd)));
}
else
{
return std::filesystem::path();
}
}
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)
return false;
if (pid == 0)
{
setsid();
std::u8string workU8 = work.u8string();
chdir((const char*)(workU8.c_str()));
std::u8string pathU8 = path.u8string();
std::vector<char*> argStrs;
argStrs.push_back((char*)(pathU8.c_str()));
for (const std::string& arg : args)
argStrs.push_back((char *)(arg.c_str()));
argStrs.push_back(nullptr);
execvp((const char*)(pathU8.c_str()), argStrs.data());
raise(SIGKILL);
}
return true;
}

View file

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

View file

@ -1,6 +1,6 @@
#include <cpu/guest_code.h>
#include <api/SWA.h>
#include <ui/window.h>
#include <ui/game_window.h>
#include <user/config.h>
constexpr float m_baseAspectRatio = 16.0f / 9.0f;
@ -8,7 +8,7 @@ constexpr float m_baseAspectRatio = 16.0f / 9.0f;
bool CameraAspectRatioMidAsmHook(PPCRegister& r31)
{
auto pCamera = (SWA::CCamera*)g_memory.Translate(r31.u32);
auto newAspectRatio = (float)Window::s_width / (float)Window::s_height;
auto newAspectRatio = (float)GameWindow::s_width / (float)GameWindow::s_height;
// Dynamically adjust horizontal aspect ratio to window dimensions.
pCamera->m_HorzAspectRatio = newAspectRatio;
@ -27,7 +27,7 @@ bool CameraBoostAspectRatioMidAsmHook(PPCRegister& r31, PPCRegister& f0, PPCRegi
{
auto pCamera = (SWA::CCamera*)g_memory.Translate(r31.u32);
if (Window::s_width < Window::s_height)
if (GameWindow::s_width < GameWindow::s_height)
{
pCamera->m_VertFieldOfView = pCamera->m_HorzFieldOfView + f10.f64;
}

View file

@ -1,11 +1,11 @@
#include <cpu/guest_code.h>
#include <api/SWA.h>
#include <ui/window.h>
#include <ui/game_window.h>
#include <user/config.h>
#include <app.h>
float m_lastLoadingFrameDelta = 0.0f;
std::chrono::steady_clock::time_point m_lastLoadingFrameTime;
std::chrono::high_resolution_clock::time_point m_lastLoadingFrameTime;
void DownForceDeltaTimeFixMidAsmHook(PPCRegister& f0)
{

View file

@ -1,6 +1,6 @@
#include <cpu/guest_code.h>
#include <api/SWA.h>
#include <ui/window.h>
#include <ui/game_window.h>
#include <user/achievement_data.h>
#include <user/config.h>

View file

@ -1,6 +1,6 @@
#include <cpu/guest_code.h>
#include <api/SWA.h>
#include <ui/window.h>
#include <ui/game_window.h>
#include <ui/window_events.h>
#include <user/config.h>
#include <os/logger.h>
@ -126,7 +126,7 @@ PPC_FUNC(sub_823B49D8)
{
__imp__sub_823B49D8(ctx, base);
SDL_User_EvilSonic(Window::s_pWindow, true);
SDL_User_EvilSonic(GameWindow::s_pWindow, true);
}
// SWA::Player::CEvilSonicContext::Dtor
@ -135,5 +135,5 @@ PPC_FUNC(sub_823B4590)
{
__imp__sub_823B4590(ctx, base);
SDL_User_EvilSonic(Window::s_pWindow, false);
SDL_User_EvilSonic(GameWindow::s_pWindow, false);
}

View file

@ -1,7 +1,7 @@
#include <cpu/guest_code.h>
#include <user/config.h>
#include <api/SWA.h>
#include <ui/window.h>
#include <ui/game_window.h>
// TODO: to be removed.
constexpr float m_baseAspectRatio = 16.0f / 9.0f;
@ -12,7 +12,7 @@ void CSDAspectRatioMidAsmHook(PPCRegister& f1, PPCRegister& f2)
if (Config::UIScaleMode == EUIScaleMode::Stretch)
return;
auto newAspectRatio = (float)Window::s_width / (float)Window::s_height;
auto newAspectRatio = (float)GameWindow::s_width / (float)GameWindow::s_height;
if (newAspectRatio > m_baseAspectRatio)
{

View file

@ -34,11 +34,11 @@ using Microsoft::WRL::ComPtr;
#include <toml++/toml.hpp>
#include <zstd.h>
#include <stb_image.h>
#include <concurrentqueue/blockingconcurrentqueue.h>
#include <blockingconcurrentqueue.h>
#include <SDL.h>
#include <imgui.h>
#include <imgui_internal.h>
#include <imgui_impl_sdl2.h>
#include <backends/imgui_impl_sdl2.h>
#include <o1heap.h>
#include <cstddef>
#include <smolv.h>
@ -46,6 +46,7 @@ using Microsoft::WRL::ComPtr;
#include <miniaudio.h>
#include <extras/miniaudio_libvorbis.h>
#include <fmt/core.h>
#include <list>
#include "framework.h"
#include "mutex.h"

View file

@ -281,9 +281,14 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
return;
char buffer[32];
struct tm time;
localtime_s(&time, &timestamp);
strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M", &time);
#ifdef _WIN32
tm timeStruct;
tm *timePtr = &timeStruct;
localtime_s(timePtr, &timestamp);
#else
tm *timePtr = localtime(&timestamp);
#endif
strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M", timePtr);
fontSize = Scale(12);
textSize = g_fntNewRodinDB->CalcTextSizeA(fontSize, FLT_MAX, 0, buffer);

View file

@ -1,4 +1,4 @@
#include "window.h"
#include "game_window.h"
#include "sdl_listener.h"
#include <user/config.h>
#include <SDL_syswm.h>
@ -31,10 +31,10 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
if (!(event->key.keysym.mod & KMOD_ALT) || !m_isFullscreenKeyReleased)
break;
Config::Fullscreen = Window::SetFullscreen(!Window::IsFullscreen());
Config::Fullscreen = GameWindow::SetFullscreen(!GameWindow::IsFullscreen());
if (!Config::Fullscreen)
Config::WindowState = Window::SetMaximised(Config::WindowState == EWindowState::Maximised);
Config::WindowState = GameWindow::SetMaximised(Config::WindowState == EWindowState::Maximised);
// Block holding ALT+ENTER spamming window changes.
m_isFullscreenKeyReleased = false;
@ -44,17 +44,17 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
// Restore original window dimensions on F2.
case SDLK_F2:
Config::Fullscreen = Window::SetFullscreen(false);
Window::SetDimensions(DEFAULT_WIDTH, DEFAULT_HEIGHT);
Config::Fullscreen = GameWindow::SetFullscreen(false);
GameWindow::SetDimensions(DEFAULT_WIDTH, DEFAULT_HEIGHT);
break;
// Recentre window on F3.
case SDLK_F3:
{
if (Window::IsFullscreen())
if (GameWindow::IsFullscreen())
break;
Window::SetDimensions(Window::s_width, Window::s_height);
GameWindow::SetDimensions(GameWindow::s_width, GameWindow::s_height);
break;
}
@ -79,16 +79,16 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
switch (event->window.event)
{
case SDL_WINDOWEVENT_FOCUS_LOST:
Window::s_isFocused = false;
GameWindow::s_isFocused = false;
SDL_ShowCursor(SDL_ENABLE);
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
{
Window::s_isFocused = true;
GameWindow::s_isFocused = true;
if (Window::IsFullscreen())
SDL_ShowCursor(Window::s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE);
if (GameWindow::IsFullscreen())
SDL_ShowCursor(GameWindow::s_isFullscreenCursorVisible ? SDL_ENABLE : SDL_DISABLE);
break;
}
@ -103,14 +103,14 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
case SDL_WINDOWEVENT_RESIZED:
m_isResizing = true;
Window::s_width = event->window.data1;
Window::s_height = event->window.data2;
Window::SetTitle(fmt::format("{} - [{}x{}]", Window::GetTitle(), Window::s_width, Window::s_height).c_str());
GameWindow::s_width = event->window.data1;
GameWindow::s_height = event->window.data2;
GameWindow::SetTitle(fmt::format("{} - [{}x{}]", GameWindow::GetTitle(), GameWindow::s_width, GameWindow::s_height).c_str());
break;
case SDL_WINDOWEVENT_MOVED:
Window::s_x = event->window.data1;
Window::s_y = event->window.data2;
GameWindow::s_x = event->window.data1;
GameWindow::s_y = event->window.data2;
break;
}
@ -119,13 +119,13 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
case SDL_USER_EVILSONIC:
{
Window::s_isIconNight = event->user.code;
Window::SetIcon(Window::s_isIconNight);
GameWindow::s_isIconNight = event->user.code;
GameWindow::SetIcon(GameWindow::s_isIconNight);
break;
}
}
if (!Window::IsFullscreen())
if (!GameWindow::IsFullscreen())
{
if (event->type == SDL_CONTROLLERBUTTONDOWN || event->type == SDL_CONTROLLERBUTTONUP || event->type == SDL_CONTROLLERAXISMOTION)
{
@ -142,12 +142,14 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
return 0;
}
void Window::Init()
void GameWindow::Init()
{
SDL_InitSubSystem(SDL_INIT_VIDEO);
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
SDL_AddEventWatch(Window_OnSDLEvent, s_pWindow);
#ifdef _WIN32
SetProcessDPIAware();
#endif
s_x = Config::WindowX;
s_y = Config::WindowY;
@ -183,21 +185,26 @@ void Window::Init()
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(s_pWindow, &info);
s_handle = info.info.win.window;
#if defined(_WIN32)
s_renderWindow = info.info.win.window;
SetDarkTitleBar(true);
#elif defined(__linux__)
s_renderWindow = { info.info.x11.display, info.info.x11.window };
#else
static_assert(false, "Unknown platform.");
#endif
SDL_ShowWindow(s_pWindow);
}
void Window::Update()
void GameWindow::Update()
{
if (!Window::IsFullscreen() && !Window::IsMaximised())
if (!GameWindow::IsFullscreen() && !GameWindow::IsMaximised())
{
Config::WindowX = Window::s_x;
Config::WindowY = Window::s_y;
Config::WindowWidth = Window::s_width;
Config::WindowHeight = Window::s_height;
Config::WindowX = GameWindow::s_x;
Config::WindowY = GameWindow::s_y;
Config::WindowWidth = GameWindow::s_width;
Config::WindowHeight = GameWindow::s_height;
}
if (m_isResizing)

View file

@ -6,6 +6,7 @@
#include <os/version.h>
#include <ui/window_events.h>
#include <user/config.h>
#include <gpu/rhi/plume_render_interface_types.h>
#if _WIN32
#include <dwmapi.h>
@ -15,11 +16,11 @@
#define DEFAULT_WIDTH 1280
#define DEFAULT_HEIGHT 720
class Window
class GameWindow
{
public:
static inline SDL_Window* s_pWindow;
static inline HWND s_handle;
static inline plume::RenderWindow s_renderWindow;
static inline int s_x;
static inline int s_y;
@ -87,7 +88,7 @@ public:
: 19; // DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1
const DWORD useImmersiveDarkMode = isEnabled;
DwmSetWindowAttribute(s_handle, flag, &useImmersiveDarkMode, sizeof(useImmersiveDarkMode));
DwmSetWindowAttribute(s_renderWindow, flag, &useImmersiveDarkMode, sizeof(useImmersiveDarkMode));
#endif
}
@ -107,7 +108,7 @@ public:
{
SDL_SetWindowFullscreen(s_pWindow, 0);
SDL_ShowCursor(SDL_ENABLE);
SetIcon(Window::s_isIconNight);
SetIcon(GameWindow::s_isIconNight);
}
return isEnabled;

View file

@ -13,7 +13,7 @@
#include <ui/button_guide.h>
#include <ui/message_window.h>
#include <ui/sdl_listener.h>
#include <ui/window.h>
#include <ui/game_window.h>
#include <decompressor.h>
#include <res/images/installer/install_001.dds.h>
@ -133,8 +133,12 @@ static WizardPage g_firstPage = WizardPage::SelectLanguage;
static WizardPage g_currentPage = g_firstPage;
static std::string g_currentMessagePrompt = "";
static bool g_currentMessagePromptConfirmation = false;
static std::list<std::filesystem::path> g_currentPickerResults;
static std::atomic<bool> g_currentPickerResultsReady = false;
static std::unique_ptr<std::thread> g_currentPickerThread;
static bool g_currentPickerVisible = false;
static bool g_currentPickerFolderMode = false;
static int g_currentMessageResult = -1;
static bool g_filesPickerSkipUpdate = false;
static ImVec2 g_joypadAxis = {};
static int g_currentCursorIndex = -1;
static int g_currentCursorDefault = 0;
@ -148,7 +152,7 @@ public:
{
constexpr float AxisValueRange = 32767.0f;
constexpr float AxisTapRange = 0.5f;
if (!InstallerWizard::s_isVisible || !g_currentMessagePrompt.empty())
if (!InstallerWizard::s_isVisible || !g_currentMessagePrompt.empty() || g_currentPickerVisible)
{
return;
}
@ -217,7 +221,7 @@ public:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEMOTION:
{
for (size_t i = 0; i < g_currentCursorRects.size() && !g_filesPickerSkipUpdate; i++)
for (size_t i = 0; i < g_currentCursorRects.size(); i++)
{
auto &currentRect = g_currentCursorRects[i];
if (ImGui::IsMouseHoveringRect(currentRect.first, currentRect.second, false))
@ -734,7 +738,7 @@ static void DrawButton(ImVec2 min, ImVec2 max, const char *buttonText, bool sour
int baser = 0;
int baseg = 0;
if (g_currentMessagePrompt.empty() && !sourceButton && buttonEnabled && (alpha >= 1.0f))
if (g_currentMessagePrompt.empty() && !g_currentPickerVisible && !sourceButton && buttonEnabled && (alpha >= 1.0f))
{
bool cursorOnButton = PushCursorRect(min, max, buttonPressed, makeDefault);
if (cursorOnButton)
@ -882,44 +886,44 @@ static bool ConvertPathSet(const nfdpathset_t *pathSet, std::list<std::filesyste
return true;
}
static bool ShowFilesPicker(std::list<std::filesystem::path> &filePaths)
static void PickerThreadProcess()
{
filePaths.clear();
const nfdpathset_t *pathSet;
nfdresult_t result = NFD_OpenDialogMultipleU8(&pathSet, nullptr, 0, nullptr);
g_filesPickerSkipUpdate = true;
if (result == NFD_OKAY)
nfdresult_t result = NFD_ERROR;
if (g_currentPickerFolderMode)
{
bool pathsConverted = ConvertPathSet(pathSet, filePaths);
NFD_PathSet_Free(pathSet);
return pathsConverted;
nfdpickfolderu8args_t openArgs = {};
result = NFD_PickFolderMultipleU8_With(&pathSet, &openArgs);
}
else
{
return false;
nfdopendialogu8args_t openArgs = {};
result = NFD_OpenDialogMultipleU8_With(&pathSet, &openArgs);
}
if (result == NFD_OKAY)
{
bool pathsConverted = ConvertPathSet(pathSet, g_currentPickerResults);
NFD_PathSet_Free(pathSet);
}
g_currentPickerResultsReady = true;
g_currentPickerVisible = false;
}
static bool ShowFoldersPicker(std::list<std::filesystem::path> &folderPaths)
static void ShowPicker(bool folderMode)
{
folderPaths.clear();
const nfdpathset_t *pathSet;
nfdresult_t result = NFD_PickFolderMultipleU8(&pathSet, nullptr);
g_filesPickerSkipUpdate = true;
if (result == NFD_OKAY)
if (g_currentPickerThread != nullptr)
{
bool pathsConverted = ConvertPathSet(pathSet, folderPaths);
NFD_PathSet_Free(pathSet);
return pathsConverted;
}
else
{
return false;
g_currentPickerThread->join();
g_currentPickerThread.reset();
}
g_currentPickerResults.clear();
g_currentPickerFolderMode = folderMode;
g_currentPickerResultsReady = false;
g_currentPickerVisible = true;
g_currentPickerThread = std::make_unique<std::thread>(PickerThreadProcess);
}
static void ParseSourcePaths(std::list<std::filesystem::path> &paths)
@ -1013,8 +1017,6 @@ static void DrawLanguagePicker()
static void DrawSourcePickers()
{
g_filesPickerSkipUpdate = false;
bool buttonPressed = false;
std::list<std::filesystem::path> paths;
if (g_currentPage == WizardPage::SelectGameAndUpdate || g_currentPage == WizardPage::SelectDLC)
@ -1028,9 +1030,9 @@ static void DrawSourcePickers()
ImVec2 min = { Scale(AlignToNextGrid(CONTAINER_X) + BOTTOM_X_GAP), Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) + BOTTOM_Y_GAP) };
ImVec2 max = { Scale(AlignToNextGrid(CONTAINER_X) + BOTTOM_X_GAP + textSize.x * squashRatio), Scale(AlignToNextGrid(CONTAINER_Y + CONTAINER_HEIGHT) + BOTTOM_Y_GAP + BUTTON_HEIGHT) };
DrawButton(min, max, addFilesText.c_str(), false, true, buttonPressed, ADD_BUTTON_MAX_TEXT_WIDTH);
if (buttonPressed && ShowFilesPicker(paths))
if (buttonPressed)
{
ParseSourcePaths(paths);
ShowPicker(false);
}
min.x += Scale(BOTTOM_X_GAP + textSize.x * squashRatio);
@ -1041,9 +1043,9 @@ static void DrawSourcePickers()
max.x = min.x + Scale(textSize.x * squashRatio);
DrawButton(min, max, addFolderText.c_str(), false, true, buttonPressed, ADD_BUTTON_MAX_TEXT_WIDTH);
if (buttonPressed && ShowFoldersPicker(paths))
if (buttonPressed)
{
ParseSourcePaths(paths);
ShowPicker(true);
}
}
}
@ -1305,14 +1307,6 @@ static void DrawBorders()
static void DrawMessagePrompt()
{
if (g_filesPickerSkipUpdate)
{
// If a blocking function like the files picker is called, we must wait one update before actually showing
// the message box, as a lot of time has passed since the last real update. Otherwise, animations will play
// too quickly and input glitches might happen.
return;
}
if (g_currentMessagePrompt.empty())
{
return;
@ -1342,6 +1336,18 @@ static void DrawMessagePrompt()
}
}
static void CheckPickerResults()
{
if (!g_currentPickerResultsReady)
{
return;
}
ParseSourcePaths(g_currentPickerResults);
g_currentPickerResultsReady = false;
g_currentPickerVisible = false;
}
void InstallerWizard::Init()
{
auto &io = ImGui::GetIO();
@ -1380,6 +1386,7 @@ void InstallerWizard::Draw()
DrawNextButton();
DrawBorders();
DrawMessagePrompt();
CheckPickerResults();
if (g_isDisappearing)
{
@ -1439,18 +1446,18 @@ bool InstallerWizard::Run(bool skipGame)
g_currentPage = g_firstPage;
}
Window::SetFullscreenCursorVisibility(true);
GameWindow::SetFullscreenCursorVisibility(true);
s_isVisible = true;
while (s_isVisible)
{
SDL_PumpEvents();
SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
Window::Update();
GameWindow::Update();
Video::HostPresent();
}
Window::SetFullscreenCursorVisibility(false);
GameWindow::SetFullscreenCursorVisibility(false);
NFD_Quit();
InstallerWizard::Shutdown();

View file

@ -1,7 +1,7 @@
#include "options_menu.h"
#include "options_menu_thumbnails.h"
#include "imgui_utils.h"
#include "window.h"
#include "game_window.h"
#include "exports.h"
#include <api/SWA/System/InputState.h>
@ -444,7 +444,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
ImVec2 min = { clipRectMin.x, clipRectMin.y + (optionHeight + optionPadding) * rowIndex + yOffset };
ImVec2 max = { min.x + optionWidth, min.y + optionHeight };
auto configName = config->GetNameLocalised();
auto configName = config->GetNameLocalised(Config::Language);
auto size = Scale(26.0f);
auto textSize = g_seuratFont->CalcTextSizeA(size, FLT_MAX, 0.0f, configName.c_str());
@ -747,7 +747,7 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
}
else
{
valueText = config->GetValueLocalised();
valueText = config->GetValueLocalised(Config::Language);
}
size = Scale(20.0f);
@ -952,7 +952,7 @@ static void DrawInfoPanel()
if (g_selectedItem)
{
auto desc = g_selectedItem->GetDescription();
auto desc = g_selectedItem->GetDescription(Config::Language);
auto thumbnail = GetThumbnail(g_selectedItem);
if (thumbnail)
@ -971,13 +971,13 @@ static void DrawInfoPanel()
auto resScale = round(*(float*)g_selectedItem->GetValue() * 1000) / 1000;
std::snprintf(buf, sizeof(buf), desc.c_str(),
(int)((float)Window::s_width * resScale),
(int)((float)Window::s_height * resScale));
(int)((float)GameWindow::s_width * resScale),
(int)((float)GameWindow::s_height * resScale));
desc = buf;
}
desc += "\n\n" + g_selectedItem->GetValueDescription();
desc += "\n\n" + g_selectedItem->GetValueDescription(Config::Language);
}
auto size = Scale(26.0f);

View file

@ -1,7 +1,7 @@
#pragma once
#include <SDL.h>
#include "ui/window.h"
#include "ui/game_window.h"
#define SDL_USER_EVILSONIC (SDL_USEREVENT + 1)

View file

@ -20,7 +20,7 @@ void Config::Load()
toml = toml::parse(tomlStream);
}
for (auto def : Config::Definitions)
for (auto def : g_configDefinitions)
{
def->ReadValue(toml);
#if _DEBUG
@ -44,7 +44,7 @@ void Config::Save()
std::string result;
std::string section;
for (auto def : Config::Definitions)
for (auto def : g_configDefinitions)
{
auto isFirstSection = section.empty();
auto isDefWithSection = section != def->GetSection();

View file

@ -1,14 +1,592 @@
#pragma once
#include <user/config_detail.h>
#include <locale/locale.h>
#include <user/paths.h>
#include <exports.h>
class IConfigDef
{
public:
virtual ~IConfigDef() = default;
virtual void ReadValue(toml::v3::ex::parse_result& toml) = 0;
virtual void MakeDefault() = 0;
virtual std::string_view GetSection() const = 0;
virtual std::string_view GetName() const = 0;
virtual std::string GetNameLocalised(ELanguage language) const = 0;
virtual std::string GetDescription(ELanguage language) const = 0;
virtual bool IsDefaultValue() const = 0;
virtual const void* GetValue() const = 0;
virtual std::string GetValueLocalised(ELanguage language) const = 0;
virtual std::string GetValueDescription(ELanguage language) const = 0;
virtual std::string GetDefinition(bool withSection = false) const = 0;
virtual std::string ToString(bool strWithQuotes = true) const = 0;
virtual void GetLocaleStrings(std::vector<std::string_view>& localeStrings) const = 0;
};
#define CONFIG_LOCALE std::unordered_map<ELanguage, std::tuple<std::string, std::string>>
#define CONFIG_ENUM_LOCALE(type) std::unordered_map<ELanguage, std::unordered_map<type, std::tuple<std::string, std::string>>>
#define CONFIG_DEFINE(section, type, name, defaultValue) \
static inline ConfigDef<type> name{section, #name, defaultValue};
#define CONFIG_DEFINE_LOCALISED(section, type, name, defaultValue) \
static CONFIG_LOCALE g_##name##_locale; \
static inline ConfigDef<type> name{section, #name, &g_##name##_locale, defaultValue};
#define CONFIG_DEFINE_ENUM(section, type, name, defaultValue) \
static inline ConfigDef<type> name{section, #name, defaultValue, &g_##type##_template};
#define CONFIG_DEFINE_ENUM_LOCALISED(section, type, name, defaultValue) \
static CONFIG_LOCALE g_##name##_locale; \
static CONFIG_ENUM_LOCALE(type) g_##type##_locale; \
static inline ConfigDef<type> name{section, #name, &g_##name##_locale, defaultValue, &g_##type##_template, &g_##type##_locale};
#define CONFIG_DEFINE_CALLBACK(section, type, name, defaultValue, readCallback) \
static CONFIG_LOCALE g_##name##_locale; \
static inline ConfigDef<type> name{section, #name, defaultValue, [](ConfigDef<type>* def) readCallback};
#define CONFIG_DEFINE_ENUM_TEMPLATE(type) \
inline std::unordered_map<std::string, type> g_##type##_template =
#define WINDOWPOS_CENTRED 0x2FFF0000
static inline std::vector<IConfigDef*> g_configDefinitions{};
CONFIG_DEFINE_ENUM_TEMPLATE(ELanguage)
{
{ "English", ELanguage::English },
{ "Japanese", ELanguage::Japanese },
{ "German", ELanguage::German },
{ "French", ELanguage::French },
{ "Spanish", ELanguage::Spanish },
{ "Italian", ELanguage::Italian }
};
enum class EUnleashGaugeBehaviour : uint32_t
{
Original,
Revised
};
CONFIG_DEFINE_ENUM_TEMPLATE(EUnleashGaugeBehaviour)
{
{ "Original", EUnleashGaugeBehaviour::Original },
{ "Revised", EUnleashGaugeBehaviour::Revised }
};
enum class ETimeOfDayTransition : uint32_t
{
Xbox,
PlayStation
};
CONFIG_DEFINE_ENUM_TEMPLATE(ETimeOfDayTransition)
{
{ "Xbox", ETimeOfDayTransition::Xbox },
{ "PlayStation", ETimeOfDayTransition::PlayStation }
};
enum class EControllerIcons : uint32_t
{
Auto,
Xbox,
PlayStation
};
CONFIG_DEFINE_ENUM_TEMPLATE(EControllerIcons)
{
{ "Auto", EControllerIcons::Auto },
{ "Xbox", EControllerIcons::Xbox },
{ "PlayStation", EControllerIcons::PlayStation }
};
enum class EVoiceLanguage : uint32_t
{
English,
Japanese
};
CONFIG_DEFINE_ENUM_TEMPLATE(EVoiceLanguage)
{
{ "English", EVoiceLanguage::English },
{ "Japanese", EVoiceLanguage::Japanese }
};
enum class EGraphicsAPI : uint32_t
{
#ifdef SWA_D3D12
D3D12,
#endif
Vulkan
};
CONFIG_DEFINE_ENUM_TEMPLATE(EGraphicsAPI)
{
#ifdef SWA_D3D12
{ "D3D12", EGraphicsAPI::D3D12 },
#endif
{ "Vulkan", EGraphicsAPI::Vulkan }
};
enum class EWindowState : uint32_t
{
Normal,
Maximised
};
CONFIG_DEFINE_ENUM_TEMPLATE(EWindowState)
{
{ "Normal", EWindowState::Normal },
{ "Maximised", EWindowState::Maximised },
{ "Maximized", EWindowState::Maximised }
};
enum class EAspectRatio : uint32_t
{
Auto,
Square,
Widescreen
};
CONFIG_DEFINE_ENUM_TEMPLATE(EAspectRatio)
{
{ "Auto", EAspectRatio::Auto },
{ "4:3", EAspectRatio::Square },
{ "16:9", EAspectRatio::Widescreen }
};
enum class ETripleBuffering : uint32_t
{
Auto,
On,
Off
};
CONFIG_DEFINE_ENUM_TEMPLATE(ETripleBuffering)
{
{ "Auto", ETripleBuffering::Auto },
{ "On", ETripleBuffering::On },
{ "Off", ETripleBuffering::Off }
};
enum class EAntiAliasing : uint32_t
{
None = 0,
MSAA2x = 2,
MSAA4x = 4,
MSAA8x = 8
};
CONFIG_DEFINE_ENUM_TEMPLATE(EAntiAliasing)
{
{ "None", EAntiAliasing::None },
{ "2x MSAA", EAntiAliasing::MSAA2x },
{ "4x MSAA", EAntiAliasing::MSAA4x },
{ "8x MSAA", EAntiAliasing::MSAA8x }
};
enum class EShadowResolution : int32_t
{
Original = -1,
x512 = 512,
x1024 = 1024,
x2048 = 2048,
x4096 = 4096,
x8192 = 8192
};
CONFIG_DEFINE_ENUM_TEMPLATE(EShadowResolution)
{
{ "Original", EShadowResolution::Original },
{ "512", EShadowResolution::x512 },
{ "1024", EShadowResolution::x1024 },
{ "2048", EShadowResolution::x2048 },
{ "4096", EShadowResolution::x4096 },
{ "8192", EShadowResolution::x8192 },
};
enum class EGITextureFiltering : uint32_t
{
Bilinear,
Bicubic
};
CONFIG_DEFINE_ENUM_TEMPLATE(EGITextureFiltering)
{
{ "Bilinear", EGITextureFiltering::Bilinear },
{ "Bicubic", EGITextureFiltering::Bicubic }
};
enum class EDepthOfFieldQuality : uint32_t
{
Auto,
Low,
Medium,
High,
Ultra
};
CONFIG_DEFINE_ENUM_TEMPLATE(EDepthOfFieldQuality)
{
{ "Auto", EDepthOfFieldQuality::Auto },
{ "Low", EDepthOfFieldQuality::Low },
{ "Medium", EDepthOfFieldQuality::Medium },
{ "High", EDepthOfFieldQuality::High },
{ "Ultra", EDepthOfFieldQuality::Ultra }
};
enum class EMotionBlur : uint32_t
{
Off,
Original,
Enhanced
};
CONFIG_DEFINE_ENUM_TEMPLATE(EMotionBlur)
{
{ "Off", EMotionBlur::Off },
{ "Original", EMotionBlur::Original },
{ "Enhanced", EMotionBlur::Enhanced }
};
enum class EMovieScaleMode : uint32_t
{
Stretch,
Fit,
Fill
};
CONFIG_DEFINE_ENUM_TEMPLATE(EMovieScaleMode)
{
{ "Stretch", EMovieScaleMode::Stretch },
{ "Fit", EMovieScaleMode::Fit },
{ "Fill", EMovieScaleMode::Fill }
};
enum class EUIScaleMode : uint32_t
{
Stretch,
Edge,
Centre
};
CONFIG_DEFINE_ENUM_TEMPLATE(EUIScaleMode)
{
{ "Stretch", EUIScaleMode::Stretch },
{ "Edge", EUIScaleMode::Edge },
{ "Centre", EUIScaleMode::Centre },
{ "Center", EUIScaleMode::Centre }
};
template<typename T>
class ConfigDef final : public IConfigDef
{
public:
std::string Section{};
std::string Name{};
CONFIG_LOCALE* Locale{};
T DefaultValue{};
T Value{ DefaultValue };
std::unordered_map<std::string, T>* EnumTemplate;
std::map<T, std::string> EnumTemplateReverse{};
CONFIG_ENUM_LOCALE(T)* EnumLocale{};
std::function<void(ConfigDef<T>*)> Callback;
// CONFIG_DEFINE
ConfigDef(std::string section, std::string name, T defaultValue) : Section(section), Name(name), DefaultValue(defaultValue)
{
g_configDefinitions.emplace_back(this);
}
// CONFIG_DEFINE_LOCALISED
ConfigDef(std::string section, std::string name, CONFIG_LOCALE* nameLocale, T defaultValue) : Section(section), Name(name), Locale(nameLocale), DefaultValue(defaultValue)
{
g_configDefinitions.emplace_back(this);
}
// CONFIG_DEFINE_ENUM
ConfigDef(std::string section, std::string name, T defaultValue, std::unordered_map<std::string, T>* enumTemplate) : Section(section), Name(name), DefaultValue(defaultValue), EnumTemplate(enumTemplate)
{
for (const auto& pair : *EnumTemplate)
EnumTemplateReverse[pair.second] = pair.first;
g_configDefinitions.emplace_back(this);
}
// CONFIG_DEFINE_ENUM_LOCALISED
ConfigDef(std::string section, std::string name, CONFIG_LOCALE* nameLocale, T defaultValue, std::unordered_map<std::string, T>* enumTemplate, CONFIG_ENUM_LOCALE(T)* enumLocale) : Section(section), Name(name), Locale(nameLocale), DefaultValue(defaultValue), EnumTemplate(enumTemplate), EnumLocale(enumLocale)
{
for (const auto& pair : *EnumTemplate)
EnumTemplateReverse[pair.second] = pair.first;
g_configDefinitions.emplace_back(this);
}
// CONFIG_DEFINE_CALLBACK
ConfigDef(std::string section, std::string name, T defaultValue, std::function<void(ConfigDef<T>*)> callback) : Section(section), Name(name), DefaultValue(defaultValue), Callback(callback)
{
g_configDefinitions.emplace_back(this);
}
void ReadValue(toml::v3::ex::parse_result& toml) override
{
if (auto pSection = toml[Section].as_table())
{
const auto& section = *pSection;
if constexpr (std::is_same<T, std::string>::value)
{
Value = section[Name].value_or<std::string>(DefaultValue);
}
else if constexpr (std::is_enum_v<T>)
{
std::string value = section[Name].value_or(std::string());
auto it = EnumTemplate->find(value);
if (it != EnumTemplate->end())
{
Value = it->second;
}
else
{
Value = DefaultValue;
}
}
else
{
Value = section[Name].value_or(DefaultValue);
}
if (Callback)
Callback(this);
}
}
void MakeDefault() override
{
Value = DefaultValue;
}
std::string_view GetSection() const override
{
return Section;
}
std::string_view GetName() const override
{
return Name;
}
std::string GetNameLocalised(ELanguage language) const override
{
if (!Locale)
return Name;
if (!Locale->count(language))
{
if (Locale->count(ELanguage::English))
{
return std::get<0>(Locale->at(ELanguage::English));
}
else
{
return Name;
}
}
return std::get<0>(Locale->at(language));
}
std::string GetDescription(ELanguage language) const override
{
if (!Locale)
return "";
if (!Locale->count(language))
{
if (Locale->count(ELanguage::English))
{
return std::get<1>(Locale->at(ELanguage::English));
}
else
{
return "";
}
}
return std::get<1>(Locale->at(language));
}
bool IsDefaultValue() const override
{
return Value == DefaultValue;
}
const void* GetValue() const override
{
return &Value;
}
std::string GetValueLocalised(ELanguage language) const override
{
CONFIG_ENUM_LOCALE(T)* locale = nullptr;
if constexpr (std::is_enum_v<T>)
{
locale = EnumLocale;
}
else if constexpr (std::is_same_v<T, bool>)
{
return Value
? Localise("Common_On")
: Localise("Common_Off");
}
if (!locale)
return ToString(false);
if (!locale->count(language))
{
if (locale->count(ELanguage::English))
{
language = ELanguage::English;
}
else
{
return ToString(false);
}
}
auto strings = locale->at(language);
if (!strings.count(Value))
return ToString(false);
return std::get<0>(strings.at(Value));
}
std::string GetValueDescription(ELanguage language) const override
{
CONFIG_ENUM_LOCALE(T)* locale = nullptr;
if constexpr (std::is_enum_v<T>)
{
locale = EnumLocale;
}
else if constexpr (std::is_same_v<T, bool>)
{
return "";
}
if (!locale)
return "";
if (!locale->count(language))
{
if (locale->count(ELanguage::English))
{
language = ELanguage::English;
}
else
{
return "";
}
}
auto strings = locale->at(language);
if (!strings.count(Value))
return "";
return std::get<1>(strings.at(Value));
}
std::string GetDefinition(bool withSection = false) const override
{
std::string result;
if (withSection)
result += "[" + Section + "]\n";
result += Name + " = " + ToString();
return result;
}
std::string ToString(bool strWithQuotes = true) const override
{
std::string result = "N/A";
if constexpr (std::is_same_v<T, std::string>)
{
result = fmt::format("{}", Value);
if (strWithQuotes)
result = fmt::format("\"{}\"", result);
}
else if constexpr (std::is_enum_v<T>)
{
auto it = EnumTemplateReverse.find(Value);
if (it != EnumTemplateReverse.end())
result = fmt::format("{}", it->second);
if (strWithQuotes)
result = fmt::format("\"{}\"", result);
}
else
{
result = fmt::format("{}", Value);
}
return result;
}
void GetLocaleStrings(std::vector<std::string_view>& localeStrings) const override
{
if (Locale != nullptr)
{
for (auto& [language, nameAndDesc] : *Locale)
{
localeStrings.push_back(std::get<0>(nameAndDesc));
localeStrings.push_back(std::get<1>(nameAndDesc));
}
}
if (EnumLocale != nullptr)
{
for (auto& [language, locale] : *EnumLocale)
{
for (auto& [value, nameAndDesc] : locale)
{
localeStrings.push_back(std::get<0>(nameAndDesc));
localeStrings.push_back(std::get<1>(nameAndDesc));
}
}
}
}
ConfigDef& operator=(const ConfigDef& other)
{
if (this != &other)
Value = other.Value;
return *this;
}
operator T() const
{
return Value;
}
void operator=(const T& other)
{
Value = other;
}
};
class Config
{
public:
static inline std::vector<IConfigDef*> Definitions{};
CONFIG_DEFINE_ENUM_LOCALISED("System", ELanguage, Language, ELanguage::English);
CONFIG_DEFINE_LOCALISED("System", bool, Hints, true);
CONFIG_DEFINE_LOCALISED("System", bool, ControlTutorial, true);

View file

@ -1,193 +0,0 @@
#include "config.h"
#include "config_detail.h"
#include <locale/locale.h>
// CONFIG_DEFINE
template<typename T>
ConfigDef<T>::ConfigDef(std::string section, std::string name, T defaultValue) : Section(section), Name(name), DefaultValue(defaultValue)
{
Config::Definitions.emplace_back(this);
}
// CONFIG_DEFINE_LOCALISED
template<typename T>
ConfigDef<T>::ConfigDef(std::string section, std::string name, CONFIG_LOCALE* locale, T defaultValue)
: Section(section), Name(name), Locale(locale), DefaultValue(defaultValue)
{
Config::Definitions.emplace_back(this);
}
// CONFIG_DEFINE_ENUM
template<typename T>
ConfigDef<T>::ConfigDef(std::string section, std::string name, T defaultValue, std::unordered_map<std::string, T>* enumTemplate)
: Section(section), Name(name), DefaultValue(defaultValue), EnumTemplate(enumTemplate)
{
for (const auto& pair : *EnumTemplate)
EnumTemplateReverse[pair.second] = pair.first;
Config::Definitions.emplace_back(this);
}
// CONFIG_DEFINE_ENUM_LOCALISED
template<typename T>
ConfigDef<T>::ConfigDef(std::string section, std::string name, CONFIG_LOCALE* locale, T defaultValue, std::unordered_map<std::string, T>* enumTemplate, CONFIG_ENUM_LOCALE(T)* enumLocale)
: Section(section), Name(name), Locale(locale), DefaultValue(defaultValue), EnumTemplate(enumTemplate), EnumLocale(enumLocale)
{
for (const auto& pair : *EnumTemplate)
EnumTemplateReverse[pair.second] = pair.first;
Config::Definitions.emplace_back(this);
}
// CONFIG_DEFINE_CALLBACK
template<typename T>
ConfigDef<T>::ConfigDef(std::string section, std::string name, T defaultValue, std::function<void(ConfigDef<T>*)> callback)
: Section(section), Name(name), DefaultValue(defaultValue), Callback(callback)
{
Config::Definitions.emplace_back(this);
}
template<typename T>
std::string ConfigDef<T>::GetNameLocalised() const
{
if (!Locale)
return Name;
if (!Locale->count(Config::Language))
{
if (Locale->count(ELanguage::English))
{
return std::get<0>(Locale->at(ELanguage::English));
}
else
{
return Name;
}
}
return std::get<0>(Locale->at(Config::Language));
}
template<typename T>
std::string ConfigDef<T>::GetDescription() const
{
if (!Locale)
return "";
if (!Locale->count(Config::Language))
{
if (Locale->count(ELanguage::English))
{
return std::get<1>(Locale->at(ELanguage::English));
}
else
{
return "";
}
}
return std::get<1>(Locale->at(Config::Language));
}
template<typename T>
std::string ConfigDef<T>::GetValueLocalised() const
{
auto language = Config::Language;
CONFIG_ENUM_LOCALE(T)* locale = nullptr;
if constexpr (std::is_enum_v<T>)
{
locale = EnumLocale;
}
else if constexpr (std::is_same_v<T, bool>)
{
return Value
? Localise("Common_On")
: Localise("Common_Off");
}
if (!locale)
return ToString(false);
if (!locale->count(language))
{
if (locale->count(ELanguage::English))
{
language = ELanguage::English;
}
else
{
return ToString(false);
}
}
auto strings = locale->at(language);
if (!strings.count(Value))
return ToString(false);
return std::get<0>(strings.at(Value));
}
template<typename T>
std::string ConfigDef<T>::GetValueDescription() const
{
auto language = Config::Language;
CONFIG_ENUM_LOCALE(T)* locale = nullptr;
if constexpr (std::is_enum_v<T>)
{
locale = EnumLocale;
}
else if constexpr (std::is_same_v<T, bool>)
{
return "";
}
if (!locale)
return "";
if (!locale->count(language))
{
if (locale->count(ELanguage::English))
{
language = ELanguage::English;
}
else
{
return "";
}
}
auto strings = locale->at(language);
if (!strings.count(Value))
return "";
return std::get<1>(strings.at(Value));
}
template<typename T>
inline void ConfigDef<T>::GetLocaleStrings(std::vector<std::string_view>& localeStrings) const
{
if (Locale != nullptr)
{
for (auto& [language, nameAndDesc] : *Locale)
{
localeStrings.push_back(std::get<0>(nameAndDesc));
localeStrings.push_back(std::get<1>(nameAndDesc));
}
}
if (EnumLocale != nullptr)
{
for (auto& [language, locale] : *EnumLocale)
{
for (auto& [value, nameAndDesc] : locale)
{
localeStrings.push_back(std::get<0>(nameAndDesc));
localeStrings.push_back(std::get<1>(nameAndDesc));
}
}
}
}

View file

@ -1,440 +0,0 @@
#pragma once
#define CONFIG_LOCALE std::unordered_map<ELanguage, std::tuple<std::string, std::string>>
#define CONFIG_ENUM_LOCALE(type) std::unordered_map<ELanguage, std::unordered_map<type, std::tuple<std::string, std::string>>>
#define CONFIG_DEFINE(section, type, name, defaultValue) \
static inline ConfigDef<type> name{section, #name, defaultValue};
#define CONFIG_DEFINE_LOCALISED(section, type, name, defaultValue) \
static CONFIG_LOCALE g_##name##_locale; \
static inline ConfigDef<type> name{section, #name, &g_##name##_locale, defaultValue};
#define CONFIG_DEFINE_ENUM(section, type, name, defaultValue) \
static inline ConfigDef<type> name{section, #name, defaultValue, &g_##type##_template};
#define CONFIG_DEFINE_ENUM_LOCALISED(section, type, name, defaultValue) \
static CONFIG_LOCALE g_##name##_locale; \
static CONFIG_ENUM_LOCALE(type) g_##type##_locale; \
static inline ConfigDef<type> name{section, #name, &g_##name##_locale, defaultValue, &g_##type##_template, &g_##type##_locale};
#define CONFIG_DEFINE_CALLBACK(section, type, name, defaultValue, readCallback) \
static CONFIG_LOCALE g_##name##_locale; \
static inline ConfigDef<type> name{section, #name, defaultValue, [](ConfigDef<type>* def) readCallback};
#define CONFIG_DEFINE_ENUM_TEMPLATE(type) \
inline std::unordered_map<std::string, type> g_##type##_template =
#define WINDOWPOS_CENTRED 0x2FFF0000
enum class ELanguage : uint32_t
{
English = 1,
Japanese,
German,
French,
Spanish,
Italian
};
CONFIG_DEFINE_ENUM_TEMPLATE(ELanguage)
{
{ "English", ELanguage::English },
{ "Japanese", ELanguage::Japanese },
{ "German", ELanguage::German },
{ "French", ELanguage::French },
{ "Spanish", ELanguage::Spanish },
{ "Italian", ELanguage::Italian }
};
enum class EUnleashGaugeBehaviour : uint32_t
{
Original,
Revised
};
CONFIG_DEFINE_ENUM_TEMPLATE(EUnleashGaugeBehaviour)
{
{ "Original", EUnleashGaugeBehaviour::Original },
{ "Revised", EUnleashGaugeBehaviour::Revised }
};
enum class ETimeOfDayTransition : uint32_t
{
Xbox,
PlayStation
};
CONFIG_DEFINE_ENUM_TEMPLATE(ETimeOfDayTransition)
{
{ "Xbox", ETimeOfDayTransition::Xbox },
{ "PlayStation", ETimeOfDayTransition::PlayStation }
};
enum class EControllerIcons : uint32_t
{
Auto,
Xbox,
PlayStation
};
CONFIG_DEFINE_ENUM_TEMPLATE(EControllerIcons)
{
{ "Auto", EControllerIcons::Auto },
{ "Xbox", EControllerIcons::Xbox },
{ "PlayStation", EControllerIcons::PlayStation }
};
enum class EVoiceLanguage : uint32_t
{
English,
Japanese
};
CONFIG_DEFINE_ENUM_TEMPLATE(EVoiceLanguage)
{
{ "English", EVoiceLanguage::English },
{ "Japanese", EVoiceLanguage::Japanese }
};
enum class EGraphicsAPI : uint32_t
{
#ifdef SWA_D3D12
D3D12,
#endif
Vulkan
};
CONFIG_DEFINE_ENUM_TEMPLATE(EGraphicsAPI)
{
#ifdef SWA_D3D12
{ "D3D12", EGraphicsAPI::D3D12 },
#endif
{ "Vulkan", EGraphicsAPI::Vulkan }
};
enum class EWindowState : uint32_t
{
Normal,
Maximised
};
CONFIG_DEFINE_ENUM_TEMPLATE(EWindowState)
{
{ "Normal", EWindowState::Normal },
{ "Maximised", EWindowState::Maximised },
{ "Maximized", EWindowState::Maximised }
};
enum class EAspectRatio : uint32_t
{
Auto,
Square,
Widescreen
};
CONFIG_DEFINE_ENUM_TEMPLATE(EAspectRatio)
{
{ "Auto", EAspectRatio::Auto },
{ "4:3", EAspectRatio::Square },
{ "16:9", EAspectRatio::Widescreen }
};
enum class ETripleBuffering : uint32_t
{
Auto,
On,
Off
};
CONFIG_DEFINE_ENUM_TEMPLATE(ETripleBuffering)
{
{ "Auto", ETripleBuffering::Auto },
{ "On", ETripleBuffering::On },
{ "Off", ETripleBuffering::Off }
};
enum class EAntiAliasing : uint32_t
{
None = 0,
MSAA2x = 2,
MSAA4x = 4,
MSAA8x = 8
};
CONFIG_DEFINE_ENUM_TEMPLATE(EAntiAliasing)
{
{ "None", EAntiAliasing::None },
{ "2x MSAA", EAntiAliasing::MSAA2x },
{ "4x MSAA", EAntiAliasing::MSAA4x },
{ "8x MSAA", EAntiAliasing::MSAA8x }
};
enum class EShadowResolution : int32_t
{
Original = -1,
x512 = 512,
x1024 = 1024,
x2048 = 2048,
x4096 = 4096,
x8192 = 8192
};
CONFIG_DEFINE_ENUM_TEMPLATE(EShadowResolution)
{
{ "Original", EShadowResolution::Original },
{ "512", EShadowResolution::x512 },
{ "1024", EShadowResolution::x1024 },
{ "2048", EShadowResolution::x2048 },
{ "4096", EShadowResolution::x4096 },
{ "8192", EShadowResolution::x8192 },
};
enum class EGITextureFiltering : uint32_t
{
Bilinear,
Bicubic
};
CONFIG_DEFINE_ENUM_TEMPLATE(EGITextureFiltering)
{
{ "Bilinear", EGITextureFiltering::Bilinear },
{ "Bicubic", EGITextureFiltering::Bicubic }
};
enum class EDepthOfFieldQuality : uint32_t
{
Auto,
Low,
Medium,
High,
Ultra
};
CONFIG_DEFINE_ENUM_TEMPLATE(EDepthOfFieldQuality)
{
{ "Auto", EDepthOfFieldQuality::Auto },
{ "Low", EDepthOfFieldQuality::Low },
{ "Medium", EDepthOfFieldQuality::Medium },
{ "High", EDepthOfFieldQuality::High },
{ "Ultra", EDepthOfFieldQuality::Ultra }
};
enum class EMotionBlur : uint32_t
{
Off,
Original,
Enhanced
};
CONFIG_DEFINE_ENUM_TEMPLATE(EMotionBlur)
{
{ "Off", EMotionBlur::Off },
{ "Original", EMotionBlur::Original },
{ "Enhanced", EMotionBlur::Enhanced }
};
enum class EMovieScaleMode : uint32_t
{
Stretch,
Fit,
Fill
};
CONFIG_DEFINE_ENUM_TEMPLATE(EMovieScaleMode)
{
{ "Stretch", EMovieScaleMode::Stretch },
{ "Fit", EMovieScaleMode::Fit },
{ "Fill", EMovieScaleMode::Fill }
};
enum class EUIScaleMode : uint32_t
{
Stretch,
Edge,
Centre
};
CONFIG_DEFINE_ENUM_TEMPLATE(EUIScaleMode)
{
{ "Stretch", EUIScaleMode::Stretch },
{ "Edge", EUIScaleMode::Edge },
{ "Centre", EUIScaleMode::Centre },
{ "Center", EUIScaleMode::Centre }
};
class IConfigDef
{
public:
virtual ~IConfigDef() = default;
virtual void ReadValue(toml::v3::ex::parse_result& toml) = 0;
virtual void MakeDefault() = 0;
virtual std::string_view GetSection() const = 0;
virtual std::string_view GetName() const = 0;
virtual std::string GetNameLocalised() const = 0;
virtual std::string GetDescription() const = 0;
virtual bool IsDefaultValue() const = 0;
virtual const void* GetValue() const = 0;
virtual std::string GetValueLocalised() const = 0;
virtual std::string GetValueDescription() const = 0;
virtual std::string GetDefinition(bool withSection = false) const = 0;
virtual std::string ToString(bool strWithQuotes = true) const = 0;
virtual void GetLocaleStrings(std::vector<std::string_view>& localeStrings) const = 0;
};
template<typename T>
class ConfigDef final : public IConfigDef
{
public:
std::string Section{};
std::string Name{};
CONFIG_LOCALE* Locale{};
T DefaultValue{};
T Value{ DefaultValue };
std::unordered_map<std::string, T>* EnumTemplate;
std::map<T, std::string> EnumTemplateReverse{};
CONFIG_ENUM_LOCALE(T)* EnumLocale{};
std::function<void(ConfigDef<T>*)> Callback;
// CONFIG_DEFINE
ConfigDef(std::string section, std::string name, T defaultValue);
// CONFIG_DEFINE_LOCALISED
ConfigDef(std::string section, std::string name, CONFIG_LOCALE* nameLocale, T defaultValue);
// CONFIG_DEFINE_ENUM
ConfigDef(std::string section, std::string name, T defaultValue, std::unordered_map<std::string, T>* enumTemplate);
// CONFIG_DEFINE_ENUM_LOCALISED
ConfigDef(std::string section, std::string name, CONFIG_LOCALE* nameLocale, T defaultValue, std::unordered_map<std::string, T>* enumTemplate, CONFIG_ENUM_LOCALE(T)* enumLocale);
// CONFIG_DEFINE_CALLBACK
ConfigDef(std::string section, std::string name, T defaultValue, std::function<void(ConfigDef<T>*)> callback);
void ReadValue(toml::v3::ex::parse_result& toml) override
{
if (auto pSection = toml[Section].as_table())
{
const auto& section = *pSection;
if constexpr (std::is_same<T, std::string>::value)
{
Value = section[Name].value_or<std::string>(DefaultValue);
}
else if constexpr (std::is_enum_v<T>)
{
std::string value = section[Name].value_or(std::string());
auto it = EnumTemplate->find(value);
if (it != EnumTemplate->end())
{
Value = it->second;
}
else
{
Value = DefaultValue;
}
}
else
{
Value = section[Name].value_or(DefaultValue);
}
if (Callback)
Callback(this);
}
}
void MakeDefault() override
{
Value = DefaultValue;
}
std::string_view GetSection() const override
{
return Section;
}
std::string_view GetName() const override
{
return Name;
}
std::string GetNameLocalised() const override;
std::string GetDescription() const override;
bool IsDefaultValue() const override
{
return Value == DefaultValue;
}
const void* GetValue() const override
{
return &Value;
}
std::string GetValueLocalised() const override;
std::string GetValueDescription() const override;
std::string GetDefinition(bool withSection = false) const override
{
std::string result;
if (withSection)
result += "[" + Section + "]\n";
result += Name + " = " + ToString();
return result;
}
std::string ToString(bool strWithQuotes = true) const override
{
std::string result = "N/A";
if constexpr (std::is_same_v<T, std::string>)
{
result = fmt::format("{}", Value);
if (strWithQuotes)
result = fmt::format("\"{}\"", result);
}
else if constexpr (std::is_enum_v<T>)
{
auto it = EnumTemplateReverse.find(Value);
if (it != EnumTemplateReverse.end())
result = fmt::format("{}", it->second);
if (strWithQuotes)
result = fmt::format("\"{}\"", result);
}
else
{
result = fmt::format("{}", Value);
}
return result;
}
void GetLocaleStrings(std::vector<std::string_view>& localeStrings) const override;
ConfigDef& operator=(const ConfigDef& other)
{
if (this != &other)
Value = other.Value;
return *this;
}
operator T() const
{
return Value;
}
void operator=(const T& other)
{
Value = other;
}
};

View file

@ -30,13 +30,12 @@ inline std::filesystem::path GetUserPath()
if (homeDir != nullptr)
{
// Prefer to store in the .config directory if it exists. Use the home directory otherwise.
const std::string dirName = "." USER_DIRECTORY;
std::filesystem::path homePath = homeDir;
std::filesystem::path configPath = homePath / ".config";
if (std::filesystem::exists(configPath))
userPath = configPath / dirName;
userPath = configPath / USER_DIRECTORY;
else
userPath = homePath / dirName;
userPath = homePath / ("." USER_DIRECTORY);
}
#else
static_assert(false, "GetUserPath() not implemented for this platform.");

View file

@ -1,11 +1,17 @@
project("UnleashedRecompLib")
add_compile_options(
"/fp:strict"
"-march=sandybridge"
"-fno-strict-aliasing"
-march=sandybridge
-mlzcnt
-fno-strict-aliasing
)
if (WIN32)
add_compile_options(/fp:strict)
else()
add_compile_options(-ffp-model=strict)
endif()
target_compile_definitions(PowerRecomp PRIVATE CONFIG_FILE_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml\")
set(SWA_PPC_RECOMPILED_SOURCES
@ -21,7 +27,7 @@ endforeach()
add_custom_command(
OUTPUT ${SWA_PPC_RECOMPILED_SOURCES}
COMMAND PowerRecomp
COMMAND $<TARGET_FILE:PowerRecomp>
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/private/default.xex" "${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml"
)
@ -41,7 +47,7 @@ file(GLOB SHADER_RECOMP_SOURCES
add_custom_command(
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp"
COMMAND ShaderRecomp
COMMAND $<TARGET_FILE:ShaderRecomp>
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/private/shader.ar" ${SHADER_RECOMP_SOURCES} ${SHADER_RECOMP_INCLUDE}
)

View file

@ -3,5 +3,9 @@ set(MSDF_ATLAS_USE_SKIA OFF)
set(MSDF_ATLAS_NO_ARTERY_FONT ON)
set(MSDFGEN_DISABLE_PNG ON)
add_subdirectory(${SWA_THIRDPARTY_ROOT}/o1heap)
add_subdirectory(${SWA_THIRDPARTY_ROOT}/msdf-atlas-gen)
add_subdirectory("${SWA_THIRDPARTY_ROOT}/msdf-atlas-gen")
add_subdirectory("${SWA_THIRDPARTY_ROOT}/nativefiledialog-extended")
add_subdirectory("${SWA_THIRDPARTY_ROOT}/ogg")
add_subdirectory("${SWA_THIRDPARTY_ROOT}/o1heap")
add_subdirectory("${SWA_THIRDPARTY_ROOT}/SDL")
add_subdirectory("${SWA_THIRDPARTY_ROOT}/vorbis")

1
thirdparty/D3D12MemoryAllocator vendored Submodule

@ -0,0 +1 @@
Subproject commit e00c4a7c85cf9c28c6f4a6cc75032736f416410f

1
thirdparty/SDL vendored Submodule

@ -0,0 +1 @@
Subproject commit 1edaad17218d67b567c149badce9ef0fc67f65fa

1
thirdparty/Vulkan-Headers vendored Submodule

@ -0,0 +1 @@
Subproject commit 14345dab231912ee9601136e96ca67a6e1f632e7

1
thirdparty/VulkanMemoryAllocator vendored Submodule

@ -0,0 +1 @@
Subproject commit 1c35ba99ce775f8342d87a83a3f0f696f99c2a39

1
thirdparty/concurrentqueue vendored Submodule

@ -0,0 +1 @@
Subproject commit 6dd38b8a1dbaa7863aa907045f32308a56a6ff5d

1
thirdparty/imgui vendored Submodule

@ -0,0 +1 @@
Subproject commit 8199457a7d9e453f8d3d9cadc14683fb54a858b5

1
thirdparty/magic_enum vendored Submodule

@ -0,0 +1 @@
Subproject commit 1a1824df7ac798177a521eed952720681b0bf482

@ -0,0 +1 @@
Subproject commit 388549a5badaa7cbd138f5f189f50c67d5bf060c

1
thirdparty/ogg vendored Submodule

@ -0,0 +1 @@
Subproject commit 7cf42ea17aef7bc1b7b21af70724840a96c2e7d0

1
thirdparty/stb vendored Submodule

@ -0,0 +1 @@
Subproject commit 5c205738c191bcb0abc65c4febfa9bd25ff35234

1
thirdparty/tiny-AES-c vendored Submodule

@ -0,0 +1 @@
Subproject commit 23856752fbd139da0b8ca6e471a13d5bcc99a08d

1
thirdparty/unordered_dense vendored Submodule

@ -0,0 +1 @@
Subproject commit d911053e390816ecc5dedd5a9d6b4bb5ed92b4c9

2
thirdparty/vcpkg vendored

@ -1 +1 @@
Subproject commit 19847ac3d8cad7599e96bd531f9bc1f0ebae6131
Subproject commit b322364f06308bdd24823f9d8f03fe0cc86fd46f

1
thirdparty/volk vendored Submodule

@ -0,0 +1 @@
Subproject commit 447e21b5d92ed8d5271b0d39b071f938fcfa875f

1
thirdparty/vorbis vendored Submodule

@ -0,0 +1 @@
Subproject commit 84c023699cdf023a32fa4ded32019f194afcdad0

@ -1 +1 @@
Subproject commit 45c00cfec6c2ad141ebf8fce1f5dbcdde2816e94
Subproject commit 14b7fd3445857a44ad91b832592cffb069451e4f

@ -1 +1 @@
Subproject commit 4b69741e196e0a8aed9d51bbe0cf24019afab08e
Subproject commit cf44a5e6fb7c9931888ee4e6506109787141f87e

View file

@ -6,5 +6,4 @@ set(CMAKE_CXX_STANDARD 17)
add_executable(bc_diff "bc_diff.cpp")
add_compile_definitions(bc_diff PRIVATE _CRT_SECURE_NO_WARNINGS)
find_package(xxHash CONFIG REQUIRED)
target_link_libraries(bc_diff PRIVATE xxHash::xxhash)

View file

@ -7,5 +7,4 @@ set(CMAKE_CXX_STANDARD 17)
add_executable(file_to_c "file_to_c.cpp")
find_package(zstd CONFIG REQUIRED)
target_link_libraries(file_to_c PRIVATE $<IF:$<TARGET_EXISTS:zstd::libzstd_static>,zstd::libzstd_static,zstd::libzstd>)
target_link_libraries(file_to_c PRIVATE $<IF:$<TARGET_EXISTS:libzstd_static>,libzstd_static,libzstd_shared>)

View file

@ -110,8 +110,8 @@ int main(int argc, const char** argv) {
// Write decompressed size.
if (!compressed_contents.empty()) {
output_c_file << "extern size_t " << array_name << "_uncompressed_size;\n";
output_c_file << "size_t " << array_name << "_uncompressed_size = " << contents.size() << ";\n";
output_c_file << "extern unsigned long long " << array_name << "_uncompressed_size;\n";
output_c_file << "unsigned long long " << array_name << "_uncompressed_size = " << contents.size() << ";\n";
}
}
@ -126,7 +126,7 @@ int main(int argc, const char** argv) {
// Write decompressed size.
if (!compressed_contents.empty()) {
output_h_file << "extern size_t " << array_name << "_uncompressed_size;\n";
output_h_file << "extern unsigned long long " << array_name << "_uncompressed_size;\n";
}
output_h_file <<

View file

@ -2,6 +2,4 @@ project("fshasher")
add_executable(fshasher "fshasher.cpp")
find_package(xxHash CONFIG REQUIRED)
target_link_libraries(fshasher PRIVATE xxHash::xxhash)

View file

@ -1,5 +1,5 @@
{
"builtin-baseline": "e63bd09dc0b7204467705c1c7c71d0e2a3f8860b",
"builtin-baseline": "b322364f06308bdd24823f9d8f03fe0cc86fd46f",
"dependencies": [
{
"name": "directx-headers",
@ -9,34 +9,7 @@
"name": "directx12-agility",
"platform": "windows"
},
{
"name": "d3d12-memory-allocator",
"platform": "windows"
},
{
"name": "pkgconf",
"platform": "windows"
},
{
"name": "imgui",
"features": [ "sdl2-binding" ]
},
"directx-dxc",
"sdl2",
"unordered-dense",
"volk",
"vulkan-headers",
"vulkan-memory-allocator",
"xxhash",
"tomlplusplus",
"zstd",
"stb",
"concurrentqueue",
"tiny-aes-c",
"magic-enum",
"nativefiledialog-extended",
"freetype",
"libvorbis",
"fmt"
"freetype"
]
}