Merge branch 'shadps4-emu:main' into fontlib
12
.gitmodules
vendored
|
@ -1,15 +1,3 @@
|
||||||
[submodule "externals/cryptopp-cmake"]
|
|
||||||
path = externals/cryptopp-cmake
|
|
||||||
url = https://github.com/shadps4-emu/ext-cryptopp-cmake.git
|
|
||||||
shallow = true
|
|
||||||
[submodule "externals/cryptopp"]
|
|
||||||
path = externals/cryptopp
|
|
||||||
url = https://github.com/shadps4-emu/ext-cryptopp.git
|
|
||||||
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
|
||||||
|
|
117
CMakeLists.txt
|
@ -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")
|
||||||
|
|
||||||
|
@ -106,28 +113,74 @@ git_describe(GIT_DESC --always --long --dirty)
|
||||||
git_branch_name(GIT_BRANCH)
|
git_branch_name(GIT_BRANCH)
|
||||||
string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S")
|
string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
message("start git things")
|
||||||
|
|
||||||
# Try to get the upstream remote and branch
|
# Try to get the upstream remote and branch
|
||||||
|
message("check for remote and branch")
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND git rev-parse --abbrev-ref --symbolic-full-name @{u}
|
COMMAND git rev-parse --abbrev-ref --symbolic-full-name @{u}
|
||||||
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
||||||
RESULT_VARIABLE GIT_BRANCH_RESULT
|
RESULT_VARIABLE GIT_REMOTE_RESULT
|
||||||
ERROR_QUIET
|
ERROR_QUIET
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
|
|
||||||
# If there's no upstream set or the command failed, check remote.pushDefault
|
# If there's no upstream set or the command failed, check remote.pushDefault
|
||||||
if (GIT_BRANCH_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||||
|
message("check default push")
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND git config --get remote.pushDefault
|
COMMAND git config --get remote.pushDefault
|
||||||
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
||||||
RESULT_VARIABLE GIT_PUSH_DEFAULT_RESULT
|
RESULT_VARIABLE GIT_REMOTE_RESULT
|
||||||
ERROR_QUIET
|
ERROR_QUIET
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
# If remote.pushDefault is not set or fails, default to origin
|
|
||||||
if (GIT_PUSH_DEFAULT_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
# If running in GitHub Actions and the above fails
|
||||||
set(GIT_REMOTE_NAME "origin")
|
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||||
|
message("check github")
|
||||||
|
set(GIT_REMOTE_NAME "origin")
|
||||||
|
|
||||||
|
# Retrieve environment variables
|
||||||
|
if (DEFINED ENV{GITHUB_HEAD_REF} AND NOT "$ENV{GITHUB_HEAD_REF}" STREQUAL "")
|
||||||
|
message("github head ref: $ENV{GITHUB_HEAD_REF}")
|
||||||
|
set(GITHUB_HEAD_REF "$ENV{GITHUB_HEAD_REF}")
|
||||||
|
else()
|
||||||
|
set(GITHUB_HEAD_REF "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (DEFINED ENV{GITHUB_REF} AND NOT "$ENV{GITHUB_REF}" STREQUAL "")
|
||||||
|
message("github ref: $ENV{GITHUB_REF}")
|
||||||
|
string(REGEX REPLACE "^refs/[^/]*/" "" GITHUB_BRANCH "$ENV{GITHUB_REF}")
|
||||||
|
string(REGEX MATCH "refs/pull/([0-9]+)/merge" MATCHED_REF "$ENV{GITHUB_REF}")
|
||||||
|
if (MATCHED_REF)
|
||||||
|
set(PR_NUMBER "${CMAKE_MATCH_1}")
|
||||||
|
set(GITHUB_BRANCH "")
|
||||||
|
message("PR number: ${PR_NUMBER}")
|
||||||
|
else()
|
||||||
|
set(PR_NUMBER "")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(GITHUB_BRANCH "")
|
||||||
|
set(PR_NUMBER "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT "${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_HEAD_REF}" STREQUAL "")
|
||||||
|
set(GIT_BRANCH "pr-${PR_NUMBER}-${GITHUB_HEAD_REF}")
|
||||||
|
elseif (NOT "${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_BRANCH}" STREQUAL "")
|
||||||
|
set(GIT_BRANCH "pr-${PR_NUMBER}-${GITHUB_BRANCH}")
|
||||||
|
elseif (NOT "${PR_NUMBER}" STREQUAL "")
|
||||||
|
set(GIT_BRANCH "pr-${PR_NUMBER}")
|
||||||
|
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_HEAD_REF}" STREQUAL "")
|
||||||
|
set(GIT_BRANCH "${GITHUB_HEAD_REF}")
|
||||||
|
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_BRANCH}" STREQUAL "")
|
||||||
|
set(GIT_BRANCH "${GITHUB_BRANCH}")
|
||||||
|
elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_REF}" STREQUAL "")
|
||||||
|
set(GIT_BRANCH "${GITHUB_REF}")
|
||||||
|
else()
|
||||||
|
message("couldn't find branch")
|
||||||
|
set(GIT_BRANCH "detached-head")
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
# Extract remote name if the output contains a remote/branch format
|
# Extract remote name if the output contains a remote/branch format
|
||||||
|
@ -141,6 +194,7 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Get remote link
|
# Get remote link
|
||||||
|
message("getting remote link")
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
|
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
|
||||||
OUTPUT_VARIABLE GIT_REMOTE_URL
|
OUTPUT_VARIABLE GIT_REMOTE_URL
|
||||||
|
@ -149,6 +203,8 @@ execute_process(
|
||||||
|
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
|
||||||
|
|
||||||
|
message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}")
|
||||||
|
|
||||||
find_package(Boost 1.84.0 CONFIG)
|
find_package(Boost 1.84.0 CONFIG)
|
||||||
find_package(FFmpeg 5.1.2 MODULE)
|
find_package(FFmpeg 5.1.2 MODULE)
|
||||||
find_package(fmt 10.2.0 CONFIG)
|
find_package(fmt 10.2.0 CONFIG)
|
||||||
|
@ -278,6 +334,8 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
||||||
src/core/libraries/kernel/threads/thread_state.h
|
src/core/libraries/kernel/threads/thread_state.h
|
||||||
src/core/libraries/kernel/process.cpp
|
src/core/libraries/kernel/process.cpp
|
||||||
src/core/libraries/kernel/process.h
|
src/core/libraries/kernel/process.h
|
||||||
|
src/core/libraries/kernel/debug.cpp
|
||||||
|
src/core/libraries/kernel/debug.h
|
||||||
src/core/libraries/kernel/equeue.cpp
|
src/core/libraries/kernel/equeue.cpp
|
||||||
src/core/libraries/kernel/equeue.h
|
src/core/libraries/kernel/equeue.h
|
||||||
src/core/libraries/kernel/file_system.cpp
|
src/core/libraries/kernel/file_system.cpp
|
||||||
|
@ -371,6 +429,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
|
||||||
|
@ -550,6 +626,7 @@ set(COMMON src/common/logging/backend.cpp
|
||||||
src/common/logging/text_formatter.cpp
|
src/common/logging/text_formatter.cpp
|
||||||
src/common/logging/text_formatter.h
|
src/common/logging/text_formatter.h
|
||||||
src/common/logging/types.h
|
src/common/logging/types.h
|
||||||
|
src/common/aes.h
|
||||||
src/common/alignment.h
|
src/common/alignment.h
|
||||||
src/common/arch.h
|
src/common/arch.h
|
||||||
src/common/assert.cpp
|
src/common/assert.cpp
|
||||||
|
@ -581,6 +658,7 @@ set(COMMON src/common/logging/backend.cpp
|
||||||
src/common/polyfill_thread.h
|
src/common/polyfill_thread.h
|
||||||
src/common/rdtsc.cpp
|
src/common/rdtsc.cpp
|
||||||
src/common/rdtsc.h
|
src/common/rdtsc.h
|
||||||
|
src/common/sha1.h
|
||||||
src/common/signal_context.h
|
src/common/signal_context.h
|
||||||
src/common/signal_context.cpp
|
src/common/signal_context.cpp
|
||||||
src/common/singleton.h
|
src/common/singleton.h
|
||||||
|
@ -620,9 +698,6 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||||
src/core/aerolib/aerolib.h
|
src/core/aerolib/aerolib.h
|
||||||
src/core/address_space.cpp
|
src/core/address_space.cpp
|
||||||
src/core/address_space.h
|
src/core/address_space.h
|
||||||
src/core/crypto/crypto.cpp
|
|
||||||
src/core/crypto/crypto.h
|
|
||||||
src/core/crypto/keys.h
|
|
||||||
src/core/devices/base_device.cpp
|
src/core/devices/base_device.cpp
|
||||||
src/core/devices/base_device.h
|
src/core/devices/base_device.h
|
||||||
src/core/devices/ioccom.h
|
src/core/devices/ioccom.h
|
||||||
|
@ -640,10 +715,6 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||||
src/core/devices/srandom_device.cpp
|
src/core/devices/srandom_device.cpp
|
||||||
src/core/devices/srandom_device.h
|
src/core/devices/srandom_device.h
|
||||||
src/core/file_format/pfs.h
|
src/core/file_format/pfs.h
|
||||||
src/core/file_format/pkg.cpp
|
|
||||||
src/core/file_format/pkg.h
|
|
||||||
src/core/file_format/pkg_type.cpp
|
|
||||||
src/core/file_format/pkg_type.h
|
|
||||||
src/core/file_format/psf.cpp
|
src/core/file_format/psf.cpp
|
||||||
src/core/file_format/psf.h
|
src/core/file_format/psf.h
|
||||||
src/core/file_format/playgo_chunk.cpp
|
src/core/file_format/playgo_chunk.cpp
|
||||||
|
@ -652,8 +723,6 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||||
src/core/file_format/trp.h
|
src/core/file_format/trp.h
|
||||||
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.h
|
|
||||||
src/core/loader/dwarf.cpp
|
src/core/loader/dwarf.cpp
|
||||||
src/core/loader/dwarf.h
|
src/core/loader/dwarf.h
|
||||||
src/core/loader/elf.cpp
|
src/core/loader/elf.cpp
|
||||||
|
@ -770,6 +839,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
|
||||||
|
@ -942,10 +1012,6 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
|
||||||
src/qt_gui/game_grid_frame.h
|
src/qt_gui/game_grid_frame.h
|
||||||
src/qt_gui/game_install_dialog.cpp
|
src/qt_gui/game_install_dialog.cpp
|
||||||
src/qt_gui/game_install_dialog.h
|
src/qt_gui/game_install_dialog.h
|
||||||
src/qt_gui/install_dir_select.cpp
|
|
||||||
src/qt_gui/install_dir_select.h
|
|
||||||
src/qt_gui/pkg_viewer.cpp
|
|
||||||
src/qt_gui/pkg_viewer.h
|
|
||||||
src/qt_gui/trophy_viewer.cpp
|
src/qt_gui/trophy_viewer.cpp
|
||||||
src/qt_gui/trophy_viewer.h
|
src/qt_gui/trophy_viewer.h
|
||||||
src/qt_gui/elf_viewer.cpp
|
src/qt_gui/elf_viewer.cpp
|
||||||
|
@ -1050,12 +1116,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)
|
||||||
|
@ -1126,7 +1186,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
|
||||||
|
|
|
@ -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",
|
||||||
|
@ -48,8 +49,10 @@ path = [
|
||||||
"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",
|
||||||
|
|
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>
|
||||||
|
|
Before Width: | Height: | Size: 658 KiB |
|
@ -13,7 +13,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
- [**RAM**](#ram)
|
- [**RAM**](#ram)
|
||||||
- [**OS**](#os)
|
- [**OS**](#os)
|
||||||
- [**Have the latest WIP version**](#how-to-run-the-latest-work-in-progress-builds-of-shadps4)
|
- [**Have the latest WIP version**](#how-to-run-the-latest-work-in-progress-builds-of-shadps4)
|
||||||
- [**Install PKG files (Games and Updates)**](#install-pkg-files)
|
|
||||||
- [**Configure the emulator**](#configure-the-emulator)
|
- [**Configure the emulator**](#configure-the-emulator)
|
||||||
|
|
||||||
## Minimum PC requirements
|
## Minimum PC requirements
|
||||||
|
@ -48,13 +47,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
2. Once downloaded, extract to its own folder, and run shadPS4's executable from the extracted folder.
|
2. Once downloaded, extract to its own folder, and run shadPS4's executable from the extracted folder.
|
||||||
|
|
||||||
3. Upon first launch, shadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that shadPS4 can use to install your PKG files to.
|
3. Upon first launch, shadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that contains your dumped games.
|
||||||
|
|
||||||
## Install PKG files
|
|
||||||
|
|
||||||
To install PKG files (game and updates), you will need the Qt application (with UI). You will have to go to "File" then to "Install Packages (PKG)", a window will open then you will have to select the files. You can install multiple PKG files at once. Once finished, the game should appear in the application.
|
|
||||||
|
|
||||||
<img src="https://github.com/shadps4-emu/shadPS4/blob/main/documents/Quickstart/2.png" width="800">
|
|
||||||
|
|
||||||
## Configure the emulator
|
## Configure the emulator
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ Now run the emulator. If Qt was enabled at configure time:
|
||||||
./build/shadps4
|
./build/shadps4
|
||||||
```
|
```
|
||||||
|
|
||||||
Otherwise, specify the path to your PKG's boot file:
|
Otherwise, specify the path to your game's boot file:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./build/shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin
|
./build/shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin
|
||||||
|
|
19
externals/CMakeLists.txt
vendored
|
@ -26,24 +26,7 @@ if (NOT TARGET fmt::fmt)
|
||||||
add_subdirectory(fmt)
|
add_subdirectory(fmt)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND MSVC)
|
# FFmpeg
|
||||||
# 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
|
|
||||||
if (NOT TARGET cryptopp::cryptopp)
|
|
||||||
set(CRYPTOPP_INSTALL OFF)
|
|
||||||
set(CRYPTOPP_BUILD_TESTING OFF)
|
|
||||||
set(CRYPTOPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cryptopp)
|
|
||||||
add_subdirectory(cryptopp-cmake)
|
|
||||||
file(COPY cryptopp DESTINATION cryptopp FILES_MATCHING PATTERN "*.h")
|
|
||||||
# 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")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (NOT TARGET FFmpeg::ffmpeg)
|
if (NOT TARGET FFmpeg::ffmpeg)
|
||||||
add_subdirectory(ffmpeg-core)
|
add_subdirectory(ffmpeg-core)
|
||||||
add_library(FFmpeg::ffmpeg ALIAS ffmpeg)
|
add_library(FFmpeg::ffmpeg ALIAS ffmpeg)
|
||||||
|
|
1
externals/cryptopp
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 60f81a77e0c9a0e7ffc1ca1bc438ddfa2e43b78e
|
|
1
externals/cryptopp-cmake
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 2c384c28265a93358a2455e610e76393358794df
|
|
1
externals/cryptoppwin
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit bc3441dd2d6a9728e747dc0180bc8b9065a2923c
|
|
1195
src/common/aes.h
Normal file
|
@ -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;
|
||||||
|
@ -40,7 +41,7 @@ static u32 screenWidth = 1280;
|
||||||
static u32 screenHeight = 720;
|
static u32 screenHeight = 720;
|
||||||
static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto select
|
static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto select
|
||||||
static std::string logFilter;
|
static std::string logFilter;
|
||||||
static std::string logType = "async";
|
static std::string logType = "sync";
|
||||||
static std::string userName = "shadPS4";
|
static std::string userName = "shadPS4";
|
||||||
static std::string updateChannel;
|
static std::string updateChannel;
|
||||||
static std::string chooseHomeTab;
|
static std::string chooseHomeTab;
|
||||||
|
@ -74,14 +75,14 @@ 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};
|
||||||
static bool separateupdatefolder = false;
|
|
||||||
static bool compatibilityData = false;
|
static bool compatibilityData = false;
|
||||||
static bool checkCompatibilityOnStartup = false;
|
static bool checkCompatibilityOnStartup = false;
|
||||||
static std::string trophyKey;
|
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;
|
||||||
|
@ -96,7 +97,6 @@ u32 m_slider_pos_grid = 0;
|
||||||
u32 m_table_mode = 0;
|
u32 m_table_mode = 0;
|
||||||
u32 m_window_size_W = 1280;
|
u32 m_window_size_W = 1280;
|
||||||
u32 m_window_size_H = 720;
|
u32 m_window_size_H = 720;
|
||||||
std::vector<std::string> m_pkg_viewer;
|
|
||||||
std::vector<std::string> m_elf_viewer;
|
std::vector<std::string> m_elf_viewer;
|
||||||
std::vector<std::string> m_recent_files;
|
std::vector<std::string> m_recent_files;
|
||||||
std::string emulator_language = "en_US";
|
std::string emulator_language = "en_US";
|
||||||
|
@ -105,6 +105,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
|
||||||
|
@ -166,10 +167,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;
|
||||||
}
|
}
|
||||||
|
@ -338,10 +351,6 @@ void setVkGuestMarkersEnabled(bool enable) {
|
||||||
vkGuestMarkers = enable;
|
vkGuestMarkers = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getSeparateUpdateEnabled() {
|
|
||||||
return separateupdatefolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getCompatibilityEnabled() {
|
bool getCompatibilityEnabled() {
|
||||||
return compatibilityData;
|
return compatibilityData;
|
||||||
}
|
}
|
||||||
|
@ -421,6 +430,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;
|
||||||
|
@ -500,10 +512,6 @@ void setIsMotionControlsEnabled(bool use) {
|
||||||
isMotionControlsEnabled = use;
|
isMotionControlsEnabled = use;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSeparateUpdateEnabled(bool use) {
|
|
||||||
separateupdatefolder = use;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCompatibilityEnabled(bool use) {
|
void setCompatibilityEnabled(bool use) {
|
||||||
compatibilityData = use;
|
compatibilityData = use;
|
||||||
}
|
}
|
||||||
|
@ -519,22 +527,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 false;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -571,11 +591,6 @@ void setMainWindowHeight(u32 height) {
|
||||||
m_window_size_H = height;
|
m_window_size_H = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPkgViewer(const std::vector<std::string>& pkgList) {
|
|
||||||
m_pkg_viewer.resize(pkgList.size());
|
|
||||||
m_pkg_viewer = pkgList;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setElfViewer(const std::vector<std::string>& elfList) {
|
void setElfViewer(const std::vector<std::string>& elfList) {
|
||||||
m_elf_viewer.resize(elfList.size());
|
m_elf_viewer.resize(elfList.size());
|
||||||
m_elf_viewer = elfList;
|
m_elf_viewer = elfList;
|
||||||
|
@ -590,8 +605,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) {
|
||||||
|
@ -614,8 +636,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() {
|
||||||
|
@ -658,10 +694,6 @@ u32 getMainWindowHeight() {
|
||||||
return m_window_size_H;
|
return m_window_size_H;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> getPkgViewer() {
|
|
||||||
return m_pkg_viewer;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> getElfViewer() {
|
std::vector<std::string> getElfViewer() {
|
||||||
return m_elf_viewer;
|
return m_elf_viewer;
|
||||||
}
|
}
|
||||||
|
@ -721,6 +753,7 @@ 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 =
|
trophyNotificationDuration =
|
||||||
|
@ -739,7 +772,6 @@ void load(const std::filesystem::path& path) {
|
||||||
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");
|
isSideTrophy = toml::find_or<std::string>(general, "sideTrophy", "right");
|
||||||
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 =
|
||||||
toml::find_or<bool>(general, "checkCompatibilityOnStartup", false);
|
toml::find_or<bool>(general, "checkCompatibilityOnStartup", false);
|
||||||
|
@ -808,9 +840,23 @@ void load(const std::filesystem::path& path) {
|
||||||
m_window_size_H = toml::find_or<int>(gui, "mw_height", 0);
|
m_window_size_H = toml::find_or<int>(gui, "mw_height", 0);
|
||||||
|
|
||||||
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::u8string>>(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", {});
|
||||||
|
@ -820,7 +866,6 @@ void load(const std::filesystem::path& path) {
|
||||||
main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0);
|
main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0);
|
||||||
main_window_geometry_w = toml::find_or<int>(gui, "geometry_w", 0);
|
main_window_geometry_w = toml::find_or<int>(gui, "geometry_w", 0);
|
||||||
main_window_geometry_h = toml::find_or<int>(gui, "geometry_h", 0);
|
main_window_geometry_h = toml::find_or<int>(gui, "geometry_h", 0);
|
||||||
m_pkg_viewer = toml::find_or<std::vector<std::string>>(gui, "pkgDirs", {});
|
|
||||||
m_elf_viewer = toml::find_or<std::vector<std::string>>(gui, "elfDirs", {});
|
m_elf_viewer = toml::find_or<std::vector<std::string>>(gui, "elfDirs", {});
|
||||||
m_recent_files = toml::find_or<std::vector<std::string>>(gui, "recentFiles", {});
|
m_recent_files = toml::find_or<std::vector<std::string>>(gui, "recentFiles", {});
|
||||||
m_table_mode = toml::find_or<int>(gui, "gameTableMode", 0);
|
m_table_mode = toml::find_or<int>(gui, "gameTableMode", 0);
|
||||||
|
@ -853,6 +898,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;
|
||||||
|
|
||||||
|
@ -876,6 +952,7 @@ 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"]["trophyNotificationDuration"] = trophyNotificationDuration;
|
||||||
data["General"]["playBGM"] = playBGM;
|
data["General"]["playBGM"] = playBGM;
|
||||||
|
@ -890,7 +967,6 @@ void save(const std::filesystem::path& path) {
|
||||||
data["General"]["autoUpdate"] = isAutoUpdate;
|
data["General"]["autoUpdate"] = isAutoUpdate;
|
||||||
data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog;
|
data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog;
|
||||||
data["General"]["sideTrophy"] = isSideTrophy;
|
data["General"]["sideTrophy"] = isSideTrophy;
|
||||||
data["General"]["separateUpdateEnabled"] = separateupdatefolder;
|
|
||||||
data["General"]["compatibilityEnabled"] = compatibilityData;
|
data["General"]["compatibilityEnabled"] = compatibilityData;
|
||||||
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
|
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
|
||||||
data["Input"]["cursorState"] = cursorState;
|
data["Input"]["cursorState"] = cursorState;
|
||||||
|
@ -922,14 +998,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;
|
||||||
|
|
||||||
|
@ -940,9 +1039,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -980,10 +1083,12 @@ void saveMainWindow(const std::filesystem::path& path) {
|
||||||
data["GUI"]["geometry_y"] = main_window_geometry_y;
|
data["GUI"]["geometry_y"] = main_window_geometry_y;
|
||||||
data["GUI"]["geometry_w"] = main_window_geometry_w;
|
data["GUI"]["geometry_w"] = main_window_geometry_w;
|
||||||
data["GUI"]["geometry_h"] = main_window_geometry_h;
|
data["GUI"]["geometry_h"] = main_window_geometry_h;
|
||||||
data["GUI"]["pkgDirs"] = m_pkg_viewer;
|
|
||||||
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();
|
||||||
|
@ -992,6 +1097,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;
|
||||||
|
@ -1000,7 +1106,7 @@ void setDefaultValues() {
|
||||||
screenWidth = 1280;
|
screenWidth = 1280;
|
||||||
screenHeight = 720;
|
screenHeight = 720;
|
||||||
logFilter = "";
|
logFilter = "";
|
||||||
logType = "async";
|
logType = "sync";
|
||||||
userName = "shadPS4";
|
userName = "shadPS4";
|
||||||
if (Common::isRelease) {
|
if (Common::isRelease) {
|
||||||
updateChannel = "Release";
|
updateChannel = "Release";
|
||||||
|
@ -1033,7 +1139,6 @@ void setDefaultValues() {
|
||||||
emulator_language = "en_US";
|
emulator_language = "en_US";
|
||||||
m_language = 1;
|
m_language = 1;
|
||||||
gpuId = -1;
|
gpuId = -1;
|
||||||
separateupdatefolder = false;
|
|
||||||
compatibilityData = false;
|
compatibilityData = false;
|
||||||
checkCompatibilityOnStartup = false;
|
checkCompatibilityOnStartup = false;
|
||||||
backgroundImageOpacity = 50;
|
backgroundImageOpacity = 50;
|
||||||
|
|
|
@ -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,13 +26,15 @@ 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();
|
||||||
bool getEnableDiscordRPC();
|
bool getEnableDiscordRPC();
|
||||||
bool getSeparateUpdateEnabled();
|
|
||||||
bool getCompatibilityEnabled();
|
bool getCompatibilityEnabled();
|
||||||
bool getCheckCompatibilityOnStartup();
|
bool getCheckCompatibilityOnStartup();
|
||||||
int getBackgroundImageOpacity();
|
int getBackgroundImageOpacity();
|
||||||
|
@ -97,8 +104,8 @@ void setNeoMode(bool enable);
|
||||||
void setUserName(const std::string& type);
|
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 setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
|
||||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_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);
|
||||||
|
@ -133,8 +140,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);
|
||||||
|
@ -144,7 +152,6 @@ void setSliderPositionGrid(u32 pos);
|
||||||
void setTableMode(u32 mode);
|
void setTableMode(u32 mode);
|
||||||
void setMainWindowWidth(u32 width);
|
void setMainWindowWidth(u32 width);
|
||||||
void setMainWindowHeight(u32 height);
|
void setMainWindowHeight(u32 height);
|
||||||
void setPkgViewer(const std::vector<std::string>& pkgList);
|
|
||||||
void setElfViewer(const std::vector<std::string>& elfList);
|
void setElfViewer(const std::vector<std::string>& elfList);
|
||||||
void setRecentFiles(const std::vector<std::string>& recentFiles);
|
void setRecentFiles(const std::vector<std::string>& recentFiles);
|
||||||
void setEmulatorLanguage(std::string language);
|
void setEmulatorLanguage(std::string language);
|
||||||
|
@ -153,7 +160,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();
|
||||||
|
@ -163,7 +171,6 @@ u32 getSliderPositionGrid();
|
||||||
u32 getTableMode();
|
u32 getTableMode();
|
||||||
u32 getMainWindowWidth();
|
u32 getMainWindowWidth();
|
||||||
u32 getMainWindowHeight();
|
u32 getMainWindowHeight();
|
||||||
std::vector<std::string> getPkgViewer();
|
|
||||||
std::vector<std::string> getElfViewer();
|
std::vector<std::string> getElfViewer();
|
||||||
std::vector<std::string> getRecentFiles();
|
std::vector<std::string> getRecentFiles();
|
||||||
std::string getEmulatorLanguage();
|
std::string getEmulatorLanguage();
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
180
src/common/sha1.h
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
// SPDX-FileCopyrightText: 2012 SAURAV MOHAPATRA <mohaps@gmail.com>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace sha1 {
|
||||||
|
class SHA1 {
|
||||||
|
public:
|
||||||
|
typedef uint32_t digest32_t[5];
|
||||||
|
typedef uint8_t digest8_t[20];
|
||||||
|
inline static uint32_t LeftRotate(uint32_t value, size_t count) {
|
||||||
|
return (value << count) ^ (value >> (32 - count));
|
||||||
|
}
|
||||||
|
SHA1() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
virtual ~SHA1() {}
|
||||||
|
SHA1(const SHA1& s) {
|
||||||
|
*this = s;
|
||||||
|
}
|
||||||
|
const SHA1& operator=(const SHA1& s) {
|
||||||
|
memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t));
|
||||||
|
memcpy(m_block, s.m_block, 64);
|
||||||
|
m_blockByteIndex = s.m_blockByteIndex;
|
||||||
|
m_byteCount = s.m_byteCount;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SHA1& reset() {
|
||||||
|
m_digest[0] = 0x67452301;
|
||||||
|
m_digest[1] = 0xEFCDAB89;
|
||||||
|
m_digest[2] = 0x98BADCFE;
|
||||||
|
m_digest[3] = 0x10325476;
|
||||||
|
m_digest[4] = 0xC3D2E1F0;
|
||||||
|
m_blockByteIndex = 0;
|
||||||
|
m_byteCount = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SHA1& processByte(uint8_t octet) {
|
||||||
|
this->m_block[this->m_blockByteIndex++] = octet;
|
||||||
|
++this->m_byteCount;
|
||||||
|
if (m_blockByteIndex == 64) {
|
||||||
|
this->m_blockByteIndex = 0;
|
||||||
|
processBlock();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SHA1& processBlock(const void* const start, const void* const end) {
|
||||||
|
const uint8_t* begin = static_cast<const uint8_t*>(start);
|
||||||
|
const uint8_t* finish = static_cast<const uint8_t*>(end);
|
||||||
|
while (begin != finish) {
|
||||||
|
processByte(*begin);
|
||||||
|
begin++;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
SHA1& processBytes(const void* const data, size_t len) {
|
||||||
|
const uint8_t* block = static_cast<const uint8_t*>(data);
|
||||||
|
processBlock(block, block + len);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
const uint32_t* getDigest(digest32_t digest) {
|
||||||
|
size_t bitCount = this->m_byteCount * 8;
|
||||||
|
processByte(0x80);
|
||||||
|
if (this->m_blockByteIndex > 56) {
|
||||||
|
while (m_blockByteIndex != 0) {
|
||||||
|
processByte(0);
|
||||||
|
}
|
||||||
|
while (m_blockByteIndex < 56) {
|
||||||
|
processByte(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (m_blockByteIndex < 56) {
|
||||||
|
processByte(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processByte(0);
|
||||||
|
processByte(0);
|
||||||
|
processByte(0);
|
||||||
|
processByte(0);
|
||||||
|
processByte(static_cast<unsigned char>((bitCount >> 24) & 0xFF));
|
||||||
|
processByte(static_cast<unsigned char>((bitCount >> 16) & 0xFF));
|
||||||
|
processByte(static_cast<unsigned char>((bitCount >> 8) & 0xFF));
|
||||||
|
processByte(static_cast<unsigned char>((bitCount) & 0xFF));
|
||||||
|
|
||||||
|
memcpy(digest, m_digest, 5 * sizeof(uint32_t));
|
||||||
|
return digest;
|
||||||
|
}
|
||||||
|
const uint8_t* getDigestBytes(digest8_t digest) {
|
||||||
|
digest32_t d32;
|
||||||
|
getDigest(d32);
|
||||||
|
size_t di = 0;
|
||||||
|
digest[di++] = ((d32[0] >> 24) & 0xFF);
|
||||||
|
digest[di++] = ((d32[0] >> 16) & 0xFF);
|
||||||
|
digest[di++] = ((d32[0] >> 8) & 0xFF);
|
||||||
|
digest[di++] = ((d32[0]) & 0xFF);
|
||||||
|
|
||||||
|
digest[di++] = ((d32[1] >> 24) & 0xFF);
|
||||||
|
digest[di++] = ((d32[1] >> 16) & 0xFF);
|
||||||
|
digest[di++] = ((d32[1] >> 8) & 0xFF);
|
||||||
|
digest[di++] = ((d32[1]) & 0xFF);
|
||||||
|
|
||||||
|
digest[di++] = ((d32[2] >> 24) & 0xFF);
|
||||||
|
digest[di++] = ((d32[2] >> 16) & 0xFF);
|
||||||
|
digest[di++] = ((d32[2] >> 8) & 0xFF);
|
||||||
|
digest[di++] = ((d32[2]) & 0xFF);
|
||||||
|
|
||||||
|
digest[di++] = ((d32[3] >> 24) & 0xFF);
|
||||||
|
digest[di++] = ((d32[3] >> 16) & 0xFF);
|
||||||
|
digest[di++] = ((d32[3] >> 8) & 0xFF);
|
||||||
|
digest[di++] = ((d32[3]) & 0xFF);
|
||||||
|
|
||||||
|
digest[di++] = ((d32[4] >> 24) & 0xFF);
|
||||||
|
digest[di++] = ((d32[4] >> 16) & 0xFF);
|
||||||
|
digest[di++] = ((d32[4] >> 8) & 0xFF);
|
||||||
|
digest[di++] = ((d32[4]) & 0xFF);
|
||||||
|
return digest;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void processBlock() {
|
||||||
|
uint32_t w[80];
|
||||||
|
for (size_t i = 0; i < 16; i++) {
|
||||||
|
w[i] = (m_block[i * 4 + 0] << 24);
|
||||||
|
w[i] |= (m_block[i * 4 + 1] << 16);
|
||||||
|
w[i] |= (m_block[i * 4 + 2] << 8);
|
||||||
|
w[i] |= (m_block[i * 4 + 3]);
|
||||||
|
}
|
||||||
|
for (size_t i = 16; i < 80; i++) {
|
||||||
|
w[i] = LeftRotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t a = m_digest[0];
|
||||||
|
uint32_t b = m_digest[1];
|
||||||
|
uint32_t c = m_digest[2];
|
||||||
|
uint32_t d = m_digest[3];
|
||||||
|
uint32_t e = m_digest[4];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < 80; ++i) {
|
||||||
|
uint32_t f = 0;
|
||||||
|
uint32_t k = 0;
|
||||||
|
|
||||||
|
if (i < 20) {
|
||||||
|
f = (b & c) | (~b & d);
|
||||||
|
k = 0x5A827999;
|
||||||
|
} else if (i < 40) {
|
||||||
|
f = b ^ c ^ d;
|
||||||
|
k = 0x6ED9EBA1;
|
||||||
|
} else if (i < 60) {
|
||||||
|
f = (b & c) | (b & d) | (c & d);
|
||||||
|
k = 0x8F1BBCDC;
|
||||||
|
} else {
|
||||||
|
f = b ^ c ^ d;
|
||||||
|
k = 0xCA62C1D6;
|
||||||
|
}
|
||||||
|
uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i];
|
||||||
|
e = d;
|
||||||
|
d = c;
|
||||||
|
c = LeftRotate(b, 30);
|
||||||
|
b = a;
|
||||||
|
a = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_digest[0] += a;
|
||||||
|
m_digest[1] += b;
|
||||||
|
m_digest[2] += c;
|
||||||
|
m_digest[3] += d;
|
||||||
|
m_digest[4] += e;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
digest32_t m_digest;
|
||||||
|
uint8_t m_block[64];
|
||||||
|
size_t m_blockByteIndex;
|
||||||
|
size_t m_byteCount;
|
||||||
|
};
|
||||||
|
} // namespace sha1
|
|
@ -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
|
||||||
|
|
|
@ -1,215 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#include "crypto.h"
|
|
||||||
|
|
||||||
CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() {
|
|
||||||
CryptoPP::InvertibleRSAFunction params;
|
|
||||||
params.SetPrime1(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime1, 0x80));
|
|
||||||
params.SetPrime2(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime2, 0x80));
|
|
||||||
|
|
||||||
params.SetPublicExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PublicExponent, 4));
|
|
||||||
params.SetPrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PrivateExponent, 0x100));
|
|
||||||
|
|
||||||
params.SetModPrime1PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent1, 0x80));
|
|
||||||
params.SetModPrime2PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent2, 0x80));
|
|
||||||
|
|
||||||
params.SetModulus(CryptoPP::Integer(PkgDerivedKey3Keyset::Modulus, 0x100));
|
|
||||||
params.SetMultiplicativeInverseOfPrime2ModPrime1(
|
|
||||||
CryptoPP::Integer(PkgDerivedKey3Keyset::Coefficient, 0x80));
|
|
||||||
|
|
||||||
CryptoPP::RSA::PrivateKey privateKey(params);
|
|
||||||
|
|
||||||
return privateKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
CryptoPP::RSA::PrivateKey Crypto::FakeKeyset_keyset_init() {
|
|
||||||
CryptoPP::InvertibleRSAFunction params;
|
|
||||||
params.SetPrime1(CryptoPP::Integer(FakeKeyset::Prime1, 0x80));
|
|
||||||
params.SetPrime2(CryptoPP::Integer(FakeKeyset::Prime2, 0x80));
|
|
||||||
|
|
||||||
params.SetPublicExponent(CryptoPP::Integer(FakeKeyset::PublicExponent, 4));
|
|
||||||
params.SetPrivateExponent(CryptoPP::Integer(FakeKeyset::PrivateExponent, 0x100));
|
|
||||||
|
|
||||||
params.SetModPrime1PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent1, 0x80));
|
|
||||||
params.SetModPrime2PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent2, 0x80));
|
|
||||||
|
|
||||||
params.SetModulus(CryptoPP::Integer(FakeKeyset::Modulus, 0x100));
|
|
||||||
params.SetMultiplicativeInverseOfPrime2ModPrime1(
|
|
||||||
CryptoPP::Integer(FakeKeyset::Coefficient, 0x80));
|
|
||||||
|
|
||||||
CryptoPP::RSA::PrivateKey privateKey(params);
|
|
||||||
|
|
||||||
return privateKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
CryptoPP::RSA::PrivateKey Crypto::DebugRifKeyset_init() {
|
|
||||||
CryptoPP::InvertibleRSAFunction params;
|
|
||||||
params.SetPrime1(CryptoPP::Integer(DebugRifKeyset::Prime1, sizeof(DebugRifKeyset::Prime1)));
|
|
||||||
params.SetPrime2(CryptoPP::Integer(DebugRifKeyset::Prime2, sizeof(DebugRifKeyset::Prime2)));
|
|
||||||
|
|
||||||
params.SetPublicExponent(
|
|
||||||
CryptoPP::Integer(DebugRifKeyset::PublicExponent, sizeof(DebugRifKeyset::PublicExponent)));
|
|
||||||
params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset::PrivateExponent,
|
|
||||||
sizeof(DebugRifKeyset::PrivateExponent)));
|
|
||||||
|
|
||||||
params.SetModPrime1PrivateExponent(
|
|
||||||
CryptoPP::Integer(DebugRifKeyset::Exponent1, sizeof(DebugRifKeyset::Exponent1)));
|
|
||||||
params.SetModPrime2PrivateExponent(
|
|
||||||
CryptoPP::Integer(DebugRifKeyset::Exponent2, sizeof(DebugRifKeyset::Exponent2)));
|
|
||||||
|
|
||||||
params.SetModulus(CryptoPP::Integer(DebugRifKeyset::Modulus, sizeof(DebugRifKeyset::Modulus)));
|
|
||||||
params.SetMultiplicativeInverseOfPrime2ModPrime1(
|
|
||||||
CryptoPP::Integer(DebugRifKeyset::Coefficient, sizeof(DebugRifKeyset::Coefficient)));
|
|
||||||
|
|
||||||
CryptoPP::RSA::PrivateKey privateKey(params);
|
|
||||||
|
|
||||||
return privateKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Crypto::RSA2048Decrypt(std::span<CryptoPP::byte, 32> dec_key,
|
|
||||||
std::span<const CryptoPP::byte, 256> ciphertext,
|
|
||||||
bool is_dk3) { // RSAES_PKCS1v15_
|
|
||||||
// Create an RSA decryptor
|
|
||||||
CryptoPP::RSA::PrivateKey privateKey;
|
|
||||||
if (is_dk3) {
|
|
||||||
privateKey = key_pkg_derived_key3_keyset_init();
|
|
||||||
} else {
|
|
||||||
privateKey = FakeKeyset_keyset_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
CryptoPP::RSAES_PKCS1v15_Decryptor rsaDecryptor(privateKey);
|
|
||||||
|
|
||||||
// Allocate memory for the decrypted data
|
|
||||||
std::array<CryptoPP::byte, 256> decrypted;
|
|
||||||
|
|
||||||
// Perform the decryption
|
|
||||||
CryptoPP::AutoSeededRandomPool rng;
|
|
||||||
CryptoPP::DecodingResult result =
|
|
||||||
rsaDecryptor.Decrypt(rng, ciphertext.data(), decrypted.size(), decrypted.data());
|
|
||||||
std::copy(decrypted.begin(), decrypted.begin() + dec_key.size(), dec_key.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Crypto::ivKeyHASH256(std::span<const CryptoPP::byte, 64> cipher_input,
|
|
||||||
std::span<CryptoPP::byte, 32> ivkey_result) {
|
|
||||||
CryptoPP::SHA256 sha256;
|
|
||||||
std::array<CryptoPP::byte, CryptoPP::SHA256::DIGESTSIZE> hashResult;
|
|
||||||
auto array_sink = new CryptoPP::ArraySink(hashResult.data(), CryptoPP::SHA256::DIGESTSIZE);
|
|
||||||
auto filter = new CryptoPP::HashFilter(sha256, array_sink);
|
|
||||||
CryptoPP::ArraySource r(cipher_input.data(), cipher_input.size(), true, filter);
|
|
||||||
std::copy(hashResult.begin(), hashResult.begin() + ivkey_result.size(), ivkey_result.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Crypto::aesCbcCfb128Decrypt(std::span<const CryptoPP::byte, 32> ivkey,
|
|
||||||
std::span<const CryptoPP::byte, 256> ciphertext,
|
|
||||||
std::span<CryptoPP::byte, 256> decrypted) {
|
|
||||||
std::array<CryptoPP::byte, CryptoPP::AES::DEFAULT_KEYLENGTH> key;
|
|
||||||
std::array<CryptoPP::byte, CryptoPP::AES::DEFAULT_KEYLENGTH> iv;
|
|
||||||
|
|
||||||
std::copy(ivkey.begin() + 16, ivkey.begin() + 16 + key.size(), key.begin());
|
|
||||||
std::copy(ivkey.begin(), ivkey.begin() + iv.size(), iv.begin());
|
|
||||||
|
|
||||||
CryptoPP::AES::Decryption aesDecryption(key.data(), CryptoPP::AES::DEFAULT_KEYLENGTH);
|
|
||||||
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
|
|
||||||
cbcDecryption.ProcessData(decrypted.data() + i, ciphertext.data() + i,
|
|
||||||
CryptoPP::AES::BLOCKSIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Crypto::aesCbcCfb128DecryptEntry(std::span<const CryptoPP::byte, 32> ivkey,
|
|
||||||
std::span<CryptoPP::byte> ciphertext,
|
|
||||||
std::span<CryptoPP::byte> decrypted) {
|
|
||||||
std::array<CryptoPP::byte, CryptoPP::AES::DEFAULT_KEYLENGTH> key;
|
|
||||||
std::array<CryptoPP::byte, CryptoPP::AES::DEFAULT_KEYLENGTH> iv;
|
|
||||||
|
|
||||||
std::copy(ivkey.begin() + 16, ivkey.begin() + 16 + key.size(), key.begin());
|
|
||||||
std::copy(ivkey.begin(), ivkey.begin() + iv.size(), iv.begin());
|
|
||||||
|
|
||||||
CryptoPP::AES::Decryption aesDecryption(key.data(), CryptoPP::AES::DEFAULT_KEYLENGTH);
|
|
||||||
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
|
|
||||||
cbcDecryption.ProcessData(decrypted.data() + i, ciphertext.data() + i,
|
|
||||||
CryptoPP::AES::BLOCKSIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Crypto::decryptEFSM(std::span<CryptoPP::byte, 16> trophyKey,
|
|
||||||
std::span<CryptoPP::byte, 16> NPcommID,
|
|
||||||
std::span<CryptoPP::byte, 16> efsmIv, std::span<CryptoPP::byte> ciphertext,
|
|
||||||
std::span<CryptoPP::byte> decrypted) {
|
|
||||||
|
|
||||||
// step 1: Encrypt NPcommID
|
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encrypt;
|
|
||||||
|
|
||||||
std::vector<CryptoPP::byte> trophyIv(16, 0);
|
|
||||||
std::vector<CryptoPP::byte> trpKey(16);
|
|
||||||
|
|
||||||
encrypt.SetKeyWithIV(trophyKey.data(), trophyKey.size(), trophyIv.data());
|
|
||||||
encrypt.ProcessData(trpKey.data(), NPcommID.data(), 16);
|
|
||||||
|
|
||||||
// step 2: decrypt efsm.
|
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decrypt;
|
|
||||||
decrypt.SetKeyWithIV(trpKey.data(), trpKey.size(), efsmIv.data());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
|
|
||||||
decrypt.ProcessData(decrypted.data() + i, ciphertext.data() + i, CryptoPP::AES::BLOCKSIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Crypto::PfsGenCryptoKey(std::span<const CryptoPP::byte, 32> ekpfs,
|
|
||||||
std::span<const CryptoPP::byte, 16> seed,
|
|
||||||
std::span<CryptoPP::byte, 16> dataKey,
|
|
||||||
std::span<CryptoPP::byte, 16> tweakKey) {
|
|
||||||
CryptoPP::HMAC<CryptoPP::SHA256> hmac(ekpfs.data(), ekpfs.size());
|
|
||||||
|
|
||||||
CryptoPP::SecByteBlock d(20); // Use Crypto++ SecByteBlock for better memory management
|
|
||||||
|
|
||||||
// Copy the bytes of 'index' to the 'd' array
|
|
||||||
uint32_t index = 1;
|
|
||||||
std::memcpy(d, &index, sizeof(uint32_t));
|
|
||||||
|
|
||||||
// Copy the bytes of 'seed' to the 'd' array starting from index 4
|
|
||||||
std::memcpy(d + sizeof(uint32_t), seed.data(), seed.size());
|
|
||||||
|
|
||||||
// Allocate memory for 'u64' using new
|
|
||||||
std::vector<CryptoPP::byte> data_tweak_key(hmac.DigestSize());
|
|
||||||
|
|
||||||
// Calculate the HMAC
|
|
||||||
hmac.CalculateDigest(data_tweak_key.data(), d, d.size());
|
|
||||||
std::copy(data_tweak_key.begin(), data_tweak_key.begin() + dataKey.size(), tweakKey.begin());
|
|
||||||
std::copy(data_tweak_key.begin() + tweakKey.size(),
|
|
||||||
data_tweak_key.begin() + tweakKey.size() + dataKey.size(), dataKey.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Crypto::decryptPFS(std::span<const CryptoPP::byte, 16> dataKey,
|
|
||||||
std::span<const CryptoPP::byte, 16> tweakKey, std::span<const u8> src_image,
|
|
||||||
std::span<CryptoPP::byte> dst_image, u64 sector) {
|
|
||||||
// Start at 0x10000 to keep the header when decrypting the whole pfs_image.
|
|
||||||
for (int i = 0; i < src_image.size(); i += 0x1000) {
|
|
||||||
const u64 current_sector = sector + (i / 0x1000);
|
|
||||||
CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption encrypt(tweakKey.data(), tweakKey.size());
|
|
||||||
CryptoPP::ECB_Mode<CryptoPP::AES>::Decryption decrypt(dataKey.data(), dataKey.size());
|
|
||||||
|
|
||||||
std::array<CryptoPP::byte, 16> tweak{};
|
|
||||||
std::array<CryptoPP::byte, 16> encryptedTweak;
|
|
||||||
std::array<CryptoPP::byte, 16> xorBuffer;
|
|
||||||
std::memcpy(tweak.data(), ¤t_sector, sizeof(u64));
|
|
||||||
|
|
||||||
// Encrypt the tweak for each sector.
|
|
||||||
encrypt.ProcessData(encryptedTweak.data(), tweak.data(), 16);
|
|
||||||
|
|
||||||
for (int plaintextOffset = 0; plaintextOffset < 0x1000; plaintextOffset += 16) {
|
|
||||||
xtsXorBlock(xorBuffer.data(), src_image.data() + i + plaintextOffset,
|
|
||||||
encryptedTweak.data()); // x, c, t
|
|
||||||
decrypt.ProcessData(xorBuffer.data(), xorBuffer.data(), 16); // x, x
|
|
||||||
xtsXorBlock(dst_image.data() + i + plaintextOffset, xorBuffer.data(),
|
|
||||||
encryptedTweak.data()); //(p) c, x , t
|
|
||||||
xtsMult(encryptedTweak);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <span>
|
|
||||||
#include <cryptopp/aes.h>
|
|
||||||
#include <cryptopp/filters.h>
|
|
||||||
#include <cryptopp/modes.h>
|
|
||||||
#include <cryptopp/oaep.h>
|
|
||||||
#include <cryptopp/osrng.h>
|
|
||||||
#include <cryptopp/rsa.h>
|
|
||||||
#include <cryptopp/sha.h>
|
|
||||||
|
|
||||||
#include "common/types.h"
|
|
||||||
#include "keys.h"
|
|
||||||
|
|
||||||
class Crypto {
|
|
||||||
public:
|
|
||||||
CryptoPP::RSA::PrivateKey key_pkg_derived_key3_keyset_init();
|
|
||||||
CryptoPP::RSA::PrivateKey FakeKeyset_keyset_init();
|
|
||||||
CryptoPP::RSA::PrivateKey DebugRifKeyset_init();
|
|
||||||
|
|
||||||
void RSA2048Decrypt(std::span<CryptoPP::byte, 32> dk3,
|
|
||||||
std::span<const CryptoPP::byte, 256> ciphertext,
|
|
||||||
bool is_dk3); // RSAES_PKCS1v15_
|
|
||||||
void ivKeyHASH256(std::span<const CryptoPP::byte, 64> cipher_input,
|
|
||||||
std::span<CryptoPP::byte, 32> ivkey_result);
|
|
||||||
void aesCbcCfb128Decrypt(std::span<const CryptoPP::byte, 32> ivkey,
|
|
||||||
std::span<const CryptoPP::byte, 256> ciphertext,
|
|
||||||
std::span<CryptoPP::byte, 256> decrypted);
|
|
||||||
void aesCbcCfb128DecryptEntry(std::span<const CryptoPP::byte, 32> ivkey,
|
|
||||||
std::span<CryptoPP::byte> ciphertext,
|
|
||||||
std::span<CryptoPP::byte> decrypted);
|
|
||||||
void decryptEFSM(std::span<CryptoPP::byte, 16> trophyKey,
|
|
||||||
std::span<CryptoPP::byte, 16> NPcommID, std::span<CryptoPP::byte, 16> efsmIv,
|
|
||||||
std::span<CryptoPP::byte> ciphertext, std::span<CryptoPP::byte> decrypted);
|
|
||||||
void PfsGenCryptoKey(std::span<const CryptoPP::byte, 32> ekpfs,
|
|
||||||
std::span<const CryptoPP::byte, 16> seed,
|
|
||||||
std::span<CryptoPP::byte, 16> dataKey,
|
|
||||||
std::span<CryptoPP::byte, 16> tweakKey);
|
|
||||||
void decryptPFS(std::span<const CryptoPP::byte, 16> dataKey,
|
|
||||||
std::span<const CryptoPP::byte, 16> tweakKey, std::span<const u8> src_image,
|
|
||||||
std::span<CryptoPP::byte> dst_image, u64 sector);
|
|
||||||
|
|
||||||
void xtsXorBlock(CryptoPP::byte* x, const CryptoPP::byte* a, const CryptoPP::byte* b) {
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
x[i] = a[i] ^ b[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void xtsMult(std::span<CryptoPP::byte, 16> encryptedTweak) {
|
|
||||||
int feedback = 0;
|
|
||||||
for (int k = 0; k < encryptedTweak.size(); k++) {
|
|
||||||
const auto tmp = (encryptedTweak[k] >> 7) & 1;
|
|
||||||
encryptedTweak[k] = ((encryptedTweak[k] << 1) + feedback) & 0xFF;
|
|
||||||
feedback = tmp;
|
|
||||||
}
|
|
||||||
if (feedback != 0) {
|
|
||||||
encryptedTweak[0] ^= 0x87;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,305 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <cryptopp/rsa.h>
|
|
||||||
|
|
||||||
class FakeKeyset {
|
|
||||||
public:
|
|
||||||
// Constructor
|
|
||||||
static constexpr CryptoPP::byte Exponent1[] = {
|
|
||||||
0x6D, 0x48, 0xE0, 0x54, 0x40, 0x25, 0xC8, 0x41, 0x29, 0x52, 0x42, 0x27, 0xEB, 0xD2, 0xC7,
|
|
||||||
0xAB, 0x6B, 0x9C, 0x27, 0x0A, 0xB4, 0x1F, 0x94, 0x4E, 0xFA, 0x42, 0x1D, 0xB7, 0xBC, 0xB9,
|
|
||||||
0xAE, 0xBC, 0x04, 0x6F, 0x75, 0x8F, 0x10, 0x5F, 0x89, 0xAC, 0xAB, 0x9C, 0xD2, 0xFA, 0xE6,
|
|
||||||
0xA4, 0x13, 0x83, 0x68, 0xD4, 0x56, 0x38, 0xFE, 0xE5, 0x2B, 0x78, 0x44, 0x9C, 0x34, 0xE6,
|
|
||||||
0x5A, 0xA0, 0xBE, 0x05, 0x70, 0xAD, 0x15, 0xC3, 0x2D, 0x31, 0xAC, 0x97, 0x5D, 0x88, 0xFC,
|
|
||||||
0xC1, 0x62, 0x3D, 0xE2, 0xED, 0x11, 0xDB, 0xB6, 0x9E, 0xFC, 0x5A, 0x5A, 0x03, 0xF6, 0xCF,
|
|
||||||
0x08, 0xD4, 0x5D, 0x90, 0xC9, 0x2A, 0xB9, 0x9B, 0xCF, 0xC8, 0x1A, 0x65, 0xF3, 0x5B, 0xE8,
|
|
||||||
0x7F, 0xCF, 0xA5, 0xA6, 0x4C, 0x5C, 0x2A, 0x12, 0x0F, 0x92, 0xA5, 0xE3, 0xF0, 0x17, 0x1E,
|
|
||||||
0x9A, 0x97, 0x45, 0x86, 0xFD, 0xDB, 0x54, 0x25};
|
|
||||||
// exponent2 = d mod (q - 1)
|
|
||||||
static constexpr CryptoPP::byte Exponent2[] = {
|
|
||||||
0x2A, 0x51, 0xCE, 0x02, 0x44, 0x28, 0x50, 0xE8, 0x30, 0x20, 0x7C, 0x9C, 0x55, 0xBF, 0x60,
|
|
||||||
0x39, 0xBC, 0xD1, 0xF0, 0xE7, 0x68, 0xF8, 0x08, 0x5B, 0x61, 0x1F, 0xA7, 0xBF, 0xD0, 0xE8,
|
|
||||||
0x8B, 0xB5, 0xB1, 0xD5, 0xD9, 0x16, 0xAC, 0x75, 0x0C, 0x6D, 0xF2, 0xE0, 0xB5, 0x97, 0x75,
|
|
||||||
0xD2, 0x68, 0x16, 0x1F, 0x00, 0x7D, 0x8B, 0x17, 0xE8, 0x78, 0x48, 0x41, 0x71, 0x2B, 0x18,
|
|
||||||
0x96, 0x80, 0x11, 0xDB, 0x68, 0x39, 0x9C, 0xD6, 0xE0, 0x72, 0x42, 0x86, 0xF0, 0x1B, 0x16,
|
|
||||||
0x0D, 0x3E, 0x12, 0x94, 0x3D, 0x25, 0xA8, 0xA9, 0x30, 0x9E, 0x54, 0x5A, 0xD6, 0x36, 0x6C,
|
|
||||||
0xD6, 0x8C, 0x20, 0x62, 0x8F, 0xA1, 0x6B, 0x1F, 0x7C, 0x6D, 0xB2, 0xB1, 0xC1, 0x2E, 0xAD,
|
|
||||||
0x36, 0x02, 0x9C, 0x3A, 0xCA, 0x2F, 0x09, 0xD2, 0x45, 0x9E, 0xEB, 0xF2, 0xBC, 0x6C, 0xAA,
|
|
||||||
0x3B, 0x3E, 0x90, 0xBC, 0x38, 0x67, 0x35, 0x4D};
|
|
||||||
// e
|
|
||||||
static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1};
|
|
||||||
// (InverseQ)(q) = 1 mod p
|
|
||||||
static constexpr CryptoPP::byte Coefficient[] = {
|
|
||||||
0x0B, 0x67, 0x1C, 0x0D, 0x6C, 0x57, 0xD3, 0xE7, 0x05, 0x65, 0x94, 0x31, 0x56, 0x55, 0xFD,
|
|
||||||
0x28, 0x08, 0xFA, 0x05, 0x8A, 0xCC, 0x55, 0x39, 0x61, 0x97, 0x63, 0xA0, 0x16, 0x27, 0x3D,
|
|
||||||
0xED, 0xC1, 0x16, 0x40, 0x2A, 0x12, 0xEA, 0x6F, 0xD9, 0xD8, 0x58, 0x56, 0xA8, 0x56, 0x8B,
|
|
||||||
0x0D, 0x38, 0x5E, 0x1E, 0x80, 0x3B, 0x5F, 0x40, 0x80, 0x6F, 0x62, 0x4F, 0x28, 0xA2, 0x69,
|
|
||||||
0xF3, 0xD3, 0xF7, 0xFD, 0xB2, 0xC3, 0x52, 0x43, 0x20, 0x92, 0x9D, 0x97, 0x8D, 0xA0, 0x15,
|
|
||||||
0x07, 0x15, 0x6E, 0xA4, 0x0D, 0x56, 0xD3, 0x37, 0x1A, 0xC4, 0x9E, 0xDF, 0x02, 0x49, 0xB8,
|
|
||||||
0x0A, 0x84, 0x62, 0xF5, 0xFA, 0xB9, 0x3F, 0xA4, 0x09, 0x76, 0xCC, 0xAA, 0xB9, 0x9B, 0xA6,
|
|
||||||
0x4F, 0xC1, 0x6A, 0x64, 0xCE, 0xD8, 0x77, 0xAB, 0x4B, 0xF9, 0xA0, 0xAE, 0xDA, 0xF1, 0x67,
|
|
||||||
0x87, 0x7C, 0x98, 0x5C, 0x7E, 0xB8, 0x73, 0xF5};
|
|
||||||
// n = p * q
|
|
||||||
static constexpr CryptoPP::byte Modulus[] = {
|
|
||||||
0xC6, 0xCF, 0x71, 0xE7, 0xE5, 0x9A, 0xF0, 0xD1, 0x2A, 0x2C, 0x45, 0x8B, 0xF9, 0x2A, 0x0E,
|
|
||||||
0xC1, 0x43, 0x05, 0x8B, 0xC3, 0x71, 0x17, 0x80, 0x1D, 0xCD, 0x49, 0x7D, 0xDE, 0x35, 0x9D,
|
|
||||||
0x25, 0x9B, 0xA0, 0xD7, 0xA0, 0xF2, 0x7D, 0x6C, 0x08, 0x7E, 0xAA, 0x55, 0x02, 0x68, 0x2B,
|
|
||||||
0x23, 0xC6, 0x44, 0xB8, 0x44, 0x18, 0xEB, 0x56, 0xCF, 0x16, 0xA2, 0x48, 0x03, 0xC9, 0xE7,
|
|
||||||
0x4F, 0x87, 0xEB, 0x3D, 0x30, 0xC3, 0x15, 0x88, 0xBF, 0x20, 0xE7, 0x9D, 0xFF, 0x77, 0x0C,
|
|
||||||
0xDE, 0x1D, 0x24, 0x1E, 0x63, 0xA9, 0x4F, 0x8A, 0xBF, 0x5B, 0xBE, 0x60, 0x19, 0x68, 0x33,
|
|
||||||
0x3B, 0xFC, 0xED, 0x9F, 0x47, 0x4E, 0x5F, 0xF8, 0xEA, 0xCB, 0x3D, 0x00, 0xBD, 0x67, 0x01,
|
|
||||||
0xF9, 0x2C, 0x6D, 0xC6, 0xAC, 0x13, 0x64, 0xE7, 0x67, 0x14, 0xF3, 0xDC, 0x52, 0x69, 0x6A,
|
|
||||||
0xB9, 0x83, 0x2C, 0x42, 0x30, 0x13, 0x1B, 0xB2, 0xD8, 0xA5, 0x02, 0x0D, 0x79, 0xED, 0x96,
|
|
||||||
0xB1, 0x0D, 0xF8, 0xCC, 0x0C, 0xDF, 0x81, 0x95, 0x4F, 0x03, 0x58, 0x09, 0x57, 0x0E, 0x80,
|
|
||||||
0x69, 0x2E, 0xFE, 0xFF, 0x52, 0x77, 0xEA, 0x75, 0x28, 0xA8, 0xFB, 0xC9, 0xBE, 0xBF, 0x9F,
|
|
||||||
0xBB, 0xB7, 0x79, 0x8E, 0x18, 0x05, 0xE1, 0x80, 0xBD, 0x50, 0x34, 0x94, 0x81, 0xD3, 0x53,
|
|
||||||
0xC2, 0x69, 0xA2, 0xD2, 0x4C, 0xCF, 0x6C, 0xF4, 0x57, 0x2C, 0x10, 0x4A, 0x3F, 0xFB, 0x22,
|
|
||||||
0xFD, 0x8B, 0x97, 0xE2, 0xC9, 0x5B, 0xA6, 0x2B, 0xCD, 0xD6, 0x1B, 0x6B, 0xDB, 0x68, 0x7F,
|
|
||||||
0x4B, 0xC2, 0xA0, 0x50, 0x34, 0xC0, 0x05, 0xE5, 0x8D, 0xEF, 0x24, 0x67, 0xFF, 0x93, 0x40,
|
|
||||||
0xCF, 0x2D, 0x62, 0xA2, 0xA0, 0x50, 0xB1, 0xF1, 0x3A, 0xA8, 0x3D, 0xFD, 0x80, 0xD1, 0xF9,
|
|
||||||
0xB8, 0x05, 0x22, 0xAF, 0xC8, 0x35, 0x45, 0x90, 0x58, 0x8E, 0xE3, 0x3A, 0x7C, 0xBD, 0x3E,
|
|
||||||
0x27};
|
|
||||||
// p
|
|
||||||
static constexpr CryptoPP::byte Prime1[] = {
|
|
||||||
0xFE, 0xF6, 0xBF, 0x1D, 0x69, 0xAB, 0x16, 0x25, 0x08, 0x47, 0x55, 0x6B, 0x86, 0xE4, 0x35,
|
|
||||||
0x88, 0x72, 0x2A, 0xB1, 0x3D, 0xF8, 0xB6, 0x44, 0xCA, 0xB3, 0xAB, 0x19, 0xD1, 0x04, 0x24,
|
|
||||||
0x28, 0x0A, 0x74, 0x55, 0xB8, 0x15, 0x45, 0x09, 0xCC, 0x13, 0x1C, 0xF2, 0xBA, 0x37, 0xA9,
|
|
||||||
0x03, 0x90, 0x8F, 0x02, 0x10, 0xFF, 0x25, 0x79, 0x86, 0xCC, 0x18, 0x50, 0x9A, 0x10, 0x5F,
|
|
||||||
0x5B, 0x4C, 0x1C, 0x4E, 0xB0, 0xA7, 0xE3, 0x59, 0xB1, 0x2D, 0xA0, 0xC6, 0xB0, 0x20, 0x2C,
|
|
||||||
0x21, 0x33, 0x12, 0xB3, 0xAF, 0x72, 0x34, 0x83, 0xCD, 0x52, 0x2F, 0xAF, 0x0F, 0x20, 0x5A,
|
|
||||||
0x1B, 0xC0, 0xE2, 0xA3, 0x76, 0x34, 0x0F, 0xD7, 0xFC, 0xC1, 0x41, 0xC9, 0xF9, 0x79, 0x40,
|
|
||||||
0x17, 0x42, 0x21, 0x3E, 0x9D, 0xFD, 0xC7, 0xC1, 0x50, 0xDE, 0x44, 0x5A, 0xC9, 0x31, 0x89,
|
|
||||||
0x6A, 0x78, 0x05, 0xBE, 0x65, 0xB4, 0xE8, 0x2D};
|
|
||||||
// q
|
|
||||||
static constexpr CryptoPP::byte Prime2[] = {
|
|
||||||
0xC7, 0x9E, 0x47, 0x58, 0x00, 0x7D, 0x62, 0x82, 0xB0, 0xD2, 0x22, 0x81, 0xD4, 0xA8, 0x97,
|
|
||||||
0x1B, 0x79, 0x0C, 0x3A, 0xB0, 0xD7, 0xC9, 0x30, 0xE3, 0xC3, 0x53, 0x8E, 0x57, 0xEF, 0xF0,
|
|
||||||
0x9B, 0x9F, 0xB3, 0x90, 0x52, 0xC6, 0x94, 0x22, 0x36, 0xAA, 0xE6, 0x4A, 0x5F, 0x72, 0x1D,
|
|
||||||
0x70, 0xE8, 0x76, 0x58, 0xC8, 0xB2, 0x91, 0xCE, 0x9C, 0xC3, 0xE9, 0x09, 0x7F, 0x2E, 0x47,
|
|
||||||
0x97, 0xCC, 0x90, 0x39, 0x15, 0x35, 0x31, 0xDE, 0x1F, 0x0C, 0x8C, 0x0D, 0xC1, 0xC2, 0x92,
|
|
||||||
0xBE, 0x97, 0xBF, 0x2F, 0x91, 0xA1, 0x8C, 0x7D, 0x50, 0xA8, 0x21, 0x2F, 0xD7, 0xA2, 0x9A,
|
|
||||||
0x7E, 0xB5, 0xA7, 0x2A, 0x90, 0x02, 0xD9, 0xF3, 0x3D, 0xD1, 0xEB, 0xB8, 0xE0, 0x5A, 0x79,
|
|
||||||
0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B, 0x2A, 0xFE, 0x51,
|
|
||||||
0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23};
|
|
||||||
static constexpr CryptoPP::byte PrivateExponent[] = {
|
|
||||||
0x7F, 0x76, 0xCD, 0x0E, 0xE2, 0xD4, 0xDE, 0x05, 0x1C, 0xC6, 0xD9, 0xA8, 0x0E, 0x8D, 0xFA,
|
|
||||||
0x7B, 0xCA, 0x1E, 0xAA, 0x27, 0x1A, 0x40, 0xF8, 0xF1, 0x22, 0x87, 0x35, 0xDD, 0xDB, 0xFD,
|
|
||||||
0xEE, 0xF8, 0xC2, 0xBC, 0xBD, 0x01, 0xFB, 0x8B, 0xE2, 0x3E, 0x63, 0xB2, 0xB1, 0x22, 0x5C,
|
|
||||||
0x56, 0x49, 0x6E, 0x11, 0xBE, 0x07, 0x44, 0x0B, 0x9A, 0x26, 0x66, 0xD1, 0x49, 0x2C, 0x8F,
|
|
||||||
0xD3, 0x1B, 0xCF, 0xA4, 0xA1, 0xB8, 0xD1, 0xFB, 0xA4, 0x9E, 0xD2, 0x21, 0x28, 0x83, 0x09,
|
|
||||||
0x8A, 0xF6, 0xA0, 0x0B, 0xA3, 0xD6, 0x0F, 0x9B, 0x63, 0x68, 0xCC, 0xBC, 0x0C, 0x4E, 0x14,
|
|
||||||
0x5B, 0x27, 0xA4, 0xA9, 0xF4, 0x2B, 0xB9, 0xB8, 0x7B, 0xC0, 0xE6, 0x51, 0xAD, 0x1D, 0x77,
|
|
||||||
0xD4, 0x6B, 0xB9, 0xCE, 0x20, 0xD1, 0x26, 0x66, 0x7E, 0x5E, 0x9E, 0xA2, 0xE9, 0x6B, 0x90,
|
|
||||||
0xF3, 0x73, 0xB8, 0x52, 0x8F, 0x44, 0x11, 0x03, 0x0C, 0x13, 0x97, 0x39, 0x3D, 0x13, 0x22,
|
|
||||||
0x58, 0xD5, 0x43, 0x82, 0x49, 0xDA, 0x6E, 0x7C, 0xA1, 0xC5, 0x8C, 0xA5, 0xB0, 0x09, 0xE0,
|
|
||||||
0xCE, 0x3D, 0xDF, 0xF4, 0x9D, 0x3C, 0x97, 0x15, 0xE2, 0x6A, 0xC7, 0x2B, 0x3C, 0x50, 0x93,
|
|
||||||
0x23, 0xDB, 0xBA, 0x4A, 0x22, 0x66, 0x44, 0xAC, 0x78, 0xBB, 0x0E, 0x1A, 0x27, 0x43, 0xB5,
|
|
||||||
0x71, 0x67, 0xAF, 0xF4, 0xAB, 0x48, 0x46, 0x93, 0x73, 0xD0, 0x42, 0xAB, 0x93, 0x63, 0xE5,
|
|
||||||
0x6C, 0x9A, 0xDE, 0x50, 0x24, 0xC0, 0x23, 0x7D, 0x99, 0x79, 0x3F, 0x22, 0x07, 0xE0, 0xC1,
|
|
||||||
0x48, 0x56, 0x1B, 0xDF, 0x83, 0x09, 0x12, 0xB4, 0x2D, 0x45, 0x6B, 0xC9, 0xC0, 0x68, 0x85,
|
|
||||||
0x99, 0x90, 0x79, 0x96, 0x1A, 0xD7, 0xF5, 0x4D, 0x1F, 0x37, 0x83, 0x40, 0x4A, 0xEC, 0x39,
|
|
||||||
0x37, 0xA6, 0x80, 0x92, 0x7D, 0xC5, 0x80, 0xC7, 0xD6, 0x6F, 0xFE, 0x8A, 0x79, 0x89, 0xC6,
|
|
||||||
0xB1};
|
|
||||||
};
|
|
||||||
|
|
||||||
class DebugRifKeyset {
|
|
||||||
public:
|
|
||||||
// std::uint8_t* PrivateExponent;
|
|
||||||
static constexpr CryptoPP::byte Exponent1[] = {
|
|
||||||
0xCD, 0x9A, 0x61, 0xB0, 0xB8, 0xD5, 0xB4, 0xE4, 0xE4, 0xF6, 0xAB, 0xF7, 0x27, 0xB7, 0x56,
|
|
||||||
0x59, 0x6B, 0xB9, 0x11, 0xE7, 0xF4, 0x83, 0xAF, 0xB9, 0x73, 0x99, 0x7F, 0x49, 0xA2, 0x9C,
|
|
||||||
0xF0, 0xB5, 0x6D, 0x37, 0x82, 0x14, 0x15, 0xF1, 0x04, 0x8A, 0xD4, 0x8E, 0xEB, 0x2E, 0x1F,
|
|
||||||
0xE2, 0x81, 0xA9, 0x62, 0x6E, 0xB1, 0x68, 0x75, 0x62, 0xF3, 0x0F, 0xFE, 0xD4, 0x91, 0x87,
|
|
||||||
0x98, 0x78, 0xBF, 0x26, 0xB5, 0x07, 0x58, 0xD0, 0xEE, 0x3F, 0x21, 0xE8, 0xC8, 0x0F, 0x5F,
|
|
||||||
0xFA, 0x1C, 0x64, 0x74, 0x49, 0x52, 0xEB, 0xE7, 0xEE, 0xDE, 0xBA, 0x23, 0x26, 0x4A, 0xF6,
|
|
||||||
0x9C, 0x1A, 0x09, 0x3F, 0xB9, 0x0B, 0x36, 0x26, 0x1A, 0xBE, 0xA9, 0x76, 0xE6, 0xF2, 0x69,
|
|
||||||
0xDE, 0xFF, 0xAF, 0xCC, 0x0C, 0x9A, 0x66, 0x03, 0x86, 0x0A, 0x1F, 0x49, 0xA4, 0x10, 0xB6,
|
|
||||||
0xBC, 0xC3, 0x7C, 0x88, 0xE8, 0xCE, 0x4B, 0xD9};
|
|
||||||
// exponent2 = d mod (q - 1)
|
|
||||||
static constexpr CryptoPP::byte Exponent2[] = {
|
|
||||||
0xB3, 0x73, 0xA3, 0x59, 0xE6, 0x97, 0xC0, 0xAB, 0x3B, 0x68, 0xFC, 0x39, 0xAC, 0xDB, 0x44,
|
|
||||||
0xB1, 0xB4, 0x9E, 0x35, 0x4D, 0xBE, 0xC5, 0x36, 0x69, 0x6C, 0x3D, 0xC5, 0xFC, 0xFE, 0x4B,
|
|
||||||
0x2F, 0xDC, 0x86, 0x80, 0x46, 0x96, 0x40, 0x1A, 0x0D, 0x6E, 0xFA, 0x8C, 0xE0, 0x47, 0x91,
|
|
||||||
0xAC, 0xAD, 0x95, 0x2B, 0x8E, 0x1F, 0xF2, 0x0A, 0x45, 0xF8, 0x29, 0x95, 0x70, 0xC6, 0x88,
|
|
||||||
0x5F, 0x71, 0x03, 0x99, 0x79, 0xBC, 0x84, 0x71, 0xBD, 0xE8, 0x84, 0x8C, 0x0E, 0xD4, 0x7B,
|
|
||||||
0x30, 0x74, 0x57, 0x1A, 0x95, 0xE7, 0x90, 0x19, 0x8D, 0xAD, 0x8B, 0x4C, 0x4E, 0xC3, 0xE7,
|
|
||||||
0x6B, 0x23, 0x86, 0x01, 0xEE, 0x9B, 0xE0, 0x2F, 0x15, 0xA2, 0x2C, 0x4C, 0x39, 0xD3, 0xDF,
|
|
||||||
0x9C, 0x39, 0x01, 0xF1, 0x8C, 0x44, 0x4A, 0x15, 0x44, 0xDC, 0x51, 0xF7, 0x22, 0xD7, 0x7F,
|
|
||||||
0x41, 0x7F, 0x68, 0xFA, 0xEE, 0x56, 0xE8, 0x05};
|
|
||||||
// e
|
|
||||||
static constexpr CryptoPP::byte PublicExponent[] = {0x00, 0x01, 0x00, 0x01};
|
|
||||||
// (InverseQ)(q) = 1 mod p
|
|
||||||
static constexpr CryptoPP::byte Coefficient[] = {
|
|
||||||
0xC0, 0x32, 0x43, 0xD3, 0x8C, 0x3D, 0xB4, 0xD2, 0x48, 0x8C, 0x42, 0x41, 0x24, 0x94, 0x6C,
|
|
||||||
0x80, 0xC9, 0xC1, 0x79, 0x36, 0x7F, 0xAC, 0xC3, 0xFF, 0x6A, 0x25, 0xEB, 0x2C, 0xFB, 0xD4,
|
|
||||||
0x2B, 0xA0, 0xEB, 0xFE, 0x25, 0xE9, 0xC6, 0x77, 0xCE, 0xFE, 0x2D, 0x23, 0xFE, 0xD0, 0xF4,
|
|
||||||
0x0F, 0xD9, 0x7E, 0xD5, 0xA5, 0x7D, 0x1F, 0xC0, 0xE8, 0xE8, 0xEC, 0x80, 0x5B, 0xC7, 0xFD,
|
|
||||||
0xE2, 0xBD, 0x94, 0xA6, 0x2B, 0xDD, 0x6A, 0x60, 0x45, 0x54, 0xAB, 0xCA, 0x42, 0x9C, 0x6A,
|
|
||||||
0x6C, 0xBF, 0x3C, 0x84, 0xF9, 0xA5, 0x0E, 0x63, 0x0C, 0x51, 0x58, 0x62, 0x6D, 0x5A, 0xB7,
|
|
||||||
0x3C, 0x3F, 0x49, 0x1A, 0xD0, 0x93, 0xB8, 0x4F, 0x1A, 0x6C, 0x5F, 0xC5, 0xE5, 0xA9, 0x75,
|
|
||||||
0xD4, 0x86, 0x9E, 0xDF, 0x87, 0x0F, 0x27, 0xB0, 0x26, 0x78, 0x4E, 0xFB, 0xC1, 0x8A, 0x4A,
|
|
||||||
0x24, 0x3F, 0x7F, 0x8F, 0x9A, 0x12, 0x51, 0xCB};
|
|
||||||
// n = p * q
|
|
||||||
static constexpr CryptoPP::byte Modulus[] = {
|
|
||||||
0xC2, 0xD2, 0x44, 0xBC, 0xDD, 0x84, 0x3F, 0xD9, 0xC5, 0x22, 0xAF, 0xF7, 0xFC, 0x88, 0x8A,
|
|
||||||
0x33, 0x80, 0xED, 0x8E, 0xE2, 0xCC, 0x81, 0xF7, 0xEC, 0xF8, 0x1C, 0x79, 0xBF, 0x02, 0xBB,
|
|
||||||
0x12, 0x8E, 0x61, 0x68, 0x29, 0x1B, 0x15, 0xB6, 0x5E, 0xC6, 0xF8, 0xBF, 0x5A, 0xE0, 0x3B,
|
|
||||||
0x6A, 0x6C, 0xD9, 0xD6, 0xF5, 0x75, 0xAB, 0xA0, 0x6F, 0x34, 0x81, 0x34, 0x9A, 0x5B, 0xAD,
|
|
||||||
0xED, 0x31, 0xE3, 0xC6, 0xEA, 0x1A, 0xD1, 0x13, 0x22, 0xBB, 0xB3, 0xDA, 0xB3, 0xB2, 0x53,
|
|
||||||
0xBD, 0x45, 0x79, 0x87, 0xAD, 0x0A, 0x01, 0x72, 0x18, 0x10, 0x29, 0x49, 0xF4, 0x41, 0x7F,
|
|
||||||
0xD6, 0x47, 0x0C, 0x72, 0x92, 0x9E, 0xE9, 0xBB, 0x95, 0xA9, 0x5D, 0x79, 0xEB, 0xE4, 0x30,
|
|
||||||
0x76, 0x90, 0x45, 0x4B, 0x9D, 0x9C, 0xCF, 0x92, 0x03, 0x60, 0x8C, 0x4B, 0x6C, 0xB3, 0x7A,
|
|
||||||
0x3A, 0x05, 0x39, 0xA0, 0x66, 0xA9, 0x35, 0xCF, 0xB9, 0xFA, 0xAD, 0x9C, 0xAB, 0xEB, 0xE4,
|
|
||||||
0x6A, 0x8C, 0xE9, 0x3B, 0xCC, 0x72, 0x12, 0x62, 0x63, 0xBD, 0x80, 0xC4, 0xEE, 0x37, 0x2B,
|
|
||||||
0x32, 0x03, 0xA3, 0x09, 0xF7, 0xA0, 0x61, 0x57, 0xAD, 0x0D, 0xCF, 0x15, 0x98, 0x9E, 0x4E,
|
|
||||||
0x49, 0xF8, 0xB5, 0xA3, 0x5C, 0x27, 0xEE, 0x45, 0x04, 0xEA, 0xE4, 0x4B, 0xBC, 0x8F, 0x87,
|
|
||||||
0xED, 0x19, 0x1E, 0x46, 0x75, 0x63, 0xC4, 0x5B, 0xD5, 0xBC, 0x09, 0x2F, 0x02, 0x73, 0x19,
|
|
||||||
0x3C, 0x58, 0x55, 0x49, 0x66, 0x4C, 0x11, 0xEC, 0x0F, 0x09, 0xFA, 0xA5, 0x56, 0x0A, 0x5A,
|
|
||||||
0x63, 0x56, 0xAD, 0xA0, 0x0D, 0x86, 0x08, 0xC1, 0xE6, 0xB6, 0x13, 0x22, 0x49, 0x2F, 0x7C,
|
|
||||||
0xDB, 0x4C, 0x56, 0x97, 0x0E, 0xC2, 0xD9, 0x2E, 0x87, 0xBC, 0x0E, 0x67, 0xC0, 0x1B, 0x58,
|
|
||||||
0xBC, 0x64, 0x2B, 0xC2, 0x6E, 0xE2, 0x93, 0x2E, 0xB5, 0x6B, 0x70, 0xA4, 0x42, 0x9F, 0x64,
|
|
||||||
0xC1};
|
|
||||||
// p
|
|
||||||
static constexpr CryptoPP::byte Prime1[] = {
|
|
||||||
0xE5, 0x62, 0xE1, 0x7F, 0x9F, 0x86, 0x08, 0xE2, 0x61, 0xD3, 0xD0, 0x42, 0xE2, 0xC4, 0xB6,
|
|
||||||
0xA8, 0x51, 0x09, 0x19, 0x14, 0xA4, 0x3A, 0x11, 0x4C, 0x33, 0xA5, 0x9C, 0x01, 0x5E, 0x34,
|
|
||||||
0xB6, 0x3F, 0x02, 0x1A, 0xCA, 0x47, 0xF1, 0x4F, 0x3B, 0x35, 0x2A, 0x07, 0x20, 0xEC, 0xD8,
|
|
||||||
0xC1, 0x15, 0xD9, 0xCA, 0x03, 0x4F, 0xB8, 0xE8, 0x09, 0x73, 0x3F, 0x85, 0xB7, 0x41, 0xD5,
|
|
||||||
0x51, 0x3E, 0x7B, 0xE3, 0x53, 0x2B, 0x48, 0x8B, 0x8E, 0xCB, 0xBA, 0xF7, 0xE0, 0x60, 0xF5,
|
|
||||||
0x35, 0x0E, 0x6F, 0xB0, 0xD9, 0x2A, 0x99, 0xD0, 0xFF, 0x60, 0x14, 0xED, 0x40, 0xEA, 0xF8,
|
|
||||||
0xD7, 0x0B, 0xC3, 0x8D, 0x8C, 0xE8, 0x81, 0xB3, 0x75, 0x93, 0x15, 0xB3, 0x7D, 0xF6, 0x39,
|
|
||||||
0x60, 0x1A, 0x00, 0xE7, 0xC3, 0x27, 0xAD, 0xA4, 0x33, 0xD5, 0x3E, 0xA4, 0x35, 0x48, 0x6F,
|
|
||||||
0x22, 0xEF, 0x5D, 0xDD, 0x7D, 0x7B, 0x61, 0x05};
|
|
||||||
// q
|
|
||||||
static constexpr CryptoPP::byte Prime2[] = {
|
|
||||||
0xD9, 0x6C, 0xC2, 0x0C, 0xF7, 0xAE, 0xD1, 0xF3, 0x3B, 0x3B, 0x49, 0x1E, 0x9F, 0x12, 0x9C,
|
|
||||||
0xA1, 0x78, 0x1F, 0x35, 0x1D, 0x98, 0x26, 0x13, 0x71, 0xF9, 0x09, 0xFD, 0xF0, 0xAD, 0x38,
|
|
||||||
0x55, 0xB7, 0xEE, 0x61, 0x04, 0x72, 0x51, 0x87, 0x2E, 0x05, 0x84, 0xB1, 0x1D, 0x0C, 0x0D,
|
|
||||||
0xDB, 0xD4, 0x25, 0x3E, 0x26, 0xED, 0xEA, 0xB8, 0xF7, 0x49, 0xFE, 0xA2, 0x94, 0xE6, 0xF2,
|
|
||||||
0x08, 0x92, 0xA7, 0x85, 0xF5, 0x30, 0xB9, 0x84, 0x22, 0xBF, 0xCA, 0xF0, 0x5F, 0xCB, 0x31,
|
|
||||||
0x20, 0x34, 0x49, 0x16, 0x76, 0x34, 0xCC, 0x7A, 0xCB, 0x96, 0xFE, 0x78, 0x7A, 0x41, 0xFE,
|
|
||||||
0x9A, 0xA2, 0x23, 0xF7, 0x68, 0x80, 0xD6, 0xCE, 0x4A, 0x78, 0xA5, 0xB7, 0x05, 0x77, 0x81,
|
|
||||||
0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6, 0x54, 0x91, 0x6B,
|
|
||||||
0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D};
|
|
||||||
static constexpr CryptoPP::byte PrivateExponent[] = {
|
|
||||||
0x01, 0x61, 0xAD, 0xD8, 0x9C, 0x06, 0x89, 0xD0, 0x60, 0xC8, 0x41, 0xF0, 0xB3, 0x83, 0x01,
|
|
||||||
0x5D, 0xE3, 0xA2, 0x6B, 0xA2, 0xBA, 0x9A, 0x0A, 0x58, 0xCD, 0x1A, 0xA0, 0x97, 0x64, 0xEC,
|
|
||||||
0xD0, 0x31, 0x1F, 0xCA, 0x36, 0x0E, 0x69, 0xDD, 0x40, 0xF7, 0x4E, 0xC0, 0xC6, 0xA3, 0x73,
|
|
||||||
0xF0, 0x69, 0x84, 0xB2, 0xF4, 0x4B, 0x29, 0x14, 0x2A, 0x6D, 0xB8, 0x23, 0xD8, 0x1B, 0x61,
|
|
||||||
0xD4, 0x9E, 0x87, 0xB3, 0xBB, 0xA9, 0xC4, 0x85, 0x4A, 0xF8, 0x03, 0x4A, 0xBF, 0xFE, 0xF9,
|
|
||||||
0xFE, 0x8B, 0xDD, 0x54, 0x83, 0xBA, 0xE0, 0x2F, 0x3F, 0xB1, 0xEF, 0xA5, 0x05, 0x5D, 0x28,
|
|
||||||
0x8B, 0xAB, 0xB5, 0xD0, 0x23, 0x2F, 0x8A, 0xCF, 0x48, 0x7C, 0xAA, 0xBB, 0xC8, 0x5B, 0x36,
|
|
||||||
0x27, 0xC5, 0x16, 0xA4, 0xB6, 0x61, 0xAC, 0x0C, 0x28, 0x47, 0x79, 0x3F, 0x38, 0xAE, 0x5E,
|
|
||||||
0x25, 0xC6, 0xAF, 0x35, 0xAE, 0xBC, 0xB0, 0xF3, 0xBC, 0xBD, 0xFD, 0xA4, 0x87, 0x0D, 0x14,
|
|
||||||
0x3D, 0x90, 0xE4, 0xDE, 0x5D, 0x1D, 0x46, 0x81, 0xF1, 0x28, 0x6D, 0x2F, 0x2C, 0x5E, 0x97,
|
|
||||||
0x2D, 0x89, 0x2A, 0x51, 0x72, 0x3C, 0x20, 0x02, 0x59, 0xB1, 0x98, 0x93, 0x05, 0x1E, 0x3F,
|
|
||||||
0xA1, 0x8A, 0x69, 0x30, 0x0E, 0x70, 0x84, 0x8B, 0xAE, 0x97, 0xA1, 0x08, 0x95, 0x63, 0x4C,
|
|
||||||
0xC7, 0xE8, 0x5D, 0x59, 0xCA, 0x78, 0x2A, 0x23, 0x87, 0xAC, 0x6F, 0x04, 0x33, 0xB1, 0x61,
|
|
||||||
0xB9, 0xF0, 0x95, 0xDA, 0x33, 0xCC, 0xE0, 0x4C, 0x82, 0x68, 0x82, 0x14, 0x51, 0xBE, 0x49,
|
|
||||||
0x1C, 0x58, 0xA2, 0x8B, 0x05, 0x4E, 0x98, 0x37, 0xEB, 0x94, 0x0B, 0x01, 0x22, 0xDC, 0xB3,
|
|
||||||
0x19, 0xCA, 0x77, 0xA6, 0x6E, 0x97, 0xFF, 0x8A, 0x53, 0x5A, 0xC5, 0x24, 0xE4, 0xAF, 0x6E,
|
|
||||||
0xA8, 0x2B, 0x53, 0xA4, 0xBE, 0x96, 0xA5, 0x7B, 0xCE, 0x22, 0x56, 0xA3, 0xF1, 0xCF, 0x14,
|
|
||||||
0xA5};
|
|
||||||
};
|
|
||||||
|
|
||||||
class PkgDerivedKey3Keyset {
|
|
||||||
public:
|
|
||||||
// std::uint8_t* PrivateExponent;
|
|
||||||
static constexpr CryptoPP::byte Exponent1[] = {
|
|
||||||
0x52, 0xCC, 0x2D, 0xA0, 0x9C, 0x9E, 0x75, 0xE7, 0x28, 0xEE, 0x3D, 0xDE, 0xE3, 0x45, 0xD1,
|
|
||||||
0x4F, 0x94, 0x1C, 0xCC, 0xC8, 0x87, 0x29, 0x45, 0x3B, 0x8D, 0x6E, 0xAB, 0x6E, 0x2A, 0xA7,
|
|
||||||
0xC7, 0x15, 0x43, 0xA3, 0x04, 0x8F, 0x90, 0x5F, 0xEB, 0xF3, 0x38, 0x4A, 0x77, 0xFA, 0x36,
|
|
||||||
0xB7, 0x15, 0x76, 0xB6, 0x01, 0x1A, 0x8E, 0x25, 0x87, 0x82, 0xF1, 0x55, 0xD8, 0xC6, 0x43,
|
|
||||||
0x2A, 0xC0, 0xE5, 0x98, 0xC9, 0x32, 0xD1, 0x94, 0x6F, 0xD9, 0x01, 0xBA, 0x06, 0x81, 0xE0,
|
|
||||||
0x6D, 0x88, 0xF2, 0x24, 0x2A, 0x25, 0x01, 0x64, 0x5C, 0xBF, 0xF2, 0xD9, 0x99, 0x67, 0x3E,
|
|
||||||
0xF6, 0x72, 0xEE, 0xE4, 0xE2, 0x33, 0x5C, 0xF8, 0x00, 0x40, 0xE3, 0x2A, 0x9A, 0xF4, 0x3D,
|
|
||||||
0x22, 0x86, 0x44, 0x3C, 0xFB, 0x0A, 0xA5, 0x7C, 0x3F, 0xCC, 0xF5, 0xF1, 0x16, 0xC4, 0xAC,
|
|
||||||
0x88, 0xB4, 0xDE, 0x62, 0x94, 0x92, 0x6A, 0x13};
|
|
||||||
// exponent2 = d mod (q - 1)
|
|
||||||
static constexpr CryptoPP::byte Exponent2[] = {
|
|
||||||
0x7C, 0x9D, 0xAD, 0x39, 0xE0, 0xD5, 0x60, 0x14, 0x94, 0x48, 0x19, 0x7F, 0x88, 0x95, 0xD5,
|
|
||||||
0x8B, 0x80, 0xAD, 0x85, 0x8A, 0x4B, 0x77, 0x37, 0x85, 0xD0, 0x77, 0xBB, 0xBF, 0x89, 0x71,
|
|
||||||
0x4A, 0x72, 0xCB, 0x72, 0x68, 0x38, 0xEC, 0x02, 0xC6, 0x7D, 0xC6, 0x44, 0x06, 0x33, 0x51,
|
|
||||||
0x1C, 0xC0, 0xFF, 0x95, 0x8F, 0x0D, 0x75, 0xDC, 0x25, 0xBB, 0x0B, 0x73, 0x91, 0xA9, 0x6D,
|
|
||||||
0x42, 0xD8, 0x03, 0xB7, 0x68, 0xD4, 0x1E, 0x75, 0x62, 0xA3, 0x70, 0x35, 0x79, 0x78, 0x00,
|
|
||||||
0xC8, 0xF5, 0xEF, 0x15, 0xB9, 0xFC, 0x4E, 0x47, 0x5A, 0xC8, 0x70, 0x70, 0x5B, 0x52, 0x98,
|
|
||||||
0xC0, 0xC2, 0x58, 0x4A, 0x70, 0x96, 0xCC, 0xB8, 0x10, 0xE1, 0x2F, 0x78, 0x8B, 0x2B, 0xA1,
|
|
||||||
0x7F, 0xF9, 0xAC, 0xDE, 0xF0, 0xBB, 0x2B, 0xE2, 0x66, 0xE3, 0x22, 0x92, 0x31, 0x21, 0x57,
|
|
||||||
0x92, 0xC4, 0xB8, 0xF2, 0x3E, 0x76, 0x20, 0x37};
|
|
||||||
// e
|
|
||||||
static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1};
|
|
||||||
// (InverseQ)(q) = 1 mod p
|
|
||||||
static constexpr CryptoPP::byte Coefficient[] = {
|
|
||||||
0x45, 0x97, 0x55, 0xD4, 0x22, 0x08, 0x5E, 0xF3, 0x5C, 0xB4, 0x05, 0x7A, 0xFD, 0xAA, 0x42,
|
|
||||||
0x42, 0xAD, 0x9A, 0x8C, 0xA0, 0x6C, 0xBB, 0x1D, 0x68, 0x54, 0x54, 0x6E, 0x3E, 0x32, 0xE3,
|
|
||||||
0x53, 0x73, 0x76, 0xF1, 0x3E, 0x01, 0xEA, 0xD3, 0xCF, 0xEB, 0xEB, 0x23, 0x3E, 0xC0, 0xBE,
|
|
||||||
0xCE, 0xEC, 0x2C, 0x89, 0x5F, 0xA8, 0x27, 0x3A, 0x4C, 0xB7, 0xE6, 0x74, 0xBC, 0x45, 0x4C,
|
|
||||||
0x26, 0xC8, 0x25, 0xFF, 0x34, 0x63, 0x25, 0x37, 0xE1, 0x48, 0x10, 0xC1, 0x93, 0xA6, 0xAF,
|
|
||||||
0xEB, 0xBA, 0xE3, 0xA2, 0xF1, 0x3D, 0xEF, 0x63, 0xD8, 0xF4, 0xFD, 0xD3, 0xEE, 0xE2, 0x5D,
|
|
||||||
0xE9, 0x33, 0xCC, 0xAD, 0xBA, 0x75, 0x5C, 0x85, 0xAF, 0xCE, 0xA9, 0x3D, 0xD1, 0xA2, 0x17,
|
|
||||||
0xF3, 0xF6, 0x98, 0xB3, 0x50, 0x8E, 0x5E, 0xF6, 0xEB, 0x02, 0x8E, 0xA1, 0x62, 0xA7, 0xD6,
|
|
||||||
0x2C, 0xEC, 0x91, 0xFF, 0x15, 0x40, 0xD2, 0xE3};
|
|
||||||
// n = p * q
|
|
||||||
static constexpr CryptoPP::byte Modulus[] = {
|
|
||||||
0xd2, 0x12, 0xfc, 0x33, 0x5f, 0x6d, 0xdb, 0x83, 0x16, 0x09, 0x62, 0x8b, 0x03, 0x56, 0x27,
|
|
||||||
0x37, 0x82, 0xd4, 0x77, 0x85, 0x35, 0x29, 0x39, 0x2d, 0x52, 0x6b, 0x8c, 0x4c, 0x8c, 0xfb,
|
|
||||||
0x06, 0xc1, 0x84, 0x5b, 0xe7, 0xd4, 0xf7, 0xbc, 0xd2, 0x4e, 0x62, 0x45, 0xcd, 0x2a, 0xbb,
|
|
||||||
0xd7, 0x77, 0x76, 0x45, 0x36, 0x55, 0x27, 0x3f, 0xb3, 0xf5, 0xf9, 0x8e, 0xda, 0x4b, 0xef,
|
|
||||||
0xaa, 0x59, 0xae, 0xb3, 0x9b, 0xea, 0x54, 0x98, 0xd2, 0x06, 0x32, 0x6a, 0x58, 0x31, 0x2a,
|
|
||||||
0xe0, 0xd4, 0x4f, 0x90, 0xb5, 0x0a, 0x7d, 0xec, 0xf4, 0x3a, 0x9c, 0x52, 0x67, 0x2d, 0x99,
|
|
||||||
0x31, 0x8e, 0x0c, 0x43, 0xe6, 0x82, 0xfe, 0x07, 0x46, 0xe1, 0x2e, 0x50, 0xd4, 0x1f, 0x2d,
|
|
||||||
0x2f, 0x7e, 0xd9, 0x08, 0xba, 0x06, 0xb3, 0xbf, 0x2e, 0x20, 0x3f, 0x4e, 0x3f, 0xfe, 0x44,
|
|
||||||
0xff, 0xaa, 0x50, 0x43, 0x57, 0x91, 0x69, 0x94, 0x49, 0x15, 0x82, 0x82, 0xe4, 0x0f, 0x4c,
|
|
||||||
0x8d, 0x9d, 0x2c, 0xc9, 0x5b, 0x1d, 0x64, 0xbf, 0x88, 0x8b, 0xd4, 0xc5, 0x94, 0xe7, 0x65,
|
|
||||||
0x47, 0x84, 0x1e, 0xe5, 0x79, 0x10, 0xfb, 0x98, 0x93, 0x47, 0xb9, 0x7d, 0x85, 0x12, 0xa6,
|
|
||||||
0x40, 0x98, 0x2c, 0xf7, 0x92, 0xbc, 0x95, 0x19, 0x32, 0xed, 0xe8, 0x90, 0x56, 0x0d, 0x65,
|
|
||||||
0xc1, 0xaa, 0x78, 0xc6, 0x2e, 0x54, 0xfd, 0x5f, 0x54, 0xa1, 0xf6, 0x7e, 0xe5, 0xe0, 0x5f,
|
|
||||||
0x61, 0xc1, 0x20, 0xb4, 0xb9, 0xb4, 0x33, 0x08, 0x70, 0xe4, 0xdf, 0x89, 0x56, 0xed, 0x01,
|
|
||||||
0x29, 0x46, 0x77, 0x5f, 0x8c, 0xb8, 0xa9, 0xf5, 0x1e, 0x2e, 0xb3, 0xb9, 0xbf, 0xe0, 0x09,
|
|
||||||
0xb7, 0x8d, 0x28, 0xd4, 0xa6, 0xc3, 0xb8, 0x1e, 0x1f, 0x07, 0xeb, 0xb4, 0x12, 0x0b, 0x95,
|
|
||||||
0xb8, 0x85, 0x30, 0xfd, 0xdc, 0x39, 0x13, 0xd0, 0x7c, 0xdc, 0x8f, 0xed, 0xf9, 0xc9, 0xa3,
|
|
||||||
0xc1};
|
|
||||||
// p
|
|
||||||
static constexpr CryptoPP::byte Prime1[] = {
|
|
||||||
0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46, 0xB3, 0x4D,
|
|
||||||
0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3, 0xC7, 0x3F, 0xC3, 0x42,
|
|
||||||
0xF5, 0x87, 0x49, 0x33, 0x9F, 0x07, 0x5D, 0x6E, 0x2C, 0x04, 0xFD, 0xE3, 0xE1, 0xB2, 0xAE,
|
|
||||||
0x0A, 0x0C, 0xF0, 0xC7, 0xA6, 0x1C, 0xA1, 0x63, 0x50, 0xC8, 0x09, 0x9C, 0x51, 0x24, 0x52,
|
|
||||||
0x6C, 0x5E, 0x5E, 0xBD, 0x1E, 0x27, 0x06, 0xBB, 0xBC, 0x9E, 0x94, 0xE1, 0x35, 0xD4, 0x6D,
|
|
||||||
0xB3, 0xCB, 0x3C, 0x68, 0xDD, 0x68, 0xB3, 0xFE, 0x6C, 0xCB, 0x8D, 0x82, 0x20, 0x76, 0x23,
|
|
||||||
0x63, 0xB7, 0xE9, 0x68, 0x10, 0x01, 0x4E, 0xDC, 0xBA, 0x27, 0x5D, 0x01, 0xC1, 0x2D, 0x80,
|
|
||||||
0x5E, 0x2B, 0xAF, 0x82, 0x6B, 0xD8, 0x84, 0xB6, 0x10, 0x52, 0x86, 0xA7, 0x89, 0x8E, 0xAE,
|
|
||||||
0x9A, 0xE2, 0x89, 0xC6, 0xF7, 0xD5, 0x87, 0xFB};
|
|
||||||
// q
|
|
||||||
static constexpr CryptoPP::byte Prime2[] = {
|
|
||||||
0xD7, 0xA1, 0x0F, 0x9A, 0x8B, 0xF2, 0xC9, 0x11, 0x95, 0x32, 0x9A, 0x8C, 0xF0, 0xD9, 0x40,
|
|
||||||
0x47, 0xF5, 0x68, 0xA0, 0x0D, 0xBD, 0xC1, 0xFC, 0x43, 0x2F, 0x65, 0xF9, 0xC3, 0x61, 0x0F,
|
|
||||||
0x25, 0x77, 0x54, 0xAD, 0xD7, 0x58, 0xAC, 0x84, 0x40, 0x60, 0x8D, 0x3F, 0xF3, 0x65, 0x89,
|
|
||||||
0x75, 0xB5, 0xC6, 0x2C, 0x51, 0x1A, 0x2F, 0x1F, 0x22, 0xE4, 0x43, 0x11, 0x54, 0xBE, 0xC9,
|
|
||||||
0xB4, 0xC7, 0xB5, 0x1B, 0x05, 0x0B, 0xBC, 0x56, 0x9A, 0xCD, 0x4A, 0xD9, 0x73, 0x68, 0x5E,
|
|
||||||
0x5C, 0xFB, 0x92, 0xB7, 0x8B, 0x0D, 0xFF, 0xF5, 0x07, 0xCA, 0xB4, 0xC8, 0x9B, 0x96, 0x3C,
|
|
||||||
0x07, 0x9E, 0x3E, 0x6B, 0x2A, 0x11, 0xF2, 0x8A, 0xB1, 0x8A, 0xD7, 0x2E, 0x1B, 0xA5, 0x53,
|
|
||||||
0x24, 0x06, 0xED, 0x50, 0xB8, 0x90, 0x67, 0xB1, 0xE2, 0x41, 0xC6, 0x92, 0x01, 0xEE, 0x10,
|
|
||||||
0xF0, 0x61, 0xBB, 0xFB, 0xB2, 0x7D, 0x4A, 0x73};
|
|
||||||
static constexpr CryptoPP::byte PrivateExponent[] = {
|
|
||||||
0x32, 0xD9, 0x03, 0x90, 0x8F, 0xBD, 0xB0, 0x8F, 0x57, 0x2B, 0x28, 0x5E, 0x0B, 0x8D, 0xB3,
|
|
||||||
0xEA, 0x5C, 0xD1, 0x7E, 0xA8, 0x90, 0x88, 0x8C, 0xDD, 0x6A, 0x80, 0xBB, 0xB1, 0xDF, 0xC1,
|
|
||||||
0xF7, 0x0D, 0xAA, 0x32, 0xF0, 0xB7, 0x7C, 0xCB, 0x88, 0x80, 0x0E, 0x8B, 0x64, 0xB0, 0xBE,
|
|
||||||
0x4C, 0xD6, 0x0E, 0x9B, 0x8C, 0x1E, 0x2A, 0x64, 0xE1, 0xF3, 0x5C, 0xD7, 0x76, 0x01, 0x41,
|
|
||||||
0x5E, 0x93, 0x5C, 0x94, 0xFE, 0xDD, 0x46, 0x62, 0xC3, 0x1B, 0x5A, 0xE2, 0xA0, 0xBC, 0x2D,
|
|
||||||
0xEB, 0xC3, 0x98, 0x0A, 0xA7, 0xB7, 0x85, 0x69, 0x70, 0x68, 0x2B, 0x64, 0x4A, 0xB3, 0x1F,
|
|
||||||
0xCC, 0x7D, 0xDC, 0x7C, 0x26, 0xF4, 0x77, 0xF6, 0x5C, 0xF2, 0xAE, 0x5A, 0x44, 0x2D, 0xD3,
|
|
||||||
0xAB, 0x16, 0x62, 0x04, 0x19, 0xBA, 0xFB, 0x90, 0xFF, 0xE2, 0x30, 0x50, 0x89, 0x6E, 0xCB,
|
|
||||||
0x56, 0xB2, 0xEB, 0xC0, 0x91, 0x16, 0x92, 0x5E, 0x30, 0x8E, 0xAE, 0xC7, 0x94, 0x5D, 0xFD,
|
|
||||||
0x35, 0xE1, 0x20, 0xF8, 0xAD, 0x3E, 0xBC, 0x08, 0xBF, 0xC0, 0x36, 0x74, 0x9F, 0xD5, 0xBB,
|
|
||||||
0x52, 0x08, 0xFD, 0x06, 0x66, 0xF3, 0x7A, 0xB3, 0x04, 0xF4, 0x75, 0x29, 0x5D, 0xE9, 0x5F,
|
|
||||||
0xAA, 0x10, 0x30, 0xB2, 0x0F, 0x5A, 0x1A, 0xC1, 0x2A, 0xB3, 0xFE, 0xCB, 0x21, 0xAD, 0x80,
|
|
||||||
0xEC, 0x8F, 0x20, 0x09, 0x1C, 0xDB, 0xC5, 0x58, 0x94, 0xC2, 0x9C, 0xC6, 0xCE, 0x82, 0x65,
|
|
||||||
0x3E, 0x57, 0x90, 0xBC, 0xA9, 0x8B, 0x06, 0xB4, 0xF0, 0x72, 0xF6, 0x77, 0xDF, 0x98, 0x64,
|
|
||||||
0xF1, 0xEC, 0xFE, 0x37, 0x2D, 0xBC, 0xAE, 0x8C, 0x08, 0x81, 0x1F, 0xC3, 0xC9, 0x89, 0x1A,
|
|
||||||
0xC7, 0x42, 0x82, 0x4B, 0x2E, 0xDC, 0x8E, 0x8D, 0x73, 0xCE, 0xB1, 0xCC, 0x01, 0xD9, 0x08,
|
|
||||||
0x70, 0x87, 0x3C, 0x44, 0x08, 0xEC, 0x49, 0x8F, 0x81, 0x5A, 0xE2, 0x40, 0xFF, 0x77, 0xFC,
|
|
||||||
0x0D};
|
|
||||||
};
|
|
|
@ -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>
|
||||||
|
@ -117,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;
|
||||||
|
@ -381,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
|
||||||
|
|
|
@ -1,473 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include <zlib.h>
|
|
||||||
#include "common/io_file.h"
|
|
||||||
#include "common/logging/formatter.h"
|
|
||||||
#include "core/file_format/pkg.h"
|
|
||||||
#include "core/file_format/pkg_type.h"
|
|
||||||
|
|
||||||
static void DecompressPFSC(std::span<char> compressed_data, std::span<char> decompressed_data) {
|
|
||||||
z_stream decompressStream;
|
|
||||||
decompressStream.zalloc = Z_NULL;
|
|
||||||
decompressStream.zfree = Z_NULL;
|
|
||||||
decompressStream.opaque = Z_NULL;
|
|
||||||
|
|
||||||
if (inflateInit(&decompressStream) != Z_OK) {
|
|
||||||
// std::cerr << "Error initializing zlib for deflation." << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
decompressStream.avail_in = compressed_data.size();
|
|
||||||
decompressStream.next_in = reinterpret_cast<unsigned char*>(compressed_data.data());
|
|
||||||
decompressStream.avail_out = decompressed_data.size();
|
|
||||||
decompressStream.next_out = reinterpret_cast<unsigned char*>(decompressed_data.data());
|
|
||||||
|
|
||||||
if (inflate(&decompressStream, Z_FINISH)) {
|
|
||||||
}
|
|
||||||
if (inflateEnd(&decompressStream) != Z_OK) {
|
|
||||||
// std::cerr << "Error ending zlib inflate" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 GetPFSCOffset(std::span<const u8> pfs_image) {
|
|
||||||
static constexpr u32 PfscMagic = 0x43534650;
|
|
||||||
u32 value;
|
|
||||||
for (u32 i = 0x20000; i < pfs_image.size(); i += 0x10000) {
|
|
||||||
std::memcpy(&value, &pfs_image[i], sizeof(u32));
|
|
||||||
if (value == PfscMagic)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PKG::PKG() = default;
|
|
||||||
|
|
||||||
PKG::~PKG() = default;
|
|
||||||
|
|
||||||
bool PKG::Open(const std::filesystem::path& filepath, std::string& failreason) {
|
|
||||||
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
|
|
||||||
if (!file.IsOpen()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pkgSize = file.GetSize();
|
|
||||||
|
|
||||||
file.Read(pkgheader);
|
|
||||||
if (pkgheader.magic != 0x7F434E54)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (const auto& flag : flagNames) {
|
|
||||||
if (isFlagSet(pkgheader.pkg_content_flags, flag.first)) {
|
|
||||||
if (!pkgFlags.empty())
|
|
||||||
pkgFlags += (", ");
|
|
||||||
pkgFlags += (flag.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find title id it is part of pkg_content_id starting at offset 0x40
|
|
||||||
file.Seek(0x47); // skip first 7 characters of content_id
|
|
||||||
file.Read(pkgTitleID);
|
|
||||||
|
|
||||||
u32 offset = pkgheader.pkg_table_entry_offset;
|
|
||||||
u32 n_files = pkgheader.pkg_table_entry_count;
|
|
||||||
|
|
||||||
if (!file.Seek(offset)) {
|
|
||||||
failreason = "Failed to seek to PKG table entry offset";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < n_files; i++) {
|
|
||||||
PKGEntry entry{};
|
|
||||||
file.Read(entry.id);
|
|
||||||
file.Read(entry.filename_offset);
|
|
||||||
file.Read(entry.flags1);
|
|
||||||
file.Read(entry.flags2);
|
|
||||||
file.Read(entry.offset);
|
|
||||||
file.Read(entry.size);
|
|
||||||
file.Seek(8, Common::FS::SeekOrigin::CurrentPosition);
|
|
||||||
|
|
||||||
// Try to figure out the name
|
|
||||||
const auto name = GetEntryNameByType(entry.id);
|
|
||||||
if (name == "param.sfo") {
|
|
||||||
sfo.clear();
|
|
||||||
if (!file.Seek(entry.offset)) {
|
|
||||||
failreason = "Failed to seek to param.sfo offset";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sfo.resize(entry.size);
|
|
||||||
file.ReadRaw<u8>(sfo.data(), entry.size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.Close();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::path& extract,
|
|
||||||
std::string& failreason) {
|
|
||||||
extract_path = extract;
|
|
||||||
pkgpath = filepath;
|
|
||||||
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
|
|
||||||
if (!file.IsOpen()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
pkgSize = file.GetSize();
|
|
||||||
file.ReadRaw<u8>(&pkgheader, sizeof(PKGHeader));
|
|
||||||
|
|
||||||
if (pkgheader.magic != 0x7F434E54)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (pkgheader.pkg_size > pkgSize) {
|
|
||||||
failreason = "PKG file size is different";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((pkgheader.pkg_content_size + pkgheader.pkg_content_offset) > pkgheader.pkg_size) {
|
|
||||||
failreason = "Content size is bigger than pkg size";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 offset = pkgheader.pkg_table_entry_offset;
|
|
||||||
u32 n_files = pkgheader.pkg_table_entry_count;
|
|
||||||
|
|
||||||
std::array<u8, 64> concatenated_ivkey_dk3;
|
|
||||||
std::array<u8, 32> seed_digest;
|
|
||||||
std::array<std::array<u8, 32>, 7> digest1;
|
|
||||||
std::array<std::array<u8, 256>, 7> key1;
|
|
||||||
std::array<u8, 256> imgkeydata;
|
|
||||||
|
|
||||||
if (!file.Seek(offset)) {
|
|
||||||
failreason = "Failed to seek to PKG table entry offset";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < n_files; i++) {
|
|
||||||
PKGEntry entry{};
|
|
||||||
file.Read(entry.id);
|
|
||||||
file.Read(entry.filename_offset);
|
|
||||||
file.Read(entry.flags1);
|
|
||||||
file.Read(entry.flags2);
|
|
||||||
file.Read(entry.offset);
|
|
||||||
file.Read(entry.size);
|
|
||||||
file.Seek(8, Common::FS::SeekOrigin::CurrentPosition);
|
|
||||||
|
|
||||||
auto currentPos = file.Tell();
|
|
||||||
|
|
||||||
// Try to figure out the name
|
|
||||||
const auto name = GetEntryNameByType(entry.id);
|
|
||||||
const auto filepath = extract_path / "sce_sys" / name;
|
|
||||||
std::filesystem::create_directories(filepath.parent_path());
|
|
||||||
|
|
||||||
if (name.empty()) {
|
|
||||||
// Just print with id
|
|
||||||
Common::FS::IOFile out(extract_path / "sce_sys" / std::to_string(entry.id),
|
|
||||||
Common::FS::FileAccessMode::Write);
|
|
||||||
if (!file.Seek(entry.offset)) {
|
|
||||||
failreason = "Failed to seek to PKG entry offset";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> data;
|
|
||||||
data.resize(entry.size);
|
|
||||||
file.ReadRaw<u8>(data.data(), entry.size);
|
|
||||||
out.WriteRaw<u8>(data.data(), entry.size);
|
|
||||||
out.Close();
|
|
||||||
|
|
||||||
file.Seek(currentPos);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.id == 0x1) { // DIGESTS, seek;
|
|
||||||
// file.Seek(entry.offset, fsSeekSet);
|
|
||||||
} else if (entry.id == 0x10) { // ENTRY_KEYS, seek;
|
|
||||||
file.Seek(entry.offset);
|
|
||||||
file.Read(seed_digest);
|
|
||||||
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
file.Read(digest1[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
file.Read(key1[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
PKG::crypto.RSA2048Decrypt(dk3_, key1[3], true); // decrypt DK3
|
|
||||||
} else if (entry.id == 0x20) { // IMAGE_KEY, seek; IV_KEY
|
|
||||||
file.Seek(entry.offset);
|
|
||||||
file.Read(imgkeydata);
|
|
||||||
|
|
||||||
// The Concatenated iv + dk3 imagekey for HASH256
|
|
||||||
std::memcpy(concatenated_ivkey_dk3.data(), &entry, sizeof(entry));
|
|
||||||
std::memcpy(concatenated_ivkey_dk3.data() + sizeof(entry), dk3_.data(), sizeof(dk3_));
|
|
||||||
|
|
||||||
PKG::crypto.ivKeyHASH256(concatenated_ivkey_dk3, ivKey); // ivkey_
|
|
||||||
// imgkey_ to use for last step to get ekpfs
|
|
||||||
PKG::crypto.aesCbcCfb128Decrypt(ivKey, imgkeydata, imgKey);
|
|
||||||
// ekpfs key to get data and tweak keys.
|
|
||||||
PKG::crypto.RSA2048Decrypt(ekpfsKey, imgKey, false);
|
|
||||||
} else if (entry.id == 0x80) {
|
|
||||||
// GENERAL_DIGESTS, seek;
|
|
||||||
// file.Seek(entry.offset, fsSeekSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
Common::FS::IOFile out(extract_path / "sce_sys" / name, Common::FS::FileAccessMode::Write);
|
|
||||||
if (!file.Seek(entry.offset)) {
|
|
||||||
failreason = "Failed to seek to PKG entry offset";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> data;
|
|
||||||
data.resize(entry.size);
|
|
||||||
file.ReadRaw<u8>(data.data(), entry.size);
|
|
||||||
out.WriteRaw<u8>(data.data(), entry.size);
|
|
||||||
out.Close();
|
|
||||||
|
|
||||||
// Decrypt Np stuff and overwrite.
|
|
||||||
if (entry.id == 0x400 || entry.id == 0x401 || entry.id == 0x402 ||
|
|
||||||
entry.id == 0x403) { // somehow 0x401 is not decrypting
|
|
||||||
decNp.resize(entry.size);
|
|
||||||
if (!file.Seek(entry.offset)) {
|
|
||||||
failreason = "Failed to seek to PKG entry offset";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> data;
|
|
||||||
data.resize(entry.size);
|
|
||||||
file.ReadRaw<u8>(data.data(), entry.size);
|
|
||||||
|
|
||||||
std::span<u8> cipherNp(data.data(), entry.size);
|
|
||||||
std::array<u8, 64> concatenated_ivkey_dk3_;
|
|
||||||
std::memcpy(concatenated_ivkey_dk3_.data(), &entry, sizeof(entry));
|
|
||||||
std::memcpy(concatenated_ivkey_dk3_.data() + sizeof(entry), dk3_.data(), sizeof(dk3_));
|
|
||||||
PKG::crypto.ivKeyHASH256(concatenated_ivkey_dk3_, ivKey);
|
|
||||||
PKG::crypto.aesCbcCfb128DecryptEntry(ivKey, cipherNp, decNp);
|
|
||||||
|
|
||||||
Common::FS::IOFile out(extract_path / "sce_sys" / name,
|
|
||||||
Common::FS::FileAccessMode::Write);
|
|
||||||
out.Write(decNp);
|
|
||||||
out.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
file.Seek(currentPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the seed
|
|
||||||
std::array<u8, 16> seed;
|
|
||||||
if (!file.Seek(pkgheader.pfs_image_offset + 0x370)) {
|
|
||||||
failreason = "Failed to seek to PFS image offset";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
file.Read(seed);
|
|
||||||
|
|
||||||
// Get data and tweak keys.
|
|
||||||
PKG::crypto.PfsGenCryptoKey(ekpfsKey, seed, dataKey, tweakKey);
|
|
||||||
const u32 length = pkgheader.pfs_cache_size * 0x2; // Seems to be ok.
|
|
||||||
|
|
||||||
int num_blocks = 0;
|
|
||||||
std::vector<u8> pfsc(length);
|
|
||||||
if (length != 0) {
|
|
||||||
// Read encrypted pfs_image
|
|
||||||
std::vector<u8> pfs_encrypted(length);
|
|
||||||
file.Seek(pkgheader.pfs_image_offset);
|
|
||||||
file.Read(pfs_encrypted);
|
|
||||||
file.Close();
|
|
||||||
// Decrypt the pfs_image.
|
|
||||||
std::vector<u8> pfs_decrypted(length);
|
|
||||||
PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0);
|
|
||||||
|
|
||||||
// Retrieve PFSC from decrypted pfs_image.
|
|
||||||
pfsc_offset = GetPFSCOffset(pfs_decrypted);
|
|
||||||
std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset);
|
|
||||||
|
|
||||||
PFSCHdr pfsChdr;
|
|
||||||
std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr));
|
|
||||||
|
|
||||||
num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2);
|
|
||||||
sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset.
|
|
||||||
|
|
||||||
for (int i = 0; i < num_blocks + 1; i++) {
|
|
||||||
std::memcpy(§orMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 ent_size = 0;
|
|
||||||
u32 ndinode = 0;
|
|
||||||
int ndinode_counter = 0;
|
|
||||||
bool dinode_reached = false;
|
|
||||||
bool uroot_reached = false;
|
|
||||||
std::vector<char> compressedData;
|
|
||||||
std::vector<char> decompressedData(0x10000);
|
|
||||||
|
|
||||||
// Get iNdoes and Dirents.
|
|
||||||
for (int i = 0; i < num_blocks; i++) {
|
|
||||||
const u64 sectorOffset = sectorMap[i];
|
|
||||||
const u64 sectorSize = sectorMap[i + 1] - sectorOffset;
|
|
||||||
|
|
||||||
compressedData.resize(sectorSize);
|
|
||||||
std::memcpy(compressedData.data(), pfsc.data() + sectorOffset, sectorSize);
|
|
||||||
|
|
||||||
if (sectorSize == 0x10000) // Uncompressed data
|
|
||||||
std::memcpy(decompressedData.data(), compressedData.data(), 0x10000);
|
|
||||||
else if (sectorSize < 0x10000) // Compressed data
|
|
||||||
DecompressPFSC(compressedData, decompressedData);
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
std::memcpy(&ndinode, decompressedData.data() + 0x30, 4); // number of folders and files
|
|
||||||
}
|
|
||||||
|
|
||||||
int occupied_blocks =
|
|
||||||
(ndinode * 0xA8) / 0x10000; // how many blocks(0x10000) are taken by iNodes.
|
|
||||||
if (((ndinode * 0xA8) % 0x10000) != 0)
|
|
||||||
occupied_blocks += 1;
|
|
||||||
|
|
||||||
if (i >= 1 && i <= occupied_blocks) { // Get all iNodes, gives type, file size and location.
|
|
||||||
for (int p = 0; p < 0x10000; p += 0xA8) {
|
|
||||||
Inode node;
|
|
||||||
std::memcpy(&node, &decompressedData[p], sizeof(node));
|
|
||||||
if (node.Mode == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
iNodeBuf.push_back(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// let's deal with the root/uroot entries here.
|
|
||||||
// Sometimes it's more than 2 entries (Tomb Raider Remastered)
|
|
||||||
const std::string_view flat_path_table(&decompressedData[0x10], 15);
|
|
||||||
if (flat_path_table == "flat_path_table") {
|
|
||||||
uroot_reached = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uroot_reached) {
|
|
||||||
for (int i = 0; i < 0x10000; i += ent_size) {
|
|
||||||
Dirent dirent;
|
|
||||||
std::memcpy(&dirent, &decompressedData[i], sizeof(dirent));
|
|
||||||
ent_size = dirent.entsize;
|
|
||||||
if (dirent.ino != 0) {
|
|
||||||
ndinode_counter++;
|
|
||||||
} else {
|
|
||||||
// Set the the folder according to the current inode.
|
|
||||||
// Can be 2 or more (rarely)
|
|
||||||
auto parent_path = extract_path.parent_path();
|
|
||||||
auto title_id = GetTitleID();
|
|
||||||
|
|
||||||
if (parent_path.filename() != title_id &&
|
|
||||||
!fmt::UTF(extract_path.u8string()).data.ends_with("-UPDATE")) {
|
|
||||||
extractPaths[ndinode_counter] = parent_path / title_id;
|
|
||||||
} else {
|
|
||||||
// DLCs path has different structure
|
|
||||||
extractPaths[ndinode_counter] = extract_path;
|
|
||||||
}
|
|
||||||
uroot_reached = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const char dot = decompressedData[0x10];
|
|
||||||
const std::string_view dotdot(&decompressedData[0x28], 2);
|
|
||||||
if (dot == '.' && dotdot == "..") {
|
|
||||||
dinode_reached = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get folder and file names.
|
|
||||||
bool end_reached = false;
|
|
||||||
if (dinode_reached) {
|
|
||||||
for (int j = 0; j < 0x10000; j += ent_size) { // Skip the first parent and child.
|
|
||||||
Dirent dirent;
|
|
||||||
std::memcpy(&dirent, &decompressedData[j], sizeof(dirent));
|
|
||||||
|
|
||||||
// Stop here and continue the main loop
|
|
||||||
if (dirent.ino == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ent_size = dirent.entsize;
|
|
||||||
auto& table = fsTable.emplace_back();
|
|
||||||
table.name = std::string(dirent.name, dirent.namelen);
|
|
||||||
table.inode = dirent.ino;
|
|
||||||
table.type = dirent.type;
|
|
||||||
|
|
||||||
if (table.type == PFS_CURRENT_DIR) {
|
|
||||||
current_dir = extractPaths[table.inode];
|
|
||||||
}
|
|
||||||
extractPaths[table.inode] = current_dir / std::filesystem::path(table.name);
|
|
||||||
|
|
||||||
if (table.type == PFS_FILE || table.type == PFS_DIR) {
|
|
||||||
if (table.type == PFS_DIR) { // Create dirs.
|
|
||||||
std::filesystem::create_directory(extractPaths[table.inode]);
|
|
||||||
}
|
|
||||||
ndinode_counter++;
|
|
||||||
if ((ndinode_counter + 1) == ndinode) // 1 for the image itself (root).
|
|
||||||
end_reached = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (end_reached) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PKG::ExtractFiles(const int index) {
|
|
||||||
int inode_number = fsTable[index].inode;
|
|
||||||
int inode_type = fsTable[index].type;
|
|
||||||
std::string inode_name = fsTable[index].name;
|
|
||||||
|
|
||||||
if (inode_type == PFS_FILE) {
|
|
||||||
int sector_loc = iNodeBuf[inode_number].loc;
|
|
||||||
int nblocks = iNodeBuf[inode_number].Blocks;
|
|
||||||
int bsize = iNodeBuf[inode_number].Size;
|
|
||||||
|
|
||||||
Common::FS::IOFile inflated;
|
|
||||||
inflated.Open(extractPaths[inode_number], Common::FS::FileAccessMode::Write);
|
|
||||||
|
|
||||||
Common::FS::IOFile pkgFile; // Open the file for each iteration to avoid conflict.
|
|
||||||
pkgFile.Open(pkgpath, Common::FS::FileAccessMode::Read);
|
|
||||||
|
|
||||||
int size_decompressed = 0;
|
|
||||||
std::vector<char> compressedData;
|
|
||||||
std::vector<char> decompressedData(0x10000);
|
|
||||||
|
|
||||||
u64 pfsc_buf_size = 0x11000; // extra 0x1000
|
|
||||||
std::vector<u8> pfsc(pfsc_buf_size);
|
|
||||||
std::vector<u8> pfs_decrypted(pfsc_buf_size);
|
|
||||||
|
|
||||||
for (int j = 0; j < nblocks; j++) {
|
|
||||||
u64 sectorOffset =
|
|
||||||
sectorMap[sector_loc + j]; // offset into PFSC_image and not pfs_image.
|
|
||||||
u64 sectorSize = sectorMap[sector_loc + j + 1] -
|
|
||||||
sectorOffset; // indicates if data is compressed or not.
|
|
||||||
u64 fileOffset = (pkgheader.pfs_image_offset + pfsc_offset + sectorOffset);
|
|
||||||
u64 currentSector1 =
|
|
||||||
(pfsc_offset + sectorOffset) / 0x1000; // block size is 0x1000 for xts decryption.
|
|
||||||
|
|
||||||
int sectorOffsetMask = (sectorOffset + pfsc_offset) & 0xFFFFF000;
|
|
||||||
int previousData = (sectorOffset + pfsc_offset) - sectorOffsetMask;
|
|
||||||
|
|
||||||
pkgFile.Seek(fileOffset - previousData);
|
|
||||||
pkgFile.Read(pfsc);
|
|
||||||
|
|
||||||
PKG::crypto.decryptPFS(dataKey, tweakKey, pfsc, pfs_decrypted, currentSector1);
|
|
||||||
|
|
||||||
compressedData.resize(sectorSize);
|
|
||||||
std::memcpy(compressedData.data(), pfs_decrypted.data() + previousData, sectorSize);
|
|
||||||
|
|
||||||
if (sectorSize == 0x10000) // Uncompressed data
|
|
||||||
std::memcpy(decompressedData.data(), compressedData.data(), 0x10000);
|
|
||||||
else if (sectorSize < 0x10000) // Compressed data
|
|
||||||
DecompressPFSC(compressedData, decompressedData);
|
|
||||||
|
|
||||||
size_decompressed += 0x10000;
|
|
||||||
|
|
||||||
if (j < nblocks - 1) {
|
|
||||||
inflated.WriteRaw<u8>(decompressedData.data(), decompressedData.size());
|
|
||||||
} else {
|
|
||||||
// This is to remove the zeros at the end of the file.
|
|
||||||
const u32 write_size = decompressedData.size() - (size_decompressed - bsize);
|
|
||||||
inflated.WriteRaw<u8>(decompressedData.data(), write_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pkgFile.Close();
|
|
||||||
inflated.Close();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,174 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
|
||||||
#include "common/endian.h"
|
|
||||||
#include "core/crypto/crypto.h"
|
|
||||||
#include "pfs.h"
|
|
||||||
#include "trp.h"
|
|
||||||
|
|
||||||
struct PKGHeader {
|
|
||||||
u32_be magic; // Magic
|
|
||||||
u32_be pkg_type;
|
|
||||||
u32_be pkg_0x8; // unknown field
|
|
||||||
u32_be pkg_file_count;
|
|
||||||
u32_be pkg_table_entry_count;
|
|
||||||
u16_be pkg_sc_entry_count;
|
|
||||||
u16_be pkg_table_entry_count_2; // same as pkg_entry_count
|
|
||||||
u32_be pkg_table_entry_offset; // file table offset
|
|
||||||
u32_be pkg_sc_entry_data_size;
|
|
||||||
u64_be pkg_body_offset; // offset of PKG entries
|
|
||||||
u64_be pkg_body_size; // length of all PKG entries
|
|
||||||
u64_be pkg_content_offset;
|
|
||||||
u64_be pkg_content_size;
|
|
||||||
u8 pkg_content_id[0x24]; // packages' content ID as a 36-byte string
|
|
||||||
u8 pkg_padding[0xC]; // padding
|
|
||||||
u32_be pkg_drm_type; // DRM type
|
|
||||||
u32_be pkg_content_type; // Content type
|
|
||||||
u32_be pkg_content_flags; // Content flags
|
|
||||||
u32_be pkg_promote_size;
|
|
||||||
u32_be pkg_version_date;
|
|
||||||
u32_be pkg_version_hash;
|
|
||||||
u32_be pkg_0x088;
|
|
||||||
u32_be pkg_0x08C;
|
|
||||||
u32_be pkg_0x090;
|
|
||||||
u32_be pkg_0x094;
|
|
||||||
u32_be pkg_iro_tag;
|
|
||||||
u32_be pkg_drm_type_version;
|
|
||||||
|
|
||||||
u8 pkg_zeroes_1[0x60];
|
|
||||||
|
|
||||||
/* Digest table */
|
|
||||||
u8 digest_entries1[0x20]; // sha256 digest for main entry 1
|
|
||||||
u8 digest_entries2[0x20]; // sha256 digest for main entry 2
|
|
||||||
u8 digest_table_digest[0x20]; // sha256 digest for digest table
|
|
||||||
u8 digest_body_digest[0x20]; // sha256 digest for main table
|
|
||||||
|
|
||||||
u8 pkg_zeroes_2[0x280];
|
|
||||||
|
|
||||||
u32_be pkg_0x400;
|
|
||||||
|
|
||||||
u32_be pfs_image_count; // count of PFS images
|
|
||||||
u64_be pfs_image_flags; // PFS flags
|
|
||||||
u64_be pfs_image_offset; // offset to start of external PFS image
|
|
||||||
u64_be pfs_image_size; // size of external PFS image
|
|
||||||
u64_be mount_image_offset;
|
|
||||||
u64_be mount_image_size;
|
|
||||||
u64_be pkg_size;
|
|
||||||
u32_be pfs_signed_size;
|
|
||||||
u32_be pfs_cache_size;
|
|
||||||
u8 pfs_image_digest[0x20];
|
|
||||||
u8 pfs_signed_digest[0x20];
|
|
||||||
u64_be pfs_split_size_nth_0;
|
|
||||||
u64_be pfs_split_size_nth_1;
|
|
||||||
|
|
||||||
u8 pkg_zeroes_3[0xB50];
|
|
||||||
|
|
||||||
u8 pkg_digest[0x20];
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class PKGContentFlag {
|
|
||||||
FIRST_PATCH = 0x100000,
|
|
||||||
PATCHGO = 0x200000,
|
|
||||||
REMASTER = 0x400000,
|
|
||||||
PS_CLOUD = 0x800000,
|
|
||||||
GD_AC = 0x2000000,
|
|
||||||
NON_GAME = 0x4000000,
|
|
||||||
UNKNOWN_0x8000000 = 0x8000000,
|
|
||||||
SUBSEQUENT_PATCH = 0x40000000,
|
|
||||||
DELTA_PATCH = 0x41000000,
|
|
||||||
CUMULATIVE_PATCH = 0x60000000
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PKGEntry {
|
|
||||||
u32_be id; // File ID, useful for files without a filename entry
|
|
||||||
u32_be filename_offset; // Offset into the filenames table (ID 0x200) where this file's name is
|
|
||||||
// located
|
|
||||||
u32_be flags1; // Flags including encrypted flag, etc
|
|
||||||
u32_be flags2; // Flags including encryption key index, etc
|
|
||||||
u32_be offset; // Offset into PKG to find the file
|
|
||||||
u32_be size; // Size of the file
|
|
||||||
u64_be padding; // blank padding
|
|
||||||
};
|
|
||||||
static_assert(sizeof(PKGEntry) == 32);
|
|
||||||
|
|
||||||
class PKG {
|
|
||||||
public:
|
|
||||||
PKG();
|
|
||||||
~PKG();
|
|
||||||
|
|
||||||
bool Open(const std::filesystem::path& filepath, std::string& failreason);
|
|
||||||
void ExtractFiles(const int index);
|
|
||||||
bool Extract(const std::filesystem::path& filepath, const std::filesystem::path& extract,
|
|
||||||
std::string& failreason);
|
|
||||||
|
|
||||||
std::vector<u8> sfo;
|
|
||||||
|
|
||||||
u32 GetNumberOfFiles() {
|
|
||||||
return fsTable.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 GetPkgSize() {
|
|
||||||
return pkgSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetPkgFlags() {
|
|
||||||
return pkgFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string_view GetTitleID() {
|
|
||||||
return std::string_view(pkgTitleID, 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
PKGHeader GetPkgHeader() {
|
|
||||||
return pkgheader;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isFlagSet(u32_be variable, PKGContentFlag flag) {
|
|
||||||
return (variable) & static_cast<u32>(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr std::array<std::pair<PKGContentFlag, std::string_view>, 10> flagNames = {
|
|
||||||
{{PKGContentFlag::FIRST_PATCH, "FIRST_PATCH"},
|
|
||||||
{PKGContentFlag::PATCHGO, "PATCHGO"},
|
|
||||||
{PKGContentFlag::REMASTER, "REMASTER"},
|
|
||||||
{PKGContentFlag::PS_CLOUD, "PS_CLOUD"},
|
|
||||||
{PKGContentFlag::GD_AC, "GD_AC"},
|
|
||||||
{PKGContentFlag::NON_GAME, "NON_GAME"},
|
|
||||||
{PKGContentFlag::UNKNOWN_0x8000000, "UNKNOWN_0x8000000"},
|
|
||||||
{PKGContentFlag::SUBSEQUENT_PATCH, "SUBSEQUENT_PATCH"},
|
|
||||||
{PKGContentFlag::DELTA_PATCH, "DELTA_PATCH"},
|
|
||||||
{PKGContentFlag::CUMULATIVE_PATCH, "CUMULATIVE_PATCH"}}};
|
|
||||||
|
|
||||||
private:
|
|
||||||
Crypto crypto;
|
|
||||||
TRP trp;
|
|
||||||
u64 pkgSize = 0;
|
|
||||||
char pkgTitleID[9];
|
|
||||||
PKGHeader pkgheader;
|
|
||||||
std::string pkgFlags;
|
|
||||||
|
|
||||||
std::unordered_map<int, std::filesystem::path> extractPaths;
|
|
||||||
std::vector<pfs_fs_table> fsTable;
|
|
||||||
std::vector<Inode> iNodeBuf;
|
|
||||||
std::vector<u64> sectorMap;
|
|
||||||
u64 pfsc_offset;
|
|
||||||
|
|
||||||
std::array<u8, 32> dk3_;
|
|
||||||
std::array<u8, 32> ivKey;
|
|
||||||
std::array<u8, 256> imgKey;
|
|
||||||
std::array<u8, 32> ekpfsKey;
|
|
||||||
std::array<u8, 16> dataKey;
|
|
||||||
std::array<u8, 16> tweakKey;
|
|
||||||
std::vector<u8> decNp;
|
|
||||||
|
|
||||||
std::filesystem::path pkgpath;
|
|
||||||
std::filesystem::path current_dir;
|
|
||||||
std::filesystem::path extract_path;
|
|
||||||
};
|
|
|
@ -1,638 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <array>
|
|
||||||
#include "pkg_type.h"
|
|
||||||
|
|
||||||
struct PkgEntryValue {
|
|
||||||
u32 type;
|
|
||||||
std::string_view name;
|
|
||||||
|
|
||||||
operator u32() const noexcept {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr static std::array<PkgEntryValue, 611> PkgEntries = {{
|
|
||||||
{0x0001, "digests"},
|
|
||||||
{0x0010, "entry_keys"},
|
|
||||||
{0x0020, "image_key"},
|
|
||||||
{0x0080, "general_digests"},
|
|
||||||
{0x0100, "metas"},
|
|
||||||
{0x0200, "entry_names"},
|
|
||||||
{0x0400, "license.dat"},
|
|
||||||
{0x0401, "license.info"},
|
|
||||||
{0x0402, "nptitle.dat"},
|
|
||||||
{0x0403, "npbind.dat"},
|
|
||||||
{0x0404, "selfinfo.dat"},
|
|
||||||
{0x0406, "imageinfo.dat"},
|
|
||||||
{0x0407, "target-deltainfo.dat"},
|
|
||||||
{0x0408, "origin-deltainfo.dat"},
|
|
||||||
{0x0409, "psreserved.dat"},
|
|
||||||
{0x1000, "param.sfo"},
|
|
||||||
{0x1001, "playgo-chunk.dat"},
|
|
||||||
{0x1002, "playgo-chunk.sha"},
|
|
||||||
{0x1003, "playgo-manifest.xml"},
|
|
||||||
{0x1004, "pronunciation.xml"},
|
|
||||||
{0x1005, "pronunciation.sig"},
|
|
||||||
{0x1006, "pic1.png"},
|
|
||||||
{0x1007, "pubtoolinfo.dat"},
|
|
||||||
{0x1008, "app/playgo-chunk.dat"},
|
|
||||||
{0x1009, "app/playgo-chunk.sha"},
|
|
||||||
{0x100A, "app/playgo-manifest.xml"},
|
|
||||||
{0x100B, "shareparam.json"},
|
|
||||||
{0x100C, "shareoverlayimage.png"},
|
|
||||||
{0x100D, "save_data.png"},
|
|
||||||
{0x100E, "shareprivacyguardimage.png"},
|
|
||||||
{0x1200, "icon0.png"},
|
|
||||||
{0x1201, "icon0_00.png"},
|
|
||||||
{0x1202, "icon0_01.png"},
|
|
||||||
{0x1203, "icon0_02.png"},
|
|
||||||
{0x1204, "icon0_03.png"},
|
|
||||||
{0x1205, "icon0_04.png"},
|
|
||||||
{0x1206, "icon0_05.png"},
|
|
||||||
{0x1207, "icon0_06.png"},
|
|
||||||
{0x1208, "icon0_07.png"},
|
|
||||||
{0x1209, "icon0_08.png"},
|
|
||||||
{0x120A, "icon0_09.png"},
|
|
||||||
{0x120B, "icon0_10.png"},
|
|
||||||
{0x120C, "icon0_11.png"},
|
|
||||||
{0x120D, "icon0_12.png"},
|
|
||||||
{0x120E, "icon0_13.png"},
|
|
||||||
{0x120F, "icon0_14.png"},
|
|
||||||
{0x1210, "icon0_15.png"},
|
|
||||||
{0x1211, "icon0_16.png"},
|
|
||||||
{0x1212, "icon0_17.png"},
|
|
||||||
{0x1213, "icon0_18.png"},
|
|
||||||
{0x1214, "icon0_19.png"},
|
|
||||||
{0x1215, "icon0_20.png"},
|
|
||||||
{0x1216, "icon0_21.png"},
|
|
||||||
{0x1217, "icon0_22.png"},
|
|
||||||
{0x1218, "icon0_23.png"},
|
|
||||||
{0x1219, "icon0_24.png"},
|
|
||||||
{0x121A, "icon0_25.png"},
|
|
||||||
{0x121B, "icon0_26.png"},
|
|
||||||
{0x121C, "icon0_27.png"},
|
|
||||||
{0x121D, "icon0_28.png"},
|
|
||||||
{0x121E, "icon0_29.png"},
|
|
||||||
{0x121F, "icon0_30.png"},
|
|
||||||
{0x1220, "pic0.png"},
|
|
||||||
{0x1240, "snd0.at9"},
|
|
||||||
{0x1241, "pic1_00.png"},
|
|
||||||
{0x1242, "pic1_01.png"},
|
|
||||||
{0x1243, "pic1_02.png"},
|
|
||||||
{0x1244, "pic1_03.png"},
|
|
||||||
{0x1245, "pic1_04.png"},
|
|
||||||
{0x1246, "pic1_05.png"},
|
|
||||||
{0x1247, "pic1_06.png"},
|
|
||||||
{0x1248, "pic1_07.png"},
|
|
||||||
{0x1249, "pic1_08.png"},
|
|
||||||
{0x124A, "pic1_09.png"},
|
|
||||||
{0x124B, "pic1_10.png"},
|
|
||||||
{0x124C, "pic1_11.png"},
|
|
||||||
{0x124D, "pic1_12.png"},
|
|
||||||
{0x124E, "pic1_13.png"},
|
|
||||||
{0x124F, "pic1_14.png"},
|
|
||||||
{0x1250, "pic1_15.png"},
|
|
||||||
{0x1251, "pic1_16.png"},
|
|
||||||
{0x1252, "pic1_17.png"},
|
|
||||||
{0x1253, "pic1_18.png"},
|
|
||||||
{0x1254, "pic1_19.png"},
|
|
||||||
{0x1255, "pic1_20.png"},
|
|
||||||
{0x1256, "pic1_21.png"},
|
|
||||||
{0x1257, "pic1_22.png"},
|
|
||||||
{0x1258, "pic1_23.png"},
|
|
||||||
{0x1259, "pic1_24.png"},
|
|
||||||
{0x125A, "pic1_25.png"},
|
|
||||||
{0x125B, "pic1_26.png"},
|
|
||||||
{0x125C, "pic1_27.png"},
|
|
||||||
{0x125D, "pic1_28.png"},
|
|
||||||
{0x125E, "pic1_29.png"},
|
|
||||||
{0x125F, "pic1_30.png"},
|
|
||||||
{0x1260, "changeinfo/changeinfo.xml"},
|
|
||||||
{0x1261, "changeinfo/changeinfo_00.xml"},
|
|
||||||
{0x1262, "changeinfo/changeinfo_01.xml"},
|
|
||||||
{0x1263, "changeinfo/changeinfo_02.xml"},
|
|
||||||
{0x1264, "changeinfo/changeinfo_03.xml"},
|
|
||||||
{0x1265, "changeinfo/changeinfo_04.xml"},
|
|
||||||
{0x1266, "changeinfo/changeinfo_05.xml"},
|
|
||||||
{0x1267, "changeinfo/changeinfo_06.xml"},
|
|
||||||
{0x1268, "changeinfo/changeinfo_07.xml"},
|
|
||||||
{0x1269, "changeinfo/changeinfo_08.xml"},
|
|
||||||
{0x126A, "changeinfo/changeinfo_09.xml"},
|
|
||||||
{0x126B, "changeinfo/changeinfo_10.xml"},
|
|
||||||
{0x126C, "changeinfo/changeinfo_11.xml"},
|
|
||||||
{0x126D, "changeinfo/changeinfo_12.xml"},
|
|
||||||
{0x126E, "changeinfo/changeinfo_13.xml"},
|
|
||||||
{0x126F, "changeinfo/changeinfo_14.xml"},
|
|
||||||
{0x1270, "changeinfo/changeinfo_15.xml"},
|
|
||||||
{0x1271, "changeinfo/changeinfo_16.xml"},
|
|
||||||
{0x1272, "changeinfo/changeinfo_17.xml"},
|
|
||||||
{0x1273, "changeinfo/changeinfo_18.xml"},
|
|
||||||
{0x1274, "changeinfo/changeinfo_19.xml"},
|
|
||||||
{0x1275, "changeinfo/changeinfo_20.xml"},
|
|
||||||
{0x1276, "changeinfo/changeinfo_21.xml"},
|
|
||||||
{0x1277, "changeinfo/changeinfo_22.xml"},
|
|
||||||
{0x1278, "changeinfo/changeinfo_23.xml"},
|
|
||||||
{0x1279, "changeinfo/changeinfo_24.xml"},
|
|
||||||
{0x127A, "changeinfo/changeinfo_25.xml"},
|
|
||||||
{0x127B, "changeinfo/changeinfo_26.xml"},
|
|
||||||
{0x127C, "changeinfo/changeinfo_27.xml"},
|
|
||||||
{0x127D, "changeinfo/changeinfo_28.xml"},
|
|
||||||
{0x127E, "changeinfo/changeinfo_29.xml"},
|
|
||||||
{0x127F, "changeinfo/changeinfo_30.xml"},
|
|
||||||
{0x1280, "icon0.dds"},
|
|
||||||
{0x1281, "icon0_00.dds"},
|
|
||||||
{0x1282, "icon0_01.dds"},
|
|
||||||
{0x1283, "icon0_02.dds"},
|
|
||||||
{0x1284, "icon0_03.dds"},
|
|
||||||
{0x1285, "icon0_04.dds"},
|
|
||||||
{0x1286, "icon0_05.dds"},
|
|
||||||
{0x1287, "icon0_06.dds"},
|
|
||||||
{0x1288, "icon0_07.dds"},
|
|
||||||
{0x1289, "icon0_08.dds"},
|
|
||||||
{0x128A, "icon0_09.dds"},
|
|
||||||
{0x128B, "icon0_10.dds"},
|
|
||||||
{0x128C, "icon0_11.dds"},
|
|
||||||
{0x128D, "icon0_12.dds"},
|
|
||||||
{0x128E, "icon0_13.dds"},
|
|
||||||
{0x128F, "icon0_14.dds"},
|
|
||||||
{0x1290, "icon0_15.dds"},
|
|
||||||
{0x1291, "icon0_16.dds"},
|
|
||||||
{0x1292, "icon0_17.dds"},
|
|
||||||
{0x1293, "icon0_18.dds"},
|
|
||||||
{0x1294, "icon0_19.dds"},
|
|
||||||
{0x1295, "icon0_20.dds"},
|
|
||||||
{0x1296, "icon0_21.dds"},
|
|
||||||
{0x1297, "icon0_22.dds"},
|
|
||||||
{0x1298, "icon0_23.dds"},
|
|
||||||
{0x1299, "icon0_24.dds"},
|
|
||||||
{0x129A, "icon0_25.dds"},
|
|
||||||
{0x129B, "icon0_26.dds"},
|
|
||||||
{0x129C, "icon0_27.dds"},
|
|
||||||
{0x129D, "icon0_28.dds"},
|
|
||||||
{0x129E, "icon0_29.dds"},
|
|
||||||
{0x129F, "icon0_30.dds"},
|
|
||||||
{0x12A0, "pic0.dds"},
|
|
||||||
{0x12C0, "pic1.dds"},
|
|
||||||
{0x12C1, "pic1_00.dds"},
|
|
||||||
{0x12C2, "pic1_01.dds"},
|
|
||||||
{0x12C3, "pic1_02.dds"},
|
|
||||||
{0x12C4, "pic1_03.dds"},
|
|
||||||
{0x12C5, "pic1_04.dds"},
|
|
||||||
{0x12C6, "pic1_05.dds"},
|
|
||||||
{0x12C7, "pic1_06.dds"},
|
|
||||||
{0x12C8, "pic1_07.dds"},
|
|
||||||
{0x12C9, "pic1_08.dds"},
|
|
||||||
{0x12CA, "pic1_09.dds"},
|
|
||||||
{0x12CB, "pic1_10.dds"},
|
|
||||||
{0x12CC, "pic1_11.dds"},
|
|
||||||
{0x12CD, "pic1_12.dds"},
|
|
||||||
{0x12CE, "pic1_13.dds"},
|
|
||||||
{0x12CF, "pic1_14.dds"},
|
|
||||||
{0x12D0, "pic1_15.dds"},
|
|
||||||
{0x12D1, "pic1_16.dds"},
|
|
||||||
{0x12D2, "pic1_17.dds"},
|
|
||||||
{0x12D3, "pic1_18.dds"},
|
|
||||||
{0x12D4, "pic1_19.dds"},
|
|
||||||
{0x12D5, "pic1_20.dds"},
|
|
||||||
{0x12D6, "pic1_21.dds"},
|
|
||||||
{0x12D7, "pic1_22.dds"},
|
|
||||||
{0x12D8, "pic1_23.dds"},
|
|
||||||
{0x12D9, "pic1_24.dds"},
|
|
||||||
{0x12DA, "pic1_25.dds"},
|
|
||||||
{0x12DB, "pic1_26.dds"},
|
|
||||||
{0x12DC, "pic1_27.dds"},
|
|
||||||
{0x12DD, "pic1_28.dds"},
|
|
||||||
{0x12DE, "pic1_29.dds"},
|
|
||||||
{0x12DF, "pic1_30.dds"},
|
|
||||||
{0x1400, "trophy/trophy00.trp"},
|
|
||||||
{0x1401, "trophy/trophy01.trp"},
|
|
||||||
{0x1402, "trophy/trophy02.trp"},
|
|
||||||
{0x1403, "trophy/trophy03.trp"},
|
|
||||||
{0x1404, "trophy/trophy04.trp"},
|
|
||||||
{0x1405, "trophy/trophy05.trp"},
|
|
||||||
{0x1406, "trophy/trophy06.trp"},
|
|
||||||
{0x1407, "trophy/trophy07.trp"},
|
|
||||||
{0x1408, "trophy/trophy08.trp"},
|
|
||||||
{0x1409, "trophy/trophy09.trp"},
|
|
||||||
{0x140A, "trophy/trophy10.trp"},
|
|
||||||
{0x140B, "trophy/trophy11.trp"},
|
|
||||||
{0x140C, "trophy/trophy12.trp"},
|
|
||||||
{0x140D, "trophy/trophy13.trp"},
|
|
||||||
{0x140E, "trophy/trophy14.trp"},
|
|
||||||
{0x140F, "trophy/trophy15.trp"},
|
|
||||||
{0x1410, "trophy/trophy16.trp"},
|
|
||||||
{0x1411, "trophy/trophy17.trp"},
|
|
||||||
{0x1412, "trophy/trophy18.trp"},
|
|
||||||
{0x1413, "trophy/trophy19.trp"},
|
|
||||||
{0x1414, "trophy/trophy20.trp"},
|
|
||||||
{0x1415, "trophy/trophy21.trp"},
|
|
||||||
{0x1416, "trophy/trophy22.trp"},
|
|
||||||
{0x1417, "trophy/trophy23.trp"},
|
|
||||||
{0x1418, "trophy/trophy24.trp"},
|
|
||||||
{0x1419, "trophy/trophy25.trp"},
|
|
||||||
{0x141A, "trophy/trophy26.trp"},
|
|
||||||
{0x141B, "trophy/trophy27.trp"},
|
|
||||||
{0x141C, "trophy/trophy28.trp"},
|
|
||||||
{0x141D, "trophy/trophy29.trp"},
|
|
||||||
{0x141E, "trophy/trophy30.trp"},
|
|
||||||
{0x141F, "trophy/trophy31.trp"},
|
|
||||||
{0x1420, "trophy/trophy32.trp"},
|
|
||||||
{0x1421, "trophy/trophy33.trp"},
|
|
||||||
{0x1422, "trophy/trophy34.trp"},
|
|
||||||
{0x1423, "trophy/trophy35.trp"},
|
|
||||||
{0x1424, "trophy/trophy36.trp"},
|
|
||||||
{0x1425, "trophy/trophy37.trp"},
|
|
||||||
{0x1426, "trophy/trophy38.trp"},
|
|
||||||
{0x1427, "trophy/trophy39.trp"},
|
|
||||||
{0x1428, "trophy/trophy40.trp"},
|
|
||||||
{0x1429, "trophy/trophy41.trp"},
|
|
||||||
{0x142A, "trophy/trophy42.trp"},
|
|
||||||
{0x142B, "trophy/trophy43.trp"},
|
|
||||||
{0x142C, "trophy/trophy44.trp"},
|
|
||||||
{0x142D, "trophy/trophy45.trp"},
|
|
||||||
{0x142E, "trophy/trophy46.trp"},
|
|
||||||
{0x142F, "trophy/trophy47.trp"},
|
|
||||||
{0x1430, "trophy/trophy48.trp"},
|
|
||||||
{0x1431, "trophy/trophy49.trp"},
|
|
||||||
{0x1432, "trophy/trophy50.trp"},
|
|
||||||
{0x1433, "trophy/trophy51.trp"},
|
|
||||||
{0x1434, "trophy/trophy52.trp"},
|
|
||||||
{0x1435, "trophy/trophy53.trp"},
|
|
||||||
{0x1436, "trophy/trophy54.trp"},
|
|
||||||
{0x1437, "trophy/trophy55.trp"},
|
|
||||||
{0x1438, "trophy/trophy56.trp"},
|
|
||||||
{0x1439, "trophy/trophy57.trp"},
|
|
||||||
{0x143A, "trophy/trophy58.trp"},
|
|
||||||
{0x143B, "trophy/trophy59.trp"},
|
|
||||||
{0x143C, "trophy/trophy60.trp"},
|
|
||||||
{0x143D, "trophy/trophy61.trp"},
|
|
||||||
{0x143E, "trophy/trophy62.trp"},
|
|
||||||
{0x143F, "trophy/trophy63.trp"},
|
|
||||||
{0x1440, "trophy/trophy64.trp"},
|
|
||||||
{0x1441, "trophy/trophy65.trp"},
|
|
||||||
{0x1442, "trophy/trophy66.trp"},
|
|
||||||
{0x1443, "trophy/trophy67.trp"},
|
|
||||||
{0x1444, "trophy/trophy68.trp"},
|
|
||||||
{0x1445, "trophy/trophy69.trp"},
|
|
||||||
{0x1446, "trophy/trophy70.trp"},
|
|
||||||
{0x1447, "trophy/trophy71.trp"},
|
|
||||||
{0x1448, "trophy/trophy72.trp"},
|
|
||||||
{0x1449, "trophy/trophy73.trp"},
|
|
||||||
{0x144A, "trophy/trophy74.trp"},
|
|
||||||
{0x144B, "trophy/trophy75.trp"},
|
|
||||||
{0x144C, "trophy/trophy76.trp"},
|
|
||||||
{0x144D, "trophy/trophy77.trp"},
|
|
||||||
{0x144E, "trophy/trophy78.trp"},
|
|
||||||
{0x144F, "trophy/trophy79.trp"},
|
|
||||||
{0x1450, "trophy/trophy80.trp"},
|
|
||||||
{0x1451, "trophy/trophy81.trp"},
|
|
||||||
{0x1452, "trophy/trophy82.trp"},
|
|
||||||
{0x1453, "trophy/trophy83.trp"},
|
|
||||||
{0x1454, "trophy/trophy84.trp"},
|
|
||||||
{0x1455, "trophy/trophy85.trp"},
|
|
||||||
{0x1456, "trophy/trophy86.trp"},
|
|
||||||
{0x1457, "trophy/trophy87.trp"},
|
|
||||||
{0x1458, "trophy/trophy88.trp"},
|
|
||||||
{0x1459, "trophy/trophy89.trp"},
|
|
||||||
{0x145A, "trophy/trophy90.trp"},
|
|
||||||
{0x145B, "trophy/trophy91.trp"},
|
|
||||||
{0x145C, "trophy/trophy92.trp"},
|
|
||||||
{0x145D, "trophy/trophy93.trp"},
|
|
||||||
{0x145E, "trophy/trophy94.trp"},
|
|
||||||
{0x145F, "trophy/trophy95.trp"},
|
|
||||||
{0x1460, "trophy/trophy96.trp"},
|
|
||||||
{0x1461, "trophy/trophy97.trp"},
|
|
||||||
{0x1462, "trophy/trophy98.trp"},
|
|
||||||
{0x1463, "trophy/trophy99.trp"},
|
|
||||||
{0x1600, "keymap_rp/001.png"},
|
|
||||||
{0x1601, "keymap_rp/002.png"},
|
|
||||||
{0x1602, "keymap_rp/003.png"},
|
|
||||||
{0x1603, "keymap_rp/004.png"},
|
|
||||||
{0x1604, "keymap_rp/005.png"},
|
|
||||||
{0x1605, "keymap_rp/006.png"},
|
|
||||||
{0x1606, "keymap_rp/007.png"},
|
|
||||||
{0x1607, "keymap_rp/008.png"},
|
|
||||||
{0x1608, "keymap_rp/009.png"},
|
|
||||||
{0x1609, "keymap_rp/010.png"},
|
|
||||||
{0x1610, "keymap_rp/00/001.png"},
|
|
||||||
{0x1611, "keymap_rp/00/002.png"},
|
|
||||||
{0x1612, "keymap_rp/00/003.png"},
|
|
||||||
{0x1613, "keymap_rp/00/004.png"},
|
|
||||||
{0x1614, "keymap_rp/00/005.png"},
|
|
||||||
{0x1615, "keymap_rp/00/006.png"},
|
|
||||||
{0x1616, "keymap_rp/00/007.png"},
|
|
||||||
{0x1617, "keymap_rp/00/008.png"},
|
|
||||||
{0x1618, "keymap_rp/00/009.png"},
|
|
||||||
{0x1619, "keymap_rp/00/010.png"},
|
|
||||||
{0x1620, "keymap_rp/01/001.png"},
|
|
||||||
{0x1621, "keymap_rp/01/002.png"},
|
|
||||||
{0x1622, "keymap_rp/01/003.png"},
|
|
||||||
{0x1623, "keymap_rp/01/004.png"},
|
|
||||||
{0x1624, "keymap_rp/01/005.png"},
|
|
||||||
{0x1625, "keymap_rp/01/006.png"},
|
|
||||||
{0x1626, "keymap_rp/01/007.png"},
|
|
||||||
{0x1627, "keymap_rp/01/008.png"},
|
|
||||||
{0x1628, "keymap_rp/01/009.png"},
|
|
||||||
{0x1629, "keymap_rp/01/010.png"},
|
|
||||||
{0x1630, "keymap_rp/02/001.png"},
|
|
||||||
{0x1631, "keymap_rp/02/002.png"},
|
|
||||||
{0x1632, "keymap_rp/02/003.png"},
|
|
||||||
{0x1633, "keymap_rp/02/004.png"},
|
|
||||||
{0x1634, "keymap_rp/02/005.png"},
|
|
||||||
{0x1635, "keymap_rp/02/006.png"},
|
|
||||||
{0x1636, "keymap_rp/02/007.png"},
|
|
||||||
{0x1637, "keymap_rp/02/008.png"},
|
|
||||||
{0x1638, "keymap_rp/02/009.png"},
|
|
||||||
{0x1639, "keymap_rp/02/010.png"},
|
|
||||||
{0x1640, "keymap_rp/03/001.png"},
|
|
||||||
{0x1641, "keymap_rp/03/002.png"},
|
|
||||||
{0x1642, "keymap_rp/03/003.png"},
|
|
||||||
{0x1643, "keymap_rp/03/004.png"},
|
|
||||||
{0x1644, "keymap_rp/03/005.png"},
|
|
||||||
{0x1645, "keymap_rp/03/006.png"},
|
|
||||||
{0x1646, "keymap_rp/03/007.png"},
|
|
||||||
{0x1647, "keymap_rp/03/008.png"},
|
|
||||||
{0x1648, "keymap_rp/03/0010.png"},
|
|
||||||
{0x1650, "keymap_rp/04/001.png"},
|
|
||||||
{0x1651, "keymap_rp/04/002.png"},
|
|
||||||
{0x1652, "keymap_rp/04/003.png"},
|
|
||||||
{0x1653, "keymap_rp/04/004.png"},
|
|
||||||
{0x1654, "keymap_rp/04/005.png"},
|
|
||||||
{0x1655, "keymap_rp/04/006.png"},
|
|
||||||
{0x1656, "keymap_rp/04/007.png"},
|
|
||||||
{0x1657, "keymap_rp/04/008.png"},
|
|
||||||
{0x1658, "keymap_rp/04/009.png"},
|
|
||||||
{0x1659, "keymap_rp/04/010.png"},
|
|
||||||
{0x1660, "keymap_rp/05/001.png"},
|
|
||||||
{0x1661, "keymap_rp/05/002.png"},
|
|
||||||
{0x1662, "keymap_rp/05/003.png"},
|
|
||||||
{0x1663, "keymap_rp/05/004.png"},
|
|
||||||
{0x1664, "keymap_rp/05/005.png"},
|
|
||||||
{0x1665, "keymap_rp/05/006.png"},
|
|
||||||
{0x1666, "keymap_rp/05/007.png"},
|
|
||||||
{0x1667, "keymap_rp/05/008.png"},
|
|
||||||
{0x1668, "keymap_rp/05/009.png"},
|
|
||||||
{0x1669, "keymap_rp/05/010.png"},
|
|
||||||
{0x1670, "keymap_rp/06/001.png"},
|
|
||||||
{0x1671, "keymap_rp/06/002.png"},
|
|
||||||
{0x1672, "keymap_rp/06/003.png"},
|
|
||||||
{0x1673, "keymap_rp/06/004.png"},
|
|
||||||
{0x1674, "keymap_rp/06/005.png"},
|
|
||||||
{0x1675, "keymap_rp/06/006.png"},
|
|
||||||
{0x1676, "keymap_rp/06/007.png"},
|
|
||||||
{0x1677, "keymap_rp/06/008.png"},
|
|
||||||
{0x1678, "keymap_rp/06/009.png"},
|
|
||||||
{0x1679, "keymap_rp/06/010.png"},
|
|
||||||
{0x1680, "keymap_rp/07/001.png"},
|
|
||||||
{0x1681, "keymap_rp/07/002.png"},
|
|
||||||
{0x1682, "keymap_rp/07/003.png"},
|
|
||||||
{0x1683, "keymap_rp/07/004.png"},
|
|
||||||
{0x1684, "keymap_rp/07/005.png"},
|
|
||||||
{0x1685, "keymap_rp/07/006.png"},
|
|
||||||
{0x1686, "keymap_rp/07/007.png"},
|
|
||||||
{0x1687, "keymap_rp/07/008.png"},
|
|
||||||
{0x1688, "keymap_rp/07/009.png"},
|
|
||||||
{0x1689, "keymap_rp/07/010.png"},
|
|
||||||
{0x1690, "keymap_rp/08/001.png"},
|
|
||||||
{0x1691, "keymap_rp/08/002.png"},
|
|
||||||
{0x1692, "keymap_rp/08/003.png"},
|
|
||||||
{0x1693, "keymap_rp/08/004.png"},
|
|
||||||
{0x1694, "keymap_rp/08/005.png"},
|
|
||||||
{0x1695, "keymap_rp/08/006.png"},
|
|
||||||
{0x1696, "keymap_rp/08/007.png"},
|
|
||||||
{0x1697, "keymap_rp/08/008.png"},
|
|
||||||
{0x1698, "keymap_rp/08/009.png"},
|
|
||||||
{0x1699, "keymap_rp/08/010.png"},
|
|
||||||
{0x16A0, "keymap_rp/09/001.png"},
|
|
||||||
{0x16A1, "keymap_rp/09/002.png"},
|
|
||||||
{0x16A2, "keymap_rp/09/003.png"},
|
|
||||||
{0x16A3, "keymap_rp/09/004.png"},
|
|
||||||
{0x16A4, "keymap_rp/09/005.png"},
|
|
||||||
{0x16A5, "keymap_rp/09/006.png"},
|
|
||||||
{0x16A6, "keymap_rp/09/007.png"},
|
|
||||||
{0x16A7, "keymap_rp/09/008.png"},
|
|
||||||
{0x16A8, "keymap_rp/09/009.png"},
|
|
||||||
{0x16A9, "keymap_rp/09/010.png"},
|
|
||||||
{0x16B0, "keymap_rp/10/001.png"},
|
|
||||||
{0x16B1, "keymap_rp/10/002.png"},
|
|
||||||
{0x16B2, "keymap_rp/10/003.png"},
|
|
||||||
{0x16B3, "keymap_rp/10/004.png"},
|
|
||||||
{0x16B4, "keymap_rp/10/005.png"},
|
|
||||||
{0x16B5, "keymap_rp/10/006.png"},
|
|
||||||
{0x16B6, "keymap_rp/10/007.png"},
|
|
||||||
{0x16B7, "keymap_rp/10/008.png"},
|
|
||||||
{0x16B8, "keymap_rp/10/009.png"},
|
|
||||||
{0x16B9, "keymap_rp/10/010.png"},
|
|
||||||
{0x16C0, "keymap_rp/11/001.png"},
|
|
||||||
{0x16C1, "keymap_rp/11/002.png"},
|
|
||||||
{0x16C2, "keymap_rp/11/003.png"},
|
|
||||||
{0x16C3, "keymap_rp/11/004.png"},
|
|
||||||
{0x16C4, "keymap_rp/11/005.png"},
|
|
||||||
{0x16C5, "keymap_rp/11/006.png"},
|
|
||||||
{0x16C6, "keymap_rp/11/007.png"},
|
|
||||||
{0x16C7, "keymap_rp/11/008.png"},
|
|
||||||
{0x16C8, "keymap_rp/11/009.png"},
|
|
||||||
{0x16C9, "keymap_rp/11/010.png"},
|
|
||||||
{0x16D0, "keymap_rp/12/001.png"},
|
|
||||||
{0x16D1, "keymap_rp/12/002.png"},
|
|
||||||
{0x16D2, "keymap_rp/12/003.png"},
|
|
||||||
{0x16D3, "keymap_rp/12/004.png"},
|
|
||||||
{0x16D4, "keymap_rp/12/005.png"},
|
|
||||||
{0x16D5, "keymap_rp/12/006.png"},
|
|
||||||
{0x16D6, "keymap_rp/12/007.png"},
|
|
||||||
{0x16D7, "keymap_rp/12/008.png"},
|
|
||||||
{0x16D8, "keymap_rp/12/009.png"},
|
|
||||||
{0x16D9, "keymap_rp/12/010.png"},
|
|
||||||
{0x16E0, "keymap_rp/13/001.png"},
|
|
||||||
{0x16E1, "keymap_rp/13/002.png"},
|
|
||||||
{0x16E2, "keymap_rp/13/003.png"},
|
|
||||||
{0x16E3, "keymap_rp/13/004.png"},
|
|
||||||
{0x16E4, "keymap_rp/13/005.png"},
|
|
||||||
{0x16E5, "keymap_rp/13/006.png"},
|
|
||||||
{0x16E6, "keymap_rp/13/007.png"},
|
|
||||||
{0x16E7, "keymap_rp/13/008.png"},
|
|
||||||
{0x16E8, "keymap_rp/13/009.png"},
|
|
||||||
{0x16E9, "keymap_rp/13/010.png"},
|
|
||||||
{0x16F0, "keymap_rp/14/001.png"},
|
|
||||||
{0x16F1, "keymap_rp/14/002.png"},
|
|
||||||
{0x16F2, "keymap_rp/14/003.png"},
|
|
||||||
{0x16F3, "keymap_rp/14/004.png"},
|
|
||||||
{0x16F4, "keymap_rp/14/005.png"},
|
|
||||||
{0x16F5, "keymap_rp/14/006.png"},
|
|
||||||
{0x16F6, "keymap_rp/14/007.png"},
|
|
||||||
{0x16F7, "keymap_rp/14/008.png"},
|
|
||||||
{0x16F8, "keymap_rp/14/009.png"},
|
|
||||||
{0x16F9, "keymap_rp/14/010.png"},
|
|
||||||
{0x1700, "keymap_rp/15/001.png"},
|
|
||||||
{0x1701, "keymap_rp/15/002.png"},
|
|
||||||
{0x1702, "keymap_rp/15/003.png"},
|
|
||||||
{0x1703, "keymap_rp/15/004.png"},
|
|
||||||
{0x1704, "keymap_rp/15/005.png"},
|
|
||||||
{0x1705, "keymap_rp/15/006.png"},
|
|
||||||
{0x1706, "keymap_rp/15/007.png"},
|
|
||||||
{0x1707, "keymap_rp/15/008.png"},
|
|
||||||
{0x1708, "keymap_rp/15/009.png"},
|
|
||||||
{0x1709, "keymap_rp/15/010.png"},
|
|
||||||
{0x1710, "keymap_rp/16/001.png"},
|
|
||||||
{0x1711, "keymap_rp/16/002.png"},
|
|
||||||
{0x1712, "keymap_rp/16/003.png"},
|
|
||||||
{0x1713, "keymap_rp/16/004.png"},
|
|
||||||
{0x1714, "keymap_rp/16/005.png"},
|
|
||||||
{0x1715, "keymap_rp/16/006.png"},
|
|
||||||
{0x1716, "keymap_rp/16/007.png"},
|
|
||||||
{0x1717, "keymap_rp/16/008.png"},
|
|
||||||
{0x1718, "keymap_rp/16/009.png"},
|
|
||||||
{0x1719, "keymap_rp/16/010.png"},
|
|
||||||
{0x1720, "keymap_rp/17/001.png"},
|
|
||||||
{0x1721, "keymap_rp/17/002.png"},
|
|
||||||
{0x1722, "keymap_rp/17/003.png"},
|
|
||||||
{0x1723, "keymap_rp/17/004.png"},
|
|
||||||
{0x1724, "keymap_rp/17/005.png"},
|
|
||||||
{0x1725, "keymap_rp/17/006.png"},
|
|
||||||
{0x1726, "keymap_rp/17/007.png"},
|
|
||||||
{0x1727, "keymap_rp/17/008.png"},
|
|
||||||
{0x1728, "keymap_rp/17/009.png"},
|
|
||||||
{0x1729, "keymap_rp/17/010.png"},
|
|
||||||
{0x1730, "keymap_rp/18/001.png"},
|
|
||||||
{0x1731, "keymap_rp/18/002.png"},
|
|
||||||
{0x1732, "keymap_rp/18/003.png"},
|
|
||||||
{0x1733, "keymap_rp/18/004.png"},
|
|
||||||
{0x1734, "keymap_rp/18/005.png"},
|
|
||||||
{0x1735, "keymap_rp/18/006.png"},
|
|
||||||
{0x1736, "keymap_rp/18/007.png"},
|
|
||||||
{0x1737, "keymap_rp/18/008.png"},
|
|
||||||
{0x1738, "keymap_rp/18/009.png"},
|
|
||||||
{0x1739, "keymap_rp/18/010.png"},
|
|
||||||
{0x1740, "keymap_rp/19/001.png"},
|
|
||||||
{0x1741, "keymap_rp/19/002.png"},
|
|
||||||
{0x1742, "keymap_rp/19/003.png"},
|
|
||||||
{0x1743, "keymap_rp/19/004.png"},
|
|
||||||
{0x1744, "keymap_rp/19/005.png"},
|
|
||||||
{0x1745, "keymap_rp/19/006.png"},
|
|
||||||
{0x1746, "keymap_rp/19/007.png"},
|
|
||||||
{0x1747, "keymap_rp/19/008.png"},
|
|
||||||
{0x1748, "keymap_rp/19/009.png"},
|
|
||||||
{0x1749, "keymap_rp/19/010.png"},
|
|
||||||
{0x1750, "keymap_rp/20/001.png"},
|
|
||||||
{0x1751, "keymap_rp/20/002.png"},
|
|
||||||
{0x1752, "keymap_rp/20/003.png"},
|
|
||||||
{0x1753, "keymap_rp/20/004.png"},
|
|
||||||
{0x1754, "keymap_rp/20/005.png"},
|
|
||||||
{0x1755, "keymap_rp/20/006.png"},
|
|
||||||
{0x1756, "keymap_rp/20/007.png"},
|
|
||||||
{0x1757, "keymap_rp/20/008.png"},
|
|
||||||
{0x1758, "keymap_rp/20/009.png"},
|
|
||||||
{0x1759, "keymap_rp/20/010.png"},
|
|
||||||
{0x1760, "keymap_rp/21/001.png"},
|
|
||||||
{0x1761, "keymap_rp/21/002.png"},
|
|
||||||
{0x1762, "keymap_rp/21/003.png"},
|
|
||||||
{0x1763, "keymap_rp/21/004.png"},
|
|
||||||
{0x1764, "keymap_rp/21/005.png"},
|
|
||||||
{0x1765, "keymap_rp/21/006.png"},
|
|
||||||
{0x1766, "keymap_rp/21/007.png"},
|
|
||||||
{0x1767, "keymap_rp/21/008.png"},
|
|
||||||
{0x1768, "keymap_rp/21/009.png"},
|
|
||||||
{0x1769, "keymap_rp/21/010.png"},
|
|
||||||
{0x1770, "keymap_rp/22/001.png"},
|
|
||||||
{0x1771, "keymap_rp/22/002.png"},
|
|
||||||
{0x1772, "keymap_rp/22/003.png"},
|
|
||||||
{0x1773, "keymap_rp/22/004.png"},
|
|
||||||
{0x1774, "keymap_rp/22/005.png"},
|
|
||||||
{0x1775, "keymap_rp/22/006.png"},
|
|
||||||
{0x1776, "keymap_rp/22/007.png"},
|
|
||||||
{0x1777, "keymap_rp/22/008.png"},
|
|
||||||
{0x1778, "keymap_rp/22/009.png"},
|
|
||||||
{0x1779, "keymap_rp/22/010.png"},
|
|
||||||
{0x1780, "keymap_rp/23/001.png"},
|
|
||||||
{0x1781, "keymap_rp/23/002.png"},
|
|
||||||
{0x1782, "keymap_rp/23/003.png"},
|
|
||||||
{0x1783, "keymap_rp/23/004.png"},
|
|
||||||
{0x1784, "keymap_rp/23/005.png"},
|
|
||||||
{0x1785, "keymap_rp/23/006.png"},
|
|
||||||
{0x1786, "keymap_rp/23/007.png"},
|
|
||||||
{0x1787, "keymap_rp/23/008.png"},
|
|
||||||
{0x1788, "keymap_rp/23/009.png"},
|
|
||||||
{0x1789, "keymap_rp/23/010.png"},
|
|
||||||
{0x1790, "keymap_rp/24/001.png"},
|
|
||||||
{0x1791, "keymap_rp/24/002.png"},
|
|
||||||
{0x1792, "keymap_rp/24/003.png"},
|
|
||||||
{0x1793, "keymap_rp/24/004.png"},
|
|
||||||
{0x1794, "keymap_rp/24/005.png"},
|
|
||||||
{0x1795, "keymap_rp/24/006.png"},
|
|
||||||
{0x1796, "keymap_rp/24/007.png"},
|
|
||||||
{0x1797, "keymap_rp/24/008.png"},
|
|
||||||
{0x1798, "keymap_rp/24/009.png"},
|
|
||||||
{0x1799, "keymap_rp/24/010.png"},
|
|
||||||
{0x17A0, "keymap_rp/25/001.png"},
|
|
||||||
{0x17A1, "keymap_rp/25/002.png"},
|
|
||||||
{0x17A2, "keymap_rp/25/003.png"},
|
|
||||||
{0x17A3, "keymap_rp/25/004.png"},
|
|
||||||
{0x17A4, "keymap_rp/25/005.png"},
|
|
||||||
{0x17A5, "keymap_rp/25/006.png"},
|
|
||||||
{0x17A6, "keymap_rp/25/007.png"},
|
|
||||||
{0x17A7, "keymap_rp/25/008.png"},
|
|
||||||
{0x17A8, "keymap_rp/25/009.png"},
|
|
||||||
{0x17A9, "keymap_rp/25/010.png"},
|
|
||||||
{0x17B0, "keymap_rp/26/001.png"},
|
|
||||||
{0x17B1, "keymap_rp/26/002.png"},
|
|
||||||
{0x17B2, "keymap_rp/26/003.png"},
|
|
||||||
{0x17B3, "keymap_rp/26/004.png"},
|
|
||||||
{0x17B4, "keymap_rp/26/005.png"},
|
|
||||||
{0x17B5, "keymap_rp/26/006.png"},
|
|
||||||
{0x17B6, "keymap_rp/26/007.png"},
|
|
||||||
{0x17B7, "keymap_rp/26/008.png"},
|
|
||||||
{0x17B8, "keymap_rp/26/009.png"},
|
|
||||||
{0x17B9, "keymap_rp/26/010.png"},
|
|
||||||
{0x17C0, "keymap_rp/27/001.png"},
|
|
||||||
{0x17C1, "keymap_rp/27/002.png"},
|
|
||||||
{0x17C2, "keymap_rp/27/003.png"},
|
|
||||||
{0x17C3, "keymap_rp/27/004.png"},
|
|
||||||
{0x17C4, "keymap_rp/27/005.png"},
|
|
||||||
{0x17C5, "keymap_rp/27/006.png"},
|
|
||||||
{0x17C6, "keymap_rp/27/007.png"},
|
|
||||||
{0x17C7, "keymap_rp/27/008.png"},
|
|
||||||
{0x17C8, "keymap_rp/27/009.png"},
|
|
||||||
{0x17C9, "keymap_rp/27/010.png"},
|
|
||||||
{0x17D0, "keymap_rp/28/001.png"},
|
|
||||||
{0x17D1, "keymap_rp/28/002.png"},
|
|
||||||
{0x17D2, "keymap_rp/28/003.png"},
|
|
||||||
{0x17D3, "keymap_rp/28/004.png"},
|
|
||||||
{0x17D4, "keymap_rp/28/005.png"},
|
|
||||||
{0x17D5, "keymap_rp/28/006.png"},
|
|
||||||
{0x17D6, "keymap_rp/28/007.png"},
|
|
||||||
{0x17D7, "keymap_rp/28/008.png"},
|
|
||||||
{0x17D8, "keymap_rp/28/009.png"},
|
|
||||||
{0x17D9, "keymap_rp/28/010.png"},
|
|
||||||
{0x17E0, "keymap_rp/29/001.png"},
|
|
||||||
{0x17E1, "keymap_rp/29/002.png"},
|
|
||||||
{0x17E2, "keymap_rp/29/003.png"},
|
|
||||||
{0x17E3, "keymap_rp/29/004.png"},
|
|
||||||
{0x17E4, "keymap_rp/29/005.png"},
|
|
||||||
{0x17E5, "keymap_rp/29/006.png"},
|
|
||||||
{0x17E6, "keymap_rp/29/007.png"},
|
|
||||||
{0x17E7, "keymap_rp/29/008.png"},
|
|
||||||
{0x17E8, "keymap_rp/29/009.png"},
|
|
||||||
{0x17E9, "keymap_rp/29/010.png"},
|
|
||||||
{0x17F0, "keymap_rp/30/001.png"},
|
|
||||||
{0x17F1, "keymap_rp/30/002.png"},
|
|
||||||
{0x17F2, "keymap_rp/30/003.png"},
|
|
||||||
{0x17F3, "keymap_rp/30/004.png"},
|
|
||||||
{0x17F4, "keymap_rp/30/005.png"},
|
|
||||||
{0x17F5, "keymap_rp/30/006.png"},
|
|
||||||
{0x17F6, "keymap_rp/30/007.png"},
|
|
||||||
{0x17F7, "keymap_rp/30/008.png"},
|
|
||||||
{0x17F8, "keymap_rp/30/009.png"},
|
|
||||||
{0x17F9, "keymap_rp/30/010.png"},
|
|
||||||
}};
|
|
||||||
|
|
||||||
std::string_view GetEntryNameByType(u32 type) {
|
|
||||||
const auto key = PkgEntryValue{type};
|
|
||||||
const auto it = std::ranges::lower_bound(PkgEntries, key);
|
|
||||||
if (it != PkgEntries.end() && it->type == type) {
|
|
||||||
return it->name;
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string_view>
|
|
||||||
#include "common/types.h"
|
|
||||||
|
|
||||||
/// Retrieves the PKG entry name from its type identifier.
|
|
||||||
std::string_view GetEntryNameByType(u32 type);
|
|
|
@ -1,10 +1,25 @@
|
||||||
// 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 "common/aes.h"
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/path_util.h"
|
#include "common/path_util.h"
|
||||||
#include "trp.h"
|
#include "core/file_format/trp.h"
|
||||||
|
|
||||||
|
static void DecryptEFSM(std::span<u8, 16> trophyKey, std::span<u8, 16> NPcommID,
|
||||||
|
std::span<u8, 16> efsmIv, std::span<u8> ciphertext,
|
||||||
|
std::span<u8> decrypted) {
|
||||||
|
// Step 1: Encrypt NPcommID
|
||||||
|
std::array<u8, 16> trophyIv{};
|
||||||
|
std::array<u8, 16> trpKey;
|
||||||
|
aes::encrypt_cbc(NPcommID.data(), NPcommID.size(), trophyKey.data(), trophyKey.size(),
|
||||||
|
trophyIv.data(), trpKey.data(), trpKey.size(), false);
|
||||||
|
|
||||||
|
// Step 2: Decrypt EFSM
|
||||||
|
aes::decrypt_cbc(ciphertext.data(), ciphertext.size(), trpKey.data(), trpKey.size(),
|
||||||
|
efsmIv.data(), decrypted.data(), decrypted.size(), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
TRP::TRP() = default;
|
TRP::TRP() = default;
|
||||||
TRP::~TRP() = default;
|
TRP::~TRP() = default;
|
||||||
|
@ -54,7 +69,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<CryptoPP::byte, 16> user_key{};
|
std::array<u8, 16> user_key{};
|
||||||
hexToBytes(user_key_str.c_str(), user_key.data());
|
hexToBytes(user_key_str.c_str(), user_key.data());
|
||||||
|
|
||||||
for (int index = 0; const auto& it : std::filesystem::directory_iterator(gameSysDir)) {
|
for (int index = 0; const auto& it : std::filesystem::directory_iterator(gameSysDir)) {
|
||||||
|
@ -115,7 +130,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
file.Read(ESFM);
|
file.Read(ESFM);
|
||||||
crypto.decryptEFSM(user_key, np_comm_id, esfmIv, ESFM, XML); // decrypt
|
DecryptEFSM(user_key, np_comm_id, esfmIv, ESFM, XML); // decrypt
|
||||||
removePadding(XML);
|
removePadding(XML);
|
||||||
std::string xml_name = entry.entry_name;
|
std::string xml_name = entry.entry_name;
|
||||||
size_t pos = xml_name.find("ESFM");
|
size_t pos = xml_name.find("ESFM");
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "common/endian.h"
|
#include "common/endian.h"
|
||||||
#include "common/io_file.h"
|
#include "common/io_file.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "core/crypto/crypto.h"
|
|
||||||
|
|
||||||
struct TrpHeader {
|
struct TrpHeader {
|
||||||
u32_be magic; // (0xDCA24D00)
|
u32_be magic; // (0xDCA24D00)
|
||||||
|
@ -37,10 +36,9 @@ public:
|
||||||
void GetNPcommID(const std::filesystem::path& trophyPath, int index);
|
void GetNPcommID(const std::filesystem::path& trophyPath, int index);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Crypto crypto;
|
|
||||||
std::vector<u8> NPcommID = std::vector<u8>(12);
|
std::vector<u8> NPcommID = std::vector<u8>(12);
|
||||||
std::array<u8, 16> np_comm_id{};
|
std::array<u8, 16> np_comm_id{};
|
||||||
std::array<u8, 16> esfmIv{};
|
std::array<u8, 16> esfmIv{};
|
||||||
std::filesystem::path trpFilesPath;
|
std::filesystem::path trpFilesPath;
|
||||||
static constexpr int iv_len = 16;
|
static constexpr int iv_len = 16;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
20
src/core/libraries/kernel/debug.cpp
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "core/libraries/kernel/file_system.h"
|
||||||
|
#include "core/libraries/kernel/orbis_error.h"
|
||||||
|
#include "core/libraries/libs.h"
|
||||||
|
|
||||||
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
|
void PS4_SYSV_ABI sceKernelDebugOutText(void* unk, char* text) {
|
||||||
|
sceKernelWrite(1, text, strlen(text));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterDebug(Core::Loader::SymbolsResolver* sym) {
|
||||||
|
LIB_FUNCTION("9JYNqN6jAKI", "libkernel", 1, "libkernel", 1, 1, sceKernelDebugOutText);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Libraries::Kernel
|
14
src/core/libraries/kernel/debug.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Core::Loader {
|
||||||
|
class SymbolsResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Libraries::Kernel {
|
||||||
|
|
||||||
|
void RegisterDebug(Core::Loader::SymbolsResolver* sym);
|
||||||
|
|
||||||
|
} // namespace Libraries::Kernel
|
|
@ -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
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "common/va_ctx.h"
|
#include "common/va_ctx.h"
|
||||||
#include "core/file_sys/fs.h"
|
#include "core/file_sys/fs.h"
|
||||||
#include "core/libraries/error_codes.h"
|
#include "core/libraries/error_codes.h"
|
||||||
|
#include "core/libraries/kernel/debug.h"
|
||||||
#include "core/libraries/kernel/equeue.h"
|
#include "core/libraries/kernel/equeue.h"
|
||||||
#include "core/libraries/kernel/file_system.h"
|
#include "core/libraries/kernel/file_system.h"
|
||||||
#include "core/libraries/kernel/kernel.h"
|
#include "core/libraries/kernel/kernel.h"
|
||||||
|
@ -85,17 +86,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 +112,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 +141,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;
|
||||||
|
@ -220,6 +220,7 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
||||||
Libraries::Kernel::RegisterProcess(sym);
|
Libraries::Kernel::RegisterProcess(sym);
|
||||||
Libraries::Kernel::RegisterException(sym);
|
Libraries::Kernel::RegisterException(sym);
|
||||||
Libraries::Kernel::RegisterAio(sym);
|
Libraries::Kernel::RegisterAio(sym);
|
||||||
|
Libraries::Kernel::RegisterDebug(sym);
|
||||||
|
|
||||||
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
||||||
LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl);
|
LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl);
|
||||||
|
@ -229,13 +230,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
|
||||||
|
|
|
@ -127,6 +127,11 @@ int PS4_SYSV_ABI sceKernelGetModuleInfoFromAddr(VAddr addr, int flags,
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI exit(s32 status) {
|
||||||
|
UNREACHABLE_MSG("Exiting with status code {}", status);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterProcess(Core::Loader::SymbolsResolver* sym) {
|
void RegisterProcess(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("WB66evu8bsU", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCompiledSdkVersion);
|
LIB_FUNCTION("WB66evu8bsU", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCompiledSdkVersion);
|
||||||
LIB_FUNCTION("WslcK1FQcGI", "libkernel", 1, "libkernel", 1, 1, sceKernelIsNeoMode);
|
LIB_FUNCTION("WslcK1FQcGI", "libkernel", 1, "libkernel", 1, 1, sceKernelIsNeoMode);
|
||||||
|
@ -136,6 +141,7 @@ void RegisterProcess(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", 1, 1, sceKernelDlsym);
|
LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", 1, 1, sceKernelDlsym);
|
||||||
LIB_FUNCTION("RpQJJVKTiFM", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoForUnwind);
|
LIB_FUNCTION("RpQJJVKTiFM", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoForUnwind);
|
||||||
LIB_FUNCTION("f7KBOafysXo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoFromAddr);
|
LIB_FUNCTION("f7KBOafysXo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoFromAddr);
|
||||||
|
LIB_FUNCTION("6Z83sYWFlA8", "libkernel", 1, "libkernel", 1, 1, exit);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "core/libraries/kernel/orbis_error.h"
|
||||||
#include "core/libraries/kernel/threads/exception.h"
|
#include "core/libraries/kernel/threads/exception.h"
|
||||||
#include "core/libraries/kernel/threads/pthread.h"
|
#include "core/libraries/kernel/threads/pthread.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
|
@ -148,13 +149,19 @@ int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelDebugRaiseException() {
|
s32 PS4_SYSV_ABI sceKernelDebugRaiseException(s32 error, s64 unk) {
|
||||||
UNREACHABLE();
|
if (unk != 0) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
UNREACHABLE_MSG("error {:#x}", error);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode() {
|
s32 PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode(s32 error, s64 unk) {
|
||||||
UNREACHABLE();
|
if (unk != 0) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
UNREACHABLE_MSG("error {:#x}", error);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +170,7 @@ void RegisterException(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("WkwEd3N7w0Y", "libkernel_unity", 1, "libkernel", 1, 1,
|
LIB_FUNCTION("WkwEd3N7w0Y", "libkernel_unity", 1, "libkernel", 1, 1,
|
||||||
sceKernelInstallExceptionHandler);
|
sceKernelInstallExceptionHandler);
|
||||||
LIB_FUNCTION("Qhv5ARAoOEc", "libkernel_unity", 1, "libkernel", 1, 1,
|
LIB_FUNCTION("Qhv5ARAoOEc", "libkernel_unity", 1, "libkernel", 1, 1,
|
||||||
sceKernelRemoveExceptionHandler)
|
sceKernelRemoveExceptionHandler);
|
||||||
LIB_FUNCTION("OMDRKKAZ8I4", "libkernel", 1, "libkernel", 1, 1, sceKernelDebugRaiseException);
|
LIB_FUNCTION("OMDRKKAZ8I4", "libkernel", 1, "libkernel", 1, 1, sceKernelDebugRaiseException);
|
||||||
LIB_FUNCTION("zE-wXIZjLoM", "libkernel", 1, "libkernel", 1, 1,
|
LIB_FUNCTION("zE-wXIZjLoM", "libkernel", 1, "libkernel", 1, 1,
|
||||||
sceKernelDebugRaiseExceptionOnReleaseMode);
|
sceKernelDebugRaiseExceptionOnReleaseMode);
|
||||||
|
|
|
@ -147,6 +147,11 @@ void RegisterSpec(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("0-KXaS70xy4", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_getspecific);
|
LIB_FUNCTION("0-KXaS70xy4", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_getspecific);
|
||||||
LIB_FUNCTION("WrOLvHU0yQM", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setspecific);
|
LIB_FUNCTION("WrOLvHU0yQM", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_setspecific);
|
||||||
|
|
||||||
|
// Posix-Kernel
|
||||||
|
LIB_FUNCTION("mqULNdimTn0", "libkernel", 1, "libkernel", 1, 1, posix_pthread_key_create);
|
||||||
|
LIB_FUNCTION("0-KXaS70xy4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_getspecific);
|
||||||
|
LIB_FUNCTION("WrOLvHU0yQM", "libkernel", 1, "libkernel", 1, 1, posix_pthread_setspecific);
|
||||||
|
|
||||||
// Orbis
|
// Orbis
|
||||||
LIB_FUNCTION("geDaqgH9lTg", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_key_create));
|
LIB_FUNCTION("geDaqgH9lTg", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_key_create));
|
||||||
LIB_FUNCTION("PrdHuuDekhY", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_key_delete));
|
LIB_FUNCTION("PrdHuuDekhY", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_key_delete));
|
||||||
|
|
|
@ -172,7 +172,7 @@ static s32 clock_gettime(u32 clock_id, struct timespec* ts) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct timespec* ts) {
|
int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct OrbisKernelTimespec* ts) {
|
||||||
if (ts == nullptr) {
|
if (ts == nullptr) {
|
||||||
return ORBIS_KERNEL_ERROR_EFAULT;
|
return ORBIS_KERNEL_ERROR_EFAULT;
|
||||||
}
|
}
|
||||||
|
@ -265,17 +265,18 @@ int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct timespec* ts) {
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return clock_gettime(pclock_id, ts);
|
timespec t{};
|
||||||
|
int result = clock_gettime(pclock_id, &t);
|
||||||
|
ts->tv_sec = t.tv_sec;
|
||||||
|
ts->tv_nsec = t.tv_nsec;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) {
|
int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) {
|
||||||
struct timespec ts;
|
const auto res = orbis_clock_gettime(clock_id, tp);
|
||||||
const auto res = orbis_clock_gettime(clock_id, &ts);
|
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
return ErrnoToSceKernelError(res);
|
return ErrnoToSceKernelError(res);
|
||||||
}
|
}
|
||||||
tp->tv_sec = ts.tv_sec;
|
|
||||||
tp->tv_nsec = ts.tv_nsec;
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,4 +470,4 @@ void RegisterTime(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime);
|
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
|
@ -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,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
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -190,11 +195,13 @@ 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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,17 @@ void Linker::Execute(const std::vector<std::string> args) {
|
||||||
|
|
||||||
memory->SetupMemoryRegions(fmem_size, use_extended_mem1, use_extended_mem2);
|
memory->SetupMemoryRegions(fmem_size, use_extended_mem1, use_extended_mem2);
|
||||||
|
|
||||||
|
// Simulate sceKernelInternalMemory mapping, a mapping usually performed during libkernel init.
|
||||||
|
// Due to the large size of this mapping, failing to emulate it causes issues in some titles.
|
||||||
|
// This mapping belongs in the system reserved area, which starts at address 0x880000000.
|
||||||
|
static constexpr VAddr KernelAllocBase = 0x880000000ULL;
|
||||||
|
static constexpr s64 InternalMemorySize = 0x1000000;
|
||||||
|
void* addr_out{reinterpret_cast<void*>(KernelAllocBase)};
|
||||||
|
|
||||||
|
const s32 ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory(
|
||||||
|
&addr_out, InternalMemorySize, 3, 0, "SceKernelInternalMemory");
|
||||||
|
ASSERT_MSG(ret == 0, "Unable to perform sceKernelInternalMemory mapping");
|
||||||
|
|
||||||
main_thread.Run([this, module, args](std::stop_token) {
|
main_thread.Run([this, module, args](std::stop_token) {
|
||||||
Common::SetCurrentThreadName("GAME_MainThread");
|
Common::SetCurrentThreadName("GAME_MainThread");
|
||||||
LoadSharedLibraries();
|
LoadSharedLibraries();
|
||||||
|
@ -372,7 +383,8 @@ void* Linker::AllocateTlsForThread(bool is_primary) {
|
||||||
|
|
||||||
// If sceKernelMapNamedFlexibleMemory is being called from libkernel and addr = 0
|
// If sceKernelMapNamedFlexibleMemory is being called from libkernel and addr = 0
|
||||||
// it automatically places mappings in system reserved area instead of managed.
|
// it automatically places mappings in system reserved area instead of managed.
|
||||||
static constexpr VAddr KernelAllocBase = 0x880000000ULL;
|
// Since the system reserved area already has a mapping in it, this address is slightly higher.
|
||||||
|
static constexpr VAddr KernelAllocBase = 0x881000000ULL;
|
||||||
|
|
||||||
// The kernel module has a few different paths for TLS allocation.
|
// The kernel module has a few different paths for TLS allocation.
|
||||||
// For SDK < 1.7 it allocates both main and secondary thread blocks using libc mspace/malloc.
|
// For SDK < 1.7 it allocates both main and secondary thread blocks using libc mspace/malloc.
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "common/io_file.h"
|
|
||||||
#include "common/types.h"
|
|
||||||
#include "loader.h"
|
|
||||||
|
|
||||||
namespace Loader {
|
|
||||||
|
|
||||||
FileTypes DetectFileType(const std::filesystem::path& filepath) {
|
|
||||||
// No file loaded
|
|
||||||
if (filepath.empty()) {
|
|
||||||
return FileTypes::Unknown;
|
|
||||||
}
|
|
||||||
Common::FS::IOFile file;
|
|
||||||
file.Open(filepath, Common::FS::FileAccessMode::Read);
|
|
||||||
file.Seek(0);
|
|
||||||
u32 magic;
|
|
||||||
file.Read(magic);
|
|
||||||
file.Close();
|
|
||||||
switch (magic) {
|
|
||||||
case PkgMagic:
|
|
||||||
return FileTypes::Pkg;
|
|
||||||
}
|
|
||||||
return FileTypes::Unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Loader
|
|
|
@ -1,18 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace Loader {
|
|
||||||
|
|
||||||
constexpr static u32 PkgMagic = 0x544e437f;
|
|
||||||
|
|
||||||
enum class FileTypes {
|
|
||||||
Unknown,
|
|
||||||
Pkg,
|
|
||||||
};
|
|
||||||
|
|
||||||
FileTypes DetectFileType(const std::filesystem::path& filepath);
|
|
||||||
} // namespace Loader
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
// 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 <cryptopp/sha.h>
|
|
||||||
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/arch.h"
|
#include "common/arch.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/memory_patcher.h"
|
#include "common/memory_patcher.h"
|
||||||
|
#include "common/sha1.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/aerolib/aerolib.h"
|
#include "core/aerolib/aerolib.h"
|
||||||
#include "core/cpu_patches.h"
|
#include "core/cpu_patches.h"
|
||||||
|
@ -65,11 +64,13 @@ static std::string StringToNid(std::string_view symbol) {
|
||||||
std::memcpy(input.data(), symbol.data(), symbol.size());
|
std::memcpy(input.data(), symbol.data(), symbol.size());
|
||||||
std::memcpy(input.data() + symbol.size(), Salt.data(), Salt.size());
|
std::memcpy(input.data() + symbol.size(), Salt.data(), Salt.size());
|
||||||
|
|
||||||
std::array<u8, CryptoPP::SHA1::DIGESTSIZE> hash;
|
sha1::SHA1::digest8_t hash;
|
||||||
CryptoPP::SHA1().CalculateDigest(hash.data(), input.data(), input.size());
|
sha1::SHA1 sha;
|
||||||
|
sha.processBytes(input.data(), input.size());
|
||||||
|
sha.getDigestBytes(hash);
|
||||||
|
|
||||||
u64 digest;
|
u64 digest;
|
||||||
std::memcpy(&digest, hash.data(), sizeof(digest));
|
std::memcpy(&digest, hash, sizeof(digest));
|
||||||
|
|
||||||
static constexpr std::string_view codes =
|
static constexpr std::string_view codes =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-";
|
||||||
|
|
|
@ -82,7 +82,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);
|
||||||
|
@ -291,13 +291,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", &Libraries::Font::RegisterlibSceFont},
|
{"libSceFont.sprx", &Libraries::Font::RegisterlibSceFont},
|
||||||
|
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 4 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 |
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,12 @@ public:
|
||||||
game_update_path += "-UPDATE";
|
game_update_path += "-UPDATE";
|
||||||
if (std::filesystem::exists(game_update_path / "sce_sys" / "param.sfo")) {
|
if (std::filesystem::exists(game_update_path / "sce_sys" / "param.sfo")) {
|
||||||
sce_folder_path = game_update_path / "sce_sys" / "param.sfo";
|
sce_folder_path = game_update_path / "sce_sys" / "param.sfo";
|
||||||
|
} else {
|
||||||
|
game_update_path = filePath;
|
||||||
|
game_update_path += "-patch";
|
||||||
|
if (std::filesystem::exists(game_update_path / "sce_sys" / "param.sfo")) {
|
||||||
|
sce_folder_path = game_update_path / "sce_sys" / "param.sfo";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PSF psf;
|
PSF psf;
|
||||||
|
|
|
@ -185,7 +185,8 @@ void GameListFrame::SetListBackgroundImage(QTableWidgetItem* item) {
|
||||||
|
|
||||||
// Recompute if opacity changed or we switched to a different game
|
// Recompute if opacity changed or we switched to a different game
|
||||||
if (opacity != m_last_opacity || game.pic_path != m_current_game_path) {
|
if (opacity != m_last_opacity || game.pic_path != m_current_game_path) {
|
||||||
QImage original_image(QString::fromStdString(game.pic_path.string()));
|
auto image_path = game.pic_path.u8string();
|
||||||
|
QImage original_image(QString::fromStdString({image_path.begin(), image_path.end()}));
|
||||||
if (!original_image.isNull()) {
|
if (!original_image.isNull()) {
|
||||||
backgroundImage = m_game_list_utils.ChangeImageOpacity(
|
backgroundImage = m_game_list_utils.ChangeImageOpacity(
|
||||||
original_image, original_image.rect(), opacity / 100.0f);
|
original_image, original_image.rect(), opacity / 100.0f);
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QTreeWidget>
|
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
|
|
||||||
#include <qt_gui/background_music_player.h>
|
#include <qt_gui/background_music_player.h>
|
||||||
|
@ -116,7 +115,9 @@ public:
|
||||||
|
|
||||||
compatibilityMenu->addAction(updateCompatibility);
|
compatibilityMenu->addAction(updateCompatibility);
|
||||||
compatibilityMenu->addAction(viewCompatibilityReport);
|
compatibilityMenu->addAction(viewCompatibilityReport);
|
||||||
compatibilityMenu->addAction(submitCompatibilityReport);
|
if (Common::isRelease) {
|
||||||
|
compatibilityMenu->addAction(submitCompatibilityReport);
|
||||||
|
}
|
||||||
|
|
||||||
menu.addMenu(compatibilityMenu);
|
menu.addMenu(compatibilityMenu);
|
||||||
|
|
||||||
|
@ -139,11 +140,17 @@ public:
|
||||||
QString open_update_path;
|
QString open_update_path;
|
||||||
Common::FS::PathToQString(open_update_path, m_games[itemID].path);
|
Common::FS::PathToQString(open_update_path, m_games[itemID].path);
|
||||||
open_update_path += "-UPDATE";
|
open_update_path += "-UPDATE";
|
||||||
if (!std::filesystem::exists(Common::FS::PathFromQString(open_update_path))) {
|
if (std::filesystem::exists(Common::FS::PathFromQString(open_update_path))) {
|
||||||
QMessageBox::critical(nullptr, tr("Error"),
|
|
||||||
QString(tr("This game has no update folder to open!")));
|
|
||||||
} else {
|
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(open_update_path));
|
QDesktopServices::openUrl(QUrl::fromLocalFile(open_update_path));
|
||||||
|
} else {
|
||||||
|
Common::FS::PathToQString(open_update_path, m_games[itemID].path);
|
||||||
|
open_update_path += "-patch";
|
||||||
|
if (std::filesystem::exists(Common::FS::PathFromQString(open_update_path))) {
|
||||||
|
QDesktopServices::openUrl(QUrl::fromLocalFile(open_update_path));
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(nullptr, tr("Error"),
|
||||||
|
QString(tr("This game has no update folder to open!")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +223,12 @@ public:
|
||||||
game_update_path += "-UPDATE";
|
game_update_path += "-UPDATE";
|
||||||
if (std::filesystem::exists(game_update_path)) {
|
if (std::filesystem::exists(game_update_path)) {
|
||||||
game_folder_path = game_update_path;
|
game_folder_path = game_update_path;
|
||||||
|
} else {
|
||||||
|
game_update_path = game_folder_path;
|
||||||
|
game_update_path += "-patch";
|
||||||
|
if (std::filesystem::exists(game_update_path)) {
|
||||||
|
game_folder_path = game_update_path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (psf.Open(game_folder_path / "sce_sys" / "param.sfo")) {
|
if (psf.Open(game_folder_path / "sce_sys" / "param.sfo")) {
|
||||||
int rows = psf.GetEntries().size();
|
int rows = psf.GetEntries().size();
|
||||||
|
@ -312,8 +325,40 @@ public:
|
||||||
game_update_path += "-UPDATE";
|
game_update_path += "-UPDATE";
|
||||||
if (std::filesystem::exists(game_update_path)) {
|
if (std::filesystem::exists(game_update_path)) {
|
||||||
Common::FS::PathToQString(gameTrpPath, game_update_path);
|
Common::FS::PathToQString(gameTrpPath, game_update_path);
|
||||||
|
} else {
|
||||||
|
game_update_path = Common::FS::PathFromQString(gameTrpPath);
|
||||||
|
game_update_path += "-patch";
|
||||||
|
if (std::filesystem::exists(game_update_path)) {
|
||||||
|
Common::FS::PathToQString(gameTrpPath, game_update_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TrophyViewer* trophyViewer = new TrophyViewer(trophyPath, gameTrpPath);
|
|
||||||
|
// Array with all games and their trophy information
|
||||||
|
QVector<TrophyGameInfo> allTrophyGames;
|
||||||
|
for (const auto& game : m_games) {
|
||||||
|
TrophyGameInfo gameInfo;
|
||||||
|
gameInfo.name = QString::fromStdString(game.name);
|
||||||
|
Common::FS::PathToQString(gameInfo.trophyPath, game.serial);
|
||||||
|
Common::FS::PathToQString(gameInfo.gameTrpPath, game.path);
|
||||||
|
|
||||||
|
auto update_path = Common::FS::PathFromQString(gameInfo.gameTrpPath);
|
||||||
|
update_path += "-UPDATE";
|
||||||
|
if (std::filesystem::exists(update_path)) {
|
||||||
|
Common::FS::PathToQString(gameInfo.gameTrpPath, update_path);
|
||||||
|
} else {
|
||||||
|
update_path = Common::FS::PathFromQString(gameInfo.gameTrpPath);
|
||||||
|
update_path += "-patch";
|
||||||
|
if (std::filesystem::exists(update_path)) {
|
||||||
|
Common::FS::PathToQString(gameInfo.gameTrpPath, update_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allTrophyGames.append(gameInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString gameName = QString::fromStdString(m_games[itemID].name);
|
||||||
|
TrophyViewer* trophyViewer =
|
||||||
|
new TrophyViewer(trophyPath, gameTrpPath, gameName, allTrophyGames);
|
||||||
trophyViewer->show();
|
trophyViewer->show();
|
||||||
connect(widget->parent(), &QWidget::destroyed, trophyViewer,
|
connect(widget->parent(), &QWidget::destroyed, trophyViewer,
|
||||||
[trophyViewer]() { trophyViewer->deleteLater(); });
|
[trophyViewer]() { trophyViewer->deleteLater(); });
|
||||||
|
@ -432,6 +477,9 @@ public:
|
||||||
QString folder_path, game_update_path, dlc_path, save_data_path, trophy_data_path;
|
QString folder_path, game_update_path, dlc_path, save_data_path, trophy_data_path;
|
||||||
Common::FS::PathToQString(folder_path, m_games[itemID].path);
|
Common::FS::PathToQString(folder_path, m_games[itemID].path);
|
||||||
game_update_path = folder_path + "-UPDATE";
|
game_update_path = folder_path + "-UPDATE";
|
||||||
|
if (!std::filesystem::exists(Common::FS::PathFromQString(game_update_path))) {
|
||||||
|
game_update_path = folder_path + "-patch";
|
||||||
|
}
|
||||||
Common::FS::PathToQString(
|
Common::FS::PathToQString(
|
||||||
dlc_path, Config::getAddonInstallDir() /
|
dlc_path, Config::getAddonInstallDir() /
|
||||||
Common::FS::PathFromQString(folder_path).parent_path().filename());
|
Common::FS::PathFromQString(folder_path).parent_path().filename());
|
||||||
|
@ -521,7 +569,7 @@ public:
|
||||||
"title", QString("%1 - %2").arg(QString::fromStdString(m_games[itemID].serial),
|
"title", QString("%1 - %2").arg(QString::fromStdString(m_games[itemID].serial),
|
||||||
QString::fromStdString(m_games[itemID].name)));
|
QString::fromStdString(m_games[itemID].name)));
|
||||||
query.addQueryItem("game-name", QString::fromStdString(m_games[itemID].name));
|
query.addQueryItem("game-name", QString::fromStdString(m_games[itemID].name));
|
||||||
query.addQueryItem("game-code", QString::fromStdString(m_games[itemID].serial));
|
query.addQueryItem("game-serial", QString::fromStdString(m_games[itemID].serial));
|
||||||
query.addQueryItem("game-version", QString::fromStdString(m_games[itemID].version));
|
query.addQueryItem("game-version", QString::fromStdString(m_games[itemID].version));
|
||||||
query.addQueryItem("emulator-version", QString(Common::VERSION));
|
query.addQueryItem("emulator-version", QString(Common::VERSION));
|
||||||
url.setQuery(query);
|
url.setQuery(query);
|
||||||
|
@ -552,30 +600,6 @@ public:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestGameMenuPKGViewer(
|
|
||||||
const QPoint& pos, QStringList m_pkg_app_list, QTreeWidget* treeWidget,
|
|
||||||
std::function<void(std::filesystem::path, int, int)> InstallDragDropPkg) {
|
|
||||||
QPoint global_pos = treeWidget->viewport()->mapToGlobal(pos); // context menu position
|
|
||||||
QTreeWidgetItem* currentItem = treeWidget->currentItem(); // current clicked item
|
|
||||||
int itemIndex = GetRowIndex(treeWidget, currentItem); // row
|
|
||||||
|
|
||||||
QMenu menu(treeWidget);
|
|
||||||
QAction installPackage(tr("Install PKG"), treeWidget);
|
|
||||||
|
|
||||||
menu.addAction(&installPackage);
|
|
||||||
|
|
||||||
auto selected = menu.exec(global_pos);
|
|
||||||
if (!selected) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selected == &installPackage) {
|
|
||||||
QStringList pkg_app_ = m_pkg_app_list[itemIndex].split(";;");
|
|
||||||
std::filesystem::path path = Common::FS::PathFromQString(pkg_app_[9]);
|
|
||||||
InstallDragDropPkg(path, 1, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool convertPngToIco(const QString& pngFilePath, const QString& icoFilePath) {
|
bool convertPngToIco(const QString& pngFilePath, const QString& icoFilePath) {
|
||||||
// Load the PNG image
|
// Load the PNG image
|
||||||
|
|
|
@ -1,94 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QDialogButtonBox>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QGroupBox>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QListWidget>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include "install_dir_select.h"
|
|
||||||
|
|
||||||
InstallDirSelect::InstallDirSelect() : selected_dir() {
|
|
||||||
auto install_dirs = Config::getGameInstallDirs();
|
|
||||||
selected_dir = install_dirs.empty() ? "" : install_dirs.front();
|
|
||||||
|
|
||||||
if (!install_dirs.empty() && install_dirs.size() == 1) {
|
|
||||||
accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
|
||||||
|
|
||||||
layout->addWidget(SetupInstallDirList());
|
|
||||||
layout->addStretch();
|
|
||||||
layout->addWidget(SetupDialogActions());
|
|
||||||
|
|
||||||
setWindowTitle(tr("shadPS4 - Choose directory"));
|
|
||||||
setWindowIcon(QIcon(":images/shadps4.ico"));
|
|
||||||
}
|
|
||||||
|
|
||||||
InstallDirSelect::~InstallDirSelect() {}
|
|
||||||
|
|
||||||
QWidget* InstallDirSelect::SetupInstallDirList() {
|
|
||||||
auto group = new QGroupBox(tr("Select which directory you want to install to."));
|
|
||||||
auto vlayout = new QVBoxLayout();
|
|
||||||
|
|
||||||
auto m_path_list = new QListWidget();
|
|
||||||
QList<QString> qt_list;
|
|
||||||
for (const auto& str : Config::getGameInstallDirs()) {
|
|
||||||
QString installDirPath;
|
|
||||||
Common::FS::PathToQString(installDirPath, str);
|
|
||||||
qt_list.append(installDirPath);
|
|
||||||
}
|
|
||||||
m_path_list->insertItems(0, qt_list);
|
|
||||||
m_path_list->setSpacing(1);
|
|
||||||
|
|
||||||
connect(m_path_list, &QListWidget::itemClicked, this, &InstallDirSelect::setSelectedDirectory);
|
|
||||||
connect(m_path_list, &QListWidget::itemActivated, this,
|
|
||||||
&InstallDirSelect::setSelectedDirectory);
|
|
||||||
|
|
||||||
vlayout->addWidget(m_path_list);
|
|
||||||
|
|
||||||
auto checkbox = new QCheckBox(tr("Install All Queued to Selected Folder"));
|
|
||||||
connect(checkbox, &QCheckBox::toggled, this, &InstallDirSelect::setUseForAllQueued);
|
|
||||||
vlayout->addWidget(checkbox);
|
|
||||||
|
|
||||||
auto checkbox2 = new QCheckBox(tr("Delete PKG File on Install"));
|
|
||||||
connect(checkbox2, &QCheckBox::toggled, this, &InstallDirSelect::setDeleteFileOnInstall);
|
|
||||||
vlayout->addWidget(checkbox2);
|
|
||||||
|
|
||||||
group->setLayout(vlayout);
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstallDirSelect::setSelectedDirectory(QListWidgetItem* item) {
|
|
||||||
if (item) {
|
|
||||||
const auto highlighted_path = Common::FS::PathFromQString(item->text());
|
|
||||||
if (!highlighted_path.empty()) {
|
|
||||||
selected_dir = highlighted_path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstallDirSelect::setUseForAllQueued(bool enabled) {
|
|
||||||
use_for_all_queued = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InstallDirSelect::setDeleteFileOnInstall(bool enabled) {
|
|
||||||
delete_file_on_install = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
QWidget* InstallDirSelect::SetupDialogActions() {
|
|
||||||
auto actions = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
|
||||||
|
|
||||||
connect(actions, &QDialogButtonBox::accepted, this, &InstallDirSelect::accept);
|
|
||||||
connect(actions, &QDialogButtonBox::rejected, this, &InstallDirSelect::reject);
|
|
||||||
|
|
||||||
return actions;
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QListWidget>
|
|
||||||
|
|
||||||
#include "common/config.h"
|
|
||||||
#include "common/path_util.h"
|
|
||||||
|
|
||||||
class QLineEdit;
|
|
||||||
|
|
||||||
class InstallDirSelect final : public QDialog {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
InstallDirSelect();
|
|
||||||
~InstallDirSelect();
|
|
||||||
|
|
||||||
std::filesystem::path getSelectedDirectory() {
|
|
||||||
return selected_dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool useForAllQueued() {
|
|
||||||
return use_for_all_queued;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool deleteFileOnInstall() {
|
|
||||||
return delete_file_on_install;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QWidget* SetupInstallDirList();
|
|
||||||
QWidget* SetupDialogActions();
|
|
||||||
void setSelectedDirectory(QListWidgetItem* item);
|
|
||||||
void setDeleteFileOnInstall(bool enabled);
|
|
||||||
void setUseForAllQueued(bool enabled);
|
|
||||||
std::filesystem::path selected_dir;
|
|
||||||
bool delete_file_on_install = false;
|
|
||||||
bool use_for_all_queued = false;
|
|
||||||
};
|
|
|
@ -225,7 +225,8 @@ void EditorDialog::loadInstalledGames() {
|
||||||
QDir parentFolder(installDir);
|
QDir parentFolder(installDir);
|
||||||
QFileInfoList fileList = parentFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
QFileInfoList fileList = parentFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
for (const auto& fileInfo : fileList) {
|
for (const auto& fileInfo : fileList) {
|
||||||
if (fileInfo.isDir() && !fileInfo.filePath().endsWith("-UPDATE")) {
|
if (fileInfo.isDir() && (!fileInfo.filePath().endsWith("-UPDATE") ||
|
||||||
|
!fileInfo.filePath().endsWith("-patch"))) {
|
||||||
gameComboBox->addItem(fileInfo.fileName()); // Add game name to combo box
|
gameComboBox->addItem(fileInfo.fileName()); // Add game name to combo box
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "ui_kbm_gui.h"
|
#include "ui_kbm_gui.h"
|
||||||
|
|
||||||
HelpDialog* HelpWindow;
|
HelpDialog* HelpWindow;
|
||||||
|
|
||||||
KBMSettings::KBMSettings(std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent)
|
KBMSettings::KBMSettings(std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent)
|
||||||
: QDialog(parent), m_game_info(game_info_get), ui(new Ui::KBMSettings) {
|
: QDialog(parent), m_game_info(game_info_get), ui(new Ui::KBMSettings) {
|
||||||
|
|
||||||
|
@ -48,6 +47,7 @@ KBMSettings::KBMSettings(std::shared_ptr<GameInfoClass> game_info_get, QWidget*
|
||||||
|
|
||||||
ui->ProfileComboBox->setCurrentText("Common Config");
|
ui->ProfileComboBox->setCurrentText("Common Config");
|
||||||
ui->TitleLabel->setText("Common Config");
|
ui->TitleLabel->setText("Common Config");
|
||||||
|
config_id = "default";
|
||||||
|
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, [this](QAbstractButton* button) {
|
connect(ui->buttonBox, &QDialogButtonBox::clicked, this, [this](QAbstractButton* button) {
|
||||||
if (button == ui->buttonBox->button(QDialogButtonBox::Save)) {
|
if (button == ui->buttonBox->button(QDialogButtonBox::Save)) {
|
||||||
|
@ -72,6 +72,7 @@ KBMSettings::KBMSettings(std::shared_ptr<GameInfoClass> game_info_get, QWidget*
|
||||||
connect(ui->TextEditorButton, &QPushButton::clicked, this, [this]() {
|
connect(ui->TextEditorButton, &QPushButton::clicked, this, [this]() {
|
||||||
auto kbmWindow = new EditorDialog(this);
|
auto kbmWindow = new EditorDialog(this);
|
||||||
kbmWindow->exec();
|
kbmWindow->exec();
|
||||||
|
SetUIValuestoMappings(config_id);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, [this] {
|
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, [this] {
|
||||||
|
@ -84,9 +85,6 @@ KBMSettings::KBMSettings(std::shared_ptr<GameInfoClass> game_info_get, QWidget*
|
||||||
|
|
||||||
connect(ui->ProfileComboBox, &QComboBox::currentTextChanged, this, [this] {
|
connect(ui->ProfileComboBox, &QComboBox::currentTextChanged, this, [this] {
|
||||||
GetGameTitle();
|
GetGameTitle();
|
||||||
std::string config_id = (ui->ProfileComboBox->currentText() == "Common Config")
|
|
||||||
? "default"
|
|
||||||
: ui->ProfileComboBox->currentText().toStdString();
|
|
||||||
SetUIValuestoMappings(config_id);
|
SetUIValuestoMappings(config_id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -385,10 +383,6 @@ void KBMSettings::SaveKBMConfig(bool CloseOnSave) {
|
||||||
lines.push_back(output_string + " = " + input_string);
|
lines.push_back(output_string + " = " + input_string);
|
||||||
|
|
||||||
lines.push_back("");
|
lines.push_back("");
|
||||||
|
|
||||||
std::string config_id = (ui->ProfileComboBox->currentText() == "Common Config")
|
|
||||||
? "default"
|
|
||||||
: ui->ProfileComboBox->currentText().toStdString();
|
|
||||||
const auto config_file = Config::GetFoolproofKbmConfigFile(config_id);
|
const auto config_file = Config::GetFoolproofKbmConfigFile(config_id);
|
||||||
std::fstream file(config_file);
|
std::fstream file(config_file);
|
||||||
int lineCount = 0;
|
int lineCount = 0;
|
||||||
|
@ -626,6 +620,9 @@ void KBMSettings::GetGameTitle() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
config_id = (ui->ProfileComboBox->currentText() == "Common Config")
|
||||||
|
? "default"
|
||||||
|
: ui->ProfileComboBox->currentText().toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void KBMSettings::onHelpClicked() {
|
void KBMSettings::onHelpClicked() {
|
||||||
|
|
|
@ -42,7 +42,7 @@ private:
|
||||||
QTimer* timer;
|
QTimer* timer;
|
||||||
QPushButton* MappingButton;
|
QPushButton* MappingButton;
|
||||||
QList<QPushButton*> ButtonsList;
|
QList<QPushButton*> ButtonsList;
|
||||||
|
std::string config_id;
|
||||||
const std::vector<std::string> ControllerInputs = {
|
const std::vector<std::string> ControllerInputs = {
|
||||||
"cross", "circle", "square", "triangle", "l1",
|
"cross", "circle", "square", "triangle", "l1",
|
||||||
"r1", "l2", "r2", "l3",
|
"r1", "l2", "r2", "l3",
|
||||||
|
|
|
@ -11,10 +11,16 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1193</width>
|
<width>1234</width>
|
||||||
<height>754</height>
|
<height>796</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::StrongFocus</enum>
|
<enum>Qt::FocusPolicy::StrongFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -38,8 +44,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1173</width>
|
<width>1214</width>
|
||||||
<height>704</height>
|
<height>746</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="layoutWidget">
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
@ -47,8 +53,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1171</width>
|
<width>1211</width>
|
||||||
<height>703</height>
|
<height>741</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="RemapLayout">
|
<layout class="QHBoxLayout" name="RemapLayout">
|
||||||
|
@ -63,7 +69,7 @@
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
|
@ -149,6 +155,12 @@
|
||||||
<layout class="QHBoxLayout" name="layout_dpad_left_right">
|
<layout class="QHBoxLayout" name="layout_dpad_left_right">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_dpad_left">
|
<widget class="QGroupBox" name="gb_dpad_left">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Left</string>
|
<string>Left</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -180,6 +192,12 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_dpad_right">
|
<widget class="QGroupBox" name="gb_dpad_right">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Right</string>
|
<string>Right</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -282,11 +300,17 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="LeftStickDeadZoneGB">
|
<widget class="QGroupBox" name="LeftStickDeadZoneGB">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>344</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Left Analog Halfmode</string>
|
<string>Left Analog Halfmode</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -319,7 +343,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_left_stick">
|
<widget class="QGroupBox" name="gb_left_stick">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
|
@ -405,6 +429,12 @@
|
||||||
<layout class="QHBoxLayout" name="layout_left_stick_left_right">
|
<layout class="QHBoxLayout" name="layout_left_stick_left_right">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_left_stick_left">
|
<widget class="QGroupBox" name="gb_left_stick_left">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Left</string>
|
<string>Left</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -436,6 +466,12 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_left_stick_right">
|
<widget class="QGroupBox" name="gb_left_stick_right">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>179</width>
|
<width>179</width>
|
||||||
|
@ -528,18 +564,24 @@
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_middle" stretch="0,0,0,0,0,0">
|
<layout class="QVBoxLayout" name="verticalLayout_middle" stretch="0,0,0,0,0">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="ProfileGroupBox">
|
<widget class="QGroupBox" name="ProfileGroupBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>12</pointsize>
|
<pointsize>12</pointsize>
|
||||||
|
@ -652,6 +694,18 @@
|
||||||
<layout class="QVBoxLayout" name="layout_l1_l2">
|
<layout class="QVBoxLayout" name="layout_l1_l2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_l1">
|
<widget class="QGroupBox" name="gb_l1">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>L1</string>
|
<string>L1</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -670,6 +724,12 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="L1Button">
|
<widget class="QPushButton" name="L1Button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -683,6 +743,12 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_l2">
|
<widget class="QGroupBox" name="gb_l2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>160</width>
|
<width>160</width>
|
||||||
|
@ -707,6 +773,12 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="L2Button">
|
<widget class="QPushButton" name="L2Button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -724,6 +796,18 @@
|
||||||
<layout class="QVBoxLayout" name="layout_system_buttons" stretch="0">
|
<layout class="QVBoxLayout" name="layout_system_buttons" stretch="0">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_4">
|
<widget class="QGroupBox" name="groupBox_4">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<bold>true</bold>
|
<bold>true</bold>
|
||||||
|
@ -735,6 +819,12 @@
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_20">
|
<layout class="QVBoxLayout" name="verticalLayout_20">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="TextEditorButton">
|
<widget class="QPushButton" name="TextEditorButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -745,6 +835,12 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="HelpButton">
|
<widget class="QPushButton" name="HelpButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -762,6 +858,12 @@
|
||||||
<layout class="QVBoxLayout" name="layout_r1_r2">
|
<layout class="QVBoxLayout" name="layout_r1_r2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_r1">
|
<widget class="QGroupBox" name="gb_r1">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>160</width>
|
<width>160</width>
|
||||||
|
@ -786,6 +888,12 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="R1Button">
|
<widget class="QPushButton" name="R1Button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -799,6 +907,18 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_r2">
|
<widget class="QGroupBox" name="gb_r2">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>R2</string>
|
<string>R2</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -817,6 +937,12 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="R2Button">
|
<widget class="QPushButton" name="R2Button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -857,7 +983,7 @@
|
||||||
<widget class="QLabel" name="l_controller">
|
<widget class="QLabel" name="l_controller">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>420</width>
|
<width>500</width>
|
||||||
<height>200</height>
|
<height>200</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
@ -887,6 +1013,12 @@
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_l3">
|
<widget class="QGroupBox" name="gb_l3">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>160</width>
|
<width>160</width>
|
||||||
|
@ -911,6 +1043,12 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="L3Button">
|
<widget class="QPushButton" name="L3Button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -924,12 +1062,30 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_touchpad">
|
<widget class="QGroupBox" name="gb_touchpad">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Touchpad Click</string>
|
<string>Touchpad Click</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="TouchpadButton">
|
<widget class="QPushButton" name="TouchpadButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -947,6 +1103,18 @@
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_21">
|
<layout class="QVBoxLayout" name="verticalLayout_21">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_5">
|
<widget class="QGroupBox" name="groupBox_5">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Mouse to Joystick</string>
|
<string>Mouse to Joystick</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -982,6 +1150,12 @@
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_r3">
|
<widget class="QGroupBox" name="gb_r3">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>160</width>
|
<width>160</width>
|
||||||
|
@ -1006,6 +1180,12 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="R3Button">
|
<widget class="QPushButton" name="R3Button">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -1019,9 +1199,15 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_options">
|
<widget class="QGroupBox" name="gb_options">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>145</width>
|
<width>160</width>
|
||||||
<height>0</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
@ -1043,6 +1229,12 @@
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="OptionsButton">
|
<widget class="QPushButton" name="OptionsButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::FocusPolicy::NoFocus</enum>
|
<enum>Qt::FocusPolicy::NoFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -1064,6 +1256,12 @@
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="MouseParamsBox">
|
<widget class="QGroupBox" name="MouseParamsBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<bold>false</bold>
|
<bold>false</bold>
|
||||||
|
@ -1196,6 +1394,25 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="MoreInfoLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<italic>true</italic>
|
||||||
|
<bold>false</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>note: click Help Button/Special Keybindings for more information</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -1203,19 +1420,6 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="MoreInfoLabel">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<italic>true</italic>
|
|
||||||
<bold>false</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>note: click Help Button/Special Keybindings for more information</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
@ -1226,7 +1430,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_face_buttons">
|
<widget class="QGroupBox" name="gb_face_buttons">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
|
@ -1306,6 +1510,12 @@
|
||||||
<layout class="QHBoxLayout" name="layout_square_circle">
|
<layout class="QHBoxLayout" name="layout_square_circle">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_square">
|
<widget class="QGroupBox" name="gb_square">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Square</string>
|
<string>Square</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -1337,6 +1547,12 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_circle">
|
<widget class="QGroupBox" name="gb_circle">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Circle</string>
|
<string>Circle</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -1444,6 +1660,12 @@
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>344</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Right Analog Halfmode</string>
|
<string>Right Analog Halfmode</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -1476,7 +1698,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_right_stick">
|
<widget class="QGroupBox" name="gb_right_stick">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
|
@ -1568,6 +1790,12 @@
|
||||||
<layout class="QHBoxLayout" name="layout_right_stick_left_right">
|
<layout class="QHBoxLayout" name="layout_right_stick_left_right">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_right_stick_left">
|
<widget class="QGroupBox" name="gb_right_stick_left">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Left</string>
|
<string>Left</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -1599,6 +1827,12 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="gb_right_stick_right">
|
<widget class="QGroupBox" name="gb_right_stick_right">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Right</string>
|
<string>Right</string>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -157,8 +157,8 @@ int main(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no game directory is set and no command line argument, prompt for it
|
// If no game directories are set and no command line argument, prompt for it
|
||||||
if (Config::getGameInstallDirs().empty() && !has_command_line_argument) {
|
if (Config::getGameInstallDirsEnabled().empty() && !has_command_line_argument) {
|
||||||
GameInstallDialog dlg;
|
GameInstallDialog dlg;
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
// 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_events.h"
|
||||||
|
|
||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QProgressDialog>
|
#include <QProgressDialog>
|
||||||
|
#include <QStatusBar>
|
||||||
|
|
||||||
#include "about_dialog.h"
|
#include "about_dialog.h"
|
||||||
#include "cheats_patches.h"
|
#include "cheats_patches.h"
|
||||||
|
@ -17,10 +20,7 @@
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "control_settings.h"
|
#include "control_settings.h"
|
||||||
#include "core/file_format/pkg.h"
|
|
||||||
#include "core/loader.h"
|
|
||||||
#include "game_install_dialog.h"
|
#include "game_install_dialog.h"
|
||||||
#include "install_dir_select.h"
|
|
||||||
#include "kbm_gui.h"
|
#include "kbm_gui.h"
|
||||||
#include "main_window.h"
|
#include "main_window.h"
|
||||||
#include "settings_dialog.h"
|
#include "settings_dialog.h"
|
||||||
|
@ -45,11 +45,11 @@ MainWindow::~MainWindow() {
|
||||||
bool MainWindow::Init() {
|
bool MainWindow::Init() {
|
||||||
auto start = std::chrono::steady_clock::now();
|
auto start = std::chrono::steady_clock::now();
|
||||||
// setup ui
|
// setup ui
|
||||||
|
LoadTranslation();
|
||||||
AddUiWidgets();
|
AddUiWidgets();
|
||||||
CreateActions();
|
CreateActions();
|
||||||
CreateRecentGameActions();
|
CreateRecentGameActions();
|
||||||
ConfigureGuiFromSettings();
|
ConfigureGuiFromSettings();
|
||||||
LoadTranslation();
|
|
||||||
CreateDockWindows();
|
CreateDockWindows();
|
||||||
CreateConnects();
|
CreateConnects();
|
||||||
SetLastUsedTheme();
|
SetLastUsedTheme();
|
||||||
|
@ -132,23 +132,160 @@ void MainWindow::CreateActions() {
|
||||||
m_theme_act_group->addAction(ui->setThemeOled);
|
m_theme_act_group->addAction(ui->setThemeOled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::PauseGame() {
|
||||||
|
SDL_Event event;
|
||||||
|
SDL_memset(&event, 0, sizeof(event));
|
||||||
|
event.type = SDL_EVENT_TOGGLE_PAUSE;
|
||||||
|
is_paused = !is_paused;
|
||||||
|
UpdateToolbarButtons();
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::toggleLabelsUnderIcons() {
|
||||||
|
bool showLabels = ui->toggleLabelsAct->isChecked();
|
||||||
|
Config::setShowLabelsUnderIcons();
|
||||||
|
UpdateToolbarLabels();
|
||||||
|
if (isGameRunning) {
|
||||||
|
UpdateToolbarButtons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::toggleFullscreen() {
|
||||||
|
SDL_Event event;
|
||||||
|
SDL_memset(&event, 0, sizeof(event));
|
||||||
|
event.type = SDL_EVENT_TOGGLE_FULLSCREEN;
|
||||||
|
SDL_PushEvent(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget* MainWindow::createButtonWithLabel(QPushButton* button, const QString& labelText,
|
||||||
|
bool showLabel) {
|
||||||
|
QWidget* container = new QWidget(this);
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout(container);
|
||||||
|
layout->setAlignment(Qt::AlignCenter | Qt::AlignBottom);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
layout->addWidget(button);
|
||||||
|
|
||||||
|
QLabel* label = nullptr;
|
||||||
|
if (showLabel && ui->toggleLabelsAct->isChecked()) {
|
||||||
|
label = new QLabel(labelText, this);
|
||||||
|
label->setAlignment(Qt::AlignCenter | Qt::AlignBottom);
|
||||||
|
layout->addWidget(label);
|
||||||
|
button->setToolTip("");
|
||||||
|
} else {
|
||||||
|
button->setToolTip(labelText);
|
||||||
|
}
|
||||||
|
|
||||||
|
container->setLayout(layout);
|
||||||
|
container->setProperty("buttonLabel", QVariant::fromValue(label));
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget* createSpacer(QWidget* parent) {
|
||||||
|
QWidget* spacer = new QWidget(parent);
|
||||||
|
spacer->setFixedWidth(15);
|
||||||
|
spacer->setFixedHeight(15);
|
||||||
|
return spacer;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::AddUiWidgets() {
|
void MainWindow::AddUiWidgets() {
|
||||||
// add toolbar widgets
|
// add toolbar widgets
|
||||||
QApplication::setStyle("Fusion");
|
QApplication::setStyle("Fusion");
|
||||||
ui->toolBar->setObjectName("mw_toolbar");
|
|
||||||
ui->toolBar->addWidget(ui->playButton);
|
bool showLabels = ui->toggleLabelsAct->isChecked();
|
||||||
ui->toolBar->addWidget(ui->pauseButton);
|
ui->toolBar->clear();
|
||||||
ui->toolBar->addWidget(ui->stopButton);
|
|
||||||
ui->toolBar->addWidget(ui->refreshButton);
|
ui->toolBar->addWidget(createSpacer(this));
|
||||||
ui->toolBar->addWidget(ui->settingsButton);
|
ui->toolBar->addWidget(createButtonWithLabel(ui->playButton, tr("Play"), showLabels));
|
||||||
ui->toolBar->addWidget(ui->controllerButton);
|
ui->toolBar->addWidget(createButtonWithLabel(ui->pauseButton, tr("Pause"), showLabels));
|
||||||
ui->toolBar->addWidget(ui->keyboardButton);
|
ui->toolBar->addWidget(createButtonWithLabel(ui->stopButton, tr("Stop"), showLabels));
|
||||||
|
ui->toolBar->addWidget(createButtonWithLabel(ui->restartButton, tr("Restart"), showLabels));
|
||||||
|
ui->toolBar->addWidget(createSpacer(this));
|
||||||
|
ui->toolBar->addWidget(createButtonWithLabel(ui->settingsButton, tr("Settings"), showLabels));
|
||||||
|
ui->toolBar->addWidget(
|
||||||
|
createButtonWithLabel(ui->fullscreenButton, tr("Full Screen"), showLabels));
|
||||||
|
ui->toolBar->addWidget(createSpacer(this));
|
||||||
|
ui->toolBar->addWidget(
|
||||||
|
createButtonWithLabel(ui->controllerButton, tr("Controllers"), showLabels));
|
||||||
|
ui->toolBar->addWidget(createButtonWithLabel(ui->keyboardButton, tr("Keyboard"), showLabels));
|
||||||
|
ui->toolBar->addWidget(createSpacer(this));
|
||||||
QFrame* line = new QFrame(this);
|
QFrame* line = new QFrame(this);
|
||||||
line->setFrameShape(QFrame::StyledPanel);
|
line->setFrameShape(QFrame::VLine);
|
||||||
line->setFrameShadow(QFrame::Sunken);
|
line->setFrameShadow(QFrame::Sunken);
|
||||||
|
line->setMinimumWidth(2);
|
||||||
ui->toolBar->addWidget(line);
|
ui->toolBar->addWidget(line);
|
||||||
ui->toolBar->addWidget(ui->sizeSliderContainer);
|
ui->toolBar->addWidget(createSpacer(this));
|
||||||
ui->toolBar->addWidget(ui->mw_searchbar);
|
if (showLabels) {
|
||||||
|
QLabel* pauseButtonLabel = ui->pauseButton->parentWidget()->findChild<QLabel*>();
|
||||||
|
if (pauseButtonLabel) {
|
||||||
|
pauseButtonLabel->setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui->toolBar->addWidget(
|
||||||
|
createButtonWithLabel(ui->refreshButton, tr("Refresh List"), showLabels));
|
||||||
|
ui->toolBar->addWidget(createSpacer(this));
|
||||||
|
|
||||||
|
QBoxLayout* toolbarLayout = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||||
|
toolbarLayout->setSpacing(2);
|
||||||
|
toolbarLayout->setContentsMargins(2, 2, 2, 2);
|
||||||
|
ui->sizeSliderContainer->setFixedWidth(150);
|
||||||
|
|
||||||
|
QWidget* searchSliderContainer = new QWidget(this);
|
||||||
|
QBoxLayout* searchSliderLayout = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||||
|
searchSliderLayout->setContentsMargins(0, 0, 6, 6);
|
||||||
|
searchSliderLayout->setSpacing(2);
|
||||||
|
ui->mw_searchbar->setFixedWidth(150);
|
||||||
|
|
||||||
|
searchSliderLayout->addWidget(ui->sizeSliderContainer);
|
||||||
|
searchSliderLayout->addWidget(ui->mw_searchbar);
|
||||||
|
|
||||||
|
searchSliderContainer->setLayout(searchSliderLayout);
|
||||||
|
|
||||||
|
ui->toolBar->addWidget(searchSliderContainer);
|
||||||
|
|
||||||
|
if (!showLabels) {
|
||||||
|
toolbarLayout->addWidget(searchSliderContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->playButton->setVisible(true);
|
||||||
|
ui->pauseButton->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::UpdateToolbarButtons() {
|
||||||
|
// add toolbar widgets when game is running
|
||||||
|
bool showLabels = ui->toggleLabelsAct->isChecked();
|
||||||
|
|
||||||
|
ui->playButton->setVisible(false);
|
||||||
|
ui->pauseButton->setVisible(true);
|
||||||
|
|
||||||
|
if (showLabels) {
|
||||||
|
QLabel* playButtonLabel = ui->playButton->parentWidget()->findChild<QLabel*>();
|
||||||
|
if (playButtonLabel)
|
||||||
|
playButtonLabel->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_paused) {
|
||||||
|
ui->pauseButton->setIcon(ui->playButton->icon());
|
||||||
|
ui->pauseButton->setToolTip(tr("Resume"));
|
||||||
|
} else {
|
||||||
|
if (isIconBlack) {
|
||||||
|
ui->pauseButton->setIcon(QIcon(":images/pause_icon.png"));
|
||||||
|
} else {
|
||||||
|
ui->pauseButton->setIcon(RecolorIcon(QIcon(":images/pause_icon.png"), isWhite));
|
||||||
|
}
|
||||||
|
ui->pauseButton->setToolTip(tr("Pause"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showLabels) {
|
||||||
|
QLabel* pauseButtonLabel = ui->pauseButton->parentWidget()->findChild<QLabel*>();
|
||||||
|
if (pauseButtonLabel) {
|
||||||
|
pauseButtonLabel->setText(is_paused ? tr("Resume") : tr("Pause"));
|
||||||
|
pauseButtonLabel->setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::UpdateToolbarLabels() {
|
||||||
|
AddUiWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::CreateDockWindows() {
|
void MainWindow::CreateDockWindows() {
|
||||||
|
@ -253,6 +390,8 @@ void MainWindow::CreateConnects() {
|
||||||
connect(ui->refreshButton, &QPushButton::clicked, this, &MainWindow::RefreshGameTable);
|
connect(ui->refreshButton, &QPushButton::clicked, this, &MainWindow::RefreshGameTable);
|
||||||
connect(ui->showGameListAct, &QAction::triggered, this, &MainWindow::ShowGameList);
|
connect(ui->showGameListAct, &QAction::triggered, this, &MainWindow::ShowGameList);
|
||||||
connect(this, &MainWindow::ExtractionFinished, this, &MainWindow::RefreshGameTable);
|
connect(this, &MainWindow::ExtractionFinished, this, &MainWindow::RefreshGameTable);
|
||||||
|
connect(ui->toggleLabelsAct, &QAction::toggled, this, &MainWindow::toggleLabelsUnderIcons);
|
||||||
|
connect(ui->fullscreenButton, &QPushButton::clicked, this, &MainWindow::toggleFullscreen);
|
||||||
|
|
||||||
connect(ui->sizeSlider, &QSlider::valueChanged, this, [this](int value) {
|
connect(ui->sizeSlider, &QSlider::valueChanged, this, [this](int value) {
|
||||||
if (isTableList) {
|
if (isTableList) {
|
||||||
|
@ -276,6 +415,7 @@ void MainWindow::CreateConnects() {
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(ui->playButton, &QPushButton::clicked, this, &MainWindow::StartGame);
|
connect(ui->playButton, &QPushButton::clicked, this, &MainWindow::StartGame);
|
||||||
|
connect(ui->pauseButton, &QPushButton::clicked, this, &MainWindow::PauseGame);
|
||||||
connect(m_game_grid_frame.get(), &QTableWidget::cellDoubleClicked, this,
|
connect(m_game_grid_frame.get(), &QTableWidget::cellDoubleClicked, this,
|
||||||
&MainWindow::StartGame);
|
&MainWindow::StartGame);
|
||||||
connect(m_game_list_frame.get(), &QTableWidget::cellDoubleClicked, this,
|
connect(m_game_list_frame.get(), &QTableWidget::cellDoubleClicked, this,
|
||||||
|
@ -576,7 +716,6 @@ void MainWindow::CreateConnects() {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Package install.
|
// Package install.
|
||||||
connect(ui->bootInstallPkgAct, &QAction::triggered, this, &MainWindow::InstallPkg);
|
|
||||||
connect(ui->bootGameAct, &QAction::triggered, this, &MainWindow::BootGame);
|
connect(ui->bootGameAct, &QAction::triggered, this, &MainWindow::BootGame);
|
||||||
connect(ui->gameInstallPathAct, &QAction::triggered, this, &MainWindow::InstallDirectory);
|
connect(ui->gameInstallPathAct, &QAction::triggered, this, &MainWindow::InstallDirectory);
|
||||||
|
|
||||||
|
@ -584,13 +723,58 @@ void MainWindow::CreateConnects() {
|
||||||
connect(ui->addElfFolderAct, &QAction::triggered, m_elf_viewer.data(),
|
connect(ui->addElfFolderAct, &QAction::triggered, m_elf_viewer.data(),
|
||||||
&ElfViewer::OpenElfFolder);
|
&ElfViewer::OpenElfFolder);
|
||||||
|
|
||||||
// Package Viewer.
|
// Trophy Viewer
|
||||||
connect(ui->pkgViewerAct, &QAction::triggered, this, [this]() {
|
connect(ui->trophyViewerAct, &QAction::triggered, this, [this]() {
|
||||||
PKGViewer* pkgViewer = new PKGViewer(
|
if (m_game_info->m_games.empty()) {
|
||||||
m_game_info, this, [this](std::filesystem::path file, int pkgNum, int nPkg) {
|
QMessageBox::information(
|
||||||
this->InstallDragDropPkg(file, pkgNum, nPkg);
|
this, tr("Trophy Viewer"),
|
||||||
});
|
tr("No games found. Please add your games to your library first."));
|
||||||
pkgViewer->show();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& firstGame = m_game_info->m_games[0];
|
||||||
|
QString trophyPath, gameTrpPath;
|
||||||
|
Common::FS::PathToQString(trophyPath, firstGame.serial);
|
||||||
|
Common::FS::PathToQString(gameTrpPath, firstGame.path);
|
||||||
|
|
||||||
|
auto game_update_path = Common::FS::PathFromQString(gameTrpPath);
|
||||||
|
game_update_path += "-UPDATE";
|
||||||
|
if (std::filesystem::exists(game_update_path)) {
|
||||||
|
Common::FS::PathToQString(gameTrpPath, game_update_path);
|
||||||
|
} else {
|
||||||
|
game_update_path = Common::FS::PathFromQString(gameTrpPath);
|
||||||
|
game_update_path += "-patch";
|
||||||
|
if (std::filesystem::exists(game_update_path)) {
|
||||||
|
Common::FS::PathToQString(gameTrpPath, game_update_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<TrophyGameInfo> allTrophyGames;
|
||||||
|
for (const auto& game : m_game_info->m_games) {
|
||||||
|
TrophyGameInfo gameInfo;
|
||||||
|
gameInfo.name = QString::fromStdString(game.name);
|
||||||
|
Common::FS::PathToQString(gameInfo.trophyPath, game.serial);
|
||||||
|
Common::FS::PathToQString(gameInfo.gameTrpPath, game.path);
|
||||||
|
|
||||||
|
auto update_path = Common::FS::PathFromQString(gameInfo.gameTrpPath);
|
||||||
|
update_path += "-UPDATE";
|
||||||
|
if (std::filesystem::exists(update_path)) {
|
||||||
|
Common::FS::PathToQString(gameInfo.gameTrpPath, update_path);
|
||||||
|
} else {
|
||||||
|
update_path = Common::FS::PathFromQString(gameInfo.gameTrpPath);
|
||||||
|
update_path += "-patch";
|
||||||
|
if (std::filesystem::exists(update_path)) {
|
||||||
|
Common::FS::PathToQString(gameInfo.gameTrpPath, update_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allTrophyGames.append(gameInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString gameName = QString::fromStdString(firstGame.name);
|
||||||
|
TrophyViewer* trophyViewer =
|
||||||
|
new TrophyViewer(trophyPath, gameTrpPath, gameName, allTrophyGames);
|
||||||
|
trophyViewer->show();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Themes
|
// Themes
|
||||||
|
@ -689,6 +873,8 @@ void MainWindow::StartGame() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
StartEmulator(path);
|
StartEmulator(path);
|
||||||
|
|
||||||
|
UpdateToolbarButtons();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,22 +953,6 @@ void MainWindow::SaveWindowState() const {
|
||||||
this->geometry().width(), this->geometry().height());
|
this->geometry().width(), this->geometry().height());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::InstallPkg() {
|
|
||||||
QFileDialog dialog;
|
|
||||||
dialog.setFileMode(QFileDialog::ExistingFiles);
|
|
||||||
dialog.setNameFilter(tr("PKG File (*.PKG *.pkg)"));
|
|
||||||
if (dialog.exec()) {
|
|
||||||
QStringList fileNames = dialog.selectedFiles();
|
|
||||||
int nPkg = fileNames.size();
|
|
||||||
int pkgNum = 0;
|
|
||||||
for (const QString& file : fileNames) {
|
|
||||||
++pkgNum;
|
|
||||||
std::filesystem::path path = Common::FS::PathFromQString(file);
|
|
||||||
MainWindow::InstallDragDropPkg(path, pkgNum, nPkg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::BootGame() {
|
void MainWindow::BootGame() {
|
||||||
QFileDialog dialog;
|
QFileDialog dialog;
|
||||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||||
|
@ -806,260 +976,6 @@ void MainWindow::BootGame() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::InstallDragDropPkg(std::filesystem::path file, int pkgNum, int nPkg) {
|
|
||||||
if (Loader::DetectFileType(file) == Loader::FileTypes::Pkg) {
|
|
||||||
std::string failreason;
|
|
||||||
pkg = PKG();
|
|
||||||
if (!pkg.Open(file, failreason)) {
|
|
||||||
QMessageBox::critical(this, tr("PKG ERROR"), QString::fromStdString(failreason));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!psf.Open(pkg.sfo)) {
|
|
||||||
QMessageBox::critical(this, tr("PKG ERROR"),
|
|
||||||
"Could not read SFO. Check log for details");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto category = psf.GetString("CATEGORY");
|
|
||||||
|
|
||||||
if (!use_for_all_queued || pkgNum == 1) {
|
|
||||||
InstallDirSelect ids;
|
|
||||||
const auto selected = ids.exec();
|
|
||||||
if (selected == QDialog::Rejected) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
last_install_dir = ids.getSelectedDirectory();
|
|
||||||
delete_file_on_install = ids.deleteFileOnInstall();
|
|
||||||
use_for_all_queued = ids.useForAllQueued();
|
|
||||||
}
|
|
||||||
std::filesystem::path game_install_dir = last_install_dir;
|
|
||||||
|
|
||||||
QString pkgType = QString::fromStdString(pkg.GetPkgFlags());
|
|
||||||
bool use_game_update = pkgType.contains("PATCH") && Config::getSeparateUpdateEnabled();
|
|
||||||
|
|
||||||
// Default paths
|
|
||||||
auto game_folder_path = game_install_dir / pkg.GetTitleID();
|
|
||||||
auto game_update_path = use_game_update ? game_folder_path.parent_path() /
|
|
||||||
(std::string{pkg.GetTitleID()} + "-UPDATE")
|
|
||||||
: game_folder_path;
|
|
||||||
const int max_depth = 5;
|
|
||||||
|
|
||||||
if (pkgType.contains("PATCH")) {
|
|
||||||
// For patches, try to find the game recursively
|
|
||||||
auto found_game = Common::FS::FindGameByID(game_install_dir,
|
|
||||||
std::string{pkg.GetTitleID()}, max_depth);
|
|
||||||
if (found_game.has_value()) {
|
|
||||||
game_folder_path = found_game.value().parent_path();
|
|
||||||
game_update_path = use_game_update ? game_folder_path.parent_path() /
|
|
||||||
(std::string{pkg.GetTitleID()} + "-UPDATE")
|
|
||||||
: game_folder_path;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// For base games, we check if the game is already installed
|
|
||||||
auto found_game = Common::FS::FindGameByID(game_install_dir,
|
|
||||||
std::string{pkg.GetTitleID()}, max_depth);
|
|
||||||
if (found_game.has_value()) {
|
|
||||||
game_folder_path = found_game.value().parent_path();
|
|
||||||
}
|
|
||||||
// If the game is not found, we install it in the game install directory
|
|
||||||
else {
|
|
||||||
game_folder_path = game_install_dir / pkg.GetTitleID();
|
|
||||||
}
|
|
||||||
game_update_path = use_game_update ? game_folder_path.parent_path() /
|
|
||||||
(std::string{pkg.GetTitleID()} + "-UPDATE")
|
|
||||||
: game_folder_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString gameDirPath;
|
|
||||||
Common::FS::PathToQString(gameDirPath, game_folder_path);
|
|
||||||
QDir game_dir(gameDirPath);
|
|
||||||
if (game_dir.exists()) {
|
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setWindowTitle(tr("PKG Extraction"));
|
|
||||||
|
|
||||||
std::string content_id;
|
|
||||||
if (auto value = psf.GetString("CONTENT_ID"); value.has_value()) {
|
|
||||||
content_id = std::string{*value};
|
|
||||||
} else {
|
|
||||||
QMessageBox::critical(this, tr("PKG ERROR"), "PSF file there is no CONTENT_ID");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::string entitlement_label = Common::SplitString(content_id, '-')[2];
|
|
||||||
|
|
||||||
auto addon_extract_path =
|
|
||||||
Config::getAddonInstallDir() / pkg.GetTitleID() / entitlement_label;
|
|
||||||
QString addonDirPath;
|
|
||||||
Common::FS::PathToQString(addonDirPath, addon_extract_path);
|
|
||||||
QDir addon_dir(addonDirPath);
|
|
||||||
|
|
||||||
if (pkgType.contains("PATCH")) {
|
|
||||||
QString pkg_app_version;
|
|
||||||
if (auto app_ver = psf.GetString("APP_VER"); app_ver.has_value()) {
|
|
||||||
pkg_app_version = QString::fromStdString(std::string{*app_ver});
|
|
||||||
} else {
|
|
||||||
QMessageBox::critical(this, tr("PKG ERROR"), "PSF file there is no APP_VER");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::filesystem::path sce_folder_path =
|
|
||||||
std::filesystem::exists(game_update_path / "sce_sys" / "param.sfo")
|
|
||||||
? game_update_path / "sce_sys" / "param.sfo"
|
|
||||||
: game_folder_path / "sce_sys" / "param.sfo";
|
|
||||||
psf.Open(sce_folder_path);
|
|
||||||
QString game_app_version;
|
|
||||||
if (auto app_ver = psf.GetString("APP_VER"); app_ver.has_value()) {
|
|
||||||
game_app_version = QString::fromStdString(std::string{*app_ver});
|
|
||||||
} else {
|
|
||||||
QMessageBox::critical(this, tr("PKG ERROR"), "PSF file there is no APP_VER");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
double appD = game_app_version.toDouble();
|
|
||||||
double pkgD = pkg_app_version.toDouble();
|
|
||||||
if (pkgD == appD) {
|
|
||||||
msgBox.setText(QString(tr("Patch detected!") + "\n" +
|
|
||||||
tr("PKG and Game versions match: ") + pkg_app_version +
|
|
||||||
"\n" + tr("Would you like to overwrite?")));
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
||||||
msgBox.setDefaultButton(QMessageBox::No);
|
|
||||||
} else if (pkgD < appD) {
|
|
||||||
msgBox.setText(QString(tr("Patch detected!") + "\n" +
|
|
||||||
tr("PKG Version %1 is older than installed version: ")
|
|
||||||
.arg(pkg_app_version) +
|
|
||||||
game_app_version + "\n" +
|
|
||||||
tr("Would you like to overwrite?")));
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
||||||
msgBox.setDefaultButton(QMessageBox::No);
|
|
||||||
} else {
|
|
||||||
msgBox.setText(QString(tr("Patch detected!") + "\n" +
|
|
||||||
tr("Game is installed: ") + game_app_version + "\n" +
|
|
||||||
tr("Would you like to install Patch: ") +
|
|
||||||
pkg_app_version + " ?"));
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
||||||
msgBox.setDefaultButton(QMessageBox::No);
|
|
||||||
}
|
|
||||||
int result = msgBox.exec();
|
|
||||||
if (result == QMessageBox::Yes) {
|
|
||||||
// Do nothing.
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (category == "ac") {
|
|
||||||
if (!addon_dir.exists()) {
|
|
||||||
QMessageBox addonMsgBox;
|
|
||||||
addonMsgBox.setWindowTitle(tr("DLC Installation"));
|
|
||||||
addonMsgBox.setText(QString(tr("Would you like to install DLC: %1?"))
|
|
||||||
.arg(QString::fromStdString(entitlement_label)));
|
|
||||||
|
|
||||||
addonMsgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
||||||
addonMsgBox.setDefaultButton(QMessageBox::No);
|
|
||||||
int result = addonMsgBox.exec();
|
|
||||||
if (result == QMessageBox::Yes) {
|
|
||||||
game_update_path = addon_extract_path;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msgBox.setText(QString(tr("DLC already installed:") + "\n" + addonDirPath +
|
|
||||||
"\n\n" + tr("Would you like to overwrite?")));
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
||||||
msgBox.setDefaultButton(QMessageBox::No);
|
|
||||||
int result = msgBox.exec();
|
|
||||||
if (result == QMessageBox::Yes) {
|
|
||||||
game_update_path = addon_extract_path;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msgBox.setText(QString(tr("Game already installed") + "\n" + gameDirPath + "\n" +
|
|
||||||
tr("Would you like to overwrite?")));
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
|
||||||
msgBox.setDefaultButton(QMessageBox::No);
|
|
||||||
int result = msgBox.exec();
|
|
||||||
if (result == QMessageBox::Yes) {
|
|
||||||
// Do nothing.
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Do nothing;
|
|
||||||
if (pkgType.contains("PATCH") || category == "ac") {
|
|
||||||
QMessageBox::information(
|
|
||||||
this, tr("PKG Extraction"),
|
|
||||||
tr("PKG is a patch or DLC, please install the game first!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// what else?
|
|
||||||
}
|
|
||||||
if (!pkg.Extract(file, game_update_path, failreason)) {
|
|
||||||
QMessageBox::critical(this, tr("PKG ERROR"), QString::fromStdString(failreason));
|
|
||||||
} else {
|
|
||||||
int nfiles = pkg.GetNumberOfFiles();
|
|
||||||
|
|
||||||
if (nfiles > 0) {
|
|
||||||
QVector<int> indices;
|
|
||||||
for (int i = 0; i < nfiles; i++) {
|
|
||||||
indices.append(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
QProgressDialog dialog;
|
|
||||||
dialog.setWindowTitle(tr("PKG Extraction"));
|
|
||||||
dialog.setWindowModality(Qt::WindowModal);
|
|
||||||
QString extractmsg = QString(tr("Extracting PKG %1/%2")).arg(pkgNum).arg(nPkg);
|
|
||||||
dialog.setLabelText(extractmsg);
|
|
||||||
dialog.setAutoClose(true);
|
|
||||||
dialog.setRange(0, nfiles);
|
|
||||||
|
|
||||||
dialog.setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter,
|
|
||||||
dialog.size(), this->geometry()));
|
|
||||||
|
|
||||||
QFutureWatcher<void> futureWatcher;
|
|
||||||
connect(&futureWatcher, &QFutureWatcher<void>::finished, this, [=, this]() {
|
|
||||||
if (pkgNum == nPkg) {
|
|
||||||
QString path;
|
|
||||||
|
|
||||||
// We want to show the parent path instead of the full path
|
|
||||||
Common::FS::PathToQString(path, game_folder_path.parent_path());
|
|
||||||
QIcon windowIcon(
|
|
||||||
Common::FS::PathToUTF8String(game_folder_path / "sce_sys/icon0.png")
|
|
||||||
.c_str());
|
|
||||||
|
|
||||||
QMessageBox extractMsgBox(this);
|
|
||||||
extractMsgBox.setWindowTitle(tr("Extraction Finished"));
|
|
||||||
if (!windowIcon.isNull()) {
|
|
||||||
extractMsgBox.setWindowIcon(windowIcon);
|
|
||||||
}
|
|
||||||
extractMsgBox.setText(
|
|
||||||
QString(tr("Game successfully installed at %1")).arg(path));
|
|
||||||
extractMsgBox.addButton(QMessageBox::Ok);
|
|
||||||
extractMsgBox.setDefaultButton(QMessageBox::Ok);
|
|
||||||
connect(&extractMsgBox, &QMessageBox::buttonClicked, this,
|
|
||||||
[&](QAbstractButton* button) {
|
|
||||||
if (extractMsgBox.button(QMessageBox::Ok) == button) {
|
|
||||||
extractMsgBox.close();
|
|
||||||
emit ExtractionFinished();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
extractMsgBox.exec();
|
|
||||||
}
|
|
||||||
if (delete_file_on_install) {
|
|
||||||
std::filesystem::remove(file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
connect(&dialog, &QProgressDialog::canceled, [&]() { futureWatcher.cancel(); });
|
|
||||||
connect(&futureWatcher, &QFutureWatcher<void>::progressValueChanged, &dialog,
|
|
||||||
&QProgressDialog::setValue);
|
|
||||||
futureWatcher.setFuture(
|
|
||||||
QtConcurrent::map(indices, [&](int index) { pkg.ExtractFiles(index); }));
|
|
||||||
dialog.exec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QMessageBox::critical(this, tr("PKG ERROR"),
|
|
||||||
tr("File doesn't appear to be a valid PKG file"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::InstallDirectory() {
|
void MainWindow::InstallDirectory() {
|
||||||
GameInstallDialog dlg;
|
GameInstallDialog dlg;
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
|
@ -1142,7 +1058,6 @@ QIcon MainWindow::RecolorIcon(const QIcon& icon, bool isWhite) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::SetUiIcons(bool isWhite) {
|
void MainWindow::SetUiIcons(bool isWhite) {
|
||||||
ui->bootInstallPkgAct->setIcon(RecolorIcon(ui->bootInstallPkgAct->icon(), isWhite));
|
|
||||||
ui->bootGameAct->setIcon(RecolorIcon(ui->bootGameAct->icon(), isWhite));
|
ui->bootGameAct->setIcon(RecolorIcon(ui->bootGameAct->icon(), isWhite));
|
||||||
ui->shadFolderAct->setIcon(RecolorIcon(ui->shadFolderAct->icon(), isWhite));
|
ui->shadFolderAct->setIcon(RecolorIcon(ui->shadFolderAct->icon(), isWhite));
|
||||||
ui->exitAct->setIcon(RecolorIcon(ui->exitAct->icon(), isWhite));
|
ui->exitAct->setIcon(RecolorIcon(ui->exitAct->icon(), isWhite));
|
||||||
|
@ -1163,12 +1078,14 @@ void MainWindow::SetUiIcons(bool isWhite) {
|
||||||
ui->pauseButton->setIcon(RecolorIcon(ui->pauseButton->icon(), isWhite));
|
ui->pauseButton->setIcon(RecolorIcon(ui->pauseButton->icon(), isWhite));
|
||||||
ui->stopButton->setIcon(RecolorIcon(ui->stopButton->icon(), isWhite));
|
ui->stopButton->setIcon(RecolorIcon(ui->stopButton->icon(), isWhite));
|
||||||
ui->refreshButton->setIcon(RecolorIcon(ui->refreshButton->icon(), isWhite));
|
ui->refreshButton->setIcon(RecolorIcon(ui->refreshButton->icon(), isWhite));
|
||||||
|
ui->restartButton->setIcon(RecolorIcon(ui->restartButton->icon(), isWhite));
|
||||||
ui->settingsButton->setIcon(RecolorIcon(ui->settingsButton->icon(), isWhite));
|
ui->settingsButton->setIcon(RecolorIcon(ui->settingsButton->icon(), isWhite));
|
||||||
|
ui->fullscreenButton->setIcon(RecolorIcon(ui->fullscreenButton->icon(), isWhite));
|
||||||
ui->controllerButton->setIcon(RecolorIcon(ui->controllerButton->icon(), isWhite));
|
ui->controllerButton->setIcon(RecolorIcon(ui->controllerButton->icon(), isWhite));
|
||||||
ui->keyboardButton->setIcon(RecolorIcon(ui->keyboardButton->icon(), isWhite));
|
ui->keyboardButton->setIcon(RecolorIcon(ui->keyboardButton->icon(), isWhite));
|
||||||
ui->refreshGameListAct->setIcon(RecolorIcon(ui->refreshGameListAct->icon(), isWhite));
|
ui->refreshGameListAct->setIcon(RecolorIcon(ui->refreshGameListAct->icon(), isWhite));
|
||||||
ui->menuGame_List_Mode->setIcon(RecolorIcon(ui->menuGame_List_Mode->icon(), isWhite));
|
ui->menuGame_List_Mode->setIcon(RecolorIcon(ui->menuGame_List_Mode->icon(), isWhite));
|
||||||
ui->pkgViewerAct->setIcon(RecolorIcon(ui->pkgViewerAct->icon(), isWhite));
|
ui->trophyViewerAct->setIcon(RecolorIcon(ui->trophyViewerAct->icon(), isWhite));
|
||||||
ui->configureAct->setIcon(RecolorIcon(ui->configureAct->icon(), isWhite));
|
ui->configureAct->setIcon(RecolorIcon(ui->configureAct->icon(), isWhite));
|
||||||
ui->addElfFolderAct->setIcon(RecolorIcon(ui->addElfFolderAct->icon(), isWhite));
|
ui->addElfFolderAct->setIcon(RecolorIcon(ui->addElfFolderAct->icon(), isWhite));
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <QActionGroup>
|
#include <QActionGroup>
|
||||||
#include <QDragEnterEvent>
|
#include <QDragEnterEvent>
|
||||||
|
#include <QProcess>
|
||||||
#include <QTranslator>
|
#include <QTranslator>
|
||||||
|
|
||||||
#include "background_music_player.h"
|
#include "background_music_player.h"
|
||||||
|
@ -21,7 +22,6 @@
|
||||||
#include "game_list_utils.h"
|
#include "game_list_utils.h"
|
||||||
#include "main_window_themes.h"
|
#include "main_window_themes.h"
|
||||||
#include "main_window_ui.h"
|
#include "main_window_ui.h"
|
||||||
#include "pkg_viewer.h"
|
|
||||||
|
|
||||||
class GameListFrame;
|
class GameListFrame;
|
||||||
|
|
||||||
|
@ -35,9 +35,10 @@ public:
|
||||||
explicit MainWindow(QWidget* parent = nullptr);
|
explicit MainWindow(QWidget* parent = nullptr);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
bool Init();
|
bool Init();
|
||||||
void InstallDragDropPkg(std::filesystem::path file, int pkgNum, int nPkg);
|
|
||||||
void InstallDirectory();
|
void InstallDirectory();
|
||||||
void StartGame();
|
void StartGame();
|
||||||
|
void PauseGame();
|
||||||
|
bool showLabels;
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void ConfigureGuiFromSettings();
|
void ConfigureGuiFromSettings();
|
||||||
|
@ -47,15 +48,21 @@ private Q_SLOTS:
|
||||||
void RefreshGameTable();
|
void RefreshGameTable();
|
||||||
void HandleResize(QResizeEvent* event);
|
void HandleResize(QResizeEvent* event);
|
||||||
void OnLanguageChanged(const std::string& locale);
|
void OnLanguageChanged(const std::string& locale);
|
||||||
|
void toggleLabelsUnderIcons();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui_MainWindow* ui;
|
Ui_MainWindow* ui;
|
||||||
void AddUiWidgets();
|
void AddUiWidgets();
|
||||||
|
void UpdateToolbarLabels();
|
||||||
|
void UpdateToolbarButtons();
|
||||||
|
QWidget* createButtonWithLabel(QPushButton* button, const QString& labelText, bool showLabel);
|
||||||
void CreateActions();
|
void CreateActions();
|
||||||
|
void toggleFullscreen();
|
||||||
void CreateRecentGameActions();
|
void CreateRecentGameActions();
|
||||||
void CreateDockWindows();
|
void CreateDockWindows();
|
||||||
void GetPhysicalDevices();
|
void GetPhysicalDevices();
|
||||||
void LoadGameLists();
|
void LoadGameLists();
|
||||||
|
|
||||||
#ifdef ENABLE_UPDATER
|
#ifdef ENABLE_UPDATER
|
||||||
void CheckUpdateMain(bool checkSave);
|
void CheckUpdateMain(bool checkSave);
|
||||||
#endif
|
#endif
|
||||||
|
@ -63,7 +70,6 @@ private:
|
||||||
void SetLastUsedTheme();
|
void SetLastUsedTheme();
|
||||||
void SetLastIconSizeBullet();
|
void SetLastIconSizeBullet();
|
||||||
void SetUiIcons(bool isWhite);
|
void SetUiIcons(bool isWhite);
|
||||||
void InstallPkg();
|
|
||||||
void BootGame();
|
void BootGame();
|
||||||
void AddRecentFiles(QString filePath);
|
void AddRecentFiles(QString filePath);
|
||||||
void LoadTranslation();
|
void LoadTranslation();
|
||||||
|
@ -73,11 +79,13 @@ private:
|
||||||
bool isIconBlack = false;
|
bool isIconBlack = false;
|
||||||
bool isTableList = true;
|
bool isTableList = true;
|
||||||
bool isGameRunning = false;
|
bool isGameRunning = false;
|
||||||
|
bool isWhite = false;
|
||||||
|
bool is_paused = false;
|
||||||
|
|
||||||
QActionGroup* m_icon_size_act_group = nullptr;
|
QActionGroup* m_icon_size_act_group = nullptr;
|
||||||
QActionGroup* m_list_mode_act_group = nullptr;
|
QActionGroup* m_list_mode_act_group = nullptr;
|
||||||
QActionGroup* m_theme_act_group = nullptr;
|
QActionGroup* m_theme_act_group = nullptr;
|
||||||
QActionGroup* m_recent_files_group = nullptr;
|
QActionGroup* m_recent_files_group = nullptr;
|
||||||
PKG pkg;
|
|
||||||
// Dockable widget frames
|
// Dockable widget frames
|
||||||
WindowThemes m_window_themes;
|
WindowThemes m_window_themes;
|
||||||
GameListUtils m_game_list_utils;
|
GameListUtils m_game_list_utils;
|
||||||
|
@ -108,20 +116,6 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dropEvent(QDropEvent* event1) override {
|
|
||||||
const QMimeData* mimeData = event1->mimeData();
|
|
||||||
if (mimeData->hasUrls()) {
|
|
||||||
QList<QUrl> urlList = mimeData->urls();
|
|
||||||
int pkgNum = 0;
|
|
||||||
int nPkg = urlList.size();
|
|
||||||
for (const QUrl& url : urlList) {
|
|
||||||
pkgNum++;
|
|
||||||
std::filesystem::path path = Common::FS::PathFromQString(url.toLocalFile());
|
|
||||||
InstallDragDropPkg(path, pkgNum, nPkg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent* event) override;
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
|
|
||||||
std::filesystem::path last_install_dir = "";
|
std::filesystem::path last_install_dir = "";
|
||||||
|
|
|
@ -19,7 +19,7 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) {
|
||||||
themePalette.setColor(QPalette::WindowText, Qt::white);
|
themePalette.setColor(QPalette::WindowText, Qt::white);
|
||||||
themePalette.setColor(QPalette::Base, QColor(20, 20, 20));
|
themePalette.setColor(QPalette::Base, QColor(20, 20, 20));
|
||||||
themePalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
|
themePalette.setColor(QPalette::AlternateBase, QColor(53, 53, 53));
|
||||||
themePalette.setColor(QPalette::ToolTipBase, Qt::white);
|
themePalette.setColor(QPalette::ToolTipBase, QColor(20, 20, 20));
|
||||||
themePalette.setColor(QPalette::ToolTipText, Qt::white);
|
themePalette.setColor(QPalette::ToolTipText, Qt::white);
|
||||||
themePalette.setColor(QPalette::Text, Qt::white);
|
themePalette.setColor(QPalette::Text, Qt::white);
|
||||||
themePalette.setColor(QPalette::Button, QColor(53, 53, 53));
|
themePalette.setColor(QPalette::Button, QColor(53, 53, 53));
|
||||||
|
@ -37,18 +37,18 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) {
|
||||||
"border-radius: 4px; padding: 5px; }"
|
"border-radius: 4px; padding: 5px; }"
|
||||||
"QLineEdit:focus {"
|
"QLineEdit:focus {"
|
||||||
"border: 1px solid #2A82DA; }");
|
"border: 1px solid #2A82DA; }");
|
||||||
themePalette.setColor(QPalette::Window, QColor(240, 240, 240)); // Light gray
|
themePalette.setColor(QPalette::Window, QColor(240, 240, 240)); // Light gray
|
||||||
themePalette.setColor(QPalette::WindowText, Qt::black); // Black
|
themePalette.setColor(QPalette::WindowText, Qt::black); // Black
|
||||||
themePalette.setColor(QPalette::Base, QColor(230, 230, 230, 80)); // Grayish
|
themePalette.setColor(QPalette::Base, QColor(230, 230, 230, 80)); // Grayish
|
||||||
themePalette.setColor(QPalette::ToolTipBase, Qt::black); // Black
|
themePalette.setColor(QPalette::ToolTipBase, QColor(230, 230, 230, 80)); // Grayish
|
||||||
themePalette.setColor(QPalette::ToolTipText, Qt::black); // Black
|
themePalette.setColor(QPalette::ToolTipText, Qt::black); // Black
|
||||||
themePalette.setColor(QPalette::Text, Qt::black); // Black
|
themePalette.setColor(QPalette::Text, Qt::black); // Black
|
||||||
themePalette.setColor(QPalette::Button, QColor(240, 240, 240)); // Light gray
|
themePalette.setColor(QPalette::Button, QColor(240, 240, 240)); // Light gray
|
||||||
themePalette.setColor(QPalette::ButtonText, Qt::black); // Black
|
themePalette.setColor(QPalette::ButtonText, Qt::black); // Black
|
||||||
themePalette.setColor(QPalette::BrightText, Qt::red); // Red
|
themePalette.setColor(QPalette::BrightText, Qt::red); // Red
|
||||||
themePalette.setColor(QPalette::Link, QColor(42, 130, 218)); // Blue
|
themePalette.setColor(QPalette::Link, QColor(42, 130, 218)); // Blue
|
||||||
themePalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); // Blue
|
themePalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); // Blue
|
||||||
themePalette.setColor(QPalette::HighlightedText, Qt::white); // White
|
themePalette.setColor(QPalette::HighlightedText, Qt::white); // White
|
||||||
qApp->setPalette(themePalette);
|
qApp->setPalette(themePalette);
|
||||||
break;
|
break;
|
||||||
case Theme::Green:
|
case Theme::Green:
|
||||||
|
@ -62,8 +62,9 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) {
|
||||||
themePalette.setColor(QPalette::WindowText, Qt::white); // White text
|
themePalette.setColor(QPalette::WindowText, Qt::white); // White text
|
||||||
themePalette.setColor(QPalette::Base, QColor(25, 40, 25)); // Darker green base
|
themePalette.setColor(QPalette::Base, QColor(25, 40, 25)); // Darker green base
|
||||||
themePalette.setColor(QPalette::AlternateBase,
|
themePalette.setColor(QPalette::AlternateBase,
|
||||||
QColor(53, 69, 53)); // Dark green alternate base
|
QColor(53, 69, 53)); // Dark green alternate base
|
||||||
themePalette.setColor(QPalette::ToolTipBase, Qt::white); // White tooltip background
|
themePalette.setColor(QPalette::ToolTipBase,
|
||||||
|
QColor(25, 40, 25)); // White tooltip background
|
||||||
themePalette.setColor(QPalette::ToolTipText, Qt::white); // White tooltip text
|
themePalette.setColor(QPalette::ToolTipText, Qt::white); // White tooltip text
|
||||||
themePalette.setColor(QPalette::Text, Qt::white); // White text
|
themePalette.setColor(QPalette::Text, Qt::white); // White text
|
||||||
themePalette.setColor(QPalette::Button, QColor(53, 69, 53)); // Dark green button
|
themePalette.setColor(QPalette::Button, QColor(53, 69, 53)); // Dark green button
|
||||||
|
@ -85,8 +86,9 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) {
|
||||||
themePalette.setColor(QPalette::WindowText, Qt::white); // White text
|
themePalette.setColor(QPalette::WindowText, Qt::white); // White text
|
||||||
themePalette.setColor(QPalette::Base, QColor(20, 40, 60)); // Darker blue base
|
themePalette.setColor(QPalette::Base, QColor(20, 40, 60)); // Darker blue base
|
||||||
themePalette.setColor(QPalette::AlternateBase,
|
themePalette.setColor(QPalette::AlternateBase,
|
||||||
QColor(40, 60, 90)); // Dark blue alternate base
|
QColor(40, 60, 90)); // Dark blue alternate base
|
||||||
themePalette.setColor(QPalette::ToolTipBase, Qt::white); // White tooltip background
|
themePalette.setColor(QPalette::ToolTipBase,
|
||||||
|
QColor(20, 40, 60)); // White tooltip background
|
||||||
themePalette.setColor(QPalette::ToolTipText, Qt::white); // White tooltip text
|
themePalette.setColor(QPalette::ToolTipText, Qt::white); // White tooltip text
|
||||||
themePalette.setColor(QPalette::Text, Qt::white); // White text
|
themePalette.setColor(QPalette::Text, Qt::white); // White text
|
||||||
themePalette.setColor(QPalette::Button, QColor(40, 60, 90)); // Dark blue button
|
themePalette.setColor(QPalette::Button, QColor(40, 60, 90)); // Dark blue button
|
||||||
|
@ -109,8 +111,9 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) {
|
||||||
themePalette.setColor(QPalette::WindowText, Qt::white); // White text
|
themePalette.setColor(QPalette::WindowText, Qt::white); // White text
|
||||||
themePalette.setColor(QPalette::Base, QColor(80, 30, 90)); // Darker violet base
|
themePalette.setColor(QPalette::Base, QColor(80, 30, 90)); // Darker violet base
|
||||||
themePalette.setColor(QPalette::AlternateBase,
|
themePalette.setColor(QPalette::AlternateBase,
|
||||||
QColor(100, 50, 120)); // Violet alternate base
|
QColor(100, 50, 120)); // Violet alternate base
|
||||||
themePalette.setColor(QPalette::ToolTipBase, Qt::white); // White tooltip background
|
themePalette.setColor(QPalette::ToolTipBase,
|
||||||
|
QColor(80, 30, 90)); // White tooltip background
|
||||||
themePalette.setColor(QPalette::ToolTipText, Qt::white); // White tooltip text
|
themePalette.setColor(QPalette::ToolTipText, Qt::white); // White tooltip text
|
||||||
themePalette.setColor(QPalette::Text, Qt::white); // White text
|
themePalette.setColor(QPalette::Text, Qt::white); // White text
|
||||||
themePalette.setColor(QPalette::Button, QColor(100, 50, 120)); // Violet button
|
themePalette.setColor(QPalette::Button, QColor(100, 50, 120)); // Violet button
|
||||||
|
@ -133,7 +136,7 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) {
|
||||||
themePalette.setColor(QPalette::WindowText, QColor(249, 245, 215));
|
themePalette.setColor(QPalette::WindowText, QColor(249, 245, 215));
|
||||||
themePalette.setColor(QPalette::Base, QColor(29, 32, 33));
|
themePalette.setColor(QPalette::Base, QColor(29, 32, 33));
|
||||||
themePalette.setColor(QPalette::AlternateBase, QColor(50, 48, 47));
|
themePalette.setColor(QPalette::AlternateBase, QColor(50, 48, 47));
|
||||||
themePalette.setColor(QPalette::ToolTipBase, QColor(249, 245, 215));
|
themePalette.setColor(QPalette::ToolTipBase, QColor(29, 32, 33));
|
||||||
themePalette.setColor(QPalette::ToolTipText, QColor(249, 245, 215));
|
themePalette.setColor(QPalette::ToolTipText, QColor(249, 245, 215));
|
||||||
themePalette.setColor(QPalette::Text, QColor(249, 245, 215));
|
themePalette.setColor(QPalette::Text, QColor(249, 245, 215));
|
||||||
themePalette.setColor(QPalette::Button, QColor(40, 40, 40));
|
themePalette.setColor(QPalette::Button, QColor(40, 40, 40));
|
||||||
|
@ -155,7 +158,7 @@ void WindowThemes::SetWindowTheme(Theme theme, QLineEdit* mw_searchbar) {
|
||||||
themePalette.setColor(QPalette::WindowText, QColor(192, 202, 245));
|
themePalette.setColor(QPalette::WindowText, QColor(192, 202, 245));
|
||||||
themePalette.setColor(QPalette::Base, QColor(25, 28, 39));
|
themePalette.setColor(QPalette::Base, QColor(25, 28, 39));
|
||||||
themePalette.setColor(QPalette::AlternateBase, QColor(36, 40, 59));
|
themePalette.setColor(QPalette::AlternateBase, QColor(36, 40, 59));
|
||||||
themePalette.setColor(QPalette::ToolTipBase, QColor(192, 202, 245));
|
themePalette.setColor(QPalette::ToolTipBase, QColor(25, 28, 39));
|
||||||
themePalette.setColor(QPalette::ToolTipText, QColor(192, 202, 245));
|
themePalette.setColor(QPalette::ToolTipText, QColor(192, 202, 245));
|
||||||
themePalette.setColor(QPalette::Text, QColor(192, 202, 245));
|
themePalette.setColor(QPalette::Text, QColor(192, 202, 245));
|
||||||
themePalette.setColor(QPalette::Button, QColor(30, 30, 41));
|
themePalette.setColor(QPalette::Button, QColor(30, 30, 41));
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
class Ui_MainWindow {
|
class Ui_MainWindow {
|
||||||
public:
|
public:
|
||||||
QAction* bootInstallPkgAct;
|
|
||||||
QAction* bootGameAct;
|
QAction* bootGameAct;
|
||||||
QAction* addElfFolderAct;
|
QAction* addElfFolderAct;
|
||||||
QAction* shadFolderAct;
|
QAction* shadFolderAct;
|
||||||
|
@ -20,13 +19,14 @@ public:
|
||||||
QAction* setIconSizeSmallAct;
|
QAction* setIconSizeSmallAct;
|
||||||
QAction* setIconSizeMediumAct;
|
QAction* setIconSizeMediumAct;
|
||||||
QAction* setIconSizeLargeAct;
|
QAction* setIconSizeLargeAct;
|
||||||
|
QAction* toggleLabelsAct;
|
||||||
QAction* setlistModeListAct;
|
QAction* setlistModeListAct;
|
||||||
QAction* setlistModeGridAct;
|
QAction* setlistModeGridAct;
|
||||||
QAction* setlistElfAct;
|
QAction* setlistElfAct;
|
||||||
QAction* gameInstallPathAct;
|
QAction* gameInstallPathAct;
|
||||||
QAction* downloadCheatsPatchesAct;
|
QAction* downloadCheatsPatchesAct;
|
||||||
QAction* dumpGameListAct;
|
QAction* dumpGameListAct;
|
||||||
QAction* pkgViewerAct;
|
QAction* trophyViewerAct;
|
||||||
#ifdef ENABLE_UPDATER
|
#ifdef ENABLE_UPDATER
|
||||||
QAction* updaterAct;
|
QAction* updaterAct;
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,6 +49,8 @@ public:
|
||||||
QPushButton* settingsButton;
|
QPushButton* settingsButton;
|
||||||
QPushButton* controllerButton;
|
QPushButton* controllerButton;
|
||||||
QPushButton* keyboardButton;
|
QPushButton* keyboardButton;
|
||||||
|
QPushButton* fullscreenButton;
|
||||||
|
QPushButton* restartButton;
|
||||||
|
|
||||||
QWidget* sizeSliderContainer;
|
QWidget* sizeSliderContainer;
|
||||||
QHBoxLayout* sizeSliderContainer_layout;
|
QHBoxLayout* sizeSliderContainer_layout;
|
||||||
|
@ -83,9 +85,6 @@ public:
|
||||||
MainWindow->setDockNestingEnabled(true);
|
MainWindow->setDockNestingEnabled(true);
|
||||||
MainWindow->setDockOptions(QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks |
|
MainWindow->setDockOptions(QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks |
|
||||||
QMainWindow::AnimatedDocks | QMainWindow::GroupedDragging);
|
QMainWindow::AnimatedDocks | QMainWindow::GroupedDragging);
|
||||||
bootInstallPkgAct = new QAction(MainWindow);
|
|
||||||
bootInstallPkgAct->setObjectName("bootInstallPkgAct");
|
|
||||||
bootInstallPkgAct->setIcon(QIcon(":images/file_icon.png"));
|
|
||||||
bootGameAct = new QAction(MainWindow);
|
bootGameAct = new QAction(MainWindow);
|
||||||
bootGameAct->setObjectName("bootGameAct");
|
bootGameAct->setObjectName("bootGameAct");
|
||||||
bootGameAct->setIcon(QIcon(":images/play_icon.png"));
|
bootGameAct->setIcon(QIcon(":images/play_icon.png"));
|
||||||
|
@ -103,7 +102,15 @@ public:
|
||||||
showGameListAct->setCheckable(true);
|
showGameListAct->setCheckable(true);
|
||||||
refreshGameListAct = new QAction(MainWindow);
|
refreshGameListAct = new QAction(MainWindow);
|
||||||
refreshGameListAct->setObjectName("refreshGameListAct");
|
refreshGameListAct->setObjectName("refreshGameListAct");
|
||||||
refreshGameListAct->setIcon(QIcon(":images/refresh_icon.png"));
|
refreshGameListAct->setIcon(QIcon(":images/refreshlist_icon.png"));
|
||||||
|
|
||||||
|
toggleLabelsAct = new QAction(MainWindow);
|
||||||
|
toggleLabelsAct->setObjectName("toggleLabelsAct");
|
||||||
|
toggleLabelsAct->setText(
|
||||||
|
QCoreApplication::translate("MainWindow", "Show Labels Under Icons"));
|
||||||
|
toggleLabelsAct->setCheckable(true);
|
||||||
|
toggleLabelsAct->setChecked(Config::getShowLabelsUnderIcons());
|
||||||
|
|
||||||
setIconSizeTinyAct = new QAction(MainWindow);
|
setIconSizeTinyAct = new QAction(MainWindow);
|
||||||
setIconSizeTinyAct->setObjectName("setIconSizeTinyAct");
|
setIconSizeTinyAct->setObjectName("setIconSizeTinyAct");
|
||||||
setIconSizeTinyAct->setCheckable(true);
|
setIconSizeTinyAct->setCheckable(true);
|
||||||
|
@ -136,9 +143,10 @@ public:
|
||||||
dumpGameListAct = new QAction(MainWindow);
|
dumpGameListAct = new QAction(MainWindow);
|
||||||
dumpGameListAct->setObjectName("dumpGameList");
|
dumpGameListAct->setObjectName("dumpGameList");
|
||||||
dumpGameListAct->setIcon(QIcon(":images/dump_icon.png"));
|
dumpGameListAct->setIcon(QIcon(":images/dump_icon.png"));
|
||||||
pkgViewerAct = new QAction(MainWindow);
|
trophyViewerAct = new QAction(MainWindow);
|
||||||
pkgViewerAct->setObjectName("pkgViewer");
|
trophyViewerAct->setObjectName("trophyViewer");
|
||||||
pkgViewerAct->setIcon(QIcon(":images/file_icon.png"));
|
trophyViewerAct->setIcon(QIcon(":images/trophy_icon.png"));
|
||||||
|
|
||||||
#ifdef ENABLE_UPDATER
|
#ifdef ENABLE_UPDATER
|
||||||
updaterAct = new QAction(MainWindow);
|
updaterAct = new QAction(MainWindow);
|
||||||
updaterAct->setObjectName("updaterAct");
|
updaterAct->setObjectName("updaterAct");
|
||||||
|
@ -205,20 +213,28 @@ public:
|
||||||
stopButton->setIconSize(QSize(40, 40));
|
stopButton->setIconSize(QSize(40, 40));
|
||||||
refreshButton = new QPushButton(centralWidget);
|
refreshButton = new QPushButton(centralWidget);
|
||||||
refreshButton->setFlat(true);
|
refreshButton->setFlat(true);
|
||||||
refreshButton->setIcon(QIcon(":images/refresh_icon.png"));
|
refreshButton->setIcon(QIcon(":images/refreshlist_icon.png"));
|
||||||
refreshButton->setIconSize(QSize(32, 32));
|
refreshButton->setIconSize(QSize(40, 40));
|
||||||
|
fullscreenButton = new QPushButton(centralWidget);
|
||||||
|
fullscreenButton->setFlat(true);
|
||||||
|
fullscreenButton->setIcon(QIcon(":images/fullscreen_icon.png"));
|
||||||
|
fullscreenButton->setIconSize(QSize(38, 38));
|
||||||
settingsButton = new QPushButton(centralWidget);
|
settingsButton = new QPushButton(centralWidget);
|
||||||
settingsButton->setFlat(true);
|
settingsButton->setFlat(true);
|
||||||
settingsButton->setIcon(QIcon(":images/settings_icon.png"));
|
settingsButton->setIcon(QIcon(":images/settings_icon.png"));
|
||||||
settingsButton->setIconSize(QSize(44, 44));
|
settingsButton->setIconSize(QSize(40, 40));
|
||||||
controllerButton = new QPushButton(centralWidget);
|
controllerButton = new QPushButton(centralWidget);
|
||||||
controllerButton->setFlat(true);
|
controllerButton->setFlat(true);
|
||||||
controllerButton->setIcon(QIcon(":images/controller_icon.png"));
|
controllerButton->setIcon(QIcon(":images/controller_icon.png"));
|
||||||
controllerButton->setIconSize(QSize(40, 40));
|
controllerButton->setIconSize(QSize(55, 48));
|
||||||
keyboardButton = new QPushButton(centralWidget);
|
keyboardButton = new QPushButton(centralWidget);
|
||||||
keyboardButton->setFlat(true);
|
keyboardButton->setFlat(true);
|
||||||
keyboardButton->setIcon(QIcon(":images/keyboard_icon.png"));
|
keyboardButton->setIcon(QIcon(":images/keyboard_icon.png"));
|
||||||
keyboardButton->setIconSize(QSize(48, 44));
|
keyboardButton->setIconSize(QSize(50, 50));
|
||||||
|
restartButton = new QPushButton(centralWidget);
|
||||||
|
restartButton->setFlat(true);
|
||||||
|
restartButton->setIcon(QIcon(":images/restart_game_icon.png"));
|
||||||
|
restartButton->setIconSize(QSize(40, 40));
|
||||||
|
|
||||||
sizeSliderContainer = new QWidget(centralWidget);
|
sizeSliderContainer = new QWidget(centralWidget);
|
||||||
sizeSliderContainer->setObjectName("sizeSliderContainer");
|
sizeSliderContainer->setObjectName("sizeSliderContainer");
|
||||||
|
@ -285,7 +301,6 @@ public:
|
||||||
menuBar->addAction(menuView->menuAction());
|
menuBar->addAction(menuView->menuAction());
|
||||||
menuBar->addAction(menuSettings->menuAction());
|
menuBar->addAction(menuSettings->menuAction());
|
||||||
menuBar->addAction(menuHelp->menuAction());
|
menuBar->addAction(menuHelp->menuAction());
|
||||||
menuFile->addAction(bootInstallPkgAct);
|
|
||||||
menuFile->addAction(bootGameAct);
|
menuFile->addAction(bootGameAct);
|
||||||
menuFile->addSeparator();
|
menuFile->addSeparator();
|
||||||
menuFile->addAction(addElfFolderAct);
|
menuFile->addAction(addElfFolderAct);
|
||||||
|
@ -299,6 +314,7 @@ public:
|
||||||
menuView->addAction(refreshGameListAct);
|
menuView->addAction(refreshGameListAct);
|
||||||
menuView->addAction(menuGame_List_Mode->menuAction());
|
menuView->addAction(menuGame_List_Mode->menuAction());
|
||||||
menuView->addAction(menuGame_List_Icons->menuAction());
|
menuView->addAction(menuGame_List_Icons->menuAction());
|
||||||
|
menuView->addAction(toggleLabelsAct);
|
||||||
menuView->addAction(menuThemes->menuAction());
|
menuView->addAction(menuThemes->menuAction());
|
||||||
menuThemes->addAction(setThemeDark);
|
menuThemes->addAction(setThemeDark);
|
||||||
menuThemes->addAction(setThemeLight);
|
menuThemes->addAction(setThemeLight);
|
||||||
|
@ -320,7 +336,7 @@ public:
|
||||||
menuSettings->addAction(menuUtils->menuAction());
|
menuSettings->addAction(menuUtils->menuAction());
|
||||||
menuUtils->addAction(downloadCheatsPatchesAct);
|
menuUtils->addAction(downloadCheatsPatchesAct);
|
||||||
menuUtils->addAction(dumpGameListAct);
|
menuUtils->addAction(dumpGameListAct);
|
||||||
menuUtils->addAction(pkgViewerAct);
|
menuUtils->addAction(trophyViewerAct);
|
||||||
#ifdef ENABLE_UPDATER
|
#ifdef ENABLE_UPDATER
|
||||||
menuHelp->addAction(updaterAct);
|
menuHelp->addAction(updaterAct);
|
||||||
#endif
|
#endif
|
||||||
|
@ -335,8 +351,6 @@ public:
|
||||||
MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "shadPS4", nullptr));
|
MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "shadPS4", nullptr));
|
||||||
addElfFolderAct->setText(
|
addElfFolderAct->setText(
|
||||||
QCoreApplication::translate("MainWindow", "Open/Add Elf Folder", nullptr));
|
QCoreApplication::translate("MainWindow", "Open/Add Elf Folder", nullptr));
|
||||||
bootInstallPkgAct->setText(
|
|
||||||
QCoreApplication::translate("MainWindow", "Install Packages (PKG)", nullptr));
|
|
||||||
bootGameAct->setText(QCoreApplication::translate("MainWindow", "Boot Game", nullptr));
|
bootGameAct->setText(QCoreApplication::translate("MainWindow", "Boot Game", nullptr));
|
||||||
#ifdef ENABLE_UPDATER
|
#ifdef ENABLE_UPDATER
|
||||||
updaterAct->setText(
|
updaterAct->setText(
|
||||||
|
@ -345,8 +359,6 @@ public:
|
||||||
aboutAct->setText(QCoreApplication::translate("MainWindow", "About shadPS4", nullptr));
|
aboutAct->setText(QCoreApplication::translate("MainWindow", "About shadPS4", nullptr));
|
||||||
configureAct->setText(QCoreApplication::translate("MainWindow", "Configure...", nullptr));
|
configureAct->setText(QCoreApplication::translate("MainWindow", "Configure...", nullptr));
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
bootInstallPkgAct->setToolTip(QCoreApplication::translate(
|
|
||||||
"MainWindow", "Install application from a .pkg file", nullptr));
|
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
menuRecent->setTitle(QCoreApplication::translate("MainWindow", "Recent Games", nullptr));
|
menuRecent->setTitle(QCoreApplication::translate("MainWindow", "Recent Games", nullptr));
|
||||||
shadFolderAct->setText(
|
shadFolderAct->setText(
|
||||||
|
@ -378,7 +390,8 @@ public:
|
||||||
QCoreApplication::translate("MainWindow", "Download Cheats/Patches", nullptr));
|
QCoreApplication::translate("MainWindow", "Download Cheats/Patches", nullptr));
|
||||||
dumpGameListAct->setText(
|
dumpGameListAct->setText(
|
||||||
QCoreApplication::translate("MainWindow", "Dump Game List", nullptr));
|
QCoreApplication::translate("MainWindow", "Dump Game List", nullptr));
|
||||||
pkgViewerAct->setText(QCoreApplication::translate("MainWindow", "PKG Viewer", nullptr));
|
trophyViewerAct->setText(
|
||||||
|
QCoreApplication::translate("MainWindow", "Trophy Viewer", nullptr));
|
||||||
mw_searchbar->setPlaceholderText(
|
mw_searchbar->setPlaceholderText(
|
||||||
QCoreApplication::translate("MainWindow", "Search...", nullptr));
|
QCoreApplication::translate("MainWindow", "Search...", nullptr));
|
||||||
menuFile->setTitle(QCoreApplication::translate("MainWindow", "File", nullptr));
|
menuFile->setTitle(QCoreApplication::translate("MainWindow", "File", nullptr));
|
||||||
|
@ -405,4 +418,4 @@ public:
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class MainWindow : public Ui_MainWindow {};
|
class MainWindow : public Ui_MainWindow {};
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
@ -1,217 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#include "pkg_viewer.h"
|
|
||||||
|
|
||||||
PKGViewer::PKGViewer(std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent,
|
|
||||||
std::function<void(std::filesystem::path, int, int)> InstallDragDropPkg)
|
|
||||||
: QMainWindow(), m_game_info(game_info_get) {
|
|
||||||
this->resize(1280, 720);
|
|
||||||
this->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
dir_list_std = Config::getPkgViewer();
|
|
||||||
dir_list.clear();
|
|
||||||
for (const auto& str : dir_list_std) {
|
|
||||||
dir_list.append(QString::fromStdString(str));
|
|
||||||
}
|
|
||||||
statusBar = new QStatusBar(treeWidget);
|
|
||||||
this->setStatusBar(statusBar);
|
|
||||||
treeWidget = new QTreeWidget(this);
|
|
||||||
treeWidget->setColumnCount(9);
|
|
||||||
QStringList headers;
|
|
||||||
headers << tr("Name") << tr("Serial") << tr("Installed") << tr("Size") << tr("Category")
|
|
||||||
<< tr("Type") << tr("App Ver") << tr("FW") << tr("Region") << tr("Flags") << tr("Path");
|
|
||||||
treeWidget->setHeaderLabels(headers);
|
|
||||||
treeWidget->header()->setDefaultAlignment(Qt::AlignCenter);
|
|
||||||
treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
treeWidget->setColumnWidth(8, 170);
|
|
||||||
this->setCentralWidget(treeWidget);
|
|
||||||
QMenuBar* menuBar = new QMenuBar(this);
|
|
||||||
menuBar->setContextMenuPolicy(Qt::PreventContextMenu);
|
|
||||||
QMenu* fileMenu = menuBar->addMenu(tr("File"));
|
|
||||||
QAction* openFolderAct = new QAction(tr("Open Folder"), this);
|
|
||||||
fileMenu->addAction(openFolderAct);
|
|
||||||
this->setMenuBar(menuBar);
|
|
||||||
CheckPKGFolders(); // Check for new PKG files in existing folders.
|
|
||||||
ProcessPKGInfo();
|
|
||||||
|
|
||||||
connect(openFolderAct, &QAction::triggered, this, &PKGViewer::OpenPKGFolder);
|
|
||||||
|
|
||||||
connect(treeWidget, &QTreeWidget::customContextMenuRequested, this,
|
|
||||||
[=, this](const QPoint& pos) {
|
|
||||||
if (treeWidget->selectedItems().isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_gui_context_menus.RequestGameMenuPKGViewer(pos, m_full_pkg_list, treeWidget,
|
|
||||||
InstallDragDropPkg);
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(parent, &QWidget::destroyed, this, [this]() { this->deleteLater(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
PKGViewer::~PKGViewer() {}
|
|
||||||
|
|
||||||
void PKGViewer::OpenPKGFolder() {
|
|
||||||
QString folderPath =
|
|
||||||
QFileDialog::getExistingDirectory(this, tr("Open Folder"), QDir::homePath());
|
|
||||||
if (!dir_list.contains(folderPath)) {
|
|
||||||
dir_list.append(folderPath);
|
|
||||||
QDir directory(folderPath);
|
|
||||||
QFileInfoList fileInfoList = directory.entryInfoList(QDir::Files);
|
|
||||||
for (const QFileInfo& fileInfo : fileInfoList) {
|
|
||||||
QString file_ext = fileInfo.suffix();
|
|
||||||
if (fileInfo.isFile() && file_ext == "pkg") {
|
|
||||||
m_pkg_list.append(fileInfo.absoluteFilePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(m_pkg_list.begin(), m_pkg_list.end());
|
|
||||||
ProcessPKGInfo();
|
|
||||||
dir_list_std.clear();
|
|
||||||
for (auto dir : dir_list) {
|
|
||||||
dir_list_std.push_back(dir.toStdString());
|
|
||||||
}
|
|
||||||
Config::setPkgViewer(dir_list_std);
|
|
||||||
} else {
|
|
||||||
// qDebug() << "Folder selection canceled.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PKGViewer::CheckPKGFolders() { // Check for new PKG file additions.
|
|
||||||
m_pkg_list.clear();
|
|
||||||
for (const QString& dir : dir_list) {
|
|
||||||
QDir directory(dir);
|
|
||||||
QFileInfoList fileInfoList = directory.entryInfoList(QDir::Files);
|
|
||||||
for (const QFileInfo& fileInfo : fileInfoList) {
|
|
||||||
QString file_ext = fileInfo.suffix();
|
|
||||||
if (fileInfo.isFile() && file_ext == "pkg") {
|
|
||||||
m_pkg_list.append(fileInfo.absoluteFilePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(m_pkg_list.begin(), m_pkg_list.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PKGViewer::ProcessPKGInfo() {
|
|
||||||
treeWidget->clear();
|
|
||||||
map_strings.clear();
|
|
||||||
map_integers.clear();
|
|
||||||
m_pkg_app_list.clear();
|
|
||||||
m_pkg_patch_list.clear();
|
|
||||||
m_full_pkg_list.clear();
|
|
||||||
for (int i = 0; i < m_pkg_list.size(); i++) {
|
|
||||||
std::filesystem::path path = Common::FS::PathFromQString(m_pkg_list[i]);
|
|
||||||
std::string failreason;
|
|
||||||
if (!package.Open(path, failreason)) {
|
|
||||||
QMessageBox::critical(this, tr("PKG ERROR"), QString::fromStdString(failreason));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
psf.Open(package.sfo);
|
|
||||||
QString title_name = QString::fromStdString(
|
|
||||||
std::string{psf.GetString("TITLE").value_or(std::string{tr("Unknown").toStdString()})});
|
|
||||||
QString title_id = QString::fromStdString(std::string{
|
|
||||||
psf.GetString("TITLE_ID").value_or(std::string{tr("Unknown").toStdString()})});
|
|
||||||
QString app_type = GameListUtils::GetAppType(psf.GetInteger("APP_TYPE").value_or(0));
|
|
||||||
QString app_version = QString::fromStdString(std::string{
|
|
||||||
psf.GetString("APP_VER").value_or(std::string{tr("Unknown").toStdString()})});
|
|
||||||
QString title_category = QString::fromStdString(std::string{
|
|
||||||
psf.GetString("CATEGORY").value_or(std::string{tr("Unknown").toStdString()})});
|
|
||||||
QString pkg_size = GameListUtils::FormatSize(package.GetPkgHeader().pkg_size);
|
|
||||||
pkg_content_flag = package.GetPkgHeader().pkg_content_flags;
|
|
||||||
QString flagss = "";
|
|
||||||
for (const auto& flag : package.flagNames) {
|
|
||||||
if (package.isFlagSet(pkg_content_flag, flag.first)) {
|
|
||||||
if (!flagss.isEmpty())
|
|
||||||
flagss += (", ");
|
|
||||||
flagss += QString::fromStdString(flag.second.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QString fw_ = tr("Unknown");
|
|
||||||
if (const auto fw_int_opt = psf.GetInteger("SYSTEM_VER"); fw_int_opt.has_value()) {
|
|
||||||
const u32 fw_int = *fw_int_opt;
|
|
||||||
if (fw_int == 0) {
|
|
||||||
fw_ = "0.00";
|
|
||||||
} else {
|
|
||||||
QString fw = QString::number(fw_int, 16);
|
|
||||||
fw_ = fw.length() > 7 ? QString::number(fw_int, 16).left(3).insert(2, '.')
|
|
||||||
: fw.left(3).insert(1, '.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
char region = package.GetPkgHeader().pkg_content_id[0];
|
|
||||||
QString pkg_info = "";
|
|
||||||
if (title_category == "gd" && !flagss.contains("PATCH")) {
|
|
||||||
title_category = "App";
|
|
||||||
pkg_info = title_name + ";;" + title_id + ";;" + pkg_size + ";;" + title_category +
|
|
||||||
";;" + app_type + ";;" + app_version + ";;" + fw_ + ";;" +
|
|
||||||
game_list_util.GetRegion(region) + ";;" + flagss + ";;" + m_pkg_list[i];
|
|
||||||
m_pkg_app_list.append(pkg_info);
|
|
||||||
} else {
|
|
||||||
title_category = "Patch";
|
|
||||||
pkg_info = title_name + ";;" + title_id + ";;" + pkg_size + ";;" + title_category +
|
|
||||||
";;" + app_type + ";;" + app_version + ";;" + fw_ + ";;" +
|
|
||||||
game_list_util.GetRegion(region) + ";;" + flagss + ";;" + m_pkg_list[i];
|
|
||||||
m_pkg_patch_list.append(pkg_info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(m_pkg_app_list.begin(), m_pkg_app_list.end());
|
|
||||||
for (int i = 0; i < m_pkg_app_list.size(); i++) {
|
|
||||||
QTreeWidgetItem* treeItem = new QTreeWidgetItem(treeWidget);
|
|
||||||
QStringList pkg_app_ = m_pkg_app_list[i].split(";;");
|
|
||||||
m_full_pkg_list.append(m_pkg_app_list[i]);
|
|
||||||
treeItem->setExpanded(true);
|
|
||||||
treeItem->setText(0, pkg_app_[0]);
|
|
||||||
treeItem->setText(1, pkg_app_[1]);
|
|
||||||
treeItem->setText(3, pkg_app_[2]);
|
|
||||||
treeItem->setTextAlignment(3, Qt::AlignCenter);
|
|
||||||
treeItem->setText(4, pkg_app_[3]);
|
|
||||||
treeItem->setTextAlignment(4, Qt::AlignCenter);
|
|
||||||
treeItem->setText(5, pkg_app_[4]);
|
|
||||||
treeItem->setTextAlignment(5, Qt::AlignCenter);
|
|
||||||
treeItem->setText(6, pkg_app_[5]);
|
|
||||||
treeItem->setTextAlignment(6, Qt::AlignCenter);
|
|
||||||
treeItem->setText(7, pkg_app_[6]);
|
|
||||||
treeItem->setTextAlignment(7, Qt::AlignCenter);
|
|
||||||
treeItem->setText(8, pkg_app_[7]);
|
|
||||||
treeItem->setTextAlignment(8, Qt::AlignCenter);
|
|
||||||
treeItem->setText(9, pkg_app_[8]);
|
|
||||||
treeItem->setText(10, pkg_app_[9]);
|
|
||||||
for (const GameInfo& info : m_game_info->m_games) { // Check if game is installed.
|
|
||||||
if (info.serial == pkg_app_[1].toStdString()) {
|
|
||||||
treeItem->setText(2, QChar(0x2713));
|
|
||||||
treeItem->setTextAlignment(2, Qt::AlignCenter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const QString& item : m_pkg_patch_list) {
|
|
||||||
QStringList pkg_patch_ = item.split(";;");
|
|
||||||
if (pkg_patch_[1] == pkg_app_[1]) { // check patches with serial.
|
|
||||||
m_full_pkg_list.append(item);
|
|
||||||
QTreeWidgetItem* childItem = new QTreeWidgetItem(treeItem);
|
|
||||||
childItem->setText(0, pkg_patch_[0]);
|
|
||||||
childItem->setText(1, pkg_patch_[1]);
|
|
||||||
childItem->setText(3, pkg_patch_[2]);
|
|
||||||
childItem->setTextAlignment(3, Qt::AlignCenter);
|
|
||||||
childItem->setText(4, pkg_patch_[3]);
|
|
||||||
childItem->setTextAlignment(4, Qt::AlignCenter);
|
|
||||||
childItem->setText(5, pkg_patch_[4]);
|
|
||||||
childItem->setTextAlignment(5, Qt::AlignCenter);
|
|
||||||
childItem->setText(6, pkg_patch_[5]);
|
|
||||||
childItem->setTextAlignment(6, Qt::AlignCenter);
|
|
||||||
childItem->setText(7, pkg_patch_[6]);
|
|
||||||
childItem->setTextAlignment(7, Qt::AlignCenter);
|
|
||||||
childItem->setText(8, pkg_patch_[7]);
|
|
||||||
childItem->setTextAlignment(8, Qt::AlignCenter);
|
|
||||||
childItem->setText(9, pkg_patch_[8]);
|
|
||||||
childItem->setText(10, pkg_patch_[9]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int column = 0; column < treeWidget->columnCount() - 2; ++column) {
|
|
||||||
// Resize the column to fit its contents
|
|
||||||
treeWidget->resizeColumnToContents(column);
|
|
||||||
}
|
|
||||||
// Update status bar.
|
|
||||||
statusBar->clearMessage();
|
|
||||||
int numPkgs = m_pkg_list.size();
|
|
||||||
QString statusMessage = QString::number(numPkgs) + " " + tr("Package");
|
|
||||||
statusBar->showMessage(statusMessage);
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QMenuBar>
|
|
||||||
#include <QStatusBar>
|
|
||||||
|
|
||||||
#include "common/io_file.h"
|
|
||||||
#include "core/file_format/pkg.h"
|
|
||||||
#include "core/file_format/pkg_type.h"
|
|
||||||
#include "core/file_format/psf.h"
|
|
||||||
#include "game_info.h"
|
|
||||||
#include "game_list_utils.h"
|
|
||||||
#include "gui_context_menus.h"
|
|
||||||
|
|
||||||
class PKGViewer : public QMainWindow {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit PKGViewer(
|
|
||||||
std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent,
|
|
||||||
std::function<void(std::filesystem::path, int, int)> InstallDragDropPkg = nullptr);
|
|
||||||
~PKGViewer();
|
|
||||||
void OpenPKGFolder();
|
|
||||||
void CheckPKGFolders();
|
|
||||||
void ProcessPKGInfo();
|
|
||||||
|
|
||||||
private:
|
|
||||||
GuiContextMenus m_gui_context_menus;
|
|
||||||
PKG package;
|
|
||||||
PSF psf;
|
|
||||||
PKGHeader pkgheader;
|
|
||||||
PKGEntry entry;
|
|
||||||
PSFHeader header;
|
|
||||||
char pkgTitleID[9];
|
|
||||||
std::vector<u8> pkg;
|
|
||||||
u64 pkgSize = 0;
|
|
||||||
std::unordered_map<std::string, std::string> map_strings;
|
|
||||||
std::unordered_map<std::string, u32> map_integers;
|
|
||||||
|
|
||||||
u32_be pkg_content_flag;
|
|
||||||
std::shared_ptr<GameInfoClass> m_game_info;
|
|
||||||
GameListUtils game_list_util;
|
|
||||||
// Status bar
|
|
||||||
QStatusBar* statusBar;
|
|
||||||
|
|
||||||
std::vector<std::pair<int, QString>> appTypes = {
|
|
||||||
{0, "FULL APP"},
|
|
||||||
{1, "UPGRADABLE"},
|
|
||||||
{2, "DEMO"},
|
|
||||||
{3, "FREEMIUM"},
|
|
||||||
};
|
|
||||||
|
|
||||||
QStringList m_full_pkg_list;
|
|
||||||
QStringList m_pkg_app_list;
|
|
||||||
QStringList m_pkg_patch_list;
|
|
||||||
QStringList m_pkg_list;
|
|
||||||
QStringList dir_list;
|
|
||||||
std::vector<std::string> dir_list_std;
|
|
||||||
QTreeWidget* treeWidget = nullptr;
|
|
||||||
};
|
|
|
@ -246,12 +246,13 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
|
||||||
// PATH TAB
|
// PATH TAB
|
||||||
{
|
{
|
||||||
connect(ui->addFolderButton, &QPushButton::clicked, this, [this]() {
|
connect(ui->addFolderButton, &QPushButton::clicked, this, [this]() {
|
||||||
const auto config_dir = Config::getGameInstallDirs();
|
|
||||||
QString file_path_string =
|
QString file_path_string =
|
||||||
QFileDialog::getExistingDirectory(this, tr("Directory to install games"));
|
QFileDialog::getExistingDirectory(this, tr("Directory to install games"));
|
||||||
auto file_path = Common::FS::PathFromQString(file_path_string);
|
auto file_path = Common::FS::PathFromQString(file_path_string);
|
||||||
if (!file_path.empty() && Config::addGameInstallDir(file_path)) {
|
if (!file_path.empty() && Config::addGameInstallDir(file_path, true)) {
|
||||||
QListWidgetItem* item = new QListWidgetItem(file_path_string);
|
QListWidgetItem* item = new QListWidgetItem(file_path_string);
|
||||||
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||||
|
item->setCheckState(Qt::Checked);
|
||||||
ui->gameFoldersListWidget->addItem(item);
|
ui->gameFoldersListWidget->addItem(item);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -317,7 +318,6 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
|
||||||
// General
|
// General
|
||||||
ui->consoleLanguageGroupBox->installEventFilter(this);
|
ui->consoleLanguageGroupBox->installEventFilter(this);
|
||||||
ui->emulatorLanguageGroupBox->installEventFilter(this);
|
ui->emulatorLanguageGroupBox->installEventFilter(this);
|
||||||
ui->separateUpdatesCheckBox->installEventFilter(this);
|
|
||||||
ui->showSplashCheckBox->installEventFilter(this);
|
ui->showSplashCheckBox->installEventFilter(this);
|
||||||
ui->discordRPCCheckbox->installEventFilter(this);
|
ui->discordRPCCheckbox->installEventFilter(this);
|
||||||
ui->userName->installEventFilter(this);
|
ui->userName->installEventFilter(this);
|
||||||
|
@ -449,8 +449,6 @@ void SettingsDialog::LoadValuesFromConfig() {
|
||||||
QString translatedText_FullscreenMode =
|
QString translatedText_FullscreenMode =
|
||||||
screenModeMap.key(QString::fromStdString(Config::getFullscreenMode()));
|
screenModeMap.key(QString::fromStdString(Config::getFullscreenMode()));
|
||||||
ui->displayModeComboBox->setCurrentText(translatedText_FullscreenMode);
|
ui->displayModeComboBox->setCurrentText(translatedText_FullscreenMode);
|
||||||
ui->separateUpdatesCheckBox->setChecked(
|
|
||||||
toml::find_or<bool>(data, "General", "separateUpdateEnabled", false));
|
|
||||||
ui->gameSizeCheckBox->setChecked(toml::find_or<bool>(data, "GUI", "loadGameSizeEnabled", true));
|
ui->gameSizeCheckBox->setChecked(toml::find_or<bool>(data, "GUI", "loadGameSizeEnabled", true));
|
||||||
ui->showSplashCheckBox->setChecked(toml::find_or<bool>(data, "General", "showSplash", false));
|
ui->showSplashCheckBox->setChecked(toml::find_or<bool>(data, "General", "showSplash", false));
|
||||||
QString translatedText_logType = logTypeMap.key(QString::fromStdString(Config::getLogType()));
|
QString translatedText_logType = logTypeMap.key(QString::fromStdString(Config::getLogType()));
|
||||||
|
@ -599,8 +597,6 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
|
||||||
text = tr("Console Language:\\nSets the language that the PS4 game uses.\\nIt's recommended to set this to a language the game supports, which will vary by region.");
|
text = tr("Console Language:\\nSets the language that the PS4 game uses.\\nIt's recommended to set this to a language the game supports, which will vary by region.");
|
||||||
} else if (elementName == "emulatorLanguageGroupBox") {
|
} else if (elementName == "emulatorLanguageGroupBox") {
|
||||||
text = tr("Emulator Language:\\nSets the language of the emulator's user interface.");
|
text = tr("Emulator Language:\\nSets the language of the emulator's user interface.");
|
||||||
} else if (elementName == "separateUpdatesCheckBox") {
|
|
||||||
text = tr("Enable Separate Update Folder:\\nEnables installing game updates into a separate folder for easy management.\\nThis can be manually created by adding the extracted update to the game folder with the name \"CUSA00000-UPDATE\" where the CUSA ID matches the game's ID.");
|
|
||||||
} else if (elementName == "showSplashCheckBox") {
|
} else if (elementName == "showSplashCheckBox") {
|
||||||
text = tr("Show Splash Screen:\\nShows the game's splash screen (a special image) while the game is starting.");
|
text = tr("Show Splash Screen:\\nShows the game's splash screen (a special image) while the game is starting.");
|
||||||
} else if (elementName == "discordRPCCheckbox") {
|
} else if (elementName == "discordRPCCheckbox") {
|
||||||
|
@ -759,7 +755,6 @@ void SettingsDialog::UpdateSettings() {
|
||||||
Config::setVblankDiv(ui->vblankSpinBox->value());
|
Config::setVblankDiv(ui->vblankSpinBox->value());
|
||||||
Config::setDumpShaders(ui->dumpShadersCheckBox->isChecked());
|
Config::setDumpShaders(ui->dumpShadersCheckBox->isChecked());
|
||||||
Config::setNullGpu(ui->nullGpuCheckBox->isChecked());
|
Config::setNullGpu(ui->nullGpuCheckBox->isChecked());
|
||||||
Config::setSeparateUpdateEnabled(ui->separateUpdatesCheckBox->isChecked());
|
|
||||||
Config::setLoadGameSizeEnabled(ui->gameSizeCheckBox->isChecked());
|
Config::setLoadGameSizeEnabled(ui->gameSizeCheckBox->isChecked());
|
||||||
Config::setShowSplash(ui->showSplashCheckBox->isChecked());
|
Config::setShowSplash(ui->showSplashCheckBox->isChecked());
|
||||||
Config::setDebugDump(ui->debugDump->isChecked());
|
Config::setDebugDump(ui->debugDump->isChecked());
|
||||||
|
@ -783,6 +778,17 @@ void SettingsDialog::UpdateSettings() {
|
||||||
emit BackgroundOpacityChanged(ui->backgroundImageOpacitySlider->value());
|
emit BackgroundOpacityChanged(ui->backgroundImageOpacitySlider->value());
|
||||||
Config::setShowBackgroundImage(ui->showBackgroundImageCheckBox->isChecked());
|
Config::setShowBackgroundImage(ui->showBackgroundImageCheckBox->isChecked());
|
||||||
|
|
||||||
|
std::vector<Config::GameInstallDir> dirs_with_states;
|
||||||
|
for (int i = 0; i < ui->gameFoldersListWidget->count(); i++) {
|
||||||
|
QListWidgetItem* item = ui->gameFoldersListWidget->item(i);
|
||||||
|
QString path_string = item->text();
|
||||||
|
auto path = Common::FS::PathFromQString(path_string);
|
||||||
|
bool enabled = (item->checkState() == Qt::Checked);
|
||||||
|
|
||||||
|
dirs_with_states.push_back({path, enabled});
|
||||||
|
}
|
||||||
|
Config::setAllGameInstallDirs(dirs_with_states);
|
||||||
|
|
||||||
#ifdef ENABLE_DISCORD_RPC
|
#ifdef ENABLE_DISCORD_RPC
|
||||||
auto* rpc = Common::Singleton<DiscordRPCHandler::RPC>::Instance();
|
auto* rpc = Common::Singleton<DiscordRPCHandler::RPC>::Instance();
|
||||||
if (Config::getEnableDiscordRPC()) {
|
if (Config::getEnableDiscordRPC()) {
|
||||||
|
@ -797,6 +803,7 @@ void SettingsDialog::UpdateSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingsDialog::ResetInstallFolders() {
|
void SettingsDialog::ResetInstallFolders() {
|
||||||
|
ui->gameFoldersListWidget->clear();
|
||||||
|
|
||||||
std::filesystem::path userdir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
std::filesystem::path userdir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
||||||
const toml::value data = toml::parse(userdir / "config.toml");
|
const toml::value data = toml::parse(userdir / "config.toml");
|
||||||
|
@ -804,22 +811,37 @@ void SettingsDialog::ResetInstallFolders() {
|
||||||
if (data.contains("GUI")) {
|
if (data.contains("GUI")) {
|
||||||
const toml::value& gui = data.at("GUI");
|
const toml::value& gui = data.at("GUI");
|
||||||
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::u8string>>(gui, "installDirs", {});
|
||||||
std::vector<std::filesystem::path> settings_install_dirs_config = {};
|
|
||||||
|
|
||||||
for (const auto& dir : install_dir_array) {
|
std::vector<bool> install_dirs_enabled;
|
||||||
if (std::find(settings_install_dirs_config.begin(), settings_install_dirs_config.end(),
|
try {
|
||||||
dir) == settings_install_dirs_config.end()) {
|
install_dirs_enabled = Config::getGameInstallDirsEnabled();
|
||||||
settings_install_dirs_config.push_back(dir);
|
} catch (...) {
|
||||||
}
|
// If it does not exist, assume that all are enabled.
|
||||||
|
install_dirs_enabled.resize(install_dir_array.size(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& dir : settings_install_dirs_config) {
|
if (install_dirs_enabled.size() < install_dir_array.size()) {
|
||||||
|
install_dirs_enabled.resize(install_dir_array.size(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Config::GameInstallDir> settings_install_dirs_config;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < install_dir_array.size(); i++) {
|
||||||
|
std::filesystem::path dir = install_dir_array[i];
|
||||||
|
bool enabled = install_dirs_enabled[i];
|
||||||
|
|
||||||
|
settings_install_dirs_config.push_back({dir, enabled});
|
||||||
|
|
||||||
QString path_string;
|
QString path_string;
|
||||||
Common::FS::PathToQString(path_string, dir);
|
Common::FS::PathToQString(path_string, dir);
|
||||||
|
|
||||||
QListWidgetItem* item = new QListWidgetItem(path_string);
|
QListWidgetItem* item = new QListWidgetItem(path_string);
|
||||||
|
item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
|
||||||
|
item->setCheckState(enabled ? Qt::Checked : Qt::Unchecked);
|
||||||
ui->gameFoldersListWidget->addItem(item);
|
ui->gameFoldersListWidget->addItem(item);
|
||||||
}
|
}
|
||||||
Config::setGameInstallDirs(settings_install_dirs_config);
|
|
||||||
|
Config::setAllGameInstallDirs(settings_install_dirs_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|