mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-28 13:28:03 +03:00
Compare commits
138 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
81fa9b7fff | ||
![]() |
385c5a4507 | ||
![]() |
59d060bc16 | ||
![]() |
83fd0683fa | ||
![]() |
81ad31ce31 | ||
![]() |
ff984d3cde | ||
![]() |
b505829e16 | ||
![]() |
254375ef0c | ||
![]() |
cef795b80b | ||
![]() |
410313ca87 | ||
![]() |
c09fff2da6 | ||
![]() |
e816bc4b99 | ||
![]() |
632ed99ee7 | ||
![]() |
15d6a45dcd | ||
![]() |
d370ea32f4 | ||
![]() |
c01590175a | ||
![]() |
a12d447bd6 | ||
![]() |
ce3aded3e5 | ||
![]() |
4ecdcf77d1 | ||
![]() |
3f4249084c | ||
![]() |
aeee7706ee | ||
![]() |
5db162cbcd | ||
![]() |
354a2e6946 | ||
![]() |
53ca64f6ff | ||
![]() |
ee7fe305c9 | ||
![]() |
b1ebb2fec5 | ||
![]() |
96bee58d0f | ||
![]() |
0297aee3f4 | ||
![]() |
5b0205bc59 | ||
![]() |
cda421434b | ||
![]() |
0c86c54d48 | ||
![]() |
5be726ca3b | ||
![]() |
69777e2ffa | ||
![]() |
111ff2bedd | ||
![]() |
d188510e59 | ||
![]() |
d0dbb737d9 | ||
![]() |
e11ffe242b | ||
![]() |
6e963a7f71 | ||
![]() |
81ada41baa | ||
![]() |
0feb2e7211 | ||
![]() |
23c616c647 | ||
![]() |
20b11f2d63 | ||
![]() |
df89241eb8 | ||
![]() |
703620c7cd | ||
![]() |
b1b7538afd | ||
![]() |
ddc05e8a5f | ||
![]() |
62a4182aca | ||
![]() |
aa8dab5371 | ||
![]() |
ddf3df7f56 | ||
![]() |
243ee04b1c | ||
![]() |
04e4ce0775 | ||
![]() |
52ab1ed04b | ||
![]() |
3bc876ca78 | ||
![]() |
247e935353 | ||
![]() |
4bea00135d | ||
![]() |
683a223c1b | ||
![]() |
2b633fd3c5 | ||
![]() |
cd8e2c4e79 | ||
![]() |
7d32efbd31 | ||
![]() |
b8884d9591 | ||
![]() |
bec1b9056f | ||
![]() |
657073b9e2 | ||
![]() |
fb146f2a20 | ||
![]() |
ec515ad113 | ||
![]() |
d188d14e19 | ||
![]() |
14fad28a9b | ||
![]() |
aec6e330dc | ||
![]() |
6c2574364b | ||
![]() |
8ed82712a0 | ||
![]() |
b0fe1532f7 | ||
![]() |
6ebed7ce69 | ||
![]() |
37d4cd091c | ||
![]() |
5abec2a291 | ||
![]() |
e3b1c041d0 | ||
![]() |
2965656325 | ||
![]() |
03b1fef331 | ||
![]() |
08731303d8 | ||
![]() |
7fee289b66 | ||
![]() |
040fd79ef7 | ||
![]() |
473b66649f | ||
![]() |
b8f6ef1c0b | ||
![]() |
9d2175180e | ||
![]() |
0c6f2b470f | ||
![]() |
54b4d7fc78 | ||
![]() |
1ee2016902 | ||
![]() |
7bb49d85d3 | ||
![]() |
806b2ddc89 | ||
![]() |
afd0251dd2 | ||
![]() |
eb300d0aa7 | ||
![]() |
f6cc245e40 | ||
![]() |
9ee5d066a2 | ||
![]() |
01243fb8e5 | ||
![]() |
a2a1ecde0a | ||
![]() |
a5958bf7f0 | ||
![]() |
7533206d89 | ||
![]() |
b0a12c02e1 | ||
![]() |
374b66ad8e | ||
![]() |
f85d8df71e | ||
![]() |
a707d31a4c | ||
![]() |
f1e0a096d5 | ||
![]() |
3f33d218b3 | ||
![]() |
99b90cbd5c | ||
![]() |
bad82e7204 | ||
![]() |
faae1218fa | ||
![]() |
064c3161c3 | ||
![]() |
8122f8ecbf | ||
![]() |
9dbc79dc96 | ||
![]() |
df9151481c | ||
![]() |
be7d646e83 | ||
![]() |
78c8bca2bb | ||
![]() |
751a23af0f | ||
![]() |
501f46e515 | ||
![]() |
31e1d4f839 | ||
![]() |
be22674f8c | ||
![]() |
d339b3f7d6 | ||
![]() |
602de0c370 | ||
![]() |
c96853816a | ||
![]() |
437af93201 | ||
![]() |
ae2c9a745e | ||
![]() |
5caab76a45 | ||
![]() |
9c37aa039b | ||
![]() |
3abe5b0d57 | ||
![]() |
90b949b8ce | ||
![]() |
69cb4d5787 | ||
![]() |
d8204641fa | ||
![]() |
7d0631cf26 | ||
![]() |
a1ec8b0a88 | ||
![]() |
5c72030fb8 | ||
![]() |
1908d26093 | ||
![]() |
16a68d78eb | ||
![]() |
4f8e5dfd7c | ||
![]() |
10bf3d383c | ||
![]() |
99332e4ec2 | ||
![]() |
6f944ab117 | ||
![]() |
1f9ac53c28 | ||
![]() |
a80c4a7f48 | ||
![]() |
0fa1220eca | ||
![]() |
d7b947dd79 |
271 changed files with 13339 additions and 11743 deletions
21
.github/ISSUE_TEMPLATE/app-bug-report.yaml
vendored
21
.github/ISSUE_TEMPLATE/app-bug-report.yaml
vendored
|
@ -53,3 +53,24 @@ body:
|
|||
placeholder: "Example: Windows 11, Arch Linux, MacOS 15"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: cpu
|
||||
attributes:
|
||||
label: CPU
|
||||
placeholder: "Example: Intel Core i7-8700"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: gpu
|
||||
attributes:
|
||||
label: GPU
|
||||
placeholder: "Example: nVidia GTX 1650"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: ram
|
||||
attributes:
|
||||
label: Amount of RAM in GB
|
||||
placeholder: "Example: 16 GB"
|
||||
validations:
|
||||
required: true
|
||||
|
|
34
.github/workflows/build.yml
vendored
34
.github/workflows/build.yml
vendored
|
@ -30,7 +30,7 @@ jobs:
|
|||
- name: Install
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-19 main'
|
||||
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
|
||||
sudo apt update
|
||||
sudo apt install clang-format-19
|
||||
- name: Build
|
||||
|
@ -205,12 +205,12 @@ jobs:
|
|||
run: |
|
||||
mkdir upload
|
||||
mv ${{github.workspace}}/build/shadps4 upload
|
||||
cp ${{github.workspace}}/build/externals/MoltenVK/libMoltenVK.dylib upload
|
||||
tar cf shadps4-macos-sdl.tar.gz -C upload .
|
||||
mv ${{github.workspace}}/build/MoltenVK_icd.json upload
|
||||
mv ${{github.workspace}}/build/libMoltenVK.dylib upload
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
||||
path: shadps4-macos-sdl.tar.gz
|
||||
path: upload/
|
||||
|
||||
macos-qt:
|
||||
runs-on: macos-15
|
||||
|
@ -281,8 +281,13 @@ jobs:
|
|||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Add LLVM repository
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang-19 mold build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
||||
|
||||
- name: Cache CMake Configuration
|
||||
uses: actions/cache@v4
|
||||
|
@ -304,7 +309,7 @@ jobs:
|
|||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
||||
|
@ -337,8 +342,13 @@ jobs:
|
|||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Add LLVM repository
|
||||
run: |
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo add-apt-repository 'deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main'
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang-19 mold build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
||||
|
||||
- name: Cache CMake Configuration
|
||||
uses: actions/cache@v4
|
||||
|
@ -360,7 +370,7 @@ jobs:
|
|||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-19 -DCMAKE_CXX_COMPILER=clang++-19 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
||||
|
@ -385,7 +395,7 @@ jobs:
|
|||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 mold build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
||||
|
||||
- name: Cache CMake Configuration
|
||||
uses: actions/cache@v4
|
||||
|
@ -407,7 +417,7 @@ jobs:
|
|||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
||||
|
@ -421,7 +431,7 @@ jobs:
|
|||
submodules: recursive
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
||||
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 mold build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
|
||||
|
||||
- name: Cache CMake Configuration
|
||||
uses: actions/cache@v4
|
||||
|
@ -443,7 +453,7 @@ jobs:
|
|||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold" -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
||||
|
|
11
.gitmodules
vendored
11
.gitmodules
vendored
|
@ -1,11 +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/zlib-ng"]
|
||||
path = externals/zlib-ng
|
||||
url = https://github.com/shadps4-emu/ext-zlib-ng.git
|
||||
|
@ -115,3 +107,6 @@
|
|||
path = externals/MoltenVK/cereal
|
||||
url = https://github.com/USCiLab/cereal
|
||||
shallow = true
|
||||
[submodule "externals/libusb"]
|
||||
path = externals/libusb
|
||||
url = https://github.com/libusb/libusb-cmake.git
|
||||
|
|
207
CMakeLists.txt
207
CMakeLists.txt
|
@ -9,7 +9,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
|
|||
|
||||
if(APPLE)
|
||||
list(APPEND ADDITIONAL_LANGUAGES OBJC)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 14)
|
||||
# Starting with 15.4, Rosetta 2 has support for all the necessary instruction sets.
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 15.4 CACHE STRING "")
|
||||
endif()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
|
@ -53,8 +54,9 @@ else()
|
|||
endif()
|
||||
|
||||
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)
|
||||
# Target the same CPU architecture as the PS4, to maintain the same level of compatibility.
|
||||
# Exclude SSE4a as it is only available on AMD CPUs.
|
||||
add_compile_options(-march=btver2 -mtune=generic -mno-sse4a)
|
||||
endif()
|
||||
|
||||
if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
|
@ -103,38 +105,81 @@ if (CLANG_FORMAT)
|
|||
unset(CCOMMENT)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
# generate git revision information
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules/")
|
||||
include(GetGitRevisionDescription)
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules/GetGitRevisionDescription.cmake")
|
||||
get_git_head_revision(GIT_REF_SPEC GIT_REV)
|
||||
git_describe(GIT_DESC --always --long --dirty)
|
||||
git_branch_name(GIT_BRANCH)
|
||||
string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S")
|
||||
|
||||
message("start git things")
|
||||
|
||||
# Try to get the upstream remote and branch
|
||||
message("check for remote and branch")
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref --symbolic-full-name @{u}
|
||||
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
||||
RESULT_VARIABLE GIT_BRANCH_RESULT
|
||||
RESULT_VARIABLE GIT_REMOTE_RESULT
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# 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(
|
||||
COMMAND git config --get remote.pushDefault
|
||||
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
||||
RESULT_VARIABLE GIT_PUSH_DEFAULT_RESULT
|
||||
RESULT_VARIABLE GIT_REMOTE_RESULT
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# If remote.pushDefault is not set or fails, default to origin
|
||||
if (GIT_PUSH_DEFAULT_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
set(GIT_REMOTE_NAME "origin")
|
||||
endif()
|
||||
|
||||
# If running in GitHub Actions and the above fails
|
||||
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()
|
||||
else()
|
||||
# Extract remote name if the output contains a remote/branch format
|
||||
|
@ -148,14 +193,27 @@ else()
|
|||
endif()
|
||||
|
||||
# Get remote link
|
||||
message("getting remote link")
|
||||
execute_process(
|
||||
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
|
||||
OUTPUT_VARIABLE GIT_REMOTE_URL
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
# Set Version
|
||||
set(EMULATOR_VERSION_MAJOR "0")
|
||||
set(EMULATOR_VERSION_MINOR "8")
|
||||
set(EMULATOR_VERSION_PATCH "1")
|
||||
|
||||
set_source_files_properties(src/shadps4.rc PROPERTIES COMPILE_DEFINITIONS "EMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR};EMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR};EMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH}")
|
||||
|
||||
set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH} WIP")
|
||||
set(APP_IS_RELEASE false)
|
||||
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}")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
find_package(Boost 1.84.0 CONFIG)
|
||||
find_package(FFmpeg 5.1.2 MODULE)
|
||||
find_package(fmt 10.2.0 CONFIG)
|
||||
|
@ -168,21 +226,18 @@ find_package(SDL3 3.1.2 CONFIG)
|
|||
find_package(stb MODULE)
|
||||
find_package(toml11 4.2.0 CONFIG)
|
||||
find_package(tsl-robin-map 1.3.0 CONFIG)
|
||||
find_package(VulkanHeaders 1.4.305 CONFIG)
|
||||
find_package(VulkanHeaders 1.4.309 CONFIG)
|
||||
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
||||
find_package(xbyak 7.07 CONFIG)
|
||||
find_package(xxHash 0.8.2 MODULE)
|
||||
find_package(ZLIB 1.3 MODULE)
|
||||
find_package(Zydis 5.0.0 CONFIG)
|
||||
find_package(pugixml 1.14 CONFIG)
|
||||
|
||||
if (NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR NOT MSVC)
|
||||
find_package(cryptopp 8.9.0 MODULE)
|
||||
endif()
|
||||
|
||||
find_package(libusb 1.0.27 MODULE)
|
||||
if (APPLE)
|
||||
find_package(date 3.0.1 CONFIG)
|
||||
endif()
|
||||
list(POP_BACK CMAKE_MODULE_PATH)
|
||||
|
||||
# Note: Windows always has these functions through winpthreads
|
||||
include(CheckSymbolExists)
|
||||
|
@ -285,6 +340,8 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
|
|||
src/core/libraries/kernel/threads/thread_state.h
|
||||
src/core/libraries/kernel/process.cpp
|
||||
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.h
|
||||
src/core/libraries/kernel/file_system.cpp
|
||||
|
@ -378,12 +435,28 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
|||
src/core/libraries/ngs2/ngs2_error.h
|
||||
src/core/libraries/ngs2/ngs2_impl.cpp
|
||||
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/audio3d/audio3d.cpp
|
||||
src/core/libraries/audio3d/audio3d.h
|
||||
src/core/libraries/audio3d/audio3d_error.h
|
||||
src/core/libraries/audio3d/audio3d_impl.cpp
|
||||
src/core/libraries/audio3d/audio3d_impl.h
|
||||
src/core/libraries/game_live_streaming/gamelivestreaming.cpp
|
||||
src/core/libraries/game_live_streaming/gamelivestreaming.h
|
||||
src/core/libraries/remote_play/remoteplay.cpp
|
||||
|
@ -497,6 +570,8 @@ set(NP_LIBS src/core/libraries/np_common/np_common.cpp
|
|||
src/core/libraries/np_web_api/np_web_api.h
|
||||
src/core/libraries/np_party/np_party.cpp
|
||||
src/core/libraries/np_party/np_party.h
|
||||
src/core/libraries/np_auth/np_auth.cpp
|
||||
src/core/libraries/np_auth/np_auth.h
|
||||
)
|
||||
|
||||
set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
||||
|
@ -512,6 +587,8 @@ set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
|
|||
src/core/libraries/screenshot/screenshot.h
|
||||
src/core/libraries/move/move.cpp
|
||||
src/core/libraries/move/move.h
|
||||
src/core/libraries/ulobjmgr/ulobjmgr.cpp
|
||||
src/core/libraries/ulobjmgr/ulobjmgr.h
|
||||
)
|
||||
|
||||
set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||
|
@ -551,6 +628,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||
src/common/logging/text_formatter.cpp
|
||||
src/common/logging/text_formatter.h
|
||||
src/common/logging/types.h
|
||||
src/common/aes.h
|
||||
src/common/alignment.h
|
||||
src/common/arch.h
|
||||
src/common/assert.cpp
|
||||
|
@ -582,6 +660,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||
src/common/polyfill_thread.h
|
||||
src/common/rdtsc.cpp
|
||||
src/common/rdtsc.h
|
||||
src/common/sha1.h
|
||||
src/common/signal_context.h
|
||||
src/common/signal_context.cpp
|
||||
src/common/singleton.h
|
||||
|
@ -600,7 +679,6 @@ set(COMMON src/common/logging/backend.cpp
|
|||
src/common/uint128.h
|
||||
src/common/unique_function.h
|
||||
src/common/va_ctx.h
|
||||
src/common/version.h
|
||||
src/common/ntapi.h
|
||||
src/common/ntapi.cpp
|
||||
src/common/number_utils.h
|
||||
|
@ -621,9 +699,6 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||
src/core/aerolib/aerolib.h
|
||||
src/core/address_space.cpp
|
||||
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.h
|
||||
src/core/devices/ioccom.h
|
||||
|
@ -641,10 +716,6 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||
src/core/devices/srandom_device.cpp
|
||||
src/core/devices/srandom_device.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.h
|
||||
src/core/file_format/playgo_chunk.cpp
|
||||
|
@ -653,8 +724,6 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||
src/core/file_format/trp.h
|
||||
src/core/file_sys/fs.cpp
|
||||
src/core/file_sys/fs.h
|
||||
src/core/loader.cpp
|
||||
src/core/loader.h
|
||||
src/core/loader/dwarf.cpp
|
||||
src/core/loader/dwarf.h
|
||||
src/core/loader/elf.cpp
|
||||
|
@ -771,6 +840,8 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||
src/shader_recompiler/ir/passes/identity_removal_pass.cpp
|
||||
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_fp64_to_fp32.cpp
|
||||
src/shader_recompiler/ir/passes/readlane_elimination_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/shader_info_collection_pass.cpp
|
||||
|
@ -943,10 +1014,6 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
|
|||
src/qt_gui/game_grid_frame.h
|
||||
src/qt_gui/game_install_dialog.cpp
|
||||
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.h
|
||||
src/qt_gui/elf_viewer.cpp
|
||||
|
@ -1002,7 +1069,7 @@ endif()
|
|||
create_target_directory_groups(shadps4)
|
||||
|
||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers cryptopp::cryptopp)
|
||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers libusb::usb)
|
||||
|
||||
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
||||
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
||||
|
@ -1017,34 +1084,43 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ENABLE_USERFAULTFD)
|
|||
endif()
|
||||
|
||||
if (APPLE)
|
||||
if (ENABLE_QT_GUI)
|
||||
# Include MoltenVK in the app bundle, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
|
||||
set(MVK_ICD ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK_icd.json)
|
||||
target_sources(shadps4 PRIVATE ${MVK_ICD})
|
||||
set_source_files_properties(${MVK_ICD} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/vulkan/icd.d)
|
||||
# Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
|
||||
if (ENABLE_QT_GUI)
|
||||
set(MVK_BUNDLE_PATH "Resources/vulkan/icd.d")
|
||||
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../${MVK_BUNDLE_PATH}")
|
||||
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/${MVK_BUNDLE_PATH})
|
||||
else()
|
||||
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path")
|
||||
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib)
|
||||
set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib)
|
||||
add_custom_command(
|
||||
OUTPUT ${MVK_DYLIB_DST}
|
||||
DEPENDS ${MVK_DYLIB_SRC}
|
||||
COMMAND cmake -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST})
|
||||
add_custom_target(CopyMoltenVK DEPENDS ${MVK_DYLIB_DST})
|
||||
add_dependencies(CopyMoltenVK MoltenVK)
|
||||
add_dependencies(shadps4 CopyMoltenVK)
|
||||
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks")
|
||||
else()
|
||||
# For non-bundled SDL build, just do a normal library link.
|
||||
target_link_libraries(shadps4 PRIVATE MoltenVK)
|
||||
endif()
|
||||
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib)
|
||||
set(MVK_DYLIB_DST ${MVK_DST}/libMoltenVK.dylib)
|
||||
set(MVK_ICD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK/MoltenVK/icd/MoltenVK_icd.json)
|
||||
set(MVK_ICD_DST ${MVK_DST}/MoltenVK_icd.json)
|
||||
|
||||
if (ARCHITECTURE STREQUAL "x86_64")
|
||||
# Reserve system-managed memory space.
|
||||
target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,SYSTEM_MANAGED,0x400000,-segaddr,SYSTEM_RESERVED,0x7FFFFC000,-image_base,0x20000000000)
|
||||
endif()
|
||||
add_custom_command(
|
||||
OUTPUT ${MVK_DST}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DST})
|
||||
add_custom_command(
|
||||
OUTPUT ${MVK_ICD_DST}
|
||||
DEPENDS ${MVK_ICD_SRC} ${MVK_DST}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${MVK_ICD_SRC} ${MVK_ICD_DST})
|
||||
add_custom_command(
|
||||
OUTPUT ${MVK_DYLIB_DST}
|
||||
DEPENDS ${MVK_DYLIB_SRC} ${MVK_DST}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST})
|
||||
add_custom_target(CopyMoltenVK DEPENDS ${MVK_ICD_DST} ${MVK_DYLIB_DST})
|
||||
add_dependencies(CopyMoltenVK MoltenVK)
|
||||
add_dependencies(shadps4 CopyMoltenVK)
|
||||
|
||||
# Replacement for std::chrono::time_zone
|
||||
target_link_libraries(shadps4 PRIVATE date::date-tz)
|
||||
if (ARCHITECTURE STREQUAL "x86_64")
|
||||
# Reserve system-managed memory space.
|
||||
target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,SYSTEM_MANAGED,0x400000,-segaddr,SYSTEM_RESERVED,0x7FFFFC000,-image_base,0x20000000000)
|
||||
endif()
|
||||
|
||||
# Replacement for std::chrono::time_zone
|
||||
target_link_libraries(shadps4 PRIVATE date::date-tz)
|
||||
endif()
|
||||
|
||||
if (NOT ENABLE_QT_GUI)
|
||||
|
@ -1113,7 +1189,7 @@ target_include_directories(shadps4 PRIVATE ${HOST_SHADERS_INCLUDE})
|
|||
|
||||
# embed resources
|
||||
|
||||
include(CMakeRC)
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeRC.cmake")
|
||||
cmrc_add_resource_library(embedded-resources
|
||||
ALIAS res::embedded
|
||||
NAMESPACE res
|
||||
|
@ -1121,7 +1197,6 @@ cmrc_add_resource_library(embedded-resources
|
|||
src/images/gold.png
|
||||
src/images/platinum.png
|
||||
src/images/silver.png)
|
||||
|
||||
target_link_libraries(shadps4 PRIVATE res::embedded)
|
||||
|
||||
# ImGui resources
|
||||
|
@ -1135,8 +1210,8 @@ if (ENABLE_QT_GUI)
|
|||
MACOSX_BUNDLE ON
|
||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/dist/MacOSBundleInfo.plist.in"
|
||||
MACOSX_BUNDLE_ICON_FILE "shadPS4.icns"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "0.4.1"
|
||||
)
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${APP_VERSION}"
|
||||
)
|
||||
|
||||
set_source_files_properties(src/images/shadPS4.icns PROPERTIES
|
||||
MACOSX_PACKAGE_LOCATION Resources)
|
||||
|
|
36
README.md
36
README.md
|
@ -13,7 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
|
||||
<h1 align="center">
|
||||
<a href="https://discord.gg/bFJxfftGW6">
|
||||
<img src="https://img.shields.io/discord/1080089157554155590?color=5865F2&label=shadPS4 Discord&logo=Discord&logoColor=white" width="240">
|
||||
<img src="https://img.shields.io/discord/1080089157554155590?color=5865F2&label=shadPS4%20Discord&logo=Discord&logoColor=white" width="275">
|
||||
<a href="https://github.com/shadps4-emu/shadPS4/releases/latest">
|
||||
<img src="https://img.shields.io/github/downloads/shadps4-emu/shadPS4/total.svg" width="140">
|
||||
<a href="https://shadps4.net/">
|
||||
|
@ -71,7 +71,7 @@ Check the build instructions for [**Linux**](https://github.com/shadps4-emu/shad
|
|||
Check the build instructions for [**macOS**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-macos.md).
|
||||
|
||||
> [!IMPORTANT]
|
||||
> macOS users need at least macOS 15 on Apple Silicon-based Mac devices and at least macOS 14 on Intel-based Mac devices.
|
||||
> macOS users need at least macOS 15.4 to run shadPS4. Due to GPU issues there are currently heavy bugs on Intel Macs.
|
||||
|
||||
# Debugging and reporting issues
|
||||
|
||||
|
@ -122,19 +122,37 @@ R3 | M |
|
|||
Keyboard and mouse inputs can be customized in the settings menu by clicking the Controller button, and further details and help on controls are also found there. Custom bindings are saved per-game. Inputs support up to three keys per binding, mouse buttons, mouse movement mapped to joystick input, and more.
|
||||
|
||||
|
||||
# Firmware files
|
||||
|
||||
shadPS4 can load some PlayStation 4 firmware files, these must be dumped from your legally owned PlayStation 4 console.\
|
||||
The following firmware modules are supported and must be placed in shadPS4's `user/sys_modules` folder.
|
||||
|
||||
<div align="center">
|
||||
|
||||
| Modules | Modules | Modules | Modules |
|
||||
|-------------------------|-------------------------|-------------------------|-------------------------|
|
||||
| libSceCesCs.sprx | libSceFont.sprx | libSceFontFt.sprx | libSceFreeTypeOt.sprx |
|
||||
| libSceJson.sprx | libSceJson2.sprx | libSceLibcInternal.sprx | libSceNgs2.sprx |
|
||||
| libSceRtc.sprx | libSceUlt.sprx | | |
|
||||
|
||||
</div>
|
||||
|
||||
> [!Caution]
|
||||
> The above modules are required to run the games properly and must be extracted from your PlayStation 4.\
|
||||
> **We do not provide any information or support on how to do this**.
|
||||
|
||||
|
||||
|
||||
# Main team
|
||||
|
||||
- [**georgemoralis**](https://github.com/georgemoralis)
|
||||
- [**raphaelthegreat**](https://github.com/raphaelthegreat)
|
||||
- [**psucien**](https://github.com/psucien)
|
||||
- [**skmp**](https://github.com/skmp)
|
||||
- [**wheremyfoodat**](https://github.com/wheremyfoodat)
|
||||
- [**raziel1000**](https://github.com/raziel1000)
|
||||
- [**viniciuslrangel**](https://github.com/viniciuslrangel)
|
||||
- [**roamic**](https://github.com/vladmikhalin)
|
||||
- [**poly**](https://github.com/polybiusproxy)
|
||||
- [**squidbus**](https://github.com/squidbus)
|
||||
- [**frodo**](https://github.com/baggins183)
|
||||
- [**Stephen Miller**](https://github.com/StevenMiller123)
|
||||
- [**kalaposfos13**](https://github.com/kalaposfos13)
|
||||
|
||||
Logo is done by [**Xphalnos**](https://github.com/Xphalnos)
|
||||
|
||||
|
@ -145,11 +163,11 @@ Open a PR and we'll check it :)
|
|||
|
||||
# Translations
|
||||
|
||||
If you want to translate shadPS4 to your language we use [**crowdin**](https://crowdin.com/project/shadps4-emulator).
|
||||
If you want to translate shadPS4 to your language we use [**Crowdin**](https://crowdin.com/project/shadps4-emulator).
|
||||
# Contributors
|
||||
|
||||
<a href="https://github.com/shadps4-emu/shadPS4/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=shadps4-emu/shadPS4&max=15">
|
||||
<img src="https://contrib.rocks/image?repo=shadps4-emu/shadPS4&max=24">
|
||||
</a>
|
||||
|
||||
|
||||
|
|
12
REUSE.toml
12
REUSE.toml
|
@ -30,6 +30,7 @@ path = [
|
|||
"src/images/dump_icon.png",
|
||||
"src/images/exit_icon.png",
|
||||
"src/images/file_icon.png",
|
||||
"src/images/trophy_icon.png",
|
||||
"src/images/flag_china.png",
|
||||
"src/images/flag_eu.png",
|
||||
"src/images/flag_jp.png",
|
||||
|
@ -48,17 +49,26 @@ path = [
|
|||
"src/images/pause_icon.png",
|
||||
"src/images/play_icon.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/fullscreen_icon.png",
|
||||
"src/images/stop_icon.png",
|
||||
"src/images/utils_icon.png",
|
||||
"src/images/shadPS4.icns",
|
||||
"src/images/shadps4.ico",
|
||||
"src/images/shadps4.png",
|
||||
"src/images/net.shadps4.shadPS4.svg",
|
||||
"src/images/themes_icon.png",
|
||||
"src/images/update_icon.png",
|
||||
"src/images/youtube.png",
|
||||
"src/images/website.png",
|
||||
"src/images/discord.svg",
|
||||
"src/images/github.svg",
|
||||
"src/images/ko-fi.svg",
|
||||
"src/images/shadps4.svg",
|
||||
"src/images/website.svg",
|
||||
"src/images/youtube.svg",
|
||||
"src/shadps4.qrc",
|
||||
"src/shadps4.rc",
|
||||
"src/qt_gui/translations/update_translation.sh",
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(CRYPTOPP QUIET IMPORTED_TARGET libcryptopp)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(cryptopp
|
||||
REQUIRED_VARS CRYPTOPP_LINK_LIBRARIES
|
||||
VERSION_VAR CRYPTOPP_VERSION
|
||||
)
|
||||
|
||||
if (cryptopp_FOUND AND NOT TARGET cryptopp::cryptopp)
|
||||
add_library(cryptopp::cryptopp ALIAS PkgConfig::CRYPTOPP)
|
||||
endif()
|
15
cmake/Findlibusb.cmake
Normal file
15
cmake/Findlibusb.cmake
Normal file
|
@ -0,0 +1,15 @@
|
|||
# SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(LIBUSB QUIET IMPORTED_TARGET libusb-1.0)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(libusb
|
||||
REQUIRED_VARS LIBUSB_LINK_LIBRARIES
|
||||
VERSION_VAR LIBUSB_VERSION
|
||||
)
|
||||
|
||||
if (libusb_FOUND AND NOT TARGET libusb::usb)
|
||||
add_library(libusb::usb ALIAS PkgConfig::LIBUSB)
|
||||
endif()
|
3
dist/net.shadps4.shadPS4.metainfo.xml
vendored
3
dist/net.shadps4.shadPS4.metainfo.xml
vendored
|
@ -37,6 +37,9 @@
|
|||
<category translate="no">Game</category>
|
||||
</categories>
|
||||
<releases>
|
||||
<release version="0.8.0" date="2025-05-23">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.8.0</url>
|
||||
</release>
|
||||
<release version="0.7.0" date="2025-03-23">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.7.0</url>
|
||||
</release>
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 658 KiB |
|
@ -13,7 +13,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
- [**RAM**](#ram)
|
||||
- [**OS**](#os)
|
||||
- [**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)
|
||||
|
||||
## Minimum PC requirements
|
||||
|
@ -25,13 +24,13 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||
- A CPU supporting the following instruction sets: MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, F16C, CLMUL, AES, BMI1, MOVBE, XSAVE, ABM
|
||||
- **Intel**: Haswell generation or newer
|
||||
- **AMD**: Jaguar generation or newer
|
||||
- **Apple**: Rosetta 2 on macOS 15 or newer
|
||||
- **Apple**: Rosetta 2 on macOS 15.4 or newer
|
||||
|
||||
### GPU
|
||||
|
||||
- A graphics card with at least 1GB of VRAM
|
||||
- Keep your graphics drivers up to date
|
||||
- Vulkan 1.3 support (required)
|
||||
- Up-to-date graphics drivers
|
||||
- Vulkan 1.3 with the `VK_KHR_swapchain` and `VK_KHR_push_descriptor` extensions
|
||||
|
||||
### RAM
|
||||
|
||||
|
@ -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.
|
||||
|
||||
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.
|
||||
|
||||
## 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">
|
||||
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.
|
||||
|
||||
## Configure the emulator
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ Now run the emulator. If Qt was enabled at configure time:
|
|||
./build/shadps4
|
||||
```
|
||||
|
||||
Otherwise, specify the path to your PKG's boot file:
|
||||
Otherwise, specify the path to your game's boot file:
|
||||
|
||||
```bash
|
||||
./build/shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin
|
||||
|
|
22
externals/CMakeLists.txt
vendored
22
externals/CMakeLists.txt
vendored
|
@ -26,21 +26,7 @@ if (NOT TARGET fmt::fmt)
|
|||
add_subdirectory(fmt)
|
||||
endif()
|
||||
|
||||
# CryptoPP
|
||||
if (NOT TARGET cryptopp::cryptopp)
|
||||
set(CRYPTOPP_INSTALL OFF)
|
||||
set(CRYPTOPP_BUILD_TESTING OFF)
|
||||
set(CRYPTOPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cryptopp)
|
||||
# cryptopp instruction set checks do not account for added compile options,
|
||||
# so disable extensions in the library config to match our chosen target CPU.
|
||||
set(CRYPTOPP_DISABLE_AESNI ON)
|
||||
set(CRYPTOPP_DISABLE_AVX2 ON)
|
||||
add_subdirectory(cryptopp-cmake)
|
||||
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()
|
||||
|
||||
# FFmpeg
|
||||
if (NOT TARGET FFmpeg::ffmpeg)
|
||||
add_subdirectory(ffmpeg-core)
|
||||
add_library(FFmpeg::ffmpeg ALIAS ffmpeg)
|
||||
|
@ -215,6 +201,12 @@ if (NOT TARGET pugixml::pugixml)
|
|||
add_subdirectory(pugixml)
|
||||
endif()
|
||||
|
||||
# libusb
|
||||
if (NOT TARGET libusb::usb)
|
||||
add_subdirectory(libusb)
|
||||
add_library(libusb::usb ALIAS usb-1.0)
|
||||
endif()
|
||||
|
||||
# Discord RPC
|
||||
if (ENABLE_DISCORD_RPC)
|
||||
add_subdirectory(discord-rpc)
|
||||
|
|
2
externals/MoltenVK/MoltenVK
vendored
2
externals/MoltenVK/MoltenVK
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 2048427e50f9eb20f2b8f98d316ecaee398c9b91
|
||||
Subproject commit 87a8e8b13d4ad8835367fea1ebad1896d0460946
|
8
externals/MoltenVK/MoltenVK_icd.json
vendored
8
externals/MoltenVK/MoltenVK_icd.json
vendored
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"file_format_version": "1.0.0",
|
||||
"ICD": {
|
||||
"library_path": "../../../Frameworks/libMoltenVK.dylib",
|
||||
"api_version": "1.2.0",
|
||||
"is_portability_driver": true
|
||||
}
|
||||
}
|
2
externals/MoltenVK/SPIRV-Cross
vendored
2
externals/MoltenVK/SPIRV-Cross
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 2c32b6bf86f3c4a5539aa1f0bacbd59fe61759cf
|
||||
Subproject commit 7918775748c5e2f5c40d9918ce68825035b5a1e1
|
2
externals/MoltenVK/cereal
vendored
2
externals/MoltenVK/cereal
vendored
|
@ -1 +1 @@
|
|||
Subproject commit d1fcec807b372f04e4c1041b3058e11c12853e6e
|
||||
Subproject commit a56bad8bbb770ee266e930c95d37fff2a5be7fea
|
1
externals/cryptopp
vendored
1
externals/cryptopp
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit effed0d0b865afc23ed67e0916f83734e4b9b3b7
|
1
externals/cryptopp-cmake
vendored
1
externals/cryptopp-cmake
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 2c384c28265a93358a2455e610e76393358794df
|
2
externals/date
vendored
2
externals/date
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 28b7b232521ace2c8ef3f2ad4126daec3569c14f
|
||||
Subproject commit a45ea7c17b4a7f320e199b71436074bd624c9e15
|
2
externals/dear_imgui
vendored
2
externals/dear_imgui
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 636cd4a7d623a2bc9bf59bb3acbb4ca075befba3
|
||||
Subproject commit f4d9359095eff3eb03f685921edc1cf0e37b1687
|
2
externals/discord-rpc
vendored
2
externals/discord-rpc
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 51b09d426a4a1bcfa6ee6d4894e57d669f4a2e65
|
||||
Subproject commit 19f66e6dcabb2268965f453db9e5774ede43238f
|
2
externals/ffmpeg-core
vendored
2
externals/ffmpeg-core
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 27de97c826b6b40c255891c37ac046a25836a575
|
||||
Subproject commit b0de1dcca26c0ebfb8011b8e59dd17fc399db0ff
|
2
externals/fmt
vendored
2
externals/fmt
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 8ee89546ffcf046309d1f0d38c0393f02fde56c8
|
||||
Subproject commit 64db979e38ec644b1798e41610b28c8d2c8a2739
|
2
externals/glslang
vendored
2
externals/glslang
vendored
|
@ -1 +1 @@
|
|||
Subproject commit a0995c49ebcaca2c6d3b03efbabf74f3843decdb
|
||||
Subproject commit ba1640446f3826a518721d1f083f3a8cca1120c3
|
1
externals/libusb
vendored
Submodule
1
externals/libusb
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit a63a7e43e0950a595cf4b98a0eaf4051749ace5f
|
2
externals/magic_enum
vendored
2
externals/magic_enum
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 1a1824df7ac798177a521eed952720681b0bf482
|
||||
Subproject commit a413fcc9c46a020a746907136a384c227f3cd095
|
2
externals/pugixml
vendored
2
externals/pugixml
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 4bc14418d12d289dd9978fdce9490a45deeb653e
|
||||
Subproject commit caade5a28aad86b92a4b5337a9dc70c4ba73c5eb
|
2
externals/robin-map
vendored
2
externals/robin-map
vendored
|
@ -1 +1 @@
|
|||
Subproject commit fe845fd7852ef541c5479ae23b3d36b57f8608ee
|
||||
Subproject commit 4ec1bf19c6a96125ea22062f38c2cf5b958e448e
|
2
externals/sdl3
vendored
2
externals/sdl3
vendored
|
@ -1 +1 @@
|
|||
Subproject commit a336b62d8b0b97b09214e053203e442e2b6e2be5
|
||||
Subproject commit 4093e4a193971ef1d4928158e0a1832be42e4599
|
2
externals/sirit
vendored
2
externals/sirit
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 8b9b12c2089505ac8b10fa56bf56b3ed49d9d7b0
|
||||
Subproject commit 427a42c9ed99b38204d9107bc3dc14e92458acf1
|
2
externals/toml11
vendored
2
externals/toml11
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 7f6c574ff5aa1053534e7e19c0a4f22bf4c6aaca
|
||||
Subproject commit a01fe3b4c14c6d7b99ee3f07c9e80058c6403097
|
2
externals/vma
vendored
2
externals/vma
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 5a53a198945ba8260fbc58fadb788745ce6aa263
|
||||
Subproject commit f378e7b3f18f6e2b06b957f6ba7b1c7207d2a536
|
2
externals/vulkan-headers
vendored
2
externals/vulkan-headers
vendored
|
@ -1 +1 @@
|
|||
Subproject commit a03d2f6d5753b365d704d58161825890baad0755
|
||||
Subproject commit 5ceb9ed481e58e705d0d9b5326537daedd06b97d
|
2
externals/winpthreads
vendored
2
externals/winpthreads
vendored
|
@ -1 +1 @@
|
|||
Subproject commit f00c973a6ab2a23573708568b8ef4acc20a9d36b
|
||||
Subproject commit f35b0948d36a736e6a2d052ae295a3ffde09703f
|
2
externals/xbyak
vendored
2
externals/xbyak
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 4e44f4614ddbf038f2a6296f5b906d5c72691e0f
|
||||
Subproject commit 44a72f369268f7d552650891b296693e91db86bb
|
2
externals/xxhash
vendored
2
externals/xxhash
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 2bf8313b934633b2a5b7e8fd239645b85e10c852
|
||||
Subproject commit 953a09abc39096da9e216b6eb0002c681cdc1199
|
2
externals/zlib-ng
vendored
2
externals/zlib-ng
vendored
|
@ -1 +1 @@
|
|||
Subproject commit d54e3769be0c522015b784eca2af258b1c026107
|
||||
Subproject commit fd0d263cedab1a136f40d65199987e3eaeecfcbd
|
2
externals/zydis
vendored
2
externals/zydis
vendored
|
@ -1 +1 @@
|
|||
Subproject commit bffbb610cfea643b98e87658b9058382f7522807
|
||||
Subproject commit 120e0e705f8e3b507dc49377ac2879979f0d545c
|
1195
src/common/aes.h
Normal file
1195
src/common/aes.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -7,10 +7,10 @@
|
|||
#include <fmt/xchar.h> // for wstring support
|
||||
#include <toml.hpp>
|
||||
|
||||
#include "common/config.h"
|
||||
#include "common/logging/formatter.h"
|
||||
#include "common/path_util.h"
|
||||
#include "config.h"
|
||||
#include "logging/formatter.h"
|
||||
#include "version.h"
|
||||
#include "common/scm_rev.h"
|
||||
|
||||
namespace toml {
|
||||
template <typename TC, typename K>
|
||||
|
@ -32,6 +32,7 @@ std::filesystem::path find_fs_path_or(const basic_value<TC>& v, const K& ky,
|
|||
namespace Config {
|
||||
|
||||
static bool isNeo = false;
|
||||
static bool isDevKit = false;
|
||||
static bool playBGM = false;
|
||||
static bool isTrophyPopupDisabled = false;
|
||||
static int BGMvolume = 50;
|
||||
|
@ -40,7 +41,7 @@ static u32 screenWidth = 1280;
|
|||
static u32 screenHeight = 720;
|
||||
static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto select
|
||||
static std::string logFilter;
|
||||
static std::string logType = "async";
|
||||
static std::string logType = "sync";
|
||||
static std::string userName = "shadPS4";
|
||||
static std::string updateChannel;
|
||||
static std::string chooseHomeTab;
|
||||
|
@ -74,14 +75,14 @@ static double trophyNotificationDuration = 6.0;
|
|||
static bool useUnifiedInputConfig = true;
|
||||
static bool overrideControllerColor = false;
|
||||
static int controllerCustomColorRGB[3] = {0, 0, 255};
|
||||
static bool separateupdatefolder = false;
|
||||
static bool compatibilityData = false;
|
||||
static bool checkCompatibilityOnStartup = false;
|
||||
static std::string trophyKey;
|
||||
|
||||
// Gui
|
||||
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 save_data_path = {};
|
||||
u32 main_window_geometry_x = 400;
|
||||
|
@ -96,7 +97,6 @@ u32 m_slider_pos_grid = 0;
|
|||
u32 m_table_mode = 0;
|
||||
u32 m_window_size_W = 1280;
|
||||
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_recent_files;
|
||||
std::string emulator_language = "en_US";
|
||||
|
@ -105,6 +105,7 @@ static bool showBackgroundImage = true;
|
|||
static bool isFullscreen = false;
|
||||
static std::string fullscreenMode = "Windowed";
|
||||
static bool isHDRAllowed = false;
|
||||
static bool showLabelsUnderIcons = true;
|
||||
|
||||
// Language
|
||||
u32 m_language = 1; // english
|
||||
|
@ -166,10 +167,22 @@ bool isNeoModeConsole() {
|
|||
return isNeo;
|
||||
}
|
||||
|
||||
bool isDevKitConsole() {
|
||||
return isDevKit;
|
||||
}
|
||||
|
||||
bool getIsFullscreen() {
|
||||
return isFullscreen;
|
||||
}
|
||||
|
||||
bool getShowLabelsUnderIcons() {
|
||||
return showLabelsUnderIcons;
|
||||
}
|
||||
|
||||
bool setShowLabelsUnderIcons() {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string getFullscreenMode() {
|
||||
return fullscreenMode;
|
||||
}
|
||||
|
@ -338,10 +351,6 @@ void setVkGuestMarkersEnabled(bool enable) {
|
|||
vkGuestMarkers = enable;
|
||||
}
|
||||
|
||||
bool getSeparateUpdateEnabled() {
|
||||
return separateupdatefolder;
|
||||
}
|
||||
|
||||
bool getCompatibilityEnabled() {
|
||||
return compatibilityData;
|
||||
}
|
||||
|
@ -421,6 +430,9 @@ void setVblankDiv(u32 value) {
|
|||
void setIsFullscreen(bool enable) {
|
||||
isFullscreen = enable;
|
||||
}
|
||||
static void setShowLabelsUnderIcons(bool enable) {
|
||||
showLabelsUnderIcons = enable;
|
||||
}
|
||||
|
||||
void setFullscreenMode(std::string mode) {
|
||||
fullscreenMode = mode;
|
||||
|
@ -500,10 +512,6 @@ void setIsMotionControlsEnabled(bool use) {
|
|||
isMotionControlsEnabled = use;
|
||||
}
|
||||
|
||||
void setSeparateUpdateEnabled(bool use) {
|
||||
separateupdatefolder = use;
|
||||
}
|
||||
|
||||
void setCompatibilityEnabled(bool use) {
|
||||
compatibilityData = use;
|
||||
}
|
||||
|
@ -519,22 +527,34 @@ void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) {
|
|||
main_window_geometry_h = h;
|
||||
}
|
||||
|
||||
bool addGameInstallDir(const std::filesystem::path& dir) {
|
||||
if (std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir) ==
|
||||
settings_install_dirs.end()) {
|
||||
settings_install_dirs.push_back(dir);
|
||||
return true;
|
||||
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled) {
|
||||
for (const auto& install_dir : settings_install_dirs) {
|
||||
if (install_dir.path == dir) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
settings_install_dirs.push_back({dir, enabled});
|
||||
return true;
|
||||
}
|
||||
|
||||
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()) {
|
||||
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) {
|
||||
settings_addon_install_dir = dir;
|
||||
}
|
||||
|
@ -571,11 +591,6 @@ void setMainWindowHeight(u32 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) {
|
||||
m_elf_viewer.resize(elfList.size());
|
||||
m_elf_viewer = elfList;
|
||||
|
@ -590,8 +605,15 @@ void setEmulatorLanguage(std::string language) {
|
|||
emulator_language = language;
|
||||
}
|
||||
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config) {
|
||||
settings_install_dirs = settings_install_dirs_config;
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& 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) {
|
||||
|
@ -614,8 +636,22 @@ u32 getMainWindowGeometryH() {
|
|||
return main_window_geometry_h;
|
||||
}
|
||||
|
||||
const std::vector<std::filesystem::path>& getGameInstallDirs() {
|
||||
return settings_install_dirs;
|
||||
const std::vector<std::filesystem::path> getGameInstallDirs() {
|
||||
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() {
|
||||
|
@ -658,10 +694,6 @@ u32 getMainWindowHeight() {
|
|||
return m_window_size_H;
|
||||
}
|
||||
|
||||
std::vector<std::string> getPkgViewer() {
|
||||
return m_pkg_viewer;
|
||||
}
|
||||
|
||||
std::vector<std::string> getElfViewer() {
|
||||
return m_elf_viewer;
|
||||
}
|
||||
|
@ -721,6 +753,7 @@ void load(const std::filesystem::path& path) {
|
|||
const toml::value& general = data.at("General");
|
||||
|
||||
isNeo = toml::find_or<bool>(general, "isPS4Pro", false);
|
||||
isDevKit = toml::find_or<bool>(general, "isDevKit", false);
|
||||
playBGM = toml::find_or<bool>(general, "playBGM", false);
|
||||
isTrophyPopupDisabled = toml::find_or<bool>(general, "isTrophyPopupDisabled", false);
|
||||
trophyNotificationDuration =
|
||||
|
@ -730,7 +763,7 @@ void load(const std::filesystem::path& path) {
|
|||
logFilter = toml::find_or<std::string>(general, "logFilter", "");
|
||||
logType = toml::find_or<std::string>(general, "logType", "sync");
|
||||
userName = toml::find_or<std::string>(general, "userName", "shadPS4");
|
||||
if (Common::isRelease) {
|
||||
if (Common::g_is_release) {
|
||||
updateChannel = toml::find_or<std::string>(general, "updateChannel", "Release");
|
||||
} else {
|
||||
updateChannel = toml::find_or<std::string>(general, "updateChannel", "Nightly");
|
||||
|
@ -739,7 +772,6 @@ void load(const std::filesystem::path& path) {
|
|||
isAutoUpdate = toml::find_or<bool>(general, "autoUpdate", false);
|
||||
isAlwaysShowChangelog = toml::find_or<bool>(general, "alwaysShowChangelog", false);
|
||||
isSideTrophy = toml::find_or<std::string>(general, "sideTrophy", "right");
|
||||
separateupdatefolder = toml::find_or<bool>(general, "separateUpdateEnabled", false);
|
||||
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false);
|
||||
checkCompatibilityOnStartup =
|
||||
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);
|
||||
|
||||
const auto install_dir_array =
|
||||
toml::find_or<std::vector<std::string>>(gui, "installDirs", {});
|
||||
for (const auto& dir : install_dir_array) {
|
||||
addGameInstallDir(std::filesystem::path{dir});
|
||||
toml::find_or<std::vector<std::u8string>>(gui, "installDirs", {});
|
||||
|
||||
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", {});
|
||||
|
@ -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_w = toml::find_or<int>(gui, "geometry_w", 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_recent_files = toml::find_or<std::vector<std::string>>(gui, "recentFiles", {});
|
||||
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) {
|
||||
toml::ordered_value data;
|
||||
|
||||
|
@ -876,6 +952,7 @@ void save(const std::filesystem::path& path) {
|
|||
}
|
||||
|
||||
data["General"]["isPS4Pro"] = isNeo;
|
||||
data["General"]["isDevKit"] = isDevKit;
|
||||
data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled;
|
||||
data["General"]["trophyNotificationDuration"] = trophyNotificationDuration;
|
||||
data["General"]["playBGM"] = playBGM;
|
||||
|
@ -890,7 +967,6 @@ void save(const std::filesystem::path& path) {
|
|||
data["General"]["autoUpdate"] = isAutoUpdate;
|
||||
data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog;
|
||||
data["General"]["sideTrophy"] = isSideTrophy;
|
||||
data["General"]["separateUpdateEnabled"] = separateupdatefolder;
|
||||
data["General"]["compatibilityEnabled"] = compatibilityData;
|
||||
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
|
||||
data["Input"]["cursorState"] = cursorState;
|
||||
|
@ -922,14 +998,37 @@ void save(const std::filesystem::path& path) {
|
|||
data["Debug"]["CollectShader"] = isShaderDebug;
|
||||
data["Debug"]["isSeparateLogFilesEnabled"] = isSeparateLogFilesEnabled;
|
||||
data["Debug"]["FPSColor"] = isFpsColor;
|
||||
|
||||
data["Keys"]["TrophyKey"] = trophyKey;
|
||||
|
||||
std::vector<std::string> install_dirs;
|
||||
for (const auto& dirString : settings_install_dirs) {
|
||||
install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data});
|
||||
std::vector<bool> install_dirs_enabled;
|
||||
|
||||
// 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"]["installDirsEnabled"] = install_dirs_enabled;
|
||||
data["GUI"]["saveDataPath"] = std::string{fmt::UTF(save_data_path.u8string()).data};
|
||||
data["GUI"]["loadGameSizeEnabled"] = load_game_size;
|
||||
|
||||
|
@ -940,9 +1039,13 @@ void save(const std::filesystem::path& path) {
|
|||
data["GUI"]["showBackgroundImage"] = showBackgroundImage;
|
||||
data["Settings"]["consoleLanguage"] = m_language;
|
||||
|
||||
// Sorting of TOML sections
|
||||
sortTomlSections(data);
|
||||
|
||||
std::ofstream file(path, std::ios::binary);
|
||||
file << data;
|
||||
file.close();
|
||||
|
||||
saveMainWindow(path);
|
||||
}
|
||||
|
||||
|
@ -980,10 +1083,12 @@ void saveMainWindow(const std::filesystem::path& path) {
|
|||
data["GUI"]["geometry_y"] = main_window_geometry_y;
|
||||
data["GUI"]["geometry_w"] = main_window_geometry_w;
|
||||
data["GUI"]["geometry_h"] = main_window_geometry_h;
|
||||
data["GUI"]["pkgDirs"] = m_pkg_viewer;
|
||||
data["GUI"]["elfDirs"] = m_elf_viewer;
|
||||
data["GUI"]["recentFiles"] = m_recent_files;
|
||||
|
||||
// Sorting of TOML sections
|
||||
sortTomlSections(data);
|
||||
|
||||
std::ofstream file(path, std::ios::binary);
|
||||
file << data;
|
||||
file.close();
|
||||
|
@ -992,6 +1097,7 @@ void saveMainWindow(const std::filesystem::path& path) {
|
|||
void setDefaultValues() {
|
||||
isHDRAllowed = false;
|
||||
isNeo = false;
|
||||
isDevKit = false;
|
||||
isFullscreen = false;
|
||||
isTrophyPopupDisabled = false;
|
||||
playBGM = false;
|
||||
|
@ -1000,9 +1106,9 @@ void setDefaultValues() {
|
|||
screenWidth = 1280;
|
||||
screenHeight = 720;
|
||||
logFilter = "";
|
||||
logType = "async";
|
||||
logType = "sync";
|
||||
userName = "shadPS4";
|
||||
if (Common::isRelease) {
|
||||
if (Common::g_is_release) {
|
||||
updateChannel = "Release";
|
||||
} else {
|
||||
updateChannel = "Nightly";
|
||||
|
@ -1033,7 +1139,6 @@ void setDefaultValues() {
|
|||
emulator_language = "en_US";
|
||||
m_language = 1;
|
||||
gpuId = -1;
|
||||
separateupdatefolder = false;
|
||||
compatibilityData = false;
|
||||
checkCompatibilityOnStartup = false;
|
||||
backgroundImageOpacity = 50;
|
||||
|
|
|
@ -9,6 +9,11 @@
|
|||
|
||||
namespace Config {
|
||||
|
||||
struct GameInstallDir {
|
||||
std::filesystem::path path;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
enum HideCursorState : s16 { Never, Idle, Always };
|
||||
|
||||
void load(const std::filesystem::path& path);
|
||||
|
@ -21,13 +26,15 @@ bool GetLoadGameSizeEnabled();
|
|||
std::filesystem::path GetSaveDataPath();
|
||||
void setLoadGameSizeEnabled(bool enable);
|
||||
bool getIsFullscreen();
|
||||
bool getShowLabelsUnderIcons();
|
||||
bool setShowLabelsUnderIcons();
|
||||
std::string getFullscreenMode();
|
||||
bool isNeoModeConsole();
|
||||
bool isDevKitConsole();
|
||||
bool getPlayBGM();
|
||||
int getBGMvolume();
|
||||
bool getisTrophyPopupDisabled();
|
||||
bool getEnableDiscordRPC();
|
||||
bool getSeparateUpdateEnabled();
|
||||
bool getCompatibilityEnabled();
|
||||
bool getCheckCompatibilityOnStartup();
|
||||
int getBackgroundImageOpacity();
|
||||
|
@ -97,8 +104,8 @@ void setNeoMode(bool enable);
|
|||
void setUserName(const std::string& type);
|
||||
void setUpdateChannel(const std::string& type);
|
||||
void setChooseHomeTab(const std::string& type);
|
||||
void setSeparateUpdateEnabled(bool use);
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config);
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
|
||||
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
|
||||
void setSaveDataPath(const std::filesystem::path& path);
|
||||
void setCompatibilityEnabled(bool use);
|
||||
void setCheckCompatibilityOnStartup(bool use);
|
||||
|
@ -133,8 +140,9 @@ void setVkGuestMarkersEnabled(bool enable);
|
|||
|
||||
// Gui
|
||||
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 setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled);
|
||||
void setAddonInstallDir(const std::filesystem::path& dir);
|
||||
void setMainWindowTheme(u32 theme);
|
||||
void setIconSize(u32 size);
|
||||
|
@ -144,7 +152,6 @@ void setSliderPositionGrid(u32 pos);
|
|||
void setTableMode(u32 mode);
|
||||
void setMainWindowWidth(u32 width);
|
||||
void setMainWindowHeight(u32 height);
|
||||
void setPkgViewer(const std::vector<std::string>& pkgList);
|
||||
void setElfViewer(const std::vector<std::string>& elfList);
|
||||
void setRecentFiles(const std::vector<std::string>& recentFiles);
|
||||
void setEmulatorLanguage(std::string language);
|
||||
|
@ -153,7 +160,8 @@ u32 getMainWindowGeometryX();
|
|||
u32 getMainWindowGeometryY();
|
||||
u32 getMainWindowGeometryW();
|
||||
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();
|
||||
u32 getMainWindowTheme();
|
||||
u32 getIconSize();
|
||||
|
@ -163,7 +171,6 @@ u32 getSliderPositionGrid();
|
|||
u32 getTableMode();
|
||||
u32 getMainWindowWidth();
|
||||
u32 getMainWindowHeight();
|
||||
std::vector<std::string> getPkgViewer();
|
||||
std::vector<std::string> getElfViewer();
|
||||
std::vector<std::string> getRecentFiles();
|
||||
std::string getEmulatorLanguage();
|
||||
|
|
|
@ -125,12 +125,15 @@ namespace {
|
|||
[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) {
|
||||
switch (origin) {
|
||||
case SeekOrigin::SetOrigin:
|
||||
default:
|
||||
return SEEK_SET;
|
||||
case SeekOrigin::CurrentPosition:
|
||||
return SEEK_CUR;
|
||||
case SeekOrigin::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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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.
|
||||
CurrentPosition, // Seeks from the current file pointer position.
|
||||
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 {
|
||||
|
|
|
@ -101,6 +101,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||
SUB(Lib, Ssl2) \
|
||||
SUB(Lib, SysModule) \
|
||||
SUB(Lib, Move) \
|
||||
SUB(Lib, NpAuth) \
|
||||
SUB(Lib, NpCommon) \
|
||||
SUB(Lib, NpManager) \
|
||||
SUB(Lib, NpScore) \
|
||||
|
|
|
@ -69,6 +69,7 @@ enum class Class : u8 {
|
|||
Lib_Http2, ///< The LibSceHttp2 implementation.
|
||||
Lib_SysModule, ///< The LibSceSysModule implementation
|
||||
Lib_NpCommon, ///< The LibSceNpCommon implementation
|
||||
Lib_NpAuth, ///< The LibSceNpAuth implementation
|
||||
Lib_NpManager, ///< The LibSceNpManager implementation
|
||||
Lib_NpScore, ///< The LibSceNpScore implementation
|
||||
Lib_NpTrophy, ///< The LibSceNpTrophy implementation
|
||||
|
|
|
@ -60,7 +60,7 @@ static CFURLRef UntranslocateBundlePath(const CFURLRef bundle_path) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static std::filesystem::path GetBundleParentDirectory() {
|
||||
static std::optional<std::filesystem::path> GetBundleParentDirectory() {
|
||||
if (CFBundleRef bundle_ref = CFBundleGetMainBundle()) {
|
||||
if (CFURLRef bundle_url_ref = CFBundleCopyBundleURL(bundle_ref)) {
|
||||
SCOPE_EXIT {
|
||||
|
@ -83,14 +83,16 @@ static std::filesystem::path GetBundleParentDirectory() {
|
|||
}
|
||||
}
|
||||
}
|
||||
return std::filesystem::current_path();
|
||||
return std::nullopt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static auto UserPaths = [] {
|
||||
#ifdef __APPLE__
|
||||
#if defined(__APPLE__) && defined(ENABLE_QT_GUI)
|
||||
// Set the current path to the directory containing the app bundle.
|
||||
std::filesystem::current_path(GetBundleParentDirectory());
|
||||
if (const auto bundle_dir = GetBundleParentDirectory()) {
|
||||
std::filesystem::current_path(*bundle_dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Try the portable user directory first.
|
||||
|
|
|
@ -3,21 +3,17 @@
|
|||
|
||||
#include "common/scm_rev.h"
|
||||
|
||||
#define GIT_REV "@GIT_REV@"
|
||||
#define GIT_BRANCH "@GIT_BRANCH@"
|
||||
#define GIT_DESC "@GIT_DESC@"
|
||||
#define GIT_REMOTE_NAME "@GIT_REMOTE_NAME@"
|
||||
#define GIT_REMOTE_URL "@GIT_REMOTE_URL@"
|
||||
#define BUILD_DATE "@BUILD_DATE@"
|
||||
|
||||
namespace Common {
|
||||
|
||||
const char g_scm_rev[] = GIT_REV;
|
||||
const char g_scm_branch[] = GIT_BRANCH;
|
||||
const char g_scm_desc[] = GIT_DESC;
|
||||
const char g_scm_remote_name[] = GIT_REMOTE_NAME;
|
||||
const char g_scm_remote_url[] = GIT_REMOTE_URL;
|
||||
const char g_scm_date[] = BUILD_DATE;
|
||||
constexpr char g_version[] = "@APP_VERSION@";
|
||||
constexpr bool g_is_release = @APP_IS_RELEASE@;
|
||||
|
||||
constexpr char g_scm_rev[] = "@GIT_REV@";
|
||||
constexpr char g_scm_branch[] = "@GIT_BRANCH@";
|
||||
constexpr char g_scm_desc[] = "@GIT_DESC@";
|
||||
constexpr char g_scm_remote_name[] = "@GIT_REMOTE_NAME@";
|
||||
constexpr char g_scm_remote_url[] = "@GIT_REMOTE_URL@";
|
||||
constexpr char g_scm_date[] = "@BUILD_DATE@";
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
|
||||
namespace Common {
|
||||
|
||||
extern const char g_version[];
|
||||
extern const bool g_is_release;
|
||||
|
||||
extern const char g_scm_rev[];
|
||||
extern const char g_scm_branch[];
|
||||
extern const char g_scm_desc[];
|
||||
|
|
180
src/common/sha1.h
Normal file
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
|
|
@ -1,14 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace Common {
|
||||
|
||||
constexpr char VERSION[] = "0.7.0";
|
||||
constexpr bool isRelease = true;
|
||||
|
||||
} // namespace Common
|
|
@ -22,10 +22,6 @@
|
|||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#ifdef __APPLE__
|
||||
#include <half.hpp>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace Xbyak::util;
|
||||
|
@ -81,538 +77,6 @@ static Xbyak::Address ZydisToXbyakMemoryOperand(const ZydisDecodedOperand& opera
|
|||
return ptr[expression];
|
||||
}
|
||||
|
||||
static u64 ZydisToXbyakImmediateOperand(const ZydisDecodedOperand& operand) {
|
||||
ASSERT_MSG(operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE,
|
||||
"Expected immediate operand, got type: {}", static_cast<u32>(operand.type));
|
||||
return operand.imm.value.u;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Xbyak::Operand> ZydisToXbyakOperand(const ZydisDecodedOperand& operand) {
|
||||
switch (operand.type) {
|
||||
case ZYDIS_OPERAND_TYPE_REGISTER: {
|
||||
return std::make_unique<Xbyak::Reg>(ZydisToXbyakRegisterOperand(operand));
|
||||
}
|
||||
case ZYDIS_OPERAND_TYPE_MEMORY: {
|
||||
return std::make_unique<Xbyak::Address>(ZydisToXbyakMemoryOperand(operand));
|
||||
}
|
||||
default:
|
||||
UNREACHABLE_MSG("Unsupported operand type: {}", static_cast<u32>(operand.type));
|
||||
}
|
||||
}
|
||||
|
||||
static bool OperandUsesRegister(const Xbyak::Operand* operand, int index) {
|
||||
if (operand->isREG()) {
|
||||
return operand->getIdx() == index;
|
||||
}
|
||||
if (operand->isMEM()) {
|
||||
const Xbyak::RegExp& reg_exp = operand->getAddress().getRegExp();
|
||||
return reg_exp.getBase().getIdx() == index || reg_exp.getIndex().getIdx() == index;
|
||||
}
|
||||
UNREACHABLE_MSG("Unsupported operand kind: {}", static_cast<u32>(operand->getKind()));
|
||||
}
|
||||
|
||||
static bool IsRegisterAllocated(
|
||||
const std::initializer_list<const Xbyak::Operand*>& allocated_registers, const int index) {
|
||||
return std::ranges::find_if(allocated_registers.begin(), allocated_registers.end(),
|
||||
[index](const Xbyak::Operand* operand) {
|
||||
return OperandUsesRegister(operand, index);
|
||||
}) != allocated_registers.end();
|
||||
}
|
||||
|
||||
static Xbyak::Reg AllocateScratchRegister(
|
||||
const std::initializer_list<const Xbyak::Operand*> allocated_registers, const u32 bits) {
|
||||
for (int index = Xbyak::Operand::R8; index <= Xbyak::Operand::R15; index++) {
|
||||
if (!IsRegisterAllocated(allocated_registers, index)) {
|
||||
return Xbyak::Reg32e(index, static_cast<int>(bits));
|
||||
}
|
||||
}
|
||||
UNREACHABLE_MSG("Out of scratch registers!");
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
static pthread_key_t stack_pointer_slot;
|
||||
static pthread_key_t patch_stack_slot;
|
||||
static std::once_flag patch_context_slots_init_flag;
|
||||
static constexpr u32 patch_stack_size = 0x1000;
|
||||
|
||||
static_assert(sizeof(void*) == sizeof(u64),
|
||||
"Cannot fit a register inside a thread local storage slot.");
|
||||
|
||||
static void FreePatchStack(void* patch_stack) {
|
||||
// Subtract back to the bottom of the stack for free.
|
||||
std::free(static_cast<u8*>(patch_stack) - patch_stack_size);
|
||||
}
|
||||
|
||||
static void InitializePatchContextSlots() {
|
||||
ASSERT_MSG(pthread_key_create(&stack_pointer_slot, nullptr) == 0,
|
||||
"Unable to allocate thread-local register for stack pointer.");
|
||||
ASSERT_MSG(pthread_key_create(&patch_stack_slot, FreePatchStack) == 0,
|
||||
"Unable to allocate thread-local register for patch stack.");
|
||||
}
|
||||
|
||||
void InitializeThreadPatchStack() {
|
||||
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
|
||||
|
||||
pthread_setspecific(patch_stack_slot,
|
||||
static_cast<u8*>(std::malloc(patch_stack_size)) + patch_stack_size);
|
||||
}
|
||||
|
||||
/// Saves the stack pointer to thread local storage and loads the patch stack.
|
||||
static void SaveStack(Xbyak::CodeGenerator& c) {
|
||||
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
|
||||
|
||||
// Save original stack pointer and load patch stack.
|
||||
c.putSeg(gs);
|
||||
c.mov(qword[reinterpret_cast<void*>(stack_pointer_slot * sizeof(void*))], rsp);
|
||||
c.putSeg(gs);
|
||||
c.mov(rsp, qword[reinterpret_cast<void*>(patch_stack_slot * sizeof(void*))]);
|
||||
}
|
||||
|
||||
/// Restores the stack pointer from thread local storage.
|
||||
static void RestoreStack(Xbyak::CodeGenerator& c) {
|
||||
std::call_once(patch_context_slots_init_flag, InitializePatchContextSlots);
|
||||
|
||||
// Save patch stack pointer and load original stack.
|
||||
c.putSeg(gs);
|
||||
c.mov(qword[reinterpret_cast<void*>(patch_stack_slot * sizeof(void*))], rsp);
|
||||
c.putSeg(gs);
|
||||
c.mov(rsp, qword[reinterpret_cast<void*>(stack_pointer_slot * sizeof(void*))]);
|
||||
}
|
||||
|
||||
/// Validates that the dst register is supported given the SaveStack/RestoreStack implementation.
|
||||
static void ValidateDst(const Xbyak::Reg& dst) {
|
||||
// No restrictions.
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void InitializeThreadPatchStack() {
|
||||
// No-op
|
||||
}
|
||||
|
||||
// NOTE: Since stack pointer here is subtracted through safe zone and not saved anywhere,
|
||||
// it must not be modified during the instruction. Otherwise, we will not be able to find
|
||||
// and load registers back from where they were saved. Thus, a limitation is placed on
|
||||
// instructions, that they must not use the stack pointer register as a destination.
|
||||
|
||||
/// Saves the stack pointer to thread local storage and loads the patch stack.
|
||||
static void SaveStack(Xbyak::CodeGenerator& c) {
|
||||
c.lea(rsp, ptr[rsp - 128]); // red zone
|
||||
}
|
||||
|
||||
/// Restores the stack pointer from thread local storage.
|
||||
static void RestoreStack(Xbyak::CodeGenerator& c) {
|
||||
c.lea(rsp, ptr[rsp + 128]); // red zone
|
||||
}
|
||||
|
||||
/// Validates that the dst register is supported given the SaveStack/RestoreStack implementation.
|
||||
static void ValidateDst(const Xbyak::Reg& dst) {
|
||||
// Stack pointer is not preserved, so it can't be used as a dst.
|
||||
ASSERT_MSG(dst.getIdx() != rsp.getIdx(), "Stack pointer not supported as destination.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// Switches to the patch stack, saves registers, and restores the original stack.
|
||||
static void SaveRegisters(Xbyak::CodeGenerator& c, const std::initializer_list<Xbyak::Reg> regs) {
|
||||
// Uses a more robust solution for saving registers on MacOS to avoid potential stack corruption
|
||||
// if games decide to not follow the ABI and use the red zone.
|
||||
SaveStack(c);
|
||||
for (const auto& reg : regs) {
|
||||
c.push(reg.cvt64());
|
||||
}
|
||||
RestoreStack(c);
|
||||
}
|
||||
|
||||
/// Switches to the patch stack, restores registers, and restores the original stack.
|
||||
static void RestoreRegisters(Xbyak::CodeGenerator& c,
|
||||
const std::initializer_list<Xbyak::Reg> regs) {
|
||||
SaveStack(c);
|
||||
for (const auto& reg : regs) {
|
||||
c.pop(reg.cvt64());
|
||||
}
|
||||
RestoreStack(c);
|
||||
}
|
||||
|
||||
/// Switches to the patch stack and stores all registers.
|
||||
static void SaveContext(Xbyak::CodeGenerator& c, bool save_flags = false) {
|
||||
SaveStack(c);
|
||||
for (int reg = Xbyak::Operand::RAX; reg <= Xbyak::Operand::R15; reg++) {
|
||||
c.push(Xbyak::Reg64(reg));
|
||||
}
|
||||
c.lea(rsp, ptr[rsp - 32 * 16]);
|
||||
for (int reg = 0; reg <= 15; reg++) {
|
||||
c.vmovdqu(ptr[rsp + 32 * reg], Xbyak::Ymm(reg));
|
||||
}
|
||||
if (save_flags) {
|
||||
c.pushfq();
|
||||
}
|
||||
}
|
||||
|
||||
/// Restores all registers and restores the original stack.
|
||||
/// If the destination is a register, it is not restored to preserve the output.
|
||||
static void RestoreContext(Xbyak::CodeGenerator& c, const Xbyak::Operand& dst,
|
||||
bool restore_flags = false) {
|
||||
if (restore_flags) {
|
||||
c.popfq();
|
||||
}
|
||||
for (int reg = 15; reg >= 0; reg--) {
|
||||
if ((!dst.isXMM() && !dst.isYMM()) || dst.getIdx() != reg) {
|
||||
c.vmovdqu(Xbyak::Ymm(reg), ptr[rsp + 32 * reg]);
|
||||
}
|
||||
}
|
||||
c.lea(rsp, ptr[rsp + 32 * 16]);
|
||||
for (int reg = Xbyak::Operand::R15; reg >= Xbyak::Operand::RAX; reg--) {
|
||||
if (!dst.isREG() || dst.getIdx() != reg) {
|
||||
c.pop(Xbyak::Reg64(reg));
|
||||
} else {
|
||||
c.lea(rsp, ptr[rsp + 8]);
|
||||
}
|
||||
}
|
||||
RestoreStack(c);
|
||||
}
|
||||
|
||||
static void GenerateANDN(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src1 = ZydisToXbyakRegisterOperand(operands[1]);
|
||||
const auto src2 = ZydisToXbyakOperand(operands[2]);
|
||||
ValidateDst(dst);
|
||||
|
||||
// Check if src2 is a memory operand or a register different to dst.
|
||||
// In those cases, we don't need to use a temporary register and are free to modify dst.
|
||||
// In cases where dst and src2 are the same register, a temporary needs to be used to avoid
|
||||
// modifying src2.
|
||||
bool src2_uses_dst = false;
|
||||
if (src2->isMEM()) {
|
||||
const auto base = src2->getAddress().getRegExp().getBase().getIdx();
|
||||
const auto index = src2->getAddress().getRegExp().getIndex().getIdx();
|
||||
src2_uses_dst = base == dst.getIdx() || index == dst.getIdx();
|
||||
} else {
|
||||
ASSERT(src2->isREG());
|
||||
src2_uses_dst = src2->getReg() == dst;
|
||||
}
|
||||
|
||||
if (!src2_uses_dst) {
|
||||
if (dst != src1)
|
||||
c.mov(dst, src1);
|
||||
c.not_(dst);
|
||||
c.and_(dst, *src2);
|
||||
} else {
|
||||
const auto scratch = AllocateScratchRegister({&dst, &src1, src2.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
c.mov(scratch, src1);
|
||||
c.not_(scratch);
|
||||
c.and_(scratch, *src2);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateBEXTR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
const auto start_len = ZydisToXbyakRegisterOperand(operands[2]);
|
||||
ValidateDst(dst);
|
||||
|
||||
const Xbyak::Reg32e shift(Xbyak::Operand::RCX, static_cast<int>(start_len.getBit()));
|
||||
const auto scratch1 =
|
||||
AllocateScratchRegister({&dst, src.get(), &start_len, &shift}, dst.getBit());
|
||||
const auto scratch2 =
|
||||
AllocateScratchRegister({&dst, src.get(), &start_len, &shift, &scratch1}, dst.getBit());
|
||||
|
||||
if (dst.getIdx() == shift.getIdx()) {
|
||||
SaveRegisters(c, {scratch1, scratch2});
|
||||
} else {
|
||||
SaveRegisters(c, {scratch1, scratch2, shift});
|
||||
}
|
||||
|
||||
c.mov(scratch1, *src);
|
||||
if (shift.getIdx() != start_len.getIdx()) {
|
||||
c.mov(shift, start_len);
|
||||
}
|
||||
|
||||
c.shr(scratch1, shift.cvt8());
|
||||
c.shr(shift, 8);
|
||||
c.mov(scratch2, 1);
|
||||
c.shl(scratch2, shift.cvt8());
|
||||
c.dec(scratch2);
|
||||
|
||||
c.mov(dst, scratch1);
|
||||
c.and_(dst, scratch2);
|
||||
|
||||
if (dst.getIdx() == shift.getIdx()) {
|
||||
RestoreRegisters(c, {scratch2, scratch1});
|
||||
} else {
|
||||
RestoreRegisters(c, {shift, scratch2, scratch1});
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateBLSI(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
ValidateDst(dst);
|
||||
|
||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
// BLSI sets CF to zero if source is zero, otherwise it sets CF to one.
|
||||
Xbyak::Label clear_carry, end;
|
||||
|
||||
c.mov(scratch, *src);
|
||||
c.neg(scratch); // NEG, like BLSI, clears CF if the source is zero and sets it otherwise
|
||||
c.jnc(clear_carry);
|
||||
|
||||
c.and_(scratch, *src);
|
||||
c.stc(); // setting/clearing carry needs to happen after the AND because that clears CF
|
||||
c.jmp(end);
|
||||
|
||||
c.L(clear_carry);
|
||||
c.and_(scratch, *src);
|
||||
// We don't need to clear carry here since AND does that for us
|
||||
|
||||
c.L(end);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
|
||||
static void GenerateBLSMSK(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
ValidateDst(dst);
|
||||
|
||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
Xbyak::Label clear_carry, end;
|
||||
|
||||
// BLSMSK sets CF to zero if source is NOT zero, otherwise it sets CF to one.
|
||||
c.mov(scratch, *src);
|
||||
c.test(scratch, scratch);
|
||||
c.jnz(clear_carry);
|
||||
|
||||
c.dec(scratch);
|
||||
c.xor_(scratch, *src);
|
||||
c.stc();
|
||||
c.jmp(end);
|
||||
|
||||
c.L(clear_carry);
|
||||
c.dec(scratch);
|
||||
c.xor_(scratch, *src);
|
||||
// We don't need to clear carry here since XOR does that for us
|
||||
|
||||
c.L(end);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
|
||||
static void GenerateTZCNT(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
ValidateDst(dst);
|
||||
|
||||
Xbyak::Label src_zero, end;
|
||||
|
||||
c.cmp(*src, 0);
|
||||
c.je(src_zero);
|
||||
|
||||
// If src is not zero, functions like a BSF, but also clears the CF
|
||||
c.bsf(dst, *src);
|
||||
c.clc();
|
||||
c.jmp(end);
|
||||
|
||||
c.L(src_zero);
|
||||
c.mov(dst, operands[0].size);
|
||||
// Since dst is not zero, also set ZF to zero. Testing dst with itself when we know
|
||||
// it isn't zero is a good way to do this.
|
||||
// Use cvt32 to avoid REX/Operand size prefixes.
|
||||
c.test(dst.cvt32(), dst.cvt32());
|
||||
// When source is zero, TZCNT also sets CF.
|
||||
c.stc();
|
||||
|
||||
c.L(end);
|
||||
}
|
||||
|
||||
static void GenerateBLSR(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
ValidateDst(dst);
|
||||
|
||||
const auto scratch = AllocateScratchRegister({&dst, src.get()}, dst.getBit());
|
||||
|
||||
SaveRegisters(c, {scratch});
|
||||
|
||||
Xbyak::Label clear_carry, end;
|
||||
|
||||
// BLSR sets CF to zero if source is NOT zero, otherwise it sets CF to one.
|
||||
c.mov(scratch, *src);
|
||||
c.test(scratch, scratch);
|
||||
c.jnz(clear_carry);
|
||||
|
||||
c.dec(scratch);
|
||||
c.and_(scratch, *src);
|
||||
c.stc();
|
||||
c.jmp(end);
|
||||
|
||||
c.L(clear_carry);
|
||||
c.dec(scratch);
|
||||
c.and_(scratch, *src);
|
||||
// We don't need to clear carry here since AND does that for us
|
||||
|
||||
c.L(end);
|
||||
c.mov(dst, scratch);
|
||||
|
||||
RestoreRegisters(c, {scratch});
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
static __attribute__((sysv_abi)) void PerformVCVTPH2PS(float* out, const half_float::half* in,
|
||||
const u32 count) {
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
out[i] = half_float::half_cast<float>(in[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateVCVTPH2PS(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakOperand(operands[1]);
|
||||
|
||||
const auto float_count = dst.getBit() / 32;
|
||||
const auto byte_count = float_count * 4;
|
||||
|
||||
SaveContext(c, true);
|
||||
|
||||
// Allocate stack space for outputs and load into first parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rdi, rsp);
|
||||
|
||||
if (src->isXMM()) {
|
||||
// Allocate stack space for inputs and load into second parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rsi, rsp);
|
||||
|
||||
// Move input to the allocated space.
|
||||
c.movdqu(ptr[rsp], *reinterpret_cast<Xbyak::Xmm*>(src.get()));
|
||||
} else {
|
||||
c.lea(rsi, src->getAddress());
|
||||
}
|
||||
|
||||
// Load float count into third parameter.
|
||||
c.mov(rdx, float_count);
|
||||
|
||||
c.mov(rax, reinterpret_cast<u64>(PerformVCVTPH2PS));
|
||||
c.call(rax);
|
||||
|
||||
if (src->isXMM()) {
|
||||
// Clean up after inputs space.
|
||||
c.add(rsp, byte_count);
|
||||
}
|
||||
|
||||
// Load outputs into destination register and clean up space.
|
||||
if (dst.isYMM()) {
|
||||
c.vmovdqu(*reinterpret_cast<const Xbyak::Ymm*>(&dst), ptr[rsp]);
|
||||
} else {
|
||||
c.movdqu(*reinterpret_cast<const Xbyak::Xmm*>(&dst), ptr[rsp]);
|
||||
}
|
||||
c.add(rsp, byte_count);
|
||||
|
||||
RestoreContext(c, dst, true);
|
||||
}
|
||||
|
||||
using SingleToHalfFloatConverter = half_float::half (*)(float);
|
||||
static const SingleToHalfFloatConverter SingleToHalfFloatConverters[4] = {
|
||||
half_float::half_cast<half_float::half, std::round_to_nearest, float>,
|
||||
half_float::half_cast<half_float::half, std::round_toward_neg_infinity, float>,
|
||||
half_float::half_cast<half_float::half, std::round_toward_infinity, float>,
|
||||
half_float::half_cast<half_float::half, std::round_toward_zero, float>,
|
||||
};
|
||||
|
||||
static __attribute__((sysv_abi)) void PerformVCVTPS2PH(half_float::half* out, const float* in,
|
||||
const u32 count, const u8 rounding_mode) {
|
||||
const auto conversion_func = SingleToHalfFloatConverters[rounding_mode];
|
||||
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
out[i] = conversion_func(in[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateVCVTPS2PH(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakOperand(operands[0]);
|
||||
const auto src = ZydisToXbyakRegisterOperand(operands[1]);
|
||||
const auto ctrl = ZydisToXbyakImmediateOperand(operands[2]);
|
||||
|
||||
const auto float_count = src.getBit() / 32;
|
||||
const auto byte_count = float_count * 4;
|
||||
|
||||
SaveContext(c, true);
|
||||
|
||||
if (dst->isXMM()) {
|
||||
// Allocate stack space for outputs and load into first parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rdi, rsp);
|
||||
} else {
|
||||
c.lea(rdi, dst->getAddress());
|
||||
}
|
||||
|
||||
// Allocate stack space for inputs and load into second parameter.
|
||||
c.sub(rsp, byte_count);
|
||||
c.mov(rsi, rsp);
|
||||
|
||||
// Move input to the allocated space.
|
||||
if (src.isYMM()) {
|
||||
c.vmovdqu(ptr[rsp], *reinterpret_cast<const Xbyak::Ymm*>(&src));
|
||||
} else {
|
||||
c.movdqu(ptr[rsp], *reinterpret_cast<const Xbyak::Xmm*>(&src));
|
||||
}
|
||||
|
||||
// Load float count into third parameter.
|
||||
c.mov(rdx, float_count);
|
||||
|
||||
// Load rounding mode into fourth parameter.
|
||||
if (ctrl & 4) {
|
||||
// Load from MXCSR.RC.
|
||||
c.stmxcsr(ptr[rsp - 4]);
|
||||
c.mov(rcx, ptr[rsp - 4]);
|
||||
c.shr(rcx, 13);
|
||||
c.and_(rcx, 3);
|
||||
} else {
|
||||
c.mov(rcx, ctrl & 3);
|
||||
}
|
||||
|
||||
c.mov(rax, reinterpret_cast<u64>(PerformVCVTPS2PH));
|
||||
c.call(rax);
|
||||
|
||||
// Clean up after inputs space.
|
||||
c.add(rsp, byte_count);
|
||||
|
||||
if (dst->isXMM()) {
|
||||
// Load outputs into destination register and clean up space.
|
||||
c.movdqu(*reinterpret_cast<Xbyak::Xmm*>(dst.get()), ptr[rsp]);
|
||||
c.add(rsp, byte_count);
|
||||
}
|
||||
|
||||
RestoreContext(c, *dst, true);
|
||||
}
|
||||
|
||||
static bool FilterRosetta2Only(const ZydisDecodedOperand*) {
|
||||
int ret = 0;
|
||||
size_t size = sizeof(ret);
|
||||
if (sysctlbyname("sysctl.proc_translated", &ret, &size, nullptr, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else // __APPLE__
|
||||
|
||||
static bool FilterTcbAccess(const ZydisDecodedOperand* operands) {
|
||||
const auto& dst_op = operands[0];
|
||||
const auto& src_op = operands[1];
|
||||
|
@ -657,18 +121,11 @@ static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGe
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
static bool FilterNoSSE4a(const ZydisDecodedOperand*) {
|
||||
Cpu cpu;
|
||||
return !cpu.has(Cpu::tSSE4a);
|
||||
}
|
||||
|
||||
static bool FilterNoBMI1(const ZydisDecodedOperand*) {
|
||||
Cpu cpu;
|
||||
return !cpu.has(Cpu::tBMI1);
|
||||
}
|
||||
|
||||
static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||
operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
||||
|
@ -940,30 +397,16 @@ struct PatchInfo {
|
|||
};
|
||||
|
||||
static const std::unordered_map<ZydisMnemonic, PatchInfo> Patches = {
|
||||
// SSE4a
|
||||
{ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}},
|
||||
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows needs a trampoline.
|
||||
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, true}},
|
||||
#elif !defined(__APPLE__)
|
||||
{ZYDIS_MNEMONIC_MOV, {FilterTcbAccess, GenerateTcbAccess, false}},
|
||||
#endif
|
||||
|
||||
{ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}},
|
||||
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
||||
|
||||
// BMI1
|
||||
{ZYDIS_MNEMONIC_ANDN, {FilterNoBMI1, GenerateANDN, true}},
|
||||
{ZYDIS_MNEMONIC_BEXTR, {FilterNoBMI1, GenerateBEXTR, true}},
|
||||
{ZYDIS_MNEMONIC_BLSI, {FilterNoBMI1, GenerateBLSI, true}},
|
||||
{ZYDIS_MNEMONIC_BLSMSK, {FilterNoBMI1, GenerateBLSMSK, true}},
|
||||
{ZYDIS_MNEMONIC_BLSR, {FilterNoBMI1, GenerateBLSR, true}},
|
||||
{ZYDIS_MNEMONIC_TZCNT, {FilterNoBMI1, GenerateTZCNT, true}},
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Patches for instruction sets not supported by Rosetta 2.
|
||||
// F16C
|
||||
{ZYDIS_MNEMONIC_VCVTPH2PS, {FilterRosetta2Only, GenerateVCVTPH2PS, true}},
|
||||
{ZYDIS_MNEMONIC_VCVTPS2PH, {FilterRosetta2Only, GenerateVCVTPS2PH, true}},
|
||||
#endif
|
||||
};
|
||||
|
||||
static std::once_flag init_flag;
|
||||
|
@ -1280,18 +723,7 @@ void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_are
|
|||
}
|
||||
|
||||
void PrePatchInstructions(u64 segment_addr, u64 segment_size) {
|
||||
#if defined(__APPLE__)
|
||||
// HACK: For some reason patching in the signal handler at the start of a page does not work
|
||||
// under Rosetta 2. Patch any instructions at the start of a page ahead of time.
|
||||
if (!Patches.empty()) {
|
||||
auto* code_page = reinterpret_cast<u8*>(Common::AlignUp(segment_addr, 0x1000));
|
||||
const auto* end_page = code_page + Common::AlignUp(segment_size, 0x1000);
|
||||
while (code_page < end_page) {
|
||||
TryPatchJit(code_page);
|
||||
code_page += 0x1000;
|
||||
}
|
||||
}
|
||||
#elif !defined(_WIN32)
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
// Linux and others have an FS segment pointing to valid memory, so continue to do full
|
||||
// ahead-of-time patching for now until a better solution is worked out.
|
||||
if (!Patches.empty()) {
|
||||
|
|
|
@ -7,12 +7,6 @@
|
|||
|
||||
namespace Core {
|
||||
|
||||
/// Initializes a stack for the current thread for use by patch implementations.
|
||||
void InitializeThreadPatchStack();
|
||||
|
||||
/// Cleans up the patch stack for the current thread.
|
||||
void CleanupThreadPatchStack();
|
||||
|
||||
/// Registers a module for patching, providing an area to generate trampoline code.
|
||||
void RegisterPatchModule(void* module_ptr, u64 module_size, void* trampoline_area_ptr,
|
||||
u64 trampoline_area_size);
|
||||
|
|
|
@ -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};
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <imgui.h>
|
||||
|
||||
#include "SDL3/SDL_log.h"
|
||||
#include "common/config.h"
|
||||
#include "common/singleton.h"
|
||||
#include "common/types.h"
|
||||
|
@ -117,22 +118,6 @@ void L::DrawMenuBar() {
|
|||
|
||||
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) {
|
||||
OpenPopup("GPU Tools Options");
|
||||
just_opened_options = true;
|
||||
|
@ -381,6 +366,32 @@ void L::Draw() {
|
|||
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 (Begin("Video Info", nullptr,
|
||||
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDecoration |
|
||||
|
|
|
@ -19,6 +19,7 @@ public:
|
|||
static void SetupSettings();
|
||||
|
||||
void Draw() override;
|
||||
bool show_pause_status = false;
|
||||
};
|
||||
|
||||
} // namespace Core::Devtools
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "options.h"
|
||||
|
||||
#include <memory>
|
||||
#include <imgui.h>
|
||||
|
||||
#include "options.h"
|
||||
#include "video_core/renderer_vulkan/vk_presenter.h"
|
||||
|
||||
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
||||
|
||||
namespace Core::Devtools {
|
||||
|
||||
|
@ -12,6 +17,7 @@ TOptions Options;
|
|||
void LoadOptionsConfig(const char* line) {
|
||||
char str[512];
|
||||
int i;
|
||||
float f;
|
||||
if (sscanf(line, "disassembler_cli_isa=%511[^\n]", str) == 1) {
|
||||
Options.disassembler_cli_isa = str;
|
||||
return;
|
||||
|
@ -24,12 +30,26 @@ void LoadOptionsConfig(const char* line) {
|
|||
Options.frame_dump_render_on_collapse = i != 0;
|
||||
return;
|
||||
}
|
||||
if (sscanf(line, "fsr_enabled=%d", &i) == 1) {
|
||||
presenter->GetFsrSettingsRef().enable = i != 0;
|
||||
return;
|
||||
}
|
||||
if (sscanf(line, "fsr_rcas_enabled=%d", &i) == 1) {
|
||||
presenter->GetFsrSettingsRef().use_rcas = i != 0;
|
||||
return;
|
||||
}
|
||||
if (sscanf(line, "fsr_rcas_attenuation=%f", &f) == 1) {
|
||||
presenter->GetFsrSettingsRef().rcas_attenuation = f;
|
||||
}
|
||||
}
|
||||
|
||||
void SerializeOptionsConfig(ImGuiTextBuffer* buf) {
|
||||
buf->appendf("disassembler_cli_isa=%s\n", Options.disassembler_cli_isa.c_str());
|
||||
buf->appendf("disassembler_cli_spv=%s\n", Options.disassembler_cli_spv.c_str());
|
||||
buf->appendf("frame_dump_render_on_collapse=%d\n", Options.frame_dump_render_on_collapse);
|
||||
buf->appendf("fsr_enabled=%d\n", presenter->GetFsrSettingsRef().enable);
|
||||
buf->appendf("fsr_rcas_enabled=%d\n", presenter->GetFsrSettingsRef().use_rcas);
|
||||
buf->appendf("fsr_rcas_attenuation=%f\n", presenter->GetFsrSettingsRef().rcas_attenuation);
|
||||
}
|
||||
|
||||
} // namespace Core::Devtools
|
||||
|
|
|
@ -627,65 +627,56 @@ void TextEditor::HandleKeyboardInputs() {
|
|||
io.WantCaptureKeyboard = true;
|
||||
io.WantTextInput = true;
|
||||
|
||||
if (!IsReadOnly() && ctrl && !shift && !alt &&
|
||||
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Z)))
|
||||
if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Z))
|
||||
Undo();
|
||||
else if (!IsReadOnly() && !ctrl && !shift && alt &&
|
||||
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
|
||||
else if (!IsReadOnly() && !ctrl && !shift && alt && ImGui::IsKeyPressed(ImGuiKey_Backspace))
|
||||
Undo();
|
||||
else if (!IsReadOnly() && ctrl && !shift && !alt &&
|
||||
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Y)))
|
||||
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Y))
|
||||
Redo();
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow)))
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_UpArrow))
|
||||
MoveUp(1, shift);
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow)))
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_DownArrow))
|
||||
MoveDown(1, shift);
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)))
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGuiKey_LeftArrow))
|
||||
MoveLeft(1, shift, ctrl);
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow)))
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGuiKey_RightArrow))
|
||||
MoveRight(1, shift, ctrl);
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageUp)))
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGuiKey_PageUp))
|
||||
MoveUp(GetPageSize() - 4, shift);
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageDown)))
|
||||
else if (!alt && ImGui::IsKeyPressed(ImGuiKey_PageDown))
|
||||
MoveDown(GetPageSize() - 4, shift);
|
||||
else if (!alt && ctrl && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
|
||||
else if (!alt && ctrl && ImGui::IsKeyPressed(ImGuiKey_Home))
|
||||
MoveTop(shift);
|
||||
else if (ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
|
||||
else if (ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_End))
|
||||
MoveBottom(shift);
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_Home))
|
||||
MoveHome(shift);
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
|
||||
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_End))
|
||||
MoveEnd(shift);
|
||||
else if (!IsReadOnly() && !ctrl && !shift && !alt &&
|
||||
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
|
||||
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Delete))
|
||||
Delete();
|
||||
else if (!IsReadOnly() && !ctrl && !shift && !alt &&
|
||||
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
|
||||
ImGui::IsKeyPressed(ImGuiKey_Backspace))
|
||||
Backspace();
|
||||
else if (!ctrl && !shift && !alt &&
|
||||
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
|
||||
else if (!ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Insert))
|
||||
mOverwrite ^= true;
|
||||
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
|
||||
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Insert))
|
||||
Copy();
|
||||
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
|
||||
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_C))
|
||||
Copy();
|
||||
else if (!IsReadOnly() && !ctrl && shift && !alt &&
|
||||
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
|
||||
else if (!IsReadOnly() && !ctrl && shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Insert))
|
||||
Paste();
|
||||
else if (!IsReadOnly() && ctrl && !shift && !alt &&
|
||||
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_V)))
|
||||
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_V))
|
||||
Paste();
|
||||
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_X)))
|
||||
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_X))
|
||||
Cut();
|
||||
else if (!ctrl && shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
|
||||
else if (!ctrl && shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Delete))
|
||||
Cut();
|
||||
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_A)))
|
||||
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_A))
|
||||
SelectAll();
|
||||
else if (!IsReadOnly() && !ctrl && !shift && !alt &&
|
||||
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))
|
||||
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Enter))
|
||||
EnterCharacter('\n', false);
|
||||
else if (!IsReadOnly() && !ctrl && !alt &&
|
||||
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Tab)))
|
||||
else if (!IsReadOnly() && !ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_Tab))
|
||||
EnterCharacter('\t', shift);
|
||||
|
||||
if (!IsReadOnly() && !io.InputQueueCharacters.empty()) {
|
||||
|
|
|
@ -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-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/aes.h"
|
||||
#include "common/config.h"
|
||||
#include "common/logging/log.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;
|
||||
|
@ -54,7 +69,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit
|
|||
return false;
|
||||
}
|
||||
|
||||
std::array<CryptoPP::byte, 16> user_key{};
|
||||
std::array<u8, 16> user_key{};
|
||||
hexToBytes(user_key_str.c_str(), user_key.data());
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
std::string xml_name = entry.entry_name;
|
||||
size_t pos = xml_name.find("ESFM");
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include "common/endian.h"
|
||||
#include "common/io_file.h"
|
||||
#include "common/types.h"
|
||||
#include "core/crypto/crypto.h"
|
||||
|
||||
struct TrpHeader {
|
||||
u32_be magic; // (0xDCA24D00)
|
||||
|
@ -37,10 +36,9 @@ public:
|
|||
void GetNPcommID(const std::filesystem::path& trophyPath, int index);
|
||||
|
||||
private:
|
||||
Crypto crypto;
|
||||
std::vector<u8> NPcommID = std::vector<u8>(12);
|
||||
std::array<u8, 16> np_comm_id{};
|
||||
std::array<u8, 16> esfmIv{};
|
||||
std::filesystem::path trpFilesPath;
|
||||
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 patch_path = mount->host_path;
|
||||
patch_path += "-UPDATE";
|
||||
if (!std::filesystem::exists(patch_path)) {
|
||||
patch_path = mount->host_path;
|
||||
patch_path += "-patch";
|
||||
}
|
||||
patch_path /= rel_path;
|
||||
|
||||
if ((corrected_path.starts_with("/app0") || corrected_path.starts_with("/hostapp")) &&
|
||||
|
|
|
@ -191,6 +191,7 @@ int PS4_SYSV_ABI sceAudioOutGetPortState(s32 handle, OrbisAudioOutPortState* sta
|
|||
case OrbisAudioOutPort::Main:
|
||||
case OrbisAudioOutPort::Bgm:
|
||||
case OrbisAudioOutPort::Voice:
|
||||
case OrbisAudioOutPort::Audio3d:
|
||||
state->output = 1;
|
||||
state->channel = port.format_info.num_channels > 2 ? 2 : port.format_info.num_channels;
|
||||
break;
|
||||
|
@ -316,7 +317,7 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
|
|||
return ORBIS_AUDIO_OUT_ERROR_NOT_INIT;
|
||||
}
|
||||
if ((port_type < OrbisAudioOutPort::Main || port_type > OrbisAudioOutPort::Padspk) &&
|
||||
(port_type != OrbisAudioOutPort::Aux)) {
|
||||
(port_type != OrbisAudioOutPort::Audio3d && port_type != OrbisAudioOutPort::Aux)) {
|
||||
LOG_ERROR(Lib_AudioOut, "Invalid port type");
|
||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT_TYPE;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,15 @@ class PortBackend;
|
|||
constexpr s32 SCE_AUDIO_OUT_NUM_PORTS = 22;
|
||||
constexpr s32 SCE_AUDIO_OUT_VOLUME_0DB = 32768; // max volume value
|
||||
|
||||
enum class OrbisAudioOutPort { Main = 0, Bgm = 1, Voice = 2, Personal = 3, Padspk = 4, Aux = 127 };
|
||||
enum class OrbisAudioOutPort {
|
||||
Main = 0,
|
||||
Bgm = 1,
|
||||
Voice = 2,
|
||||
Personal = 3,
|
||||
Padspk = 4,
|
||||
Audio3d = 126,
|
||||
Aux = 127,
|
||||
};
|
||||
|
||||
enum class OrbisAudioOutParamFormat : u32 {
|
||||
S16Mono = 0,
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <SDL3/SDL_audio.h>
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/audio/audioout.h"
|
||||
#include "core/libraries/audio/audioout_error.h"
|
||||
#include "core/libraries/audio3d/audio3d.h"
|
||||
#include "core/libraries/audio3d/audio3d_error.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
|
@ -10,331 +15,577 @@
|
|||
|
||||
namespace Libraries::Audio3d {
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dInitialize(s64 iReserved) {
|
||||
LOG_INFO(Lib_Audio3d, "iReserved = {}", iReserved);
|
||||
return ORBIS_OK;
|
||||
static constexpr u32 AUDIO3D_SAMPLE_RATE = 48000;
|
||||
|
||||
static constexpr AudioOut::OrbisAudioOutParamFormat AUDIO3D_OUTPUT_FORMAT =
|
||||
AudioOut::OrbisAudioOutParamFormat::S16Stereo;
|
||||
static constexpr u32 AUDIO3D_OUTPUT_NUM_CHANNELS = 2;
|
||||
static constexpr u32 AUDIO3D_OUTPUT_BUFFER_FRAMES = 0x100;
|
||||
|
||||
static std::unique_ptr<Audio3dState> state;
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutClose(const s32 handle) {
|
||||
LOG_INFO(Lib_Audio3d, "called, handle = {}", handle);
|
||||
return AudioOut::sceAudioOutClose(handle);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dTerminate() {
|
||||
// TODO: When not initialized or some ports still open, return ORBIS_AUDIO3D_ERROR_NOT_READY
|
||||
LOG_INFO(Lib_Audio3d, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void PS4_SYSV_ABI sceAudio3dGetDefaultOpenParameters(OrbisAudio3dOpenParameters* parameters) {
|
||||
if (parameters == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "Invalid OpenParameters ptr");
|
||||
return;
|
||||
}
|
||||
|
||||
parameters->size_this = sizeof(OrbisAudio3dOpenParameters);
|
||||
parameters->granularity = 256;
|
||||
parameters->rate = OrbisAudio3dRate::Rate48000;
|
||||
parameters->max_objects = 512;
|
||||
parameters->queue_depth = 2;
|
||||
parameters->buffer_mode = OrbisAudio3dBufferMode::AdvanceAndPush;
|
||||
parameters->num_beds = 2;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortOpen(OrbisUserServiceUserId iUserId,
|
||||
const OrbisAudio3dOpenParameters* pParameters,
|
||||
OrbisAudio3dPortId* pId) {
|
||||
LOG_INFO(Lib_Audio3d, "iUserId = {}", iUserId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortClose(OrbisAudio3dPortId uiPortId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortSetAttribute(OrbisAudio3dPortId uiPortId,
|
||||
OrbisAudio3dAttributeId uiAttributeId,
|
||||
const void* pAttribute, size_t szAttribute) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiAttributeId = {}, szAttribute = {}", uiPortId,
|
||||
uiAttributeId, szAttribute);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortFlush(OrbisAudio3dPortId uiPortId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortAdvance(OrbisAudio3dPortId uiPortId) {
|
||||
LOG_TRACE(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortPush(OrbisAudio3dPortId uiPortId, OrbisAudio3dBlocking eBlocking) {
|
||||
LOG_TRACE(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetAttributesSupported(OrbisAudio3dPortId uiPortId,
|
||||
OrbisAudio3dAttributeId* pCapabilities,
|
||||
u32* pNumCapabilities) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetQueueLevel(OrbisAudio3dPortId uiPortId, u32* pQueueLevel,
|
||||
u32* pQueueAvailable) {
|
||||
LOG_TRACE(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dObjectReserve(OrbisAudio3dPortId uiPortId, OrbisAudio3dObjectId* pId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dObjectUnreserve(OrbisAudio3dPortId uiPortId,
|
||||
OrbisAudio3dObjectId uiObjectId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiObjectId = {}", uiPortId, uiObjectId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dObjectSetAttributes(OrbisAudio3dPortId uiPortId,
|
||||
OrbisAudio3dObjectId uiObjectId,
|
||||
size_t szNumAttributes,
|
||||
const OrbisAudio3dAttribute* pAttributeArray) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiObjectId = {}, szNumAttributes = {}", uiPortId,
|
||||
uiObjectId, szNumAttributes);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dBedWrite(OrbisAudio3dPortId uiPortId, u32 uiNumChannels,
|
||||
OrbisAudio3dFormat eFormat, const void* pBuffer,
|
||||
u32 uiNumSamples) {
|
||||
LOG_TRACE(Lib_Audio3d, "uiPortId = {}, uiNumChannels = {}, uiNumSamples = {}", uiPortId,
|
||||
uiNumChannels, uiNumSamples);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dBedWrite2(OrbisAudio3dPortId uiPortId, u32 uiNumChannels,
|
||||
OrbisAudio3dFormat eFormat, const void* pBuffer,
|
||||
u32 uiNumSamples, OrbisAudio3dOutputRoute eOutputRoute,
|
||||
bool bRestricted) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}, uiNumChannels = {}, uiNumSamples = {}, bRestricted = {}",
|
||||
uiPortId, uiNumChannels, uiNumSamples, bRestricted);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
size_t PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMemorySize(u32 uiNumSpeakers, bool bIs3d) {
|
||||
LOG_INFO(Lib_Audio3d, "uiNumSpeakers = {}, bIs3d = {}", uiNumSpeakers, bIs3d);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI
|
||||
sceAudio3dCreateSpeakerArray(OrbisAudio3dSpeakerArrayHandle* pHandle,
|
||||
const OrbisAudio3dSpeakerArrayParameters* pParameters) {
|
||||
if (pHandle == nullptr || pParameters == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid SpeakerArray parameters");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
LOG_INFO(Lib_Audio3d, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dDeleteSpeakerArray(OrbisAudio3dSpeakerArrayHandle handle) {
|
||||
if (handle == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid SpeakerArrayHandle");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
LOG_INFO(Lib_Audio3d, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients(OrbisAudio3dSpeakerArrayHandle handle,
|
||||
OrbisAudio3dPosition pos, float fSpread,
|
||||
float* pCoefficients,
|
||||
u32 uiNumCoefficients) {
|
||||
LOG_INFO(Lib_Audio3d, "fSpread = {}, uiNumCoefficients = {}", fSpread, uiNumCoefficients);
|
||||
if (handle == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid SpeakerArrayHandle");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients2(OrbisAudio3dSpeakerArrayHandle handle,
|
||||
OrbisAudio3dPosition pos, float fSpread,
|
||||
float* pCoefficients,
|
||||
u32 uiNumCoefficients, bool bHeightAware,
|
||||
float fDownmixSpreadRadius) {
|
||||
s32 PS4_SYSV_ABI
|
||||
sceAudio3dAudioOutOpen(const OrbisAudio3dPortId port_id, const OrbisUserServiceUserId user_id,
|
||||
s32 type, const s32 index, const u32 len, const u32 freq,
|
||||
const AudioOut::OrbisAudioOutParamExtendedInformation param) {
|
||||
LOG_INFO(Lib_Audio3d,
|
||||
"fSpread = {}, uiNumCoefficients = {}, bHeightAware = {}, fDownmixSpreadRadius = {}",
|
||||
fSpread, uiNumCoefficients, bHeightAware, fDownmixSpreadRadius);
|
||||
if (handle == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid SpeakerArrayHandle");
|
||||
"called, port_id = {}, user_id = {}, type = {}, index = {}, len = {}, freq = {}",
|
||||
port_id, user_id, type, index, len, freq);
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
if (len != state->ports[port_id].parameters.granularity) {
|
||||
LOG_ERROR(Lib_Audio3d, "len != state->ports[port_id].parameters.granularity");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return sceAudioOutOpen(user_id, static_cast<AudioOut::OrbisAudioOutPort>(type), index, len,
|
||||
freq, param);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutput(const s32 handle, void* ptr) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called, handle = {}, ptr = {}", handle, ptr);
|
||||
|
||||
if (!ptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "!ptr");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (handle < 0 || (handle & 0xFFFF) > 25) {
|
||||
LOG_ERROR(Lib_Audio3d, "handle < 0 || (handle & 0xFFFF) > 25");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
return AudioOut::sceAudioOutOutput(handle, ptr);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutputs(AudioOut::OrbisAudioOutOutputParam* param,
|
||||
const u32 num) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called, param = {}, num = {}", static_cast<void*>(param), num);
|
||||
|
||||
if (!param || !num) {
|
||||
LOG_ERROR(Lib_Audio3d, "!param || !num");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return AudioOut::sceAudioOutOutputs(param, num);
|
||||
}
|
||||
|
||||
static s32 PortQueueAudio(Port& port, const OrbisAudio3dPcm& pcm, const u32 num_channels) {
|
||||
// Audio3d output is configured for stereo signed 16-bit PCM. Convert the data to match.
|
||||
const SDL_AudioSpec src_spec = {
|
||||
.format = pcm.format == OrbisAudio3dFormat::ORBIS_AUDIO3D_FORMAT_S16 ? SDL_AUDIO_S16LE
|
||||
: SDL_AUDIO_F32LE,
|
||||
.channels = static_cast<int>(num_channels),
|
||||
.freq = AUDIO3D_SAMPLE_RATE,
|
||||
};
|
||||
constexpr SDL_AudioSpec dst_spec = {
|
||||
.format = SDL_AUDIO_S16LE,
|
||||
.channels = AUDIO3D_OUTPUT_NUM_CHANNELS,
|
||||
.freq = AUDIO3D_SAMPLE_RATE,
|
||||
};
|
||||
const auto src_size = pcm.num_samples *
|
||||
(pcm.format == OrbisAudio3dFormat::ORBIS_AUDIO3D_FORMAT_S16 ? 2 : 4) *
|
||||
num_channels;
|
||||
|
||||
u8* dst_data;
|
||||
int dst_len;
|
||||
if (!SDL_ConvertAudioSamples(&src_spec, static_cast<u8*>(pcm.sample_buffer),
|
||||
static_cast<int>(src_size), &dst_spec, &dst_data, &dst_len)) {
|
||||
LOG_ERROR(Lib_Audio3d, "SDL_ConvertAudioSamples failed: {}", SDL_GetError());
|
||||
return ORBIS_AUDIO3D_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
port.queue.emplace_back(AudioData{
|
||||
.sample_buffer = dst_data,
|
||||
.num_samples = pcm.num_samples,
|
||||
});
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dBedWrite(const OrbisAudio3dPortId port_id, const u32 num_channels,
|
||||
const OrbisAudio3dFormat format, void* buffer,
|
||||
const u32 num_samples) {
|
||||
return sceAudio3dBedWrite2(port_id, num_channels, format, buffer, num_samples,
|
||||
OrbisAudio3dOutputRoute::ORBIS_AUDIO3D_OUTPUT_BOTH, false);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dBedWrite2(const OrbisAudio3dPortId port_id, const u32 num_channels,
|
||||
const OrbisAudio3dFormat format, void* buffer,
|
||||
const u32 num_samples,
|
||||
const OrbisAudio3dOutputRoute output_route,
|
||||
const bool restricted) {
|
||||
LOG_DEBUG(
|
||||
Lib_Audio3d,
|
||||
"called, port_id = {}, num_channels = {}, format = {}, num_samples = {}, output_route "
|
||||
"= {}, restricted = {}",
|
||||
port_id, num_channels, magic_enum::enum_name(format), num_samples,
|
||||
magic_enum::enum_name(output_route), restricted);
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
if (output_route > OrbisAudio3dOutputRoute::ORBIS_AUDIO3D_OUTPUT_BOTH) {
|
||||
LOG_ERROR(Lib_Audio3d, "output_route > ORBIS_AUDIO3D_OUTPUT_BOTH");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (format > OrbisAudio3dFormat::ORBIS_AUDIO3D_FORMAT_FLOAT) {
|
||||
LOG_ERROR(Lib_Audio3d, "format > ORBIS_AUDIO3D_FORMAT_FLOAT");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (num_channels != 2 && num_channels != 8) {
|
||||
LOG_ERROR(Lib_Audio3d, "num_channels != 2 && num_channels != 8");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!buffer || !num_samples) {
|
||||
LOG_ERROR(Lib_Audio3d, "!buffer || !num_samples");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (format == OrbisAudio3dFormat::ORBIS_AUDIO3D_FORMAT_FLOAT) {
|
||||
if ((reinterpret_cast<uintptr_t>(buffer) & 3) != 0) {
|
||||
LOG_ERROR(Lib_Audio3d, "buffer & 3 != 0");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
} else if (format == OrbisAudio3dFormat::ORBIS_AUDIO3D_FORMAT_S16) {
|
||||
if ((reinterpret_cast<uintptr_t>(buffer) & 1) != 0) {
|
||||
LOG_ERROR(Lib_Audio3d, "buffer & 1 != 0");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
return PortQueueAudio(state->ports[port_id],
|
||||
OrbisAudio3dPcm{
|
||||
.format = format,
|
||||
.sample_buffer = buffer,
|
||||
.num_samples = num_samples,
|
||||
},
|
||||
num_channels);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dCreateSpeakerArray() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dDeleteSpeakerArray() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetDefaultOpenParameters(OrbisAudio3dOpenParameters* params) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called");
|
||||
if (params) {
|
||||
*params = OrbisAudio3dOpenParameters{
|
||||
.size_this = 0x20,
|
||||
.granularity = 0x100,
|
||||
.rate = OrbisAudio3dRate::ORBIS_AUDIO3D_RATE_48000,
|
||||
.max_objects = 512,
|
||||
.queue_depth = 2,
|
||||
.buffer_mode = OrbisAudio3dBufferMode::ORBIS_AUDIO3D_BUFFER_ADVANCE_AND_PUSH,
|
||||
};
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOpen(OrbisAudio3dPortId uiPortId, OrbisUserServiceUserId userId,
|
||||
s32 type, s32 index, u32 len, u32 freq, u32 param) {
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMemorySize() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients2() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dInitialize(const s64 reserved) {
|
||||
LOG_INFO(Lib_Audio3d, "called, reserved = {}", reserved);
|
||||
|
||||
if (reserved != 0) {
|
||||
LOG_ERROR(Lib_Audio3d, "reserved != 0");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (state) {
|
||||
LOG_ERROR(Lib_Audio3d, "already initialized");
|
||||
return ORBIS_AUDIO3D_ERROR_NOT_READY;
|
||||
}
|
||||
|
||||
state = std::make_unique<Audio3dState>();
|
||||
|
||||
if (const auto init_ret = AudioOut::sceAudioOutInit();
|
||||
init_ret < 0 && init_ret != ORBIS_AUDIO_OUT_ERROR_ALREADY_INIT) {
|
||||
return init_ret;
|
||||
}
|
||||
|
||||
AudioOut::OrbisAudioOutParamExtendedInformation ext_info{};
|
||||
ext_info.data_format.Assign(AUDIO3D_OUTPUT_FORMAT);
|
||||
state->audio_out_handle =
|
||||
AudioOut::sceAudioOutOpen(0xFF, AudioOut::OrbisAudioOutPort::Audio3d, 0,
|
||||
AUDIO3D_OUTPUT_BUFFER_FRAMES, AUDIO3D_SAMPLE_RATE, ext_info);
|
||||
if (state->audio_out_handle < 0) {
|
||||
return state->audio_out_handle;
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectReserve(const OrbisAudio3dPortId port_id,
|
||||
OrbisAudio3dObjectId* object_id) {
|
||||
LOG_INFO(Lib_Audio3d, "called, port_id = {}, object_id = {}", port_id,
|
||||
static_cast<void*>(object_id));
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
if (!object_id) {
|
||||
LOG_ERROR(Lib_Audio3d, "!object_id");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
static int last_id = 0;
|
||||
*object_id = ++last_id;
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectSetAttributes(const OrbisAudio3dPortId port_id,
|
||||
OrbisAudio3dObjectId object_id,
|
||||
const u64 num_attributes,
|
||||
const OrbisAudio3dAttribute* attribute_array) {
|
||||
LOG_DEBUG(Lib_Audio3d,
|
||||
"called, port_id = {}, object_id = {}, num_attributes = {}, attribute_array = {}",
|
||||
port_id, object_id, num_attributes, fmt::ptr(attribute_array));
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
auto& port = state->ports[port_id];
|
||||
|
||||
for (u64 i = 0; i < num_attributes; i++) {
|
||||
const auto& attribute = attribute_array[i];
|
||||
|
||||
switch (attribute.attribute_id) {
|
||||
case OrbisAudio3dAttributeId::ORBIS_AUDIO3D_ATTRIBUTE_PCM: {
|
||||
const auto pcm = static_cast<OrbisAudio3dPcm*>(attribute.value);
|
||||
// Object audio has 1 channel.
|
||||
if (const auto ret = PortQueueAudio(port, *pcm, 1); ret != ORBIS_OK) {
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR(Lib_Audio3d, "Unsupported attribute ID: {:#x}",
|
||||
static_cast<u32>(attribute.attribute_id));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectUnreserve() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortAdvance(const OrbisAudio3dPortId port_id) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called, port_id = {}", port_id);
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
if (state->ports[port_id].parameters.buffer_mode ==
|
||||
OrbisAudio3dBufferMode::ORBIS_AUDIO3D_BUFFER_NO_ADVANCE) {
|
||||
LOG_ERROR(Lib_Audio3d, "port doesn't have advance capability");
|
||||
return ORBIS_AUDIO3D_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
auto& port = state->ports[port_id];
|
||||
if (port.current_buffer.has_value()) {
|
||||
// Free existing buffer before replacing.
|
||||
SDL_free(port.current_buffer->sample_buffer);
|
||||
}
|
||||
|
||||
if (!port.queue.empty()) {
|
||||
port.current_buffer = port.queue.front();
|
||||
port.queue.pop_front();
|
||||
} else {
|
||||
// Nothing to advance to.
|
||||
LOG_DEBUG(Lib_Audio3d, "Port advance with no buffer queued");
|
||||
port.current_buffer = std::nullopt;
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortClose() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortCreate() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortDestroy() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortFlush() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortFreeState() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetAttributesSupported() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetList() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetParameters() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetQueueLevel(const OrbisAudio3dPortId port_id, u32* queue_level,
|
||||
u32* queue_available) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called, port_id = {}, queue_level = {}, queue_available = {}", port_id,
|
||||
static_cast<void*>(queue_level), static_cast<void*>(queue_available));
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
if (!queue_level && !queue_available) {
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const auto port = state->ports[port_id];
|
||||
const size_t size = port.queue.size();
|
||||
|
||||
if (queue_level) {
|
||||
*queue_level = size;
|
||||
}
|
||||
|
||||
if (queue_available) {
|
||||
*queue_available = port.parameters.queue_depth - size;
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetState() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetStatus() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortOpen(const OrbisUserServiceUserId user_id,
|
||||
const OrbisAudio3dOpenParameters* parameters,
|
||||
OrbisAudio3dPortId* port_id) {
|
||||
LOG_INFO(Lib_Audio3d, "called, user_id = {}, parameters = {}, id = {}", user_id,
|
||||
static_cast<const void*>(parameters), static_cast<void*>(port_id));
|
||||
|
||||
if (!state) {
|
||||
LOG_ERROR(Lib_Audio3d, "!initialized");
|
||||
return ORBIS_AUDIO3D_ERROR_NOT_READY;
|
||||
}
|
||||
|
||||
if (!parameters || !port_id) {
|
||||
LOG_ERROR(Lib_Audio3d, "!parameters || !id");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const int id = static_cast<int>(state->ports.size()) + 1;
|
||||
|
||||
if (id > 3) {
|
||||
LOG_ERROR(Lib_Audio3d, "id > 3");
|
||||
return ORBIS_AUDIO3D_ERROR_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
*port_id = id;
|
||||
std::memcpy(&state->ports[id].parameters, parameters, sizeof(OrbisAudio3dOpenParameters));
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortPush(const OrbisAudio3dPortId port_id,
|
||||
const OrbisAudio3dBlocking blocking) {
|
||||
LOG_DEBUG(Lib_Audio3d, "called, port_id = {}, blocking = {}", port_id,
|
||||
magic_enum::enum_name(blocking));
|
||||
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
const auto& port = state->ports[port_id];
|
||||
if (port.parameters.buffer_mode !=
|
||||
OrbisAudio3dBufferMode::ORBIS_AUDIO3D_BUFFER_ADVANCE_AND_PUSH) {
|
||||
LOG_ERROR(Lib_Audio3d, "port doesn't have push capability");
|
||||
return ORBIS_AUDIO3D_ERROR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!port.current_buffer.has_value()) {
|
||||
// Nothing to push.
|
||||
LOG_DEBUG(Lib_Audio3d, "Port push with no buffer ready");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// TODO: Implement asynchronous blocking mode.
|
||||
const auto& [sample_buffer, num_samples] = port.current_buffer.value();
|
||||
return AudioOut::sceAudioOutOutput(state->audio_out_handle, sample_buffer);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortQueryDebug() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortSetAttribute(const OrbisAudio3dPortId port_id,
|
||||
const OrbisAudio3dAttributeId attribute_id,
|
||||
void* attribute, const u64 attribute_size) {
|
||||
LOG_INFO(Lib_Audio3d,
|
||||
"uiPortId = {}, userId = {}, type = {}, index = {}, len = {}, freq = {}, param = {}",
|
||||
uiPortId, userId, type, index, len, freq, param);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
"called, port_id = {}, attribute_id = {}, attribute = {}, attribute_size = {}",
|
||||
port_id, static_cast<u32>(attribute_id), attribute, attribute_size);
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutClose(s32 handle) {
|
||||
LOG_INFO(Lib_Audio3d, "handle = {}", handle);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
if (!state->ports.contains(port_id)) {
|
||||
LOG_ERROR(Lib_Audio3d, "!state->ports.contains(port_id)");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PORT;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutput(s32 handle, const void* ptr) {
|
||||
LOG_TRACE(Lib_Audio3d, "handle = {}", handle);
|
||||
if (ptr == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid Output ptr");
|
||||
if (!attribute) {
|
||||
LOG_ERROR(Lib_Audio3d, "!attribute");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutputs(::Libraries::AudioOut::OrbisAudioOutOutputParam* param,
|
||||
s32 num) {
|
||||
LOG_INFO(Lib_Audio3d, "num = {}", num);
|
||||
if (param == nullptr) {
|
||||
LOG_ERROR(Lib_Audio3d, "invalid OutputParam ptr");
|
||||
return ORBIS_AUDIO3D_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortCreate(u32 uiGranularity, OrbisAudio3dRate eRate, s64 iReserved,
|
||||
OrbisAudio3dPortId* pId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiGranularity = {}, iReserved = {}", uiGranularity, iReserved);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortDestroy(OrbisAudio3dPortId uiPortId) {
|
||||
LOG_INFO(Lib_Audio3d, "uiPortId = {}", uiPortId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// Audio3dPrivate
|
||||
|
||||
const char* PS4_SYSV_ABI sceAudio3dStrError(int iErrorCode) {
|
||||
LOG_ERROR(Lib_Audio3d, "(PRIVATE) called, iErrorCode = {}", iErrorCode);
|
||||
return "NOT_IMPLEMENTED";
|
||||
}
|
||||
|
||||
// Audio3dDebug
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortQueryDebug() {
|
||||
LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortQueryDebug called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetList() {
|
||||
LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortGetList called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetParameters() {
|
||||
LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortGetParameters called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetState() {
|
||||
LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortGetState called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortFreeState() {
|
||||
LOG_WARNING(Lib_Audio3d, "(DEBUG) sceAudio3dPortFreeState called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// Unknown
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetBufferLevel() {
|
||||
s32 PS4_SYSV_ABI sceAudio3dReportRegisterHandler() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dPortGetStatus() {
|
||||
s32 PS4_SYSV_ABI sceAudio3dReportUnregisterHandler() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dReportRegisterHandler() {
|
||||
s32 PS4_SYSV_ABI sceAudio3dSetGpuRenderer() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dReportUnregisterHandler() {
|
||||
s32 PS4_SYSV_ABI sceAudio3dStrError() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudio3dSetGpuRenderer() {
|
||||
s32 PS4_SYSV_ABI sceAudio3dTerminate() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceAudio3d(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("pZlOm1aF3aA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutClose);
|
||||
LIB_FUNCTION("ucEsi62soTo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutOpen);
|
||||
LIB_FUNCTION("7NYEzJ9SJbM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dAudioOutOutput);
|
||||
LIB_FUNCTION("HbxYY27lK6E", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dAudioOutOutputs);
|
||||
LIB_FUNCTION("9tEwE0GV0qo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dBedWrite);
|
||||
LIB_FUNCTION("xH4Q9UILL3o", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dBedWrite2);
|
||||
LIB_FUNCTION("lvWMW6vEqFU", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dCreateSpeakerArray);
|
||||
LIB_FUNCTION("8hm6YdoQgwg", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dDeleteSpeakerArray);
|
||||
LIB_FUNCTION("Im+jOoa5WAI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetDefaultOpenParameters);
|
||||
LIB_FUNCTION("kEqqyDkmgdI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetSpeakerArrayMemorySize);
|
||||
LIB_FUNCTION("-R1DukFq7Dk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetSpeakerArrayMixCoefficients);
|
||||
LIB_FUNCTION("-Re+pCWvwjQ", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetSpeakerArrayMixCoefficients2);
|
||||
LIB_FUNCTION("-pzYDZozm+M", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortQueryDebug);
|
||||
LIB_FUNCTION("1HXxo-+1qCw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dObjectUnreserve);
|
||||
LIB_FUNCTION("UmCvjSmuZIw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dInitialize);
|
||||
LIB_FUNCTION("jO2tec4dJ2M", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dObjectReserve);
|
||||
LIB_FUNCTION("4uyHN9q4ZeU", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dObjectSetAttributes);
|
||||
LIB_FUNCTION("7NYEzJ9SJbM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dAudioOutOutput);
|
||||
LIB_FUNCTION("8hm6YdoQgwg", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dDeleteSpeakerArray);
|
||||
LIB_FUNCTION("1HXxo-+1qCw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dObjectUnreserve);
|
||||
LIB_FUNCTION("lw0qrdSjZt8", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortAdvance);
|
||||
LIB_FUNCTION("OyVqOeVNtSk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortClose);
|
||||
LIB_FUNCTION("UHFOgVNz0kk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortCreate);
|
||||
LIB_FUNCTION("Mw9mRQtWepY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortDestroy);
|
||||
LIB_FUNCTION("ZOGrxWLgQzE", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortFlush);
|
||||
LIB_FUNCTION("uJ0VhGcxCTQ", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortFreeState);
|
||||
LIB_FUNCTION("9ZA23Ia46Po", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortGetAttributesSupported);
|
||||
LIB_FUNCTION("9tEwE0GV0qo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dBedWrite);
|
||||
LIB_FUNCTION("Aacl5qkRU6U", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dStrError);
|
||||
LIB_FUNCTION("CKHlRW2E9dA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetState);
|
||||
LIB_FUNCTION("HbxYY27lK6E", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dAudioOutOutputs);
|
||||
LIB_FUNCTION("Im+jOoa5WAI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetDefaultOpenParameters);
|
||||
LIB_FUNCTION("Mw9mRQtWepY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortDestroy);
|
||||
LIB_FUNCTION("OyVqOeVNtSk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortClose);
|
||||
LIB_FUNCTION("QfNXBrKZeI0", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dReportRegisterHandler);
|
||||
LIB_FUNCTION("QqgTQQdzEMY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortGetBufferLevel);
|
||||
LIB_FUNCTION("SEggctIeTcI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetList);
|
||||
LIB_FUNCTION("UHFOgVNz0kk", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortCreate);
|
||||
LIB_FUNCTION("UmCvjSmuZIw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dInitialize);
|
||||
LIB_FUNCTION("VEVhZ9qd4ZY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortPush);
|
||||
LIB_FUNCTION("WW1TS2iz5yc", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dTerminate);
|
||||
LIB_FUNCTION("XeDDK0xJWQA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortOpen);
|
||||
LIB_FUNCTION("YaaDbDwKpFM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortGetQueueLevel);
|
||||
LIB_FUNCTION("Yq9bfUQ0uJg", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortSetAttribute);
|
||||
LIB_FUNCTION("ZOGrxWLgQzE", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortFlush);
|
||||
LIB_FUNCTION("flPcUaXVXcw", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortGetParameters);
|
||||
LIB_FUNCTION("YaaDbDwKpFM", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortGetQueueLevel);
|
||||
LIB_FUNCTION("CKHlRW2E9dA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetState);
|
||||
LIB_FUNCTION("iRX6GJs9tvE", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortGetStatus);
|
||||
LIB_FUNCTION("jO2tec4dJ2M", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dObjectReserve);
|
||||
LIB_FUNCTION("kEqqyDkmgdI", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dGetSpeakerArrayMemorySize);
|
||||
LIB_FUNCTION("lvWMW6vEqFU", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dCreateSpeakerArray);
|
||||
LIB_FUNCTION("lw0qrdSjZt8", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortAdvance);
|
||||
LIB_FUNCTION("pZlOm1aF3aA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutClose);
|
||||
LIB_FUNCTION("XeDDK0xJWQA", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortOpen);
|
||||
LIB_FUNCTION("VEVhZ9qd4ZY", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortPush);
|
||||
LIB_FUNCTION("-pzYDZozm+M", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortQueryDebug);
|
||||
LIB_FUNCTION("Yq9bfUQ0uJg", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dPortSetAttribute);
|
||||
LIB_FUNCTION("QfNXBrKZeI0", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dReportRegisterHandler);
|
||||
LIB_FUNCTION("psv2gbihC1A", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dReportUnregisterHandler);
|
||||
LIB_FUNCTION("uJ0VhGcxCTQ", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dPortFreeState);
|
||||
LIB_FUNCTION("ucEsi62soTo", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dAudioOutOpen);
|
||||
LIB_FUNCTION("xH4Q9UILL3o", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dBedWrite2);
|
||||
LIB_FUNCTION("yEYXcbAGK14", "libSceAudio3d", 1, "libSceAudio3d", 1, 1,
|
||||
sceAudio3dSetGpuRenderer);
|
||||
LIB_FUNCTION("Aacl5qkRU6U", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dStrError);
|
||||
LIB_FUNCTION("WW1TS2iz5yc", "libSceAudio3d", 1, "libSceAudio3d", 1, 1, sceAudio3dTerminate);
|
||||
};
|
||||
|
||||
} // namespace Libraries::Audio3d
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
|
||||
#include <stddef.h>
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/audio/audioout.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
|
@ -13,123 +15,131 @@ class SymbolsResolver;
|
|||
|
||||
namespace Libraries::Audio3d {
|
||||
|
||||
class Audio3d;
|
||||
|
||||
using OrbisUserServiceUserId = s32;
|
||||
using OrbisAudio3dPortId = u32;
|
||||
using OrbisAudio3dObjectId = u32;
|
||||
using OrbisAudio3dAttributeId = u32;
|
||||
|
||||
enum class OrbisAudio3dFormat {
|
||||
S16 = 0,
|
||||
Float = 1,
|
||||
enum class OrbisAudio3dRate : u32 {
|
||||
ORBIS_AUDIO3D_RATE_48000 = 0,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dRate {
|
||||
Rate48000 = 0,
|
||||
enum class OrbisAudio3dBufferMode : u32 {
|
||||
ORBIS_AUDIO3D_BUFFER_NO_ADVANCE = 0,
|
||||
ORBIS_AUDIO3D_BUFFER_ADVANCE_NO_PUSH = 1,
|
||||
ORBIS_AUDIO3D_BUFFER_ADVANCE_AND_PUSH = 2,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dBufferMode { NoAdvance = 0, AdvanceNoPush = 1, AdvanceAndPush = 2 };
|
||||
|
||||
enum class OrbisAudio3dBlocking {
|
||||
Async = 0,
|
||||
Sync = 1,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dPassthrough {
|
||||
None = 0,
|
||||
Left = 1,
|
||||
Right = 2,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dOutputRoute {
|
||||
Both = 0,
|
||||
HmuOnly = 1,
|
||||
TvOnly = 2,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dAmbisonics : u32 {
|
||||
None = ~0U,
|
||||
W = 0,
|
||||
X = 1,
|
||||
Y = 2,
|
||||
Z = 3,
|
||||
R = 4,
|
||||
S = 5,
|
||||
T = 6,
|
||||
U = 7,
|
||||
V = 8,
|
||||
K = 9,
|
||||
L = 10,
|
||||
M = 11,
|
||||
N = 12,
|
||||
O = 13,
|
||||
P = 14,
|
||||
Q = 15
|
||||
};
|
||||
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributePcm = 0x00000001;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributePriority = 0x00000002;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributePosition = 0x00000003;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeSpread = 0x00000004;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeGain = 0x00000005;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributePassthrough = 0x00000006;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeResetState = 0x00000007;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeApplicationSpecific = 0x00000008;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeAmbisonics = 0x00000009;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeRestricted = 0x0000000A;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeOutputRoute = 0x0000000B;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeLateReverbLevel = 0x00010001;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeDownmixSpreadRadius = 0x00010002;
|
||||
static const OrbisAudio3dAttributeId s_sceAudio3dAttributeDownmixSpreadHeightAware = 0x00010003;
|
||||
|
||||
struct OrbisAudio3dSpeakerArray;
|
||||
using OrbisAudio3dSpeakerArrayHandle = OrbisAudio3dSpeakerArray*; // head
|
||||
|
||||
struct OrbisAudio3dOpenParameters {
|
||||
size_t size_this;
|
||||
u64 size_this;
|
||||
u32 granularity;
|
||||
OrbisAudio3dRate rate;
|
||||
u32 max_objects;
|
||||
u32 queue_depth;
|
||||
OrbisAudio3dBufferMode buffer_mode;
|
||||
char padding[32];
|
||||
int : 32;
|
||||
u32 num_beds;
|
||||
};
|
||||
|
||||
struct OrbisAudio3dAttribute {
|
||||
OrbisAudio3dAttributeId attribute_id;
|
||||
char padding[32];
|
||||
const void* p_value;
|
||||
size_t value;
|
||||
enum class OrbisAudio3dFormat : u32 {
|
||||
ORBIS_AUDIO3D_FORMAT_S16 = 0,
|
||||
ORBIS_AUDIO3D_FORMAT_FLOAT = 1,
|
||||
};
|
||||
|
||||
struct OrbisAudio3dPosition {
|
||||
float fX;
|
||||
float fY;
|
||||
float fZ;
|
||||
enum class OrbisAudio3dOutputRoute : u32 {
|
||||
ORBIS_AUDIO3D_OUTPUT_BOTH = 0,
|
||||
ORBIS_AUDIO3D_OUTPUT_HMU_ONLY = 1,
|
||||
ORBIS_AUDIO3D_OUTPUT_TV_ONLY = 2,
|
||||
};
|
||||
|
||||
enum class OrbisAudio3dBlocking : u32 {
|
||||
ORBIS_AUDIO3D_BLOCKING_ASYNC = 0,
|
||||
ORBIS_AUDIO3D_BLOCKING_SYNC = 1,
|
||||
};
|
||||
|
||||
struct OrbisAudio3dPcm {
|
||||
OrbisAudio3dFormat format;
|
||||
const void* sample_buffer;
|
||||
void* sample_buffer;
|
||||
u32 num_samples;
|
||||
};
|
||||
|
||||
struct OrbisAudio3dSpeakerArrayParameters {
|
||||
OrbisAudio3dPosition* speaker_position;
|
||||
u32 num_speakers;
|
||||
bool is_3d;
|
||||
void* buffer;
|
||||
size_t size;
|
||||
enum class OrbisAudio3dAttributeId : u32 {
|
||||
ORBIS_AUDIO3D_ATTRIBUTE_PCM = 1,
|
||||
};
|
||||
|
||||
struct OrbisAudio3dApplicationSpecific {
|
||||
size_t size_this;
|
||||
u8 application_specific[32];
|
||||
using OrbisAudio3dPortId = u32;
|
||||
using OrbisAudio3dObjectId = u32;
|
||||
|
||||
struct OrbisAudio3dAttribute {
|
||||
OrbisAudio3dAttributeId attribute_id;
|
||||
int : 32;
|
||||
void* value;
|
||||
u64 value_size;
|
||||
};
|
||||
|
||||
void PS4_SYSV_ABI sceAudio3dGetDefaultOpenParameters(OrbisAudio3dOpenParameters* sParameters);
|
||||
struct AudioData {
|
||||
u8* sample_buffer;
|
||||
u32 num_samples;
|
||||
};
|
||||
|
||||
struct Port {
|
||||
OrbisAudio3dOpenParameters parameters{};
|
||||
std::deque<AudioData> queue; // Only stores PCM buffers for now
|
||||
std::optional<AudioData> current_buffer{};
|
||||
};
|
||||
|
||||
struct Audio3dState {
|
||||
std::unordered_map<OrbisAudio3dPortId, Port> ports;
|
||||
s32 audio_out_handle;
|
||||
};
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutClose(s32 handle);
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOpen(OrbisAudio3dPortId port_id, OrbisUserServiceUserId user_id,
|
||||
s32 type, s32 index, u32 len, u32 freq,
|
||||
AudioOut::OrbisAudioOutParamExtendedInformation param);
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutput(s32 handle, void* ptr);
|
||||
s32 PS4_SYSV_ABI sceAudio3dAudioOutOutputs(AudioOut::OrbisAudioOutOutputParam* param, u32 num);
|
||||
s32 PS4_SYSV_ABI sceAudio3dBedWrite(OrbisAudio3dPortId port_id, u32 num_channels,
|
||||
OrbisAudio3dFormat format, void* buffer, u32 num_samples);
|
||||
s32 PS4_SYSV_ABI sceAudio3dBedWrite2(OrbisAudio3dPortId port_id, u32 num_channels,
|
||||
OrbisAudio3dFormat format, void* buffer, u32 num_samples,
|
||||
OrbisAudio3dOutputRoute output_route, bool restricted);
|
||||
s32 PS4_SYSV_ABI sceAudio3dCreateSpeakerArray();
|
||||
s32 PS4_SYSV_ABI sceAudio3dDeleteSpeakerArray();
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetDefaultOpenParameters(OrbisAudio3dOpenParameters* params);
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMemorySize();
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients();
|
||||
s32 PS4_SYSV_ABI sceAudio3dGetSpeakerArrayMixCoefficients2();
|
||||
s32 PS4_SYSV_ABI sceAudio3dInitialize(s64 reserved);
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectReserve(OrbisAudio3dPortId port_id,
|
||||
OrbisAudio3dObjectId* object_id);
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectSetAttributes(OrbisAudio3dPortId port_id,
|
||||
OrbisAudio3dObjectId object_id, u64 num_attributes,
|
||||
const OrbisAudio3dAttribute* attribute_array);
|
||||
s32 PS4_SYSV_ABI sceAudio3dObjectUnreserve();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortAdvance(OrbisAudio3dPortId port_id);
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortClose();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortCreate();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortDestroy();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortFlush();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortFreeState();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetAttributesSupported();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetList();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetParameters();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetQueueLevel(OrbisAudio3dPortId port_id, u32* queue_level,
|
||||
u32* queue_available);
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetState();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortGetStatus();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortOpen(OrbisUserServiceUserId user_id,
|
||||
const OrbisAudio3dOpenParameters* parameters,
|
||||
OrbisAudio3dPortId* port_id);
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortPush(OrbisAudio3dPortId port_id, OrbisAudio3dBlocking blocking);
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortQueryDebug();
|
||||
s32 PS4_SYSV_ABI sceAudio3dPortSetAttribute(OrbisAudio3dPortId port_id,
|
||||
OrbisAudio3dAttributeId attribute_id, void* attribute,
|
||||
u64 attribute_size);
|
||||
s32 PS4_SYSV_ABI sceAudio3dReportRegisterHandler();
|
||||
s32 PS4_SYSV_ABI sceAudio3dReportUnregisterHandler();
|
||||
s32 PS4_SYSV_ABI sceAudio3dSetGpuRenderer();
|
||||
s32 PS4_SYSV_ABI sceAudio3dStrError();
|
||||
s32 PS4_SYSV_ABI sceAudio3dTerminate();
|
||||
|
||||
void RegisterlibSceAudio3d(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Audio3d
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "core/libraries/error_codes.h"
|
||||
|
||||
constexpr int ORBIS_AUDIO3D_ERROR_UNKNOWN = 0x80EA0001;
|
||||
constexpr int ORBIS_AUDIO3D_ERROR_INVALID_PORT = 0x80EA0002;
|
||||
constexpr int ORBIS_AUDIO3D_ERROR_INVALID_OBJECT = 0x80EA0003;
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "audio3d.h"
|
||||
|
||||
namespace Libraries::Audio3d {
|
||||
|
||||
class Audio3d {
|
||||
public:
|
||||
private:
|
||||
using OrbisAudio3dPluginId = u32;
|
||||
};
|
||||
|
||||
} // namespace Libraries::Audio3d
|
|
@ -9,29 +9,29 @@
|
|||
|
||||
namespace Libraries::DiscMap {
|
||||
|
||||
int PS4_SYSV_ABI sceDiscMapGetPackageSize() {
|
||||
LOG_WARNING(Lib_DiscMap, "(DUMMY) called");
|
||||
int PS4_SYSV_ABI sceDiscMapGetPackageSize(s64 fflags, int* ret1, int* ret2) {
|
||||
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD() {
|
||||
LOG_WARNING(Lib_DiscMap, "(DUMMY) called");
|
||||
int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD(char* path, s64 offset, s64 nbytes, int* ret) {
|
||||
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI Func_7C980FFB0AA27E7A() {
|
||||
LOG_ERROR(Lib_DiscMap, "(STUBBED) called");
|
||||
int PS4_SYSV_ABI Func_7C980FFB0AA27E7A(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
|
||||
int* ret2) {
|
||||
*flags = 0;
|
||||
*ret1 = 0;
|
||||
*ret2 = 0;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9() {
|
||||
LOG_ERROR(Lib_DiscMap, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
|
||||
int* ret2) {
|
||||
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI Func_E7EBCE96E92F91F8() {
|
||||
LOG_ERROR(Lib_DiscMap, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
||||
}
|
||||
|
||||
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym) {
|
||||
|
|
|
@ -10,10 +10,12 @@ class SymbolsResolver;
|
|||
}
|
||||
namespace Libraries::DiscMap {
|
||||
|
||||
int PS4_SYSV_ABI sceDiscMapGetPackageSize();
|
||||
int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD();
|
||||
int PS4_SYSV_ABI Func_7C980FFB0AA27E7A();
|
||||
int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9();
|
||||
int PS4_SYSV_ABI sceDiscMapGetPackageSize(s64 fflags, int* ret1, int* ret2);
|
||||
int PS4_SYSV_ABI sceDiscMapIsRequestOnHDD(char* path, s64 offset, s64 nbytes, int* ret);
|
||||
int PS4_SYSV_ABI Func_7C980FFB0AA27E7A(char* path, s64 offset, s64 nbytes, int* flags, int* ret1,
|
||||
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();
|
||||
|
||||
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym);
|
||||
|
|
|
@ -2804,7 +2804,7 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) {
|
|||
liverpool = std::make_unique<AmdGpu::Liverpool>();
|
||||
presenter = std::make_unique<Vulkan::Presenter>(*g_window, liverpool.get());
|
||||
|
||||
const int result = sceKernelGetCompiledSdkVersion(&sdk_version);
|
||||
const s32 result = sceKernelGetCompiledSdkVersion(&sdk_version);
|
||||
if (result != ORBIS_OK) {
|
||||
sdk_version = 0;
|
||||
}
|
||||
|
|
|
@ -83,9 +83,35 @@ int PS4_SYSV_ABI sceImeDialogGetPanelPositionAndForm() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeDialogGetPanelSize() {
|
||||
LOG_ERROR(Lib_ImeDialog, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
Error PS4_SYSV_ABI sceImeDialogGetPanelSize(const OrbisImeDialogParam* param, u32* width,
|
||||
u32* height) {
|
||||
LOG_INFO(Lib_ImeDialog, "called");
|
||||
|
||||
if (!width || !height) {
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
switch (param->type) {
|
||||
case OrbisImeType::Default:
|
||||
case OrbisImeType::BasicLatin:
|
||||
case OrbisImeType::Url:
|
||||
case OrbisImeType::Mail:
|
||||
*width = 500; // original: 793
|
||||
if (True(param->option & OrbisImeDialogOption::Multiline)) {
|
||||
*height = 300; // original: 576
|
||||
} else {
|
||||
*height = 150; // original: 476
|
||||
}
|
||||
break;
|
||||
case OrbisImeType::Number:
|
||||
*width = 370;
|
||||
*height = 470;
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Lib_ImeDialog, "Unknown OrbisImeType: {}", (u32)param->type);
|
||||
return Error::INVALID_PARAM;
|
||||
}
|
||||
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeDialogGetPanelSizeExtended() {
|
||||
|
|
|
@ -13,7 +13,7 @@ class SymbolsResolver;
|
|||
|
||||
namespace Libraries::ImeDialog {
|
||||
|
||||
constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 0x78;
|
||||
constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 2048;
|
||||
|
||||
enum class Error : u32 {
|
||||
OK = 0x0,
|
||||
|
@ -155,7 +155,8 @@ Error PS4_SYSV_ABI sceImeDialogForceClose();
|
|||
Error PS4_SYSV_ABI sceImeDialogForTestFunction();
|
||||
int PS4_SYSV_ABI sceImeDialogGetCurrentStarState();
|
||||
int PS4_SYSV_ABI sceImeDialogGetPanelPositionAndForm();
|
||||
int PS4_SYSV_ABI sceImeDialogGetPanelSize();
|
||||
Error PS4_SYSV_ABI sceImeDialogGetPanelSize(const OrbisImeDialogParam* param, u32* width,
|
||||
u32* height);
|
||||
int PS4_SYSV_ABI sceImeDialogGetPanelSizeExtended();
|
||||
Error PS4_SYSV_ABI sceImeDialogGetResult(OrbisImeDialogResult* result);
|
||||
OrbisImeDialogStatus PS4_SYSV_ABI sceImeDialogGetStatus();
|
||||
|
|
20
src/core/libraries/kernel/debug.cpp
Normal file
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
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
|
|
@ -61,6 +61,18 @@ struct SceKernelEvent {
|
|||
void* udata = nullptr; /* opaque user data identifier */
|
||||
};
|
||||
|
||||
struct OrbisVideoOutEventHint {
|
||||
u64 event_id : 8;
|
||||
u64 video_id : 8;
|
||||
u64 flip_arg : 48;
|
||||
};
|
||||
|
||||
struct OrbisVideoOutEventData {
|
||||
u64 time : 12;
|
||||
u64 count : 4;
|
||||
u64 flip_arg : 48;
|
||||
};
|
||||
|
||||
struct EqueueEvent {
|
||||
SceKernelEvent event;
|
||||
void* data = nullptr;
|
||||
|
@ -84,19 +96,18 @@ struct EqueueEvent {
|
|||
|
||||
void TriggerDisplay(void* data) {
|
||||
is_triggered = true;
|
||||
auto hint = reinterpret_cast<u64>(data);
|
||||
if (hint != 0) {
|
||||
auto hint_h = static_cast<u32>(hint >> 8) & 0xFFFFFF;
|
||||
auto ident_h = static_cast<u32>(event.ident >> 40);
|
||||
if ((static_cast<u32>(hint) & 0xFF) == event.ident && event.ident != 0xFE &&
|
||||
((hint_h ^ ident_h) & 0xFF) == 0) {
|
||||
if (data != nullptr) {
|
||||
auto event_data = static_cast<OrbisVideoOutEventData>(event.data);
|
||||
auto event_hint_raw = reinterpret_cast<u64>(data);
|
||||
auto event_hint = static_cast<OrbisVideoOutEventHint>(event_hint_raw);
|
||||
if (event_hint.event_id == event.ident && event.ident != 0xfe) {
|
||||
auto time = Common::FencedRDTSC();
|
||||
auto mask = 0xF000;
|
||||
if ((static_cast<u32>(event.data) & 0xF000) != 0xF000) {
|
||||
mask = (static_cast<u32>(event.data) + 0x1000) & 0xF000;
|
||||
auto counter = event_data.count;
|
||||
if (counter != 0xf) {
|
||||
counter++;
|
||||
}
|
||||
event.data = (mask | static_cast<u64>(static_cast<u32>(time) & 0xFFF) |
|
||||
(hint & 0xFFFFFFFFFFFF0000));
|
||||
event.data =
|
||||
(time & 0xfff) | (counter << 0xc) | (event_hint_raw & 0xffffffffffff0000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -65,10 +65,10 @@ constexpr int ORBIS_KERNEL_O_DSYNC = 0x1000;
|
|||
constexpr int ORBIS_KERNEL_O_DIRECT = 0x00010000;
|
||||
constexpr int ORBIS_KERNEL_O_DIRECTORY = 0x00020000;
|
||||
|
||||
s64 PS4_SYSV_ABI sceKernelWrite(int d, const void* buf, size_t nbytes);
|
||||
s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes);
|
||||
s64 PS4_SYSV_ABI sceKernelPread(int d, 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 sceKernelWrite(s32 fd, const void* buf, size_t nbytes);
|
||||
s64 PS4_SYSV_ABI sceKernelRead(s32 fd, void* buf, size_t nbytes);
|
||||
s64 PS4_SYSV_ABI sceKernelPread(s32 fd, 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);
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "common/va_ctx.h"
|
||||
#include "core/file_sys/fs.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/kernel/debug.h"
|
||||
#include "core/libraries/kernel/equeue.h"
|
||||
#include "core/libraries/kernel/file_system.h"
|
||||
#include "core/libraries/kernel/kernel.h"
|
||||
|
@ -85,17 +86,23 @@ int ErrnoToSceKernelError(int error) {
|
|||
}
|
||||
|
||||
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) {
|
||||
case EPERM:
|
||||
g_posix_errno = POSIX_EPERM;
|
||||
break;
|
||||
case EAGAIN:
|
||||
g_posix_errno = POSIX_EAGAIN;
|
||||
case ENOENT:
|
||||
g_posix_errno = POSIX_ENOENT;
|
||||
break;
|
||||
case EDEADLK:
|
||||
g_posix_errno = POSIX_EDEADLK;
|
||||
break;
|
||||
case ENOMEM:
|
||||
g_posix_errno = POSIX_ENOMEM;
|
||||
break;
|
||||
case EACCES:
|
||||
g_posix_errno = POSIX_EACCES;
|
||||
break;
|
||||
case EINVAL:
|
||||
g_posix_errno = POSIX_EINVAL;
|
||||
break;
|
||||
|
@ -105,13 +112,14 @@ void SetPosixErrno(int e) {
|
|||
case ERANGE:
|
||||
g_posix_errno = POSIX_ERANGE;
|
||||
break;
|
||||
case EDEADLK:
|
||||
g_posix_errno = POSIX_EDEADLK;
|
||||
case EAGAIN:
|
||||
g_posix_errno = POSIX_EAGAIN;
|
||||
break;
|
||||
case ETIMEDOUT:
|
||||
g_posix_errno = POSIX_ETIMEDOUT;
|
||||
break;
|
||||
default:
|
||||
LOG_WARNING(Kernel, "Unhandled errno {}", e);
|
||||
g_posix_errno = e;
|
||||
}
|
||||
}
|
||||
|
@ -133,14 +141,6 @@ void PS4_SYSV_ABI sceLibcHeapGetTraceInfo(HeapInfoInfo* info) {
|
|||
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 {
|
||||
u32 timeLow;
|
||||
u16 timeMid;
|
||||
|
@ -220,6 +220,7 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
|||
Libraries::Kernel::RegisterProcess(sym);
|
||||
Libraries::Kernel::RegisterException(sym);
|
||||
Libraries::Kernel::RegisterAio(sym);
|
||||
Libraries::Kernel::RegisterDebug(sym);
|
||||
|
||||
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
||||
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("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail);
|
||||
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", "libScePosix", 1, "libkernel", 1, 1, posix_getpagesize);
|
||||
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
|
||||
sceLibcHeapGetTraceInfo);
|
||||
LIB_FUNCTION("FxVZqBAA7ks", "libkernel", 1, "libkernel", 1, 1, ps4__write);
|
||||
LIB_FUNCTION("FN4gaPmuFV8", "libScePosix", 1, "libkernel", 1, 1, ps4__write);
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
namespace Libraries::Kernel {
|
||||
|
||||
u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() {
|
||||
LOG_WARNING(Kernel_Vmm, "called");
|
||||
LOG_TRACE(Kernel_Vmm, "called");
|
||||
const auto* memory = Core::Memory::Instance();
|
||||
return memory->GetTotalDirectSize();
|
||||
}
|
||||
|
@ -106,12 +106,6 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE
|
|||
if (physAddrOut == nullptr || sizeOut == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
if (searchEnd > sceKernelGetDirectMemorySize()) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
if (searchEnd <= searchStart) {
|
||||
return ORBIS_KERNEL_ERROR_ENOMEM;
|
||||
}
|
||||
|
||||
auto* memory = Core::Memory::Instance();
|
||||
|
||||
|
|
|
@ -127,6 +127,67 @@ int PS4_SYSV_ABI sceKernelGetModuleInfoFromAddr(VAddr addr, int flags,
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelGetModuleInfo(s32 handle, Core::OrbisKernelModuleInfo* info) {
|
||||
if (info == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EFAULT;
|
||||
}
|
||||
if (info->st_size != sizeof(Core::OrbisKernelModuleInfo)) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
auto* linker = Common::Singleton<Core::Linker>::Instance();
|
||||
auto* module = linker->GetModule(handle);
|
||||
if (module == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_ESRCH;
|
||||
}
|
||||
*info = module->GetModuleInfo();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelGetModuleInfoInternal(s32 handle, Core::OrbisKernelModuleInfoEx* info) {
|
||||
if (info == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EFAULT;
|
||||
}
|
||||
if (info->st_size != sizeof(Core::OrbisKernelModuleInfoEx)) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
auto* linker = Common::Singleton<Core::Linker>::Instance();
|
||||
auto* module = linker->GetModule(handle);
|
||||
if (module == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_ESRCH;
|
||||
}
|
||||
*info = module->GetModuleInfoEx();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelGetModuleList(s32* handles, u64 num_array, u64* out_count) {
|
||||
if (handles == nullptr || out_count == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EFAULT;
|
||||
}
|
||||
|
||||
auto* linker = Common::Singleton<Core::Linker>::Instance();
|
||||
u64 count = 0;
|
||||
auto* module = linker->GetModule(count);
|
||||
while (module != nullptr && count < num_array) {
|
||||
handles[count] = count;
|
||||
count++;
|
||||
module = linker->GetModule(count);
|
||||
}
|
||||
|
||||
if (count == num_array && module != nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_ENOMEM;
|
||||
}
|
||||
|
||||
*out_count = count;
|
||||
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) {
|
||||
LIB_FUNCTION("WB66evu8bsU", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCompiledSdkVersion);
|
||||
LIB_FUNCTION("WslcK1FQcGI", "libkernel", 1, "libkernel", 1, 1, sceKernelIsNeoMode);
|
||||
|
@ -136,6 +197,10 @@ void RegisterProcess(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", 1, 1, sceKernelDlsym);
|
||||
LIB_FUNCTION("RpQJJVKTiFM", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoForUnwind);
|
||||
LIB_FUNCTION("f7KBOafysXo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoFromAddr);
|
||||
LIB_FUNCTION("kUpgrXIrz7Q", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfo);
|
||||
LIB_FUNCTION("HZO7xOos4xc", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoInternal);
|
||||
LIB_FUNCTION("IuxnUuXk6Bg", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleList);
|
||||
LIB_FUNCTION("6Z83sYWFlA8", "libkernel", 1, "libkernel", 1, 1, exit);
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "core/libraries/kernel/orbis_error.h"
|
||||
#include "core/libraries/kernel/threads/exception.h"
|
||||
#include "core/libraries/kernel/threads/pthread.h"
|
||||
#include "core/libraries/libs.h"
|
||||
|
@ -148,13 +149,19 @@ int PS4_SYSV_ABI sceKernelRaiseException(PthreadT thread, int signum) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelDebugRaiseException() {
|
||||
UNREACHABLE();
|
||||
s32 PS4_SYSV_ABI sceKernelDebugRaiseException(s32 error, s64 unk) {
|
||||
if (unk != 0) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
UNREACHABLE_MSG("error {:#x}", error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode() {
|
||||
UNREACHABLE();
|
||||
s32 PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode(s32 error, s64 unk) {
|
||||
if (unk != 0) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
UNREACHABLE_MSG("error {:#x}", error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -163,7 +170,7 @@ void RegisterException(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("WkwEd3N7w0Y", "libkernel_unity", 1, "libkernel", 1, 1,
|
||||
sceKernelInstallExceptionHandler);
|
||||
LIB_FUNCTION("Qhv5ARAoOEc", "libkernel_unity", 1, "libkernel", 1, 1,
|
||||
sceKernelRemoveExceptionHandler)
|
||||
sceKernelRemoveExceptionHandler);
|
||||
LIB_FUNCTION("OMDRKKAZ8I4", "libkernel", 1, "libkernel", 1, 1, sceKernelDebugRaiseException);
|
||||
LIB_FUNCTION("zE-wXIZjLoM", "libkernel", 1, "libkernel", 1, 1,
|
||||
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("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
|
||||
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));
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "core/libraries/network/netctl.h"
|
||||
#include "core/libraries/network/ssl.h"
|
||||
#include "core/libraries/network/ssl2.h"
|
||||
#include "core/libraries/np_auth/np_auth.h"
|
||||
#include "core/libraries/np_common/np_common.h"
|
||||
#include "core/libraries/np_manager/np_manager.h"
|
||||
#include "core/libraries/np_party/np_party.h"
|
||||
|
@ -50,6 +51,7 @@
|
|||
#include "core/libraries/system/sysmodule.h"
|
||||
#include "core/libraries/system/systemservice.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
#include "core/libraries/ulobjmgr/ulobjmgr.h"
|
||||
#include "core/libraries/usbd/usbd.h"
|
||||
#include "core/libraries/videodec/videodec.h"
|
||||
#include "core/libraries/videodec/videodec2.h"
|
||||
|
@ -87,6 +89,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
|||
Libraries::NpScore::RegisterlibSceNpScore(sym);
|
||||
Libraries::NpTrophy::RegisterlibSceNpTrophy(sym);
|
||||
Libraries::NpWebApi::RegisterlibSceNpWebApi(sym);
|
||||
Libraries::NpAuth::RegisterlibSceNpAuth(sym);
|
||||
Libraries::ScreenShot::RegisterlibSceScreenShot(sym);
|
||||
Libraries::AppContent::RegisterlibSceAppContent(sym);
|
||||
Libraries::PngDec::RegisterlibScePngDec(sym);
|
||||
|
@ -115,6 +118,8 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
|||
Libraries::NpParty::RegisterlibSceNpParty(sym);
|
||||
Libraries::Zlib::RegisterlibSceZlib(sym);
|
||||
Libraries::Hmd::RegisterlibSceHmd(sym);
|
||||
Libraries::DiscMap::RegisterlibSceDiscMap(sym);
|
||||
Libraries::Ulobjmgr::RegisterlibSceUlobjmgr(sym);
|
||||
}
|
||||
|
||||
} // namespace Libraries
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
namespace Libraries::Move {
|
||||
|
||||
int PS4_SYSV_ABI sceMoveOpen() {
|
||||
LOG_ERROR(Lib_Move, "(STUBBED) called");
|
||||
LOG_TRACE(Lib_Move, "(STUBBED) called");
|
||||
return ORBIS_FAIL;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,11 @@ int PS4_SYSV_ABI sceMoveGetDeviceInfo() {
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceMoveReadStateLatest() {
|
||||
LOG_TRACE(Lib_Move, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceMoveReadStateRecent() {
|
||||
LOG_TRACE(Lib_Move, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
|
@ -36,6 +41,7 @@ int PS4_SYSV_ABI sceMoveInit() {
|
|||
void RegisterlibSceMove(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("HzC60MfjJxU", "libSceMove", 1, "libSceMove", 1, 1, sceMoveOpen);
|
||||
LIB_FUNCTION("GWXTyxs4QbE", "libSceMove", 1, "libSceMove", 1, 1, sceMoveGetDeviceInfo);
|
||||
LIB_FUNCTION("ttU+JOhShl4", "libSceMove", 1, "libSceMove", 1, 1, sceMoveReadStateLatest);
|
||||
LIB_FUNCTION("f2bcpK6kJfg", "libSceMove", 1, "libSceMove", 1, 1, sceMoveReadStateRecent);
|
||||
LIB_FUNCTION("tsZi60H4ypY", "libSceMove", 1, "libSceMove", 1, 1, sceMoveTerm);
|
||||
LIB_FUNCTION("j1ITE-EoJmE", "libSceMove", 1, "libSceMove", 1, 1, sceMoveInit);
|
||||
|
|
|
@ -5,21 +5,416 @@
|
|||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.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_geom.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 {
|
||||
|
||||
int PS4_SYSV_ABI sceNgs2CalcWaveformBlock() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
// Ngs2
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2CalcWaveformBlock(const OrbisNgs2WaveformFormat* format, u32 samplePos,
|
||||
u32 numSamples, OrbisNgs2WaveformBlock* outBlock) {
|
||||
LOG_ERROR(Lib_Ngs2, "samplePos = {}, numSamples = {}", samplePos, numSamples);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceNgs2CustomRackGetModuleInfo() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
s32 PS4_SYSV_ABI sceNgs2GetWaveformFrameInfo(const OrbisNgs2WaveformFormat* format,
|
||||
u32* outFrameSize, u32* outNumFrameSamples,
|
||||
u32* outUnitsPerFrame, u32* outNumDelaySamples) {
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2ParseWaveformData(const void* data, size_t dataSize,
|
||||
OrbisNgs2WaveformInfo* outInfo) {
|
||||
LOG_ERROR(Lib_Ngs2, "dataSize = {}", dataSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2ParseWaveformFile(const char* path, u64 offset,
|
||||
OrbisNgs2WaveformInfo* outInfo) {
|
||||
LOG_ERROR(Lib_Ngs2, "path = {}, offset = {}", path, offset);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2ParseWaveformUser(OrbisNgs2ParseReadHandler handler, uintptr_t userData,
|
||||
OrbisNgs2WaveformInfo* outInfo) {
|
||||
LOG_ERROR(Lib_Ngs2, "userData = {}", userData);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackCreate(OrbisNgs2Handle systemHandle, u32 rackId,
|
||||
const OrbisNgs2RackOption* option,
|
||||
const OrbisNgs2ContextBufferInfo* bufferInfo,
|
||||
OrbisNgs2Handle* outHandle) {
|
||||
LOG_ERROR(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_ERROR(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) {
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackGetInfo(OrbisNgs2Handle rackHandle, OrbisNgs2RackInfo* outInfo,
|
||||
size_t infoSize) {
|
||||
LOG_ERROR(Lib_Ngs2, "infoSize = {}", infoSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackGetUserData(OrbisNgs2Handle rackHandle, uintptr_t* outUserData) {
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackGetVoiceHandle(OrbisNgs2Handle rackHandle, u32 voiceIndex,
|
||||
OrbisNgs2Handle* outHandle) {
|
||||
LOG_DEBUG(Lib_Ngs2, "(STUBBED) voiceIndex = {}", voiceIndex);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackLock(OrbisNgs2Handle rackHandle) {
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackQueryBufferSize(u32 rackId, const OrbisNgs2RackOption* option,
|
||||
OrbisNgs2ContextBufferInfo* outBufferInfo) {
|
||||
LOG_ERROR(Lib_Ngs2, "rackId = {}", rackId);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackSetUserData(OrbisNgs2Handle rackHandle, uintptr_t userData) {
|
||||
LOG_ERROR(Lib_Ngs2, "userData = {}", userData);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2RackUnlock(OrbisNgs2Handle rackHandle) {
|
||||
LOG_ERROR(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;
|
||||
result = SystemSetup(option, &bufferInfo, 0, 0);
|
||||
if (result >= 0) {
|
||||
uintptr_t sysUserData = allocator->userData;
|
||||
result = Core::ExecuteGuest(hostAlloc, &bufferInfo);
|
||||
if (result >= 0) {
|
||||
OrbisNgs2Handle* handleCopy = outHandle;
|
||||
result = SystemSetup(option, &bufferInfo, hostFree, handleCopy);
|
||||
if (result < 0) {
|
||||
if (hostFree) {
|
||||
Core::ExecuteGuest(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_ERROR(Lib_Ngs2, "maxHandles = {}", maxHandles);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2SystemEnumRackHandles(OrbisNgs2Handle systemHandle,
|
||||
OrbisNgs2Handle* aOutHandle, u32 maxHandles) {
|
||||
LOG_ERROR(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_ERROR(Lib_Ngs2, "infoSize = {}", infoSize);
|
||||
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_ERROR(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_ERROR(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_DEBUG(Lib_Ngs2, "(STUBBED) 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_ERROR(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_ERROR(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_ERROR(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_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceControl(OrbisNgs2Handle voiceHandle,
|
||||
const OrbisNgs2VoiceParamHeader* paramList) {
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceGetMatrixInfo(OrbisNgs2Handle voiceHandle, u32 matrixId,
|
||||
OrbisNgs2VoiceMatrixInfo* outInfo, size_t outInfoSize) {
|
||||
LOG_ERROR(Lib_Ngs2, "matrixId = {}, outInfoSize = {}", matrixId, outInfoSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceGetOwner(OrbisNgs2Handle voiceHandle, OrbisNgs2Handle* outRackHandle,
|
||||
u32* outVoiceId) {
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceGetPortInfo(OrbisNgs2Handle voiceHandle, u32 port,
|
||||
OrbisNgs2VoicePortInfo* outInfo, size_t outInfoSize) {
|
||||
LOG_ERROR(Lib_Ngs2, "port = {}, outInfoSize = {}", port, outInfoSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceGetState(OrbisNgs2Handle voiceHandle, OrbisNgs2VoiceState* outState,
|
||||
size_t stateSize) {
|
||||
LOG_ERROR(Lib_Ngs2, "stateSize = {}", stateSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2VoiceGetStateFlags(OrbisNgs2Handle voiceHandle, u32* outStateFlags) {
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// Ngs2Custom
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2CustomRackGetModuleInfo(OrbisNgs2Handle rackHandle, u32 moduleIndex,
|
||||
OrbisNgs2CustomModuleInfo* outInfo,
|
||||
size_t infoSize) {
|
||||
LOG_ERROR(Lib_Ngs2, "moduleIndex = {}, infoSize = {}", moduleIndex, infoSize);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// Ngs2Geom
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2GeomResetListenerParam(OrbisNgs2GeomListenerParam* outListenerParam) {
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2GeomResetSourceParam(OrbisNgs2GeomSourceParam* outSourceParam) {
|
||||
LOG_ERROR(Lib_Ngs2, "called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2GeomCalcListener(const OrbisNgs2GeomListenerParam* param,
|
||||
OrbisNgs2GeomListenerWork* outWork, u32 flags) {
|
||||
LOG_ERROR(Lib_Ngs2, "flags = {}", flags);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2GeomApply(const OrbisNgs2GeomListenerWork* listener,
|
||||
const OrbisNgs2GeomSourceParam* source,
|
||||
OrbisNgs2GeomAttribute* outAttrib, u32 flags) {
|
||||
LOG_ERROR(Lib_Ngs2, "flags = {}", flags);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
// Ngs2Pan
|
||||
|
||||
s32 PS4_SYSV_ABI sceNgs2PanInit(OrbisNgs2PanWork* work, const float* aSpeakerAngle, float unitAngle,
|
||||
u32 numSpeakers) {
|
||||
LOG_ERROR(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_ERROR(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() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
|
@ -35,31 +430,6 @@ int PS4_SYSV_ABI sceNgs2FftQuerySize() {
|
|||
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() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
|
@ -80,71 +450,6 @@ int PS4_SYSV_ABI sceNgs2ModuleQueueEnumItems() {
|
|||
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() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
|
@ -155,116 +460,21 @@ int PS4_SYSV_ABI sceNgs2RackRunCommands() {
|
|||
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() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
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() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceNgs2SystemSetGrainSamples() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceNgs2SystemSetLoudThreshold() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
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() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
|
@ -300,36 +510,6 @@ int PS4_SYSV_ABI sceNgs2StreamRunCommands() {
|
|||
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() {
|
||||
LOG_ERROR(Lib_Ngs2, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "core/libraries/ngs2/ngs2_impl.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
|
@ -12,60 +16,257 @@ class SymbolsResolver;
|
|||
|
||||
namespace Libraries::Ngs2 {
|
||||
|
||||
class Ngs2;
|
||||
using OrbisNgs2ParseReadHandler = s32 PS4_SYSV_ABI (*)(uintptr_t user_data, u32 offset, void* data,
|
||||
size_t size);
|
||||
|
||||
using SceNgs2Handle = Ngs2*;
|
||||
|
||||
enum class SceNgs2HandleType : u32 {
|
||||
System = 0,
|
||||
enum class OrbisNgs2HandleType : u32 {
|
||||
Invalid = 0,
|
||||
System = 1,
|
||||
Rack = 2,
|
||||
Voice = 3,
|
||||
VoiceControl = 6
|
||||
};
|
||||
|
||||
struct Ngs2Handle {
|
||||
void* selfPointer;
|
||||
void* dataPointer;
|
||||
std::atomic<u32>* atomicPtr;
|
||||
u32 handleType;
|
||||
u32 flags_unk;
|
||||
static const int ORBIS_NGS2_MAX_VOICE_CHANNELS = 8;
|
||||
static const int ORBIS_NGS2_WAVEFORM_INFO_MAX_BLOCKS = 4;
|
||||
static const int ORBIS_NGS2_MAX_MATRIX_LEVELS =
|
||||
(ORBIS_NGS2_MAX_VOICE_CHANNELS * ORBIS_NGS2_MAX_VOICE_CHANNELS);
|
||||
|
||||
u32 uid;
|
||||
u16 maxGrainSamples;
|
||||
u16 minGrainSamples;
|
||||
u16 currentGrainSamples;
|
||||
u16 numGrainSamples;
|
||||
u16 unknown2;
|
||||
struct OrbisNgs2WaveformFormat {
|
||||
u32 waveformType;
|
||||
u32 numChannels;
|
||||
u32 sampleRate;
|
||||
u32 unknown3;
|
||||
|
||||
void* flushMutex;
|
||||
u32 flushMutexInitialized;
|
||||
void* processMutex;
|
||||
u32 processMutexInitialized;
|
||||
|
||||
// Linked list pointers for system list
|
||||
Ngs2Handle* prev;
|
||||
Ngs2Handle* next;
|
||||
u32 configData;
|
||||
u32 frameOffset;
|
||||
u32 frameMargin;
|
||||
};
|
||||
|
||||
struct SystemOptions {
|
||||
char padding[6];
|
||||
s32 maxGrainSamples;
|
||||
s32 numGrainSamples;
|
||||
s32 sampleRate;
|
||||
struct OrbisNgs2WaveformBlock {
|
||||
u32 dataOffset;
|
||||
u32 dataSize;
|
||||
u32 numRepeats;
|
||||
u32 numSkipSamples;
|
||||
u32 numSamples;
|
||||
u32 reserved;
|
||||
uintptr_t userData;
|
||||
};
|
||||
|
||||
struct SystemState {
|
||||
// TODO
|
||||
struct OrbisNgs2WaveformInfo {
|
||||
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 {
|
||||
void** top;
|
||||
void* base;
|
||||
void* curr;
|
||||
size_t usedSize;
|
||||
size_t totalSize;
|
||||
size_t alignment;
|
||||
char isVerifyEnabled;
|
||||
char padding[7];
|
||||
struct OrbisNgs2EnvelopePoint {
|
||||
u32 curve;
|
||||
u32 duration;
|
||||
float height;
|
||||
};
|
||||
|
||||
struct OrbisNgs2UserFxProcessContext {
|
||||
float** aChannelData;
|
||||
uintptr_t userData0;
|
||||
uintptr_t userData1;
|
||||
uintptr_t userData2;
|
||||
u32 flags;
|
||||
u32 numChannels;
|
||||
u32 numGrainSamples;
|
||||
u32 sampleRate;
|
||||
};
|
||||
|
||||
using OrbisNgs2UserFxProcessHandler = s32 PS4_SYSV_ABI (*)(OrbisNgs2UserFxProcessContext* context);
|
||||
|
||||
struct OrbisNgs2UserFx2SetupContext {
|
||||
void* common;
|
||||
void* param;
|
||||
void* work;
|
||||
uintptr_t userData;
|
||||
u32 maxVoices;
|
||||
u32 voiceIndex;
|
||||
u64 reserved[4];
|
||||
};
|
||||
|
||||
using OrbisNgs2UserFx2SetupHandler = s32 PS4_SYSV_ABI (*)(OrbisNgs2UserFx2SetupContext* context);
|
||||
|
||||
struct OrbisNgs2UserFx2CleanupContext {
|
||||
void* common;
|
||||
void* param;
|
||||
void* work;
|
||||
uintptr_t userData;
|
||||
u32 maxVoices;
|
||||
u32 voiceIndex;
|
||||
u64 reserved[4];
|
||||
};
|
||||
|
||||
using OrbisNgs2UserFx2CleanupHandler =
|
||||
s32 PS4_SYSV_ABI (*)(OrbisNgs2UserFx2CleanupContext* context);
|
||||
|
||||
struct OrbisNgs2UserFx2ControlContext {
|
||||
const void* data;
|
||||
size_t dataSize;
|
||||
void* common;
|
||||
void* param;
|
||||
uintptr_t userData;
|
||||
u64 reserved[4];
|
||||
};
|
||||
|
||||
using OrbisNgs2UserFx2ControlHandler =
|
||||
s32 PS4_SYSV_ABI (*)(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];
|
||||
};
|
||||
|
||||
using OrbisNgs2UserFx2ProcessHandler =
|
||||
s32 PS4_SYSV_ABI (*)(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;
|
||||
};
|
||||
|
||||
using OrbisNgs2VoiceCallbackHandler = void PS4_SYSV_ABI (*)(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);
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "audio3d_error.h"
|
||||
#include "audio3d_impl.h"
|
||||
#include "ngs2_error.h"
|
||||
#include "ngs2_impl.h"
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/kernel/kernel.h"
|
||||
|
||||
using namespace Libraries::Kernel;
|
||||
|
||||
namespace Libraries::Audio3d {} // namespace Libraries::Audio3d
|
||||
namespace Libraries::Ngs2 {} // namespace Libraries::Ngs2
|
444
src/core/libraries/ngs2/ngs2_custom.h
Normal file
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
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
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
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
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 {
|
||||
|
||||
s32 Ngs2::ReportInvalid(Ngs2Handle* handle, u32 handle_type) const {
|
||||
uintptr_t hAddress = reinterpret_cast<uintptr_t>(handle);
|
||||
switch (handle_type) {
|
||||
s32 HandleReportInvalid(OrbisNgs2Handle handle, u32 handleType) {
|
||||
switch (handleType) {
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
default:
|
||||
LOG_ERROR(Lib_Ngs2, "Invalid handle {}", hAddress);
|
||||
LOG_ERROR(Lib_Ngs2, "Invalid handle {}", handle);
|
||||
return ORBIS_NGS2_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
s32 Ngs2::HandleSetup(Ngs2Handle* handle, void* data, std::atomic<u32>* atomic, u32 type,
|
||||
u32 flags) {
|
||||
handle->dataPointer = data;
|
||||
handle->atomicPtr = atomic;
|
||||
handle->handleType = type;
|
||||
handle->flags_unk = flags;
|
||||
return ORBIS_OK;
|
||||
void* MemoryClear(void* buffer, size_t size) {
|
||||
return memset(buffer, 0, size);
|
||||
}
|
||||
|
||||
s32 Ngs2::HandleCleanup(Ngs2Handle* handle, u32 hType, void* dataOut) {
|
||||
if (handle && handle->selfPointer == handle) {
|
||||
std::atomic<u32>* tmp_atomic = handle->atomicPtr;
|
||||
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;
|
||||
s32 StackBufferClose(StackBuffer* stackBuffer, size_t* outTotalSize) {
|
||||
if (outTotalSize) {
|
||||
*outTotalSize = stackBuffer->usedSize + stackBuffer->alignment;
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 Ngs2::HandleLeave(Ngs2Handle* handle) {
|
||||
std::atomic<u32>* tmp_atomic;
|
||||
u32 i;
|
||||
do {
|
||||
tmp_atomic = handle->atomicPtr;
|
||||
i = tmp_atomic->load();
|
||||
} while (!tmp_atomic->compare_exchange_strong(i, i - 1));
|
||||
return ORBIS_OK;
|
||||
}
|
||||
s32 StackBufferOpen(StackBuffer* stackBuffer, void* bufferStart, size_t bufferSize,
|
||||
void** outBuffer, u8 flags) {
|
||||
stackBuffer->top = outBuffer;
|
||||
stackBuffer->base = bufferStart;
|
||||
stackBuffer->size = (size_t)bufferStart;
|
||||
stackBuffer->currentOffset = (size_t)bufferStart;
|
||||
stackBuffer->usedSize = 0;
|
||||
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,
|
||||
bool verify) {
|
||||
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;
|
||||
if (outBuffer != NULL) {
|
||||
*outBuffer = NULL;
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 Ngs2::StackBufferClose(StackBuffer* buf, size_t* usedSize) {
|
||||
if (usedSize) {
|
||||
*usedSize = buf->usedSize + buf->alignment;
|
||||
s32 SystemCleanup(OrbisNgs2Handle systemHandle, OrbisNgs2ContextBufferInfo* outInfo) {
|
||||
if (!systemHandle) {
|
||||
return ORBIS_NGS2_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
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 numGrainSamples = 256;
|
||||
u32 sampleRate = 48000;
|
||||
|
||||
if (options) {
|
||||
maxGrainSamples = options->maxGrainSamples;
|
||||
numGrainSamples = options->numGrainSamples;
|
||||
sampleRate = options->sampleRate;
|
||||
if (option) {
|
||||
sampleRate = option->sampleRate;
|
||||
maxGrainSamples = option->maxGrainSamples;
|
||||
numGrainSamples = option->numGrainSamples;
|
||||
}
|
||||
|
||||
// Validate maxGrainSamples
|
||||
if (maxGrainSamples < 64 || maxGrainSamples > 1024 || (maxGrainSamples & 0x3F) != 0) {
|
||||
if (maxGrainSamples < 64 || maxGrainSamples > 1024 || (maxGrainSamples & 63) != 0) {
|
||||
LOG_ERROR(Lib_Ngs2, "Invalid system option (maxGrainSamples={},x64)", maxGrainSamples);
|
||||
return ORBIS_NGS2_ERROR_INVALID_MAX_GRAIN_SAMPLES;
|
||||
}
|
||||
|
||||
// Validate numGrainSamples
|
||||
if (numGrainSamples < 64 || numGrainSamples > 1024 || (numGrainSamples & 0x3F) != 0) {
|
||||
if (numGrainSamples < 64 || numGrainSamples > 1024 || (numGrainSamples & 63) != 0) {
|
||||
LOG_ERROR(Lib_Ngs2, "Invalid system option (numGrainSamples={},x64)", numGrainSamples);
|
||||
return ORBIS_NGS2_ERROR_INVALID_NUM_GRAIN_SAMPLES;
|
||||
}
|
||||
|
||||
// Validate sampleRate
|
||||
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);
|
||||
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
|
||||
// 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
|
||||
|
|
|
@ -3,23 +3,177 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "ngs2.h"
|
||||
#include "core/libraries/kernel/threads/pthread.h"
|
||||
|
||||
namespace Libraries::Ngs2 {
|
||||
|
||||
class Ngs2 {
|
||||
public:
|
||||
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);
|
||||
static const int ORBIS_NGS2_SYSTEM_NAME_LENGTH = 16;
|
||||
static const int ORBIS_NGS2_RACK_NAME_LENGTH = 16;
|
||||
|
||||
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];
|
||||
};
|
||||
|
||||
using OrbisNgs2BufferAllocHandler =
|
||||
s32 PS4_SYSV_ABI (*)(OrbisNgs2ContextBufferInfo* io_buffer_info);
|
||||
using OrbisNgs2BufferFreeHandler = s32 PS4_SYSV_ABI (*)(OrbisNgs2ContextBufferInfo* io_buffer_info);
|
||||
|
||||
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
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue