Merge branch 'shadps4-emu:main' into audio-but-3d
4
.gitmodules
vendored
@ -6,10 +6,6 @@
|
|||||||
path = externals/cryptopp
|
path = externals/cryptopp
|
||||||
url = https://github.com/shadps4-emu/ext-cryptopp.git
|
url = https://github.com/shadps4-emu/ext-cryptopp.git
|
||||||
shallow = true
|
shallow = true
|
||||||
[submodule "externals/cryptoppwin"]
|
|
||||||
path = externals/cryptoppwin
|
|
||||||
url = https://github.com/shadps4-emu/ext-cryptoppwin.git
|
|
||||||
shallow = true
|
|
||||||
[submodule "externals/zlib-ng"]
|
[submodule "externals/zlib-ng"]
|
||||||
path = externals/zlib-ng
|
path = externals/zlib-ng
|
||||||
url = https://github.com/shadps4-emu/ext-zlib-ng.git
|
url = https://github.com/shadps4-emu/ext-zlib-ng.git
|
||||||
|
@ -37,8 +37,10 @@ option(ENABLE_UPDATER "Enables the options to updater" ON)
|
|||||||
# First, determine whether to use CMAKE_OSX_ARCHITECTURES or CMAKE_SYSTEM_PROCESSOR.
|
# First, determine whether to use CMAKE_OSX_ARCHITECTURES or CMAKE_SYSTEM_PROCESSOR.
|
||||||
if (APPLE AND CMAKE_OSX_ARCHITECTURES)
|
if (APPLE AND CMAKE_OSX_ARCHITECTURES)
|
||||||
set(BASE_ARCHITECTURE "${CMAKE_OSX_ARCHITECTURES}")
|
set(BASE_ARCHITECTURE "${CMAKE_OSX_ARCHITECTURES}")
|
||||||
else()
|
elseif (CMAKE_SYSTEM_PROCESSOR)
|
||||||
set(BASE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}")
|
set(BASE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}")
|
||||||
|
else()
|
||||||
|
set(BASE_ARCHITECTURE "${CMAKE_HOST_SYSTEM_PROCESSOR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Next, match common architecture strings down to a known common value.
|
# Next, match common architecture strings down to a known common value.
|
||||||
@ -50,7 +52,12 @@ else()
|
|||||||
message(FATAL_ERROR "Unsupported CPU architecture: ${BASE_ARCHITECTURE}")
|
message(FATAL_ERROR "Unsupported CPU architecture: ${BASE_ARCHITECTURE}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
|
if (ARCHITECTURE STREQUAL "x86_64")
|
||||||
|
# Set x86_64 target level to Sandy Bridge to generally match what is supported for PS4 guest code with CPU patches.
|
||||||
|
add_compile_options(-march=sandybridge)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||||
# Exclude ARM homebrew path to avoid conflicts when cross compiling.
|
# Exclude ARM homebrew path to avoid conflicts when cross compiling.
|
||||||
list(APPEND CMAKE_IGNORE_PREFIX_PATH "/opt/homebrew")
|
list(APPEND CMAKE_IGNORE_PREFIX_PATH "/opt/homebrew")
|
||||||
|
|
||||||
@ -298,6 +305,7 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
|||||||
|
|
||||||
set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
||||||
src/core/libraries/network/http.h
|
src/core/libraries/network/http.h
|
||||||
|
src/core/libraries/network/http_error.h
|
||||||
src/core/libraries/network/http2.cpp
|
src/core/libraries/network/http2.cpp
|
||||||
src/core/libraries/network/http2.h
|
src/core/libraries/network/http2.h
|
||||||
src/core/libraries/network/net.cpp
|
src/core/libraries/network/net.cpp
|
||||||
@ -370,6 +378,24 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
|||||||
src/core/libraries/ngs2/ngs2_error.h
|
src/core/libraries/ngs2/ngs2_error.h
|
||||||
src/core/libraries/ngs2/ngs2_impl.cpp
|
src/core/libraries/ngs2/ngs2_impl.cpp
|
||||||
src/core/libraries/ngs2/ngs2_impl.h
|
src/core/libraries/ngs2/ngs2_impl.h
|
||||||
|
src/core/libraries/ngs2/ngs2_custom.cpp
|
||||||
|
src/core/libraries/ngs2/ngs2_custom.h
|
||||||
|
src/core/libraries/ngs2/ngs2_reverb.cpp
|
||||||
|
src/core/libraries/ngs2/ngs2_reverb.h
|
||||||
|
src/core/libraries/ngs2/ngs2_geom.cpp
|
||||||
|
src/core/libraries/ngs2/ngs2_geom.h
|
||||||
|
src/core/libraries/ngs2/ngs2_pan.cpp
|
||||||
|
src/core/libraries/ngs2/ngs2_pan.h
|
||||||
|
src/core/libraries/ngs2/ngs2_report.cpp
|
||||||
|
src/core/libraries/ngs2/ngs2_report.h
|
||||||
|
src/core/libraries/ngs2/ngs2_eq.cpp
|
||||||
|
src/core/libraries/ngs2/ngs2_eq.h
|
||||||
|
src/core/libraries/ngs2/ngs2_mastering.cpp
|
||||||
|
src/core/libraries/ngs2/ngs2_mastering.h
|
||||||
|
src/core/libraries/ngs2/ngs2_sampler.cpp
|
||||||
|
src/core/libraries/ngs2/ngs2_sampler.h
|
||||||
|
src/core/libraries/ngs2/ngs2_submixer.cpp
|
||||||
|
src/core/libraries/ngs2/ngs2_submixer.h
|
||||||
src/core/libraries/ajm/ajm_error.h
|
src/core/libraries/ajm/ajm_error.h
|
||||||
src/core/libraries/audio3d/audio3d.cpp
|
src/core/libraries/audio3d/audio3d.cpp
|
||||||
src/core/libraries/audio3d/audio3d.h
|
src/core/libraries/audio3d/audio3d.h
|
||||||
@ -581,6 +607,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||||||
src/common/spin_lock.h
|
src/common/spin_lock.h
|
||||||
src/common/stb.cpp
|
src/common/stb.cpp
|
||||||
src/common/stb.h
|
src/common/stb.h
|
||||||
|
src/common/string_literal.h
|
||||||
src/common/string_util.cpp
|
src/common/string_util.cpp
|
||||||
src/common/string_util.h
|
src/common/string_util.h
|
||||||
src/common/thread.cpp
|
src/common/thread.cpp
|
||||||
@ -640,8 +667,6 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
src/core/file_format/playgo_chunk.h
|
src/core/file_format/playgo_chunk.h
|
||||||
src/core/file_format/trp.cpp
|
src/core/file_format/trp.cpp
|
||||||
src/core/file_format/trp.h
|
src/core/file_format/trp.h
|
||||||
src/core/file_format/splash.h
|
|
||||||
src/core/file_format/splash.cpp
|
|
||||||
src/core/file_sys/fs.cpp
|
src/core/file_sys/fs.cpp
|
||||||
src/core/file_sys/fs.h
|
src/core/file_sys/fs.h
|
||||||
src/core/loader.cpp
|
src/core/loader.cpp
|
||||||
@ -762,6 +787,7 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||||||
src/shader_recompiler/ir/passes/identity_removal_pass.cpp
|
src/shader_recompiler/ir/passes/identity_removal_pass.cpp
|
||||||
src/shader_recompiler/ir/passes/ir_passes.h
|
src/shader_recompiler/ir/passes/ir_passes.h
|
||||||
src/shader_recompiler/ir/passes/lower_buffer_format_to_raw.cpp
|
src/shader_recompiler/ir/passes/lower_buffer_format_to_raw.cpp
|
||||||
|
src/shader_recompiler/ir/passes/readlane_elimination_pass.cpp
|
||||||
src/shader_recompiler/ir/passes/resource_tracking_pass.cpp
|
src/shader_recompiler/ir/passes/resource_tracking_pass.cpp
|
||||||
src/shader_recompiler/ir/passes/ring_access_elimination.cpp
|
src/shader_recompiler/ir/passes/ring_access_elimination.cpp
|
||||||
src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp
|
src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp
|
||||||
@ -842,6 +868,10 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
|||||||
src/video_core/renderer_vulkan/vk_shader_util.h
|
src/video_core/renderer_vulkan/vk_shader_util.h
|
||||||
src/video_core/renderer_vulkan/vk_swapchain.cpp
|
src/video_core/renderer_vulkan/vk_swapchain.cpp
|
||||||
src/video_core/renderer_vulkan/vk_swapchain.h
|
src/video_core/renderer_vulkan/vk_swapchain.h
|
||||||
|
src/video_core/renderer_vulkan/host_passes/fsr_pass.cpp
|
||||||
|
src/video_core/renderer_vulkan/host_passes/fsr_pass.h
|
||||||
|
src/video_core/renderer_vulkan/host_passes/pp_pass.cpp
|
||||||
|
src/video_core/renderer_vulkan/host_passes/pp_pass.h
|
||||||
src/video_core/texture_cache/image.cpp
|
src/video_core/texture_cache/image.cpp
|
||||||
src/video_core/texture_cache/image.h
|
src/video_core/texture_cache/image.h
|
||||||
src/video_core/texture_cache/image_info.cpp
|
src/video_core/texture_cache/image_info.cpp
|
||||||
@ -914,6 +944,9 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
|
|||||||
src/qt_gui/control_settings.cpp
|
src/qt_gui/control_settings.cpp
|
||||||
src/qt_gui/control_settings.h
|
src/qt_gui/control_settings.h
|
||||||
src/qt_gui/control_settings.ui
|
src/qt_gui/control_settings.ui
|
||||||
|
src/qt_gui/kbm_gui.cpp
|
||||||
|
src/qt_gui/kbm_gui.h
|
||||||
|
src/qt_gui/kbm_gui.ui
|
||||||
src/qt_gui/main_window_ui.h
|
src/qt_gui/main_window_ui.h
|
||||||
src/qt_gui/main_window.cpp
|
src/qt_gui/main_window.cpp
|
||||||
src/qt_gui/main_window.h
|
src/qt_gui/main_window.h
|
||||||
@ -986,7 +1019,7 @@ endif()
|
|||||||
create_target_directory_groups(shadps4)
|
create_target_directory_groups(shadps4)
|
||||||
|
|
||||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
||||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers)
|
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers cryptopp::cryptopp)
|
||||||
|
|
||||||
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
||||||
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
||||||
@ -1035,12 +1068,6 @@ if (NOT ENABLE_QT_GUI)
|
|||||||
target_link_libraries(shadps4 PRIVATE SDL3::SDL3)
|
target_link_libraries(shadps4 PRIVATE SDL3::SDL3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND MSVC)
|
|
||||||
target_link_libraries(shadps4 PRIVATE cryptoppwin)
|
|
||||||
else()
|
|
||||||
target_link_libraries(shadps4 PRIVATE cryptopp::cryptopp)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ENABLE_QT_GUI)
|
if (ENABLE_QT_GUI)
|
||||||
target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network Qt6::Multimedia)
|
target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network Qt6::Multimedia)
|
||||||
add_definitions(-DENABLE_QT_GUI)
|
add_definitions(-DENABLE_QT_GUI)
|
||||||
@ -1111,7 +1138,6 @@ cmrc_add_resource_library(embedded-resources
|
|||||||
src/images/gold.png
|
src/images/gold.png
|
||||||
src/images/platinum.png
|
src/images/platinum.png
|
||||||
src/images/silver.png)
|
src/images/silver.png)
|
||||||
|
|
||||||
target_link_libraries(shadps4 PRIVATE res::embedded)
|
target_link_libraries(shadps4 PRIVATE res::embedded)
|
||||||
|
|
||||||
# ImGui resources
|
# ImGui resources
|
||||||
|
11
REUSE.toml
@ -30,6 +30,7 @@ path = [
|
|||||||
"src/images/dump_icon.png",
|
"src/images/dump_icon.png",
|
||||||
"src/images/exit_icon.png",
|
"src/images/exit_icon.png",
|
||||||
"src/images/file_icon.png",
|
"src/images/file_icon.png",
|
||||||
|
"src/images/trophy_icon.png",
|
||||||
"src/images/flag_china.png",
|
"src/images/flag_china.png",
|
||||||
"src/images/flag_eu.png",
|
"src/images/flag_eu.png",
|
||||||
"src/images/flag_jp.png",
|
"src/images/flag_jp.png",
|
||||||
@ -41,14 +42,17 @@ path = [
|
|||||||
"src/images/grid_icon.png",
|
"src/images/grid_icon.png",
|
||||||
"src/images/keyboard_icon.png",
|
"src/images/keyboard_icon.png",
|
||||||
"src/images/iconsize_icon.png",
|
"src/images/iconsize_icon.png",
|
||||||
|
"src/images/KBM.png",
|
||||||
"src/images/ko-fi.png",
|
"src/images/ko-fi.png",
|
||||||
"src/images/list_icon.png",
|
"src/images/list_icon.png",
|
||||||
"src/images/list_mode_icon.png",
|
"src/images/list_mode_icon.png",
|
||||||
"src/images/pause_icon.png",
|
"src/images/pause_icon.png",
|
||||||
"src/images/play_icon.png",
|
"src/images/play_icon.png",
|
||||||
"src/images/ps4_controller.png",
|
"src/images/ps4_controller.png",
|
||||||
"src/images/refresh_icon.png",
|
"src/images/restart_game_icon.png",
|
||||||
|
"src/images/refreshlist_icon.png",
|
||||||
"src/images/settings_icon.png",
|
"src/images/settings_icon.png",
|
||||||
|
"src/images/fullscreen_icon.png",
|
||||||
"src/images/stop_icon.png",
|
"src/images/stop_icon.png",
|
||||||
"src/images/utils_icon.png",
|
"src/images/utils_icon.png",
|
||||||
"src/images/shadPS4.icns",
|
"src/images/shadPS4.icns",
|
||||||
@ -111,3 +115,8 @@ SPDX-License-Identifier = "CC0-1.0"
|
|||||||
path = "cmake/CMakeRC.cmake"
|
path = "cmake/CMakeRC.cmake"
|
||||||
SPDX-FileCopyrightText = "Copyright (c) 2017 vector-of-bool <vectorofbool@gmail.com>"
|
SPDX-FileCopyrightText = "Copyright (c) 2017 vector-of-bool <vectorofbool@gmail.com>"
|
||||||
SPDX-License-Identifier = "MIT"
|
SPDX-License-Identifier = "MIT"
|
||||||
|
|
||||||
|
[[annotations]]
|
||||||
|
path = "src/video_core/host_shaders/fsr/*"
|
||||||
|
SPDX-FileCopyrightText = "Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved."
|
||||||
|
SPDX-License-Identifier = "MIT"
|
||||||
|
3
dist/net.shadps4.shadPS4.metainfo.xml
vendored
@ -37,6 +37,9 @@
|
|||||||
<category translate="no">Game</category>
|
<category translate="no">Game</category>
|
||||||
</categories>
|
</categories>
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="0.7.0" date="2025-03-23">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.7.0</url>
|
||||||
|
</release>
|
||||||
<release version="0.6.0" date="2025-01-31">
|
<release version="0.6.0" date="2025-01-31">
|
||||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.6.0</url>
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.6.0</url>
|
||||||
</release>
|
</release>
|
||||||
|
11
externals/CMakeLists.txt
vendored
@ -26,23 +26,20 @@ if (NOT TARGET fmt::fmt)
|
|||||||
add_subdirectory(fmt)
|
add_subdirectory(fmt)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND MSVC)
|
|
||||||
# If it is clang and MSVC we will add a static lib
|
|
||||||
# CryptoPP
|
|
||||||
add_subdirectory(cryptoppwin)
|
|
||||||
target_include_directories(cryptoppwin INTERFACE cryptoppwin/include)
|
|
||||||
else()
|
|
||||||
# CryptoPP
|
# CryptoPP
|
||||||
if (NOT TARGET cryptopp::cryptopp)
|
if (NOT TARGET cryptopp::cryptopp)
|
||||||
set(CRYPTOPP_INSTALL OFF)
|
set(CRYPTOPP_INSTALL OFF)
|
||||||
set(CRYPTOPP_BUILD_TESTING OFF)
|
set(CRYPTOPP_BUILD_TESTING OFF)
|
||||||
set(CRYPTOPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cryptopp)
|
set(CRYPTOPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cryptopp)
|
||||||
|
# cryptopp instruction set checks do not account for added compile options,
|
||||||
|
# so disable extensions in the library config to match our chosen target CPU.
|
||||||
|
set(CRYPTOPP_DISABLE_AESNI ON)
|
||||||
|
set(CRYPTOPP_DISABLE_AVX2 ON)
|
||||||
add_subdirectory(cryptopp-cmake)
|
add_subdirectory(cryptopp-cmake)
|
||||||
file(COPY cryptopp DESTINATION cryptopp FILES_MATCHING PATTERN "*.h")
|
file(COPY cryptopp DESTINATION cryptopp FILES_MATCHING PATTERN "*.h")
|
||||||
# remove externals/cryptopp from include directories because it contains a conflicting zlib.h file
|
# remove externals/cryptopp from include directories because it contains a conflicting zlib.h file
|
||||||
set_target_properties(cryptopp PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/cryptopp")
|
set_target_properties(cryptopp PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/cryptopp")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT TARGET FFmpeg::ffmpeg)
|
if (NOT TARGET FFmpeg::ffmpeg)
|
||||||
add_subdirectory(ffmpeg-core)
|
add_subdirectory(ffmpeg-core)
|
||||||
|
2
externals/cryptopp
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 60f81a77e0c9a0e7ffc1ca1bc438ddfa2e43b78e
|
Subproject commit effed0d0b865afc23ed67e0916f83734e4b9b3b7
|
1
externals/cryptoppwin
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit bc3441dd2d6a9728e747dc0180bc8b9065a2923c
|
|
@ -32,6 +32,7 @@ std::filesystem::path find_fs_path_or(const basic_value<TC>& v, const K& ky,
|
|||||||
namespace Config {
|
namespace Config {
|
||||||
|
|
||||||
static bool isNeo = false;
|
static bool isNeo = false;
|
||||||
|
static bool isDevKit = false;
|
||||||
static bool playBGM = false;
|
static bool playBGM = false;
|
||||||
static bool isTrophyPopupDisabled = false;
|
static bool isTrophyPopupDisabled = false;
|
||||||
static int BGMvolume = 50;
|
static int BGMvolume = 50;
|
||||||
@ -53,6 +54,7 @@ static bool isShaderDebug = false;
|
|||||||
static bool isShowSplash = false;
|
static bool isShowSplash = false;
|
||||||
static bool isAutoUpdate = false;
|
static bool isAutoUpdate = false;
|
||||||
static bool isAlwaysShowChangelog = false;
|
static bool isAlwaysShowChangelog = false;
|
||||||
|
static std::string isSideTrophy = "right";
|
||||||
static bool isNullGpu = false;
|
static bool isNullGpu = false;
|
||||||
static bool shouldCopyGPUBuffers = false;
|
static bool shouldCopyGPUBuffers = false;
|
||||||
static bool shouldDumpShaders = false;
|
static bool shouldDumpShaders = false;
|
||||||
@ -69,6 +71,7 @@ static bool isFpsColor = true;
|
|||||||
static bool isSeparateLogFilesEnabled = false;
|
static bool isSeparateLogFilesEnabled = false;
|
||||||
static s16 cursorState = HideCursorState::Idle;
|
static s16 cursorState = HideCursorState::Idle;
|
||||||
static int cursorHideTimeout = 5; // 5 seconds (default)
|
static int cursorHideTimeout = 5; // 5 seconds (default)
|
||||||
|
static double trophyNotificationDuration = 6.0;
|
||||||
static bool useUnifiedInputConfig = true;
|
static bool useUnifiedInputConfig = true;
|
||||||
static bool overrideControllerColor = false;
|
static bool overrideControllerColor = false;
|
||||||
static int controllerCustomColorRGB[3] = {0, 0, 255};
|
static int controllerCustomColorRGB[3] = {0, 0, 255};
|
||||||
@ -79,7 +82,8 @@ static std::string trophyKey;
|
|||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
static bool load_game_size = true;
|
static bool load_game_size = true;
|
||||||
std::vector<std::filesystem::path> settings_install_dirs = {};
|
static std::vector<GameInstallDir> settings_install_dirs = {};
|
||||||
|
std::vector<bool> install_dirs_enabled = {};
|
||||||
std::filesystem::path settings_addon_install_dir = {};
|
std::filesystem::path settings_addon_install_dir = {};
|
||||||
std::filesystem::path save_data_path = {};
|
std::filesystem::path save_data_path = {};
|
||||||
u32 main_window_geometry_x = 400;
|
u32 main_window_geometry_x = 400;
|
||||||
@ -103,6 +107,7 @@ static bool showBackgroundImage = true;
|
|||||||
static bool isFullscreen = false;
|
static bool isFullscreen = false;
|
||||||
static std::string fullscreenMode = "Windowed";
|
static std::string fullscreenMode = "Windowed";
|
||||||
static bool isHDRAllowed = false;
|
static bool isHDRAllowed = false;
|
||||||
|
static bool showLabelsUnderIcons = true;
|
||||||
|
|
||||||
// Language
|
// Language
|
||||||
u32 m_language = 1; // english
|
u32 m_language = 1; // english
|
||||||
@ -164,10 +169,22 @@ bool isNeoModeConsole() {
|
|||||||
return isNeo;
|
return isNeo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isDevKitConsole() {
|
||||||
|
return isDevKit;
|
||||||
|
}
|
||||||
|
|
||||||
bool getIsFullscreen() {
|
bool getIsFullscreen() {
|
||||||
return isFullscreen;
|
return isFullscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool getShowLabelsUnderIcons() {
|
||||||
|
return showLabelsUnderIcons;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setShowLabelsUnderIcons() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::string getFullscreenMode() {
|
std::string getFullscreenMode() {
|
||||||
return fullscreenMode;
|
return fullscreenMode;
|
||||||
}
|
}
|
||||||
@ -196,6 +213,10 @@ int getCursorHideTimeout() {
|
|||||||
return cursorHideTimeout;
|
return cursorHideTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double getTrophyNotificationDuration() {
|
||||||
|
return trophyNotificationDuration;
|
||||||
|
}
|
||||||
|
|
||||||
u32 getScreenWidth() {
|
u32 getScreenWidth() {
|
||||||
return screenWidth;
|
return screenWidth;
|
||||||
}
|
}
|
||||||
@ -264,6 +285,10 @@ bool alwaysShowChangelog() {
|
|||||||
return isAlwaysShowChangelog;
|
return isAlwaysShowChangelog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string sideTrophy() {
|
||||||
|
return isSideTrophy;
|
||||||
|
}
|
||||||
|
|
||||||
bool nullGpu() {
|
bool nullGpu() {
|
||||||
return isNullGpu;
|
return isNullGpu;
|
||||||
}
|
}
|
||||||
@ -372,6 +397,10 @@ void setAlwaysShowChangelog(bool enable) {
|
|||||||
isAlwaysShowChangelog = enable;
|
isAlwaysShowChangelog = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setSideTrophy(std::string side) {
|
||||||
|
isSideTrophy = side;
|
||||||
|
}
|
||||||
|
|
||||||
void setNullGpu(bool enable) {
|
void setNullGpu(bool enable) {
|
||||||
isNullGpu = enable;
|
isNullGpu = enable;
|
||||||
}
|
}
|
||||||
@ -407,6 +436,9 @@ void setVblankDiv(u32 value) {
|
|||||||
void setIsFullscreen(bool enable) {
|
void setIsFullscreen(bool enable) {
|
||||||
isFullscreen = enable;
|
isFullscreen = enable;
|
||||||
}
|
}
|
||||||
|
static void setShowLabelsUnderIcons(bool enable) {
|
||||||
|
showLabelsUnderIcons = enable;
|
||||||
|
}
|
||||||
|
|
||||||
void setFullscreenMode(std::string mode) {
|
void setFullscreenMode(std::string mode) {
|
||||||
fullscreenMode = mode;
|
fullscreenMode = mode;
|
||||||
@ -435,6 +467,9 @@ void setCursorState(s16 newCursorState) {
|
|||||||
void setCursorHideTimeout(int newcursorHideTimeout) {
|
void setCursorHideTimeout(int newcursorHideTimeout) {
|
||||||
cursorHideTimeout = newcursorHideTimeout;
|
cursorHideTimeout = newcursorHideTimeout;
|
||||||
}
|
}
|
||||||
|
void setTrophyNotificationDuration(double newTrophyNotificationDuration) {
|
||||||
|
trophyNotificationDuration = newTrophyNotificationDuration;
|
||||||
|
}
|
||||||
|
|
||||||
void setLanguage(u32 language) {
|
void setLanguage(u32 language) {
|
||||||
m_language = language;
|
m_language = language;
|
||||||
@ -502,22 +537,34 @@ void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) {
|
|||||||
main_window_geometry_h = h;
|
main_window_geometry_h = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addGameInstallDir(const std::filesystem::path& dir) {
|
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled) {
|
||||||
if (std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir) ==
|
for (const auto& install_dir : settings_install_dirs) {
|
||||||
settings_install_dirs.end()) {
|
if (install_dir.path == dir) {
|
||||||
settings_install_dirs.push_back(dir);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
settings_install_dirs.push_back({dir, enabled});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void removeGameInstallDir(const std::filesystem::path& dir) {
|
void removeGameInstallDir(const std::filesystem::path& dir) {
|
||||||
auto iterator = std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir);
|
auto iterator =
|
||||||
|
std::find_if(settings_install_dirs.begin(), settings_install_dirs.end(),
|
||||||
|
[&dir](const GameInstallDir& install_dir) { return install_dir.path == dir; });
|
||||||
if (iterator != settings_install_dirs.end()) {
|
if (iterator != settings_install_dirs.end()) {
|
||||||
settings_install_dirs.erase(iterator);
|
settings_install_dirs.erase(iterator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled) {
|
||||||
|
auto iterator =
|
||||||
|
std::find_if(settings_install_dirs.begin(), settings_install_dirs.end(),
|
||||||
|
[&dir](const GameInstallDir& install_dir) { return install_dir.path == dir; });
|
||||||
|
if (iterator != settings_install_dirs.end()) {
|
||||||
|
iterator->enabled = enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void setAddonInstallDir(const std::filesystem::path& dir) {
|
void setAddonInstallDir(const std::filesystem::path& dir) {
|
||||||
settings_addon_install_dir = dir;
|
settings_addon_install_dir = dir;
|
||||||
}
|
}
|
||||||
@ -573,8 +620,15 @@ void setEmulatorLanguage(std::string language) {
|
|||||||
emulator_language = language;
|
emulator_language = language;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config) {
|
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config) {
|
||||||
settings_install_dirs = settings_install_dirs_config;
|
settings_install_dirs.clear();
|
||||||
|
for (const auto& dir : dirs_config) {
|
||||||
|
settings_install_dirs.push_back({dir, true});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config) {
|
||||||
|
settings_install_dirs = dirs_config;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSaveDataPath(const std::filesystem::path& path) {
|
void setSaveDataPath(const std::filesystem::path& path) {
|
||||||
@ -597,8 +651,22 @@ u32 getMainWindowGeometryH() {
|
|||||||
return main_window_geometry_h;
|
return main_window_geometry_h;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<std::filesystem::path>& getGameInstallDirs() {
|
const std::vector<std::filesystem::path> getGameInstallDirs() {
|
||||||
return settings_install_dirs;
|
std::vector<std::filesystem::path> enabled_dirs;
|
||||||
|
for (const auto& dir : settings_install_dirs) {
|
||||||
|
if (dir.enabled) {
|
||||||
|
enabled_dirs.push_back(dir.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return enabled_dirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<bool> getGameInstallDirsEnabled() {
|
||||||
|
std::vector<bool> enabled_dirs;
|
||||||
|
for (const auto& dir : settings_install_dirs) {
|
||||||
|
enabled_dirs.push_back(dir.enabled);
|
||||||
|
}
|
||||||
|
return enabled_dirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path getAddonInstallDir() {
|
std::filesystem::path getAddonInstallDir() {
|
||||||
@ -704,8 +772,11 @@ void load(const std::filesystem::path& path) {
|
|||||||
const toml::value& general = data.at("General");
|
const toml::value& general = data.at("General");
|
||||||
|
|
||||||
isNeo = toml::find_or<bool>(general, "isPS4Pro", false);
|
isNeo = toml::find_or<bool>(general, "isPS4Pro", false);
|
||||||
|
isDevKit = toml::find_or<bool>(general, "isDevKit", false);
|
||||||
playBGM = toml::find_or<bool>(general, "playBGM", false);
|
playBGM = toml::find_or<bool>(general, "playBGM", false);
|
||||||
isTrophyPopupDisabled = toml::find_or<bool>(general, "isTrophyPopupDisabled", false);
|
isTrophyPopupDisabled = toml::find_or<bool>(general, "isTrophyPopupDisabled", false);
|
||||||
|
trophyNotificationDuration =
|
||||||
|
toml::find_or<double>(general, "trophyNotificationDuration", 5.0);
|
||||||
BGMvolume = toml::find_or<int>(general, "BGMvolume", 50);
|
BGMvolume = toml::find_or<int>(general, "BGMvolume", 50);
|
||||||
enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", true);
|
enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", true);
|
||||||
logFilter = toml::find_or<std::string>(general, "logFilter", "");
|
logFilter = toml::find_or<std::string>(general, "logFilter", "");
|
||||||
@ -719,6 +790,7 @@ void load(const std::filesystem::path& path) {
|
|||||||
isShowSplash = toml::find_or<bool>(general, "showSplash", true);
|
isShowSplash = toml::find_or<bool>(general, "showSplash", true);
|
||||||
isAutoUpdate = toml::find_or<bool>(general, "autoUpdate", false);
|
isAutoUpdate = toml::find_or<bool>(general, "autoUpdate", false);
|
||||||
isAlwaysShowChangelog = toml::find_or<bool>(general, "alwaysShowChangelog", false);
|
isAlwaysShowChangelog = toml::find_or<bool>(general, "alwaysShowChangelog", false);
|
||||||
|
isSideTrophy = toml::find_or<std::string>(general, "sideTrophy", "right");
|
||||||
separateupdatefolder = toml::find_or<bool>(general, "separateUpdateEnabled", false);
|
separateupdatefolder = toml::find_or<bool>(general, "separateUpdateEnabled", false);
|
||||||
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false);
|
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false);
|
||||||
checkCompatibilityOnStartup =
|
checkCompatibilityOnStartup =
|
||||||
@ -789,8 +861,22 @@ void load(const std::filesystem::path& path) {
|
|||||||
|
|
||||||
const auto install_dir_array =
|
const auto install_dir_array =
|
||||||
toml::find_or<std::vector<std::string>>(gui, "installDirs", {});
|
toml::find_or<std::vector<std::string>>(gui, "installDirs", {});
|
||||||
for (const auto& dir : install_dir_array) {
|
|
||||||
addGameInstallDir(std::filesystem::path{dir});
|
try {
|
||||||
|
install_dirs_enabled = toml::find<std::vector<bool>>(gui, "installDirsEnabled");
|
||||||
|
} catch (...) {
|
||||||
|
// If it does not exist, assume that all are enabled.
|
||||||
|
install_dirs_enabled.resize(install_dir_array.size(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (install_dirs_enabled.size() < install_dir_array.size()) {
|
||||||
|
install_dirs_enabled.resize(install_dir_array.size(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
settings_install_dirs.clear();
|
||||||
|
for (size_t i = 0; i < install_dir_array.size(); i++) {
|
||||||
|
settings_install_dirs.push_back(
|
||||||
|
{std::filesystem::path{install_dir_array[i]}, install_dirs_enabled[i]});
|
||||||
}
|
}
|
||||||
|
|
||||||
save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {});
|
save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {});
|
||||||
@ -833,6 +919,37 @@ void load(const std::filesystem::path& path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sortTomlSections(toml::ordered_value& data) {
|
||||||
|
toml::ordered_value ordered_data;
|
||||||
|
std::vector<std::string> section_order = {"General", "Input", "GPU", "Vulkan",
|
||||||
|
"Debug", "Keys", "GUI", "Settings"};
|
||||||
|
|
||||||
|
for (const auto& section : section_order) {
|
||||||
|
if (data.contains(section)) {
|
||||||
|
std::vector<std::string> keys;
|
||||||
|
for (const auto& item : data.at(section).as_table()) {
|
||||||
|
keys.push_back(item.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(keys.begin(), keys.end(), [](const std::string& a, const std::string& b) {
|
||||||
|
return std::lexicographical_compare(
|
||||||
|
a.begin(), a.end(), b.begin(), b.end(), [](char a_char, char b_char) {
|
||||||
|
return std::tolower(a_char) < std::tolower(b_char);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
toml::ordered_value ordered_section;
|
||||||
|
for (const auto& key : keys) {
|
||||||
|
ordered_section[key] = data.at(section).at(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
ordered_data[section] = ordered_section;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data = ordered_data;
|
||||||
|
}
|
||||||
|
|
||||||
void save(const std::filesystem::path& path) {
|
void save(const std::filesystem::path& path) {
|
||||||
toml::ordered_value data;
|
toml::ordered_value data;
|
||||||
|
|
||||||
@ -856,7 +973,9 @@ void save(const std::filesystem::path& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data["General"]["isPS4Pro"] = isNeo;
|
data["General"]["isPS4Pro"] = isNeo;
|
||||||
|
data["General"]["isDevKit"] = isDevKit;
|
||||||
data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled;
|
data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled;
|
||||||
|
data["General"]["trophyNotificationDuration"] = trophyNotificationDuration;
|
||||||
data["General"]["playBGM"] = playBGM;
|
data["General"]["playBGM"] = playBGM;
|
||||||
data["General"]["BGMvolume"] = BGMvolume;
|
data["General"]["BGMvolume"] = BGMvolume;
|
||||||
data["General"]["enableDiscordRPC"] = enableDiscordRPC;
|
data["General"]["enableDiscordRPC"] = enableDiscordRPC;
|
||||||
@ -868,6 +987,7 @@ void save(const std::filesystem::path& path) {
|
|||||||
data["General"]["showSplash"] = isShowSplash;
|
data["General"]["showSplash"] = isShowSplash;
|
||||||
data["General"]["autoUpdate"] = isAutoUpdate;
|
data["General"]["autoUpdate"] = isAutoUpdate;
|
||||||
data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog;
|
data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog;
|
||||||
|
data["General"]["sideTrophy"] = isSideTrophy;
|
||||||
data["General"]["separateUpdateEnabled"] = separateupdatefolder;
|
data["General"]["separateUpdateEnabled"] = separateupdatefolder;
|
||||||
data["General"]["compatibilityEnabled"] = compatibilityData;
|
data["General"]["compatibilityEnabled"] = compatibilityData;
|
||||||
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
|
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
|
||||||
@ -900,14 +1020,37 @@ void save(const std::filesystem::path& path) {
|
|||||||
data["Debug"]["CollectShader"] = isShaderDebug;
|
data["Debug"]["CollectShader"] = isShaderDebug;
|
||||||
data["Debug"]["isSeparateLogFilesEnabled"] = isSeparateLogFilesEnabled;
|
data["Debug"]["isSeparateLogFilesEnabled"] = isSeparateLogFilesEnabled;
|
||||||
data["Debug"]["FPSColor"] = isFpsColor;
|
data["Debug"]["FPSColor"] = isFpsColor;
|
||||||
|
|
||||||
data["Keys"]["TrophyKey"] = trophyKey;
|
data["Keys"]["TrophyKey"] = trophyKey;
|
||||||
|
|
||||||
std::vector<std::string> install_dirs;
|
std::vector<std::string> install_dirs;
|
||||||
for (const auto& dirString : settings_install_dirs) {
|
std::vector<bool> install_dirs_enabled;
|
||||||
install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data});
|
|
||||||
|
// temporary structure for ordering
|
||||||
|
struct DirEntry {
|
||||||
|
std::string path_str;
|
||||||
|
bool enabled;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<DirEntry> sorted_dirs;
|
||||||
|
for (const auto& dirInfo : settings_install_dirs) {
|
||||||
|
sorted_dirs.push_back(
|
||||||
|
{std::string{fmt::UTF(dirInfo.path.u8string()).data}, dirInfo.enabled});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sort directories alphabetically
|
||||||
|
std::sort(sorted_dirs.begin(), sorted_dirs.end(), [](const DirEntry& a, const DirEntry& b) {
|
||||||
|
return std::lexicographical_compare(
|
||||||
|
a.path_str.begin(), a.path_str.end(), b.path_str.begin(), b.path_str.end(),
|
||||||
|
[](char a_char, char b_char) { return std::tolower(a_char) < std::tolower(b_char); });
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const auto& entry : sorted_dirs) {
|
||||||
|
install_dirs.push_back(entry.path_str);
|
||||||
|
install_dirs_enabled.push_back(entry.enabled);
|
||||||
|
}
|
||||||
|
|
||||||
data["GUI"]["installDirs"] = install_dirs;
|
data["GUI"]["installDirs"] = install_dirs;
|
||||||
|
data["GUI"]["installDirsEnabled"] = install_dirs_enabled;
|
||||||
data["GUI"]["saveDataPath"] = std::string{fmt::UTF(save_data_path.u8string()).data};
|
data["GUI"]["saveDataPath"] = std::string{fmt::UTF(save_data_path.u8string()).data};
|
||||||
data["GUI"]["loadGameSizeEnabled"] = load_game_size;
|
data["GUI"]["loadGameSizeEnabled"] = load_game_size;
|
||||||
|
|
||||||
@ -918,9 +1061,13 @@ void save(const std::filesystem::path& path) {
|
|||||||
data["GUI"]["showBackgroundImage"] = showBackgroundImage;
|
data["GUI"]["showBackgroundImage"] = showBackgroundImage;
|
||||||
data["Settings"]["consoleLanguage"] = m_language;
|
data["Settings"]["consoleLanguage"] = m_language;
|
||||||
|
|
||||||
|
// Sorting of TOML sections
|
||||||
|
sortTomlSections(data);
|
||||||
|
|
||||||
std::ofstream file(path, std::ios::binary);
|
std::ofstream file(path, std::ios::binary);
|
||||||
file << data;
|
file << data;
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
saveMainWindow(path);
|
saveMainWindow(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -962,6 +1109,9 @@ void saveMainWindow(const std::filesystem::path& path) {
|
|||||||
data["GUI"]["elfDirs"] = m_elf_viewer;
|
data["GUI"]["elfDirs"] = m_elf_viewer;
|
||||||
data["GUI"]["recentFiles"] = m_recent_files;
|
data["GUI"]["recentFiles"] = m_recent_files;
|
||||||
|
|
||||||
|
// Sorting of TOML sections
|
||||||
|
sortTomlSections(data);
|
||||||
|
|
||||||
std::ofstream file(path, std::ios::binary);
|
std::ofstream file(path, std::ios::binary);
|
||||||
file << data;
|
file << data;
|
||||||
file.close();
|
file.close();
|
||||||
@ -970,6 +1120,7 @@ void saveMainWindow(const std::filesystem::path& path) {
|
|||||||
void setDefaultValues() {
|
void setDefaultValues() {
|
||||||
isHDRAllowed = false;
|
isHDRAllowed = false;
|
||||||
isNeo = false;
|
isNeo = false;
|
||||||
|
isDevKit = false;
|
||||||
isFullscreen = false;
|
isFullscreen = false;
|
||||||
isTrophyPopupDisabled = false;
|
isTrophyPopupDisabled = false;
|
||||||
playBGM = false;
|
playBGM = false;
|
||||||
@ -988,6 +1139,7 @@ void setDefaultValues() {
|
|||||||
chooseHomeTab = "General";
|
chooseHomeTab = "General";
|
||||||
cursorState = HideCursorState::Idle;
|
cursorState = HideCursorState::Idle;
|
||||||
cursorHideTimeout = 5;
|
cursorHideTimeout = 5;
|
||||||
|
trophyNotificationDuration = 6.0;
|
||||||
backButtonBehavior = "left";
|
backButtonBehavior = "left";
|
||||||
useSpecialPad = false;
|
useSpecialPad = false;
|
||||||
specialPadClass = 1;
|
specialPadClass = 1;
|
||||||
@ -996,6 +1148,7 @@ void setDefaultValues() {
|
|||||||
isShowSplash = false;
|
isShowSplash = false;
|
||||||
isAutoUpdate = false;
|
isAutoUpdate = false;
|
||||||
isAlwaysShowChangelog = false;
|
isAlwaysShowChangelog = false;
|
||||||
|
isSideTrophy = "right";
|
||||||
isNullGpu = false;
|
isNullGpu = false;
|
||||||
shouldDumpShaders = false;
|
shouldDumpShaders = false;
|
||||||
vblankDivider = 1;
|
vblankDivider = 1;
|
||||||
|
@ -9,6 +9,11 @@
|
|||||||
|
|
||||||
namespace Config {
|
namespace Config {
|
||||||
|
|
||||||
|
struct GameInstallDir {
|
||||||
|
std::filesystem::path path;
|
||||||
|
bool enabled;
|
||||||
|
};
|
||||||
|
|
||||||
enum HideCursorState : s16 { Never, Idle, Always };
|
enum HideCursorState : s16 { Never, Idle, Always };
|
||||||
|
|
||||||
void load(const std::filesystem::path& path);
|
void load(const std::filesystem::path& path);
|
||||||
@ -21,8 +26,11 @@ bool GetLoadGameSizeEnabled();
|
|||||||
std::filesystem::path GetSaveDataPath();
|
std::filesystem::path GetSaveDataPath();
|
||||||
void setLoadGameSizeEnabled(bool enable);
|
void setLoadGameSizeEnabled(bool enable);
|
||||||
bool getIsFullscreen();
|
bool getIsFullscreen();
|
||||||
|
bool getShowLabelsUnderIcons();
|
||||||
|
bool setShowLabelsUnderIcons();
|
||||||
std::string getFullscreenMode();
|
std::string getFullscreenMode();
|
||||||
bool isNeoModeConsole();
|
bool isNeoModeConsole();
|
||||||
|
bool isDevKitConsole();
|
||||||
bool getPlayBGM();
|
bool getPlayBGM();
|
||||||
int getBGMvolume();
|
int getBGMvolume();
|
||||||
bool getisTrophyPopupDisabled();
|
bool getisTrophyPopupDisabled();
|
||||||
@ -41,6 +49,7 @@ std::string getChooseHomeTab();
|
|||||||
|
|
||||||
s16 getCursorState();
|
s16 getCursorState();
|
||||||
int getCursorHideTimeout();
|
int getCursorHideTimeout();
|
||||||
|
double getTrophyNotificationDuration();
|
||||||
std::string getBackButtonBehavior();
|
std::string getBackButtonBehavior();
|
||||||
bool getUseSpecialPad();
|
bool getUseSpecialPad();
|
||||||
int getSpecialPadClass();
|
int getSpecialPadClass();
|
||||||
@ -62,6 +71,7 @@ bool collectShadersForDebug();
|
|||||||
bool showSplash();
|
bool showSplash();
|
||||||
bool autoUpdate();
|
bool autoUpdate();
|
||||||
bool alwaysShowChangelog();
|
bool alwaysShowChangelog();
|
||||||
|
std::string sideTrophy();
|
||||||
bool nullGpu();
|
bool nullGpu();
|
||||||
bool copyGPUCmdBuffers();
|
bool copyGPUCmdBuffers();
|
||||||
bool dumpShaders();
|
bool dumpShaders();
|
||||||
@ -75,6 +85,7 @@ void setCollectShaderForDebug(bool enable);
|
|||||||
void setShowSplash(bool enable);
|
void setShowSplash(bool enable);
|
||||||
void setAutoUpdate(bool enable);
|
void setAutoUpdate(bool enable);
|
||||||
void setAlwaysShowChangelog(bool enable);
|
void setAlwaysShowChangelog(bool enable);
|
||||||
|
void setSideTrophy(std::string side);
|
||||||
void setNullGpu(bool enable);
|
void setNullGpu(bool enable);
|
||||||
void setAllowHDR(bool enable);
|
void setAllowHDR(bool enable);
|
||||||
void setCopyGPUCmdBuffers(bool enable);
|
void setCopyGPUCmdBuffers(bool enable);
|
||||||
@ -95,7 +106,8 @@ void setUserName(const std::string& type);
|
|||||||
void setUpdateChannel(const std::string& type);
|
void setUpdateChannel(const std::string& type);
|
||||||
void setChooseHomeTab(const std::string& type);
|
void setChooseHomeTab(const std::string& type);
|
||||||
void setSeparateUpdateEnabled(bool use);
|
void setSeparateUpdateEnabled(bool use);
|
||||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config);
|
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
|
||||||
|
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
|
||||||
void setSaveDataPath(const std::filesystem::path& path);
|
void setSaveDataPath(const std::filesystem::path& path);
|
||||||
void setCompatibilityEnabled(bool use);
|
void setCompatibilityEnabled(bool use);
|
||||||
void setCheckCompatibilityOnStartup(bool use);
|
void setCheckCompatibilityOnStartup(bool use);
|
||||||
@ -104,6 +116,7 @@ void setShowBackgroundImage(bool show);
|
|||||||
|
|
||||||
void setCursorState(s16 cursorState);
|
void setCursorState(s16 cursorState);
|
||||||
void setCursorHideTimeout(int newcursorHideTimeout);
|
void setCursorHideTimeout(int newcursorHideTimeout);
|
||||||
|
void setTrophyNotificationDuration(double newTrophyNotificationDuration);
|
||||||
void setBackButtonBehavior(const std::string& type);
|
void setBackButtonBehavior(const std::string& type);
|
||||||
void setUseSpecialPad(bool use);
|
void setUseSpecialPad(bool use);
|
||||||
void setSpecialPadClass(int type);
|
void setSpecialPadClass(int type);
|
||||||
@ -129,8 +142,9 @@ void setVkGuestMarkersEnabled(bool enable);
|
|||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);
|
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);
|
||||||
bool addGameInstallDir(const std::filesystem::path& dir);
|
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true);
|
||||||
void removeGameInstallDir(const std::filesystem::path& dir);
|
void removeGameInstallDir(const std::filesystem::path& dir);
|
||||||
|
void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled);
|
||||||
void setAddonInstallDir(const std::filesystem::path& dir);
|
void setAddonInstallDir(const std::filesystem::path& dir);
|
||||||
void setMainWindowTheme(u32 theme);
|
void setMainWindowTheme(u32 theme);
|
||||||
void setIconSize(u32 size);
|
void setIconSize(u32 size);
|
||||||
@ -149,7 +163,8 @@ u32 getMainWindowGeometryX();
|
|||||||
u32 getMainWindowGeometryY();
|
u32 getMainWindowGeometryY();
|
||||||
u32 getMainWindowGeometryW();
|
u32 getMainWindowGeometryW();
|
||||||
u32 getMainWindowGeometryH();
|
u32 getMainWindowGeometryH();
|
||||||
const std::vector<std::filesystem::path>& getGameInstallDirs();
|
const std::vector<std::filesystem::path> getGameInstallDirs();
|
||||||
|
const std::vector<bool> getGameInstallDirsEnabled();
|
||||||
std::filesystem::path getAddonInstallDir();
|
std::filesystem::path getAddonInstallDir();
|
||||||
u32 getMainWindowTheme();
|
u32 getMainWindowTheme();
|
||||||
u32 getIconSize();
|
u32 getIconSize();
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
@ -69,6 +70,8 @@ class ElfInfo {
|
|||||||
u32 raw_firmware_ver = 0;
|
u32 raw_firmware_ver = 0;
|
||||||
PSFAttributes psf_attributes{};
|
PSFAttributes psf_attributes{};
|
||||||
|
|
||||||
|
std::filesystem::path splash_path{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr u32 FW_15 = 0x1500000;
|
static constexpr u32 FW_15 = 0x1500000;
|
||||||
static constexpr u32 FW_16 = 0x1600000;
|
static constexpr u32 FW_16 = 0x1600000;
|
||||||
@ -116,6 +119,10 @@ public:
|
|||||||
ASSERT(initialized);
|
ASSERT(initialized);
|
||||||
return psf_attributes;
|
return psf_attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const std::filesystem::path& GetSplashPath() const {
|
||||||
|
return splash_path;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
@ -125,12 +125,15 @@ namespace {
|
|||||||
[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) {
|
[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) {
|
||||||
switch (origin) {
|
switch (origin) {
|
||||||
case SeekOrigin::SetOrigin:
|
case SeekOrigin::SetOrigin:
|
||||||
default:
|
|
||||||
return SEEK_SET;
|
return SEEK_SET;
|
||||||
case SeekOrigin::CurrentPosition:
|
case SeekOrigin::CurrentPosition:
|
||||||
return SEEK_CUR;
|
return SEEK_CUR;
|
||||||
case SeekOrigin::End:
|
case SeekOrigin::End:
|
||||||
return SEEK_END;
|
return SEEK_END;
|
||||||
|
default:
|
||||||
|
LOG_ERROR(Common_Filesystem, "Unsupported origin {}, defaulting to SEEK_SET",
|
||||||
|
static_cast<u32>(origin));
|
||||||
|
return SEEK_SET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,20 +380,6 @@ bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (False(file_access_mode & (FileAccessMode::Write | FileAccessMode::Append))) {
|
|
||||||
u64 size = GetSize();
|
|
||||||
if (origin == SeekOrigin::CurrentPosition && Tell() + offset > size) {
|
|
||||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
|
||||||
return false;
|
|
||||||
} else if (origin == SeekOrigin::SetOrigin && (u64)offset > size) {
|
|
||||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
|
||||||
return false;
|
|
||||||
} else if (origin == SeekOrigin::End && offset > 0) {
|
|
||||||
LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
|
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
|
||||||
|
@ -61,6 +61,8 @@ enum class SeekOrigin : u32 {
|
|||||||
SetOrigin, // Seeks from the start of the file.
|
SetOrigin, // Seeks from the start of the file.
|
||||||
CurrentPosition, // Seeks from the current file pointer position.
|
CurrentPosition, // Seeks from the current file pointer position.
|
||||||
End, // Seeks from the end of the file.
|
End, // Seeks from the end of the file.
|
||||||
|
SeekHole, // Seeks from the start of the next hole in the file.
|
||||||
|
SeekData, // Seeks from the start of the next non-hole region in the file.
|
||||||
};
|
};
|
||||||
|
|
||||||
class IOFile final {
|
class IOFile final {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/path_util.h"
|
#include "common/path_util.h"
|
||||||
@ -16,6 +17,8 @@
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// This is the maximum number of UTF-16 code units permissible in Windows file paths
|
// This is the maximum number of UTF-16 code units permissible in Windows file paths
|
||||||
#define MAX_PATH 260
|
#define MAX_PATH 260
|
||||||
|
#include <Shlobj.h>
|
||||||
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
// This is the maximum number of UTF-8 code units permissible in all other OSes' file paths
|
// This is the maximum number of UTF-8 code units permissible in all other OSes' file paths
|
||||||
#define MAX_PATH 1024
|
#define MAX_PATH 1024
|
||||||
@ -105,6 +108,10 @@ static auto UserPaths = [] {
|
|||||||
} else {
|
} else {
|
||||||
user_dir = std::filesystem::path(getenv("HOME")) / ".local" / "share" / "shadPS4";
|
user_dir = std::filesystem::path(getenv("HOME")) / ".local" / "share" / "shadPS4";
|
||||||
}
|
}
|
||||||
|
#elif _WIN32
|
||||||
|
TCHAR appdata[MAX_PATH] = {0};
|
||||||
|
SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, appdata);
|
||||||
|
user_dir = std::filesystem::path(appdata) / "shadPS4";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +135,22 @@ static auto UserPaths = [] {
|
|||||||
create_path(PathType::CheatsDir, user_dir / CHEATS_DIR);
|
create_path(PathType::CheatsDir, user_dir / CHEATS_DIR);
|
||||||
create_path(PathType::PatchesDir, user_dir / PATCHES_DIR);
|
create_path(PathType::PatchesDir, user_dir / PATCHES_DIR);
|
||||||
create_path(PathType::MetaDataDir, user_dir / METADATA_DIR);
|
create_path(PathType::MetaDataDir, user_dir / METADATA_DIR);
|
||||||
|
create_path(PathType::CustomTrophy, user_dir / CUSTOM_TROPHY);
|
||||||
|
|
||||||
|
std::ofstream notice_file(user_dir / CUSTOM_TROPHY / "Notice.txt");
|
||||||
|
if (notice_file.is_open()) {
|
||||||
|
notice_file
|
||||||
|
<< "++++++++++++++++++++++++++++++++\n+ Custom Trophy Images / Sound "
|
||||||
|
"+\n++++++++++++++++++++++++++++++++\n\nYou can add custom images to the "
|
||||||
|
"trophies.\n*We recommend a square resolution image, for example 200x200, 500x500, "
|
||||||
|
"the same size as the height and width.\nIn this folder ('user\\custom_trophy'), "
|
||||||
|
"add the files with the following "
|
||||||
|
"names:\n\nbronze.png\nsilver.png\ngold.png\nplatinum.png\n\nYou can add a custom "
|
||||||
|
"sound for trophy notifications.\n*By default, no audio is played unless it is in "
|
||||||
|
"this folder and you are using the QT version.\nIn this folder "
|
||||||
|
"('user\\custom_trophy'), add the files with the following names:\n\ntrophy.mp3";
|
||||||
|
notice_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
return paths;
|
return paths;
|
||||||
}();
|
}();
|
||||||
|
@ -27,6 +27,7 @@ enum class PathType {
|
|||||||
CheatsDir, // Where cheats are stored.
|
CheatsDir, // Where cheats are stored.
|
||||||
PatchesDir, // Where patches are stored.
|
PatchesDir, // Where patches are stored.
|
||||||
MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored.
|
MetaDataDir, // Where game metadata (e.g. trophies and menu backgrounds) is stored.
|
||||||
|
CustomTrophy, // Where custom files for trophies are stored.
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr auto PORTABLE_DIR = "user";
|
constexpr auto PORTABLE_DIR = "user";
|
||||||
@ -44,6 +45,7 @@ constexpr auto CAPTURES_DIR = "captures";
|
|||||||
constexpr auto CHEATS_DIR = "cheats";
|
constexpr auto CHEATS_DIR = "cheats";
|
||||||
constexpr auto PATCHES_DIR = "patches";
|
constexpr auto PATCHES_DIR = "patches";
|
||||||
constexpr auto METADATA_DIR = "game_data";
|
constexpr auto METADATA_DIR = "game_data";
|
||||||
|
constexpr auto CUSTOM_TROPHY = "custom_trophy";
|
||||||
|
|
||||||
// Filenames
|
// Filenames
|
||||||
constexpr auto LOG_FILE = "shad_log.txt";
|
constexpr auto LOG_FILE = "shad_log.txt";
|
||||||
|
15
src/common/string_literal.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
template <size_t N, typename C = char>
|
||||||
|
struct StringLiteral {
|
||||||
|
static constexpr size_t len = N;
|
||||||
|
|
||||||
|
constexpr StringLiteral(const C (&str)[N]) {
|
||||||
|
std::copy_n(str, N, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
C value[N]{};
|
||||||
|
};
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
|
||||||
constexpr char VERSION[] = "0.6.1 WIP";
|
constexpr char VERSION[] = "0.7.1 WIP";
|
||||||
constexpr bool isRelease = false;
|
constexpr bool isRelease = false;
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
@ -180,28 +180,44 @@ static void RestoreStack(Xbyak::CodeGenerator& c) {
|
|||||||
c.mov(rsp, qword[reinterpret_cast<void*>(stack_pointer_slot * sizeof(void*))]);
|
c.mov(rsp, qword[reinterpret_cast<void*>(stack_pointer_slot * sizeof(void*))]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Validates that the dst register is supported given the SaveStack/RestoreStack implementation.
|
||||||
|
static void ValidateDst(const Xbyak::Reg& dst) {
|
||||||
|
// No restrictions.
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// These utilities are not implemented as we can't save anything to thread local storage without
|
|
||||||
// temporary registers.
|
|
||||||
void InitializeThreadPatchStack() {
|
void InitializeThreadPatchStack() {
|
||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Since stack pointer here is subtracted through safe zone and not saved anywhere,
|
||||||
|
// it must not be modified during the instruction. Otherwise, we will not be able to find
|
||||||
|
// and load registers back from where they were saved. Thus, a limitation is placed on
|
||||||
|
// instructions, that they must not use the stack pointer register as a destination.
|
||||||
|
|
||||||
/// Saves the stack pointer to thread local storage and loads the patch stack.
|
/// Saves the stack pointer to thread local storage and loads the patch stack.
|
||||||
static void SaveStack(Xbyak::CodeGenerator& c) {
|
static void SaveStack(Xbyak::CodeGenerator& c) {
|
||||||
UNIMPLEMENTED();
|
c.lea(rsp, ptr[rsp - 128]); // red zone
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Restores the stack pointer from thread local storage.
|
/// Restores the stack pointer from thread local storage.
|
||||||
static void RestoreStack(Xbyak::CodeGenerator& c) {
|
static void RestoreStack(Xbyak::CodeGenerator& c) {
|
||||||
UNIMPLEMENTED();
|
c.lea(rsp, ptr[rsp + 128]); // red zone
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Validates that the dst register is supported given the SaveStack/RestoreStack implementation.
|
||||||
|
static void ValidateDst(const Xbyak::Reg& dst) {
|
||||||
|
// Stack pointer is not preserved, so it can't be used as a dst.
|
||||||
|
ASSERT_MSG(dst.getIdx() != rsp.getIdx(), "Stack pointer not supported as destination.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Switches to the patch stack, saves registers, and restores the original stack.
|
/// Switches to the patch stack, saves registers, and restores the original stack.
|
||||||
static void SaveRegisters(Xbyak::CodeGenerator& c, const std::initializer_list<Xbyak::Reg> regs) {
|
static void SaveRegisters(Xbyak::CodeGenerator& c, const std::initializer_list<Xbyak::Reg> regs) {
|
||||||
|
// Uses a more robust solution for saving registers on MacOS to avoid potential stack corruption
|
||||||
|
// if games decide to not follow the ABI and use the red zone.
|
||||||
SaveStack(c);
|
SaveStack(c);
|
||||||
for (const auto& reg : regs) {
|
for (const auto& reg : regs) {
|
||||||
c.push(reg.cvt64());
|
c.push(reg.cvt64());
|
||||||
@ -257,12 +273,11 @@ static void RestoreContext(Xbyak::CodeGenerator& c, const Xbyak::Operand& dst,
|
|||||||
RestoreStack(c);
|
RestoreStack(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
|
|
||||||
static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||||
const auto src1 = ZydisToXbyakRegisterOperand(operands[1]);
|
const auto src1 = ZydisToXbyakRegisterOperand(operands[1]);
|
||||||
const auto src2 = ZydisToXbyakOperand(operands[2]);
|
const auto src2 = ZydisToXbyakOperand(operands[2]);
|
||||||
|
ValidateDst(dst);
|
||||||
|
|
||||||
// Check if src2 is a memory operand or a register different to dst.
|
// Check if src2 is a memory operand or a register different to dst.
|
||||||
// In those cases, we don't need to use a temporary register and are free to modify dst.
|
// In those cases, we don't need to use a temporary register and are free to modify dst.
|
||||||
@ -301,6 +316,7 @@ static void GenerateBEXTR(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
|||||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||||
const auto start_len = ZydisToXbyakRegisterOperand(operands[2]);
|
const auto start_len = ZydisToXbyakRegisterOperand(operands[2]);
|
||||||
|
ValidateDst(dst);
|
||||||
|
|
||||||
const Xbyak::Reg32e shift(Xbyak::Operand::RCX, static_cast<int>(start_len.getBit()));
|
const Xbyak::Reg32e shift(Xbyak::Operand::RCX, static_cast<int>(start_len.getBit()));
|
||||||
const auto scratch1 =
|
const auto scratch1 =
|
||||||
@ -338,6 +354,7 @@ static void GenerateBEXTR(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
|||||||
static void GenerateBLSI(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
static void GenerateBLSI(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||||
|
ValidateDst(dst);
|
||||||
|
|
||||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||||
|
|
||||||
@ -367,6 +384,7 @@ static void GenerateBLSI(const ZydisDecodedOperand* operands, Xbyak::CodeGenerat
|
|||||||
static void GenerateBLSMSK(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
static void GenerateBLSMSK(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||||
|
ValidateDst(dst);
|
||||||
|
|
||||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||||
|
|
||||||
@ -395,9 +413,37 @@ static void GenerateBLSMSK(const ZydisDecodedOperand* operands, Xbyak::CodeGener
|
|||||||
RestoreRegisters(c, {scratch});
|
RestoreRegisters(c, {scratch});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void GenerateTZCNT(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||||
|
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||||
|
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||||
|
ValidateDst(dst);
|
||||||
|
|
||||||
|
Xbyak::Label src_zero, end;
|
||||||
|
|
||||||
|
c.cmp(*src, 0);
|
||||||
|
c.je(src_zero);
|
||||||
|
|
||||||
|
// If src is not zero, functions like a BSF, but also clears the CF
|
||||||
|
c.bsf(dst, *src);
|
||||||
|
c.clc();
|
||||||
|
c.jmp(end);
|
||||||
|
|
||||||
|
c.L(src_zero);
|
||||||
|
c.mov(dst, operands[0].size);
|
||||||
|
// Since dst is not zero, also set ZF to zero. Testing dst with itself when we know
|
||||||
|
// it isn't zero is a good way to do this.
|
||||||
|
// Use cvt32 to avoid REX/Operand size prefixes.
|
||||||
|
c.test(dst.cvt32(), dst.cvt32());
|
||||||
|
// When source is zero, TZCNT also sets CF.
|
||||||
|
c.stc();
|
||||||
|
|
||||||
|
c.L(end);
|
||||||
|
}
|
||||||
|
|
||||||
static void GenerateBLSR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
static void GenerateBLSR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||||
|
ValidateDst(dst);
|
||||||
|
|
||||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||||
|
|
||||||
@ -426,6 +472,8 @@ static void GenerateBLSR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerat
|
|||||||
RestoreRegisters(c, {scratch});
|
RestoreRegisters(c, {scratch});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
|
||||||
static __attribute__((sysv_abi)) void PerformVCVTPH2PS(float* out, const half_float::half* in,
|
static __attribute__((sysv_abi)) void PerformVCVTPH2PS(float* out, const half_float::half* in,
|
||||||
const u32 count) {
|
const u32 count) {
|
||||||
for (u32 i = 0; i < count; i++) {
|
for (u32 i = 0; i < count; i++) {
|
||||||
@ -616,6 +664,11 @@ static bool FilterNoSSE4a(const ZydisDecodedOperand*) {
|
|||||||
return !cpu.has(Cpu::tSSE4a);
|
return !cpu.has(Cpu::tSSE4a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool FilterNoBMI1(const ZydisDecodedOperand*) {
|
||||||
|
Cpu cpu;
|
||||||
|
return !cpu.has(Cpu::tBMI1);
|
||||||
|
}
|
||||||
|
|
||||||
static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||||
bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||||
operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
||||||
@ -897,14 +950,16 @@ static const std::unordered_map<ZydisMnemonic, PatchInfo> Patches = {
|
|||||||
{ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}},
|
{ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}},
|
||||||
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
||||||
|
|
||||||
|
// BMI1
|
||||||
|
{ZYDIS_MNEMONIC_ANDN, {FilterNoBMI1, GenerateANDN, true}},
|
||||||
|
{ZYDIS_MNEMONIC_BEXTR, {FilterNoBMI1, GenerateBEXTR, true}},
|
||||||
|
{ZYDIS_MNEMONIC_BLSI, {FilterNoBMI1, GenerateBLSI, true}},
|
||||||
|
{ZYDIS_MNEMONIC_BLSMSK, {FilterNoBMI1, GenerateBLSMSK, true}},
|
||||||
|
{ZYDIS_MNEMONIC_BLSR, {FilterNoBMI1, GenerateBLSR, true}},
|
||||||
|
{ZYDIS_MNEMONIC_TZCNT, {FilterNoBMI1, GenerateTZCNT, true}},
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// Patches for instruction sets not supported by Rosetta 2.
|
// Patches for instruction sets not supported by Rosetta 2.
|
||||||
// BMI1
|
|
||||||
{ZYDIS_MNEMONIC_ANDN, {FilterRosetta2Only, GenerateANDN, true}},
|
|
||||||
{ZYDIS_MNEMONIC_BEXTR, {FilterRosetta2Only, GenerateBEXTR, true}},
|
|
||||||
{ZYDIS_MNEMONIC_BLSI, {FilterRosetta2Only, GenerateBLSI, true}},
|
|
||||||
{ZYDIS_MNEMONIC_BLSMSK, {FilterRosetta2Only, GenerateBLSMSK, true}},
|
|
||||||
{ZYDIS_MNEMONIC_BLSR, {FilterRosetta2Only, GenerateBLSR, true}},
|
|
||||||
// F16C
|
// F16C
|
||||||
{ZYDIS_MNEMONIC_VCVTPH2PS, {FilterRosetta2Only, GenerateVCVTPH2PS, true}},
|
{ZYDIS_MNEMONIC_VCVTPH2PS, {FilterRosetta2Only, GenerateVCVTPH2PS, true}},
|
||||||
{ZYDIS_MNEMONIC_VCVTPS2PH, {FilterRosetta2Only, GenerateVCVTPS2PH, true}},
|
{ZYDIS_MNEMONIC_VCVTPS2PH, {FilterRosetta2Only, GenerateVCVTPS2PH, true}},
|
||||||
|
@ -158,6 +158,10 @@ public:
|
|||||||
float Framerate = 1.0f / 60.0f;
|
float Framerate = 1.0f / 60.0f;
|
||||||
float FrameDeltaTime;
|
float FrameDeltaTime;
|
||||||
|
|
||||||
|
std::pair<u32, u32> game_resolution{};
|
||||||
|
std::pair<u32, u32> output_resolution{};
|
||||||
|
bool is_using_fsr{};
|
||||||
|
|
||||||
void ShowDebugMessage(std::string message) {
|
void ShowDebugMessage(std::string message) {
|
||||||
if (message.empty()) {
|
if (message.empty()) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "SDL3/SDL_log.h"
|
||||||
#include "layer.h"
|
#include "layer.h"
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
@ -21,8 +22,8 @@
|
|||||||
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
||||||
|
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
using namespace Core::Devtools;
|
using namespace ::Core::Devtools;
|
||||||
using L = Core::Devtools::Layer;
|
using L = ::Core::Devtools::Layer;
|
||||||
|
|
||||||
static bool show_simple_fps = false;
|
static bool show_simple_fps = false;
|
||||||
static bool visibility_toggled = false;
|
static bool visibility_toggled = false;
|
||||||
@ -81,8 +82,24 @@ void L::DrawMenuBar() {
|
|||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
if (BeginMenu("Display")) {
|
if (BeginMenu("Display")) {
|
||||||
|
auto& pp_settings = presenter->GetPPSettingsRef();
|
||||||
if (BeginMenu("Brightness")) {
|
if (BeginMenu("Brightness")) {
|
||||||
SliderFloat("Gamma", &presenter->GetGammaRef(), 0.1f, 2.0f);
|
SliderFloat("Gamma", &pp_settings.gamma, 0.1f, 2.0f);
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
if (BeginMenu("FSR")) {
|
||||||
|
auto& fsr = presenter->GetFsrSettingsRef();
|
||||||
|
Checkbox("FSR Enabled", &fsr.enable);
|
||||||
|
BeginDisabled(!fsr.enable);
|
||||||
|
{
|
||||||
|
Checkbox("RCAS", &fsr.use_rcas);
|
||||||
|
BeginDisabled(!fsr.use_rcas);
|
||||||
|
{
|
||||||
|
SliderFloat("RCAS Attenuation", &fsr.rcas_attenuation, 0.0, 3.0);
|
||||||
|
}
|
||||||
|
EndDisabled();
|
||||||
|
}
|
||||||
|
EndDisabled();
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
@ -101,22 +118,6 @@ void L::DrawMenuBar() {
|
|||||||
|
|
||||||
EndMainMenuBar();
|
EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsKeyPressed(ImGuiKey_F9, false)) {
|
|
||||||
if (io.KeyCtrl && io.KeyAlt) {
|
|
||||||
if (!DebugState.ShouldPauseInSubmit()) {
|
|
||||||
DebugState.RequestFrameDump(dump_frame_count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!io.KeyCtrl && !io.KeyAlt) {
|
|
||||||
if (isSystemPaused) {
|
|
||||||
DebugState.ResumeGuestThreads();
|
|
||||||
} else {
|
|
||||||
DebugState.PauseGuestThreads();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (open_popup_options) {
|
if (open_popup_options) {
|
||||||
OpenPopup("GPU Tools Options");
|
OpenPopup("GPU Tools Options");
|
||||||
just_opened_options = true;
|
just_opened_options = true;
|
||||||
@ -365,6 +366,32 @@ void L::Draw() {
|
|||||||
visibility_toggled = true;
|
visibility_toggled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsKeyPressed(ImGuiKey_F9, false)) {
|
||||||
|
if (io.KeyCtrl && io.KeyAlt) {
|
||||||
|
if (!DebugState.ShouldPauseInSubmit()) {
|
||||||
|
DebugState.RequestFrameDump(dump_frame_count);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (DebugState.IsGuestThreadsPaused()) {
|
||||||
|
DebugState.ResumeGuestThreads();
|
||||||
|
SDL_Log("Game resumed from Keyboard");
|
||||||
|
show_pause_status = false;
|
||||||
|
} else {
|
||||||
|
DebugState.PauseGuestThreads();
|
||||||
|
SDL_Log("Game paused from Keyboard");
|
||||||
|
show_pause_status = true;
|
||||||
|
}
|
||||||
|
visibility_toggled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_pause_status) {
|
||||||
|
ImVec2 pos = ImVec2(10, 10);
|
||||||
|
ImU32 color = IM_COL32(255, 255, 255, 255);
|
||||||
|
|
||||||
|
ImGui::GetForegroundDrawList()->AddText(pos, color, "Game Paused Press F9 to Resume");
|
||||||
|
}
|
||||||
|
|
||||||
if (show_simple_fps) {
|
if (show_simple_fps) {
|
||||||
if (Begin("Video Info", nullptr,
|
if (Begin("Video Info", nullptr,
|
||||||
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDecoration |
|
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDecoration |
|
||||||
|
@ -19,6 +19,7 @@ public:
|
|||||||
static void SetupSettings();
|
static void SetupSettings();
|
||||||
|
|
||||||
void Draw() override;
|
void Draw() override;
|
||||||
|
bool show_pause_status = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core::Devtools
|
} // namespace Core::Devtools
|
||||||
|
@ -74,7 +74,7 @@ void FrameGraph::Draw() {
|
|||||||
if (!is_open) {
|
if (!is_open) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SetNextWindowSize({340.0, 185.0f}, ImGuiCond_FirstUseEver);
|
SetNextWindowSize({308.0, 270.0f}, ImGuiCond_FirstUseEver);
|
||||||
if (Begin("Video debug info", &is_open)) {
|
if (Begin("Video debug info", &is_open)) {
|
||||||
const auto& ctx = *GImGui;
|
const auto& ctx = *GImGui;
|
||||||
const auto& io = ctx.IO;
|
const auto& io = ctx.IO;
|
||||||
@ -88,13 +88,20 @@ void FrameGraph::Draw() {
|
|||||||
frameRate = 1000.0f / deltaTime;
|
frameRate = 1000.0f / deltaTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SeparatorText("Frame graph");
|
||||||
|
DrawFrameGraph();
|
||||||
|
|
||||||
|
SeparatorText("Renderer info");
|
||||||
|
|
||||||
Text("Frame time: %.3f ms (%.1f FPS)", deltaTime, frameRate);
|
Text("Frame time: %.3f ms (%.1f FPS)", deltaTime, frameRate);
|
||||||
Text("Presenter time: %.3f ms (%.1f FPS)", io.DeltaTime * 1000.0f, 1.0f / io.DeltaTime);
|
Text("Presenter time: %.3f ms (%.1f FPS)", io.DeltaTime * 1000.0f, 1.0f / io.DeltaTime);
|
||||||
Text("Flip frame: %d Gnm submit frame: %d", DebugState.flip_frame_count.load(),
|
Text("Flip frame: %d Gnm submit frame: %d", DebugState.flip_frame_count.load(),
|
||||||
DebugState.gnm_frame_count.load());
|
DebugState.gnm_frame_count.load());
|
||||||
|
Text("Game Res: %dx%d", DebugState.game_resolution.first,
|
||||||
SeparatorText("Frame graph");
|
DebugState.game_resolution.second);
|
||||||
DrawFrameGraph();
|
Text("Output Res: %dx%d", DebugState.output_resolution.first,
|
||||||
|
DebugState.output_resolution.second);
|
||||||
|
Text("FSR: %s", DebugState.is_using_fsr ? "on" : "off");
|
||||||
}
|
}
|
||||||
End();
|
End();
|
||||||
}
|
}
|
||||||
|
@ -350,7 +350,7 @@ bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::
|
|||||||
auto title_id = GetTitleID();
|
auto title_id = GetTitleID();
|
||||||
|
|
||||||
if (parent_path.filename() != title_id &&
|
if (parent_path.filename() != title_id &&
|
||||||
!fmt::UTF(extract_path.u8string()).data.ends_with("-UPDATE")) {
|
!fmt::UTF(extract_path.u8string()).data.ends_with("-patch")) {
|
||||||
extractPaths[ndinode_counter] = parent_path / title_id;
|
extractPaths[ndinode_counter] = parent_path / title_id;
|
||||||
} else {
|
} else {
|
||||||
// DLCs path has different structure
|
// DLCs path has different structure
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include "common/assert.h"
|
|
||||||
#include "common/io_file.h"
|
|
||||||
#include "common/stb.h"
|
|
||||||
#include "splash.h"
|
|
||||||
|
|
||||||
bool Splash::Open(const std::filesystem::path& filepath) {
|
|
||||||
ASSERT_MSG(filepath.extension().string() == ".png", "Unexpected file format passed");
|
|
||||||
|
|
||||||
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
|
|
||||||
if (!file.IsOpen()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> png_file{};
|
|
||||||
const auto png_size = file.GetSize();
|
|
||||||
png_file.resize(png_size);
|
|
||||||
file.Seek(0);
|
|
||||||
file.Read(png_file);
|
|
||||||
|
|
||||||
auto* img_mem = stbi_load_from_memory(png_file.data(), png_file.size(),
|
|
||||||
reinterpret_cast<int*>(&img_info.width),
|
|
||||||
reinterpret_cast<int*>(&img_info.height),
|
|
||||||
reinterpret_cast<int*>(&img_info.num_channels), 4);
|
|
||||||
if (!img_mem) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto img_size = img_info.GetSizeBytes();
|
|
||||||
img_data.resize(img_size);
|
|
||||||
std::memcpy(img_data.data(), img_mem, img_size);
|
|
||||||
stbi_image_free(img_mem);
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include "common/types.h"
|
|
||||||
|
|
||||||
class Splash {
|
|
||||||
public:
|
|
||||||
struct ImageInfo {
|
|
||||||
u32 width;
|
|
||||||
u32 height;
|
|
||||||
u32 num_channels;
|
|
||||||
|
|
||||||
u32 GetSizeBytes() const {
|
|
||||||
return width * height * 4; // we always forcing rgba8 for simplicity
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Splash() = default;
|
|
||||||
~Splash() = default;
|
|
||||||
|
|
||||||
bool Open(const std::filesystem::path& filepath);
|
|
||||||
[[nodiscard]] bool IsLoaded() const {
|
|
||||||
return img_data.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& GetImageData() const {
|
|
||||||
return img_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageInfo GetImageInfo() const {
|
|
||||||
return img_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ImageInfo img_info{};
|
|
||||||
std::vector<u8> img_data{};
|
|
||||||
};
|
|
@ -70,6 +70,10 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea
|
|||||||
std::filesystem::path host_path = mount->host_path / rel_path;
|
std::filesystem::path host_path = mount->host_path / rel_path;
|
||||||
std::filesystem::path patch_path = mount->host_path;
|
std::filesystem::path patch_path = mount->host_path;
|
||||||
patch_path += "-UPDATE";
|
patch_path += "-UPDATE";
|
||||||
|
if (!std::filesystem::exists(patch_path)) {
|
||||||
|
patch_path = mount->host_path;
|
||||||
|
patch_path += "-patch";
|
||||||
|
}
|
||||||
patch_path /= rel_path;
|
patch_path /= rel_path;
|
||||||
|
|
||||||
if ((corrected_path.starts_with("/app0") || corrected_path.starts_with("/hostapp")) &&
|
if ((corrected_path.starts_with("/app0") || corrected_path.starts_with("/hostapp")) &&
|
||||||
|
@ -9,29 +9,29 @@
|
|||||||
|
|
||||||
namespace Libraries::DiscMap {
|
namespace Libraries::DiscMap {
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceDiscMapGetPackageSize() {
|
int PS4_SYSV_ABI sceDiscMapGetPackageSize(s64 fflags, int* ret1, int* ret2) {
|
||||||
LOG_WARNING(Lib_DiscMap, "(DUMMY) called");
|
|
||||||
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD() {
|
int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD(char* path, s64 offset, s64 nbytes, int* ret) {
|
||||||
LOG_WARNING(Lib_DiscMap, "(DUMMY) called");
|
|
||||||
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI Func_7C980FFB0AA27E7A() {
|
int PS4_SYSV_ABI Func_7C980FFB0AA27E7A(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
|
||||||
LOG_ERROR(Lib_DiscMap, "(STUBBED) called");
|
int* ret2) {
|
||||||
|
*flags = 0;
|
||||||
|
*ret1 = 0;
|
||||||
|
*ret2 = 0;
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9() {
|
int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
|
||||||
LOG_ERROR(Lib_DiscMap, "(STUBBED) called");
|
int* ret2) {
|
||||||
return ORBIS_OK;
|
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI Func_E7EBCE96E92F91F8() {
|
int PS4_SYSV_ABI Func_E7EBCE96E92F91F8() {
|
||||||
LOG_ERROR(Lib_DiscMap, "(STUBBED) called");
|
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym) {
|
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym) {
|
||||||
|
@ -10,10 +10,12 @@ class SymbolsResolver;
|
|||||||
}
|
}
|
||||||
namespace Libraries::DiscMap {
|
namespace Libraries::DiscMap {
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceDiscMapGetPackageSize();
|
int PS4_SYSV_ABI sceDiscMapGetPackageSize(s64 fflags, int* ret1, int* ret2);
|
||||||
int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD();
|
int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD(char* path, s64 offset, s64 nbytes, int* ret);
|
||||||
int PS4_SYSV_ABI Func_7C980FFB0AA27E7A();
|
int PS4_SYSV_ABI Func_7C980FFB0AA27E7A(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
|
||||||
int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9();
|
int* ret2);
|
||||||
|
int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
|
||||||
|
int* ret2);
|
||||||
int PS4_SYSV_ABI Func_E7EBCE96E92F91F8();
|
int PS4_SYSV_ABI Func_E7EBCE96E92F91F8();
|
||||||
|
|
||||||
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym);
|
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym);
|
||||||
|
@ -1087,7 +1087,8 @@ s32 PS4_SYSV_ABI sceGnmInsertWaitFlipDone(u32* cmdbuf, u32 size, s32 vo_handle,
|
|||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t label_addr{};
|
uintptr_t label_addr{};
|
||||||
VideoOut::sceVideoOutGetBufferLabelAddress(vo_handle, &label_addr);
|
ASSERT_MSG(VideoOut::sceVideoOutGetBufferLabelAddress(vo_handle, &label_addr) == 16,
|
||||||
|
"sceVideoOutGetBufferLabelAddress call failed");
|
||||||
|
|
||||||
auto* wait_reg_mem = reinterpret_cast<PM4CmdWaitRegMem*>(cmdbuf);
|
auto* wait_reg_mem = reinterpret_cast<PM4CmdWaitRegMem*>(cmdbuf);
|
||||||
wait_reg_mem->header = PM4Type3Header{PM4ItOpcode::WaitRegMem, 5};
|
wait_reg_mem->header = PM4Type3Header{PM4ItOpcode::WaitRegMem, 5};
|
||||||
@ -2041,7 +2042,8 @@ static inline s32 PatchFlipRequest(u32* cmdbuf, u32 size, u32 vo_handle, u32 buf
|
|||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t label_addr{};
|
uintptr_t label_addr{};
|
||||||
VideoOut::sceVideoOutGetBufferLabelAddress(vo_handle, &label_addr);
|
ASSERT_MSG(VideoOut::sceVideoOutGetBufferLabelAddress(vo_handle, &label_addr) == 16,
|
||||||
|
"sceVideoOutGetBufferLabelAddress call failed");
|
||||||
|
|
||||||
// Write event to lock the VO surface
|
// Write event to lock the VO surface
|
||||||
auto* write_lock = reinterpret_cast<PM4CmdWriteData*>(cmdbuf);
|
auto* write_lock = reinterpret_cast<PM4CmdWriteData*>(cmdbuf);
|
||||||
|
@ -49,9 +49,9 @@ public:
|
|||||||
|
|
||||||
// Are we supposed to call the event handler on init with
|
// Are we supposed to call the event handler on init with
|
||||||
// ADD_OSK?
|
// ADD_OSK?
|
||||||
if (!ime_mode && False(m_param.key.option & OrbisImeKeyboardOption::AddOsk)) {
|
/* if (!ime_mode && False(m_param.key.option & OrbisImeKeyboardOption::AddOsk)) {
|
||||||
Execute(nullptr, &openEvent, true);
|
Execute(nullptr, &openEvent, true);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
if (ime_mode) {
|
if (ime_mode) {
|
||||||
g_ime_state = ImeState(&m_param.ime);
|
g_ime_state = ImeState(&m_param.ime);
|
||||||
@ -274,6 +274,13 @@ s32 PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* par
|
|||||||
if (!param) {
|
if (!param) {
|
||||||
return ORBIS_IME_ERROR_INVALID_ADDRESS;
|
return ORBIS_IME_ERROR_INVALID_ADDRESS;
|
||||||
}
|
}
|
||||||
|
if (!param->arg) {
|
||||||
|
return ORBIS_IME_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
if (!param->handler) {
|
||||||
|
return ORBIS_IME_ERROR_INVALID_HANDLER;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_keyboard_handler) {
|
if (g_keyboard_handler) {
|
||||||
return ORBIS_IME_ERROR_BUSY;
|
return ORBIS_IME_ERROR_BUSY;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ enum class OrbisImeKeyboardOption : u32 {
|
|||||||
Repeat = 1,
|
Repeat = 1,
|
||||||
RepeatEachKey = 2,
|
RepeatEachKey = 2,
|
||||||
AddOsk = 4,
|
AddOsk = 4,
|
||||||
EffectiveWithTime = 8,
|
EffectiveWithIme = 8,
|
||||||
DisableResume = 16,
|
DisableResume = 16,
|
||||||
DisableCapslockWithoutShift = 32,
|
DisableCapslockWithoutShift = 32,
|
||||||
};
|
};
|
||||||
|
@ -65,10 +65,10 @@ constexpr int ORBIS_KERNEL_O_DSYNC = 0x1000;
|
|||||||
constexpr int ORBIS_KERNEL_O_DIRECT = 0x00010000;
|
constexpr int ORBIS_KERNEL_O_DIRECT = 0x00010000;
|
||||||
constexpr int ORBIS_KERNEL_O_DIRECTORY = 0x00020000;
|
constexpr int ORBIS_KERNEL_O_DIRECTORY = 0x00020000;
|
||||||
|
|
||||||
s64 PS4_SYSV_ABI sceKernelWrite(int d, const void* buf, size_t nbytes);
|
s64 PS4_SYSV_ABI sceKernelWrite(s32 fd, const void* buf, size_t nbytes);
|
||||||
s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes);
|
s64 PS4_SYSV_ABI sceKernelRead(s32 fd, void* buf, size_t nbytes);
|
||||||
s64 PS4_SYSV_ABI sceKernelPread(int d, void* buf, size_t nbytes, s64 offset);
|
s64 PS4_SYSV_ABI sceKernelPread(s32 fd, void* buf, size_t nbytes, s64 offset);
|
||||||
s64 PS4_SYSV_ABI sceKernelPwrite(int d, void* buf, size_t nbytes, s64 offset);
|
s64 PS4_SYSV_ABI sceKernelPwrite(s32 fd, void* buf, size_t nbytes, s64 offset);
|
||||||
void RegisterFileSystem(Core::Loader::SymbolsResolver* sym);
|
void RegisterFileSystem(Core::Loader::SymbolsResolver* sym);
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
@ -85,17 +85,23 @@ int ErrnoToSceKernelError(int error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SetPosixErrno(int e) {
|
void SetPosixErrno(int e) {
|
||||||
// Some error numbers are different between supported OSes or the PS4
|
// Some error numbers are different between supported OSes
|
||||||
switch (e) {
|
switch (e) {
|
||||||
case EPERM:
|
case EPERM:
|
||||||
g_posix_errno = POSIX_EPERM;
|
g_posix_errno = POSIX_EPERM;
|
||||||
break;
|
break;
|
||||||
case EAGAIN:
|
case ENOENT:
|
||||||
g_posix_errno = POSIX_EAGAIN;
|
g_posix_errno = POSIX_ENOENT;
|
||||||
|
break;
|
||||||
|
case EDEADLK:
|
||||||
|
g_posix_errno = POSIX_EDEADLK;
|
||||||
break;
|
break;
|
||||||
case ENOMEM:
|
case ENOMEM:
|
||||||
g_posix_errno = POSIX_ENOMEM;
|
g_posix_errno = POSIX_ENOMEM;
|
||||||
break;
|
break;
|
||||||
|
case EACCES:
|
||||||
|
g_posix_errno = POSIX_EACCES;
|
||||||
|
break;
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
g_posix_errno = POSIX_EINVAL;
|
g_posix_errno = POSIX_EINVAL;
|
||||||
break;
|
break;
|
||||||
@ -105,13 +111,14 @@ void SetPosixErrno(int e) {
|
|||||||
case ERANGE:
|
case ERANGE:
|
||||||
g_posix_errno = POSIX_ERANGE;
|
g_posix_errno = POSIX_ERANGE;
|
||||||
break;
|
break;
|
||||||
case EDEADLK:
|
case EAGAIN:
|
||||||
g_posix_errno = POSIX_EDEADLK;
|
g_posix_errno = POSIX_EAGAIN;
|
||||||
break;
|
break;
|
||||||
case ETIMEDOUT:
|
case ETIMEDOUT:
|
||||||
g_posix_errno = POSIX_ETIMEDOUT;
|
g_posix_errno = POSIX_ETIMEDOUT;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
LOG_WARNING(Kernel, "Unhandled errno {}", e);
|
||||||
g_posix_errno = e;
|
g_posix_errno = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,14 +140,6 @@ void PS4_SYSV_ABI sceLibcHeapGetTraceInfo(HeapInfoInfo* info) {
|
|||||||
info->getSegmentInfo = 0;
|
info->getSegmentInfo = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 PS4_SYSV_ABI ps4__write(int d, const char* buf, std::size_t nbytes) {
|
|
||||||
return sceKernelWrite(d, buf, nbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
s64 PS4_SYSV_ABI ps4__read(int d, void* buf, u64 nbytes) {
|
|
||||||
return sceKernelRead(d, buf, nbytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct OrbisKernelUuid {
|
struct OrbisKernelUuid {
|
||||||
u32 timeLow;
|
u32 timeLow;
|
||||||
u16 timeMid;
|
u16 timeMid;
|
||||||
@ -229,13 +228,10 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("Xjoosiw+XPI", "libkernel", 1, "libkernel", 1, 1, sceKernelUuidCreate);
|
LIB_FUNCTION("Xjoosiw+XPI", "libkernel", 1, "libkernel", 1, 1, sceKernelUuidCreate);
|
||||||
LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail);
|
LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail);
|
||||||
LIB_FUNCTION("9BcDykPmo1I", "libkernel", 1, "libkernel", 1, 1, __Error);
|
LIB_FUNCTION("9BcDykPmo1I", "libkernel", 1, "libkernel", 1, 1, __Error);
|
||||||
LIB_FUNCTION("DRuBt2pvICk", "libkernel", 1, "libkernel", 1, 1, ps4__read);
|
|
||||||
LIB_FUNCTION("k+AXqu2-eBc", "libkernel", 1, "libkernel", 1, 1, posix_getpagesize);
|
LIB_FUNCTION("k+AXqu2-eBc", "libkernel", 1, "libkernel", 1, 1, posix_getpagesize);
|
||||||
LIB_FUNCTION("k+AXqu2-eBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpagesize);
|
LIB_FUNCTION("k+AXqu2-eBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpagesize);
|
||||||
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
|
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
|
||||||
sceLibcHeapGetTraceInfo);
|
sceLibcHeapGetTraceInfo);
|
||||||
LIB_FUNCTION("FxVZqBAA7ks", "libkernel", 1, "libkernel", 1, 1, ps4__write);
|
|
||||||
LIB_FUNCTION("FN4gaPmuFV8", "libScePosix", 1, "libkernel", 1, 1, ps4__write);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
|
#include "common/string_literal.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "core/libraries/kernel/orbis_error.h"
|
#include "core/libraries/kernel/orbis_error.h"
|
||||||
|
|
||||||
@ -18,15 +19,6 @@ void ErrSceToPosix(int result);
|
|||||||
int ErrnoToSceKernelError(int e);
|
int ErrnoToSceKernelError(int e);
|
||||||
void SetPosixErrno(int e);
|
void SetPosixErrno(int e);
|
||||||
|
|
||||||
template <size_t N>
|
|
||||||
struct StringLiteral {
|
|
||||||
constexpr StringLiteral(const char (&str)[N]) {
|
|
||||||
std::copy_n(str, N, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
char value[N];
|
|
||||||
};
|
|
||||||
|
|
||||||
template <StringLiteral name, class F, F f>
|
template <StringLiteral name, class F, F f>
|
||||||
struct WrapperImpl;
|
struct WrapperImpl;
|
||||||
|
|
||||||
|
@ -79,6 +79,9 @@ s32 PS4_SYSV_ABI sceKernelAllocateMainDirectMemory(size_t len, size_t alignment,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len) {
|
s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len) {
|
||||||
|
if (len == 0) {
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
LOG_INFO(Kernel_Vmm, "called start = {:#x}, len = {:#x}", start, len);
|
LOG_INFO(Kernel_Vmm, "called start = {:#x}, len = {:#x}", start, len);
|
||||||
auto* memory = Core::Memory::Instance();
|
auto* memory = Core::Memory::Instance();
|
||||||
memory->Free(start, len);
|
memory->Free(start, len);
|
||||||
@ -86,6 +89,9 @@ s32 PS4_SYSV_ABI sceKernelCheckedReleaseDirectMemory(u64 start, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceKernelReleaseDirectMemory(u64 start, size_t len) {
|
s32 PS4_SYSV_ABI sceKernelReleaseDirectMemory(u64 start, size_t len) {
|
||||||
|
if (len == 0) {
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
auto* memory = Core::Memory::Instance();
|
auto* memory = Core::Memory::Instance();
|
||||||
memory->Free(start, len);
|
memory->Free(start, len);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
@ -507,7 +513,7 @@ s32 PS4_SYSV_ABI sceKernelConfiguredFlexibleMemorySize(u64* sizeOut) {
|
|||||||
int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) {
|
int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) {
|
||||||
LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}", fmt::ptr(addr), len);
|
LOG_INFO(Kernel_Vmm, "addr = {}, len = {:#x}", fmt::ptr(addr), len);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
return ORBIS_OK;
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
auto* memory = Core::Memory::Instance();
|
auto* memory = Core::Memory::Instance();
|
||||||
return memory->UnmapMemory(std::bit_cast<VAddr>(addr), len);
|
return memory->UnmapMemory(std::bit_cast<VAddr>(addr), len);
|
||||||
|
@ -32,44 +32,44 @@ void* PS4_SYSV_ABI sceKernelGetProcParam() {
|
|||||||
return linker->GetProcParam();
|
return linker->GetProcParam();
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char* moduleFileName, size_t args, const void* argp,
|
s32 PS4_SYSV_ABI sceKernelLoadStartModule(const char* moduleFileName, u64 args, const void* argp,
|
||||||
u32 flags, const void* pOpt, int* pRes) {
|
u32 flags, const void* pOpt, int* pRes) {
|
||||||
LOG_INFO(Lib_Kernel, "called filename = {}, args = {}", moduleFileName, args);
|
LOG_INFO(Lib_Kernel, "called filename = {}, args = {}", moduleFileName, args);
|
||||||
|
ASSERT(flags == 0);
|
||||||
if (flags != 0) {
|
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
|
||||||
const auto path = mnt->GetHostPath(moduleFileName);
|
|
||||||
|
|
||||||
// Load PRX module and relocate any modules that import it.
|
|
||||||
auto* linker = Common::Singleton<Core::Linker>::Instance();
|
auto* linker = Common::Singleton<Core::Linker>::Instance();
|
||||||
u32 handle = linker->FindByName(path);
|
|
||||||
if (handle != -1) {
|
std::filesystem::path path;
|
||||||
|
std::string guest_path(moduleFileName);
|
||||||
|
|
||||||
|
s32 handle = -1;
|
||||||
|
|
||||||
|
if (guest_path[0] == '/') {
|
||||||
|
// try load /system/common/lib/ +path
|
||||||
|
// try load /system/priv/lib/ +path
|
||||||
|
path = mnt->GetHostPath(guest_path);
|
||||||
|
handle = linker->LoadAndStartModule(path, args, argp, pRes);
|
||||||
|
if (handle != -1)
|
||||||
|
return handle;
|
||||||
|
} else {
|
||||||
|
if (!guest_path.contains('/')) {
|
||||||
|
path = mnt->GetHostPath("/app0/" + guest_path);
|
||||||
|
handle = linker->LoadAndStartModule(path, args, argp, pRes);
|
||||||
|
if (handle != -1)
|
||||||
|
return handle;
|
||||||
|
// if ((flags & 0x10000) != 0)
|
||||||
|
// try load /system/priv/lib/ +basename
|
||||||
|
// try load /system/common/lib/ +basename
|
||||||
|
} else {
|
||||||
|
path = mnt->GetHostPath(guest_path);
|
||||||
|
handle = linker->LoadAndStartModule(path, args, argp, pRes);
|
||||||
|
if (handle != -1)
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
handle = linker->LoadModule(path, true);
|
|
||||||
if (handle == -1) {
|
|
||||||
return ORBIS_KERNEL_ERROR_ESRCH;
|
|
||||||
}
|
|
||||||
auto* module = linker->GetModule(handle);
|
|
||||||
linker->RelocateAnyImports(module);
|
|
||||||
|
|
||||||
// If the new module has a TLS image, trigger its load when TlsGetAddr is called.
|
|
||||||
if (module->tls.image_size != 0) {
|
|
||||||
linker->AdvanceGenerationCounter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve and verify proc param according to libkernel.
|
return ORBIS_KERNEL_ERROR_ENOENT;
|
||||||
u64* param = module->GetProcParam<u64*>();
|
|
||||||
ASSERT_MSG(!param || param[0] >= 0x18, "Invalid module param size: {}", param[0]);
|
|
||||||
s32 ret = module->Start(args, argp, param);
|
|
||||||
if (pRes) {
|
|
||||||
*pRes = ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceKernelDlsym(s32 handle, const char* symbol, void** addrp) {
|
s32 PS4_SYSV_ABI sceKernelDlsym(s32 handle, const char* symbol, void** addrp) {
|
||||||
@ -85,19 +85,7 @@ s32 PS4_SYSV_ABI sceKernelDlsym(s32 handle, const char* symbol, void** addrp) {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr size_t ORBIS_DBG_MAX_NAME_LENGTH = 256;
|
s32 PS4_SYSV_ABI sceKernelGetModuleInfoForUnwind(VAddr addr, s32 flags,
|
||||||
|
|
||||||
struct OrbisModuleInfoForUnwind {
|
|
||||||
u64 st_size;
|
|
||||||
std::array<char, ORBIS_DBG_MAX_NAME_LENGTH> name;
|
|
||||||
VAddr eh_frame_hdr_addr;
|
|
||||||
VAddr eh_frame_addr;
|
|
||||||
u64 eh_frame_size;
|
|
||||||
VAddr seg0_addr;
|
|
||||||
u64 seg0_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceKernelGetModuleInfoForUnwind(VAddr addr, int flags,
|
|
||||||
OrbisModuleInfoForUnwind* info) {
|
OrbisModuleInfoForUnwind* info) {
|
||||||
if (flags >= 3) {
|
if (flags >= 3) {
|
||||||
std::memset(info, 0, sizeof(OrbisModuleInfoForUnwind));
|
std::memset(info, 0, sizeof(OrbisModuleInfoForUnwind));
|
||||||
|
@ -11,10 +11,25 @@ class SymbolsResolver;
|
|||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
|
static constexpr size_t ORBIS_DBG_MAX_NAME_LENGTH = 256;
|
||||||
|
|
||||||
|
struct OrbisModuleInfoForUnwind {
|
||||||
|
u64 st_size;
|
||||||
|
std::array<char, ORBIS_DBG_MAX_NAME_LENGTH> name;
|
||||||
|
VAddr eh_frame_hdr_addr;
|
||||||
|
VAddr eh_frame_addr;
|
||||||
|
u64 eh_frame_size;
|
||||||
|
VAddr seg0_addr;
|
||||||
|
u64 seg0_size;
|
||||||
|
};
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelIsNeoMode();
|
int PS4_SYSV_ABI sceKernelIsNeoMode();
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver);
|
int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver);
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceKernelGetModuleInfoForUnwind(VAddr addr, s32 flags,
|
||||||
|
OrbisModuleInfoForUnwind* info);
|
||||||
|
|
||||||
void RegisterProcess(Core::Loader::SymbolsResolver* sym);
|
void RegisterProcess(Core::Loader::SymbolsResolver* sym);
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/native_clock.h"
|
#include "common/native_clock.h"
|
||||||
|
#include "core/libraries/kernel/kernel.h"
|
||||||
#include "core/libraries/kernel/orbis_error.h"
|
#include "core/libraries/kernel/orbis_error.h"
|
||||||
#include "core/libraries/kernel/time.h"
|
#include "core/libraries/kernel/time.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
@ -19,6 +20,7 @@
|
|||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
#include <date/tz.h>
|
#include <date/tz.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -93,44 +95,189 @@ u32 PS4_SYSV_ABI sceKernelSleep(u32 seconds) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) {
|
#ifdef _WIN64
|
||||||
if (tp == nullptr) {
|
#ifndef CLOCK_REALTIME
|
||||||
|
#define CLOCK_REALTIME 0
|
||||||
|
#endif
|
||||||
|
#ifndef CLOCK_MONOTONIC
|
||||||
|
#define CLOCK_MONOTONIC 1
|
||||||
|
#endif
|
||||||
|
#ifndef CLOCK_PROCESS_CPUTIME_ID
|
||||||
|
#define CLOCK_PROCESS_CPUTIME_ID 2
|
||||||
|
#endif
|
||||||
|
#ifndef CLOCK_THREAD_CPUTIME_ID
|
||||||
|
#define CLOCK_THREAD_CPUTIME_ID 3
|
||||||
|
#endif
|
||||||
|
#ifndef CLOCK_REALTIME_COARSE
|
||||||
|
#define CLOCK_REALTIME_COARSE 5
|
||||||
|
#endif
|
||||||
|
#ifndef CLOCK_MONOTONIC_COARSE
|
||||||
|
#define CLOCK_MONOTONIC_COARSE 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DELTA_EPOCH_IN_100NS 116444736000000000ULL
|
||||||
|
|
||||||
|
static u64 FileTimeTo100Ns(FILETIME& ft) {
|
||||||
|
return *reinterpret_cast<u64*>(&ft);
|
||||||
|
}
|
||||||
|
|
||||||
|
static s32 clock_gettime(u32 clock_id, struct timespec* ts) {
|
||||||
|
switch (clock_id) {
|
||||||
|
case CLOCK_REALTIME:
|
||||||
|
case CLOCK_REALTIME_COARSE: {
|
||||||
|
FILETIME ft;
|
||||||
|
GetSystemTimeAsFileTime(&ft);
|
||||||
|
const u64 ns = FileTimeTo100Ns(ft) - DELTA_EPOCH_IN_100NS;
|
||||||
|
ts->tv_sec = ns / 10'000'000;
|
||||||
|
ts->tv_nsec = (ns % 10'000'000) * 100;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case CLOCK_MONOTONIC:
|
||||||
|
case CLOCK_MONOTONIC_COARSE: {
|
||||||
|
static LARGE_INTEGER pf = [] {
|
||||||
|
LARGE_INTEGER res{};
|
||||||
|
QueryPerformanceFrequency(&pf);
|
||||||
|
return res;
|
||||||
|
}();
|
||||||
|
|
||||||
|
LARGE_INTEGER pc{};
|
||||||
|
QueryPerformanceCounter(&pc);
|
||||||
|
ts->tv_sec = pc.QuadPart / pf.QuadPart;
|
||||||
|
ts->tv_nsec = ((pc.QuadPart % pf.QuadPart) * 1000'000'000) / pf.QuadPart;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case CLOCK_PROCESS_CPUTIME_ID: {
|
||||||
|
FILETIME ct, et, kt, ut;
|
||||||
|
if (!GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut)) {
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
const u64 ns = FileTimeTo100Ns(ut) + FileTimeTo100Ns(kt);
|
||||||
|
ts->tv_sec = ns / 10'000'000;
|
||||||
|
ts->tv_nsec = (ns % 10'000'000) * 100;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case CLOCK_THREAD_CPUTIME_ID: {
|
||||||
|
FILETIME ct, et, kt, ut;
|
||||||
|
if (!GetThreadTimes(GetCurrentThread(), &ct, &et, &kt, &ut)) {
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
const u64 ns = FileTimeTo100Ns(ut) + FileTimeTo100Ns(kt);
|
||||||
|
ts->tv_sec = ns / 10'000'000;
|
||||||
|
ts->tv_nsec = (ns % 10'000'000) * 100;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct OrbisKernelTimespec* ts) {
|
||||||
|
if (ts == nullptr) {
|
||||||
return ORBIS_KERNEL_ERROR_EFAULT;
|
return ORBIS_KERNEL_ERROR_EFAULT;
|
||||||
}
|
}
|
||||||
clockid_t pclock_id = CLOCK_REALTIME;
|
|
||||||
|
clockid_t pclock_id = CLOCK_MONOTONIC;
|
||||||
switch (clock_id) {
|
switch (clock_id) {
|
||||||
case ORBIS_CLOCK_REALTIME:
|
case ORBIS_CLOCK_REALTIME:
|
||||||
case ORBIS_CLOCK_REALTIME_PRECISE:
|
case ORBIS_CLOCK_REALTIME_PRECISE:
|
||||||
case ORBIS_CLOCK_REALTIME_FAST:
|
|
||||||
pclock_id = CLOCK_REALTIME;
|
pclock_id = CLOCK_REALTIME;
|
||||||
break;
|
break;
|
||||||
case ORBIS_CLOCK_SECOND:
|
case ORBIS_CLOCK_SECOND:
|
||||||
|
case ORBIS_CLOCK_REALTIME_FAST:
|
||||||
|
#ifndef __APPLE__
|
||||||
|
pclock_id = CLOCK_REALTIME_COARSE;
|
||||||
|
#else
|
||||||
|
pclock_id = CLOCK_REALTIME;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case ORBIS_CLOCK_UPTIME:
|
||||||
|
case ORBIS_CLOCK_UPTIME_PRECISE:
|
||||||
case ORBIS_CLOCK_MONOTONIC:
|
case ORBIS_CLOCK_MONOTONIC:
|
||||||
case ORBIS_CLOCK_MONOTONIC_PRECISE:
|
case ORBIS_CLOCK_MONOTONIC_PRECISE:
|
||||||
case ORBIS_CLOCK_MONOTONIC_FAST:
|
|
||||||
pclock_id = CLOCK_MONOTONIC;
|
pclock_id = CLOCK_MONOTONIC;
|
||||||
break;
|
break;
|
||||||
default:
|
case ORBIS_CLOCK_UPTIME_FAST:
|
||||||
LOG_ERROR(Lib_Kernel, "unsupported = {} using CLOCK_REALTIME", clock_id);
|
case ORBIS_CLOCK_MONOTONIC_FAST:
|
||||||
|
#ifndef __APPLE__
|
||||||
|
pclock_id = CLOCK_MONOTONIC_COARSE;
|
||||||
|
#else
|
||||||
|
pclock_id = CLOCK_MONOTONIC;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
case ORBIS_CLOCK_THREAD_CPUTIME_ID:
|
||||||
|
pclock_id = CLOCK_THREAD_CPUTIME_ID;
|
||||||
|
break;
|
||||||
|
case ORBIS_CLOCK_PROCTIME: {
|
||||||
|
const auto us = sceKernelGetProcessTime();
|
||||||
|
ts->tv_sec = us / 1'000'000;
|
||||||
|
ts->tv_nsec = (us % 1'000'000) * 1000;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case ORBIS_CLOCK_VIRTUAL: {
|
||||||
|
#ifdef _WIN64
|
||||||
|
FILETIME ct, et, kt, ut;
|
||||||
|
if (!GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut)) {
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
const u64 ns = FileTimeTo100Ns(ut);
|
||||||
|
ts->tv_sec = ns / 10'000'000;
|
||||||
|
ts->tv_nsec = (ns % 10'000'000) * 100;
|
||||||
|
#else
|
||||||
|
struct rusage ru;
|
||||||
|
const auto res = getrusage(RUSAGE_SELF, &ru);
|
||||||
|
if (res < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
ts->tv_sec = ru.ru_utime.tv_sec;
|
||||||
|
ts->tv_nsec = ru.ru_utime.tv_usec * 1000;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case ORBIS_CLOCK_PROF: {
|
||||||
|
#ifdef _WIN64
|
||||||
|
FILETIME ct, et, kt, ut;
|
||||||
|
if (!GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut)) {
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
const u64 ns = FileTimeTo100Ns(kt);
|
||||||
|
ts->tv_sec = ns / 10'000'000;
|
||||||
|
ts->tv_nsec = (ns % 10'000'000) * 100;
|
||||||
|
#else
|
||||||
|
struct rusage ru;
|
||||||
|
const auto res = getrusage(RUSAGE_SELF, &ru);
|
||||||
|
if (res < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
ts->tv_sec = ru.ru_stime.tv_sec;
|
||||||
|
ts->tv_nsec = ru.ru_stime.tv_usec * 1000;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case ORBIS_CLOCK_EXT_NETWORK:
|
||||||
|
case ORBIS_CLOCK_EXT_DEBUG_NETWORK:
|
||||||
|
case ORBIS_CLOCK_EXT_AD_NETWORK:
|
||||||
|
case ORBIS_CLOCK_EXT_RAW_NETWORK:
|
||||||
|
pclock_id = CLOCK_MONOTONIC;
|
||||||
|
LOG_ERROR(Lib_Kernel, "unsupported = {} using CLOCK_MONOTONIC", clock_id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
timespec t{};
|
timespec t{};
|
||||||
int result = clock_gettime(pclock_id, &t);
|
int result = clock_gettime(pclock_id, &t);
|
||||||
tp->tv_sec = t.tv_sec;
|
ts->tv_sec = t.tv_sec;
|
||||||
tp->tv_nsec = t.tv_nsec;
|
ts->tv_nsec = t.tv_nsec;
|
||||||
if (result == 0) {
|
return result;
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_clock_gettime(s32 clock_id, OrbisKernelTimespec* time) {
|
int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) {
|
||||||
int result = sceKernelClockGettime(clock_id, time);
|
const auto res = orbis_clock_gettime(clock_id, tp);
|
||||||
if (result < 0) {
|
if (res < 0) {
|
||||||
UNREACHABLE(); // TODO return posix error code
|
return ErrnoToSceKernelError(res);
|
||||||
}
|
}
|
||||||
return result;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_nanosleep(const OrbisKernelTimespec* rqtp, OrbisKernelTimespec* rmtp) {
|
int PS4_SYSV_ABI posix_nanosleep(const OrbisKernelTimespec* rqtp, OrbisKernelTimespec* rmtp) {
|
||||||
@ -316,8 +463,8 @@ void RegisterTime(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("yS8U2TGCe1A", "libScePosix", 1, "libkernel", 1, 1, posix_nanosleep);
|
LIB_FUNCTION("yS8U2TGCe1A", "libScePosix", 1, "libkernel", 1, 1, posix_nanosleep);
|
||||||
LIB_FUNCTION("QBi7HCK03hw", "libkernel", 1, "libkernel", 1, 1, sceKernelClockGettime);
|
LIB_FUNCTION("QBi7HCK03hw", "libkernel", 1, "libkernel", 1, 1, sceKernelClockGettime);
|
||||||
LIB_FUNCTION("kOcnerypnQA", "libkernel", 1, "libkernel", 1, 1, sceKernelGettimezone);
|
LIB_FUNCTION("kOcnerypnQA", "libkernel", 1, "libkernel", 1, 1, sceKernelGettimezone);
|
||||||
LIB_FUNCTION("lLMT9vJAck0", "libkernel", 1, "libkernel", 1, 1, posix_clock_gettime);
|
LIB_FUNCTION("lLMT9vJAck0", "libkernel", 1, "libkernel", 1, 1, orbis_clock_gettime);
|
||||||
LIB_FUNCTION("lLMT9vJAck0", "libScePosix", 1, "libkernel", 1, 1, posix_clock_gettime);
|
LIB_FUNCTION("lLMT9vJAck0", "libScePosix", 1, "libkernel", 1, 1, orbis_clock_gettime);
|
||||||
LIB_FUNCTION("smIj7eqzZE8", "libScePosix", 1, "libkernel", 1, 1, posix_clock_getres);
|
LIB_FUNCTION("smIj7eqzZE8", "libScePosix", 1, "libkernel", 1, 1, posix_clock_getres);
|
||||||
LIB_FUNCTION("0NTHN1NKONI", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertLocaltimeToUtc);
|
LIB_FUNCTION("0NTHN1NKONI", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertLocaltimeToUtc);
|
||||||
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime);
|
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime);
|
||||||
|
@ -115,6 +115,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
|||||||
Libraries::NpParty::RegisterlibSceNpParty(sym);
|
Libraries::NpParty::RegisterlibSceNpParty(sym);
|
||||||
Libraries::Zlib::RegisterlibSceZlib(sym);
|
Libraries::Zlib::RegisterlibSceZlib(sym);
|
||||||
Libraries::Hmd::RegisterlibSceHmd(sym);
|
Libraries::Hmd::RegisterlibSceHmd(sym);
|
||||||
|
Libraries::DiscMap::RegisterlibSceDiscMap(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries
|
} // namespace Libraries
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "core/libraries/network/http.h"
|
#include "core/libraries/network/http.h"
|
||||||
|
#include "http_error.h"
|
||||||
|
|
||||||
namespace Libraries::Http {
|
namespace Libraries::Http {
|
||||||
|
|
||||||
@ -566,17 +567,277 @@ int PS4_SYSV_ABI sceHttpUriMerge() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceHttpUriParse() {
|
int PS4_SYSV_ABI sceHttpUriParse(OrbisHttpUriElement* out, const char* srcUri, void* pool,
|
||||||
|
size_t* require, size_t prepare) {
|
||||||
|
LOG_INFO(Lib_Http, "srcUri = {}", std::string(srcUri));
|
||||||
|
if (!srcUri) {
|
||||||
|
LOG_ERROR(Lib_Http, "invalid url");
|
||||||
|
return ORBIS_HTTP_ERROR_INVALID_URL;
|
||||||
|
}
|
||||||
|
if (!out && !pool && !require) {
|
||||||
|
LOG_ERROR(Lib_Http, "invalid values");
|
||||||
|
return ORBIS_HTTP_ERROR_INVALID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out && pool) {
|
||||||
|
memset(out, 0, sizeof(OrbisHttpUriElement));
|
||||||
|
out->scheme = (char*)pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Track the total required buffer size
|
||||||
|
size_t requiredSize = 0;
|
||||||
|
|
||||||
|
// Parse the scheme (e.g., "http:", "https:", "file:")
|
||||||
|
size_t schemeLength = 0;
|
||||||
|
while (srcUri[schemeLength] && srcUri[schemeLength] != ':') {
|
||||||
|
if (!isalnum(srcUri[schemeLength])) {
|
||||||
|
LOG_ERROR(Lib_Http, "invalid url");
|
||||||
|
return ORBIS_HTTP_ERROR_INVALID_URL;
|
||||||
|
}
|
||||||
|
schemeLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pool && prepare < schemeLength + 1) {
|
||||||
|
LOG_ERROR(Lib_Http, "out of memory");
|
||||||
|
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out && pool) {
|
||||||
|
memcpy(out->scheme, srcUri, schemeLength);
|
||||||
|
out->scheme[schemeLength] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
requiredSize += schemeLength + 1;
|
||||||
|
|
||||||
|
// Move past the scheme and ':' character
|
||||||
|
size_t offset = schemeLength + 1;
|
||||||
|
|
||||||
|
// Check if "//" appears after the scheme
|
||||||
|
if (strncmp(srcUri + offset, "//", 2) == 0) {
|
||||||
|
// "//" is present
|
||||||
|
if (out) {
|
||||||
|
out->opaque = false;
|
||||||
|
}
|
||||||
|
offset += 2; // Move past "//"
|
||||||
|
} else {
|
||||||
|
// "//" is not present
|
||||||
|
if (out) {
|
||||||
|
out->opaque = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle "file" scheme
|
||||||
|
if (strncmp(srcUri, "file", 4) == 0) {
|
||||||
|
// File URIs typically start with "file://"
|
||||||
|
if (out && !out->opaque) {
|
||||||
|
// Skip additional slashes (e.g., "////")
|
||||||
|
while (srcUri[offset] == '/') {
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the path (everything after the slashes)
|
||||||
|
char* pathStart = (char*)srcUri + offset;
|
||||||
|
size_t pathLength = 0;
|
||||||
|
while (pathStart[pathLength] && pathStart[pathLength] != '?' &&
|
||||||
|
pathStart[pathLength] != '#') {
|
||||||
|
pathLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the path starts with '/'
|
||||||
|
if (pathLength > 0 && pathStart[0] != '/') {
|
||||||
|
// Prepend '/' to the path
|
||||||
|
requiredSize += pathLength + 2; // Include '/' and null terminator
|
||||||
|
|
||||||
|
if (pool && prepare < requiredSize) {
|
||||||
|
LOG_ERROR(Lib_Http, "out of memory");
|
||||||
|
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out && pool) {
|
||||||
|
out->path = (char*)pool + (requiredSize - pathLength - 2);
|
||||||
|
out->path[0] = '/'; // Add leading '/'
|
||||||
|
memcpy(out->path + 1, pathStart, pathLength);
|
||||||
|
out->path[pathLength + 1] = '\0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Path already starts with '/'
|
||||||
|
requiredSize += pathLength + 1;
|
||||||
|
|
||||||
|
if (pool && prepare < requiredSize) {
|
||||||
|
LOG_ERROR(Lib_Http, "out of memory");
|
||||||
|
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out && pool) {
|
||||||
|
memcpy((char*)pool + (requiredSize - pathLength - 1), pathStart, pathLength);
|
||||||
|
out->path = (char*)pool + (requiredSize - pathLength - 1);
|
||||||
|
out->path[pathLength] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move past the path
|
||||||
|
offset += pathLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle non-file schemes (e.g., "http", "https")
|
||||||
|
else {
|
||||||
|
// Parse the host and port
|
||||||
|
char* hostStart = (char*)srcUri + offset;
|
||||||
|
while (*hostStart == '/') {
|
||||||
|
hostStart++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t hostLength = 0;
|
||||||
|
while (hostStart[hostLength] && hostStart[hostLength] != '/' &&
|
||||||
|
hostStart[hostLength] != '?' && hostStart[hostLength] != ':') {
|
||||||
|
hostLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
requiredSize += hostLength + 1;
|
||||||
|
|
||||||
|
if (pool && prepare < requiredSize) {
|
||||||
|
LOG_ERROR(Lib_Http, "out of memory");
|
||||||
|
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out && pool) {
|
||||||
|
memcpy((char*)pool + (requiredSize - hostLength - 1), hostStart, hostLength);
|
||||||
|
out->hostname = (char*)pool + (requiredSize - hostLength - 1);
|
||||||
|
out->hostname[hostLength] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move past the host
|
||||||
|
offset += hostLength;
|
||||||
|
|
||||||
|
// Parse the port (if present)
|
||||||
|
if (hostStart[hostLength] == ':') {
|
||||||
|
char* portStart = hostStart + hostLength + 1;
|
||||||
|
size_t portLength = 0;
|
||||||
|
while (portStart[portLength] && isdigit(portStart[portLength])) {
|
||||||
|
portLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
requiredSize += portLength + 1;
|
||||||
|
|
||||||
|
if (pool && prepare < requiredSize) {
|
||||||
|
LOG_ERROR(Lib_Http, "out of memory");
|
||||||
|
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the port string to a uint16_t
|
||||||
|
char portStr[6]; // Max length for a port number (65535)
|
||||||
|
if (portLength > 5) {
|
||||||
|
LOG_ERROR(Lib_Http, "invalid url");
|
||||||
|
return ORBIS_HTTP_ERROR_INVALID_URL;
|
||||||
|
}
|
||||||
|
memcpy(portStr, portStart, portLength);
|
||||||
|
portStr[portLength] = '\0';
|
||||||
|
|
||||||
|
uint16_t port = (uint16_t)atoi(portStr);
|
||||||
|
if (port == 0 && portStr[0] != '0') {
|
||||||
|
LOG_ERROR(Lib_Http, "invalid url");
|
||||||
|
return ORBIS_HTTP_ERROR_INVALID_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the port in the output structure
|
||||||
|
if (out) {
|
||||||
|
out->port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move past the port
|
||||||
|
offset += portLength + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the path (if present)
|
||||||
|
if (srcUri[offset] == '/') {
|
||||||
|
char* pathStart = (char*)srcUri + offset;
|
||||||
|
size_t pathLength = 0;
|
||||||
|
while (pathStart[pathLength] && pathStart[pathLength] != '?' &&
|
||||||
|
pathStart[pathLength] != '#') {
|
||||||
|
pathLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
requiredSize += pathLength + 1;
|
||||||
|
|
||||||
|
if (pool && prepare < requiredSize) {
|
||||||
|
LOG_ERROR(Lib_Http, "out of memory");
|
||||||
|
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out && pool) {
|
||||||
|
memcpy((char*)pool + (requiredSize - pathLength - 1), pathStart, pathLength);
|
||||||
|
out->path = (char*)pool + (requiredSize - pathLength - 1);
|
||||||
|
out->path[pathLength] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move past the path
|
||||||
|
offset += pathLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the query (if present)
|
||||||
|
if (srcUri[offset] == '?') {
|
||||||
|
char* queryStart = (char*)srcUri + offset + 1;
|
||||||
|
size_t queryLength = 0;
|
||||||
|
while (queryStart[queryLength] && queryStart[queryLength] != '#') {
|
||||||
|
queryLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
requiredSize += queryLength + 1;
|
||||||
|
|
||||||
|
if (pool && prepare < requiredSize) {
|
||||||
|
LOG_ERROR(Lib_Http, "out of memory");
|
||||||
|
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out && pool) {
|
||||||
|
memcpy((char*)pool + (requiredSize - queryLength - 1), queryStart, queryLength);
|
||||||
|
out->query = (char*)pool + (requiredSize - queryLength - 1);
|
||||||
|
out->query[queryLength] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move past the query
|
||||||
|
offset += queryLength + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the fragment (if present)
|
||||||
|
if (srcUri[offset] == '#') {
|
||||||
|
char* fragmentStart = (char*)srcUri + offset + 1;
|
||||||
|
size_t fragmentLength = 0;
|
||||||
|
while (fragmentStart[fragmentLength]) {
|
||||||
|
fragmentLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
requiredSize += fragmentLength + 1;
|
||||||
|
|
||||||
|
if (pool && prepare < requiredSize) {
|
||||||
|
LOG_ERROR(Lib_Http, "out of memory");
|
||||||
|
return ORBIS_HTTP_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out && pool) {
|
||||||
|
memcpy((char*)pool + (requiredSize - fragmentLength - 1), fragmentStart,
|
||||||
|
fragmentLength);
|
||||||
|
out->fragment = (char*)pool + (requiredSize - fragmentLength - 1);
|
||||||
|
out->fragment[fragmentLength] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the total required buffer size
|
||||||
|
if (require) {
|
||||||
|
*require = requiredSize; // Update with actual required size
|
||||||
|
}
|
||||||
|
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI sceHttpUriSweepPath(char* dst, const char* src, size_t srcSize) {
|
||||||
LOG_ERROR(Lib_Http, "(STUBBED) called");
|
LOG_ERROR(Lib_Http, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceHttpUriSweepPath() {
|
int PS4_SYSV_ABI sceHttpUriUnescape(char* out, size_t* require, size_t prepare, const char* in) {
|
||||||
LOG_ERROR(Lib_Http, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceHttpUriUnescape() {
|
|
||||||
LOG_ERROR(Lib_Http, "(STUBBED) called");
|
LOG_ERROR(Lib_Http, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,19 @@ class SymbolsResolver;
|
|||||||
|
|
||||||
namespace Libraries::Http {
|
namespace Libraries::Http {
|
||||||
|
|
||||||
|
struct OrbisHttpUriElement {
|
||||||
|
bool opaque;
|
||||||
|
char* scheme;
|
||||||
|
char* username;
|
||||||
|
char* password;
|
||||||
|
char* hostname;
|
||||||
|
char* path;
|
||||||
|
char* query;
|
||||||
|
char* fragment;
|
||||||
|
u16 port;
|
||||||
|
u8 reserved[10];
|
||||||
|
};
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceHttpAbortRequest();
|
int PS4_SYSV_ABI sceHttpAbortRequest();
|
||||||
int PS4_SYSV_ABI sceHttpAbortRequestForce();
|
int PS4_SYSV_ABI sceHttpAbortRequestForce();
|
||||||
int PS4_SYSV_ABI sceHttpAbortWaitRequest();
|
int PS4_SYSV_ABI sceHttpAbortWaitRequest();
|
||||||
@ -122,9 +135,10 @@ int PS4_SYSV_ABI sceHttpUriBuild();
|
|||||||
int PS4_SYSV_ABI sceHttpUriCopy();
|
int PS4_SYSV_ABI sceHttpUriCopy();
|
||||||
int PS4_SYSV_ABI sceHttpUriEscape();
|
int PS4_SYSV_ABI sceHttpUriEscape();
|
||||||
int PS4_SYSV_ABI sceHttpUriMerge();
|
int PS4_SYSV_ABI sceHttpUriMerge();
|
||||||
int PS4_SYSV_ABI sceHttpUriParse();
|
int PS4_SYSV_ABI sceHttpUriParse(OrbisHttpUriElement* out, const char* srcUri, void* pool,
|
||||||
int PS4_SYSV_ABI sceHttpUriSweepPath();
|
size_t* require, size_t prepare);
|
||||||
int PS4_SYSV_ABI sceHttpUriUnescape();
|
int PS4_SYSV_ABI sceHttpUriSweepPath(char* dst, const char* src, size_t srcSize);
|
||||||
|
int PS4_SYSV_ABI sceHttpUriUnescape(char* out, size_t* require, size_t prepare, const char* in);
|
||||||
int PS4_SYSV_ABI sceHttpWaitRequest();
|
int PS4_SYSV_ABI sceHttpWaitRequest();
|
||||||
|
|
||||||
void RegisterlibSceHttp(Core::Loader::SymbolsResolver* sym);
|
void RegisterlibSceHttp(Core::Loader::SymbolsResolver* sym);
|
||||||
|
66
src/core/libraries/network/http_error.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_BEFORE_INIT = 0x80431001;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_ALREADY_INITED = 0x80431020;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_BUSY = 0x80431021;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_OUT_OF_MEMORY = 0x80431022;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_NOT_FOUND = 0x80431025;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_INVALID_VERSION = 0x8043106a;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_INVALID_ID = 0x80431100;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_OUT_OF_SIZE = 0x80431104;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_INVALID_VALUE = 0x804311fe;
|
||||||
|
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_INVALID_URL = 0x80433060;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_UNKNOWN_SCHEME = 0x80431061;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_NETWORK = 0x80431063;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_BAD_RESPONSE = 0x80431064;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_BEFORE_SEND = 0x80431065;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_AFTER_SEND = 0x80431066;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_TIMEOUT = 0x80431068;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_UNKNOWN_AUTH_TYPE = 0x80431069;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_UNKNOWN_METHOD = 0x8043106b;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_READ_BY_HEAD_METHOD = 0x8043106f;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_NOT_IN_COM = 0x80431070;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_NO_CONTENT_LENGTH = 0x80431071;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_CHUNK_ENC = 0x80431072;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_TOO_LARGE_RESPONSE_HEADER = 0x80431073;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_SSL = 0x80431075;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_INSUFFICIENT_STACKSIZE = 0x80431076;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_ABORTED = 0x80431080;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_UNKNOWN = 0x80431081;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_EAGAIN = 0x80431082;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_PROXY = 0x80431084;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_BROKEN = 0x80431085;
|
||||||
|
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_PARSE_HTTP_NOT_FOUND = 0x80432025;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_PARSE_HTTP_INVALID_RESPONSE = 0x80432060;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_PARSE_HTTP_INVALID_VALUE = 0x804321fe;
|
||||||
|
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_RESOLVER_EPACKET = 0x80436001;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENODNS = 0x80436002;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ETIMEDOUT = 0x80436003;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENOSUPPORT = 0x80436004;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_RESOLVER_EFORMAT = 0x80436005;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ESERVERFAILURE = 0x80436006;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENOHOST = 0x80436007;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENOTIMPLEMENTED = 0x80436008;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ESERVERREFUSED = 0x80436009;
|
||||||
|
constexpr int ORBIS_HTTP_ERROR_RESOLVER_ENORECORD = 0x8043600a;
|
||||||
|
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_CERT = 0x80435060;
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_HANDSHAKE = 0x80435061;
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_IO = 0x80435062;
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_INTERNAL = 0x80435063;
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_PROXY = 0x80435064;
|
||||||
|
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_SSL_INTERNAL = 0x01;
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_SSL_INVALID_CERT = 0x02;
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_SSL_CN_CHECK = 0x04;
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_SSL_NOT_AFTER_CHECK = 0x08;
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_SSL_NOT_BEFORE_CHECK = 0x10;
|
||||||
|
constexpr int ORBIS_HTTPS_ERROR_SSL_UNKNOWN_CA = 0x20;
|
@ -5,21 +5,480 @@
|
|||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "core/libraries/ngs2/ngs2.h"
|
#include "core/libraries/ngs2/ngs2.h"
|
||||||
|
#include "core/libraries/ngs2/ngs2_custom.h"
|
||||||
#include "core/libraries/ngs2/ngs2_error.h"
|
#include "core/libraries/ngs2/ngs2_error.h"
|
||||||
|
#include "core/libraries/ngs2/ngs2_geom.h"
|
||||||
#include "core/libraries/ngs2/ngs2_impl.h"
|
#include "core/libraries/ngs2/ngs2_impl.h"
|
||||||
|
#include "core/libraries/ngs2/ngs2_pan.h"
|
||||||
|
#include "core/libraries/ngs2/ngs2_report.h"
|
||||||
|
|
||||||
namespace Libraries::Ngs2 {
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2CalcWaveformBlock() {
|
// Ngs2
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2CalcWaveformBlock(const OrbisNgs2WaveformFormat* format, u32 samplePos,
|
||||||
|
u32 numSamples, OrbisNgs2WaveformBlock* outBlock) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "samplePos = {}, numSamples = {}", samplePos, numSamples);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2CustomRackGetModuleInfo() {
|
s32 PS4_SYSV_ABI sceNgs2GetWaveformFrameInfo(const OrbisNgs2WaveformFormat* format,
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
u32* outFrameSize, u32* outNumFrameSamples,
|
||||||
|
u32* outUnitsPerFrame, u32* outNumDelaySamples) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2ParseWaveformData(const void* data, size_t dataSize,
|
||||||
|
OrbisNgs2WaveformInfo* outInfo) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "dataSize = {}", dataSize);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2ParseWaveformFile(const char* path, u64 offset,
|
||||||
|
OrbisNgs2WaveformInfo* outInfo) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "path = {}, offset = {}", path, offset);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2ParseWaveformUser(OrbisNgs2ParseReadHandler handler, uintptr_t userData,
|
||||||
|
OrbisNgs2WaveformInfo* outInfo) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "userData = {}", userData);
|
||||||
|
if (!handler) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "handler is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2RackCreate(OrbisNgs2Handle systemHandle, u32 rackId,
|
||||||
|
const OrbisNgs2RackOption* option,
|
||||||
|
const OrbisNgs2ContextBufferInfo* bufferInfo,
|
||||||
|
OrbisNgs2Handle* outHandle) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "rackId = {}", rackId);
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2RackCreateWithAllocator(OrbisNgs2Handle systemHandle, u32 rackId,
|
||||||
|
const OrbisNgs2RackOption* option,
|
||||||
|
const OrbisNgs2BufferAllocator* allocator,
|
||||||
|
OrbisNgs2Handle* outHandle) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "rackId = {}", rackId);
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2RackDestroy(OrbisNgs2Handle rackHandle,
|
||||||
|
OrbisNgs2ContextBufferInfo* outBufferInfo) {
|
||||||
|
if (!rackHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2RackGetInfo(OrbisNgs2Handle rackHandle, OrbisNgs2RackInfo* outInfo,
|
||||||
|
size_t infoSize) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "infoSize = {}", infoSize);
|
||||||
|
if (!rackHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2RackGetUserData(OrbisNgs2Handle rackHandle, uintptr_t* outUserData) {
|
||||||
|
if (!rackHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2RackGetVoiceHandle(OrbisNgs2Handle rackHandle, u32 voiceIndex,
|
||||||
|
OrbisNgs2Handle* outHandle) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "voiceIndex = {}", voiceIndex);
|
||||||
|
if (!rackHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2RackLock(OrbisNgs2Handle rackHandle) {
|
||||||
|
if (!rackHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2RackQueryBufferSize(u32 rackId, const OrbisNgs2RackOption* option,
|
||||||
|
OrbisNgs2ContextBufferInfo* outBufferInfo) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "rackId = {}", rackId);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2RackSetUserData(OrbisNgs2Handle rackHandle, uintptr_t userData) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "userData = {}", userData);
|
||||||
|
if (!rackHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2RackUnlock(OrbisNgs2Handle rackHandle) {
|
||||||
|
if (!rackHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemCreate(const OrbisNgs2SystemOption* option,
|
||||||
|
const OrbisNgs2ContextBufferInfo* bufferInfo,
|
||||||
|
OrbisNgs2Handle* outHandle) {
|
||||||
|
s32 result;
|
||||||
|
OrbisNgs2ContextBufferInfo localInfo;
|
||||||
|
if (!bufferInfo || !outHandle) {
|
||||||
|
if (!bufferInfo) {
|
||||||
|
result = ORBIS_NGS2_ERROR_INVALID_BUFFER_INFO;
|
||||||
|
LOG_ERROR(Lib_Ngs2, "Invalid system buffer info {}", (void*)bufferInfo);
|
||||||
|
} else {
|
||||||
|
result = ORBIS_NGS2_ERROR_INVALID_OUT_ADDRESS;
|
||||||
|
LOG_ERROR(Lib_Ngs2, "Invalid system handle address {}", (void*)outHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Report errors?
|
||||||
|
} else {
|
||||||
|
// Make bufferInfo copy
|
||||||
|
localInfo.hostBuffer = bufferInfo->hostBuffer;
|
||||||
|
localInfo.hostBufferSize = bufferInfo->hostBufferSize;
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
localInfo.reserved[i] = bufferInfo->reserved[i];
|
||||||
|
}
|
||||||
|
localInfo.userData = bufferInfo->userData;
|
||||||
|
|
||||||
|
result = SystemSetup(option, &localInfo, 0, outHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: API reporting?
|
||||||
|
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemCreateWithAllocator(const OrbisNgs2SystemOption* option,
|
||||||
|
const OrbisNgs2BufferAllocator* allocator,
|
||||||
|
OrbisNgs2Handle* outHandle) {
|
||||||
|
s32 result;
|
||||||
|
if (allocator && allocator->allocHandler != 0) {
|
||||||
|
OrbisNgs2BufferAllocHandler hostAlloc = allocator->allocHandler;
|
||||||
|
if (outHandle) {
|
||||||
|
OrbisNgs2BufferFreeHandler hostFree = allocator->freeHandler;
|
||||||
|
OrbisNgs2ContextBufferInfo* bufferInfo = 0;
|
||||||
|
result = SystemSetup(option, bufferInfo, 0, 0);
|
||||||
|
if (result >= 0) {
|
||||||
|
uintptr_t sysUserData = allocator->userData;
|
||||||
|
result = hostAlloc(bufferInfo);
|
||||||
|
if (result >= 0) {
|
||||||
|
OrbisNgs2Handle* handleCopy = outHandle;
|
||||||
|
result = SystemSetup(option, bufferInfo, hostFree, handleCopy);
|
||||||
|
if (result < 0) {
|
||||||
|
if (hostFree) {
|
||||||
|
hostFree(bufferInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = ORBIS_NGS2_ERROR_INVALID_OUT_ADDRESS;
|
||||||
|
LOG_ERROR(Lib_Ngs2, "Invalid system handle address {}", (void*)outHandle);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = ORBIS_NGS2_ERROR_INVALID_BUFFER_ALLOCATOR;
|
||||||
|
LOG_ERROR(Lib_Ngs2, "Invalid system buffer allocator {}", (void*)allocator);
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemDestroy(OrbisNgs2Handle systemHandle,
|
||||||
|
OrbisNgs2ContextBufferInfo* outBufferInfo) {
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemEnumHandles(OrbisNgs2Handle* aOutHandle, u32 maxHandles) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "maxHandles = {}", maxHandles);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemEnumRackHandles(OrbisNgs2Handle systemHandle,
|
||||||
|
OrbisNgs2Handle* aOutHandle, u32 maxHandles) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "maxHandles = {}", maxHandles);
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemGetInfo(OrbisNgs2Handle rackHandle, OrbisNgs2SystemInfo* outInfo,
|
||||||
|
size_t infoSize) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "infoSize = {}", infoSize);
|
||||||
|
if (!rackHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemGetUserData(OrbisNgs2Handle systemHandle, uintptr_t* outUserData) {
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemLock(OrbisNgs2Handle systemHandle) {
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemQueryBufferSize(const OrbisNgs2SystemOption* option,
|
||||||
|
OrbisNgs2ContextBufferInfo* outBufferInfo) {
|
||||||
|
s32 result;
|
||||||
|
if (outBufferInfo) {
|
||||||
|
result = SystemSetup(option, outBufferInfo, 0, 0);
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
} else {
|
||||||
|
result = ORBIS_NGS2_ERROR_INVALID_OUT_ADDRESS;
|
||||||
|
LOG_ERROR(Lib_Ngs2, "Invalid system buffer info {}", (void*)outBufferInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemRender(OrbisNgs2Handle systemHandle,
|
||||||
|
const OrbisNgs2RenderBufferInfo* aBufferInfo,
|
||||||
|
u32 numBufferInfo) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "numBufferInfo = {}", numBufferInfo);
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static s32 PS4_SYSV_ABI sceNgs2SystemResetOption(OrbisNgs2SystemOption* outOption) {
|
||||||
|
static const OrbisNgs2SystemOption option = {
|
||||||
|
sizeof(OrbisNgs2SystemOption), "", 0, 512, 256, 48000, {0}};
|
||||||
|
|
||||||
|
if (!outOption) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "Invalid system option address {}", (void*)outOption);
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_OPTION_ADDRESS;
|
||||||
|
}
|
||||||
|
*outOption = option;
|
||||||
|
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemSetGrainSamples(OrbisNgs2Handle systemHandle, u32 numSamples) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "numSamples = {}", numSamples);
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemSetSampleRate(OrbisNgs2Handle systemHandle, u32 sampleRate) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "sampleRate = {}", sampleRate);
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemSetUserData(OrbisNgs2Handle systemHandle, uintptr_t userData) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "userData = {}", userData);
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2SystemUnlock(OrbisNgs2Handle systemHandle) {
|
||||||
|
if (!systemHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "systemHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2VoiceControl(OrbisNgs2Handle voiceHandle,
|
||||||
|
const OrbisNgs2VoiceParamHeader* paramList) {
|
||||||
|
if (!voiceHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2VoiceGetMatrixInfo(OrbisNgs2Handle voiceHandle, u32 matrixId,
|
||||||
|
OrbisNgs2VoiceMatrixInfo* outInfo, size_t outInfoSize) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "matrixId = {}, outInfoSize = {}", matrixId, outInfoSize);
|
||||||
|
if (!voiceHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2VoiceGetOwner(OrbisNgs2Handle voiceHandle, OrbisNgs2Handle* outRackHandle,
|
||||||
|
u32* outVoiceId) {
|
||||||
|
if (!voiceHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2VoiceGetPortInfo(OrbisNgs2Handle voiceHandle, u32 port,
|
||||||
|
OrbisNgs2VoicePortInfo* outInfo, size_t outInfoSize) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "port = {}, outInfoSize = {}", port, outInfoSize);
|
||||||
|
if (!voiceHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2VoiceGetState(OrbisNgs2Handle voiceHandle, OrbisNgs2VoiceState* outState,
|
||||||
|
size_t stateSize) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "stateSize = {}", stateSize);
|
||||||
|
if (!voiceHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2VoiceGetStateFlags(OrbisNgs2Handle voiceHandle, u32* outStateFlags) {
|
||||||
|
if (!voiceHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "voiceHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ngs2Custom
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2CustomRackGetModuleInfo(OrbisNgs2Handle rackHandle, u32 moduleIndex,
|
||||||
|
OrbisNgs2CustomModuleInfo* outInfo,
|
||||||
|
size_t infoSize) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "moduleIndex = {}, infoSize = {}", moduleIndex, infoSize);
|
||||||
|
if (!rackHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "rackHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ngs2Geom
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2GeomResetListenerParam(OrbisNgs2GeomListenerParam* outListenerParam) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2GeomResetSourceParam(OrbisNgs2GeomSourceParam* outSourceParam) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2GeomCalcListener(const OrbisNgs2GeomListenerParam* param,
|
||||||
|
OrbisNgs2GeomListenerWork* outWork, u32 flags) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "flags = {}", flags);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2GeomApply(const OrbisNgs2GeomListenerWork* listener,
|
||||||
|
const OrbisNgs2GeomSourceParam* source,
|
||||||
|
OrbisNgs2GeomAttribute* outAttrib, u32 flags) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "flags = {}", flags);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ngs2Pan
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2PanInit(OrbisNgs2PanWork* work, const float* aSpeakerAngle, float unitAngle,
|
||||||
|
u32 numSpeakers) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "aSpeakerAngle = {}, unitAngle = {}, numSpeakers = {}", *aSpeakerAngle,
|
||||||
|
unitAngle, numSpeakers);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2PanGetVolumeMatrix(OrbisNgs2PanWork* work, const OrbisNgs2PanParam* aParam,
|
||||||
|
u32 numParams, u32 matrixFormat,
|
||||||
|
float* outVolumeMatrix) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "numParams = {}, matrixFormat = {}", numParams, matrixFormat);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ngs2Report
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2ReportRegisterHandler(u32 reportType, OrbisNgs2ReportHandler handler,
|
||||||
|
uintptr_t userData, OrbisNgs2Handle* outHandle) {
|
||||||
|
LOG_INFO(Lib_Ngs2, "reportType = {}, userData = {}", reportType, userData);
|
||||||
|
if (!handler) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "handler is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLE;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2ReportUnregisterHandler(OrbisNgs2Handle reportHandle) {
|
||||||
|
if (!reportHandle) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "reportHandle is nullptr");
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLE;
|
||||||
|
}
|
||||||
|
LOG_INFO(Lib_Ngs2, "called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unknown
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2FftInit() {
|
int PS4_SYSV_ABI sceNgs2FftInit() {
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
@ -35,31 +494,6 @@ int PS4_SYSV_ABI sceNgs2FftQuerySize() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2GeomApply() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2GeomCalcListener() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2GeomResetListenerParam() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2GeomResetSourceParam() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2GetWaveformFrameInfo() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2JobSchedulerResetOption() {
|
int PS4_SYSV_ABI sceNgs2JobSchedulerResetOption() {
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
@ -80,71 +514,6 @@ int PS4_SYSV_ABI sceNgs2ModuleQueueEnumItems() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2PanGetVolumeMatrix() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2PanInit() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2ParseWaveformData() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2ParseWaveformFile() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2ParseWaveformUser() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackCreate() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackCreateWithAllocator() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackDestroy() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackGetInfo() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackGetUserData() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackGetVoiceHandle() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackLock() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackQueryBufferSize() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackQueryInfo() {
|
int PS4_SYSV_ABI sceNgs2RackQueryInfo() {
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
@ -155,116 +524,21 @@ int PS4_SYSV_ABI sceNgs2RackRunCommands() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackSetUserData() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2RackUnlock() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2ReportRegisterHandler() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2ReportUnregisterHandler() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemCreate() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemCreateWithAllocator() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemDestroy() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemEnumHandles() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemEnumRackHandles() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemGetInfo() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemGetUserData() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemLock() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemQueryBufferSize() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemQueryInfo() {
|
int PS4_SYSV_ABI sceNgs2SystemQueryInfo() {
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemRender() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemResetOption() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemRunCommands() {
|
int PS4_SYSV_ABI sceNgs2SystemRunCommands() {
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemSetGrainSamples() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemSetLoudThreshold() {
|
int PS4_SYSV_ABI sceNgs2SystemSetLoudThreshold() {
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemSetSampleRate() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemSetUserData() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2SystemUnlock() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2StreamCreate() {
|
int PS4_SYSV_ABI sceNgs2StreamCreate() {
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
@ -300,36 +574,6 @@ int PS4_SYSV_ABI sceNgs2StreamRunCommands() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2VoiceControl() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2VoiceGetMatrixInfo() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2VoiceGetOwner() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2VoiceGetPortInfo() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2VoiceGetState() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2VoiceGetStateFlags() {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNgs2VoiceQueryInfo() {
|
int PS4_SYSV_ABI sceNgs2VoiceQueryInfo() {
|
||||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
|
@ -3,7 +3,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "core/libraries/ngs2/ngs2_impl.h"
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
namespace Core::Loader {
|
namespace Core::Loader {
|
||||||
@ -12,60 +16,253 @@ class SymbolsResolver;
|
|||||||
|
|
||||||
namespace Libraries::Ngs2 {
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
class Ngs2;
|
typedef s32 (*OrbisNgs2ParseReadHandler)(uintptr_t userData, u32 offset, void* data, size_t size);
|
||||||
|
|
||||||
using SceNgs2Handle = Ngs2*;
|
enum class OrbisNgs2HandleType : u32 {
|
||||||
|
Invalid = 0,
|
||||||
enum class SceNgs2HandleType : u32 {
|
System = 1,
|
||||||
System = 0,
|
Rack = 2,
|
||||||
|
Voice = 3,
|
||||||
|
VoiceControl = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ngs2Handle {
|
static const int ORBIS_NGS2_MAX_VOICE_CHANNELS = 8;
|
||||||
void* selfPointer;
|
static const int ORBIS_NGS2_WAVEFORM_INFO_MAX_BLOCKS = 4;
|
||||||
void* dataPointer;
|
static const int ORBIS_NGS2_MAX_MATRIX_LEVELS =
|
||||||
std::atomic<u32>* atomicPtr;
|
(ORBIS_NGS2_MAX_VOICE_CHANNELS * ORBIS_NGS2_MAX_VOICE_CHANNELS);
|
||||||
u32 handleType;
|
|
||||||
u32 flags_unk;
|
|
||||||
|
|
||||||
u32 uid;
|
struct OrbisNgs2WaveformFormat {
|
||||||
u16 maxGrainSamples;
|
u32 waveformType;
|
||||||
u16 minGrainSamples;
|
u32 numChannels;
|
||||||
u16 currentGrainSamples;
|
|
||||||
u16 numGrainSamples;
|
|
||||||
u16 unknown2;
|
|
||||||
u32 sampleRate;
|
u32 sampleRate;
|
||||||
u32 unknown3;
|
u32 configData;
|
||||||
|
u32 frameOffset;
|
||||||
void* flushMutex;
|
u32 frameMargin;
|
||||||
u32 flushMutexInitialized;
|
|
||||||
void* processMutex;
|
|
||||||
u32 processMutexInitialized;
|
|
||||||
|
|
||||||
// Linked list pointers for system list
|
|
||||||
Ngs2Handle* prev;
|
|
||||||
Ngs2Handle* next;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SystemOptions {
|
struct OrbisNgs2WaveformBlock {
|
||||||
char padding[6];
|
u32 dataOffset;
|
||||||
s32 maxGrainSamples;
|
u32 dataSize;
|
||||||
s32 numGrainSamples;
|
u32 numRepeats;
|
||||||
s32 sampleRate;
|
u32 numSkipSamples;
|
||||||
|
u32 numSamples;
|
||||||
|
u32 reserved;
|
||||||
|
uintptr_t userData;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SystemState {
|
struct OrbisNgs2WaveformInfo {
|
||||||
// TODO
|
OrbisNgs2WaveformFormat format;
|
||||||
|
|
||||||
|
u32 dataOffset;
|
||||||
|
u32 dataSize;
|
||||||
|
|
||||||
|
u32 loopBeginPosition;
|
||||||
|
u32 loopEndPosition;
|
||||||
|
u32 numSamples;
|
||||||
|
|
||||||
|
u32 audioUnitSize;
|
||||||
|
u32 numAudioUnitSamples;
|
||||||
|
u32 numAudioUnitPerFrame;
|
||||||
|
|
||||||
|
u32 audioFrameSize;
|
||||||
|
u32 numAudioFrameSamples;
|
||||||
|
|
||||||
|
u32 numDelaySamples;
|
||||||
|
|
||||||
|
u32 numBlocks;
|
||||||
|
OrbisNgs2WaveformBlock aBlock[ORBIS_NGS2_WAVEFORM_INFO_MAX_BLOCKS];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StackBuffer {
|
struct OrbisNgs2EnvelopePoint {
|
||||||
void** top;
|
u32 curve;
|
||||||
void* base;
|
u32 duration;
|
||||||
void* curr;
|
float height;
|
||||||
size_t usedSize;
|
};
|
||||||
size_t totalSize;
|
|
||||||
size_t alignment;
|
struct OrbisNgs2UserFxProcessContext {
|
||||||
char isVerifyEnabled;
|
float** aChannelData;
|
||||||
char padding[7];
|
uintptr_t userData0;
|
||||||
|
uintptr_t userData1;
|
||||||
|
uintptr_t userData2;
|
||||||
|
u32 flags;
|
||||||
|
u32 numChannels;
|
||||||
|
u32 numGrainSamples;
|
||||||
|
u32 sampleRate;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef s32 (*OrbisNgs2UserFxProcessHandler)(OrbisNgs2UserFxProcessContext* context);
|
||||||
|
|
||||||
|
struct OrbisNgs2UserFx2SetupContext {
|
||||||
|
void* common;
|
||||||
|
void* param;
|
||||||
|
void* work;
|
||||||
|
uintptr_t userData;
|
||||||
|
u32 maxVoices;
|
||||||
|
u32 voiceIndex;
|
||||||
|
u64 reserved[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef s32 (*OrbisNgs2UserFx2SetupHandler)(OrbisNgs2UserFx2SetupContext* context);
|
||||||
|
|
||||||
|
struct OrbisNgs2UserFx2CleanupContext {
|
||||||
|
void* common;
|
||||||
|
void* param;
|
||||||
|
void* work;
|
||||||
|
uintptr_t userData;
|
||||||
|
u32 maxVoices;
|
||||||
|
u32 voiceIndex;
|
||||||
|
u64 reserved[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef s32 (*OrbisNgs2UserFx2CleanupHandler)(OrbisNgs2UserFx2CleanupContext* context);
|
||||||
|
|
||||||
|
struct OrbisNgs2UserFx2ControlContext {
|
||||||
|
const void* data;
|
||||||
|
size_t dataSize;
|
||||||
|
void* common;
|
||||||
|
void* param;
|
||||||
|
uintptr_t userData;
|
||||||
|
u64 reserved[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef s32 (*OrbisNgs2UserFx2ControlHandler)(OrbisNgs2UserFx2ControlContext* context);
|
||||||
|
|
||||||
|
struct OrbisNgs2UserFx2ProcessContext {
|
||||||
|
float** aChannelData;
|
||||||
|
void* common;
|
||||||
|
const void* param;
|
||||||
|
void* work;
|
||||||
|
void* state;
|
||||||
|
uintptr_t userData;
|
||||||
|
u32 flags;
|
||||||
|
u32 numInputChannels;
|
||||||
|
u32 numOutputChannels;
|
||||||
|
u32 numGrainSamples;
|
||||||
|
u32 sampleRate;
|
||||||
|
u32 reserved;
|
||||||
|
u64 reserved2[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef s32 (*OrbisNgs2UserFx2ProcessHandler)(OrbisNgs2UserFx2ProcessContext* context);
|
||||||
|
|
||||||
|
struct OrbisNgs2BufferAllocator {
|
||||||
|
OrbisNgs2BufferAllocHandler allocHandler;
|
||||||
|
OrbisNgs2BufferFreeHandler freeHandler;
|
||||||
|
uintptr_t userData;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2RenderBufferInfo {
|
||||||
|
void* buffer;
|
||||||
|
size_t bufferSize;
|
||||||
|
u32 waveformType;
|
||||||
|
u32 numChannels;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2RackOption {
|
||||||
|
size_t size;
|
||||||
|
char name[ORBIS_NGS2_RACK_NAME_LENGTH];
|
||||||
|
|
||||||
|
u32 flags;
|
||||||
|
u32 maxGrainSamples;
|
||||||
|
u32 maxVoices;
|
||||||
|
u32 maxInputDelayBlocks;
|
||||||
|
u32 maxMatrices;
|
||||||
|
u32 maxPorts;
|
||||||
|
u32 aReserved[20];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoiceParamHeader {
|
||||||
|
u16 size;
|
||||||
|
s16 next;
|
||||||
|
u32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoiceMatrixLevelsParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 matrixId;
|
||||||
|
u32 numLevels;
|
||||||
|
const float* aLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoicePortMatrixParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 port;
|
||||||
|
s32 matrixId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoicePortVolumeParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 port;
|
||||||
|
float level;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoicePortDelayParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 port;
|
||||||
|
u32 numSamples;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoicePatchParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 port;
|
||||||
|
u32 destInputId;
|
||||||
|
OrbisNgs2Handle destHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoiceEventParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 eventId;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoiceCallbackInfo {
|
||||||
|
uintptr_t callbackData;
|
||||||
|
OrbisNgs2Handle voiceHandle;
|
||||||
|
u32 flag;
|
||||||
|
u32 reserved;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
uintptr_t userData;
|
||||||
|
const void* data;
|
||||||
|
u32 dataSize;
|
||||||
|
u32 repeatedCount;
|
||||||
|
u32 attributeFlags;
|
||||||
|
u32 reserved2;
|
||||||
|
} waveformBlock;
|
||||||
|
} param;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*OrbisNgs2VoiceCallbackHandler)(const OrbisNgs2VoiceCallbackInfo* info);
|
||||||
|
|
||||||
|
struct OrbisNgs2VoiceCallbackParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
OrbisNgs2VoiceCallbackHandler callbackHandler;
|
||||||
|
|
||||||
|
uintptr_t callbackData;
|
||||||
|
u32 flags;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoicePortInfo {
|
||||||
|
s32 matrixId;
|
||||||
|
float volume;
|
||||||
|
u32 numDelaySamples;
|
||||||
|
u32 destInputId;
|
||||||
|
OrbisNgs2Handle destHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoiceMatrixInfo {
|
||||||
|
u32 numLevels;
|
||||||
|
float aLevel[ORBIS_NGS2_MAX_MATRIX_LEVELS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2VoiceState {
|
||||||
|
u32 stateFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
void RegisterlibSceNgs2(Core::Loader::SymbolsResolver* sym);
|
void RegisterlibSceNgs2(Core::Loader::SymbolsResolver* sym);
|
||||||
|
12
src/core/libraries/ngs2/ngs2_custom.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ngs2_error.h"
|
||||||
|
#include "ngs2_impl.h"
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
|
||||||
|
using namespace Libraries::Kernel;
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
|
444
src/core/libraries/ngs2/ngs2_custom.h
Normal file
@ -0,0 +1,444 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ngs2.h"
|
||||||
|
#include "ngs2_reverb.h"
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
|
class Ngs2Custom;
|
||||||
|
|
||||||
|
static const int ORBIS_NGS2_CUSTOM_MAX_MODULES = 24;
|
||||||
|
static const int ORBIS_NGS2_CUSTOM_MAX_PORTS = 16;
|
||||||
|
static const int ORBIS_NGS2_CUSTOM_DELAY_MAX_TAPS = 8;
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomModuleOption {
|
||||||
|
u32 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomEnvelopeModuleOption {
|
||||||
|
OrbisNgs2CustomModuleOption customModuleOption;
|
||||||
|
|
||||||
|
u32 maxPoints;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomReverbModuleOption {
|
||||||
|
OrbisNgs2CustomModuleOption customModuleOption;
|
||||||
|
|
||||||
|
u32 reverbSize;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomChorusModuleOption {
|
||||||
|
OrbisNgs2CustomModuleOption customModuleOption;
|
||||||
|
|
||||||
|
u32 maxPhases;
|
||||||
|
u32 reserved;
|
||||||
|
} OrbisNgs2CustomChorusModuleOption;
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomPeakMeterModuleOption {
|
||||||
|
OrbisNgs2CustomModuleOption customModuleOption;
|
||||||
|
u32 numBlocks;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomDelayModuleOption {
|
||||||
|
OrbisNgs2CustomModuleOption customModuleOption;
|
||||||
|
|
||||||
|
u32 type;
|
||||||
|
u32 maxTaps;
|
||||||
|
float maxLength;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomPitchShiftModuleOption {
|
||||||
|
OrbisNgs2CustomModuleOption customModuleOption;
|
||||||
|
|
||||||
|
u32 quality;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomUserFx2ModuleOption {
|
||||||
|
OrbisNgs2CustomModuleOption customModuleOption;
|
||||||
|
|
||||||
|
OrbisNgs2UserFx2SetupHandler setupHandler;
|
||||||
|
OrbisNgs2UserFx2CleanupHandler cleanupHandler;
|
||||||
|
OrbisNgs2UserFx2ControlHandler controlHandler;
|
||||||
|
OrbisNgs2UserFx2ProcessHandler processHandler;
|
||||||
|
|
||||||
|
size_t commonSize;
|
||||||
|
size_t paramSize;
|
||||||
|
size_t workSize;
|
||||||
|
uintptr_t userData;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomRackModuleInfo {
|
||||||
|
const OrbisNgs2CustomModuleOption* option;
|
||||||
|
|
||||||
|
u32 moduleId;
|
||||||
|
u32 sourceBufferId;
|
||||||
|
u32 extraBufferId;
|
||||||
|
u32 destBufferId;
|
||||||
|
u32 stateOffset;
|
||||||
|
u32 stateSize;
|
||||||
|
u32 reserved;
|
||||||
|
u32 reserved2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomRackPortInfo {
|
||||||
|
u32 sourceBufferId;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomRackOption {
|
||||||
|
OrbisNgs2RackOption rackOption;
|
||||||
|
u32 stateSize;
|
||||||
|
u32 numBuffers;
|
||||||
|
u32 numModules;
|
||||||
|
u32 reserved;
|
||||||
|
OrbisNgs2CustomRackModuleInfo aModule[ORBIS_NGS2_CUSTOM_MAX_MODULES];
|
||||||
|
OrbisNgs2CustomRackPortInfo aPort[ORBIS_NGS2_CUSTOM_MAX_PORTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSamplerRackOption {
|
||||||
|
OrbisNgs2CustomRackOption customRackOption;
|
||||||
|
|
||||||
|
u32 maxChannelWorks;
|
||||||
|
u32 maxWaveformBlocks;
|
||||||
|
u32 maxAtrac9Decoders;
|
||||||
|
u32 maxAtrac9ChannelWorks;
|
||||||
|
u32 maxAjmAtrac9Decoders;
|
||||||
|
u32 maxCodecCaches;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSubmixerRackOption {
|
||||||
|
OrbisNgs2CustomRackOption customRackOption;
|
||||||
|
|
||||||
|
u32 maxChannels;
|
||||||
|
u32 maxInputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomMasteringRackOption {
|
||||||
|
OrbisNgs2CustomRackOption customRackOption;
|
||||||
|
|
||||||
|
u32 maxChannels;
|
||||||
|
u32 maxInputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSamplerVoiceSetupParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
OrbisNgs2WaveformFormat format;
|
||||||
|
u32 flags;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSamplerVoiceWaveformBlocksParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
const void* data;
|
||||||
|
u32 flags;
|
||||||
|
u32 numBlocks;
|
||||||
|
const OrbisNgs2WaveformBlock* aBlock;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSamplerVoiceWaveformAddressParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
const void* from;
|
||||||
|
const void* to;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSamplerVoiceWaveformFrameOffsetParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 frameOffset;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSamplerVoiceExitLoopParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSamplerVoicePitchParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
float ratio;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSamplerVoiceState {
|
||||||
|
OrbisNgs2VoiceState voiceState;
|
||||||
|
char padding[32];
|
||||||
|
const void* waveformData;
|
||||||
|
u64 numDecodedSamples;
|
||||||
|
u64 decodedDataSize;
|
||||||
|
u64 userData;
|
||||||
|
u32 reserved;
|
||||||
|
u32 reserved2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSubmixerVoiceSetupParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 numInputChannels;
|
||||||
|
u32 numOutputChannels;
|
||||||
|
u32 flags;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSubmixerVoiceState {
|
||||||
|
OrbisNgs2VoiceState voiceState; // Voice state
|
||||||
|
u32 reserved;
|
||||||
|
u32 reserved2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomMasteringVoiceSetupParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 numInputChannels;
|
||||||
|
u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomMasteringVoiceOutputParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 outputId;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomMasteringVoiceState {
|
||||||
|
OrbisNgs2VoiceState voiceState;
|
||||||
|
u32 reserved;
|
||||||
|
u32 reserved2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceEnvelopeParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 numForwardPoints;
|
||||||
|
u32 numReleasePoints;
|
||||||
|
const OrbisNgs2EnvelopePoint* aPoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceDistortionParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 flags;
|
||||||
|
float a;
|
||||||
|
float b;
|
||||||
|
float clip;
|
||||||
|
float gate;
|
||||||
|
float wetLevel;
|
||||||
|
float dryLevel;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceCompressorParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 flags;
|
||||||
|
float threshold;
|
||||||
|
float ratio;
|
||||||
|
float knee;
|
||||||
|
float attackTime;
|
||||||
|
float releaseTime;
|
||||||
|
float level;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceFilterParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 type;
|
||||||
|
u32 channelMask;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
float i0;
|
||||||
|
float i1;
|
||||||
|
float i2;
|
||||||
|
float o1;
|
||||||
|
float o2;
|
||||||
|
} direct;
|
||||||
|
struct {
|
||||||
|
float fc;
|
||||||
|
float q;
|
||||||
|
float level;
|
||||||
|
u32 reserved;
|
||||||
|
u32 reserved2;
|
||||||
|
} fcq;
|
||||||
|
} param;
|
||||||
|
u32 reserved3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceLfeFilterParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 enableFlag;
|
||||||
|
u32 fc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceGainParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
float aLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceMixerParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
float aSourceLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS];
|
||||||
|
float aDestLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceChannelMixerParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
float aLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS][ORBIS_NGS2_MAX_VOICE_CHANNELS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceUserFxParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
OrbisNgs2UserFxProcessHandler handler;
|
||||||
|
|
||||||
|
uintptr_t userData0;
|
||||||
|
uintptr_t userData1;
|
||||||
|
uintptr_t userData2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceUserFx2Param {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
const void* data;
|
||||||
|
size_t dataSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceOutputParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 outputId;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoicePeakMeterParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 enableFlag;
|
||||||
|
u32 reserved;
|
||||||
|
} OrbisNgs2CustomVoicePeakMeterParam;
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceReverbParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
OrbisNgs2ReverbI3DL2Param i3dl2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceChorusParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 flags;
|
||||||
|
u32 numPhases;
|
||||||
|
u32 channelMask;
|
||||||
|
float inputLevel;
|
||||||
|
float delayTime;
|
||||||
|
float modulationRatio;
|
||||||
|
float modulationDepth;
|
||||||
|
float feedbackLevel;
|
||||||
|
float wetLevel;
|
||||||
|
float dryLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2DelayTapInfo {
|
||||||
|
float tapLevel;
|
||||||
|
float delayTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceDelayParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
float dryLevel;
|
||||||
|
float wetLevel;
|
||||||
|
float inputLevel;
|
||||||
|
float feedbackLevel;
|
||||||
|
float lowpassFc;
|
||||||
|
u32 numTaps;
|
||||||
|
OrbisNgs2DelayTapInfo aTap[ORBIS_NGS2_CUSTOM_DELAY_MAX_TAPS];
|
||||||
|
float aInputMixLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS];
|
||||||
|
u32 channelMask;
|
||||||
|
u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoiceNoiseGateParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 flags;
|
||||||
|
float threshold;
|
||||||
|
float attackTime;
|
||||||
|
float releaseTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomVoicePitchShiftParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
s32 cent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomEnvelopeModuleState {
|
||||||
|
float height;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomCompressorModuleState {
|
||||||
|
float peakHeight;
|
||||||
|
float compressorHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomPeakMeterModuleState {
|
||||||
|
float peak;
|
||||||
|
float aChannelPeak[ORBIS_NGS2_MAX_VOICE_CHANNELS];
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomNoiseGateModuleState {
|
||||||
|
float gateHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomRackInfo {
|
||||||
|
OrbisNgs2RackInfo rackInfo;
|
||||||
|
u32 stateSize;
|
||||||
|
u32 numBuffers;
|
||||||
|
u32 numModules;
|
||||||
|
u32 reserved;
|
||||||
|
OrbisNgs2CustomRackModuleInfo aModule[ORBIS_NGS2_CUSTOM_MAX_MODULES];
|
||||||
|
OrbisNgs2CustomRackPortInfo aPort[ORBIS_NGS2_CUSTOM_MAX_PORTS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSamplerRackInfo {
|
||||||
|
OrbisNgs2CustomRackInfo customRackInfo;
|
||||||
|
|
||||||
|
u32 maxChannelWorks;
|
||||||
|
u32 maxWaveformBlocks;
|
||||||
|
u32 maxAtrac9Decoders;
|
||||||
|
u32 maxAtrac9ChannelWorks;
|
||||||
|
u32 maxAjmAtrac9Decoders;
|
||||||
|
u32 maxCodecCaches;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomSubmixerRackInfo {
|
||||||
|
OrbisNgs2CustomRackInfo customRackInfo;
|
||||||
|
|
||||||
|
u32 maxChannels;
|
||||||
|
u32 maxInputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomMasteringRackInfo {
|
||||||
|
OrbisNgs2CustomRackInfo customRackInfo;
|
||||||
|
|
||||||
|
u32 maxChannels;
|
||||||
|
u32 maxInputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomModuleInfo {
|
||||||
|
u32 moduleId;
|
||||||
|
u32 sourceBufferId;
|
||||||
|
u32 extraBufferId;
|
||||||
|
u32 destBufferId;
|
||||||
|
u32 stateOffset;
|
||||||
|
u32 stateSize;
|
||||||
|
u32 reserved;
|
||||||
|
u32 reserved2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomEnvelopeModuleInfo {
|
||||||
|
OrbisNgs2CustomModuleInfo moduleInfo;
|
||||||
|
|
||||||
|
u32 maxPoints;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2CustomReverbModuleInfo {
|
||||||
|
OrbisNgs2CustomModuleInfo moduleInfo;
|
||||||
|
|
||||||
|
u32 reverbSize;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Ngs2
|
12
src/core/libraries/ngs2/ngs2_eq.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ngs2_error.h"
|
||||||
|
#include "ngs2_impl.h"
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
|
||||||
|
using namespace Libraries::Kernel;
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
|
41
src/core/libraries/ngs2/ngs2_eq.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ngs2.h"
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
|
class Ngs2Eq;
|
||||||
|
|
||||||
|
struct OrbisNgs2EqVoiceSetupParam {
|
||||||
|
u32 numChannels;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2EqVoiceFilterParam {
|
||||||
|
u32 type;
|
||||||
|
u32 channelMask;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
float i0;
|
||||||
|
float i1;
|
||||||
|
float i2;
|
||||||
|
float o1;
|
||||||
|
float o2;
|
||||||
|
} direct;
|
||||||
|
struct {
|
||||||
|
float fc;
|
||||||
|
float q;
|
||||||
|
float level;
|
||||||
|
u32 reserved;
|
||||||
|
u32 reserved2;
|
||||||
|
} fcq;
|
||||||
|
} param;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2EqVoiceState {
|
||||||
|
u32 stateFlags;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Ngs2
|
12
src/core/libraries/ngs2/ngs2_geom.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ngs2_error.h"
|
||||||
|
#include "ngs2_impl.h"
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
|
||||||
|
using namespace Libraries::Kernel;
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
|
80
src/core/libraries/ngs2/ngs2_geom.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ngs2.h"
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
|
class Ngs2Geom;
|
||||||
|
|
||||||
|
struct OrbisNgs2GeomVector {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2GeomCone {
|
||||||
|
float innerLevel;
|
||||||
|
float innerAngle;
|
||||||
|
float outerLevel;
|
||||||
|
float outerAngle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2GeomRolloff {
|
||||||
|
u32 model;
|
||||||
|
float maxDistance;
|
||||||
|
float rolloffFactor;
|
||||||
|
float referenceDistance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2GeomListenerParam {
|
||||||
|
OrbisNgs2GeomVector position;
|
||||||
|
OrbisNgs2GeomVector orientFront;
|
||||||
|
OrbisNgs2GeomVector orientUp;
|
||||||
|
OrbisNgs2GeomVector velocity;
|
||||||
|
float soundSpeed;
|
||||||
|
u32 reserved[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2GeomListenerWork {
|
||||||
|
float matrix[4][4];
|
||||||
|
OrbisNgs2GeomVector velocity;
|
||||||
|
float soundSpeed;
|
||||||
|
u32 coordinate;
|
||||||
|
u32 reserved[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2GeomSourceParam {
|
||||||
|
OrbisNgs2GeomVector position;
|
||||||
|
OrbisNgs2GeomVector velocity;
|
||||||
|
OrbisNgs2GeomVector direction;
|
||||||
|
OrbisNgs2GeomCone cone;
|
||||||
|
OrbisNgs2GeomRolloff rolloff;
|
||||||
|
float dopplerFactor;
|
||||||
|
float fbwLevel;
|
||||||
|
float lfeLevel;
|
||||||
|
float maxLevel;
|
||||||
|
float minLevel;
|
||||||
|
float radius;
|
||||||
|
u32 numSpeakers;
|
||||||
|
u32 matrixFormat;
|
||||||
|
u32 reserved[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2GeomA3dAttribute {
|
||||||
|
OrbisNgs2GeomVector position;
|
||||||
|
float volume;
|
||||||
|
u32 reserved[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2GeomAttribute {
|
||||||
|
float pitchRatio;
|
||||||
|
float aLevel[ORBIS_NGS2_MAX_VOICE_CHANNELS * ORBIS_NGS2_MAX_VOICE_CHANNELS];
|
||||||
|
|
||||||
|
OrbisNgs2GeomA3dAttribute a3dAttrib;
|
||||||
|
u32 reserved[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Ngs2
|
@ -12,153 +12,171 @@ using namespace Libraries::Kernel;
|
|||||||
|
|
||||||
namespace Libraries::Ngs2 {
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
s32 Ngs2::ReportInvalid(Ngs2Handle* handle, u32 handle_type) const {
|
s32 HandleReportInvalid(OrbisNgs2Handle handle, u32 handleType) {
|
||||||
uintptr_t hAddress = reinterpret_cast<uintptr_t>(handle);
|
switch (handleType) {
|
||||||
switch (handle_type) {
|
|
||||||
case 1:
|
case 1:
|
||||||
LOG_ERROR(Lib_Ngs2, "Invalid system handle {}", hAddress);
|
LOG_ERROR(Lib_Ngs2, "Invalid system handle {}", handle);
|
||||||
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
return ORBIS_NGS2_ERROR_INVALID_SYSTEM_HANDLE;
|
||||||
case 2:
|
case 2:
|
||||||
LOG_ERROR(Lib_Ngs2, "Invalid rack handle {}", hAddress);
|
LOG_ERROR(Lib_Ngs2, "Invalid rack handle {}", handle);
|
||||||
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
return ORBIS_NGS2_ERROR_INVALID_RACK_HANDLE;
|
||||||
case 4:
|
case 4:
|
||||||
LOG_ERROR(Lib_Ngs2, "Invalid voice handle {}", hAddress);
|
LOG_ERROR(Lib_Ngs2, "Invalid voice handle {}", handle);
|
||||||
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
return ORBIS_NGS2_ERROR_INVALID_VOICE_HANDLE;
|
||||||
case 8:
|
case 8:
|
||||||
LOG_ERROR(Lib_Ngs2, "Invalid report handle {}", hAddress);
|
LOG_ERROR(Lib_Ngs2, "Invalid report handle {}", handle);
|
||||||
return ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLE;
|
return ORBIS_NGS2_ERROR_INVALID_REPORT_HANDLE;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Lib_Ngs2, "Invalid handle {}", hAddress);
|
LOG_ERROR(Lib_Ngs2, "Invalid handle {}", handle);
|
||||||
return ORBIS_NGS2_ERROR_INVALID_HANDLE;
|
return ORBIS_NGS2_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 Ngs2::HandleSetup(Ngs2Handle* handle, void* data, std::atomic<u32>* atomic, u32 type,
|
void* MemoryClear(void* buffer, size_t size) {
|
||||||
u32 flags) {
|
return memset(buffer, 0, size);
|
||||||
handle->dataPointer = data;
|
|
||||||
handle->atomicPtr = atomic;
|
|
||||||
handle->handleType = type;
|
|
||||||
handle->flags_unk = flags;
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 Ngs2::HandleCleanup(Ngs2Handle* handle, u32 hType, void* dataOut) {
|
s32 StackBufferClose(StackBuffer* stackBuffer, size_t* outTotalSize) {
|
||||||
if (handle && handle->selfPointer == handle) {
|
if (outTotalSize) {
|
||||||
std::atomic<u32>* tmp_atomic = handle->atomicPtr;
|
*outTotalSize = stackBuffer->usedSize + stackBuffer->alignment;
|
||||||
if (tmp_atomic && handle->handleType == hType) {
|
|
||||||
while (tmp_atomic->load() != 0) {
|
|
||||||
u32 expected = 1;
|
|
||||||
if (tmp_atomic->compare_exchange_strong(expected, 0)) {
|
|
||||||
if (dataOut) {
|
|
||||||
dataOut = handle->dataPointer;
|
|
||||||
}
|
|
||||||
// sceNgs2MemoryClear(handle, 32);
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
|
||||||
tmp_atomic = handle->atomicPtr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this->ReportInvalid(handle, hType);
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 Ngs2::HandleEnter(Ngs2Handle* handle, u32 hType, Ngs2Handle* handleOut) {
|
|
||||||
if (!handle) {
|
|
||||||
return this->ReportInvalid(handle, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle->selfPointer != handle || !handle->atomicPtr || !handle->dataPointer ||
|
|
||||||
(~hType & handle->handleType)) {
|
|
||||||
return this->ReportInvalid(handle, handle->handleType);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::atomic<u32>* atomic = handle->atomicPtr;
|
|
||||||
while (true) {
|
|
||||||
u32 i = atomic->load();
|
|
||||||
if (i == 0) {
|
|
||||||
return this->ReportInvalid(handle, handle->handleType);
|
|
||||||
}
|
|
||||||
if (atomic->compare_exchange_strong(i, i + 1)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handleOut) {
|
|
||||||
handleOut = handle;
|
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 Ngs2::HandleLeave(Ngs2Handle* handle) {
|
s32 StackBufferOpen(StackBuffer* stackBuffer, void* bufferStart, size_t bufferSize,
|
||||||
std::atomic<u32>* tmp_atomic;
|
void** outBuffer, u8 flags) {
|
||||||
u32 i;
|
stackBuffer->top = outBuffer;
|
||||||
do {
|
stackBuffer->base = bufferStart;
|
||||||
tmp_atomic = handle->atomicPtr;
|
stackBuffer->size = (size_t)bufferStart;
|
||||||
i = tmp_atomic->load();
|
stackBuffer->currentOffset = (size_t)bufferStart;
|
||||||
} while (!tmp_atomic->compare_exchange_strong(i, i - 1));
|
stackBuffer->usedSize = 0;
|
||||||
return ORBIS_OK;
|
stackBuffer->totalSize = bufferSize;
|
||||||
}
|
stackBuffer->alignment = 8; // this is a fixed value
|
||||||
|
stackBuffer->flags = flags;
|
||||||
|
|
||||||
s32 Ngs2::StackBufferOpen(StackBuffer* buf, void* base_addr, size_t size, void** stackTop,
|
if (outBuffer != NULL) {
|
||||||
bool verify) {
|
*outBuffer = NULL;
|
||||||
buf->top = stackTop;
|
|
||||||
buf->base = base_addr;
|
|
||||||
buf->curr = base_addr;
|
|
||||||
buf->usedSize = 0;
|
|
||||||
buf->totalSize = size;
|
|
||||||
buf->alignment = 8;
|
|
||||||
buf->isVerifyEnabled = verify;
|
|
||||||
|
|
||||||
if (stackTop) {
|
|
||||||
*stackTop = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 Ngs2::StackBufferClose(StackBuffer* buf, size_t* usedSize) {
|
s32 SystemCleanup(OrbisNgs2Handle systemHandle, OrbisNgs2ContextBufferInfo* outInfo) {
|
||||||
if (usedSize) {
|
if (!systemHandle) {
|
||||||
*usedSize = buf->usedSize + buf->alignment;
|
return ORBIS_NGS2_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 Ngs2::SystemSetupCore(StackBuffer* buf, SystemOptions* options, Ngs2Handle** sysOut) {
|
s32 SystemSetupCore(StackBuffer* stackBuffer, const OrbisNgs2SystemOption* option,
|
||||||
|
SystemInternal* outSystem) {
|
||||||
u32 maxGrainSamples = 512;
|
u32 maxGrainSamples = 512;
|
||||||
u32 numGrainSamples = 256;
|
u32 numGrainSamples = 256;
|
||||||
u32 sampleRate = 48000;
|
u32 sampleRate = 48000;
|
||||||
|
|
||||||
if (options) {
|
if (option) {
|
||||||
maxGrainSamples = options->maxGrainSamples;
|
sampleRate = option->sampleRate;
|
||||||
numGrainSamples = options->numGrainSamples;
|
maxGrainSamples = option->maxGrainSamples;
|
||||||
sampleRate = options->sampleRate;
|
numGrainSamples = option->numGrainSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate maxGrainSamples
|
if (maxGrainSamples < 64 || maxGrainSamples > 1024 || (maxGrainSamples & 63) != 0) {
|
||||||
if (maxGrainSamples < 64 || maxGrainSamples > 1024 || (maxGrainSamples & 0x3F) != 0) {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "Invalid system option (maxGrainSamples={},x64)", maxGrainSamples);
|
LOG_ERROR(Lib_Ngs2, "Invalid system option (maxGrainSamples={},x64)", maxGrainSamples);
|
||||||
return ORBIS_NGS2_ERROR_INVALID_MAX_GRAIN_SAMPLES;
|
return ORBIS_NGS2_ERROR_INVALID_MAX_GRAIN_SAMPLES;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate numGrainSamples
|
if (numGrainSamples < 64 || numGrainSamples > 1024 || (numGrainSamples & 63) != 0) {
|
||||||
if (numGrainSamples < 64 || numGrainSamples > 1024 || (numGrainSamples & 0x3F) != 0) {
|
|
||||||
LOG_ERROR(Lib_Ngs2, "Invalid system option (numGrainSamples={},x64)", numGrainSamples);
|
LOG_ERROR(Lib_Ngs2, "Invalid system option (numGrainSamples={},x64)", numGrainSamples);
|
||||||
return ORBIS_NGS2_ERROR_INVALID_NUM_GRAIN_SAMPLES;
|
return ORBIS_NGS2_ERROR_INVALID_NUM_GRAIN_SAMPLES;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate sampleRate
|
|
||||||
if (sampleRate != 11025 && sampleRate != 12000 && sampleRate != 22050 && sampleRate != 24000 &&
|
if (sampleRate != 11025 && sampleRate != 12000 && sampleRate != 22050 && sampleRate != 24000 &&
|
||||||
sampleRate != 44100 && sampleRate != 48000 && sampleRate != 88200 && sampleRate != 96000) {
|
sampleRate != 44100 && sampleRate != 48000 && sampleRate != 88200 && sampleRate != 96000 &&
|
||||||
|
sampleRate != 176400 && sampleRate != 192000) {
|
||||||
LOG_ERROR(Lib_Ngs2, "Invalid system option(sampleRate={}:44.1/48kHz series)", sampleRate);
|
LOG_ERROR(Lib_Ngs2, "Invalid system option(sampleRate={}:44.1/48kHz series)", sampleRate);
|
||||||
return ORBIS_NGS2_ERROR_INVALID_SAMPLE_RATE;
|
return ORBIS_NGS2_ERROR_INVALID_SAMPLE_RATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int result = ORBIS_OK;
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 SystemSetup(const OrbisNgs2SystemOption* option, OrbisNgs2ContextBufferInfo* hostBufferInfo,
|
||||||
|
OrbisNgs2BufferFreeHandler hostFree, OrbisNgs2Handle* outHandle) {
|
||||||
|
u8 optionFlags = 0;
|
||||||
|
StackBuffer stackBuffer;
|
||||||
|
SystemInternal setupResult;
|
||||||
|
void* systemList = NULL;
|
||||||
|
size_t requiredBufferSize = 0;
|
||||||
|
u32 result = ORBIS_NGS2_ERROR_INVALID_BUFFER_SIZE;
|
||||||
|
|
||||||
|
if (option) {
|
||||||
|
if (option->size != 64) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "Invalid system option size ({})", option->size);
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_OPTION_SIZE;
|
||||||
|
}
|
||||||
|
optionFlags = option->flags >> 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init
|
||||||
|
StackBufferOpen(&stackBuffer, NULL, 0, NULL, optionFlags);
|
||||||
|
result = SystemSetupCore(&stackBuffer, option, 0);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackBufferClose(&stackBuffer, &requiredBufferSize);
|
||||||
|
|
||||||
|
// outHandle unprovided
|
||||||
|
if (!outHandle) {
|
||||||
|
hostBufferInfo->hostBuffer = NULL;
|
||||||
|
hostBufferInfo->hostBufferSize = requiredBufferSize;
|
||||||
|
MemoryClear(&hostBufferInfo->reserved, sizeof(hostBufferInfo->reserved));
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hostBufferInfo->hostBuffer) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "Invalid system buffer address ({})", hostBufferInfo->hostBuffer);
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_BUFFER_ADDRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostBufferInfo->hostBufferSize < requiredBufferSize) {
|
||||||
|
LOG_ERROR(Lib_Ngs2, "Invalid system buffer size ({}<{}[byte])",
|
||||||
|
hostBufferInfo->hostBufferSize, requiredBufferSize);
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_BUFFER_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup
|
||||||
|
StackBufferOpen(&stackBuffer, hostBufferInfo->hostBuffer, hostBufferInfo->hostBufferSize,
|
||||||
|
&systemList, optionFlags);
|
||||||
|
result = SystemSetupCore(&stackBuffer, option, &setupResult);
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
StackBufferClose(&stackBuffer, &requiredBufferSize);
|
||||||
|
|
||||||
|
// Copy buffer results
|
||||||
|
setupResult.bufferInfo = *hostBufferInfo;
|
||||||
|
setupResult.hostFree = hostFree;
|
||||||
// TODO
|
// TODO
|
||||||
|
// setupResult.systemList = systemList;
|
||||||
|
|
||||||
return result; // Success
|
OrbisNgs2Handle systemHandle = setupResult.systemHandle;
|
||||||
|
if (hostBufferInfo->hostBufferSize >= requiredBufferSize) {
|
||||||
|
*outHandle = systemHandle;
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemCleanup(systemHandle, 0);
|
||||||
|
|
||||||
|
LOG_ERROR(Lib_Ngs2, "Invalid system buffer size ({}<{}[byte])", hostBufferInfo->hostBufferSize,
|
||||||
|
requiredBufferSize);
|
||||||
|
return ORBIS_NGS2_ERROR_INVALID_BUFFER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Ngs2
|
} // namespace Libraries::Ngs2
|
||||||
|
@ -3,23 +3,176 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ngs2.h"
|
#include "core/libraries/kernel/threads/pthread.h"
|
||||||
|
|
||||||
namespace Libraries::Ngs2 {
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
class Ngs2 {
|
static const int ORBIS_NGS2_SYSTEM_NAME_LENGTH = 16;
|
||||||
public:
|
static const int ORBIS_NGS2_RACK_NAME_LENGTH = 16;
|
||||||
s32 ReportInvalid(Ngs2Handle* handle, u32 handle_type) const;
|
|
||||||
s32 HandleSetup(Ngs2Handle* handle, void* data, std::atomic<u32>* atomic, u32 type, u32 flags);
|
|
||||||
s32 HandleCleanup(Ngs2Handle* handle, u32 hType, void* dataOut);
|
|
||||||
s32 HandleEnter(Ngs2Handle* handle, u32 hType, Ngs2Handle* handleOut);
|
|
||||||
s32 HandleLeave(Ngs2Handle* handle);
|
|
||||||
s32 StackBufferOpen(StackBuffer* buf, void* base_addr, size_t size, void** stackTop,
|
|
||||||
bool verify);
|
|
||||||
s32 StackBufferClose(StackBuffer* buf, size_t* usedSize);
|
|
||||||
s32 SystemSetupCore(StackBuffer* buf, SystemOptions* options, Ngs2Handle** sysOut);
|
|
||||||
|
|
||||||
private:
|
typedef uintptr_t OrbisNgs2Handle;
|
||||||
|
|
||||||
|
struct OrbisNgs2ContextBufferInfo {
|
||||||
|
void* hostBuffer;
|
||||||
|
size_t hostBufferSize;
|
||||||
|
uintptr_t reserved[5];
|
||||||
|
uintptr_t userData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SystemOption {
|
||||||
|
size_t size;
|
||||||
|
char name[ORBIS_NGS2_SYSTEM_NAME_LENGTH];
|
||||||
|
|
||||||
|
u32 flags;
|
||||||
|
u32 maxGrainSamples;
|
||||||
|
u32 numGrainSamples;
|
||||||
|
u32 sampleRate;
|
||||||
|
u32 aReserved[6];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef s32 (*OrbisNgs2BufferAllocHandler)(OrbisNgs2ContextBufferInfo* ioBufferInfo);
|
||||||
|
typedef s32 (*OrbisNgs2BufferFreeHandler)(OrbisNgs2ContextBufferInfo* ioBufferInfo);
|
||||||
|
|
||||||
|
struct OrbisNgs2SystemInfo {
|
||||||
|
char name[ORBIS_NGS2_SYSTEM_NAME_LENGTH]; // 0
|
||||||
|
|
||||||
|
OrbisNgs2Handle systemHandle; // 16
|
||||||
|
OrbisNgs2ContextBufferInfo bufferInfo; // 24
|
||||||
|
|
||||||
|
u32 uid; // 88
|
||||||
|
u32 minGrainSamples; // 92
|
||||||
|
u32 maxGrainSamples; // 96
|
||||||
|
|
||||||
|
u32 stateFlags; // 100
|
||||||
|
u32 rackCount; // 104
|
||||||
|
float lastRenderRatio; // 108
|
||||||
|
s64 lastRenderTick; // 112
|
||||||
|
s64 renderCount; // 120
|
||||||
|
u32 sampleRate; // 128
|
||||||
|
u32 numGrainSamples; // 132
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2RackInfo {
|
||||||
|
char name[ORBIS_NGS2_RACK_NAME_LENGTH]; // 0
|
||||||
|
|
||||||
|
OrbisNgs2Handle rackHandle; // 16
|
||||||
|
OrbisNgs2ContextBufferInfo bufferInfo; // 24
|
||||||
|
|
||||||
|
OrbisNgs2Handle ownerSystemHandle; // 88
|
||||||
|
|
||||||
|
u32 type; // 96
|
||||||
|
u32 rackId; // 100
|
||||||
|
u32 uid; // 104
|
||||||
|
u32 minGrainSamples; // 108
|
||||||
|
u32 maxGrainSamples; // 112
|
||||||
|
u32 maxVoices; // 116
|
||||||
|
u32 maxChannelWorks; // 120
|
||||||
|
u32 maxInputs; // 124
|
||||||
|
u32 maxMatrices; // 128
|
||||||
|
u32 maxPorts; // 132
|
||||||
|
|
||||||
|
u32 stateFlags; // 136
|
||||||
|
float lastProcessRatio; // 140
|
||||||
|
u64 lastProcessTick; // 144
|
||||||
|
u64 renderCount; // 152
|
||||||
|
u32 activeVoiceCount; // 160
|
||||||
|
u32 activeChannelWorkCount; // 164
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StackBuffer {
|
||||||
|
void** top;
|
||||||
|
void* base;
|
||||||
|
size_t size;
|
||||||
|
size_t currentOffset;
|
||||||
|
size_t usedSize;
|
||||||
|
size_t totalSize;
|
||||||
|
size_t alignment;
|
||||||
|
u8 flags;
|
||||||
|
char padding[7];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SystemInternal {
|
||||||
|
// setup init
|
||||||
|
char name[ORBIS_NGS2_SYSTEM_NAME_LENGTH]; // 0
|
||||||
|
OrbisNgs2ContextBufferInfo bufferInfo; // 16
|
||||||
|
OrbisNgs2BufferFreeHandler hostFree; // 80
|
||||||
|
OrbisNgs2Handle systemHandle; // 88
|
||||||
|
void* unknown1; // 96
|
||||||
|
void* unknown2; // 104
|
||||||
|
OrbisNgs2Handle rackHandle; // 112
|
||||||
|
uintptr_t* userData; // 120
|
||||||
|
SystemInternal* systemList; // 128
|
||||||
|
StackBuffer* stackBuffer; // 136
|
||||||
|
OrbisNgs2SystemInfo ownerSystemInfo; // 144
|
||||||
|
|
||||||
|
struct rackList {
|
||||||
|
void* prev;
|
||||||
|
void* next;
|
||||||
|
void* unknown;
|
||||||
|
};
|
||||||
|
|
||||||
|
rackList rackListPreset; // 152
|
||||||
|
rackList rackListNormal; // 176
|
||||||
|
rackList rackListMaster; // 200
|
||||||
|
|
||||||
|
void* unknown3; // 208
|
||||||
|
void* systemListPrev; // 216
|
||||||
|
void* unknown4; // 224
|
||||||
|
void* systemListNext; // 232
|
||||||
|
void* rackFunction; // 240
|
||||||
|
|
||||||
|
Kernel::PthreadMutex processLock; // 248
|
||||||
|
u32 hasProcessMutex; // 256
|
||||||
|
u32 unknown5; // 260
|
||||||
|
Kernel::PthreadMutex flushLock; // 264
|
||||||
|
u32 hasFlushMutex; // 272
|
||||||
|
u32 unknown6; // 276
|
||||||
|
|
||||||
|
// info
|
||||||
|
u64 lastRenderTick; // 280
|
||||||
|
u64 renderCount; // 288
|
||||||
|
u32 isActive; // 296
|
||||||
|
std::atomic<int> lockCount; // 300
|
||||||
|
u32 uid; // 304
|
||||||
|
u32 systemType; // 308
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u8 isBufferValid : 1;
|
||||||
|
u8 isRendering : 1;
|
||||||
|
u8 isSorted : 1;
|
||||||
|
u8 isFlushReady : 1;
|
||||||
|
} flags; // 312
|
||||||
|
|
||||||
|
u16 currentMaxGrainSamples; // 316
|
||||||
|
u16 minGrainSamples; // 318
|
||||||
|
u16 maxGrainSamples; // 320
|
||||||
|
u16 numGrainSamples; // 322
|
||||||
|
u32 currentNumGrainSamples; // 324
|
||||||
|
u32 sampleRate; // 328
|
||||||
|
u32 currentSampleRate; // 332
|
||||||
|
u32 rackCount; // 336
|
||||||
|
float lastRenderRatio; // 340
|
||||||
|
float cpuLoad; // 344
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HandleInternal {
|
||||||
|
HandleInternal* selfPtr; // 0
|
||||||
|
SystemInternal* systemData; // 8
|
||||||
|
std::atomic<int> refCount; // 16
|
||||||
|
u32 handleType; // 24
|
||||||
|
u32 handleID; // 28
|
||||||
|
};
|
||||||
|
|
||||||
|
s32 StackBufferClose(StackBuffer* stackBuffer, size_t* outTotalSize);
|
||||||
|
s32 StackBufferOpen(StackBuffer* stackBuffer, void* buffer, size_t bufferSize, void** outBuffer,
|
||||||
|
u8 flags);
|
||||||
|
s32 SystemSetupCore(StackBuffer* stackBuffer, const OrbisNgs2SystemOption* option,
|
||||||
|
SystemInternal* outSystem);
|
||||||
|
|
||||||
|
s32 HandleReportInvalid(OrbisNgs2Handle handle, u32 handleType);
|
||||||
|
void* MemoryClear(void* buffer, size_t size);
|
||||||
|
s32 SystemCleanup(OrbisNgs2Handle systemHandle, OrbisNgs2ContextBufferInfo* outInfo);
|
||||||
|
s32 SystemSetup(const OrbisNgs2SystemOption* option, OrbisNgs2ContextBufferInfo* hostBufferInfo,
|
||||||
|
OrbisNgs2BufferFreeHandler hostFree, OrbisNgs2Handle* outHandle);
|
||||||
|
|
||||||
} // namespace Libraries::Ngs2
|
} // namespace Libraries::Ngs2
|
||||||
|
12
src/core/libraries/ngs2/ngs2_mastering.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ngs2_error.h"
|
||||||
|
#include "ngs2_impl.h"
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
|
||||||
|
using namespace Libraries::Kernel;
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
|
81
src/core/libraries/ngs2/ngs2_mastering.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ngs2.h"
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
|
class Ngs2Mastering;
|
||||||
|
|
||||||
|
struct OrbisNgs2MasteringRackOption {
|
||||||
|
OrbisNgs2RackOption rackOption;
|
||||||
|
u32 maxChannels;
|
||||||
|
u32 numPeakMeterBlocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2MasteringVoiceSetupParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 numInputChannels;
|
||||||
|
u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2MasteringVoiceMatrixParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 type;
|
||||||
|
u32 numLevels;
|
||||||
|
const float* aLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2MasteringVoiceLfeParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 enableFlag;
|
||||||
|
u32 fc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2MasteringVoiceLimiterParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 enableFlag;
|
||||||
|
float threshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2MasteringVoiceGainParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
float fbwLevel;
|
||||||
|
float lfeLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2MasteringVoiceOutputParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 outputId;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2MasteringVoicePeakMeterParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 enableFlag;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2MasteringVoiceState {
|
||||||
|
OrbisNgs2VoiceState voiceState;
|
||||||
|
float limiterPeakLevel;
|
||||||
|
float limiterPressLevel;
|
||||||
|
float aInputPeakHeight[ORBIS_NGS2_MAX_VOICE_CHANNELS];
|
||||||
|
float aOutputPeakHeight[ORBIS_NGS2_MAX_VOICE_CHANNELS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2MasteringRackInfo {
|
||||||
|
OrbisNgs2RackInfo rackInfo;
|
||||||
|
u32 maxChannels;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Ngs2
|
12
src/core/libraries/ngs2/ngs2_pan.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ngs2_error.h"
|
||||||
|
#include "ngs2_impl.h"
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
|
||||||
|
using namespace Libraries::Kernel;
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
|
25
src/core/libraries/ngs2/ngs2_pan.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ngs2.h"
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
|
class Ngs2Pan;
|
||||||
|
|
||||||
|
struct OrbisNgs2PanParam {
|
||||||
|
float angle;
|
||||||
|
float distance;
|
||||||
|
float fbwLevel;
|
||||||
|
float lfeLevel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2PanWork {
|
||||||
|
float aSpeakerAngle[ORBIS_NGS2_MAX_VOICE_CHANNELS];
|
||||||
|
float unitAngle;
|
||||||
|
u32 numSpeakers;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Ngs2
|
12
src/core/libraries/ngs2/ngs2_report.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ngs2_error.h"
|
||||||
|
#include "ngs2_impl.h"
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
|
||||||
|
using namespace Libraries::Kernel;
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
|
78
src/core/libraries/ngs2/ngs2_report.h
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ngs2.h"
|
||||||
|
|
||||||
|
#include <stdarg.h> // va_list
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
|
class Ngs2Report;
|
||||||
|
|
||||||
|
struct OrbisNgs2ReportDataHeader {
|
||||||
|
size_t size;
|
||||||
|
OrbisNgs2Handle handle;
|
||||||
|
u32 type;
|
||||||
|
s32 result;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef void (*OrbisNgs2ReportHandler)(const OrbisNgs2ReportDataHeader* data, uintptr_t userData);
|
||||||
|
|
||||||
|
struct OrbisNgs2ReportMessageData {
|
||||||
|
OrbisNgs2ReportDataHeader header;
|
||||||
|
const char* message;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReportApiData {
|
||||||
|
OrbisNgs2ReportDataHeader header;
|
||||||
|
const char* functionName;
|
||||||
|
const char* format;
|
||||||
|
va_list argument;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReportControlData {
|
||||||
|
OrbisNgs2ReportDataHeader header;
|
||||||
|
const OrbisNgs2VoiceParamHeader* param;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReportOutputData {
|
||||||
|
OrbisNgs2ReportDataHeader header;
|
||||||
|
const OrbisNgs2RenderBufferInfo* bufferInfo;
|
||||||
|
|
||||||
|
u32 bufferIndex;
|
||||||
|
u32 sampleRate;
|
||||||
|
u32 numGrainSamples;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReportCpuLoadData {
|
||||||
|
OrbisNgs2ReportDataHeader header;
|
||||||
|
float totalRatio;
|
||||||
|
float flushRatio;
|
||||||
|
float processRatio;
|
||||||
|
float feedbackRatio;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReportRenderStateData {
|
||||||
|
OrbisNgs2ReportDataHeader header;
|
||||||
|
u32 state;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReportVoiceWaveformData {
|
||||||
|
OrbisNgs2ReportDataHeader header;
|
||||||
|
u32 location;
|
||||||
|
u32 waveformType;
|
||||||
|
u32 numChannels;
|
||||||
|
u32 sampleRate;
|
||||||
|
u32 numGrainSamples;
|
||||||
|
u32 reserved;
|
||||||
|
void* const* aData;
|
||||||
|
};
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceNgs2ReportRegisterHandler(u32 reportType, OrbisNgs2ReportHandler handler,
|
||||||
|
uintptr_t userData, OrbisNgs2Handle* outHandle);
|
||||||
|
|
||||||
|
} // namespace Libraries::Ngs2
|
12
src/core/libraries/ngs2/ngs2_reverb.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ngs2_error.h"
|
||||||
|
#include "ngs2_impl.h"
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
|
||||||
|
using namespace Libraries::Kernel;
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
|
61
src/core/libraries/ngs2/ngs2_reverb.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ngs2.h"
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
|
class Ngs2Reverb;
|
||||||
|
|
||||||
|
struct OrbisNgs2ReverbRackOption {
|
||||||
|
OrbisNgs2RackOption rackOption;
|
||||||
|
u32 maxChannels;
|
||||||
|
u32 reverbSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReverbI3DL2Param {
|
||||||
|
float wet;
|
||||||
|
float dry;
|
||||||
|
s32 room;
|
||||||
|
s32 roomHF;
|
||||||
|
u32 reflectionPattern;
|
||||||
|
float decayTime;
|
||||||
|
float decayHFRatio;
|
||||||
|
s32 reflections;
|
||||||
|
float reflectionsDelay;
|
||||||
|
s32 reverb;
|
||||||
|
float reverbDelay;
|
||||||
|
float diffusion;
|
||||||
|
float density;
|
||||||
|
float HFReference;
|
||||||
|
u32 reserve[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReverbVoiceSetupParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 numInputChannels;
|
||||||
|
u32 numOutputChannels;
|
||||||
|
u32 flags;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReverbVoiceI3DL2Param {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
OrbisNgs2ReverbI3DL2Param i3dl2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReverbVoiceState {
|
||||||
|
OrbisNgs2VoiceState voiceState;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2ReverbRackInfo {
|
||||||
|
OrbisNgs2RackInfo rackInfo;
|
||||||
|
u32 maxChannels;
|
||||||
|
u32 reverbSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Ngs2
|
12
src/core/libraries/ngs2/ngs2_sampler.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ngs2_error.h"
|
||||||
|
#include "ngs2_impl.h"
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
|
||||||
|
using namespace Libraries::Kernel;
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
|
162
src/core/libraries/ngs2/ngs2_sampler.h
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ngs2.h"
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
|
class Ngs2Sampler;
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerRackOption {
|
||||||
|
OrbisNgs2RackOption rackOption;
|
||||||
|
u32 maxChannelWorks;
|
||||||
|
u32 maxCodecCaches;
|
||||||
|
u32 maxWaveformBlocks;
|
||||||
|
u32 maxEnvelopePoints;
|
||||||
|
u32 maxFilters;
|
||||||
|
u32 maxAtrac9Decoders;
|
||||||
|
u32 maxAtrac9ChannelWorks;
|
||||||
|
u32 maxAjmAtrac9Decoders;
|
||||||
|
u32 numPeakMeterBlocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceSetupParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
OrbisNgs2WaveformFormat format;
|
||||||
|
u32 flags;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceWaveformBlocksParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
const void* data;
|
||||||
|
u32 flags;
|
||||||
|
u32 numBlocks;
|
||||||
|
const OrbisNgs2WaveformBlock* aBlock;
|
||||||
|
// Blocks
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceWaveformAddressParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
const void* from;
|
||||||
|
const void* to;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceWaveformFrameOffsetParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 frameOffset;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceExitLoopParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoicePitchParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
float ratio;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceEnvelopeParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 numForwardPoints;
|
||||||
|
u32 numReleasePoints;
|
||||||
|
const OrbisNgs2EnvelopePoint* aPoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceDistortionParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 flags;
|
||||||
|
float a;
|
||||||
|
float b;
|
||||||
|
float clip;
|
||||||
|
float gate;
|
||||||
|
float wetLevel;
|
||||||
|
float dryLevel;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceUserFxParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
OrbisNgs2UserFxProcessHandler handler;
|
||||||
|
|
||||||
|
uintptr_t userData0;
|
||||||
|
uintptr_t userData1;
|
||||||
|
uintptr_t userData2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoicePeakMeterParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 enableFlag;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceFilterParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 index;
|
||||||
|
u32 location;
|
||||||
|
u32 type;
|
||||||
|
u32 channelMask;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
float i0;
|
||||||
|
float i1;
|
||||||
|
float i2;
|
||||||
|
float o1;
|
||||||
|
float o2;
|
||||||
|
} direct;
|
||||||
|
struct {
|
||||||
|
float fc;
|
||||||
|
float q;
|
||||||
|
float level;
|
||||||
|
u32 reserved;
|
||||||
|
u32 reserved2;
|
||||||
|
} fcq;
|
||||||
|
} param;
|
||||||
|
u32 reserved3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceNumFilters {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 numFilters;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerVoiceState {
|
||||||
|
OrbisNgs2VoiceState voiceState;
|
||||||
|
float envelopeHeight;
|
||||||
|
float peakHeight;
|
||||||
|
u32 reserved;
|
||||||
|
u64 numDecodedSamples;
|
||||||
|
u64 decodedDataSize;
|
||||||
|
u64 userData;
|
||||||
|
const void* waveformData;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SamplerRackInfo {
|
||||||
|
OrbisNgs2RackInfo rackInfo;
|
||||||
|
u32 maxChannelWorks;
|
||||||
|
u32 maxCodecCaches;
|
||||||
|
u32 maxWaveformBlocks;
|
||||||
|
u32 maxEnvelopePoints;
|
||||||
|
u32 maxFilters;
|
||||||
|
u32 maxAtrac9Decoders;
|
||||||
|
u32 maxAtrac9ChannelWorks;
|
||||||
|
u32 maxAjmAtrac9Decoders;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Ngs2
|
12
src/core/libraries/ngs2/ngs2_submixer.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "ngs2_error.h"
|
||||||
|
#include "ngs2_impl.h"
|
||||||
|
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
|
||||||
|
using namespace Libraries::Kernel;
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
|
126
src/core/libraries/ngs2/ngs2_submixer.h
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ngs2.h"
|
||||||
|
|
||||||
|
namespace Libraries::Ngs2 {
|
||||||
|
|
||||||
|
class Ngs2Submixer;
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerRackOption {
|
||||||
|
OrbisNgs2RackOption rackOption;
|
||||||
|
u32 maxChannels;
|
||||||
|
u32 maxEnvelopePoints;
|
||||||
|
u32 maxFilters;
|
||||||
|
u32 maxInputs;
|
||||||
|
u32 numPeakMeterBlocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerVoiceSetupParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
u32 numIoChannels;
|
||||||
|
u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerVoiceEnvelopeParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 numForwardPoints;
|
||||||
|
u32 numReleasePoints;
|
||||||
|
const OrbisNgs2EnvelopePoint* aPoint;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerVoiceCompressorParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 flags;
|
||||||
|
float threshold;
|
||||||
|
float ratio;
|
||||||
|
float knee;
|
||||||
|
float attackTime;
|
||||||
|
float releaseTime;
|
||||||
|
float level;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerVoiceDistortionParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 flags;
|
||||||
|
float a;
|
||||||
|
float b;
|
||||||
|
float clip;
|
||||||
|
float gate;
|
||||||
|
float wetLevel;
|
||||||
|
float dryLevel;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerVoiceUserFxParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
OrbisNgs2UserFxProcessHandler handler;
|
||||||
|
|
||||||
|
uintptr_t userData0;
|
||||||
|
uintptr_t userData1;
|
||||||
|
uintptr_t userData2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerVoicePeakMeterParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 enableFlag;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerVoiceFilterParam {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 index;
|
||||||
|
u32 location;
|
||||||
|
u32 type;
|
||||||
|
u32 channelMask;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
float i0;
|
||||||
|
float i1;
|
||||||
|
float i2;
|
||||||
|
float o1;
|
||||||
|
float o2;
|
||||||
|
} direct;
|
||||||
|
struct {
|
||||||
|
float fc;
|
||||||
|
float q;
|
||||||
|
float level;
|
||||||
|
u32 reserved;
|
||||||
|
u32 reserved2;
|
||||||
|
} fcq;
|
||||||
|
} param;
|
||||||
|
u32 reserved3;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerVoiceNumFilters {
|
||||||
|
OrbisNgs2VoiceParamHeader header;
|
||||||
|
|
||||||
|
u32 numFilters;
|
||||||
|
u32 reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerVoiceState {
|
||||||
|
OrbisNgs2VoiceState voiceState;
|
||||||
|
float envelopeHeight;
|
||||||
|
float peakHeight;
|
||||||
|
float compressorHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OrbisNgs2SubmixerRackInfo {
|
||||||
|
OrbisNgs2RackInfo rackInfo;
|
||||||
|
u32 maxChannels;
|
||||||
|
u32 maxEnvelopePoints;
|
||||||
|
u32 maxFilters;
|
||||||
|
u32 maxInputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::Ngs2
|
@ -923,15 +923,16 @@ int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTr
|
|||||||
node.attribute("unlockstate").set_value("true");
|
node.attribute("unlockstate").set_value("true");
|
||||||
}
|
}
|
||||||
|
|
||||||
Rtc::OrbisRtcTick trophyTimestamp;
|
auto trophyTimestamp = std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
Rtc::sceRtcGetCurrentTick(&trophyTimestamp);
|
std::chrono::system_clock::now().time_since_epoch())
|
||||||
|
.count();
|
||||||
|
|
||||||
if (node.attribute("timestamp").empty()) {
|
if (node.attribute("timestamp").empty()) {
|
||||||
node.append_attribute("timestamp") =
|
node.append_attribute("timestamp") =
|
||||||
std::to_string(trophyTimestamp.tick).c_str();
|
std::to_string(trophyTimestamp).c_str();
|
||||||
} else {
|
} else {
|
||||||
node.attribute("timestamp")
|
node.attribute("timestamp")
|
||||||
.set_value(std::to_string(trophyTimestamp.tick).c_str());
|
.set_value(std::to_string(trophyTimestamp).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string trophy_icon_file = "TROP";
|
std::string trophy_icon_file = "TROP";
|
||||||
@ -955,15 +956,16 @@ int PS4_SYSV_ABI sceNpTrophyUnlockTrophy(OrbisNpTrophyContext context, OrbisNpTr
|
|||||||
platinum_node.attribute("unlockstate").set_value("true");
|
platinum_node.attribute("unlockstate").set_value("true");
|
||||||
}
|
}
|
||||||
|
|
||||||
Rtc::OrbisRtcTick trophyTimestamp;
|
auto trophyTimestamp = std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
Rtc::sceRtcGetCurrentTick(&trophyTimestamp);
|
std::chrono::system_clock::now().time_since_epoch())
|
||||||
|
.count();
|
||||||
|
|
||||||
if (platinum_node.attribute("timestamp").empty()) {
|
if (platinum_node.attribute("timestamp").empty()) {
|
||||||
platinum_node.append_attribute("timestamp") =
|
platinum_node.append_attribute("timestamp") =
|
||||||
std::to_string(trophyTimestamp.tick).c_str();
|
std::to_string(trophyTimestamp).c_str();
|
||||||
} else {
|
} else {
|
||||||
platinum_node.attribute("timestamp")
|
platinum_node.attribute("timestamp")
|
||||||
.set_value(std::to_string(trophyTimestamp.tick).c_str());
|
.set_value(std::to_string(trophyTimestamp).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
int platinum_trophy_id =
|
int platinum_trophy_id =
|
||||||
|
@ -2,9 +2,17 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <cmrc/cmrc.hpp>
|
#include <cmrc/cmrc.hpp>
|
||||||
|
#include <common/path_util.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#ifdef ENABLE_QT_GUI
|
||||||
|
#include <qt_gui/background_music_player.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
@ -12,7 +20,7 @@
|
|||||||
#include "trophy_ui.h"
|
#include "trophy_ui.h"
|
||||||
|
|
||||||
CMRC_DECLARE(res);
|
CMRC_DECLARE(res);
|
||||||
|
namespace fs = std::filesystem;
|
||||||
using namespace ImGui;
|
using namespace ImGui;
|
||||||
namespace Libraries::NpTrophy {
|
namespace Libraries::NpTrophy {
|
||||||
|
|
||||||
@ -20,10 +28,18 @@ std::optional<TrophyUI> current_trophy_ui;
|
|||||||
std::queue<TrophyInfo> trophy_queue;
|
std::queue<TrophyInfo> trophy_queue;
|
||||||
std::mutex queueMtx;
|
std::mutex queueMtx;
|
||||||
|
|
||||||
|
std::string side = "right";
|
||||||
|
|
||||||
|
double trophy_timer;
|
||||||
|
|
||||||
TrophyUI::TrophyUI(const std::filesystem::path& trophyIconPath, const std::string& trophyName,
|
TrophyUI::TrophyUI(const std::filesystem::path& trophyIconPath, const std::string& trophyName,
|
||||||
const std::string_view& rarity)
|
const std::string_view& rarity)
|
||||||
: trophy_name(trophyName), trophy_type(rarity) {
|
: trophy_name(trophyName), trophy_type(rarity) {
|
||||||
|
|
||||||
|
side = Config::sideTrophy();
|
||||||
|
|
||||||
|
trophy_timer = Config::getTrophyNotificationDuration();
|
||||||
|
|
||||||
if (std::filesystem::exists(trophyIconPath)) {
|
if (std::filesystem::exists(trophyIconPath)) {
|
||||||
trophy_icon = RefCountedTexture::DecodePngFile(trophyIconPath);
|
trophy_icon = RefCountedTexture::DecodePngFile(trophyIconPath);
|
||||||
} else {
|
} else {
|
||||||
@ -31,23 +47,61 @@ TrophyUI::TrophyUI(const std::filesystem::path& trophyIconPath, const std::strin
|
|||||||
fmt::UTF(trophyIconPath.u8string()));
|
fmt::UTF(trophyIconPath.u8string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string pathString;
|
std::string pathString = "src/images/";
|
||||||
|
|
||||||
if (trophy_type == "P") {
|
if (trophy_type == "P") {
|
||||||
pathString = "src/images/platinum.png";
|
pathString += "platinum.png";
|
||||||
} else if (trophy_type == "G") {
|
} else if (trophy_type == "G") {
|
||||||
pathString = "src/images/gold.png";
|
pathString += "gold.png";
|
||||||
} else if (trophy_type == "S") {
|
} else if (trophy_type == "S") {
|
||||||
pathString = "src/images/silver.png";
|
pathString += "silver.png";
|
||||||
} else if (trophy_type == "B") {
|
} else if (trophy_type == "B") {
|
||||||
pathString = "src/images/bronze.png";
|
pathString += "bronze.png";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto CustomTrophy_Dir = Common::FS::GetUserPath(Common::FS::PathType::CustomTrophy);
|
||||||
|
std::string customPath;
|
||||||
|
|
||||||
|
if (trophy_type == "P" && fs::exists(CustomTrophy_Dir / "platinum.png")) {
|
||||||
|
customPath = (CustomTrophy_Dir / "platinum.png").string();
|
||||||
|
} else if (trophy_type == "G" && fs::exists(CustomTrophy_Dir / "gold.png")) {
|
||||||
|
customPath = (CustomTrophy_Dir / "gold.png").string();
|
||||||
|
} else if (trophy_type == "S" && fs::exists(CustomTrophy_Dir / "silver.png")) {
|
||||||
|
customPath = (CustomTrophy_Dir / "silver.png").string();
|
||||||
|
} else if (trophy_type == "B" && fs::exists(CustomTrophy_Dir / "bronze.png")) {
|
||||||
|
customPath = (CustomTrophy_Dir / "bronze.png").string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u8> imgdata;
|
||||||
|
if (!customPath.empty()) {
|
||||||
|
std::ifstream file(customPath, std::ios::binary);
|
||||||
|
if (file) {
|
||||||
|
imgdata = std::vector<u8>(std::istreambuf_iterator<char>(file),
|
||||||
|
std::istreambuf_iterator<char>());
|
||||||
|
} else {
|
||||||
|
LOG_ERROR(Lib_NpTrophy, "Could not open custom file for trophy in {}", customPath);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
auto resource = cmrc::res::get_filesystem();
|
auto resource = cmrc::res::get_filesystem();
|
||||||
auto file = resource.open(pathString);
|
auto file = resource.open(pathString);
|
||||||
std::vector<u8> imgdata(file.begin(), file.end());
|
imgdata = std::vector<u8>(file.begin(), file.end());
|
||||||
|
}
|
||||||
|
|
||||||
trophy_type_icon = RefCountedTexture::DecodePngTexture(imgdata);
|
trophy_type_icon = RefCountedTexture::DecodePngTexture(imgdata);
|
||||||
|
|
||||||
AddLayer(this);
|
AddLayer(this);
|
||||||
|
|
||||||
|
#ifdef ENABLE_QT_GUI
|
||||||
|
QString musicPathWav = QString::fromStdString(CustomTrophy_Dir.string() + "/trophy.wav");
|
||||||
|
QString musicPathMp3 = QString::fromStdString(CustomTrophy_Dir.string() + "/trophy.mp3");
|
||||||
|
if (fs::exists(musicPathWav.toStdString())) {
|
||||||
|
BackgroundMusicPlayer::getInstance().setVolume(100);
|
||||||
|
BackgroundMusicPlayer::getInstance().playMusic(musicPathWav, false);
|
||||||
|
} else if (fs::exists(musicPathMp3.toStdString())) {
|
||||||
|
BackgroundMusicPlayer::getInstance().setVolume(100);
|
||||||
|
BackgroundMusicPlayer::getInstance().playMusic(musicPathMp3, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
TrophyUI::~TrophyUI() {
|
TrophyUI::~TrophyUI() {
|
||||||
@ -58,36 +112,94 @@ void TrophyUI::Finish() {
|
|||||||
RemoveLayer(this);
|
RemoveLayer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float fade_opacity = 0.0f; // Initial opacity (invisible)
|
||||||
|
ImVec2 start_pos = ImVec2(1280.0f, 50.0f); // Starts off screen, right
|
||||||
|
ImVec2 target_pos = ImVec2(0.0f, 50.0f); // Final position
|
||||||
|
float animation_duration = 0.5f; // Animation duration
|
||||||
|
float elapsed_time = 0.0f; // Animation time
|
||||||
|
float fade_out_duration = 0.5f; // Final fade duration
|
||||||
|
|
||||||
void TrophyUI::Draw() {
|
void TrophyUI::Draw() {
|
||||||
const auto& io = GetIO();
|
const auto& io = GetIO();
|
||||||
|
|
||||||
float AdjustWidth = io.DisplaySize.x / 1280;
|
float AdjustWidth = io.DisplaySize.x / 1920;
|
||||||
float AdjustHeight = io.DisplaySize.y / 720;
|
float AdjustHeight = io.DisplaySize.y / 1080;
|
||||||
const ImVec2 window_size{
|
const ImVec2 window_size{
|
||||||
std::min(io.DisplaySize.x, (350 * AdjustWidth)),
|
std::min(io.DisplaySize.x, (350 * AdjustWidth)),
|
||||||
std::min(io.DisplaySize.y, (70 * AdjustHeight)),
|
std::min(io.DisplaySize.y, (70 * AdjustHeight)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
elapsed_time += io.DeltaTime;
|
||||||
|
float progress = std::min(elapsed_time / animation_duration, 1.0f);
|
||||||
|
|
||||||
|
float final_pos_x, start_x;
|
||||||
|
float final_pos_y, start_y;
|
||||||
|
|
||||||
|
if (side == "top") {
|
||||||
|
start_x = (io.DisplaySize.x - window_size.x) * 0.5f;
|
||||||
|
start_y = -window_size.y;
|
||||||
|
final_pos_x = start_x;
|
||||||
|
final_pos_y = 20 * AdjustHeight;
|
||||||
|
} else if (side == "left") {
|
||||||
|
start_x = -window_size.x;
|
||||||
|
start_y = 50 * AdjustHeight;
|
||||||
|
final_pos_x = 20 * AdjustWidth;
|
||||||
|
final_pos_y = start_y;
|
||||||
|
} else if (side == "right") {
|
||||||
|
start_x = io.DisplaySize.x;
|
||||||
|
start_y = 50 * AdjustHeight;
|
||||||
|
final_pos_x = io.DisplaySize.x - window_size.x - 20 * AdjustWidth;
|
||||||
|
final_pos_y = start_y;
|
||||||
|
} else if (side == "bottom") {
|
||||||
|
start_x = (io.DisplaySize.x - window_size.x) * 0.5f;
|
||||||
|
start_y = io.DisplaySize.y;
|
||||||
|
final_pos_x = start_x;
|
||||||
|
final_pos_y = io.DisplaySize.y - window_size.y - 20 * AdjustHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImVec2 current_pos = ImVec2(start_x + (final_pos_x - start_x) * progress,
|
||||||
|
start_y + (final_pos_y - start_y) * progress);
|
||||||
|
|
||||||
|
trophy_timer -= io.DeltaTime;
|
||||||
|
|
||||||
|
ImGui::SetNextWindowPos(current_pos);
|
||||||
|
|
||||||
|
// If the remaining time of the trophy is less than or equal to 1 second, the fade-out begins.
|
||||||
|
if (trophy_timer <= 1.0f) {
|
||||||
|
float fade_out_time = 1.0f - (trophy_timer / 1.0f);
|
||||||
|
fade_opacity = 1.0f - fade_out_time;
|
||||||
|
} else {
|
||||||
|
// Fade in , 0 to 1
|
||||||
|
fade_opacity = progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
fade_opacity = std::max(0.0f, std::min(fade_opacity, 1.0f));
|
||||||
|
|
||||||
SetNextWindowSize(window_size);
|
SetNextWindowSize(window_size);
|
||||||
|
SetNextWindowPos(current_pos);
|
||||||
SetNextWindowCollapsed(false);
|
SetNextWindowCollapsed(false);
|
||||||
SetNextWindowPos(ImVec2(io.DisplaySize.x - (370 * AdjustWidth), (50 * AdjustHeight)));
|
|
||||||
KeepNavHighlight();
|
KeepNavHighlight();
|
||||||
|
PushStyleVar(ImGuiStyleVar_Alpha, fade_opacity);
|
||||||
|
|
||||||
if (Begin("Trophy Window", nullptr,
|
if (Begin("Trophy Window", nullptr,
|
||||||
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
|
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoSavedSettings |
|
||||||
ImGuiWindowFlags_NoInputs)) {
|
ImGuiWindowFlags_NoInputs)) {
|
||||||
|
|
||||||
|
// Displays the trophy icon
|
||||||
if (trophy_type_icon) {
|
if (trophy_type_icon) {
|
||||||
SetCursorPosY((window_size.y * 0.5f) - (25 * AdjustHeight));
|
SetCursorPosY((window_size.y * 0.5f) - (25 * AdjustHeight));
|
||||||
Image(trophy_type_icon.GetTexture().im_id,
|
Image(trophy_type_icon.GetTexture().im_id,
|
||||||
ImVec2((50 * AdjustWidth), (50 * AdjustHeight)));
|
ImVec2((50 * AdjustWidth), (50 * AdjustHeight)));
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
} else {
|
} else {
|
||||||
// placeholder
|
// Placeholder
|
||||||
const auto pos = GetCursorScreenPos();
|
const auto pos = GetCursorScreenPos();
|
||||||
ImGui::GetWindowDrawList()->AddRectFilled(pos, pos + ImVec2{50.0f * AdjustHeight},
|
ImGui::GetWindowDrawList()->AddRectFilled(pos, pos + ImVec2{50.0f * AdjustHeight},
|
||||||
GetColorU32(ImVec4{0.7f}));
|
GetColorU32(ImVec4{0.7f}));
|
||||||
ImGui::Indent(60);
|
ImGui::Indent(60);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Displays the name of the trophy
|
||||||
const std::string combinedString = "Trophy earned!\n%s" + trophy_name;
|
const std::string combinedString = "Trophy earned!\n%s" + trophy_name;
|
||||||
const float wrap_width =
|
const float wrap_width =
|
||||||
CalcWrapWidthForPos(GetCursorScreenPos(), (window_size.x - (60 * AdjustWidth)));
|
CalcWrapWidthForPos(GetCursorScreenPos(), (window_size.x - (60 * AdjustWidth)));
|
||||||
@ -104,15 +216,23 @@ void TrophyUI::Draw() {
|
|||||||
const float text_height = ImGui::CalcTextSize(combinedString.c_str()).y;
|
const float text_height = ImGui::CalcTextSize(combinedString.c_str()).y;
|
||||||
SetCursorPosY((window_size.y - text_height) * 0.5);
|
SetCursorPosY((window_size.y - text_height) * 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (side == "top" || side == "bottom") {
|
||||||
|
float text_width = ImGui::CalcTextSize(trophy_name.c_str()).x;
|
||||||
|
float centered_x = (window_size.x - text_width) * 0.5f;
|
||||||
|
ImGui::SetCursorPosX(std::max(centered_x, 10.0f * AdjustWidth));
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::PushTextWrapPos(window_size.x - (60 * AdjustWidth));
|
ImGui::PushTextWrapPos(window_size.x - (60 * AdjustWidth));
|
||||||
TextWrapped("Trophy earned!\n%s", trophy_name.c_str());
|
TextWrapped("Trophy earned!\n%s", trophy_name.c_str());
|
||||||
ImGui::SameLine(window_size.x - (60 * AdjustWidth));
|
ImGui::SameLine(window_size.x - (60 * AdjustWidth));
|
||||||
|
|
||||||
|
// Displays the trophy icon
|
||||||
if (trophy_icon) {
|
if (trophy_icon) {
|
||||||
SetCursorPosY((window_size.y * 0.5f) - (25 * AdjustHeight));
|
SetCursorPosY((window_size.y * 0.5f) - (25 * AdjustHeight));
|
||||||
Image(trophy_icon.GetTexture().im_id, ImVec2((50 * AdjustWidth), (50 * AdjustHeight)));
|
Image(trophy_icon.GetTexture().im_id, ImVec2((50 * AdjustWidth), (50 * AdjustHeight)));
|
||||||
} else {
|
} else {
|
||||||
// placeholder
|
// Placeholder
|
||||||
const auto pos = GetCursorScreenPos();
|
const auto pos = GetCursorScreenPos();
|
||||||
ImGui::GetWindowDrawList()->AddRectFilled(pos, pos + ImVec2{50.0f * AdjustHeight},
|
ImGui::GetWindowDrawList()->AddRectFilled(pos, pos + ImVec2{50.0f * AdjustHeight},
|
||||||
GetColorU32(ImVec4{0.7f}));
|
GetColorU32(ImVec4{0.7f}));
|
||||||
@ -120,7 +240,8 @@ void TrophyUI::Draw() {
|
|||||||
}
|
}
|
||||||
End();
|
End();
|
||||||
|
|
||||||
trophy_timer -= io.DeltaTime;
|
PopStyleVar();
|
||||||
|
|
||||||
if (trophy_timer <= 0) {
|
if (trophy_timer <= 0) {
|
||||||
std::lock_guard<std::mutex> lock(queueMtx);
|
std::lock_guard<std::mutex> lock(queueMtx);
|
||||||
if (!trophy_queue.empty()) {
|
if (!trophy_queue.empty()) {
|
||||||
@ -141,13 +262,27 @@ void AddTrophyToQueue(const std::filesystem::path& trophyIconPath, const std::st
|
|||||||
if (Config::getisTrophyPopupDisabled()) {
|
if (Config::getisTrophyPopupDisabled()) {
|
||||||
return;
|
return;
|
||||||
} else if (current_trophy_ui.has_value()) {
|
} else if (current_trophy_ui.has_value()) {
|
||||||
|
current_trophy_ui.reset();
|
||||||
|
}
|
||||||
|
|
||||||
TrophyInfo new_trophy;
|
TrophyInfo new_trophy;
|
||||||
new_trophy.trophy_icon_path = trophyIconPath;
|
new_trophy.trophy_icon_path = trophyIconPath;
|
||||||
new_trophy.trophy_name = trophyName;
|
new_trophy.trophy_name = trophyName;
|
||||||
new_trophy.trophy_type = rarity;
|
new_trophy.trophy_type = rarity;
|
||||||
trophy_queue.push(new_trophy);
|
trophy_queue.push(new_trophy);
|
||||||
} else {
|
|
||||||
current_trophy_ui.emplace(trophyIconPath, trophyName, rarity);
|
if (!current_trophy_ui.has_value()) {
|
||||||
|
#ifdef ENABLE_QT_GUI
|
||||||
|
BackgroundMusicPlayer::getInstance().stopMusic();
|
||||||
|
#endif
|
||||||
|
// Resetting the animation for the next trophy
|
||||||
|
elapsed_time = 0.0f; // Resetting animation time
|
||||||
|
fade_opacity = 0.0f; // Starts invisible
|
||||||
|
start_pos = ImVec2(1280.0f, 50.0f); // Starts off screen, right
|
||||||
|
TrophyInfo next_trophy = trophy_queue.front();
|
||||||
|
trophy_queue.pop();
|
||||||
|
current_trophy_ui.emplace(next_trophy.trophy_icon_path, next_trophy.trophy_name,
|
||||||
|
next_trophy.trophy_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::string trophy_name;
|
std::string trophy_name;
|
||||||
std::string_view trophy_type;
|
std::string_view trophy_type;
|
||||||
float trophy_timer = 5.0f;
|
|
||||||
ImGui::RefCountedTexture trophy_icon;
|
ImGui::RefCountedTexture trophy_icon;
|
||||||
ImGui::RefCountedTexture trophy_type_icon;
|
ImGui::RefCountedTexture trophy_type_icon;
|
||||||
};
|
};
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
|
#include "core/libraries/kernel/process.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "core/libraries/system/sysmodule.h"
|
#include "core/libraries/system/sysmodule.h"
|
||||||
#include "core/libraries/system/system_error.h"
|
#include "core/libraries/system/system_error.h"
|
||||||
@ -18,9 +19,12 @@ int PS4_SYSV_ABI sceSysmoduleGetModuleHandleInternal() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind() {
|
s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags, void* info) {
|
||||||
LOG_ERROR(Lib_SysModule, "(STUBBED) called");
|
LOG_ERROR(Lib_SysModule, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
Kernel::OrbisModuleInfoForUnwind module_info;
|
||||||
|
module_info.st_size = 0x130;
|
||||||
|
s32 res = Kernel::sceKernelGetModuleInfoForUnwind(addr, flags, &module_info);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceSysmoduleIsCalledFromSysModule() {
|
int PS4_SYSV_ABI sceSysmoduleIsCalledFromSysModule() {
|
||||||
|
@ -152,7 +152,7 @@ enum class OrbisSysModuleInternal : u32 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceSysmoduleGetModuleHandleInternal();
|
int PS4_SYSV_ABI sceSysmoduleGetModuleHandleInternal();
|
||||||
int PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind();
|
s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags, void* info);
|
||||||
int PS4_SYSV_ABI sceSysmoduleIsCalledFromSysModule();
|
int PS4_SYSV_ABI sceSysmoduleIsCalledFromSysModule();
|
||||||
int PS4_SYSV_ABI sceSysmoduleIsCameraPreloaded();
|
int PS4_SYSV_ABI sceSysmoduleIsCameraPreloaded();
|
||||||
int PS4_SYSV_ABI sceSysmoduleIsLoaded(OrbisSysModule id);
|
int PS4_SYSV_ABI sceSysmoduleIsLoaded(OrbisSysModule id);
|
||||||
|
@ -1893,7 +1893,7 @@ int PS4_SYSV_ABI sceSystemServiceNavigateToGoHome() {
|
|||||||
|
|
||||||
s32 PS4_SYSV_ABI sceSystemServiceParamGetInt(OrbisSystemServiceParamId param_id, int* value) {
|
s32 PS4_SYSV_ABI sceSystemServiceParamGetInt(OrbisSystemServiceParamId param_id, int* value) {
|
||||||
// TODO this probably should be stored in config for UI configuration
|
// TODO this probably should be stored in config for UI configuration
|
||||||
LOG_INFO(Lib_SystemService, "called param_id {}", u32(param_id));
|
LOG_DEBUG(Lib_SystemService, "called param_id {}", u32(param_id));
|
||||||
if (value == nullptr) {
|
if (value == nullptr) {
|
||||||
LOG_ERROR(Lib_SystemService, "value is null");
|
LOG_ERROR(Lib_SystemService, "value is null");
|
||||||
return ORBIS_SYSTEM_SERVICE_ERROR_PARAMETER;
|
return ORBIS_SYSTEM_SERVICE_ERROR_PARAMETER;
|
||||||
|
@ -1043,7 +1043,7 @@ int PS4_SYSV_ABI sceUserServiceGetTraditionalChineseInputType() {
|
|||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUserServiceGetUserColor(int user_id, OrbisUserServiceUserColor* color) {
|
s32 PS4_SYSV_ABI sceUserServiceGetUserColor(int user_id, OrbisUserServiceUserColor* color) {
|
||||||
// TODO fix me better
|
// TODO fix me better
|
||||||
LOG_INFO(Lib_UserService, "called user_id = {}", user_id);
|
LOG_DEBUG(Lib_UserService, "called user_id = {}", user_id);
|
||||||
if (color == nullptr) {
|
if (color == nullptr) {
|
||||||
LOG_ERROR(Lib_UserService, "color is null");
|
LOG_ERROR(Lib_UserService, "color is null");
|
||||||
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||||
@ -1068,7 +1068,7 @@ int PS4_SYSV_ABI sceUserServiceGetUserGroupNum() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceUserServiceGetUserName(int user_id, char* user_name, std::size_t size) {
|
s32 PS4_SYSV_ABI sceUserServiceGetUserName(int user_id, char* user_name, std::size_t size) {
|
||||||
LOG_INFO(Lib_UserService, "called user_id = {} ,size = {} ", user_id, size);
|
LOG_DEBUG(Lib_UserService, "called user_id = {} ,size = {} ", user_id, size);
|
||||||
if (user_name == nullptr) {
|
if (user_name == nullptr) {
|
||||||
LOG_ERROR(Lib_UserService, "user_name is null");
|
LOG_ERROR(Lib_UserService, "user_name is null");
|
||||||
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;
|
||||||
|
@ -63,6 +63,7 @@ void VideoOutDriver::Close(s32 handle) {
|
|||||||
|
|
||||||
main_port.is_open = false;
|
main_port.is_open = false;
|
||||||
main_port.flip_rate = 0;
|
main_port.flip_rate = 0;
|
||||||
|
main_port.prev_index = -1;
|
||||||
ASSERT(main_port.flip_events.empty());
|
ASSERT(main_port.flip_events.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,6 +134,10 @@ int VideoOutDriver::RegisterBuffers(VideoOutPort* port, s32 startIndex, void* co
|
|||||||
.address_right = 0,
|
.address_right = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Reset flip label also when registering buffer
|
||||||
|
port->buffer_labels[startIndex + i] = 0;
|
||||||
|
port->SignalVoLabel();
|
||||||
|
|
||||||
presenter->RegisterVideoOutSurface(group, address);
|
presenter->RegisterVideoOutSurface(group, address);
|
||||||
LOG_INFO(Lib_VideoOut, "buffers[{}] = {:#x}", i + startIndex, address);
|
LOG_INFO(Lib_VideoOut, "buffers[{}] = {:#x}", i + startIndex, address);
|
||||||
}
|
}
|
||||||
@ -160,11 +165,8 @@ int VideoOutDriver::UnregisterBuffers(VideoOutPort* port, s32 attributeIndex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VideoOutDriver::Flip(const Request& req) {
|
void VideoOutDriver::Flip(const Request& req) {
|
||||||
// Whatever the game is rendering show splash if it is active
|
|
||||||
if (!presenter->ShowSplash(req.frame)) {
|
|
||||||
// Present the frame.
|
// Present the frame.
|
||||||
presenter->Present(req.frame);
|
presenter->Present(req.frame);
|
||||||
}
|
|
||||||
|
|
||||||
// Update flip status.
|
// Update flip status.
|
||||||
auto* port = req.port;
|
auto* port = req.port;
|
||||||
@ -193,17 +195,16 @@ void VideoOutDriver::Flip(const Request& req) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset flip label
|
// Reset prev flip label
|
||||||
if (req.index != -1) {
|
if (port->prev_index != -1) {
|
||||||
port->buffer_labels[req.index] = 0;
|
port->buffer_labels[port->prev_index] = 0;
|
||||||
port->SignalVoLabel();
|
port->SignalVoLabel();
|
||||||
}
|
}
|
||||||
|
// save to prev buf index
|
||||||
|
port->prev_index = req.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoOutDriver::DrawBlankFrame() {
|
void VideoOutDriver::DrawBlankFrame() {
|
||||||
if (presenter->ShowSplash(nullptr)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto empty_frame = presenter->PrepareBlankFrame(false);
|
const auto empty_frame = presenter->PrepareBlankFrame(false);
|
||||||
presenter->Present(empty_frame);
|
presenter->Present(empty_frame);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ struct VideoOutPort {
|
|||||||
std::condition_variable vo_cv;
|
std::condition_variable vo_cv;
|
||||||
std::condition_variable vblank_cv;
|
std::condition_variable vblank_cv;
|
||||||
int flip_rate = 0;
|
int flip_rate = 0;
|
||||||
|
int prev_index = -1;
|
||||||
bool is_open = false;
|
bool is_open = false;
|
||||||
bool is_mode_changing = false; // Used to prevent flip during mode change
|
bool is_mode_changing = false; // Used to prevent flip during mode change
|
||||||
|
|
||||||
|
@ -295,10 +295,16 @@ s32 PS4_SYSV_ABI sceVideoOutUnregisterBuffers(s32 handle, s32 attributeIndex) {
|
|||||||
return driver->UnregisterBuffers(port, attributeIndex);
|
return driver->UnregisterBuffers(port, attributeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sceVideoOutGetBufferLabelAddress(s32 handle, uintptr_t* label_addr) {
|
s32 PS4_SYSV_ABI sceVideoOutGetBufferLabelAddress(s32 handle, uintptr_t* label_addr) {
|
||||||
|
if (label_addr == nullptr) {
|
||||||
|
return ORBIS_VIDEO_OUT_ERROR_INVALID_ADDRESS;
|
||||||
|
}
|
||||||
auto* port = driver->GetPort(handle);
|
auto* port = driver->GetPort(handle);
|
||||||
ASSERT(port);
|
if (!port) {
|
||||||
|
return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
*label_addr = reinterpret_cast<uintptr_t>(port->buffer_labels.data());
|
*label_addr = reinterpret_cast<uintptr_t>(port->buffer_labels.data());
|
||||||
|
return 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void** unk) {
|
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void** unk) {
|
||||||
@ -360,7 +366,7 @@ s32 PS4_SYSV_ABI sceVideoOutAdjustColor(s32 handle, const SceVideoOutColorSettin
|
|||||||
return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE;
|
return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
presenter->GetGammaRef() = settings->gamma;
|
presenter->GetPPSettingsRef().gamma = settings->gamma;
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -430,6 +436,8 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
|||||||
sceVideoOutIsFlipPending);
|
sceVideoOutIsFlipPending);
|
||||||
LIB_FUNCTION("N5KDtkIjjJ4", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
|
LIB_FUNCTION("N5KDtkIjjJ4", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
|
||||||
sceVideoOutUnregisterBuffers);
|
sceVideoOutUnregisterBuffers);
|
||||||
|
LIB_FUNCTION("OcQybQejHEY", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
|
||||||
|
sceVideoOutGetBufferLabelAddress);
|
||||||
LIB_FUNCTION("uquVH4-Du78", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutClose);
|
LIB_FUNCTION("uquVH4-Du78", "libSceVideoOut", 1, "libSceVideoOut", 0, 0, sceVideoOutClose);
|
||||||
LIB_FUNCTION("1FZBKy8HeNU", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
|
LIB_FUNCTION("1FZBKy8HeNU", "libSceVideoOut", 1, "libSceVideoOut", 0, 0,
|
||||||
sceVideoOutGetVblankStatus);
|
sceVideoOutGetVblankStatus);
|
||||||
@ -460,6 +468,8 @@ void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
|||||||
sceVideoOutSetBufferAttribute);
|
sceVideoOutSetBufferAttribute);
|
||||||
LIB_FUNCTION("w3BY+tAEiQY", "libSceVideoOut", 1, "libSceVideoOut", 1, 1,
|
LIB_FUNCTION("w3BY+tAEiQY", "libSceVideoOut", 1, "libSceVideoOut", 1, 1,
|
||||||
sceVideoOutRegisterBuffers);
|
sceVideoOutRegisterBuffers);
|
||||||
|
LIB_FUNCTION("OcQybQejHEY", "libSceVideoOut", 1, "libSceVideoOut", 1, 1,
|
||||||
|
sceVideoOutGetBufferLabelAddress);
|
||||||
LIB_FUNCTION("U46NwOiJpys", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutSubmitFlip);
|
LIB_FUNCTION("U46NwOiJpys", "libSceVideoOut", 1, "libSceVideoOut", 1, 1, sceVideoOutSubmitFlip);
|
||||||
LIB_FUNCTION("SbU3dwp80lQ", "libSceVideoOut", 1, "libSceVideoOut", 1, 1,
|
LIB_FUNCTION("SbU3dwp80lQ", "libSceVideoOut", 1, "libSceVideoOut", 1, 1,
|
||||||
sceVideoOutGetFlipStatus);
|
sceVideoOutGetFlipStatus);
|
||||||
|
@ -118,6 +118,7 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Kernel::SceKernelEqueue eq, s32 handle,
|
|||||||
s32 PS4_SYSV_ABI sceVideoOutAddVblankEvent(Kernel::SceKernelEqueue eq, s32 handle, void* udata);
|
s32 PS4_SYSV_ABI sceVideoOutAddVblankEvent(Kernel::SceKernelEqueue eq, s32 handle, void* udata);
|
||||||
s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses,
|
s32 PS4_SYSV_ABI sceVideoOutRegisterBuffers(s32 handle, s32 startIndex, void* const* addresses,
|
||||||
s32 bufferNum, const BufferAttribute* attribute);
|
s32 bufferNum, const BufferAttribute* attribute);
|
||||||
|
s32 PS4_SYSV_ABI sceVideoOutGetBufferLabelAddress(s32 handle, uintptr_t* label_addr);
|
||||||
s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate);
|
s32 PS4_SYSV_ABI sceVideoOutSetFlipRate(s32 handle, s32 rate);
|
||||||
s32 PS4_SYSV_ABI sceVideoOutIsFlipPending(s32 handle);
|
s32 PS4_SYSV_ABI sceVideoOutIsFlipPending(s32 handle);
|
||||||
s32 PS4_SYSV_ABI sceVideoOutWaitVblank(s32 handle);
|
s32 PS4_SYSV_ABI sceVideoOutWaitVblank(s32 handle);
|
||||||
@ -133,7 +134,6 @@ s32 PS4_SYSV_ABI sceVideoOutColorSettingsSetGamma(SceVideoOutColorSettings* sett
|
|||||||
s32 PS4_SYSV_ABI sceVideoOutAdjustColor(s32 handle, const SceVideoOutColorSettings* settings);
|
s32 PS4_SYSV_ABI sceVideoOutAdjustColor(s32 handle, const SceVideoOutColorSettings* settings);
|
||||||
|
|
||||||
// Internal system functions
|
// Internal system functions
|
||||||
void sceVideoOutGetBufferLabelAddress(s32 handle, uintptr_t* label_addr);
|
|
||||||
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void** unk);
|
s32 sceVideoOutSubmitEopFlip(s32 handle, u32 buf_id, u32 mode, u32 arg, void** unk);
|
||||||
|
|
||||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||||
|
@ -139,6 +139,35 @@ s32 Linker::LoadModule(const std::filesystem::path& elf_name, bool is_dynamic) {
|
|||||||
return m_modules.size() - 1;
|
return m_modules.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 Linker::LoadAndStartModule(const std::filesystem::path& path, u64 args, const void* argp,
|
||||||
|
int* pRes) {
|
||||||
|
u32 handle = FindByName(path);
|
||||||
|
if (handle != -1) {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
handle = LoadModule(path, true);
|
||||||
|
if (handle == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auto* module = GetModule(handle);
|
||||||
|
RelocateAnyImports(module);
|
||||||
|
|
||||||
|
// If the new module has a TLS image, trigger its load when TlsGetAddr is called.
|
||||||
|
if (module->tls.image_size != 0) {
|
||||||
|
AdvanceGenerationCounter();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve and verify proc param according to libkernel.
|
||||||
|
u64* param = module->GetProcParam<u64*>();
|
||||||
|
ASSERT_MSG(!param || param[0] >= 0x18, "Invalid module param size: {}", param[0]);
|
||||||
|
s32 ret = module->Start(args, argp, param);
|
||||||
|
if (pRes) {
|
||||||
|
*pRes = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
Module* Linker::FindByAddress(VAddr address) {
|
Module* Linker::FindByAddress(VAddr address) {
|
||||||
for (auto& module : m_modules) {
|
for (auto& module : m_modules) {
|
||||||
const VAddr base = module->GetBaseAddress();
|
const VAddr base = module->GetBaseAddress();
|
||||||
|
@ -144,6 +144,8 @@ public:
|
|||||||
void FreeTlsForNonPrimaryThread(void* pointer);
|
void FreeTlsForNonPrimaryThread(void* pointer);
|
||||||
|
|
||||||
s32 LoadModule(const std::filesystem::path& elf_name, bool is_dynamic = false);
|
s32 LoadModule(const std::filesystem::path& elf_name, bool is_dynamic = false);
|
||||||
|
s32 LoadAndStartModule(const std::filesystem::path& path, u64 args, const void* argp,
|
||||||
|
int* pRes);
|
||||||
Module* FindByAddress(VAddr address);
|
Module* FindByAddress(VAddr address);
|
||||||
|
|
||||||
void Relocate(Module* module);
|
void Relocate(Module* module);
|
||||||
|
@ -38,6 +38,16 @@ void MemoryManager::SetupMemoryRegions(u64 flexible_size, bool use_extended_mem1
|
|||||||
bool use_extended_mem2) {
|
bool use_extended_mem2) {
|
||||||
const bool is_neo = ::Libraries::Kernel::sceKernelIsNeoMode();
|
const bool is_neo = ::Libraries::Kernel::sceKernelIsNeoMode();
|
||||||
auto total_size = is_neo ? SCE_KERNEL_TOTAL_MEM_PRO : SCE_KERNEL_TOTAL_MEM;
|
auto total_size = is_neo ? SCE_KERNEL_TOTAL_MEM_PRO : SCE_KERNEL_TOTAL_MEM;
|
||||||
|
if (Config::isDevKitConsole()) {
|
||||||
|
const auto old_size = total_size;
|
||||||
|
// Assuming 2gb is neo for now, will need to link it with sceKernelIsDevKit
|
||||||
|
total_size += is_neo ? 2_GB : 768_MB;
|
||||||
|
LOG_WARNING(Kernel_Vmm,
|
||||||
|
"Config::isDevKitConsole is enabled! Added additional {:s} of direct memory.",
|
||||||
|
is_neo ? "2 GB" : "768 MB");
|
||||||
|
LOG_WARNING(Kernel_Vmm, "Old Direct Size: {:#x} -> New Direct Size: {:#x}", old_size,
|
||||||
|
total_size);
|
||||||
|
}
|
||||||
if (!use_extended_mem1 && is_neo) {
|
if (!use_extended_mem1 && is_neo) {
|
||||||
total_size -= 256_MB;
|
total_size -= 256_MB;
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ Module::Module(Core::MemoryManager* memory_, const std::filesystem::path& file_,
|
|||||||
|
|
||||||
Module::~Module() = default;
|
Module::~Module() = default;
|
||||||
|
|
||||||
s32 Module::Start(size_t args, const void* argp, void* param) {
|
s32 Module::Start(u64 args, const void* argp, void* param) {
|
||||||
LOG_INFO(Core_Linker, "Module started : {}", name);
|
LOG_INFO(Core_Linker, "Module started : {}", name);
|
||||||
const VAddr addr = dynamic_info.init_virtual_addr + GetBaseAddress();
|
const VAddr addr = dynamic_info.init_virtual_addr + GetBaseAddress();
|
||||||
return ExecuteGuest(reinterpret_cast<EntryFunc>(addr), args, argp, param);
|
return ExecuteGuest(reinterpret_cast<EntryFunc>(addr), args, argp, param);
|
||||||
|
@ -203,7 +203,7 @@ public:
|
|||||||
return (rela_bits[index >> 3] >> (index & 7)) & 1;
|
return (rela_bits[index >> 3] >> (index & 7)) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 Start(size_t args, const void* argp, void* param);
|
s32 Start(u64 args, const void* argp, void* param);
|
||||||
void LoadModuleToMemory(u32& max_tls_index);
|
void LoadModuleToMemory(u32& max_tls_index);
|
||||||
void LoadDynamicInfo();
|
void LoadDynamicInfo();
|
||||||
void LoadSymbols();
|
void LoadSymbols();
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "core/file_format/psf.h"
|
#include "core/file_format/psf.h"
|
||||||
#include "core/file_format/splash.h"
|
|
||||||
#include "core/file_format/trp.h"
|
#include "core/file_format/trp.h"
|
||||||
#include "core/file_sys/fs.h"
|
#include "core/file_sys/fs.h"
|
||||||
#include "core/libraries/disc_map/disc_map.h"
|
#include "core/libraries/disc_map/disc_map.h"
|
||||||
@ -81,7 +80,7 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
|
|||||||
const auto eboot_name = file.filename().string();
|
const auto eboot_name = file.filename().string();
|
||||||
auto game_folder = file.parent_path();
|
auto game_folder = file.parent_path();
|
||||||
if (const auto game_folder_name = game_folder.filename().string();
|
if (const auto game_folder_name = game_folder.filename().string();
|
||||||
game_folder_name.ends_with("-UPDATE")) {
|
game_folder_name.ends_with("-UPDATE") || game_folder_name.ends_with("-patch")) {
|
||||||
// If an executable was launched from a separate update directory,
|
// If an executable was launched from a separate update directory,
|
||||||
// use the base game directory as the game folder.
|
// use the base game directory as the game folder.
|
||||||
const auto base_name = game_folder_name.substr(0, game_folder_name.size() - 7);
|
const auto base_name = game_folder_name.substr(0, game_folder_name.size() - 7);
|
||||||
@ -107,6 +106,11 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
|
|||||||
Common::PSFAttributes psf_attributes{};
|
Common::PSFAttributes psf_attributes{};
|
||||||
|
|
||||||
const auto param_sfo_path = mnt->GetHostPath("/app0/sce_sys/param.sfo");
|
const auto param_sfo_path = mnt->GetHostPath("/app0/sce_sys/param.sfo");
|
||||||
|
if (!std::filesystem::exists(param_sfo_path) || !Config::getSeparateLogFilesEnabled()) {
|
||||||
|
Common::Log::Initialize();
|
||||||
|
Common::Log::Start();
|
||||||
|
}
|
||||||
|
|
||||||
if (std::filesystem::exists(param_sfo_path)) {
|
if (std::filesystem::exists(param_sfo_path)) {
|
||||||
auto* param_sfo = Common::Singleton<PSF>::Instance();
|
auto* param_sfo = Common::Singleton<PSF>::Instance();
|
||||||
const bool success = param_sfo->Open(param_sfo_path);
|
const bool success = param_sfo->Open(param_sfo_path);
|
||||||
@ -117,10 +121,8 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
|
|||||||
|
|
||||||
if (Config::getSeparateLogFilesEnabled()) {
|
if (Config::getSeparateLogFilesEnabled()) {
|
||||||
Common::Log::Initialize(id + ".log");
|
Common::Log::Initialize(id + ".log");
|
||||||
} else {
|
|
||||||
Common::Log::Initialize();
|
|
||||||
}
|
|
||||||
Common::Log::Start();
|
Common::Log::Start();
|
||||||
|
}
|
||||||
LOG_INFO(Loader, "Starting shadps4 emulator v{} ", Common::VERSION);
|
LOG_INFO(Loader, "Starting shadps4 emulator v{} ", Common::VERSION);
|
||||||
LOG_INFO(Loader, "Revision {}", Common::g_scm_rev);
|
LOG_INFO(Loader, "Revision {}", Common::g_scm_rev);
|
||||||
LOG_INFO(Loader, "Branch {}", Common::g_scm_branch);
|
LOG_INFO(Loader, "Branch {}", Common::g_scm_branch);
|
||||||
@ -182,12 +184,7 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
|
|||||||
|
|
||||||
const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png");
|
const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png");
|
||||||
if (std::filesystem::exists(pic1_path)) {
|
if (std::filesystem::exists(pic1_path)) {
|
||||||
auto* splash = Common::Singleton<Splash>::Instance();
|
game_info.splash_path = pic1_path;
|
||||||
if (!splash->IsLoaded()) {
|
|
||||||
if (!splash->Open(pic1_path)) {
|
|
||||||
LOG_ERROR(Loader, "Game splash: unable to open file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
game_info.initialized = true;
|
game_info.initialized = true;
|
||||||
@ -292,13 +289,12 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::LoadSystemModules(const std::string& game_serial) {
|
void Emulator::LoadSystemModules(const std::string& game_serial) {
|
||||||
constexpr std::array<SysModules, 11> ModulesToLoad{
|
constexpr std::array<SysModules, 10> ModulesToLoad{
|
||||||
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
|
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
|
||||||
{"libSceUlt.sprx", nullptr},
|
{"libSceUlt.sprx", nullptr},
|
||||||
{"libSceJson.sprx", nullptr},
|
{"libSceJson.sprx", nullptr},
|
||||||
{"libSceJson2.sprx", nullptr},
|
{"libSceJson2.sprx", nullptr},
|
||||||
{"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal},
|
{"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal},
|
||||||
{"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap},
|
|
||||||
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
|
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
|
||||||
{"libSceCesCs.sprx", nullptr},
|
{"libSceCesCs.sprx", nullptr},
|
||||||
{"libSceFont.sprx", nullptr},
|
{"libSceFont.sprx", nullptr},
|
||||||
|
BIN
src/images/KBM.png
Normal file
After Width: | Height: | Size: 236 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 4.0 KiB |
BIN
src/images/fullscreen_icon.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 965 B After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 3.3 KiB |
BIN
src/images/refreshlist_icon.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
src/images/restart_game_icon.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 658 B After Width: | Height: | Size: 1.6 KiB |
BIN
src/images/trophy_icon.png
Normal file
After Width: | Height: | Size: 17 KiB |
@ -175,6 +175,7 @@ void WorkerLoop() {
|
|||||||
|
|
||||||
auto texture = Vulkan::UploadTexture(pixels, vk::Format::eR8G8B8A8Unorm, width, height,
|
auto texture = Vulkan::UploadTexture(pixels, vk::Format::eR8G8B8A8Unorm, width, height,
|
||||||
width * height * 4 * sizeof(stbi_uc));
|
width * height * 4 * sizeof(stbi_uc));
|
||||||
|
stbi_image_free((void*)pixels);
|
||||||
|
|
||||||
core->upload_data = texture;
|
core->upload_data = texture;
|
||||||
core->width = width;
|
core->width = width;
|
||||||
|
@ -7,7 +7,6 @@ BackgroundMusicPlayer::BackgroundMusicPlayer(QObject* parent) : QObject(parent)
|
|||||||
m_mediaPlayer = new QMediaPlayer(this);
|
m_mediaPlayer = new QMediaPlayer(this);
|
||||||
m_audioOutput = new QAudioOutput(this);
|
m_audioOutput = new QAudioOutput(this);
|
||||||
m_mediaPlayer->setAudioOutput(m_audioOutput);
|
m_mediaPlayer->setAudioOutput(m_audioOutput);
|
||||||
m_mediaPlayer->setLoops(QMediaPlayer::Infinite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundMusicPlayer::setVolume(int volume) {
|
void BackgroundMusicPlayer::setVolume(int volume) {
|
||||||
@ -16,7 +15,7 @@ void BackgroundMusicPlayer::setVolume(int volume) {
|
|||||||
m_audioOutput->setVolume(linearVolume);
|
m_audioOutput->setVolume(linearVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundMusicPlayer::playMusic(const QString& snd0path) {
|
void BackgroundMusicPlayer::playMusic(const QString& snd0path, bool loops) {
|
||||||
if (snd0path.isEmpty()) {
|
if (snd0path.isEmpty()) {
|
||||||
stopMusic();
|
stopMusic();
|
||||||
return;
|
return;
|
||||||
@ -28,6 +27,12 @@ void BackgroundMusicPlayer::playMusic(const QString& snd0path) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (loops) {
|
||||||
|
m_mediaPlayer->setLoops(QMediaPlayer::Infinite);
|
||||||
|
} else {
|
||||||
|
m_mediaPlayer->setLoops(1);
|
||||||
|
}
|
||||||
|
|
||||||
m_currentMusic = newMusic;
|
m_currentMusic = newMusic;
|
||||||
m_mediaPlayer->setSource(newMusic);
|
m_mediaPlayer->setSource(newMusic);
|
||||||
m_mediaPlayer->play();
|
m_mediaPlayer->play();
|
||||||
@ -35,4 +40,5 @@ void BackgroundMusicPlayer::playMusic(const QString& snd0path) {
|
|||||||
|
|
||||||
void BackgroundMusicPlayer::stopMusic() {
|
void BackgroundMusicPlayer::stopMusic() {
|
||||||
m_mediaPlayer->stop();
|
m_mediaPlayer->stop();
|
||||||
|
m_mediaPlayer->setSource(QUrl(""));
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setVolume(int volume);
|
void setVolume(int volume);
|
||||||
void playMusic(const QString& snd0path);
|
void playMusic(const QString& snd0path, bool loops = true);
|
||||||
void stopMusic();
|
void stopMusic();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1082,7 +1082,11 @@ void CheatsPatches::addCheatsToLayout(const QJsonArray& modsArray, const QJsonAr
|
|||||||
QLabel* creditsLabel = new QLabel();
|
QLabel* creditsLabel = new QLabel();
|
||||||
QString creditsText = tr("Author: ");
|
QString creditsText = tr("Author: ");
|
||||||
if (!creditsArray.isEmpty()) {
|
if (!creditsArray.isEmpty()) {
|
||||||
creditsText += creditsArray[0].toString();
|
QStringList authors;
|
||||||
|
for (const QJsonValue& credit : creditsArray) {
|
||||||
|
authors << credit.toString();
|
||||||
|
}
|
||||||
|
creditsText += authors.join(", ");
|
||||||
}
|
}
|
||||||
creditsLabel->setText(creditsText);
|
creditsLabel->setText(creditsText);
|
||||||
creditsLabel->setAlignment(Qt::AlignLeft);
|
creditsLabel->setAlignment(Qt::AlignLeft);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTextEdit>
|
#include <QTextBrowser>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <common/config.h>
|
#include <common/config.h>
|
||||||
#include <common/path_util.h>
|
#include <common/path_util.h>
|
||||||
@ -247,7 +247,7 @@ void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate,
|
|||||||
bool latest_isWIP = latestRev.endsWith("WIP", Qt::CaseInsensitive);
|
bool latest_isWIP = latestRev.endsWith("WIP", Qt::CaseInsensitive);
|
||||||
if (current_isWIP && !latest_isWIP) {
|
if (current_isWIP && !latest_isWIP) {
|
||||||
} else {
|
} else {
|
||||||
QTextEdit* textField = new QTextEdit(this);
|
QTextBrowser* textField = new QTextBrowser(this);
|
||||||
textField->setReadOnly(true);
|
textField->setReadOnly(true);
|
||||||
textField->setFixedWidth(500);
|
textField->setFixedWidth(500);
|
||||||
textField->setFixedHeight(200);
|
textField->setFixedHeight(200);
|
||||||
@ -349,8 +349,28 @@ void CheckUpdate::requestChangelog(const QString& currentRev, const QString& lat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the text field with the changelog
|
// Update the text field with the changelog
|
||||||
QTextEdit* textField = findChild<QTextEdit*>();
|
QTextBrowser* textField = findChild<QTextBrowser*>();
|
||||||
if (textField) {
|
if (textField) {
|
||||||
|
QRegularExpression re("\\(\\#(\\d+)\\)");
|
||||||
|
QString newChanges;
|
||||||
|
int lastIndex = 0;
|
||||||
|
QRegularExpressionMatchIterator i = re.globalMatch(changes);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
QRegularExpressionMatch match = i.next();
|
||||||
|
newChanges += changes.mid(lastIndex, match.capturedStart() - lastIndex);
|
||||||
|
QString num = match.captured(1);
|
||||||
|
newChanges +=
|
||||||
|
QString(
|
||||||
|
"(<a "
|
||||||
|
"href=\"https://github.com/shadps4-emu/shadPS4/pull/%1\">#%1</a>)")
|
||||||
|
.arg(num);
|
||||||
|
lastIndex = match.capturedEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
newChanges += changes.mid(lastIndex);
|
||||||
|
changes = newChanges;
|
||||||
|
|
||||||
|
textField->setOpenExternalLinks(true);
|
||||||
textField->setHtml("<h2>" + tr("Changes") + ":</h2>" + changes);
|
textField->setHtml("<h2>" + tr("Changes") + ":</h2>" + changes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,12 +78,22 @@ void CompatibilityInfoClass::UpdateCompatibilityDatabase(QWidget* parent, bool f
|
|||||||
CompatibilityEntry CompatibilityInfoClass::GetCompatibilityInfo(const std::string& serial) {
|
CompatibilityEntry CompatibilityInfoClass::GetCompatibilityInfo(const std::string& serial) {
|
||||||
QString title_id = QString::fromStdString(serial);
|
QString title_id = QString::fromStdString(serial);
|
||||||
if (m_compatibility_database.contains(title_id)) {
|
if (m_compatibility_database.contains(title_id)) {
|
||||||
{
|
|
||||||
QJsonObject compatibility_obj = m_compatibility_database[title_id].toObject();
|
QJsonObject compatibility_obj = m_compatibility_database[title_id].toObject();
|
||||||
for (int os_int = 0; os_int != static_cast<int>(OSType::Last); os_int++) {
|
|
||||||
QString os_string = OSTypeToString.at(static_cast<OSType>(os_int));
|
// Set current_os automatically
|
||||||
if (compatibility_obj.contains(os_string)) {
|
QString current_os;
|
||||||
QJsonObject compatibility_entry_obj = compatibility_obj[os_string].toObject();
|
#ifdef Q_OS_WIN
|
||||||
|
current_os = "os-windows";
|
||||||
|
#elif defined(Q_OS_MAC)
|
||||||
|
current_os = "os-macOS";
|
||||||
|
#elif defined(Q_OS_LINUX)
|
||||||
|
current_os = "os-linux";
|
||||||
|
#else
|
||||||
|
current_os = "os-unknown";
|
||||||
|
#endif
|
||||||
|
// Check if the game is compatible with the current operating system
|
||||||
|
if (compatibility_obj.contains(current_os)) {
|
||||||
|
QJsonObject compatibility_entry_obj = compatibility_obj[current_os].toObject();
|
||||||
CompatibilityEntry compatibility_entry{
|
CompatibilityEntry compatibility_entry{
|
||||||
LabelToCompatStatus.at(compatibility_entry_obj["status"].toString()),
|
LabelToCompatStatus.at(compatibility_entry_obj["status"].toString()),
|
||||||
compatibility_entry_obj["version"].toString(),
|
compatibility_entry_obj["version"].toString(),
|
||||||
@ -92,11 +102,14 @@ CompatibilityEntry CompatibilityInfoClass::GetCompatibilityInfo(const std::strin
|
|||||||
compatibility_entry_obj["url"].toString(),
|
compatibility_entry_obj["url"].toString(),
|
||||||
compatibility_entry_obj["issue_number"].toString()};
|
compatibility_entry_obj["issue_number"].toString()};
|
||||||
return compatibility_entry;
|
return compatibility_entry;
|
||||||
}
|
} else {
|
||||||
}
|
// If there is no entry for the current operating system, return "Unknown"
|
||||||
|
return CompatibilityEntry{CompatibilityStatus::Unknown, "",
|
||||||
|
QDateTime::currentDateTime(), "", 0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If title not found, return "Unknown"
|
||||||
return CompatibilityEntry{CompatibilityStatus::Unknown, "", QDateTime::currentDateTime(), "",
|
return CompatibilityEntry{CompatibilityStatus::Unknown, "", QDateTime::currentDateTime(), "",
|
||||||
0};
|
0};
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,11 @@ ControlSettings::ControlSettings(std::shared_ptr<GameInfoClass> game_info_get, Q
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::Save)->setText(tr("Save"));
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::Apply)->setText(tr("Apply"));
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setText(tr("Restore Defaults"));
|
||||||
|
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
|
||||||
|
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close);
|
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close);
|
||||||
|
|
||||||
connect(ui->ProfileComboBox, &QComboBox::currentTextChanged, this, [this] {
|
connect(ui->ProfileComboBox, &QComboBox::currentTextChanged, this, [this] {
|
||||||
@ -100,8 +105,8 @@ void ControlSettings::SaveControllerConfig(bool CloseOnSave) {
|
|||||||
if (count_axis_left_x > 1 | count_axis_left_y > 1 | count_axis_right_x > 1 |
|
if (count_axis_left_x > 1 | count_axis_left_y > 1 | count_axis_right_x > 1 |
|
||||||
count_axis_right_y > 1) {
|
count_axis_right_y > 1) {
|
||||||
QMessageBox::StandardButton nosave;
|
QMessageBox::StandardButton nosave;
|
||||||
nosave = QMessageBox::information(this, "Unable to Save",
|
nosave = QMessageBox::information(this, tr("Unable to Save"),
|
||||||
"Cannot bind axis values more than once");
|
tr("Cannot bind axis values more than once"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ void ScanDirectoryRecursively(const QString& dir, QStringList& filePaths, int cu
|
|||||||
QFileInfoList entries = directory.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
QFileInfoList entries = directory.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
|
|
||||||
for (const auto& entry : entries) {
|
for (const auto& entry : entries) {
|
||||||
if (entry.fileName().endsWith("-UPDATE")) {
|
if (entry.fileName().endsWith("-UPDATE") || entry.fileName().endsWith("-patch")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|