mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-23 02:24:38 +00:00
Compare commits
318 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
14ef56d148 | ||
|
9e2af5f619 | ||
|
637e503685 | ||
|
1fc9eedbab | ||
|
bad9cd097a | ||
|
a4c5fa4b5c | ||
|
95a386308a | ||
|
0706223aaf | ||
|
fd03fe2b5a | ||
|
f0cd981548 | ||
|
bd0102c8d0 | ||
|
0b72a795eb | ||
|
2ae7037c08 | ||
|
af67473de3 | ||
|
b56039b15a | ||
|
3019bfb978 | ||
|
76f003d388 | ||
|
fafd3fb564 | ||
|
e914099ae2 | ||
|
1689cdb1a2 | ||
|
fddded8d20 | ||
|
161aa49f37 | ||
|
68b147488e | ||
|
aeab525a7f | ||
|
499451bb80 | ||
|
cf8a6efd37 | ||
|
6e350a5085 | ||
|
a82698d601 | ||
|
83475ac828 | ||
|
6d6068e0e2 | ||
|
4407ebdd9b | ||
|
87f6cce7b1 | ||
|
bf623d4f85 | ||
|
97daee836a | ||
|
b68ca43166 | ||
|
00f4eeddaf | ||
|
399a725343 | ||
|
b403e1be33 | ||
|
8bc30270c8 | ||
|
88abb93669 | ||
|
ee97c5c110 | ||
|
27cbd6647f | ||
|
dc6ef99dc7 | ||
|
7d4b875ee3 | ||
|
f5336358ea | ||
|
df4314f831 | ||
|
e5f899aae3 | ||
|
2d1a2982df | ||
|
ddede4a52d | ||
|
80f7ec2681 | ||
|
7fedbd52e0 | ||
|
d6163a6edb | ||
|
4eaa992aff | ||
|
70eef0de90 | ||
|
146e81a56a | ||
|
5eef2fd28a | ||
|
d1f5a7e8fb | ||
|
78cb5334cf | ||
|
f56eecea44 | ||
|
41b05ce7ed | ||
|
a63db68114 | ||
|
4f99f304e6 | ||
|
a050c9d65b | ||
|
b22da77f9a | ||
|
df22c4225e | ||
|
48460d1cbe | ||
|
7431b30005 | ||
|
9eae6b57ce | ||
|
efa7093f34 | ||
|
0594dac405 | ||
|
5789fd881c | ||
|
1757dfaf5a | ||
|
77117abb31 | ||
|
64dfccdf26 | ||
|
6bf3c44b9c | ||
|
434dcde9f3 | ||
|
bdd2419de9 | ||
|
7f727340aa | ||
|
59dd73492b | ||
|
83056712e0 | ||
|
fa32537f40 | ||
|
09b584b23f | ||
|
4bfd8b967b | ||
|
52bd92b97d | ||
|
8e44a7099f | ||
|
0a58ead5f6 | ||
|
9f37ede336 | ||
|
a49b13fe66 | ||
|
6eaec7a004 | ||
|
075d6425e2 | ||
|
70e4f81655 | ||
|
12198f9255 | ||
|
4bfa8c9fc7 | ||
|
669b19c2f3 | ||
|
d9dac05db2 | ||
|
802124309d | ||
|
5b5096e9ea | ||
|
54163ffaa5 | ||
|
2d335f436c | ||
|
1fc95bf44b | ||
|
0bb1ee167f | ||
|
a62027d4c2 | ||
|
8dcd9cc0f9 | ||
|
7b0249d9ca | ||
|
551751df3c | ||
|
be12305f65 | ||
|
e214ca6884 | ||
|
43321fb45a | ||
|
423254692a | ||
|
612f340292 | ||
|
6d65ea7314 | ||
|
e389d03601 | ||
|
33f46202d2 | ||
|
8e06b1b2b0 | ||
|
1437c5a1de | ||
|
20670186ab | ||
|
5bc4cc761a | ||
|
efa8f6a154 | ||
|
9dd35c3a42 | ||
|
21d14abaee | ||
|
c27f45c8c0 | ||
|
d0e2a40cdc | ||
|
e2b8ceb6ba | ||
|
213ca72fa1 | ||
|
de69f2b40b | ||
|
3f40a8d46e | ||
|
226058d2e9 | ||
|
ae6f7b8d5a | ||
|
1a27af6951 | ||
|
c35141b33f | ||
|
a1d6cd15f4 | ||
|
34d0d85c15 | ||
|
c71dc740e2 | ||
|
69a50fa713 | ||
|
34a1ffbcda | ||
|
3e0ec9ebef | ||
|
2741829545 | ||
|
dedf6de2ac | ||
|
fc4fd0107d | ||
|
ca92e72efe | ||
|
b49340dff8 | ||
|
9981c8df03 | ||
|
e0c930f2d8 | ||
|
e2b726382e | ||
|
0444e590e0 | ||
|
64bbedeb82 | ||
|
217d32b502 | ||
|
a71bfb30a2 | ||
|
046cf50412 | ||
|
d7051f15f4 | ||
|
12f4a8f073 | ||
|
c20d02dd40 | ||
|
ae2053c487 | ||
|
14b082f5ea | ||
|
ce42eccc9d | ||
|
8ffcfc87bd | ||
|
5004e41100 | ||
|
a07a6bb9d3 | ||
|
f2bbb6847d | ||
|
ce84e80f65 | ||
|
952cef5a15 | ||
|
2bc199a41b | ||
|
5d064dd89f | ||
|
2857ef34f0 | ||
|
5edd9ff54b | ||
|
91d29459fb | ||
|
fff3bf9917 | ||
|
43bf4ed1bc | ||
|
3b3026ff1c | ||
|
0e9420a7b2 | ||
|
93222c6f9f | ||
|
285df1b5be | ||
|
d4fbeea085 | ||
|
4d1a1ce9c2 | ||
|
23710f397e | ||
|
88f6cb4d41 | ||
|
5b6fc788b3 | ||
|
8cdd8dd725 | ||
|
c09d1c3cff | ||
|
ca0f458505 | ||
|
bb3f8af81a | ||
|
eed99141b3 | ||
|
2c78272185 | ||
|
1930a2132c | ||
|
6bdd83684b | ||
|
b1af1334c9 | ||
|
bb199865cf | ||
|
c09e463b8e | ||
|
4019319d92 | ||
|
790b54bf29 | ||
|
2091bc5651 | ||
|
8fffdc3918 | ||
|
6cdc52cdde | ||
|
aca8e7e9eb | ||
|
eb9f66c349 | ||
|
7f0503bf8b | ||
|
95f04b746d | ||
|
e0309a4b01 | ||
|
139a253edc | ||
|
99ccf56938 | ||
|
149898193f | ||
|
10d09ac977 | ||
|
e5c6c88835 | ||
|
d124f40503 | ||
|
e518a7062c | ||
|
f9bbde9c79 | ||
|
37887e8fde | ||
|
9c2f71326a | ||
|
b55c3f4555 | ||
|
3f949d2b6c | ||
|
f4eb0b9b9e | ||
|
6935b24440 | ||
|
786ad6f71e | ||
|
eb21083078 | ||
|
1b952bf173 | ||
|
60224e1d22 | ||
|
034ae8cffa | ||
|
5eb58799fe | ||
|
6ee205d4e2 | ||
|
5f447a815e | ||
|
e2513d50be | ||
|
a09f7158b8 | ||
|
251d0f0d7c | ||
|
a0acb47185 | ||
|
ffd31589cf | ||
|
4d769d9c7e | ||
|
7de6aec337 | ||
|
18ff65efc8 | ||
|
aeb4536988 | ||
|
98faff425e | ||
|
6d38100a41 | ||
|
26c965cf4a | ||
|
99eaba7c96 | ||
|
1639640902 | ||
|
647b1d3ee4 | ||
|
6abda17532 | ||
|
3ab69e24db | ||
|
073f931729 | ||
|
0d127a82dd | ||
|
e5b675d607 | ||
|
1832ec2ac2 | ||
|
484fbcc320 | ||
|
7334fb620b | ||
|
f97c0deea9 | ||
|
4cd13ea9d8 | ||
|
e6a144ddb0 | ||
|
3a10fda008 | ||
|
2a3a701115 | ||
|
6bbb424c28 | ||
|
3a3a6d8e45 | ||
|
b23f6fdc1d | ||
|
9baa58dd92 | ||
|
5ab5fa7024 | ||
|
b3abb83fc5 | ||
|
f94c7e52b7 | ||
|
8909d9bb89 | ||
|
678f18ddb9 | ||
|
02d3ed4973 | ||
|
6206986914 | ||
|
c0562a6b1b | ||
|
3a090e988c | ||
|
ff1339b0b6 | ||
|
afcf3a12a3 | ||
|
6ece91c763 | ||
|
7eea1fc4d6 | ||
|
c6ea7d8f76 | ||
|
6477dc4f1e | ||
|
a1439b15cf | ||
|
8d7cbf9943 | ||
|
b130fe6ed5 | ||
|
8e7c5a4d99 | ||
|
46b88bd10f | ||
|
58df609ba0 | ||
|
3b7c36e1ba | ||
|
1aa7eb8a42 | ||
|
c7fb3ebd93 | ||
|
fed064931a | ||
|
9a22185ab7 | ||
|
17b6343f18 | ||
|
d542d952f4 | ||
|
0ba9ea6a3b | ||
|
eb09c4ccce | ||
|
6c39bf229c | ||
|
b0e4e87ff3 | ||
|
4202d9d621 | ||
|
5fd5b62539 | ||
|
10b24d04bc | ||
|
c47d9b2ad6 | ||
|
ede60e8f7f | ||
|
c08f92aca1 | ||
|
a3bbf2274f | ||
|
bb59cd81fa | ||
|
53b2ccffca | ||
|
fa9f58446f | ||
|
5e3157a82c | ||
|
beb9c86749 | ||
|
81fa9b7fff | ||
|
385c5a4507 | ||
|
59d060bc16 | ||
|
83fd0683fa | ||
|
81ad31ce31 | ||
|
ff984d3cde | ||
|
b505829e16 | ||
|
254375ef0c | ||
|
cef795b80b | ||
|
410313ca87 | ||
|
c09fff2da6 | ||
|
e816bc4b99 | ||
|
632ed99ee7 | ||
|
15d6a45dcd | ||
|
d370ea32f4 | ||
|
c01590175a | ||
|
a12d447bd6 | ||
|
ce3aded3e5 | ||
|
4ecdcf77d1 | ||
|
3f4249084c | ||
|
aeee7706ee | ||
|
5db162cbcd |
4
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
4
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
@ -17,7 +17,7 @@ body:
|
||||
|
||||
This repository does not provide support for game patches. If you are having issues with patches please refer to [Cheats and Patches Repository](https://github.com/shadps4-emu/ps4_cheats).
|
||||
|
||||
Before submitting an issue please check [Game Compatibility Repository](https://github.com/shadps4-emu/shadps4-game-compatibility) for the information about the status of the game.
|
||||
Before submitting an issue please check [Game Compatibility Repository](https://github.com/shadps4-compatibility/shadps4-game-compatibility) for the information about the status of the game.
|
||||
|
||||
Please make an effort to make sure your issue isn't already reported.
|
||||
|
||||
@ -35,7 +35,7 @@ body:
|
||||
required: true
|
||||
- label: I have disabled all patches and cheats and the issue is still present.
|
||||
required: true
|
||||
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadps4-game-compatibility?tab=readme-ov-file#informations) installed.
|
||||
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadPS4/wiki/I.-Quick-start-%5BUsers%5D#4-adding-modules) installed.
|
||||
required: true
|
||||
- type: textarea
|
||||
id: desc
|
||||
|
69
.github/workflows/build.yml
vendored
69
.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
|
||||
@ -76,18 +76,13 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
||||
with:
|
||||
append-timestamp: false
|
||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
||||
|
||||
- name: Setup VS Environment
|
||||
uses: ilammy/msvc-dev-cmd@v1.13.0
|
||||
with:
|
||||
arch: amd64
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
@ -111,7 +106,7 @@ jobs:
|
||||
- name: Setup Qt
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: 6.9.0
|
||||
version: 6.9.1
|
||||
host: windows
|
||||
target: desktop
|
||||
arch: win64_msvc2022_64
|
||||
@ -130,18 +125,13 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-qt-cache-cmake-build
|
||||
with:
|
||||
append-timestamp: false
|
||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
||||
|
||||
- name: Setup VS Environment
|
||||
uses: ilammy/msvc-dev-cmd@v1.13.0
|
||||
with:
|
||||
arch: amd64
|
||||
|
||||
- name: Configure CMake
|
||||
run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
@ -186,7 +176,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
env:
|
||||
cache-name: ${{runner.os}}-sdl-cache-cmake-build
|
||||
with:
|
||||
@ -228,13 +218,16 @@ jobs:
|
||||
- name: Setup Qt
|
||||
uses: jurplel/install-qt-action@v4
|
||||
with:
|
||||
version: 6.9.0
|
||||
version: 6.9.1
|
||||
host: mac
|
||||
target: desktop
|
||||
arch: clang_64
|
||||
archives: qtbase qttools
|
||||
modules: qtmultimedia
|
||||
|
||||
|
||||
- name: Workaround Qt <=6.9.1 issue
|
||||
run: sed -i '' '/target_link_libraries(WrapOpenGL::WrapOpenGL INTERFACE ${__opengl_agl_fw_path})/d' ${{env.QT_ROOT_DIR}}/lib/cmake/Qt6/FindWrapOpenGL.cmake
|
||||
|
||||
- name: Cache CMake Configuration
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
@ -247,7 +240,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
env:
|
||||
cache-name: ${{runner.os}}-qt-cache-cmake-build
|
||||
with:
|
||||
@ -281,8 +274,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
|
||||
@ -296,7 +294,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
||||
with:
|
||||
@ -304,7 +302,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 +335,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
|
||||
@ -352,7 +355,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-qt-cache-cmake-build
|
||||
with:
|
||||
@ -360,7 +363,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 +388,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
|
||||
@ -399,7 +402,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-sdl-gcc-cache-cmake-build
|
||||
with:
|
||||
@ -407,7 +410,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 +424,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
|
||||
@ -435,7 +438,7 @@ jobs:
|
||||
${{ env.cache-name }}-
|
||||
|
||||
- name: Cache CMake Build
|
||||
uses: hendrikmuhs/ccache-action@v1.2.17
|
||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
||||
env:
|
||||
cache-name: ${{ runner.os }}-qt-gcc-cache-cmake-build
|
||||
with:
|
||||
@ -443,7 +446,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)
|
||||
@ -484,7 +487,7 @@ jobs:
|
||||
with:
|
||||
token: ${{ secrets.SHADPS4_TOKEN_REPO }}
|
||||
name: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}"
|
||||
tag: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}"
|
||||
tag: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.fullhash }}"
|
||||
draft: false
|
||||
prerelease: true
|
||||
body: "Full Changelog: [${{ env.last_release_tag }}...${{ needs.get-info.outputs.shorthash }}](https://github.com/shadps4-emu/shadPS4/compare/${{ env.last_release_tag }}...${{ needs.get-info.outputs.fullhash }})"
|
||||
@ -520,14 +523,14 @@ jobs:
|
||||
|
||||
# Check if release already exists and get ID
|
||||
release_id=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||
"https://api.github.com/repos/$REPO/releases/tags/Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}" | jq -r '.id')
|
||||
"https://api.github.com/repos/$REPO/releases/tags/Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.fullhash }}" | jq -r '.id')
|
||||
|
||||
if [[ "$release_id" == "null" ]]; then
|
||||
echo "Creating release in $REPO for $filename"
|
||||
release_id=$(curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-d '{
|
||||
"tag_name": "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}",
|
||||
"tag_name": "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.fullhash }}",
|
||||
"name": "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}",
|
||||
"draft": false,
|
||||
"prerelease": true,
|
||||
|
10
.gitmodules
vendored
10
.gitmodules
vendored
@ -30,10 +30,6 @@
|
||||
path = externals/xbyak
|
||||
url = https://github.com/herumi/xbyak.git
|
||||
shallow = true
|
||||
[submodule "externals/winpthreads"]
|
||||
path = externals/winpthreads
|
||||
url = https://github.com/shadps4-emu/winpthreads.git
|
||||
shallow = true
|
||||
[submodule "externals/magic_enum"]
|
||||
path = externals/magic_enum
|
||||
url = https://github.com/Neargye/magic_enum.git
|
||||
@ -107,6 +103,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
|
||||
[submodule "externals/ext-libusb"]
|
||||
path = externals/ext-libusb
|
||||
url = https://github.com/shadps4-emu/ext-libusb.git
|
||||
|
21
CMakeLinuxPresets.json
Normal file
21
CMakeLinuxPresets.json
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"version": 9,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 30,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "x64-Clang-Base",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/Build/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang",
|
||||
"CMAKE_CXX_COMPILER": "clang++",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/Build/${presetName}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
162
CMakeLists.txt
Executable file → Normal file
162
CMakeLists.txt
Executable file → Normal file
@ -54,9 +54,9 @@ else()
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE STREQUAL "x86_64")
|
||||
# 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)
|
||||
# Target x86-64-v3 CPU architecture as this is a good balance between supporting performance critical
|
||||
# instructions like AVX2 and maintaining support for older CPUs.
|
||||
add_compile_options(-march=x86-64-v3)
|
||||
endif()
|
||||
|
||||
if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
|
||||
@ -126,7 +126,7 @@ execute_process(
|
||||
|
||||
# If there's no upstream set or the command failed, check remote.pushDefault
|
||||
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
message("check default push")
|
||||
message(STATUS "check default push")
|
||||
execute_process(
|
||||
COMMAND git config --get remote.pushDefault
|
||||
OUTPUT_VARIABLE GIT_REMOTE_NAME
|
||||
@ -134,29 +134,30 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
message(STATUS "got remote: ${GIT_REMOTE_NAME}")
|
||||
endif()
|
||||
|
||||
# If running in GitHub Actions and the above fails
|
||||
if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
|
||||
message("check github")
|
||||
message(STATUS "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}")
|
||||
message(STATUS "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}")
|
||||
message(STATUS "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}")
|
||||
message(STATUS "PR number: ${PR_NUMBER}")
|
||||
else()
|
||||
set(PR_NUMBER "")
|
||||
endif()
|
||||
@ -177,8 +178,8 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME 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")
|
||||
elseif("${GIT_BRANCH}" STREQUAL "")
|
||||
message(STATUS "couldn't find branch")
|
||||
set(GIT_BRANCH "detached-head")
|
||||
endif()
|
||||
else()
|
||||
@ -186,14 +187,14 @@ else()
|
||||
string(FIND "${GIT_REMOTE_NAME}" "/" INDEX)
|
||||
if (INDEX GREATER -1)
|
||||
string(SUBSTRING "${GIT_REMOTE_NAME}" 0 "${INDEX}" GIT_REMOTE_NAME)
|
||||
else()
|
||||
# If no remote is present (only a branch name), default to origin
|
||||
elseif("${GIT_REMOTE_NAME}" STREQUAL "")
|
||||
message(STATUS "reset to origin")
|
||||
set(GIT_REMOTE_NAME "origin")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Get remote link
|
||||
message("getting remote link")
|
||||
message(STATUS "getting remote link")
|
||||
execute_process(
|
||||
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
|
||||
OUTPUT_VARIABLE GIT_REMOTE_URL
|
||||
@ -202,16 +203,26 @@ execute_process(
|
||||
|
||||
# Set Version
|
||||
set(EMULATOR_VERSION_MAJOR "0")
|
||||
set(EMULATOR_VERSION_MINOR "8")
|
||||
set(EMULATOR_VERSION_PATCH "0")
|
||||
set(EMULATOR_VERSION_MINOR "10")
|
||||
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}")
|
||||
set(APP_IS_RELEASE true)
|
||||
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}")
|
||||
message("-- end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}, link: ${GIT_REMOTE_URL}")
|
||||
|
||||
string(TOLOWER "${GIT_REMOTE_URL}" GIT_REMOTE_URL_LOWER)
|
||||
if(NOT GIT_REMOTE_URL_LOWER MATCHES "shadps4-emu/shadps4" OR NOT GIT_BRANCH STREQUAL "main")
|
||||
message(STATUS "not main, disabling auto update")
|
||||
set(ENABLE_UPDATER OFF)
|
||||
endif()
|
||||
|
||||
if(WIN32 AND ENABLE_QT_GUI AND NOT CMAKE_PREFIX_PATH)
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/DetectQtInstallation.cmake")
|
||||
endif ()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
find_package(Boost 1.84.0 CONFIG)
|
||||
@ -226,26 +237,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.309 CONFIG)
|
||||
find_package(VulkanHeaders 1.4.314 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)
|
||||
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)
|
||||
check_symbol_exists(pthread_mutex_timedlock "pthread.h" HAVE_PTHREAD_MUTEX_TIMEDLOCK)
|
||||
if(HAVE_PTHREAD_MUTEX_TIMEDLOCK OR WIN32)
|
||||
add_compile_options(-DHAVE_PTHREAD_MUTEX_TIMEDLOCK)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
|
||||
# libc++ requires -fexperimental-library to enable std::jthread and std::stop_token support.
|
||||
include(CheckCXXSymbolExists)
|
||||
@ -257,7 +260,6 @@ endif()
|
||||
|
||||
add_subdirectory(externals)
|
||||
include_directories(src)
|
||||
include_directories(Resources)
|
||||
|
||||
if(ENABLE_QT_GUI)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network Multimedia)
|
||||
@ -302,6 +304,8 @@ set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
||||
|
||||
set(AUDIO_LIB src/core/libraries/audio/audioin.cpp
|
||||
src/core/libraries/audio/audioin.h
|
||||
src/core/libraries/voice/voice.cpp
|
||||
src/core/libraries/voice/voice.h
|
||||
src/core/libraries/audio/audioout.cpp
|
||||
src/core/libraries/audio/audioout.h
|
||||
src/core/libraries/audio/audioout_backend.h
|
||||
@ -371,11 +375,19 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
||||
src/core/libraries/network/net_ctl_obj.cpp
|
||||
src/core/libraries/network/net_ctl_obj.h
|
||||
src/core/libraries/network/net_ctl_codes.h
|
||||
src/core/libraries/network/net_util.cpp
|
||||
src/core/libraries/network/net_util.h
|
||||
src/core/libraries/network/net_error.h
|
||||
src/core/libraries/network/net.h
|
||||
src/core/libraries/network/ssl.cpp
|
||||
src/core/libraries/network/ssl.h
|
||||
src/core/libraries/network/ssl2.cpp
|
||||
src/core/libraries/network/ssl2.h
|
||||
src/core/libraries/network/sys_net.cpp
|
||||
src/core/libraries/network/sys_net.h
|
||||
src/core/libraries/network/posix_sockets.cpp
|
||||
src/core/libraries/network/p2p_sockets.cpp
|
||||
src/core/libraries/network/sockets.h
|
||||
)
|
||||
|
||||
set(AVPLAYER_LIB src/core/libraries/avplayer/avplayer_common.cpp
|
||||
@ -408,6 +420,7 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
||||
src/core/libraries/save_data/save_memory.h
|
||||
src/core/libraries/save_data/savedata.cpp
|
||||
src/core/libraries/save_data/savedata.h
|
||||
src/core/libraries/save_data/savedata_error.h
|
||||
src/core/libraries/save_data/dialog/savedatadialog.cpp
|
||||
src/core/libraries/save_data/dialog/savedatadialog.h
|
||||
src/core/libraries/save_data/dialog/savedatadialog_ui.cpp
|
||||
@ -589,8 +602,21 @@ set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
|
||||
src/core/libraries/move/move.h
|
||||
src/core/libraries/ulobjmgr/ulobjmgr.cpp
|
||||
src/core/libraries/ulobjmgr/ulobjmgr.h
|
||||
src/core/libraries/signin_dialog/signindialog.cpp
|
||||
src/core/libraries/signin_dialog/signindialog.h
|
||||
)
|
||||
|
||||
set(CAMERA_LIBS src/core/libraries/camera/camera.cpp
|
||||
src/core/libraries/camera/camera.h
|
||||
src/core/libraries/camera/camera_error.h
|
||||
)
|
||||
|
||||
set(COMPANION_LIBS src/core/libraries/companion/companion_httpd.cpp
|
||||
src/core/libraries/companion/companion_httpd.h
|
||||
src/core/libraries/companion/companion_util.cpp
|
||||
src/core/libraries/companion/companion_util.h
|
||||
src/core/libraries/companion/companion_error.h
|
||||
)
|
||||
set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||
src/core/devtools/layer.h
|
||||
src/core/devtools/options.cpp
|
||||
@ -608,6 +634,8 @@ set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||
src/core/devtools/widget/imgui_memory_editor.h
|
||||
src/core/devtools/widget/memory_map.cpp
|
||||
src/core/devtools/widget/memory_map.h
|
||||
src/core/devtools/widget/module_list.cpp
|
||||
src/core/devtools/widget/module_list.h
|
||||
src/core/devtools/widget/reg_popup.cpp
|
||||
src/core/devtools/widget/reg_popup.h
|
||||
src/core/devtools/widget/reg_view.cpp
|
||||
@ -633,6 +661,7 @@ set(COMMON src/common/logging/backend.cpp
|
||||
src/common/arch.h
|
||||
src/common/assert.cpp
|
||||
src/common/assert.h
|
||||
src/common/bit_array.h
|
||||
src/common/bit_field.h
|
||||
src/common/bounded_threadsafe_queue.h
|
||||
src/common/concepts.h
|
||||
@ -658,9 +687,13 @@ set(COMMON src/common/logging/backend.cpp
|
||||
src/common/path_util.h
|
||||
src/common/object_pool.h
|
||||
src/common/polyfill_thread.h
|
||||
src/common/range_lock.h
|
||||
src/common/rdtsc.cpp
|
||||
src/common/rdtsc.h
|
||||
src/common/recursive_lock.cpp
|
||||
src/common/recursive_lock.h
|
||||
src/common/sha1.h
|
||||
src/common/shared_first_mutex.h
|
||||
src/common/signal_context.h
|
||||
src/common/signal_context.cpp
|
||||
src/common/singleton.h
|
||||
@ -754,6 +787,8 @@ set(CORE src/core/aerolib/stubs.cpp
|
||||
${FIBER_LIB}
|
||||
${VDEC_LIB}
|
||||
${VR_LIBS}
|
||||
${CAMERA_LIBS}
|
||||
${COMPANION_LIBS}
|
||||
${DEV_TOOLS}
|
||||
src/core/debug_state.cpp
|
||||
src/core/debug_state.h
|
||||
@ -840,13 +875,16 @@ 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
|
||||
src/shader_recompiler/ir/passes/shared_memory_barrier_pass.cpp
|
||||
src/shader_recompiler/ir/passes/shared_memory_simplify_pass.cpp
|
||||
src/shader_recompiler/ir/passes/shared_memory_to_storage_pass.cpp
|
||||
src/shader_recompiler/ir/passes/ssa_rewrite_pass.cpp
|
||||
src/shader_recompiler/ir/abstract_syntax_list.cpp
|
||||
src/shader_recompiler/ir/abstract_syntax_list.h
|
||||
src/shader_recompiler/ir/attribute.cpp
|
||||
src/shader_recompiler/ir/attribute.h
|
||||
@ -886,9 +924,10 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
||||
src/video_core/buffer_cache/buffer.h
|
||||
src/video_core/buffer_cache/buffer_cache.cpp
|
||||
src/video_core/buffer_cache/buffer_cache.h
|
||||
src/video_core/buffer_cache/memory_tracker_base.h
|
||||
src/video_core/buffer_cache/memory_tracker.h
|
||||
src/video_core/buffer_cache/range_set.h
|
||||
src/video_core/buffer_cache/word_manager.h
|
||||
src/video_core/buffer_cache/region_definitions.h
|
||||
src/video_core/buffer_cache/region_manager.h
|
||||
src/video_core/renderer_vulkan/liverpool_to_vk.cpp
|
||||
src/video_core/renderer_vulkan/liverpool_to_vk.h
|
||||
src/video_core/renderer_vulkan/vk_common.cpp
|
||||
@ -925,6 +964,10 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
||||
src/video_core/renderer_vulkan/host_passes/fsr_pass.h
|
||||
src/video_core/renderer_vulkan/host_passes/pp_pass.cpp
|
||||
src/video_core/renderer_vulkan/host_passes/pp_pass.h
|
||||
src/video_core/texture_cache/blit_helper.cpp
|
||||
src/video_core/texture_cache/blit_helper.h
|
||||
src/video_core/texture_cache/host_compatibility.cpp
|
||||
src/video_core/texture_cache/host_compatibility.h
|
||||
src/video_core/texture_cache/image.cpp
|
||||
src/video_core/texture_cache/image.h
|
||||
src/video_core/texture_cache/image_info.cpp
|
||||
@ -938,7 +981,6 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
||||
src/video_core/texture_cache/tile_manager.cpp
|
||||
src/video_core/texture_cache/tile_manager.h
|
||||
src/video_core/texture_cache/types.h
|
||||
src/video_core/texture_cache/host_compatibility.h
|
||||
src/video_core/page_manager.cpp
|
||||
src/video_core/page_manager.h
|
||||
src/video_core/multi_level_page_table.h
|
||||
@ -1027,6 +1069,12 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
|
||||
src/qt_gui/settings_dialog.h
|
||||
src/qt_gui/settings_dialog.ui
|
||||
src/qt_gui/main.cpp
|
||||
src/qt_gui/gui_settings.cpp
|
||||
src/qt_gui/gui_settings.h
|
||||
src/qt_gui/settings.cpp
|
||||
src/qt_gui/settings.h
|
||||
src/qt_gui/sdl_event_wrapper.cpp
|
||||
src/qt_gui/sdl_event_wrapper.h
|
||||
${EMULATOR}
|
||||
${RESOURCE_FILES}
|
||||
${TRANSLATIONS}
|
||||
@ -1077,57 +1125,56 @@ if (ENABLE_DISCORD_RPC)
|
||||
target_compile_definitions(shadps4 PRIVATE ENABLE_DISCORD_RPC)
|
||||
endif()
|
||||
|
||||
# Optional due to https://github.com/shadps4-emu/shadPS4/issues/1704
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ENABLE_USERFAULTFD)
|
||||
target_compile_definitions(shadps4 PRIVATE ENABLE_USERFAULTFD)
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
# Optional due to https://github.com/shadps4-emu/shadPS4/issues/1704
|
||||
if (ENABLE_USERFAULTFD)
|
||||
target_compile_definitions(shadps4 PRIVATE ENABLE_USERFAULTFD)
|
||||
endif()
|
||||
|
||||
target_link_libraries(shadps4 PRIVATE uuid)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
# Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
|
||||
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib)
|
||||
|
||||
if (ENABLE_QT_GUI)
|
||||
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks")
|
||||
set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json)
|
||||
set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib)
|
||||
set(MVK_DYLIB_ICD_PATH "../../../Frameworks/libMoltenVK.dylib")
|
||||
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})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${MVK_DST}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DST})
|
||||
else()
|
||||
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path")
|
||||
set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/MoltenVK_icd.json)
|
||||
set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/libMoltenVK.dylib)
|
||||
set(MVK_DYLIB_ICD_PATH "./libMoltenVK.dylib")
|
||||
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
cmake_path(GET MVK_ICD_DST PARENT_PATH MVK_ICD_DST_PARENT)
|
||||
cmake_path(GET MVK_DYLIB_DST PARENT_PATH MVK_DYLIB_DST_PARENT)
|
||||
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)
|
||||
|
||||
set(MVK_ICD "\\\{ \\\"file_format_version\\\": \\\"1.0.0\\\", \\\"ICD\\\": \\\{ \\\"library_path\\\": \\\"${MVK_DYLIB_ICD_PATH}\\\", \\\"api_version\\\": \\\"1.2.0\\\", \\\"is_portability_driver\\\": true \\\} \\\}")
|
||||
add_custom_command(
|
||||
OUTPUT ${MVK_ICD_DST}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_ICD_DST_PARENT} && ${CMAKE_COMMAND} -E echo ${MVK_ICD} > ${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}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DYLIB_DST_PARENT} && ${CMAKE_COMMAND} -E copy ${MVK_DYLIB_SRC} ${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)
|
||||
|
||||
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)
|
||||
target_link_options(shadps4 PRIVATE -Wl,-ld_classic,-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)
|
||||
target_link_libraries(shadps4 PRIVATE SDL3::SDL3)
|
||||
endif()
|
||||
|
||||
if (ENABLE_QT_GUI)
|
||||
target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network Qt6::Multimedia)
|
||||
add_definitions(-DENABLE_QT_GUI)
|
||||
@ -1137,7 +1184,7 @@ if (ENABLE_QT_GUI)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(shadps4 PRIVATE mincore winpthreads)
|
||||
target_link_libraries(shadps4 PRIVATE mincore)
|
||||
|
||||
if (MSVC)
|
||||
# MSVC likes putting opinions on what people can use, disable:
|
||||
@ -1194,6 +1241,7 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeRC.cmake")
|
||||
cmrc_add_resource_library(embedded-resources
|
||||
ALIAS res::embedded
|
||||
NAMESPACE res
|
||||
src/images/trophy.wav
|
||||
src/images/bronze.png
|
||||
src/images/gold.png
|
||||
src/images/platinum.png
|
||||
|
62
CMakePresets.json
Normal file
62
CMakePresets.json
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"version": 9,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 30,
|
||||
"patch": 0
|
||||
},
|
||||
"include": ["CMake${hostSystemName}Presets.json"],
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "x64-Clang-Debug",
|
||||
"displayName": "Clang x64 Debug",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-Debug-Qt",
|
||||
"displayName": "Clang x64 Debug with Qt",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"ENABLE_QT_GUI": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-Release",
|
||||
"displayName": "Clang x64 Release",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-Release-Qt",
|
||||
"displayName": "Clang x64 Release with Qt",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"ENABLE_QT_GUI": "ON"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-RelWithDebInfo",
|
||||
"displayName": "Clang x64 RelWithDebInfo",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-RelWithDebInfo-Qt",
|
||||
"displayName": "Clang x64 RelWithDebInfo with Qt",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
||||
"ENABLE_QT_GUI": "ON"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -12,6 +12,18 @@
|
||||
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
||||
"intelliSenseMode": "windows-clang-x64"
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-Release-Qt",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Release",
|
||||
"buildRoot": "${projectDir}\\Build\\${name}",
|
||||
"installRoot": "${projectDir}\\Install\\${name}",
|
||||
"cmakeCommandArgs": "-DENABLE_QT_GUI=ON",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
||||
"intelliSenseMode": "windows-clang-x64"
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-Debug",
|
||||
"generator": "Ninja",
|
||||
@ -24,6 +36,18 @@
|
||||
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
||||
"intelliSenseMode": "windows-clang-x64"
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-Debug-Qt",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"buildRoot": "${projectDir}\\Build\\${name}",
|
||||
"installRoot": "${projectDir}\\Install\\${name}",
|
||||
"cmakeCommandArgs": "-DENABLE_QT_GUI=ON",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
||||
"intelliSenseMode": "windows-clang-x64"
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-RelWithDebInfo",
|
||||
"generator": "Ninja",
|
||||
@ -35,6 +59,18 @@
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
||||
"intelliSenseMode": "windows-clang-x64"
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-RelWithDebInfo-Qt",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"buildRoot": "${projectDir}\\Build\\${name}",
|
||||
"installRoot": "${projectDir}\\Install\\${name}",
|
||||
"cmakeCommandArgs": "-DENABLE_QT_GUI=ON",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
||||
"intelliSenseMode": "windows-clang-x64"
|
||||
}
|
||||
]
|
||||
}
|
26
CMakeWindowsPresets.json
Normal file
26
CMakeWindowsPresets.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"version": 9,
|
||||
"cmakeMinimumRequired": {
|
||||
"major": 3,
|
||||
"minor": 30,
|
||||
"patch": 0
|
||||
},
|
||||
"configurePresets": [
|
||||
{
|
||||
"name": "x64-Clang-Base",
|
||||
"hidden": true,
|
||||
"generator": "Ninja",
|
||||
"binaryDir": "${sourceDir}/Build/${presetName}",
|
||||
"cacheVariables": {
|
||||
"CMAKE_C_COMPILER": "clang-cl",
|
||||
"CMAKE_CXX_COMPILER": "clang-cl",
|
||||
"CMAKE_INSTALL_PREFIX": "${sourceDir}/Build/${presetName}"
|
||||
},
|
||||
"vendor": {
|
||||
"microsoft.com/VisualStudioSettings/CMake/1.0": {
|
||||
"intelliSenseMode": "windows-clang-x64"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
15
README.md
15
README.md
@ -36,8 +36,8 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
**shadPS4** is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++.
|
||||
|
||||
If you encounter problems or have doubts, do not hesitate to look at the [**Quickstart**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Quickstart/Quickstart.md).\
|
||||
To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-emu/shadps4-game-compatibility).\
|
||||
If you encounter problems or have doubts, do not hesitate to look at the [**Quickstart**](https://github.com/shadps4-emu/shadPS4/wiki/I.-Quick-start-%5BUsers%5D).\
|
||||
To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-compatibility/shadps4-game-compatibility).\
|
||||
To discuss shadPS4 development, suggest ideas or to ask for help, join our [**Discord server**](https://discord.gg/bFJxfftGW6).\
|
||||
To get the latest news, go to our [**X (Twitter)**](https://x.com/shadps4) or our [**website**](https://shadps4.net/).\
|
||||
For those who'd like to donate to the project, we now have a [**Kofi page**](https://ko-fi.com/shadps4)!
|
||||
@ -124,8 +124,8 @@ Keyboard and mouse inputs can be customized in the settings menu by clicking the
|
||||
|
||||
# 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.
|
||||
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 `sys_modules` folder.
|
||||
|
||||
<div align="center">
|
||||
|
||||
@ -138,8 +138,7 @@ The following firmware modules are supported and must be placed in shadPS4's `us
|
||||
</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**.
|
||||
> The above modules are required to run the games properly and must be extracted from your PlayStation 4.
|
||||
|
||||
|
||||
|
||||
@ -148,7 +147,7 @@ The following firmware modules are supported and must be placed in shadPS4's `us
|
||||
- [**georgemoralis**](https://github.com/georgemoralis)
|
||||
- [**psucien**](https://github.com/psucien)
|
||||
- [**viniciuslrangel**](https://github.com/viniciuslrangel)
|
||||
- [**roamic**](https://github.com/vladmikhalin)
|
||||
- [**roamic**](https://github.com/roamic)
|
||||
- [**squidbus**](https://github.com/squidbus)
|
||||
- [**frodo**](https://github.com/baggins183)
|
||||
- [**Stephen Miller**](https://github.com/StevenMiller123)
|
||||
@ -158,7 +157,7 @@ Logo is done by [**Xphalnos**](https://github.com/Xphalnos)
|
||||
|
||||
# Contributing
|
||||
|
||||
If you want to contribute, please look the [**CONTRIBUTING.md**](https://github.com/shadps4-emu/shadPS4/blob/main/CONTRIBUTING.md) file.\
|
||||
If you want to contribute, please read the [**CONTRIBUTING.md**](https://github.com/shadps4-emu/shadPS4/blob/main/CONTRIBUTING.md) file.\
|
||||
Open a PR and we'll check it :)
|
||||
|
||||
# Translations
|
||||
|
11
REUSE.toml
11
REUSE.toml
@ -5,10 +5,13 @@ path = [
|
||||
"REUSE.toml",
|
||||
"crowdin.yml",
|
||||
"CMakeSettings.json",
|
||||
"CMakeLinuxPresets.json",
|
||||
"CMakeWindowsPresets.json",
|
||||
"CMakePresets.json",
|
||||
".github/FUNDING.yml",
|
||||
".github/shadps4.png",
|
||||
".github/workflows/scripts/update_translation.sh",
|
||||
".github/workflows/update_translation.yml",
|
||||
".github/workflows/scripts/update_translation.sh",
|
||||
".github/workflows/update_translation.yml",
|
||||
".gitmodules",
|
||||
"dist/MacOSBundleInfo.plist.in",
|
||||
"dist/net.shadps4.shadPS4.desktop",
|
||||
@ -29,6 +32,7 @@ path = [
|
||||
"src/images/discord.png",
|
||||
"src/images/dump_icon.png",
|
||||
"src/images/exit_icon.png",
|
||||
"src/images/favorite_icon.png",
|
||||
"src/images/file_icon.png",
|
||||
"src/images/trophy_icon.png",
|
||||
"src/images/flag_china.png",
|
||||
@ -69,9 +73,10 @@ path = [
|
||||
"src/images/shadps4.svg",
|
||||
"src/images/website.svg",
|
||||
"src/images/youtube.svg",
|
||||
"src/images/trophy.wav",
|
||||
"src/shadps4.qrc",
|
||||
"src/shadps4.rc",
|
||||
"src/qt_gui/translations/update_translation.sh",
|
||||
"src/qt_gui/translations/update_translation.sh",
|
||||
]
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
||||
|
28
cmake/DetectQtInstallation.cmake
Normal file
28
cmake/DetectQtInstallation.cmake
Normal file
@ -0,0 +1,28 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(highest_version "0")
|
||||
set(CANDIDATE_DRIVES A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
|
||||
|
||||
foreach(drive ${CANDIDATE_DRIVES})
|
||||
file(GLOB kits LIST_DIRECTORIES true CONFIGURE_DEPENDS "${drive}:/Qt/*/msvc*_64")
|
||||
foreach(kit IN LISTS kits)
|
||||
get_filename_component(version_dir "${kit}" DIRECTORY)
|
||||
get_filename_component(kit_version "${version_dir}" NAME)
|
||||
|
||||
message(STATUS "DetectQtInstallation.cmake: Detected Qt: ${kit}")
|
||||
|
||||
if (kit_version VERSION_GREATER highest_version)
|
||||
set(highest_version "${kit_version}")
|
||||
set(QT_PREFIX "${kit}")
|
||||
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
if(QT_PREFIX)
|
||||
set(CMAKE_PREFIX_PATH "${QT_PREFIX}" CACHE PATH "Qt prefix auto‑detected" FORCE)
|
||||
message(STATUS "DetectQtInstallation.cmake: Choose newest Qt: ${QT_PREFIX}")
|
||||
else()
|
||||
message(STATUS "DetectQtInstallation.cmake: No Qt‑Directory found in <drive>:/Qt – please set CMAKE_PREFIX_PATH manually")
|
||||
endif()
|
8
dist/net.shadps4.shadPS4.metainfo.xml
vendored
8
dist/net.shadps4.shadPS4.metainfo.xml
vendored
@ -37,7 +37,13 @@
|
||||
<category translate="no">Game</category>
|
||||
</categories>
|
||||
<releases>
|
||||
<release version="0.8.0" date="2025-05-23">
|
||||
<release version="0.10.0" date="2025-07-06">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.10.0</url>
|
||||
</release>
|
||||
<release version="0.9.0" date="2025-05-22">
|
||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.9.0</url>
|
||||
</release>
|
||||
<release version="0.8.0" date="2025-04-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">
|
||||
|
@ -147,7 +147,7 @@ Accurately identifying games will help other developers that own that game recog
|
||||
- If your issue is small or you aren't sure whether you have properly identified something, [join the Discord server](https://discord.gg/MyZRaBngxA) and use the #development channel
|
||||
to concisely explain the issue, as well as any findings you currently have.
|
||||
|
||||
- It is recommended that you check the [game compatibility issue tracker](https://github.com/shadps4-emu/shadps4-game-compatibility/issues) and post very short summaries of progress changes there,
|
||||
- It is recommended that you check the [game compatibility issue tracker](https://github.com/shadps4-compatibility/shadps4-game-compatibility/issues) and post very short summaries of progress changes there,
|
||||
(such as the game now booting into the menu or getting in-game) for organizational and status update purposes.
|
||||
|
||||
- ⚠ **Do not post theoretical, unproven game-specific issues in the emulator issue tracker that you cannot verify and locate in the emulator source code as being a bug.**\
|
||||
|
@ -21,9 +21,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
- A processor with at least 4 cores and 6 threads
|
||||
- Above 2.5 GHz frequency
|
||||
- A CPU supporting the following instruction sets: MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, F16C, CLMUL, AES, BMI1, MOVBE, XSAVE, ABM
|
||||
- A CPU supporting the x86-64-v3 baseline.
|
||||
- **Intel**: Haswell generation or newer
|
||||
- **AMD**: Jaguar generation or newer
|
||||
- **AMD**: Excavator generation or newer
|
||||
- **Apple**: Rosetta 2 on macOS 15.4 or newer
|
||||
|
||||
### GPU
|
||||
@ -55,4 +55,4 @@ To configure the emulator, you can go through the interface and go to "settings"
|
||||
|
||||
You can also configure the emulator by editing the `config.toml` file located in the `user` folder created after the application is started (Mostly useful if you are using the SDL version).
|
||||
Some settings may be related to more technical development and debugging.\
|
||||
For more information on this, see [**Debugging**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md#configuration).
|
||||
For more information on this, see [**Debugging**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md#configuration).
|
||||
|
@ -25,11 +25,11 @@ sudo apt install build-essential clang git cmake libasound2-dev \
|
||||
|
||||
```bash
|
||||
sudo dnf install clang git cmake libatomic alsa-lib-devel \
|
||||
pipewire-jack-audio-connection-kit-devel openal-devel \
|
||||
pipewire-jack-audio-connection-kit-devel openal-soft-devel \
|
||||
openssl-devel libevdev-devel libudev-devel libXext-devel \
|
||||
qt6-qtbase-devel qt6-qtbase-private-devel \
|
||||
qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel \
|
||||
vulkan-devel vulkan-validation-layers libpng-devel
|
||||
vulkan-devel vulkan-validation-layers libpng-devel libuuid-devel
|
||||
```
|
||||
|
||||
#### Arch Linux
|
||||
@ -74,6 +74,7 @@ and install the dependencies on that container as cited above.
|
||||
This option is **highly recommended** for distributions with immutable/atomic filesystems (example: Fedora Kinoite, SteamOS).
|
||||
|
||||
### Cloning
|
||||
The project uses submodules to manage dependencies, and they need to be initialized before you can build the project. To achieve this, make sure you've cloned the repository with the --recursive flag
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/shadps4-emu/shadPS4.git
|
||||
|
8
externals/CMakeLists.txt
vendored
8
externals/CMakeLists.txt
vendored
@ -137,12 +137,6 @@ if (NOT TARGET Zydis::Zydis)
|
||||
add_subdirectory(zydis)
|
||||
endif()
|
||||
|
||||
# Winpthreads
|
||||
if (WIN32)
|
||||
add_subdirectory(winpthreads)
|
||||
target_include_directories(winpthreads INTERFACE winpthreads/include)
|
||||
endif()
|
||||
|
||||
# sirit
|
||||
add_subdirectory(sirit)
|
||||
if (WIN32)
|
||||
@ -203,7 +197,7 @@ endif()
|
||||
|
||||
# libusb
|
||||
if (NOT TARGET libusb::usb)
|
||||
add_subdirectory(libusb)
|
||||
add_subdirectory(ext-libusb)
|
||||
add_library(libusb::usb ALIAS usb-1.0)
|
||||
endif()
|
||||
|
||||
|
2
externals/MoltenVK/MoltenVK
vendored
2
externals/MoltenVK/MoltenVK
vendored
@ -1 +1 @@
|
||||
Subproject commit 4cf8f94684c53e581eb9cc694dd3305d1f7d9959
|
||||
Subproject commit 00abd384ce01cbd439045905d2fa6cf799dfa2f6
|
2
externals/MoltenVK/SPIRV-Cross
vendored
2
externals/MoltenVK/SPIRV-Cross
vendored
@ -1 +1 @@
|
||||
Subproject commit 2275d0efc4f2fa46851035d9d3c67c105bc8b99e
|
||||
Subproject commit 1a69a919fa302e92b337594bd0a8aaea61037d91
|
1
externals/ext-libusb
vendored
Submodule
1
externals/ext-libusb
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit e1f4ac1472bdf6aab27f8b836a2f47df85465bac
|
1
externals/libusb
vendored
1
externals/libusb
vendored
@ -1 +0,0 @@
|
||||
Subproject commit a63a7e43e0950a595cf4b98a0eaf4051749ace5f
|
2
externals/sdl3
vendored
2
externals/sdl3
vendored
@ -1 +1 @@
|
||||
Subproject commit 4093e4a193971ef1d4928158e0a1832be42e4599
|
||||
Subproject commit 86b206dadf8ad40e6657fa37db371a0aeff74e9c
|
2
externals/sirit
vendored
2
externals/sirit
vendored
@ -1 +1 @@
|
||||
Subproject commit 427a42c9ed99b38204d9107bc3dc14e92458acf1
|
||||
Subproject commit 282083a595dcca86814dedab2f2b0363ef38f1ec
|
2
externals/vulkan-headers
vendored
2
externals/vulkan-headers
vendored
@ -1 +1 @@
|
||||
Subproject commit 5ceb9ed481e58e705d0d9b5326537daedd06b97d
|
||||
Subproject commit 9c77de5c3dd216f28e407eec65ed9c0a296c1f74
|
1
externals/winpthreads
vendored
1
externals/winpthreads
vendored
@ -1 +0,0 @@
|
||||
Subproject commit f35b0948d36a736e6a2d052ae295a3ffde09703f
|
@ -18,6 +18,9 @@ public:
|
||||
void unlock() {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
[[nodiscard]] bool try_lock() {
|
||||
return pthread_mutex_trylock(&mutex) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
|
||||
|
406
src/common/bit_array.h
Normal file
406
src/common/bit_array.h
Normal file
@ -0,0 +1,406 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include "common/types.h"
|
||||
|
||||
#ifdef __AVX2__
|
||||
#define BIT_ARRAY_USE_AVX
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
namespace Common {
|
||||
|
||||
template <size_t N>
|
||||
class BitArray {
|
||||
static_assert(N % 64 == 0, "BitArray size must be a multiple of 64 bits.");
|
||||
|
||||
static constexpr size_t BITS_PER_WORD = 64;
|
||||
static constexpr size_t WORD_COUNT = N / BITS_PER_WORD;
|
||||
static constexpr size_t WORDS_PER_AVX = 4;
|
||||
static constexpr size_t AVX_WORD_COUNT = WORD_COUNT / WORDS_PER_AVX;
|
||||
|
||||
public:
|
||||
using Range = std::pair<size_t, size_t>;
|
||||
|
||||
class Iterator {
|
||||
public:
|
||||
explicit Iterator(const BitArray& bit_array_, u64 start) : bit_array(bit_array_) {
|
||||
range = bit_array.FirstRangeFrom(start);
|
||||
}
|
||||
|
||||
Iterator& operator++() {
|
||||
range = bit_array.FirstRangeFrom(range.second);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Iterator& other) const {
|
||||
return range == other.range;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
const Range& operator*() const {
|
||||
return range;
|
||||
}
|
||||
|
||||
const Range* operator->() const {
|
||||
return ⦥
|
||||
}
|
||||
|
||||
private:
|
||||
const BitArray& bit_array;
|
||||
Range range;
|
||||
};
|
||||
|
||||
using const_iterator = Iterator;
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = Range;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = const Range*;
|
||||
using reference = const Range&;
|
||||
|
||||
BitArray() = default;
|
||||
BitArray(const BitArray& other) = default;
|
||||
BitArray& operator=(const BitArray& other) = default;
|
||||
BitArray(BitArray&& other) noexcept = default;
|
||||
BitArray& operator=(BitArray&& other) noexcept = default;
|
||||
~BitArray() = default;
|
||||
|
||||
BitArray(const BitArray& other, size_t start, size_t end) {
|
||||
if (start >= end || end > N) {
|
||||
return;
|
||||
}
|
||||
const size_t first_word = start / BITS_PER_WORD;
|
||||
const size_t last_word = (end - 1) / BITS_PER_WORD;
|
||||
const size_t start_bit = start % BITS_PER_WORD;
|
||||
const size_t end_bit = (end - 1) % BITS_PER_WORD;
|
||||
const u64 start_mask = ~((1ULL << start_bit) - 1);
|
||||
const u64 end_mask = end_bit == BITS_PER_WORD - 1 ? ~0ULL : (1ULL << (end_bit + 1)) - 1;
|
||||
if (first_word == last_word) {
|
||||
data[first_word] = other.data[first_word] & (start_mask & end_mask);
|
||||
} else {
|
||||
data[first_word] = other.data[first_word] & start_mask;
|
||||
size_t i = first_word + 1;
|
||||
#ifdef BIT_ARRAY_USE_AVX
|
||||
for (; i + WORDS_PER_AVX <= last_word; i += WORDS_PER_AVX) {
|
||||
const __m256i current =
|
||||
_mm256_loadu_si256(reinterpret_cast<const __m256i*>(&other.data[i]));
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i*>(&data[i]), current);
|
||||
}
|
||||
#endif
|
||||
for (; i < last_word; ++i) {
|
||||
data[i] = other.data[i];
|
||||
}
|
||||
data[last_word] = other.data[last_word] & end_mask;
|
||||
}
|
||||
}
|
||||
|
||||
BitArray(const BitArray& other, const Range& range)
|
||||
: BitArray(other, range.first, range.second) {}
|
||||
|
||||
const_iterator begin() const {
|
||||
return Iterator(*this, 0);
|
||||
}
|
||||
const_iterator end() const {
|
||||
return Iterator(*this, N);
|
||||
}
|
||||
|
||||
inline constexpr void Set(size_t idx) {
|
||||
data[idx / BITS_PER_WORD] |= (1ULL << (idx % BITS_PER_WORD));
|
||||
}
|
||||
|
||||
inline constexpr void Unset(size_t idx) {
|
||||
data[idx / BITS_PER_WORD] &= ~(1ULL << (idx % BITS_PER_WORD));
|
||||
}
|
||||
|
||||
inline constexpr bool Get(size_t idx) const {
|
||||
return (data[idx / BITS_PER_WORD] & (1ULL << (idx % BITS_PER_WORD))) != 0;
|
||||
}
|
||||
|
||||
inline void SetRange(size_t start, size_t end) {
|
||||
if (start >= end || end > N) {
|
||||
return;
|
||||
}
|
||||
const size_t first_word = start / BITS_PER_WORD;
|
||||
const size_t last_word = (end - 1) / BITS_PER_WORD;
|
||||
const size_t start_bit = start % BITS_PER_WORD;
|
||||
const size_t end_bit = (end - 1) % BITS_PER_WORD;
|
||||
const u64 start_mask = ~((1ULL << start_bit) - 1);
|
||||
const u64 end_mask = end_bit == BITS_PER_WORD - 1 ? ~0ULL : (1ULL << (end_bit + 1)) - 1;
|
||||
if (first_word == last_word) {
|
||||
data[first_word] |= start_mask & end_mask;
|
||||
} else {
|
||||
data[first_word] |= start_mask;
|
||||
size_t i = first_word + 1;
|
||||
#ifdef BIT_ARRAY_USE_AVX
|
||||
const __m256i value = _mm256_set1_epi64x(-1);
|
||||
for (; i + WORDS_PER_AVX <= last_word; i += WORDS_PER_AVX) {
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i*>(&data[i]), value);
|
||||
}
|
||||
#endif
|
||||
for (; i < last_word; ++i) {
|
||||
data[i] = ~0ULL;
|
||||
}
|
||||
data[last_word] |= end_mask;
|
||||
}
|
||||
}
|
||||
|
||||
inline void UnsetRange(size_t start, size_t end) {
|
||||
if (start >= end || end > N) {
|
||||
return;
|
||||
}
|
||||
size_t first_word = start / BITS_PER_WORD;
|
||||
const size_t last_word = (end - 1) / BITS_PER_WORD;
|
||||
const size_t start_bit = start % BITS_PER_WORD;
|
||||
const size_t end_bit = (end - 1) % BITS_PER_WORD;
|
||||
const u64 start_mask = (1ULL << start_bit) - 1;
|
||||
const u64 end_mask = end_bit == BITS_PER_WORD - 1 ? 0ULL : ~((1ULL << (end_bit + 1)) - 1);
|
||||
if (first_word == last_word) {
|
||||
data[first_word] &= start_mask | end_mask;
|
||||
} else {
|
||||
data[first_word] &= start_mask;
|
||||
size_t i = first_word + 1;
|
||||
#ifdef BIT_ARRAY_USE_AVX
|
||||
const __m256i value = _mm256_setzero_si256();
|
||||
for (; i + WORDS_PER_AVX <= last_word; i += WORDS_PER_AVX) {
|
||||
_mm256_storeu_si256(reinterpret_cast<__m256i*>(&data[i]), value);
|
||||
}
|
||||
#endif
|
||||
for (; i < last_word; ++i) {
|
||||
data[i] = 0ULL;
|
||||
}
|
||||
data[last_word] &= end_mask;
|
||||
}
|
||||
}
|
||||
|
||||
inline constexpr void SetRange(const Range& range) {
|
||||
SetRange(range.first, range.second);
|
||||
}
|
||||
|
||||
inline constexpr void UnsetRange(const Range& range) {
|
||||
UnsetRange(range.first, range.second);
|
||||
}
|
||||
|
||||
inline constexpr void Clear() {
|
||||
data.fill(0);
|
||||
}
|
||||
|
||||
inline constexpr void Fill() {
|
||||
data.fill(~0ULL);
|
||||
}
|
||||
|
||||
inline constexpr bool None() const {
|
||||
u64 result = 0;
|
||||
for (const auto& word : data) {
|
||||
result |= word;
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
inline constexpr bool Any() const {
|
||||
return !None();
|
||||
}
|
||||
|
||||
Range FirstRangeFrom(size_t start) const {
|
||||
if (start >= N) {
|
||||
return {N, N};
|
||||
}
|
||||
const auto find_end_bit = [&](size_t word) {
|
||||
#ifdef BIT_ARRAY_USE_AVX
|
||||
const __m256i all_one = _mm256_set1_epi64x(-1);
|
||||
for (; word + WORDS_PER_AVX <= WORD_COUNT; word += WORDS_PER_AVX) {
|
||||
const __m256i current =
|
||||
_mm256_loadu_si256(reinterpret_cast<const __m256i*>(&data[word]));
|
||||
const __m256i cmp = _mm256_cmpeq_epi64(current, all_one);
|
||||
if (_mm256_movemask_epi8(cmp) != 0xFFFFFFFF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (; word < WORD_COUNT; ++word) {
|
||||
if (data[word] != ~0ULL) {
|
||||
return (word * BITS_PER_WORD) + std::countr_one(data[word]);
|
||||
}
|
||||
}
|
||||
return N;
|
||||
};
|
||||
|
||||
const auto word_bits = [&](size_t index, u64 word) {
|
||||
const int empty_bits = std::countr_zero(word);
|
||||
const int ones_count = std::countr_one(word >> empty_bits);
|
||||
const size_t start_bit = index * BITS_PER_WORD + empty_bits;
|
||||
if (ones_count + empty_bits < BITS_PER_WORD) {
|
||||
return Range{start_bit, start_bit + ones_count};
|
||||
}
|
||||
return Range{start_bit, find_end_bit(index + 1)};
|
||||
};
|
||||
|
||||
const size_t start_word = start / BITS_PER_WORD;
|
||||
const size_t start_bit = start % BITS_PER_WORD;
|
||||
const u64 masked_first = data[start_word] & (~((1ULL << start_bit) - 1));
|
||||
if (masked_first) {
|
||||
return word_bits(start_word, masked_first);
|
||||
}
|
||||
|
||||
size_t word = start_word + 1;
|
||||
#ifdef BIT_ARRAY_USE_AVX
|
||||
for (; word + WORDS_PER_AVX <= WORD_COUNT; word += WORDS_PER_AVX) {
|
||||
const __m256i current =
|
||||
_mm256_loadu_si256(reinterpret_cast<const __m256i*>(&data[word]));
|
||||
if (!_mm256_testz_si256(current, current)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (; word < WORD_COUNT; ++word) {
|
||||
if (data[word] != 0) {
|
||||
return word_bits(word, data[word]);
|
||||
}
|
||||
}
|
||||
return {N, N};
|
||||
}
|
||||
|
||||
inline constexpr Range FirstRange() const {
|
||||
return FirstRangeFrom(0);
|
||||
}
|
||||
|
||||
Range LastRangeFrom(size_t end) const {
|
||||
if (end == 0) {
|
||||
return {0, 0};
|
||||
}
|
||||
if (end > N) {
|
||||
end = N;
|
||||
}
|
||||
const auto find_start_bit = [&](size_t word) {
|
||||
#ifdef BIT_ARRAY_USE_AVX
|
||||
const __m256i all_zero = _mm256_setzero_si256();
|
||||
for (; word >= WORDS_PER_AVX; word -= WORDS_PER_AVX) {
|
||||
const __m256i current = _mm256_loadu_si256(
|
||||
reinterpret_cast<const __m256i*>(&data[word - WORDS_PER_AVX]));
|
||||
const __m256i cmp = _mm256_cmpeq_epi64(current, all_zero);
|
||||
if (_mm256_movemask_epi8(cmp) != 0xFFFFFFFF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (; word > 0; --word) {
|
||||
if (data[word - 1] != ~0ULL) {
|
||||
return word * BITS_PER_WORD - std::countl_one(data[word - 1]);
|
||||
}
|
||||
}
|
||||
return size_t(0);
|
||||
};
|
||||
const auto word_bits = [&](size_t index, u64 word) {
|
||||
const int empty_bits = std::countl_zero(word);
|
||||
const int ones_count = std::countl_one(word << empty_bits);
|
||||
const size_t end_bit = index * BITS_PER_WORD - empty_bits;
|
||||
if (empty_bits + ones_count < BITS_PER_WORD) {
|
||||
return Range{end_bit - ones_count, end_bit};
|
||||
}
|
||||
return Range{find_start_bit(index - 1), end_bit};
|
||||
};
|
||||
const size_t end_word = ((end - 1) / BITS_PER_WORD) + 1;
|
||||
const size_t end_bit = (end - 1) % BITS_PER_WORD;
|
||||
u64 masked_last = data[end_word - 1];
|
||||
if (end_bit < BITS_PER_WORD - 1) {
|
||||
masked_last &= (1ULL << (end_bit + 1)) - 1;
|
||||
}
|
||||
if (masked_last) {
|
||||
return word_bits(end_word, masked_last);
|
||||
}
|
||||
size_t word = end_word - 1;
|
||||
#ifdef BIT_ARRAY_USE_AVX
|
||||
for (; word >= WORDS_PER_AVX; word -= WORDS_PER_AVX) {
|
||||
const __m256i current =
|
||||
_mm256_loadu_si256(reinterpret_cast<const __m256i*>(&data[word - WORDS_PER_AVX]));
|
||||
if (!_mm256_testz_si256(current, current)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
for (; word > 0; --word) {
|
||||
if (data[word - 1] != 0) {
|
||||
return word_bits(word, data[word - 1]);
|
||||
}
|
||||
}
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
inline constexpr Range LastRange() const {
|
||||
return LastRangeFrom(N);
|
||||
}
|
||||
|
||||
inline constexpr size_t Size() const {
|
||||
return N;
|
||||
}
|
||||
|
||||
inline constexpr BitArray& operator|=(const BitArray& other) {
|
||||
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||
data[i] |= other.data[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline constexpr BitArray& operator&=(const BitArray& other) {
|
||||
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||
data[i] &= other.data[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline constexpr BitArray& operator^=(const BitArray& other) {
|
||||
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||
data[i] ^= other.data[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline constexpr BitArray operator|(const BitArray& other) const {
|
||||
BitArray result = *this;
|
||||
result |= other;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline constexpr BitArray operator&(const BitArray& other) const {
|
||||
BitArray result = *this;
|
||||
result &= other;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline constexpr BitArray operator^(const BitArray& other) const {
|
||||
BitArray result = *this;
|
||||
result ^= other;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline constexpr BitArray operator~() const {
|
||||
BitArray result = *this;
|
||||
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||
result.data[i] = ~result.data[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline constexpr bool operator==(const BitArray& other) const {
|
||||
u64 result = 0;
|
||||
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||
result |= data[i] ^ other.data[i];
|
||||
}
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
inline constexpr bool operator!=(const BitArray& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<u64, WORD_COUNT> data{};
|
||||
};
|
||||
|
||||
} // namespace Common
|
@ -31,35 +31,54 @@ std::filesystem::path find_fs_path_or(const basic_value<TC>& v, const K& ky,
|
||||
|
||||
namespace Config {
|
||||
|
||||
// General
|
||||
static int volumeSlider = 100;
|
||||
static bool isNeo = false;
|
||||
static bool isDevKit = false;
|
||||
static bool playBGM = false;
|
||||
static bool isPSNSignedIn = false;
|
||||
static bool isTrophyPopupDisabled = false;
|
||||
static int BGMvolume = 50;
|
||||
static double trophyNotificationDuration = 6.0;
|
||||
static bool enableDiscordRPC = false;
|
||||
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 logFilter = "";
|
||||
static std::string logType = "sync";
|
||||
static std::string userName = "shadPS4";
|
||||
static std::string updateChannel;
|
||||
static std::string chooseHomeTab;
|
||||
static std::string backButtonBehavior = "left";
|
||||
static std::string chooseHomeTab = "General";
|
||||
static bool isShowSplash = false;
|
||||
static std::string isSideTrophy = "right";
|
||||
static bool compatibilityData = false;
|
||||
static bool checkCompatibilityOnStartup = false;
|
||||
|
||||
// Input
|
||||
static int cursorState = HideCursorState::Idle;
|
||||
static int cursorHideTimeout = 5; // 5 seconds (default)
|
||||
static bool useSpecialPad = false;
|
||||
static int specialPadClass = 1;
|
||||
static bool isMotionControlsEnabled = true;
|
||||
static bool isDebugDump = false;
|
||||
static bool isShaderDebug = false;
|
||||
static bool isShowSplash = false;
|
||||
static bool isAutoUpdate = false;
|
||||
static bool isAlwaysShowChangelog = false;
|
||||
static std::string isSideTrophy = "right";
|
||||
static bool useUnifiedInputConfig = true;
|
||||
|
||||
// These two entries aren't stored in the config
|
||||
static bool overrideControllerColor = false;
|
||||
static int controllerCustomColorRGB[3] = {0, 0, 255};
|
||||
|
||||
// GPU
|
||||
static u32 windowWidth = 1280;
|
||||
static u32 windowHeight = 720;
|
||||
static u32 internalScreenWidth = 1280;
|
||||
static u32 internalScreenHeight = 720;
|
||||
static bool isNullGpu = false;
|
||||
static bool shouldCopyGPUBuffers = false;
|
||||
static bool readbacksEnabled = false;
|
||||
static bool readbackLinearImagesEnabled = false;
|
||||
static bool directMemoryAccessEnabled = false;
|
||||
static bool shouldDumpShaders = false;
|
||||
static bool shouldPatchShaders = true;
|
||||
static bool shouldPatchShaders = false;
|
||||
static u32 vblankDivider = 1;
|
||||
static bool isFullscreen = false;
|
||||
static std::string fullscreenMode = "Windowed";
|
||||
static bool isHDRAllowed = false;
|
||||
|
||||
// Vulkan
|
||||
static s32 gpuId = -1;
|
||||
static bool vkValidation = false;
|
||||
static bool vkValidationSync = false;
|
||||
static bool vkValidationGpu = false;
|
||||
@ -67,49 +86,32 @@ static bool vkCrashDiagnostic = false;
|
||||
static bool vkHostMarkers = false;
|
||||
static bool vkGuestMarkers = false;
|
||||
static bool rdocEnable = false;
|
||||
static bool isFpsColor = true;
|
||||
static bool isSeparateLogFilesEnabled = false;
|
||||
static s16 cursorState = HideCursorState::Idle;
|
||||
static int cursorHideTimeout = 5; // 5 seconds (default)
|
||||
static double trophyNotificationDuration = 6.0;
|
||||
static bool useUnifiedInputConfig = true;
|
||||
static bool overrideControllerColor = false;
|
||||
static int controllerCustomColorRGB[3] = {0, 0, 255};
|
||||
static bool compatibilityData = false;
|
||||
static bool checkCompatibilityOnStartup = false;
|
||||
static std::string trophyKey;
|
||||
|
||||
// Gui
|
||||
// Debug
|
||||
static bool isDebugDump = false;
|
||||
static bool isShaderDebug = false;
|
||||
static bool isSeparateLogFilesEnabled = false;
|
||||
static bool isFpsColor = true;
|
||||
|
||||
// GUI
|
||||
static bool load_game_size = true;
|
||||
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;
|
||||
u32 main_window_geometry_y = 400;
|
||||
u32 main_window_geometry_w = 1280;
|
||||
u32 main_window_geometry_h = 720;
|
||||
u32 mw_themes = 0;
|
||||
u32 m_icon_size = 36;
|
||||
u32 m_icon_size_grid = 69;
|
||||
u32 m_slider_pos = 0;
|
||||
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_elf_viewer;
|
||||
std::vector<std::string> m_recent_files;
|
||||
std::string emulator_language = "en_US";
|
||||
static int backgroundImageOpacity = 50;
|
||||
static bool showBackgroundImage = true;
|
||||
static bool isFullscreen = false;
|
||||
static std::string fullscreenMode = "Windowed";
|
||||
static bool isHDRAllowed = false;
|
||||
static bool showLabelsUnderIcons = true;
|
||||
|
||||
// Language
|
||||
// Settings
|
||||
u32 m_language = 1; // english
|
||||
|
||||
// Keys
|
||||
static std::string trophyKey = "";
|
||||
|
||||
// Expected number of items in the config file
|
||||
static constexpr u64 total_entries = 54;
|
||||
|
||||
int getVolumeSlider() {
|
||||
return volumeSlider;
|
||||
}
|
||||
bool allowHDR() {
|
||||
return isHDRAllowed;
|
||||
}
|
||||
@ -154,11 +156,15 @@ bool GetLoadGameSizeEnabled() {
|
||||
|
||||
std::filesystem::path GetSaveDataPath() {
|
||||
if (save_data_path.empty()) {
|
||||
return Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir);
|
||||
return Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "savedata";
|
||||
}
|
||||
return save_data_path;
|
||||
}
|
||||
|
||||
void setVolumeSlider(int volumeValue) {
|
||||
volumeSlider = volumeValue;
|
||||
}
|
||||
|
||||
void setLoadGameSizeEnabled(bool enable) {
|
||||
load_game_size = enable;
|
||||
}
|
||||
@ -175,14 +181,6 @@ bool getIsFullscreen() {
|
||||
return isFullscreen;
|
||||
}
|
||||
|
||||
bool getShowLabelsUnderIcons() {
|
||||
return showLabelsUnderIcons;
|
||||
}
|
||||
|
||||
bool setShowLabelsUnderIcons() {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string getFullscreenMode() {
|
||||
return fullscreenMode;
|
||||
}
|
||||
@ -191,14 +189,6 @@ bool getisTrophyPopupDisabled() {
|
||||
return isTrophyPopupDisabled;
|
||||
}
|
||||
|
||||
bool getPlayBGM() {
|
||||
return playBGM;
|
||||
}
|
||||
|
||||
int getBGMvolume() {
|
||||
return BGMvolume;
|
||||
}
|
||||
|
||||
bool getEnableDiscordRPC() {
|
||||
return enableDiscordRPC;
|
||||
}
|
||||
@ -215,12 +205,20 @@ double getTrophyNotificationDuration() {
|
||||
return trophyNotificationDuration;
|
||||
}
|
||||
|
||||
u32 getScreenWidth() {
|
||||
return screenWidth;
|
||||
u32 getWindowWidth() {
|
||||
return windowWidth;
|
||||
}
|
||||
|
||||
u32 getScreenHeight() {
|
||||
return screenHeight;
|
||||
u32 getWindowHeight() {
|
||||
return windowHeight;
|
||||
}
|
||||
|
||||
u32 getInternalScreenWidth() {
|
||||
return internalScreenHeight;
|
||||
}
|
||||
|
||||
u32 getInternalScreenHeight() {
|
||||
return internalScreenHeight;
|
||||
}
|
||||
|
||||
s32 getGpuId() {
|
||||
@ -239,18 +237,10 @@ std::string getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
std::string getUpdateChannel() {
|
||||
return updateChannel;
|
||||
}
|
||||
|
||||
std::string getChooseHomeTab() {
|
||||
return chooseHomeTab;
|
||||
}
|
||||
|
||||
std::string getBackButtonBehavior() {
|
||||
return backButtonBehavior;
|
||||
}
|
||||
|
||||
bool getUseSpecialPad() {
|
||||
return useSpecialPad;
|
||||
}
|
||||
@ -275,14 +265,6 @@ bool showSplash() {
|
||||
return isShowSplash;
|
||||
}
|
||||
|
||||
bool autoUpdate() {
|
||||
return isAutoUpdate;
|
||||
}
|
||||
|
||||
bool alwaysShowChangelog() {
|
||||
return isAlwaysShowChangelog;
|
||||
}
|
||||
|
||||
std::string sideTrophy() {
|
||||
return isSideTrophy;
|
||||
}
|
||||
@ -295,6 +277,18 @@ bool copyGPUCmdBuffers() {
|
||||
return shouldCopyGPUBuffers;
|
||||
}
|
||||
|
||||
bool readbacks() {
|
||||
return readbacksEnabled;
|
||||
}
|
||||
|
||||
bool readbackLinearImages() {
|
||||
return readbackLinearImagesEnabled;
|
||||
}
|
||||
|
||||
bool directMemoryAccess() {
|
||||
return directMemoryAccessEnabled;
|
||||
}
|
||||
|
||||
bool dumpShaders() {
|
||||
return shouldDumpShaders;
|
||||
}
|
||||
@ -363,12 +357,20 @@ void setGpuId(s32 selectedGpuId) {
|
||||
gpuId = selectedGpuId;
|
||||
}
|
||||
|
||||
void setScreenWidth(u32 width) {
|
||||
screenWidth = width;
|
||||
void setWindowWidth(u32 width) {
|
||||
windowWidth = width;
|
||||
}
|
||||
|
||||
void setScreenHeight(u32 height) {
|
||||
screenHeight = height;
|
||||
void setWindowHeight(u32 height) {
|
||||
windowHeight = height;
|
||||
}
|
||||
|
||||
void setInternalScreenWidth(u32 width) {
|
||||
internalScreenWidth = width;
|
||||
}
|
||||
|
||||
void setInternalScreenHeight(u32 height) {
|
||||
internalScreenHeight = height;
|
||||
}
|
||||
|
||||
void setDebugDump(bool enable) {
|
||||
@ -383,14 +385,6 @@ void setShowSplash(bool enable) {
|
||||
isShowSplash = enable;
|
||||
}
|
||||
|
||||
void setAutoUpdate(bool enable) {
|
||||
isAutoUpdate = enable;
|
||||
}
|
||||
|
||||
void setAlwaysShowChangelog(bool enable) {
|
||||
isAlwaysShowChangelog = enable;
|
||||
}
|
||||
|
||||
void setSideTrophy(std::string side) {
|
||||
isSideTrophy = side;
|
||||
}
|
||||
@ -407,6 +401,14 @@ void setCopyGPUCmdBuffers(bool enable) {
|
||||
shouldCopyGPUBuffers = enable;
|
||||
}
|
||||
|
||||
void setReadbacks(bool enable) {
|
||||
readbacksEnabled = enable;
|
||||
}
|
||||
|
||||
void setDirectMemoryAccess(bool enable) {
|
||||
directMemoryAccessEnabled = enable;
|
||||
}
|
||||
|
||||
void setDumpShaders(bool enable) {
|
||||
shouldDumpShaders = enable;
|
||||
}
|
||||
@ -430,9 +432,6 @@ void setVblankDiv(u32 value) {
|
||||
void setIsFullscreen(bool enable) {
|
||||
isFullscreen = enable;
|
||||
}
|
||||
static void setShowLabelsUnderIcons(bool enable) {
|
||||
showLabelsUnderIcons = enable;
|
||||
}
|
||||
|
||||
void setFullscreenMode(std::string mode) {
|
||||
fullscreenMode = mode;
|
||||
@ -442,14 +441,6 @@ void setisTrophyPopupDisabled(bool disable) {
|
||||
isTrophyPopupDisabled = disable;
|
||||
}
|
||||
|
||||
void setPlayBGM(bool enable) {
|
||||
playBGM = enable;
|
||||
}
|
||||
|
||||
void setBGMvolume(int volume) {
|
||||
BGMvolume = volume;
|
||||
}
|
||||
|
||||
void setEnableDiscordRPC(bool enable) {
|
||||
enableDiscordRPC = enable;
|
||||
}
|
||||
@ -461,6 +452,7 @@ void setCursorState(s16 newCursorState) {
|
||||
void setCursorHideTimeout(int newcursorHideTimeout) {
|
||||
cursorHideTimeout = newcursorHideTimeout;
|
||||
}
|
||||
|
||||
void setTrophyNotificationDuration(double newTrophyNotificationDuration) {
|
||||
trophyNotificationDuration = newTrophyNotificationDuration;
|
||||
}
|
||||
@ -489,17 +481,10 @@ void setUserName(const std::string& type) {
|
||||
userName = type;
|
||||
}
|
||||
|
||||
void setUpdateChannel(const std::string& type) {
|
||||
updateChannel = type;
|
||||
}
|
||||
void setChooseHomeTab(const std::string& type) {
|
||||
chooseHomeTab = type;
|
||||
}
|
||||
|
||||
void setBackButtonBehavior(const std::string& type) {
|
||||
backButtonBehavior = type;
|
||||
}
|
||||
|
||||
void setUseSpecialPad(bool use) {
|
||||
useSpecialPad = use;
|
||||
}
|
||||
@ -520,13 +505,6 @@ void setCheckCompatibilityOnStartup(bool use) {
|
||||
checkCompatibilityOnStartup = use;
|
||||
}
|
||||
|
||||
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) {
|
||||
main_window_geometry_x = x;
|
||||
main_window_geometry_y = y;
|
||||
main_window_geometry_w = w;
|
||||
main_window_geometry_h = h;
|
||||
}
|
||||
|
||||
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled) {
|
||||
for (const auto& install_dir : settings_install_dirs) {
|
||||
if (install_dir.path == dir) {
|
||||
@ -559,52 +537,6 @@ void setAddonInstallDir(const std::filesystem::path& dir) {
|
||||
settings_addon_install_dir = dir;
|
||||
}
|
||||
|
||||
void setMainWindowTheme(u32 theme) {
|
||||
mw_themes = theme;
|
||||
}
|
||||
|
||||
void setIconSize(u32 size) {
|
||||
m_icon_size = size;
|
||||
}
|
||||
|
||||
void setIconSizeGrid(u32 size) {
|
||||
m_icon_size_grid = size;
|
||||
}
|
||||
|
||||
void setSliderPosition(u32 pos) {
|
||||
m_slider_pos = pos;
|
||||
}
|
||||
|
||||
void setSliderPositionGrid(u32 pos) {
|
||||
m_slider_pos_grid = pos;
|
||||
}
|
||||
|
||||
void setTableMode(u32 mode) {
|
||||
m_table_mode = mode;
|
||||
}
|
||||
|
||||
void setMainWindowWidth(u32 width) {
|
||||
m_window_size_W = width;
|
||||
}
|
||||
|
||||
void setMainWindowHeight(u32 height) {
|
||||
m_window_size_H = height;
|
||||
}
|
||||
|
||||
void setElfViewer(const std::vector<std::string>& elfList) {
|
||||
m_elf_viewer.resize(elfList.size());
|
||||
m_elf_viewer = elfList;
|
||||
}
|
||||
|
||||
void setRecentFiles(const std::vector<std::string>& recentFiles) {
|
||||
m_recent_files.resize(recentFiles.size());
|
||||
m_recent_files = recentFiles;
|
||||
}
|
||||
|
||||
void setEmulatorLanguage(std::string language) {
|
||||
emulator_language = language;
|
||||
}
|
||||
|
||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config) {
|
||||
settings_install_dirs.clear();
|
||||
for (const auto& dir : dirs_config) {
|
||||
@ -620,22 +552,6 @@ void setSaveDataPath(const std::filesystem::path& path) {
|
||||
save_data_path = path;
|
||||
}
|
||||
|
||||
u32 getMainWindowGeometryX() {
|
||||
return main_window_geometry_x;
|
||||
}
|
||||
|
||||
u32 getMainWindowGeometryY() {
|
||||
return main_window_geometry_y;
|
||||
}
|
||||
|
||||
u32 getMainWindowGeometryW() {
|
||||
return main_window_geometry_w;
|
||||
}
|
||||
|
||||
u32 getMainWindowGeometryH() {
|
||||
return main_window_geometry_h;
|
||||
}
|
||||
|
||||
const std::vector<std::filesystem::path> getGameInstallDirs() {
|
||||
std::vector<std::filesystem::path> enabled_dirs;
|
||||
for (const auto& dir : settings_install_dirs) {
|
||||
@ -662,50 +578,6 @@ std::filesystem::path getAddonInstallDir() {
|
||||
return settings_addon_install_dir;
|
||||
}
|
||||
|
||||
u32 getMainWindowTheme() {
|
||||
return mw_themes;
|
||||
}
|
||||
|
||||
u32 getIconSize() {
|
||||
return m_icon_size;
|
||||
}
|
||||
|
||||
u32 getIconSizeGrid() {
|
||||
return m_icon_size_grid;
|
||||
}
|
||||
|
||||
u32 getSliderPosition() {
|
||||
return m_slider_pos;
|
||||
}
|
||||
|
||||
u32 getSliderPositionGrid() {
|
||||
return m_slider_pos_grid;
|
||||
}
|
||||
|
||||
u32 getTableMode() {
|
||||
return m_table_mode;
|
||||
}
|
||||
|
||||
u32 getMainWindowWidth() {
|
||||
return m_window_size_W;
|
||||
}
|
||||
|
||||
u32 getMainWindowHeight() {
|
||||
return m_window_size_H;
|
||||
}
|
||||
|
||||
std::vector<std::string> getElfViewer() {
|
||||
return m_elf_viewer;
|
||||
}
|
||||
|
||||
std::vector<std::string> getRecentFiles() {
|
||||
return m_recent_files;
|
||||
}
|
||||
|
||||
std::string getEmulatorLanguage() {
|
||||
return emulator_language;
|
||||
}
|
||||
|
||||
u32 GetLanguage() {
|
||||
return m_language;
|
||||
}
|
||||
@ -714,20 +586,12 @@ bool getSeparateLogFilesEnabled() {
|
||||
return isSeparateLogFilesEnabled;
|
||||
}
|
||||
|
||||
int getBackgroundImageOpacity() {
|
||||
return backgroundImageOpacity;
|
||||
bool getPSNSignedIn() {
|
||||
return isPSNSignedIn;
|
||||
}
|
||||
|
||||
void setBackgroundImageOpacity(int opacity) {
|
||||
backgroundImageOpacity = std::clamp(opacity, 0, 100);
|
||||
}
|
||||
|
||||
bool getShowBackgroundImage() {
|
||||
return showBackgroundImage;
|
||||
}
|
||||
|
||||
void setShowBackgroundImage(bool show) {
|
||||
showBackgroundImage = show;
|
||||
void setPSNSignedIn(bool sign) {
|
||||
isPSNSignedIn = sign;
|
||||
}
|
||||
|
||||
void load(const std::filesystem::path& path) {
|
||||
@ -749,95 +613,105 @@ void load(const std::filesystem::path& path) {
|
||||
fmt::print("Got exception trying to load config file. Exception: {}\n", ex.what());
|
||||
return;
|
||||
}
|
||||
|
||||
u64 entry_count = 0;
|
||||
|
||||
if (data.contains("General")) {
|
||||
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 =
|
||||
toml::find_or<double>(general, "trophyNotificationDuration", 5.0);
|
||||
BGMvolume = toml::find_or<int>(general, "BGMvolume", 50);
|
||||
enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", true);
|
||||
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::g_is_release) {
|
||||
updateChannel = toml::find_or<std::string>(general, "updateChannel", "Release");
|
||||
} else {
|
||||
updateChannel = toml::find_or<std::string>(general, "updateChannel", "Nightly");
|
||||
}
|
||||
isShowSplash = toml::find_or<bool>(general, "showSplash", true);
|
||||
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");
|
||||
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false);
|
||||
checkCompatibilityOnStartup =
|
||||
toml::find_or<bool>(general, "checkCompatibilityOnStartup", false);
|
||||
chooseHomeTab = toml::find_or<std::string>(general, "chooseHomeTab", "Release");
|
||||
volumeSlider = toml::find_or<int>(general, "volumeSlider", volumeSlider);
|
||||
isNeo = toml::find_or<bool>(general, "isPS4Pro", isNeo);
|
||||
isDevKit = toml::find_or<bool>(general, "isDevKit", isDevKit);
|
||||
isPSNSignedIn = toml::find_or<bool>(general, "isPSNSignedIn", isPSNSignedIn);
|
||||
isTrophyPopupDisabled =
|
||||
toml::find_or<bool>(general, "isTrophyPopupDisabled", isTrophyPopupDisabled);
|
||||
trophyNotificationDuration = toml::find_or<double>(general, "trophyNotificationDuration",
|
||||
trophyNotificationDuration);
|
||||
enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", enableDiscordRPC);
|
||||
logFilter = toml::find_or<std::string>(general, "logFilter", logFilter);
|
||||
logType = toml::find_or<std::string>(general, "logType", logType);
|
||||
userName = toml::find_or<std::string>(general, "userName", userName);
|
||||
isShowSplash = toml::find_or<bool>(general, "showSplash", isShowSplash);
|
||||
isSideTrophy = toml::find_or<std::string>(general, "sideTrophy", isSideTrophy);
|
||||
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", compatibilityData);
|
||||
checkCompatibilityOnStartup = toml::find_or<bool>(general, "checkCompatibilityOnStartup",
|
||||
checkCompatibilityOnStartup);
|
||||
chooseHomeTab = toml::find_or<std::string>(general, "chooseHomeTab", chooseHomeTab);
|
||||
|
||||
entry_count += general.size();
|
||||
}
|
||||
|
||||
if (data.contains("Input")) {
|
||||
const toml::value& input = data.at("Input");
|
||||
|
||||
cursorState = toml::find_or<int>(input, "cursorState", HideCursorState::Idle);
|
||||
cursorHideTimeout = toml::find_or<int>(input, "cursorHideTimeout", 5);
|
||||
backButtonBehavior = toml::find_or<std::string>(input, "backButtonBehavior", "left");
|
||||
useSpecialPad = toml::find_or<bool>(input, "useSpecialPad", false);
|
||||
specialPadClass = toml::find_or<int>(input, "specialPadClass", 1);
|
||||
isMotionControlsEnabled = toml::find_or<bool>(input, "isMotionControlsEnabled", true);
|
||||
useUnifiedInputConfig = toml::find_or<bool>(input, "useUnifiedInputConfig", true);
|
||||
cursorState = toml::find_or<int>(input, "cursorState", cursorState);
|
||||
cursorHideTimeout = toml::find_or<int>(input, "cursorHideTimeout", cursorHideTimeout);
|
||||
useSpecialPad = toml::find_or<bool>(input, "useSpecialPad", useSpecialPad);
|
||||
specialPadClass = toml::find_or<int>(input, "specialPadClass", specialPadClass);
|
||||
isMotionControlsEnabled =
|
||||
toml::find_or<bool>(input, "isMotionControlsEnabled", isMotionControlsEnabled);
|
||||
useUnifiedInputConfig =
|
||||
toml::find_or<bool>(input, "useUnifiedInputConfig", useUnifiedInputConfig);
|
||||
|
||||
entry_count += input.size();
|
||||
}
|
||||
|
||||
if (data.contains("GPU")) {
|
||||
const toml::value& gpu = data.at("GPU");
|
||||
|
||||
screenWidth = toml::find_or<int>(gpu, "screenWidth", screenWidth);
|
||||
screenHeight = toml::find_or<int>(gpu, "screenHeight", screenHeight);
|
||||
isNullGpu = toml::find_or<bool>(gpu, "nullGpu", false);
|
||||
shouldCopyGPUBuffers = toml::find_or<bool>(gpu, "copyGPUBuffers", false);
|
||||
shouldDumpShaders = toml::find_or<bool>(gpu, "dumpShaders", false);
|
||||
shouldPatchShaders = toml::find_or<bool>(gpu, "patchShaders", true);
|
||||
vblankDivider = toml::find_or<int>(gpu, "vblankDivider", 1);
|
||||
isFullscreen = toml::find_or<bool>(gpu, "Fullscreen", false);
|
||||
fullscreenMode = toml::find_or<std::string>(gpu, "FullscreenMode", "Windowed");
|
||||
isHDRAllowed = toml::find_or<bool>(gpu, "allowHDR", false);
|
||||
windowWidth = toml::find_or<int>(gpu, "screenWidth", windowWidth);
|
||||
windowHeight = toml::find_or<int>(gpu, "screenHeight", windowHeight);
|
||||
internalScreenWidth = toml::find_or<int>(gpu, "internalScreenWidth", internalScreenWidth);
|
||||
internalScreenHeight =
|
||||
toml::find_or<int>(gpu, "internalScreenHeight", internalScreenHeight);
|
||||
isNullGpu = toml::find_or<bool>(gpu, "nullGpu", isNullGpu);
|
||||
shouldCopyGPUBuffers = toml::find_or<bool>(gpu, "copyGPUBuffers", shouldCopyGPUBuffers);
|
||||
readbacksEnabled = toml::find_or<bool>(gpu, "readbacks", readbacksEnabled);
|
||||
readbackLinearImagesEnabled =
|
||||
toml::find_or<bool>(gpu, "readbackLinearImages", readbackLinearImagesEnabled);
|
||||
directMemoryAccessEnabled =
|
||||
toml::find_or<bool>(gpu, "directMemoryAccess", directMemoryAccessEnabled);
|
||||
shouldDumpShaders = toml::find_or<bool>(gpu, "dumpShaders", shouldDumpShaders);
|
||||
shouldPatchShaders = toml::find_or<bool>(gpu, "patchShaders", shouldPatchShaders);
|
||||
vblankDivider = toml::find_or<int>(gpu, "vblankDivider", vblankDivider);
|
||||
isFullscreen = toml::find_or<bool>(gpu, "Fullscreen", isFullscreen);
|
||||
fullscreenMode = toml::find_or<std::string>(gpu, "FullscreenMode", fullscreenMode);
|
||||
isHDRAllowed = toml::find_or<bool>(gpu, "allowHDR", isHDRAllowed);
|
||||
|
||||
entry_count += gpu.size();
|
||||
}
|
||||
|
||||
if (data.contains("Vulkan")) {
|
||||
const toml::value& vk = data.at("Vulkan");
|
||||
|
||||
gpuId = toml::find_or<int>(vk, "gpuId", -1);
|
||||
vkValidation = toml::find_or<bool>(vk, "validation", false);
|
||||
vkValidationSync = toml::find_or<bool>(vk, "validation_sync", false);
|
||||
vkValidationGpu = toml::find_or<bool>(vk, "validation_gpu", true);
|
||||
vkCrashDiagnostic = toml::find_or<bool>(vk, "crashDiagnostic", false);
|
||||
vkHostMarkers = toml::find_or<bool>(vk, "hostMarkers", false);
|
||||
vkGuestMarkers = toml::find_or<bool>(vk, "guestMarkers", false);
|
||||
rdocEnable = toml::find_or<bool>(vk, "rdocEnable", false);
|
||||
gpuId = toml::find_or<int>(vk, "gpuId", gpuId);
|
||||
vkValidation = toml::find_or<bool>(vk, "validation", vkValidation);
|
||||
vkValidationSync = toml::find_or<bool>(vk, "validation_sync", vkValidationSync);
|
||||
vkValidationGpu = toml::find_or<bool>(vk, "validation_gpu", vkValidationGpu);
|
||||
vkCrashDiagnostic = toml::find_or<bool>(vk, "crashDiagnostic", vkCrashDiagnostic);
|
||||
vkHostMarkers = toml::find_or<bool>(vk, "hostMarkers", vkHostMarkers);
|
||||
vkGuestMarkers = toml::find_or<bool>(vk, "guestMarkers", vkGuestMarkers);
|
||||
rdocEnable = toml::find_or<bool>(vk, "rdocEnable", rdocEnable);
|
||||
|
||||
entry_count += vk.size();
|
||||
}
|
||||
|
||||
if (data.contains("Debug")) {
|
||||
const toml::value& debug = data.at("Debug");
|
||||
|
||||
isDebugDump = toml::find_or<bool>(debug, "DebugDump", false);
|
||||
isSeparateLogFilesEnabled = toml::find_or<bool>(debug, "isSeparateLogFilesEnabled", false);
|
||||
isShaderDebug = toml::find_or<bool>(debug, "CollectShader", false);
|
||||
isFpsColor = toml::find_or<bool>(debug, "FPSColor", true);
|
||||
isDebugDump = toml::find_or<bool>(debug, "DebugDump", isDebugDump);
|
||||
isSeparateLogFilesEnabled =
|
||||
toml::find_or<bool>(debug, "isSeparateLogFilesEnabled", isSeparateLogFilesEnabled);
|
||||
isShaderDebug = toml::find_or<bool>(debug, "CollectShader", isShaderDebug);
|
||||
isFpsColor = toml::find_or<bool>(debug, "FPSColor", isFpsColor);
|
||||
|
||||
entry_count += debug.size();
|
||||
}
|
||||
|
||||
if (data.contains("GUI")) {
|
||||
const toml::value& gui = data.at("GUI");
|
||||
|
||||
load_game_size = toml::find_or<bool>(gui, "loadGameSizeEnabled", true);
|
||||
m_icon_size = toml::find_or<int>(gui, "iconSize", 0);
|
||||
m_icon_size_grid = toml::find_or<int>(gui, "iconSizeGrid", 0);
|
||||
m_slider_pos = toml::find_or<int>(gui, "sliderPos", 0);
|
||||
m_slider_pos_grid = toml::find_or<int>(gui, "sliderPosGrid", 0);
|
||||
mw_themes = toml::find_or<int>(gui, "theme", 0);
|
||||
m_window_size_W = toml::find_or<int>(gui, "mw_width", 0);
|
||||
m_window_size_H = toml::find_or<int>(gui, "mw_height", 0);
|
||||
load_game_size = toml::find_or<bool>(gui, "loadGameSizeEnabled", load_game_size);
|
||||
|
||||
const auto install_dir_array =
|
||||
toml::find_or<std::vector<std::u8string>>(gui, "installDirs", {});
|
||||
@ -859,41 +733,31 @@ void load(const std::filesystem::path& path) {
|
||||
{std::filesystem::path{install_dir_array[i]}, install_dirs_enabled[i]});
|
||||
}
|
||||
|
||||
save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {});
|
||||
save_data_path = toml::find_fs_path_or(gui, "saveDataPath", save_data_path);
|
||||
|
||||
settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {});
|
||||
main_window_geometry_x = toml::find_or<int>(gui, "geometry_x", 0);
|
||||
main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0);
|
||||
main_window_geometry_w = toml::find_or<int>(gui, "geometry_w", 0);
|
||||
main_window_geometry_h = toml::find_or<int>(gui, "geometry_h", 0);
|
||||
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);
|
||||
emulator_language = toml::find_or<std::string>(gui, "emulatorLanguage", "en_US");
|
||||
backgroundImageOpacity = toml::find_or<int>(gui, "backgroundImageOpacity", 50);
|
||||
showBackgroundImage = toml::find_or<bool>(gui, "showBackgroundImage", true);
|
||||
settings_addon_install_dir =
|
||||
toml::find_fs_path_or(gui, "addonInstallDir", settings_addon_install_dir);
|
||||
|
||||
entry_count += gui.size();
|
||||
}
|
||||
|
||||
if (data.contains("Settings")) {
|
||||
const toml::value& settings = data.at("Settings");
|
||||
m_language = toml::find_or<int>(settings, "consoleLanguage", m_language);
|
||||
|
||||
m_language = toml::find_or<int>(settings, "consoleLanguage", 1);
|
||||
entry_count += settings.size();
|
||||
}
|
||||
|
||||
if (data.contains("Keys")) {
|
||||
const toml::value& keys = data.at("Keys");
|
||||
trophyKey = toml::find_or<std::string>(keys, "TrophyKey", "");
|
||||
trophyKey = toml::find_or<std::string>(keys, "TrophyKey", trophyKey);
|
||||
|
||||
entry_count += keys.size();
|
||||
}
|
||||
|
||||
// Check if the loaded language is in the allowed list
|
||||
const std::vector<std::string> allowed_languages = {
|
||||
"ar_SA", "da_DK", "de_DE", "el_GR", "en_US", "es_ES", "fa_IR", "fi_FI", "fr_FR", "hu_HU",
|
||||
"id_ID", "it_IT", "ja_JP", "ko_KR", "lt_LT", "nb_NO", "nl_NL", "pl_PL", "pt_BR", "pt_PT",
|
||||
"ro_RO", "ru_RU", "sq_AL", "sv_SE", "tr_TR", "uk_UA", "vi_VN", "zh_CN", "zh_TW"};
|
||||
|
||||
if (std::find(allowed_languages.begin(), allowed_languages.end(), emulator_language) ==
|
||||
allowed_languages.end()) {
|
||||
emulator_language = "en_US"; // Default to en_US if not in the list
|
||||
// Run save after loading to generate any missing fields with default values.
|
||||
if (entry_count != total_entries) {
|
||||
fmt::print("Outdated config detected, updating config file.\n");
|
||||
save(path);
|
||||
}
|
||||
}
|
||||
@ -951,35 +815,36 @@ void save(const std::filesystem::path& path) {
|
||||
fmt::print("Saving new configuration file {}\n", fmt::UTF(path.u8string()));
|
||||
}
|
||||
|
||||
data["General"]["volumeSlider"] = volumeSlider;
|
||||
data["General"]["isPS4Pro"] = isNeo;
|
||||
data["General"]["isDevKit"] = isDevKit;
|
||||
data["General"]["isPSNSignedIn"] = isPSNSignedIn;
|
||||
data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled;
|
||||
data["General"]["trophyNotificationDuration"] = trophyNotificationDuration;
|
||||
data["General"]["playBGM"] = playBGM;
|
||||
data["General"]["BGMvolume"] = BGMvolume;
|
||||
data["General"]["enableDiscordRPC"] = enableDiscordRPC;
|
||||
data["General"]["logFilter"] = logFilter;
|
||||
data["General"]["logType"] = logType;
|
||||
data["General"]["userName"] = userName;
|
||||
data["General"]["updateChannel"] = updateChannel;
|
||||
data["General"]["chooseHomeTab"] = chooseHomeTab;
|
||||
data["General"]["showSplash"] = isShowSplash;
|
||||
data["General"]["autoUpdate"] = isAutoUpdate;
|
||||
data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog;
|
||||
data["General"]["sideTrophy"] = isSideTrophy;
|
||||
data["General"]["compatibilityEnabled"] = compatibilityData;
|
||||
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
|
||||
data["Input"]["cursorState"] = cursorState;
|
||||
data["Input"]["cursorHideTimeout"] = cursorHideTimeout;
|
||||
data["Input"]["backButtonBehavior"] = backButtonBehavior;
|
||||
data["Input"]["useSpecialPad"] = useSpecialPad;
|
||||
data["Input"]["specialPadClass"] = specialPadClass;
|
||||
data["Input"]["isMotionControlsEnabled"] = isMotionControlsEnabled;
|
||||
data["Input"]["useUnifiedInputConfig"] = useUnifiedInputConfig;
|
||||
data["GPU"]["screenWidth"] = screenWidth;
|
||||
data["GPU"]["screenHeight"] = screenHeight;
|
||||
data["GPU"]["screenWidth"] = windowWidth;
|
||||
data["GPU"]["screenHeight"] = windowHeight;
|
||||
data["GPU"]["internalScreenWidth"] = internalScreenWidth;
|
||||
data["GPU"]["internalScreenHeight"] = internalScreenHeight;
|
||||
data["GPU"]["nullGpu"] = isNullGpu;
|
||||
data["GPU"]["copyGPUBuffers"] = shouldCopyGPUBuffers;
|
||||
data["GPU"]["readbacks"] = readbacksEnabled;
|
||||
data["GPU"]["readbackLinearImages"] = readbackLinearImagesEnabled;
|
||||
data["GPU"]["directMemoryAccess"] = directMemoryAccessEnabled;
|
||||
data["GPU"]["dumpShaders"] = shouldDumpShaders;
|
||||
data["GPU"]["patchShaders"] = shouldPatchShaders;
|
||||
data["GPU"]["vblankDivider"] = vblankDivider;
|
||||
@ -1034,9 +899,6 @@ void save(const std::filesystem::path& path) {
|
||||
|
||||
data["GUI"]["addonInstallDir"] =
|
||||
std::string{fmt::UTF(settings_addon_install_dir.u8string()).data};
|
||||
data["GUI"]["emulatorLanguage"] = emulator_language;
|
||||
data["GUI"]["backgroundImageOpacity"] = backgroundImageOpacity;
|
||||
data["GUI"]["showBackgroundImage"] = showBackgroundImage;
|
||||
data["Settings"]["consoleLanguage"] = m_language;
|
||||
|
||||
// Sorting of TOML sections
|
||||
@ -1045,90 +907,57 @@ void save(const std::filesystem::path& path) {
|
||||
std::ofstream file(path, std::ios::binary);
|
||||
file << data;
|
||||
file.close();
|
||||
|
||||
saveMainWindow(path);
|
||||
}
|
||||
|
||||
void saveMainWindow(const std::filesystem::path& path) {
|
||||
toml::ordered_value data;
|
||||
|
||||
std::error_code error;
|
||||
if (std::filesystem::exists(path, error)) {
|
||||
try {
|
||||
std::ifstream ifs;
|
||||
ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
ifs.open(path, std::ios_base::binary);
|
||||
data = toml::parse<toml::ordered_type_config>(
|
||||
ifs, std::string{fmt::UTF(path.filename().u8string()).data});
|
||||
} catch (const std::exception& ex) {
|
||||
fmt::print("Exception trying to parse config file. Exception: {}\n", ex.what());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (error) {
|
||||
fmt::print("Filesystem error: {}\n", error.message());
|
||||
}
|
||||
fmt::print("Saving new configuration file {}\n", fmt::UTF(path.u8string()));
|
||||
}
|
||||
|
||||
data["GUI"]["mw_width"] = m_window_size_W;
|
||||
data["GUI"]["mw_height"] = m_window_size_H;
|
||||
data["GUI"]["theme"] = mw_themes;
|
||||
data["GUI"]["iconSize"] = m_icon_size;
|
||||
data["GUI"]["sliderPos"] = m_slider_pos;
|
||||
data["GUI"]["iconSizeGrid"] = m_icon_size_grid;
|
||||
data["GUI"]["sliderPosGrid"] = m_slider_pos_grid;
|
||||
data["GUI"]["gameTableMode"] = m_table_mode;
|
||||
data["GUI"]["geometry_x"] = main_window_geometry_x;
|
||||
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"]["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();
|
||||
}
|
||||
|
||||
void setDefaultValues() {
|
||||
isHDRAllowed = false;
|
||||
// General
|
||||
volumeSlider = 100;
|
||||
isNeo = false;
|
||||
isDevKit = false;
|
||||
isFullscreen = false;
|
||||
isPSNSignedIn = false;
|
||||
isTrophyPopupDisabled = false;
|
||||
playBGM = false;
|
||||
BGMvolume = 50;
|
||||
enableDiscordRPC = true;
|
||||
screenWidth = 1280;
|
||||
screenHeight = 720;
|
||||
trophyNotificationDuration = 6.0;
|
||||
enableDiscordRPC = false;
|
||||
logFilter = "";
|
||||
logType = "sync";
|
||||
userName = "shadPS4";
|
||||
if (Common::g_is_release) {
|
||||
updateChannel = "Release";
|
||||
} else {
|
||||
updateChannel = "Nightly";
|
||||
}
|
||||
chooseHomeTab = "General";
|
||||
isShowSplash = false;
|
||||
isSideTrophy = "right";
|
||||
compatibilityData = false;
|
||||
checkCompatibilityOnStartup = false;
|
||||
|
||||
// Input
|
||||
cursorState = HideCursorState::Idle;
|
||||
cursorHideTimeout = 5;
|
||||
trophyNotificationDuration = 6.0;
|
||||
backButtonBehavior = "left";
|
||||
useSpecialPad = false;
|
||||
specialPadClass = 1;
|
||||
isDebugDump = false;
|
||||
isShaderDebug = false;
|
||||
isShowSplash = false;
|
||||
isAutoUpdate = false;
|
||||
isAlwaysShowChangelog = false;
|
||||
isSideTrophy = "right";
|
||||
isMotionControlsEnabled = true;
|
||||
useUnifiedInputConfig = true;
|
||||
overrideControllerColor = false;
|
||||
controllerCustomColorRGB[0] = 0;
|
||||
controllerCustomColorRGB[1] = 0;
|
||||
controllerCustomColorRGB[2] = 255;
|
||||
|
||||
// GPU
|
||||
windowWidth = 1280;
|
||||
windowHeight = 720;
|
||||
internalScreenWidth = 1280;
|
||||
internalScreenHeight = 720;
|
||||
isNullGpu = false;
|
||||
shouldCopyGPUBuffers = false;
|
||||
readbacksEnabled = false;
|
||||
readbackLinearImagesEnabled = false;
|
||||
directMemoryAccessEnabled = false;
|
||||
shouldDumpShaders = false;
|
||||
shouldPatchShaders = false;
|
||||
vblankDivider = 1;
|
||||
isFullscreen = false;
|
||||
fullscreenMode = "Windowed";
|
||||
isHDRAllowed = false;
|
||||
|
||||
// Vulkan
|
||||
gpuId = -1;
|
||||
vkValidation = false;
|
||||
vkValidationSync = false;
|
||||
vkValidationGpu = false;
|
||||
@ -1136,13 +965,18 @@ void setDefaultValues() {
|
||||
vkHostMarkers = false;
|
||||
vkGuestMarkers = false;
|
||||
rdocEnable = false;
|
||||
emulator_language = "en_US";
|
||||
|
||||
// Debug
|
||||
isDebugDump = false;
|
||||
isShaderDebug = false;
|
||||
isSeparateLogFilesEnabled = false;
|
||||
isFpsColor = true;
|
||||
|
||||
// GUI
|
||||
load_game_size = true;
|
||||
|
||||
// Settings
|
||||
m_language = 1;
|
||||
gpuId = -1;
|
||||
compatibilityData = false;
|
||||
checkCompatibilityOnStartup = false;
|
||||
backgroundImageOpacity = 50;
|
||||
showBackgroundImage = true;
|
||||
}
|
||||
|
||||
constexpr std::string_view GetDefaultKeyboardConfig() {
|
||||
@ -1168,7 +1002,7 @@ l3 = x
|
||||
r3 = m
|
||||
|
||||
options = enter
|
||||
touchpad = space
|
||||
touchpad_center = space
|
||||
|
||||
pad_up = up
|
||||
pad_down = down
|
||||
@ -1200,7 +1034,7 @@ r2 = r2
|
||||
r3 = r3
|
||||
|
||||
options = options
|
||||
touchpad = back
|
||||
touchpad_center = back
|
||||
|
||||
pad_up = pad_up
|
||||
pad_down = pad_down
|
||||
|
@ -14,172 +14,131 @@ struct GameInstallDir {
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
enum HideCursorState : s16 { Never, Idle, Always };
|
||||
enum HideCursorState : int { Never, Idle, Always };
|
||||
|
||||
void load(const std::filesystem::path& path);
|
||||
void save(const std::filesystem::path& path);
|
||||
void saveMainWindow(const std::filesystem::path& path);
|
||||
|
||||
int getVolumeSlider();
|
||||
void setVolumeSlider(int volumeValue);
|
||||
std::string getTrophyKey();
|
||||
void setTrophyKey(std::string key);
|
||||
bool getIsFullscreen();
|
||||
void setIsFullscreen(bool enable);
|
||||
std::string getFullscreenMode();
|
||||
void setFullscreenMode(std::string mode);
|
||||
u32 getWindowWidth();
|
||||
u32 getWindowHeight();
|
||||
void setWindowWidth(u32 width);
|
||||
void setWindowHeight(u32 height);
|
||||
u32 getInternalScreenWidth();
|
||||
u32 getInternalScreenHeight();
|
||||
void setInternalScreenWidth(u32 width);
|
||||
void setInternalScreenHeight(u32 height);
|
||||
bool debugDump();
|
||||
void setDebugDump(bool enable);
|
||||
s32 getGpuId();
|
||||
void setGpuId(s32 selectedGpuId);
|
||||
bool allowHDR();
|
||||
void setAllowHDR(bool enable);
|
||||
bool collectShadersForDebug();
|
||||
void setCollectShaderForDebug(bool enable);
|
||||
bool showSplash();
|
||||
void setShowSplash(bool enable);
|
||||
std::string sideTrophy();
|
||||
void setSideTrophy(std::string side);
|
||||
bool nullGpu();
|
||||
void setNullGpu(bool enable);
|
||||
bool copyGPUCmdBuffers();
|
||||
void setCopyGPUCmdBuffers(bool enable);
|
||||
bool readbacks();
|
||||
void setReadbacks(bool enable);
|
||||
bool readbackLinearImages();
|
||||
bool directMemoryAccess();
|
||||
void setDirectMemoryAccess(bool enable);
|
||||
bool dumpShaders();
|
||||
void setDumpShaders(bool enable);
|
||||
u32 vblankDiv();
|
||||
void setVblankDiv(u32 value);
|
||||
bool getisTrophyPopupDisabled();
|
||||
void setisTrophyPopupDisabled(bool disable);
|
||||
s16 getCursorState();
|
||||
void setCursorState(s16 cursorState);
|
||||
bool vkValidationEnabled();
|
||||
void setVkValidation(bool enable);
|
||||
bool vkValidationSyncEnabled();
|
||||
void setVkSyncValidation(bool enable);
|
||||
bool getVkCrashDiagnosticEnabled();
|
||||
void setVkCrashDiagnosticEnabled(bool enable);
|
||||
bool getVkHostMarkersEnabled();
|
||||
void setVkHostMarkersEnabled(bool enable);
|
||||
bool getVkGuestMarkersEnabled();
|
||||
void setVkGuestMarkersEnabled(bool enable);
|
||||
bool getEnableDiscordRPC();
|
||||
void setEnableDiscordRPC(bool enable);
|
||||
bool isRdocEnabled();
|
||||
void setRdocEnabled(bool enable);
|
||||
std::string getLogType();
|
||||
void setLogType(const std::string& type);
|
||||
std::string getLogFilter();
|
||||
void setLogFilter(const std::string& type);
|
||||
double getTrophyNotificationDuration();
|
||||
void setTrophyNotificationDuration(double newTrophyNotificationDuration);
|
||||
int getCursorHideTimeout();
|
||||
void setCursorHideTimeout(int newcursorHideTimeout);
|
||||
void setSeparateLogFilesEnabled(bool enabled);
|
||||
bool getSeparateLogFilesEnabled();
|
||||
u32 GetLanguage();
|
||||
void setLanguage(u32 language);
|
||||
void setUseSpecialPad(bool use);
|
||||
bool getUseSpecialPad();
|
||||
void setSpecialPadClass(int type);
|
||||
int getSpecialPadClass();
|
||||
bool getPSNSignedIn();
|
||||
void setPSNSignedIn(bool sign); // no ui setting
|
||||
bool patchShaders(); // no set
|
||||
bool fpsColor(); // no set
|
||||
bool isNeoModeConsole();
|
||||
void setNeoMode(bool enable); // no ui setting
|
||||
bool isDevKitConsole(); // no set
|
||||
bool vkValidationGpuEnabled(); // no set
|
||||
bool getIsMotionControlsEnabled();
|
||||
void setIsMotionControlsEnabled(bool use);
|
||||
|
||||
// TODO
|
||||
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 getCompatibilityEnabled();
|
||||
bool getCheckCompatibilityOnStartup();
|
||||
int getBackgroundImageOpacity();
|
||||
bool getShowBackgroundImage();
|
||||
|
||||
std::string getLogFilter();
|
||||
std::string getLogType();
|
||||
std::string getUserName();
|
||||
std::string getUpdateChannel();
|
||||
std::string getChooseHomeTab();
|
||||
|
||||
s16 getCursorState();
|
||||
int getCursorHideTimeout();
|
||||
double getTrophyNotificationDuration();
|
||||
std::string getBackButtonBehavior();
|
||||
bool getUseSpecialPad();
|
||||
int getSpecialPadClass();
|
||||
bool getIsMotionControlsEnabled();
|
||||
bool GetUseUnifiedInputConfig();
|
||||
void SetUseUnifiedInputConfig(bool use);
|
||||
bool GetOverrideControllerColor();
|
||||
void SetOverrideControllerColor(bool enable);
|
||||
int* GetControllerCustomColor();
|
||||
void SetControllerCustomColor(int r, int b, int g);
|
||||
|
||||
u32 getScreenWidth();
|
||||
u32 getScreenHeight();
|
||||
s32 getGpuId();
|
||||
bool allowHDR();
|
||||
|
||||
bool debugDump();
|
||||
bool collectShadersForDebug();
|
||||
bool showSplash();
|
||||
bool autoUpdate();
|
||||
bool alwaysShowChangelog();
|
||||
std::string sideTrophy();
|
||||
bool nullGpu();
|
||||
bool copyGPUCmdBuffers();
|
||||
bool dumpShaders();
|
||||
bool patchShaders();
|
||||
bool isRdocEnabled();
|
||||
bool fpsColor();
|
||||
u32 vblankDiv();
|
||||
|
||||
void setDebugDump(bool enable);
|
||||
void setCollectShaderForDebug(bool enable);
|
||||
void setShowSplash(bool enable);
|
||||
void setAutoUpdate(bool enable);
|
||||
void setAlwaysShowChangelog(bool enable);
|
||||
void setSideTrophy(std::string side);
|
||||
void setNullGpu(bool enable);
|
||||
void setAllowHDR(bool enable);
|
||||
void setCopyGPUCmdBuffers(bool enable);
|
||||
void setDumpShaders(bool enable);
|
||||
void setVblankDiv(u32 value);
|
||||
void setGpuId(s32 selectedGpuId);
|
||||
void setScreenWidth(u32 width);
|
||||
void setScreenHeight(u32 height);
|
||||
void setIsFullscreen(bool enable);
|
||||
void setFullscreenMode(std::string mode);
|
||||
void setisTrophyPopupDisabled(bool disable);
|
||||
void setPlayBGM(bool enable);
|
||||
void setBGMvolume(int volume);
|
||||
void setEnableDiscordRPC(bool enable);
|
||||
void setLanguage(u32 language);
|
||||
void setNeoMode(bool enable);
|
||||
void setUserName(const std::string& type);
|
||||
void setUpdateChannel(const std::string& type);
|
||||
void setChooseHomeTab(const std::string& type);
|
||||
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);
|
||||
void setBackgroundImageOpacity(int opacity);
|
||||
void setShowBackgroundImage(bool show);
|
||||
|
||||
void setCursorState(s16 cursorState);
|
||||
void setCursorHideTimeout(int newcursorHideTimeout);
|
||||
void setTrophyNotificationDuration(double newTrophyNotificationDuration);
|
||||
void setBackButtonBehavior(const std::string& type);
|
||||
void setUseSpecialPad(bool use);
|
||||
void setSpecialPadClass(int type);
|
||||
void setIsMotionControlsEnabled(bool use);
|
||||
|
||||
void setLogType(const std::string& type);
|
||||
void setLogFilter(const std::string& type);
|
||||
void setSeparateLogFilesEnabled(bool enabled);
|
||||
bool getSeparateLogFilesEnabled();
|
||||
void setVkValidation(bool enable);
|
||||
void setVkSyncValidation(bool enable);
|
||||
void setRdocEnabled(bool enable);
|
||||
|
||||
bool vkValidationEnabled();
|
||||
bool vkValidationSyncEnabled();
|
||||
bool vkValidationGpuEnabled();
|
||||
bool getVkCrashDiagnosticEnabled();
|
||||
bool getVkHostMarkersEnabled();
|
||||
bool getVkGuestMarkersEnabled();
|
||||
void setVkCrashDiagnosticEnabled(bool enable);
|
||||
void setVkHostMarkersEnabled(bool enable);
|
||||
void setVkGuestMarkersEnabled(bool enable);
|
||||
|
||||
// Gui
|
||||
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);
|
||||
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);
|
||||
void setIconSizeGrid(u32 size);
|
||||
void setSliderPosition(u32 pos);
|
||||
void setSliderPositionGrid(u32 pos);
|
||||
void setTableMode(u32 mode);
|
||||
void setMainWindowWidth(u32 width);
|
||||
void setMainWindowHeight(u32 height);
|
||||
void setElfViewer(const std::vector<std::string>& elfList);
|
||||
void setRecentFiles(const std::vector<std::string>& recentFiles);
|
||||
void setEmulatorLanguage(std::string language);
|
||||
|
||||
u32 getMainWindowGeometryX();
|
||||
u32 getMainWindowGeometryY();
|
||||
u32 getMainWindowGeometryW();
|
||||
u32 getMainWindowGeometryH();
|
||||
const std::vector<std::filesystem::path> getGameInstallDirs();
|
||||
const std::vector<bool> getGameInstallDirsEnabled();
|
||||
std::filesystem::path getAddonInstallDir();
|
||||
u32 getMainWindowTheme();
|
||||
u32 getIconSize();
|
||||
u32 getIconSizeGrid();
|
||||
u32 getSliderPosition();
|
||||
u32 getSliderPositionGrid();
|
||||
u32 getTableMode();
|
||||
u32 getMainWindowWidth();
|
||||
u32 getMainWindowHeight();
|
||||
std::vector<std::string> getElfViewer();
|
||||
std::vector<std::string> getRecentFiles();
|
||||
std::string getEmulatorLanguage();
|
||||
|
||||
void setDefaultValues();
|
||||
|
||||
// todo: name and function location pending
|
||||
std::filesystem::path GetFoolproofKbmConfigFile(const std::string& game_id = "");
|
||||
|
||||
// settings
|
||||
u32 GetLanguage();
|
||||
}; // namespace Config
|
||||
|
@ -71,6 +71,7 @@ class ElfInfo {
|
||||
PSFAttributes psf_attributes{};
|
||||
|
||||
std::filesystem::path splash_path{};
|
||||
std::filesystem::path game_folder{};
|
||||
|
||||
public:
|
||||
static constexpr u32 FW_15 = 0x1500000;
|
||||
@ -123,6 +124,10 @@ public:
|
||||
[[nodiscard]] const std::filesystem::path& GetSplashPath() const {
|
||||
return splash_path;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::filesystem::path& GetGameFolder() const {
|
||||
return game_folder;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
|
@ -131,9 +131,7 @@ namespace {
|
||||
case SeekOrigin::End:
|
||||
return SEEK_END;
|
||||
default:
|
||||
LOG_ERROR(Common_Filesystem, "Unsupported origin {}, defaulting to SEEK_SET",
|
||||
static_cast<u32>(origin));
|
||||
return SEEK_SET;
|
||||
UNREACHABLE_MSG("Impossible SeekOrigin {}", static_cast<u32>(origin));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,8 +61,6 @@ 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 {
|
||||
@ -188,7 +186,9 @@ public:
|
||||
|
||||
template <typename T>
|
||||
size_t WriteRaw(const void* data, size_t size) const {
|
||||
return std::fwrite(data, sizeof(T), size, file);
|
||||
auto bytes = std::fwrite(data, sizeof(T), size, file);
|
||||
std::fflush(file);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -137,6 +137,11 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
||||
SUB(Lib, NpParty) \
|
||||
SUB(Lib, Zlib) \
|
||||
SUB(Lib, Hmd) \
|
||||
SUB(Lib, SigninDialog) \
|
||||
SUB(Lib, Camera) \
|
||||
SUB(Lib, CompanionHttpd) \
|
||||
SUB(Lib, CompanionUtil) \
|
||||
SUB(Lib, Voice) \
|
||||
CLS(Frontend) \
|
||||
CLS(Render) \
|
||||
SUB(Render, Vulkan) \
|
||||
|
@ -98,12 +98,17 @@ enum class Class : u8 {
|
||||
Lib_Fiber, ///< The LibSceFiber implementation.
|
||||
Lib_Vdec2, ///< The LibSceVideodec2 implementation.
|
||||
Lib_Videodec, ///< The LibSceVideodec implementation.
|
||||
Lib_Voice, ///< The LibSceVoice implementation.
|
||||
Lib_RazorCpu, ///< The LibRazorCpu implementation.
|
||||
Lib_Mouse, ///< The LibSceMouse implementation
|
||||
Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation
|
||||
Lib_NpParty, ///< The LibSceNpParty implementation
|
||||
Lib_Zlib, ///< The LibSceZlib implementation.
|
||||
Lib_Hmd, ///< The LibSceHmd implementation.
|
||||
Lib_SigninDialog, ///< The LibSigninDialog implementation.
|
||||
Lib_Camera, ///< The LibCamera implementation.
|
||||
Lib_CompanionHttpd, ///< The LibCompanionHttpd implementation.
|
||||
Lib_CompanionUtil, ///< The LibCompanionUtil implementation.
|
||||
Frontend, ///< Emulator UI
|
||||
Render, ///< Video Core
|
||||
Render_Vulkan, ///< Vulkan backend
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
namespace MemoryPatcher {
|
||||
|
||||
uintptr_t g_eboot_address;
|
||||
EXPORT uintptr_t g_eboot_address;
|
||||
uint64_t g_eboot_image_size;
|
||||
std::string g_game_serial;
|
||||
std::string patchFile;
|
||||
@ -169,7 +169,8 @@ void OnGameLoaded() {
|
||||
if (type == "mask_jump32")
|
||||
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
|
||||
|
||||
if (type == "mask" || type == "mask_jump32" && !maskOffsetStr.empty()) {
|
||||
if ((type == "mask" || type == "mask_jump32") &&
|
||||
!maskOffsetStr.empty()) {
|
||||
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,15 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined(WIN32)
|
||||
#define EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
namespace MemoryPatcher {
|
||||
|
||||
extern uintptr_t g_eboot_address;
|
||||
extern EXPORT uintptr_t g_eboot_address;
|
||||
extern uint64_t g_eboot_image_size;
|
||||
extern std::string g_game_serial;
|
||||
extern std::string patchFile;
|
||||
|
@ -128,7 +128,6 @@ static auto UserPaths = [] {
|
||||
create_path(PathType::LogDir, user_dir / LOG_DIR);
|
||||
create_path(PathType::ScreenshotsDir, user_dir / SCREENSHOTS_DIR);
|
||||
create_path(PathType::ShaderDir, user_dir / SHADER_DIR);
|
||||
create_path(PathType::SaveDataDir, user_dir / SAVEDATA_DIR);
|
||||
create_path(PathType::GameDataDir, user_dir / GAMEDATA_DIR);
|
||||
create_path(PathType::TempDataDir, user_dir / TEMPDATA_DIR);
|
||||
create_path(PathType::SysModuleDir, user_dir / SYSMODULES_DIR);
|
||||
|
@ -18,7 +18,6 @@ enum class PathType {
|
||||
LogDir, // Where log files are stored.
|
||||
ScreenshotsDir, // Where screenshots are stored.
|
||||
ShaderDir, // Where shaders are stored.
|
||||
SaveDataDir, // Where guest save data is stored.
|
||||
TempDataDir, // Where game temp data is stored.
|
||||
GameDataDir, // Where game data is stored.
|
||||
SysModuleDir, // Where system modules are stored.
|
||||
@ -36,7 +35,6 @@ constexpr auto PORTABLE_DIR = "user";
|
||||
constexpr auto LOG_DIR = "log";
|
||||
constexpr auto SCREENSHOTS_DIR = "screenshots";
|
||||
constexpr auto SHADER_DIR = "shader";
|
||||
constexpr auto SAVEDATA_DIR = "savedata";
|
||||
constexpr auto GAMEDATA_DIR = "data";
|
||||
constexpr auto TEMPDATA_DIR = "temp";
|
||||
constexpr auto SYSMODULES_DIR = "sys_modules";
|
||||
|
101
src/common/range_lock.h
Normal file
101
src/common/range_lock.h
Normal file
@ -0,0 +1,101 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
#include <mutex>
|
||||
|
||||
namespace Common {
|
||||
|
||||
// From boost thread locking
|
||||
|
||||
template <typename Iterator>
|
||||
struct RangeLockGuard {
|
||||
Iterator begin;
|
||||
Iterator end;
|
||||
|
||||
RangeLockGuard(Iterator begin_, Iterator end_) : begin(begin_), end(end_) {
|
||||
LockRange(begin, end);
|
||||
}
|
||||
|
||||
void release() {
|
||||
begin = end;
|
||||
}
|
||||
|
||||
~RangeLockGuard() {
|
||||
for (; begin != end; ++begin) {
|
||||
begin->unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
Iterator TryLockRange(Iterator begin, Iterator end) {
|
||||
using LockType = typename std::iterator_traits<Iterator>::value_type;
|
||||
|
||||
if (begin == end) {
|
||||
return end;
|
||||
}
|
||||
|
||||
std::unique_lock<LockType> guard(*begin, std::try_to_lock);
|
||||
if (!guard.owns_lock()) {
|
||||
return begin;
|
||||
}
|
||||
|
||||
Iterator failed = TryLockRange(++begin, end);
|
||||
if (failed == end) {
|
||||
guard.release();
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void LockRange(Iterator begin, Iterator end) {
|
||||
using LockType = typename std::iterator_traits<Iterator>::value_type;
|
||||
|
||||
if (begin == end) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool start_with_begin = true;
|
||||
Iterator second = begin;
|
||||
++second;
|
||||
Iterator next = second;
|
||||
|
||||
while (true) {
|
||||
std::unique_lock<LockType> begin_lock(*begin, std::defer_lock);
|
||||
if (start_with_begin) {
|
||||
begin_lock.lock();
|
||||
|
||||
const Iterator failed_lock = TryLockRange(next, end);
|
||||
if (failed_lock == end) {
|
||||
begin_lock.release();
|
||||
return;
|
||||
}
|
||||
|
||||
start_with_begin = false;
|
||||
next = failed_lock;
|
||||
} else {
|
||||
RangeLockGuard<Iterator> guard(next, end);
|
||||
|
||||
if (begin_lock.try_lock()) {
|
||||
const Iterator failed_lock = TryLockRange(second, next);
|
||||
if (failed_lock == next) {
|
||||
begin_lock.release();
|
||||
guard.release();
|
||||
return;
|
||||
}
|
||||
|
||||
start_with_begin = false;
|
||||
next = failed_lock;
|
||||
} else {
|
||||
start_with_begin = true;
|
||||
next = second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Common
|
37
src/common/recursive_lock.cpp
Normal file
37
src/common/recursive_lock.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <unordered_map>
|
||||
#include "common/assert.h"
|
||||
#include "common/recursive_lock.h"
|
||||
|
||||
namespace Common::Detail {
|
||||
|
||||
struct RecursiveLockState {
|
||||
RecursiveLockType type;
|
||||
int count;
|
||||
};
|
||||
|
||||
thread_local std::unordered_map<void*, RecursiveLockState> g_recursive_locks;
|
||||
|
||||
bool IncrementRecursiveLock(void* mutex, RecursiveLockType type) {
|
||||
auto& state = g_recursive_locks[mutex];
|
||||
if (state.count == 0) {
|
||||
ASSERT(state.type == RecursiveLockType::None);
|
||||
state.type = type;
|
||||
}
|
||||
ASSERT(state.type == type);
|
||||
return state.count++ == 0;
|
||||
}
|
||||
|
||||
bool DecrementRecursiveLock(void* mutex, RecursiveLockType type) {
|
||||
auto& state = g_recursive_locks[mutex];
|
||||
ASSERT(state.type == type && state.count > 0);
|
||||
if (--state.count == 0) {
|
||||
g_recursive_locks.erase(mutex);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Common::Detail
|
67
src/common/recursive_lock.h
Normal file
67
src/common/recursive_lock.h
Normal file
@ -0,0 +1,67 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <shared_mutex>
|
||||
|
||||
namespace Common {
|
||||
|
||||
namespace Detail {
|
||||
|
||||
enum class RecursiveLockType { None, Shared, Exclusive };
|
||||
|
||||
bool IncrementRecursiveLock(void* mutex, RecursiveLockType type);
|
||||
bool DecrementRecursiveLock(void* mutex, RecursiveLockType type);
|
||||
|
||||
} // namespace Detail
|
||||
|
||||
template <typename MutexType>
|
||||
class RecursiveScopedLock {
|
||||
public:
|
||||
explicit RecursiveScopedLock(MutexType& mutex) : m_mutex(mutex), m_locked(false) {
|
||||
if (Detail::IncrementRecursiveLock(&m_mutex, Detail::RecursiveLockType::Exclusive)) {
|
||||
m_locked = true;
|
||||
m_lock.emplace(m_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
~RecursiveScopedLock() {
|
||||
Detail::DecrementRecursiveLock(&m_mutex, Detail::RecursiveLockType::Exclusive);
|
||||
if (m_locked) {
|
||||
m_lock.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MutexType& m_mutex;
|
||||
std::optional<std::unique_lock<MutexType>> m_lock;
|
||||
bool m_locked = false;
|
||||
};
|
||||
|
||||
template <typename MutexType>
|
||||
class RecursiveSharedLock {
|
||||
public:
|
||||
explicit RecursiveSharedLock(MutexType& mutex) : m_mutex(mutex), m_locked(false) {
|
||||
if (Detail::IncrementRecursiveLock(&m_mutex, Detail::RecursiveLockType::Shared)) {
|
||||
m_locked = true;
|
||||
m_lock.emplace(m_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
~RecursiveSharedLock() {
|
||||
Detail::DecrementRecursiveLock(&m_mutex, Detail::RecursiveLockType::Shared);
|
||||
if (m_locked) {
|
||||
m_lock.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MutexType& m_mutex;
|
||||
std::optional<std::shared_lock<MutexType>> m_lock;
|
||||
bool m_locked = false;
|
||||
};
|
||||
|
||||
} // namespace Common
|
@ -1,6 +1,8 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common/scm_rev.h"
|
||||
|
||||
namespace Common {
|
||||
@ -15,5 +17,26 @@ 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@";
|
||||
|
||||
const std::string GetRemoteNameFromLink() {
|
||||
std::string remote_url(Common::g_scm_remote_url);
|
||||
std::string remote_host;
|
||||
try {
|
||||
if (remote_url.starts_with("http")) {
|
||||
if (*remote_url.rbegin() == '/') {
|
||||
remote_url.pop_back();
|
||||
}
|
||||
remote_host = remote_url.substr(19, remote_url.rfind('/') - 19);
|
||||
} else if (remote_url.starts_with("git@")) {
|
||||
auto after_comma_pos = remote_url.find(':') + 1, slash_pos = remote_url.find('/');
|
||||
remote_host = remote_url.substr(after_comma_pos, slash_pos - after_comma_pos);
|
||||
} else {
|
||||
remote_host = "unknown";
|
||||
}
|
||||
} catch (...) {
|
||||
remote_host = "unknown";
|
||||
}
|
||||
return remote_host;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Common {
|
||||
|
||||
extern const char g_version[];
|
||||
@ -15,4 +17,6 @@ extern const char g_scm_remote_name[];
|
||||
extern const char g_scm_remote_url[];
|
||||
extern const char g_scm_date[];
|
||||
|
||||
const std::string GetRemoteNameFromLink();
|
||||
|
||||
} // namespace Common
|
||||
|
46
src/common/shared_first_mutex.h
Normal file
46
src/common/shared_first_mutex.h
Normal file
@ -0,0 +1,46 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
namespace Common {
|
||||
|
||||
// Like std::shared_mutex, but reader has priority over writer.
|
||||
class SharedFirstMutex {
|
||||
public:
|
||||
void lock() {
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
cv.wait(lock, [this]() { return !writer_active && readers == 0; });
|
||||
writer_active = true;
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
writer_active = false;
|
||||
cv.notify_all();
|
||||
}
|
||||
|
||||
void lock_shared() {
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
cv.wait(lock, [this]() { return !writer_active; });
|
||||
++readers;
|
||||
}
|
||||
|
||||
void unlock_shared() {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
if (--readers == 0) {
|
||||
cv.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mtx;
|
||||
std::condition_variable cv;
|
||||
int readers = 0;
|
||||
bool writer_active = false;
|
||||
};
|
||||
|
||||
} // namespace Common
|
@ -14,6 +14,9 @@ namespace Common {
|
||||
struct SlotId {
|
||||
static constexpr u32 INVALID_INDEX = std::numeric_limits<u32>::max();
|
||||
|
||||
SlotId() noexcept = default;
|
||||
constexpr SlotId(u32 index) noexcept : index(index) {}
|
||||
|
||||
constexpr auto operator<=>(const SlotId&) const noexcept = default;
|
||||
|
||||
constexpr explicit operator bool() const noexcept {
|
||||
@ -28,6 +31,63 @@ class SlotVector {
|
||||
constexpr static std::size_t InitialCapacity = 2048;
|
||||
|
||||
public:
|
||||
template <typename ValueType, typename Pointer, typename Reference>
|
||||
class Iterator {
|
||||
public:
|
||||
using iterator_category = std::forward_iterator_tag;
|
||||
using value_type = ValueType;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = Pointer;
|
||||
using reference = Reference;
|
||||
|
||||
Iterator(SlotVector& vector_, SlotId index_) : vector(vector_), slot(index_) {
|
||||
AdvanceToValid();
|
||||
}
|
||||
|
||||
reference operator*() const {
|
||||
return vector[slot];
|
||||
}
|
||||
|
||||
pointer operator->() const {
|
||||
return &vector[slot];
|
||||
}
|
||||
|
||||
Iterator& operator++() {
|
||||
++slot.index;
|
||||
AdvanceToValid();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator++(int) {
|
||||
Iterator temp = *this;
|
||||
++(*this);
|
||||
return temp;
|
||||
}
|
||||
|
||||
bool operator==(const Iterator& other) const {
|
||||
return slot == other.slot;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
private:
|
||||
void AdvanceToValid() {
|
||||
while (slot < vector.values_capacity && !vector.ReadStorageBit(slot.index)) {
|
||||
++slot.index;
|
||||
}
|
||||
}
|
||||
|
||||
SlotVector& vector;
|
||||
SlotId slot;
|
||||
};
|
||||
|
||||
using iterator = Iterator<T, T*, T&>;
|
||||
using const_iterator = Iterator<const T, const T*, const T&>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
|
||||
SlotVector() {
|
||||
Reserve(InitialCapacity);
|
||||
}
|
||||
@ -60,7 +120,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
[[nodiscard]] SlotId insert(Args&&... args) noexcept {
|
||||
SlotId insert(Args&&... args) noexcept {
|
||||
const u32 index = FreeValueIndex();
|
||||
new (&values[index].object) T(std::forward<Args>(args)...);
|
||||
SetStorageBit(index);
|
||||
@ -78,6 +138,54 @@ public:
|
||||
return values_capacity - free_list.size();
|
||||
}
|
||||
|
||||
iterator begin() noexcept {
|
||||
return iterator(*this, 0);
|
||||
}
|
||||
|
||||
const_iterator begin() const noexcept {
|
||||
return const_iterator(*this, 0);
|
||||
}
|
||||
|
||||
const_iterator cbegin() const noexcept {
|
||||
return begin();
|
||||
}
|
||||
|
||||
iterator end() noexcept {
|
||||
return iterator(*this, values_capacity);
|
||||
}
|
||||
|
||||
const_iterator end() const noexcept {
|
||||
return const_iterator(*this, values_capacity);
|
||||
}
|
||||
|
||||
const_iterator cend() const noexcept {
|
||||
return end();
|
||||
}
|
||||
|
||||
reverse_iterator rbegin() noexcept {
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
const_reverse_iterator rbegin() const noexcept {
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
const_reverse_iterator crbegin() const noexcept {
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
reverse_iterator rend() noexcept {
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
const_reverse_iterator rend() const noexcept {
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
const_reverse_iterator crend() const noexcept {
|
||||
return rend();
|
||||
}
|
||||
|
||||
private:
|
||||
struct NonTrivialDummy {
|
||||
NonTrivialDummy() noexcept {}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
@ -104,14 +105,24 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
|
||||
SetThreadPriority(handle, windows_priority);
|
||||
}
|
||||
|
||||
static void AccurateSleep(std::chrono::nanoseconds duration) {
|
||||
bool AccurateSleep(const std::chrono::nanoseconds duration, std::chrono::nanoseconds* remaining,
|
||||
const bool interruptible) {
|
||||
const auto begin_sleep = std::chrono::high_resolution_clock::now();
|
||||
|
||||
LARGE_INTEGER interval{
|
||||
.QuadPart = -1 * (duration.count() / 100u),
|
||||
};
|
||||
HANDLE timer = ::CreateWaitableTimer(NULL, TRUE, NULL);
|
||||
SetWaitableTimer(timer, &interval, 0, NULL, NULL, 0);
|
||||
WaitForSingleObject(timer, INFINITE);
|
||||
const auto ret = WaitForSingleObjectEx(timer, INFINITE, interruptible);
|
||||
::CloseHandle(timer);
|
||||
|
||||
if (remaining) {
|
||||
const auto end_sleep = std::chrono::high_resolution_clock::now();
|
||||
const auto sleep_time = end_sleep - begin_sleep;
|
||||
*remaining = duration > sleep_time ? duration - sleep_time : std::chrono::nanoseconds(0);
|
||||
}
|
||||
return ret == WAIT_OBJECT_0;
|
||||
}
|
||||
|
||||
#else
|
||||
@ -134,8 +145,24 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
|
||||
pthread_setschedparam(this_thread, scheduling_type, ¶ms);
|
||||
}
|
||||
|
||||
static void AccurateSleep(std::chrono::nanoseconds duration) {
|
||||
std::this_thread::sleep_for(duration);
|
||||
bool AccurateSleep(const std::chrono::nanoseconds duration, std::chrono::nanoseconds* remaining,
|
||||
const bool interruptible) {
|
||||
timespec request = {
|
||||
.tv_sec = duration.count() / 1'000'000'000,
|
||||
.tv_nsec = duration.count() % 1'000'000'000,
|
||||
};
|
||||
timespec remain;
|
||||
int ret;
|
||||
while ((ret = nanosleep(&request, &remain)) < 0 && errno == EINTR) {
|
||||
if (interruptible) {
|
||||
break;
|
||||
}
|
||||
request = remain;
|
||||
}
|
||||
if (remaining) {
|
||||
*remaining = std::chrono::nanoseconds(remain.tv_sec * 1'000'000'000 + remain.tv_nsec);
|
||||
}
|
||||
return ret == 0 || errno != EINTR;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -196,9 +223,9 @@ AccurateTimer::AccurateTimer(std::chrono::nanoseconds target_interval)
|
||||
: target_interval(target_interval) {}
|
||||
|
||||
void AccurateTimer::Start() {
|
||||
auto begin_sleep = std::chrono::high_resolution_clock::now();
|
||||
const auto begin_sleep = std::chrono::high_resolution_clock::now();
|
||||
if (total_wait.count() > 0) {
|
||||
AccurateSleep(total_wait);
|
||||
AccurateSleep(total_wait, nullptr, false);
|
||||
}
|
||||
start_time = std::chrono::high_resolution_clock::now();
|
||||
total_wait -= std::chrono::duration_cast<std::chrono::nanoseconds>(start_time - begin_sleep);
|
||||
|
@ -25,6 +25,9 @@ void SetCurrentThreadName(const char* name);
|
||||
|
||||
void SetThreadName(void* thread, const char* name);
|
||||
|
||||
bool AccurateSleep(std::chrono::nanoseconds duration, std::chrono::nanoseconds* remaining,
|
||||
bool interruptible);
|
||||
|
||||
class AccurateTimer {
|
||||
std::chrono::nanoseconds target_interval{};
|
||||
std::chrono::nanoseconds total_wait{};
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define VA_ARGS \
|
||||
uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, \
|
||||
uint64_t overflow_arg_area, __m128 xmm0, __m128 xmm1, __m128 xmm2, __m128 xmm3, \
|
||||
__m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ...
|
||||
__m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7
|
||||
|
||||
#define VA_CTX(ctx) \
|
||||
alignas(16)::Common::VaCtx ctx{}; \
|
||||
|
@ -302,14 +302,15 @@ struct AddressSpace::Impl {
|
||||
new_flags = PAGE_READWRITE;
|
||||
} else if (read && !write) {
|
||||
new_flags = PAGE_READONLY;
|
||||
} else if (execute && !read && not write) {
|
||||
} else if (execute && !read && !write) {
|
||||
new_flags = PAGE_EXECUTE;
|
||||
} else if (!read && !write && !execute) {
|
||||
new_flags = PAGE_NOACCESS;
|
||||
} else {
|
||||
LOG_CRITICAL(Common_Memory,
|
||||
"Unsupported protection flag combination for address {:#x}, size {}",
|
||||
virtual_addr, size);
|
||||
"Unsupported protection flag combination for address {:#x}, size {}, "
|
||||
"read={}, write={}, execute={}",
|
||||
virtual_addr, size, read, write, execute);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -357,9 +358,17 @@ enum PosixPageProtection {
|
||||
[[nodiscard]] constexpr PosixPageProtection ToPosixProt(Core::MemoryProt prot) {
|
||||
if (True(prot & Core::MemoryProt::CpuReadWrite) ||
|
||||
True(prot & Core::MemoryProt::GpuReadWrite)) {
|
||||
return PAGE_READWRITE;
|
||||
if (True(prot & Core::MemoryProt::CpuExec)) {
|
||||
return PAGE_EXECUTE_READWRITE;
|
||||
} else {
|
||||
return PAGE_READWRITE;
|
||||
}
|
||||
} else if (True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead)) {
|
||||
return PAGE_READONLY;
|
||||
if (True(prot & Core::MemoryProt::CpuExec)) {
|
||||
return PAGE_EXECUTE_READ;
|
||||
} else {
|
||||
return PAGE_READONLY;
|
||||
}
|
||||
} else {
|
||||
return PAGE_NOACCESS;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
namespace Core {
|
||||
|
||||
enum class MemoryPermission : u32 {
|
||||
None = 0,
|
||||
Read = 1 << 0,
|
||||
Write = 1 << 1,
|
||||
ReadWrite = Read | Write,
|
||||
@ -19,8 +20,6 @@ enum class MemoryPermission : u32 {
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission)
|
||||
|
||||
constexpr VAddr CODE_BASE_OFFSET = 0x100000000ULL;
|
||||
|
||||
constexpr VAddr SYSTEM_MANAGED_MIN = 0x00000400000ULL;
|
||||
constexpr VAddr SYSTEM_MANAGED_MAX = 0x07FFFFBFFFULL;
|
||||
constexpr VAddr SYSTEM_RESERVED_MIN = 0x07FFFFC000ULL;
|
||||
|
@ -88,7 +88,8 @@ static bool FilterTcbAccess(const ZydisDecodedOperand* operands) {
|
||||
dst_op.reg.value <= ZYDIS_REGISTER_R15;
|
||||
}
|
||||
|
||||
static void GenerateTcbAccess(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
static void GenerateTcbAccess(void* /* address */, const ZydisDecodedOperand* operands,
|
||||
Xbyak::CodeGenerator& c) {
|
||||
const auto dst = ZydisToXbyakRegisterOperand(operands[0]);
|
||||
|
||||
#if defined(_WIN32)
|
||||
@ -126,7 +127,8 @@ static bool FilterNoSSE4a(const ZydisDecodedOperand*) {
|
||||
return !cpu.has(Cpu::tSSE4a);
|
||||
}
|
||||
|
||||
static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
static void GenerateEXTRQ(void* /* address */, const ZydisDecodedOperand* operands,
|
||||
Xbyak::CodeGenerator& c) {
|
||||
bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||
operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
||||
|
||||
@ -161,7 +163,9 @@ static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
||||
mask = (1ULL << length) - 1;
|
||||
}
|
||||
|
||||
ASSERT_MSG(length + index <= 64, "length + index must be less than or equal to 64.");
|
||||
if (length + index > 64) {
|
||||
mask = 0xFFFF'FFFF'FFFF'FFFF;
|
||||
}
|
||||
|
||||
// Get lower qword from xmm register
|
||||
c.vmovq(scratch1, xmm_dst);
|
||||
@ -175,8 +179,8 @@ static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
||||
c.mov(scratch2, mask);
|
||||
c.and_(scratch1, scratch2);
|
||||
|
||||
// Writeback to xmm register, extrq instruction says top 64-bits are undefined so we don't
|
||||
// care to preserve them
|
||||
// Writeback to xmm register, extrq instruction says top 64-bits are undefined but zeroed on
|
||||
// AMD CPUs
|
||||
c.vmovq(xmm_dst, scratch1);
|
||||
|
||||
c.pop(scratch2);
|
||||
@ -245,7 +249,8 @@ static void GenerateEXTRQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenera
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGenerator& c) {
|
||||
static void GenerateINSERTQ(void* /* address */, const ZydisDecodedOperand* operands,
|
||||
Xbyak::CodeGenerator& c) {
|
||||
bool immediateForm = operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||
operands[3].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
||||
|
||||
@ -284,7 +289,9 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
||||
mask_value = (1ULL << length) - 1;
|
||||
}
|
||||
|
||||
ASSERT_MSG(length + index <= 64, "length + index must be less than or equal to 64.");
|
||||
if (length + index > 64) {
|
||||
mask_value = 0xFFFF'FFFF'FFFF'FFFF;
|
||||
}
|
||||
|
||||
c.vmovq(scratch1, xmm_src);
|
||||
c.vmovq(scratch2, xmm_dst);
|
||||
@ -304,8 +311,9 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
||||
// dst |= src
|
||||
c.or_(scratch2, scratch1);
|
||||
|
||||
// Insert scratch2 into low 64 bits of dst, upper 64 bits are unaffected
|
||||
c.vpinsrq(xmm_dst, xmm_dst, scratch2, 0);
|
||||
// Insert scratch2 into low 64 bits of dst, upper 64 bits are undefined but zeroed on AMD
|
||||
// CPUs
|
||||
c.vmovq(xmm_dst, scratch2);
|
||||
|
||||
c.pop(mask);
|
||||
c.pop(scratch2);
|
||||
@ -371,7 +379,7 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
||||
c.and_(scratch2, mask);
|
||||
c.or_(scratch2, scratch1);
|
||||
|
||||
// Upper 64 bits are undefined in insertq
|
||||
// Upper 64 bits are undefined in insertq but AMD CPUs zero them
|
||||
c.vmovq(xmm_dst, scratch2);
|
||||
|
||||
c.pop(mask);
|
||||
@ -383,8 +391,44 @@ static void GenerateINSERTQ(const ZydisDecodedOperand* operands, Xbyak::CodeGene
|
||||
}
|
||||
}
|
||||
|
||||
static void ReplaceMOVNT(void* address, u8 rep_prefix) {
|
||||
// Find the opcode byte
|
||||
// There can be any amount of prefixes but the instruction can't be more than 15 bytes
|
||||
// And we know for sure this is a MOVNTSS/MOVNTSD
|
||||
bool found = false;
|
||||
bool rep_prefix_found = false;
|
||||
int index = 0;
|
||||
u8* ptr = reinterpret_cast<u8*>(address);
|
||||
for (int i = 0; i < 15; i++) {
|
||||
if (ptr[i] == rep_prefix) {
|
||||
rep_prefix_found = true;
|
||||
} else if (ptr[i] == 0x2B) {
|
||||
index = i;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Some sanity checks
|
||||
ASSERT(found);
|
||||
ASSERT(index >= 2);
|
||||
ASSERT(ptr[index - 1] == 0x0F);
|
||||
ASSERT(rep_prefix_found);
|
||||
|
||||
// This turns the MOVNTSS/MOVNTSD to a MOVSS/MOVSD m, xmm
|
||||
ptr[index] = 0x11;
|
||||
}
|
||||
|
||||
static void ReplaceMOVNTSS(void* address, const ZydisDecodedOperand*, Xbyak::CodeGenerator&) {
|
||||
ReplaceMOVNT(address, 0xF3);
|
||||
}
|
||||
|
||||
static void ReplaceMOVNTSD(void* address, const ZydisDecodedOperand*, Xbyak::CodeGenerator&) {
|
||||
ReplaceMOVNT(address, 0xF2);
|
||||
}
|
||||
|
||||
using PatchFilter = bool (*)(const ZydisDecodedOperand*);
|
||||
using InstructionGenerator = void (*)(const ZydisDecodedOperand*, Xbyak::CodeGenerator&);
|
||||
using InstructionGenerator = void (*)(void*, const ZydisDecodedOperand*, Xbyak::CodeGenerator&);
|
||||
struct PatchInfo {
|
||||
/// Filter for more granular patch conditions past just the instruction mnemonic.
|
||||
PatchFilter filter;
|
||||
@ -400,6 +444,8 @@ static const std::unordered_map<ZydisMnemonic, PatchInfo> Patches = {
|
||||
// SSE4a
|
||||
{ZYDIS_MNEMONIC_EXTRQ, {FilterNoSSE4a, GenerateEXTRQ, true}},
|
||||
{ZYDIS_MNEMONIC_INSERTQ, {FilterNoSSE4a, GenerateINSERTQ, true}},
|
||||
{ZYDIS_MNEMONIC_MOVNTSS, {FilterNoSSE4a, ReplaceMOVNTSS, false}},
|
||||
{ZYDIS_MNEMONIC_MOVNTSD, {FilterNoSSE4a, ReplaceMOVNTSD, false}},
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows needs a trampoline.
|
||||
@ -464,9 +510,8 @@ static std::pair<bool, u64> TryPatch(u8* code, PatchModule* module) {
|
||||
|
||||
if (needs_trampoline && instruction.length < 5) {
|
||||
// Trampoline is needed but instruction is too short to patch.
|
||||
// Return false and length to fall back to the illegal instruction handler,
|
||||
// or to signal to AOT compilation that this instruction should be skipped and
|
||||
// handled at runtime.
|
||||
// Return false and length to signal to AOT compilation that this instruction
|
||||
// should be skipped and handled at runtime.
|
||||
return std::make_pair(false, instruction.length);
|
||||
}
|
||||
|
||||
@ -478,7 +523,7 @@ static std::pair<bool, u64> TryPatch(u8* code, PatchModule* module) {
|
||||
auto& trampoline_gen = module->trampoline_gen;
|
||||
const auto trampoline_ptr = trampoline_gen.getCurr();
|
||||
|
||||
patch_info.generator(operands, trampoline_gen);
|
||||
patch_info.generator(code, operands, trampoline_gen);
|
||||
|
||||
// Return to the following instruction at the end of the trampoline.
|
||||
trampoline_gen.jmp(code + instruction.length);
|
||||
@ -486,7 +531,7 @@ static std::pair<bool, u64> TryPatch(u8* code, PatchModule* module) {
|
||||
// Replace instruction with near jump to the trampoline.
|
||||
patch_gen.jmp(trampoline_ptr, Xbyak::CodeGenerator::LabelType::T_NEAR);
|
||||
} else {
|
||||
patch_info.generator(operands, patch_gen);
|
||||
patch_info.generator(code, operands, patch_gen);
|
||||
}
|
||||
|
||||
const auto patch_size = patch_gen.getCurr() - code;
|
||||
@ -512,136 +557,139 @@ static std::pair<bool, u64> TryPatch(u8* code, PatchModule* module) {
|
||||
|
||||
#if defined(ARCH_X86_64)
|
||||
|
||||
static bool Is4ByteExtrqOrInsertq(void* code_address) {
|
||||
u8* bytes = (u8*)code_address;
|
||||
if (bytes[0] == 0x66 && bytes[1] == 0x0F && bytes[2] == 0x79) {
|
||||
return true; // extrq
|
||||
} else if (bytes[0] == 0xF2 && bytes[1] == 0x0F && bytes[2] == 0x79) {
|
||||
return true; // insertq
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
|
||||
ZydisDecodedInstruction instruction;
|
||||
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
||||
const auto status =
|
||||
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
||||
// We need to decode the instruction to find out what it is. Normally we'd use a fully fleshed
|
||||
// out decoder like Zydis, however Zydis does a bunch of stuff that impact performance that we
|
||||
// don't care about. We can get information about the instruction a lot faster by writing a mini
|
||||
// decoder here, since we know it is definitely an extrq or an insertq. If for some reason we
|
||||
// need to interpret more instructions in the future (I don't see why we would), we can revert
|
||||
// to using Zydis.
|
||||
ZydisMnemonic mnemonic;
|
||||
u8* bytes = (u8*)code_address;
|
||||
if (bytes[0] == 0x66) {
|
||||
mnemonic = ZYDIS_MNEMONIC_EXTRQ;
|
||||
} else if (bytes[0] == 0xF2) {
|
||||
mnemonic = ZYDIS_MNEMONIC_INSERTQ;
|
||||
} else {
|
||||
ZydisDecodedInstruction instruction;
|
||||
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
||||
const auto status =
|
||||
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
||||
LOG_ERROR(Core, "Unhandled illegal instruction at code address {}: {}",
|
||||
fmt::ptr(code_address),
|
||||
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
|
||||
: "Failed to decode");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (instruction.mnemonic) {
|
||||
ASSERT(bytes[1] == 0x0F && bytes[2] == 0x79);
|
||||
|
||||
// Note: It's guaranteed that there's no REX prefix in these instructions checked by
|
||||
// Is4ByteExtrqOrInsertq
|
||||
u8 modrm = bytes[3];
|
||||
u8 rm = modrm & 0b111;
|
||||
u8 reg = (modrm >> 3) & 0b111;
|
||||
u8 mod = (modrm >> 6) & 0b11;
|
||||
|
||||
ASSERT(mod == 0b11); // Any instruction we interpret here uses reg/reg addressing only
|
||||
|
||||
int dstIndex = reg;
|
||||
int srcIndex = rm;
|
||||
|
||||
switch (mnemonic) {
|
||||
case ZYDIS_MNEMONIC_EXTRQ: {
|
||||
bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||
operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
||||
if (immediateForm) {
|
||||
LOG_CRITICAL(Core, "EXTRQ immediate form should have been patched at code address: {}",
|
||||
fmt::ptr(code_address));
|
||||
return false;
|
||||
const auto dst = Common::GetXmmPointer(ctx, dstIndex);
|
||||
const auto src = Common::GetXmmPointer(ctx, srcIndex);
|
||||
|
||||
u64 lowQWordSrc;
|
||||
memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc));
|
||||
|
||||
u64 lowQWordDst;
|
||||
memcpy(&lowQWordDst, dst, sizeof(lowQWordDst));
|
||||
|
||||
u64 length = lowQWordSrc & 0x3F;
|
||||
u64 mask;
|
||||
if (length == 0) {
|
||||
length = 64; // for the check below
|
||||
mask = 0xFFFF'FFFF'FFFF'FFFF;
|
||||
} else {
|
||||
ASSERT_MSG(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
||||
operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
||||
operands[0].reg.value >= ZYDIS_REGISTER_XMM0 &&
|
||||
operands[0].reg.value <= ZYDIS_REGISTER_XMM15 &&
|
||||
operands[1].reg.value >= ZYDIS_REGISTER_XMM0 &&
|
||||
operands[1].reg.value <= ZYDIS_REGISTER_XMM15,
|
||||
"Unexpected operand types for EXTRQ instruction");
|
||||
|
||||
const auto dstIndex = operands[0].reg.value - ZYDIS_REGISTER_XMM0;
|
||||
const auto srcIndex = operands[1].reg.value - ZYDIS_REGISTER_XMM0;
|
||||
|
||||
const auto dst = Common::GetXmmPointer(ctx, dstIndex);
|
||||
const auto src = Common::GetXmmPointer(ctx, srcIndex);
|
||||
|
||||
u64 lowQWordSrc;
|
||||
memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc));
|
||||
|
||||
u64 lowQWordDst;
|
||||
memcpy(&lowQWordDst, dst, sizeof(lowQWordDst));
|
||||
|
||||
u64 length = lowQWordSrc & 0x3F;
|
||||
u64 mask;
|
||||
if (length == 0) {
|
||||
length = 64; // for the check below
|
||||
mask = 0xFFFF'FFFF'FFFF'FFFF;
|
||||
} else {
|
||||
mask = (1ULL << length) - 1;
|
||||
}
|
||||
|
||||
u64 index = (lowQWordSrc >> 8) & 0x3F;
|
||||
if (length + index > 64) {
|
||||
// Undefined behavior if length + index is bigger than 64 according to the spec,
|
||||
// we'll warn and continue execution.
|
||||
LOG_TRACE(Core,
|
||||
"extrq at {} with length {} and index {} is bigger than 64, "
|
||||
"undefined behavior",
|
||||
fmt::ptr(code_address), length, index);
|
||||
}
|
||||
|
||||
lowQWordDst >>= index;
|
||||
lowQWordDst &= mask;
|
||||
|
||||
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
||||
|
||||
Common::IncrementRip(ctx, instruction.length);
|
||||
|
||||
return true;
|
||||
mask = (1ULL << length) - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
u64 index = (lowQWordSrc >> 8) & 0x3F;
|
||||
if (length + index > 64) {
|
||||
// Undefined behavior if length + index is bigger than 64 according to the spec,
|
||||
// we'll warn and continue execution.
|
||||
LOG_TRACE(Core,
|
||||
"extrq at {} with length {} and index {} is bigger than 64, "
|
||||
"undefined behavior",
|
||||
fmt::ptr(code_address), length, index);
|
||||
}
|
||||
|
||||
lowQWordDst >>= index;
|
||||
lowQWordDst &= mask;
|
||||
|
||||
memset((u8*)dst + sizeof(u64), 0, sizeof(u64));
|
||||
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
||||
|
||||
Common::IncrementRip(ctx, 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
case ZYDIS_MNEMONIC_INSERTQ: {
|
||||
bool immediateForm = operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
||||
operands[3].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
||||
if (immediateForm) {
|
||||
LOG_CRITICAL(Core,
|
||||
"INSERTQ immediate form should have been patched at code address: {}",
|
||||
fmt::ptr(code_address));
|
||||
return false;
|
||||
const auto dst = Common::GetXmmPointer(ctx, dstIndex);
|
||||
const auto src = Common::GetXmmPointer(ctx, srcIndex);
|
||||
|
||||
u64 lowQWordSrc, highQWordSrc;
|
||||
memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc));
|
||||
memcpy(&highQWordSrc, (u8*)src + 8, sizeof(highQWordSrc));
|
||||
|
||||
u64 lowQWordDst;
|
||||
memcpy(&lowQWordDst, dst, sizeof(lowQWordDst));
|
||||
|
||||
u64 length = highQWordSrc & 0x3F;
|
||||
u64 mask;
|
||||
if (length == 0) {
|
||||
length = 64; // for the check below
|
||||
mask = 0xFFFF'FFFF'FFFF'FFFF;
|
||||
} else {
|
||||
ASSERT_MSG(operands[2].type == ZYDIS_OPERAND_TYPE_UNUSED &&
|
||||
operands[3].type == ZYDIS_OPERAND_TYPE_UNUSED,
|
||||
"operands 2 and 3 must be unused for register form.");
|
||||
|
||||
ASSERT_MSG(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
||||
operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER,
|
||||
"operands 0 and 1 must be registers.");
|
||||
|
||||
const auto dstIndex = operands[0].reg.value - ZYDIS_REGISTER_XMM0;
|
||||
const auto srcIndex = operands[1].reg.value - ZYDIS_REGISTER_XMM0;
|
||||
|
||||
const auto dst = Common::GetXmmPointer(ctx, dstIndex);
|
||||
const auto src = Common::GetXmmPointer(ctx, srcIndex);
|
||||
|
||||
u64 lowQWordSrc, highQWordSrc;
|
||||
memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc));
|
||||
memcpy(&highQWordSrc, (u8*)src + 8, sizeof(highQWordSrc));
|
||||
|
||||
u64 lowQWordDst;
|
||||
memcpy(&lowQWordDst, dst, sizeof(lowQWordDst));
|
||||
|
||||
u64 length = highQWordSrc & 0x3F;
|
||||
u64 mask;
|
||||
if (length == 0) {
|
||||
length = 64; // for the check below
|
||||
mask = 0xFFFF'FFFF'FFFF'FFFF;
|
||||
} else {
|
||||
mask = (1ULL << length) - 1;
|
||||
}
|
||||
|
||||
u64 index = (highQWordSrc >> 8) & 0x3F;
|
||||
if (length + index > 64) {
|
||||
// Undefined behavior if length + index is bigger than 64 according to the spec,
|
||||
// we'll warn and continue execution.
|
||||
LOG_TRACE(Core,
|
||||
"insertq at {} with length {} and index {} is bigger than 64, "
|
||||
"undefined behavior",
|
||||
fmt::ptr(code_address), length, index);
|
||||
}
|
||||
|
||||
lowQWordSrc &= mask;
|
||||
lowQWordDst &= ~(mask << index);
|
||||
lowQWordDst |= lowQWordSrc << index;
|
||||
|
||||
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
||||
|
||||
Common::IncrementRip(ctx, instruction.length);
|
||||
|
||||
return true;
|
||||
mask = (1ULL << length) - 1;
|
||||
}
|
||||
break;
|
||||
|
||||
u64 index = (highQWordSrc >> 8) & 0x3F;
|
||||
if (length + index > 64) {
|
||||
// Undefined behavior if length + index is bigger than 64 according to the spec,
|
||||
// we'll warn and continue execution.
|
||||
LOG_TRACE(Core,
|
||||
"insertq at {} with length {} and index {} is bigger than 64, "
|
||||
"undefined behavior",
|
||||
fmt::ptr(code_address), length, index);
|
||||
}
|
||||
|
||||
lowQWordSrc &= mask;
|
||||
lowQWordDst &= ~(mask << index);
|
||||
lowQWordDst |= lowQWordSrc << index;
|
||||
|
||||
memset((u8*)dst + sizeof(u64), 0, sizeof(u64));
|
||||
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
||||
|
||||
Common::IncrementRip(ctx, 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
default: {
|
||||
LOG_ERROR(Core, "Unhandled illegal instruction at code address {}: {}",
|
||||
fmt::ptr(code_address), ZydisMnemonicGetString(instruction.mnemonic));
|
||||
return false;
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@ -695,9 +743,26 @@ static bool PatchesAccessViolationHandler(void* context, void* /* fault_address
|
||||
|
||||
static bool PatchesIllegalInstructionHandler(void* context) {
|
||||
void* code_address = Common::GetRip(context);
|
||||
if (!TryPatchJit(code_address)) {
|
||||
if (Is4ByteExtrqOrInsertq(code_address)) {
|
||||
// The instruction is not big enough for a relative jump, don't try to patch it and pass it
|
||||
// to our illegal instruction interpreter directly
|
||||
return TryExecuteIllegalInstruction(context, code_address);
|
||||
} else {
|
||||
if (!TryPatchJit(code_address)) {
|
||||
ZydisDecodedInstruction instruction;
|
||||
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
||||
const auto status =
|
||||
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
||||
if (ZYAN_SUCCESS(status) && instruction.mnemonic == ZydisMnemonic::ZYDIS_MNEMONIC_UD2)
|
||||
[[unlikely]] {
|
||||
UNREACHABLE_MSG("ud2 at code address {:#x}", (u64)code_address);
|
||||
}
|
||||
LOG_ERROR(Core, "Failed to patch address {:x} -- mnemonic: {}", (u64)code_address,
|
||||
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
|
||||
: "Failed to decode");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,10 @@ public:
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual size_t pwritev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
||||
virtual s64 lseek(s64 offset, int whence) {
|
||||
return ORBIS_KERNEL_ERROR_EBADF;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "random_device.h"
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "srandom_device.h"
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include "common/logging/log.h"
|
||||
#include "urandom_device.h"
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "SDL3/SDL_log.h"
|
||||
#include "layer.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include "SDL3/SDL_log.h"
|
||||
#include "common/config.h"
|
||||
#include "common/singleton.h"
|
||||
#include "common/types.h"
|
||||
@ -17,6 +17,7 @@
|
||||
#include "widget/frame_dump.h"
|
||||
#include "widget/frame_graph.h"
|
||||
#include "widget/memory_map.h"
|
||||
#include "widget/module_list.h"
|
||||
#include "widget/shader_list.h"
|
||||
|
||||
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
||||
@ -40,6 +41,7 @@ static bool just_opened_options = false;
|
||||
|
||||
static Widget::MemoryMapViewer memory_map;
|
||||
static Widget::ShaderList shader_list;
|
||||
static Widget::ModuleList module_list;
|
||||
|
||||
// clang-format off
|
||||
static std::string help_text =
|
||||
@ -108,6 +110,9 @@ void L::DrawMenuBar() {
|
||||
if (MenuItem("Memory map")) {
|
||||
memory_map.open = true;
|
||||
}
|
||||
if (MenuItem("Module list")) {
|
||||
module_list.open = true;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@ -256,6 +261,9 @@ void L::DrawAdvanced() {
|
||||
if (shader_list.open) {
|
||||
shader_list.Draw();
|
||||
}
|
||||
if (module_list.open) {
|
||||
module_list.Draw();
|
||||
}
|
||||
}
|
||||
|
||||
void L::DrawSimple() {
|
||||
|
@ -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
|
||||
|
@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <fmt/chrono.h>
|
||||
#include <imgui.h>
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
|
55
src/core/devtools/widget/module_list.cpp
Normal file
55
src/core/devtools/widget/module_list.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "module_list.h"
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "core/debug_state.h"
|
||||
#include "imgui/imgui_std.h"
|
||||
|
||||
using namespace ImGui;
|
||||
|
||||
namespace Core::Devtools::Widget {
|
||||
void ModuleList::Draw() {
|
||||
SetNextWindowSize({550.0f, 600.0f}, ImGuiCond_FirstUseEver);
|
||||
if (!Begin("Module List", &open)) {
|
||||
End();
|
||||
return;
|
||||
}
|
||||
|
||||
if (BeginTable("ModuleTable", 3,
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Sortable |
|
||||
ImGuiTableFlags_RowBg)) {
|
||||
TableSetupColumn("Modulname", ImGuiTableColumnFlags_WidthStretch);
|
||||
TableHeadersRow();
|
||||
|
||||
std::scoped_lock lock(modules_mutex);
|
||||
for (const auto& module : modules) {
|
||||
TableNextRow();
|
||||
|
||||
TableSetColumnIndex(0);
|
||||
TextUnformatted(module.name.c_str());
|
||||
|
||||
TableSetColumnIndex(1);
|
||||
if (module.is_sys_module) {
|
||||
TextColored({0.2f, 0.6f, 0.8f, 1.0f}, "System Module");
|
||||
} else {
|
||||
TextColored({0.8f, 0.4f, 0.2f, 1.0f}, "Game Module");
|
||||
}
|
||||
|
||||
TableSetColumnIndex(2);
|
||||
if (module.is_lle) {
|
||||
TextColored({0.4f, 0.7f, 0.4f, 1.0f}, "LLE");
|
||||
} else {
|
||||
TextColored({0.7f, 0.4f, 0.5f, 1.0f}, "HLE");
|
||||
}
|
||||
}
|
||||
EndTable();
|
||||
}
|
||||
|
||||
End();
|
||||
}
|
||||
|
||||
} // namespace Core::Devtools::Widget
|
82
src/core/devtools/widget/module_list.h
Normal file
82
src/core/devtools/widget/module_list.h
Normal file
@ -0,0 +1,82 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "common/elf_info.h"
|
||||
#include "common/path_util.h"
|
||||
|
||||
namespace Core::Devtools::Widget {
|
||||
|
||||
class ModuleList {
|
||||
public:
|
||||
ModuleList() = default;
|
||||
~ModuleList() = default;
|
||||
|
||||
void Draw();
|
||||
bool open = false;
|
||||
|
||||
static bool IsSystemModule(const std::filesystem::path& path) {
|
||||
const auto sys_modules_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
||||
|
||||
const auto abs_path = std::filesystem::absolute(path).lexically_normal();
|
||||
const auto abs_sys_path = std::filesystem::absolute(sys_modules_path).lexically_normal();
|
||||
|
||||
const auto path_str = abs_path.string();
|
||||
const auto sys_path_str = abs_sys_path.string();
|
||||
|
||||
return path_str.starts_with(sys_path_str);
|
||||
}
|
||||
|
||||
static bool IsSystemModule(const std::string& name) {
|
||||
const auto game_modules_path = Common::ElfInfo::Instance().GetGameFolder() / "sce_module";
|
||||
const auto prx_path = game_modules_path / name;
|
||||
|
||||
if (!std::filesystem::exists(prx_path)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void AddModule(const std::string& name, std::filesystem::path path) {
|
||||
if (name == "eboot.bin") {
|
||||
return;
|
||||
}
|
||||
std::scoped_lock lock(modules_mutex);
|
||||
modules.push_back({name, IsSystemModule(path), true});
|
||||
}
|
||||
|
||||
static void AddModule(std::string name) {
|
||||
name = name + ".prx";
|
||||
std::scoped_lock lock(modules_mutex);
|
||||
|
||||
bool is_sys_module = IsSystemModule(name);
|
||||
bool is_lle = false;
|
||||
auto it = std::find_if(modules.begin(), modules.end(),
|
||||
[&name, is_sys_module, is_lle](const ModuleInfo& entry) {
|
||||
return entry.name == name && !entry.is_lle;
|
||||
});
|
||||
|
||||
if (it == modules.end()) {
|
||||
modules.push_back({name, is_sys_module, is_lle});
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct ModuleInfo {
|
||||
std::string name;
|
||||
bool is_sys_module;
|
||||
bool is_lle;
|
||||
};
|
||||
|
||||
static inline std::mutex modules_mutex;
|
||||
|
||||
static inline std::vector<ModuleInfo> modules;
|
||||
};
|
||||
|
||||
} // namespace Core::Devtools::Widget
|
@ -10,6 +10,8 @@
|
||||
|
||||
namespace Core::FileSys {
|
||||
|
||||
bool MntPoints::ignore_game_patches = false;
|
||||
|
||||
std::string RemoveTrailingSlashes(const std::string& path) {
|
||||
// Remove trailing slashes to make comparisons simpler.
|
||||
std::string path_sanitized = path;
|
||||
@ -77,7 +79,7 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea
|
||||
patch_path /= rel_path;
|
||||
|
||||
if ((corrected_path.starts_with("/app0") || corrected_path.starts_with("/hostapp")) &&
|
||||
!force_base_path && std::filesystem::exists(patch_path)) {
|
||||
!force_base_path && !ignore_game_patches && std::filesystem::exists(patch_path)) {
|
||||
return patch_path;
|
||||
}
|
||||
|
||||
@ -137,7 +139,7 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea
|
||||
return std::optional<std::filesystem::path>(current_path);
|
||||
};
|
||||
|
||||
if (!force_base_path) {
|
||||
if (!force_base_path && !ignore_game_patches) {
|
||||
if (const auto path = search(patch_path)) {
|
||||
return *path;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ class MntPoints {
|
||||
static constexpr bool NeedsCaseInsensitiveSearch = true;
|
||||
#endif
|
||||
public:
|
||||
static bool ignore_game_patches;
|
||||
struct MntPair {
|
||||
std::filesystem::path host_path;
|
||||
std::string mount; // e.g /app0
|
||||
|
@ -219,7 +219,7 @@ int PS4_SYSV_ABI sceAjmStrError() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceAjm(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("NVDXiUesSbA", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchCancel);
|
||||
LIB_FUNCTION("WfAiBW8Wcek", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchErrorDump);
|
||||
LIB_FUNCTION("dmDybN--Fn8", "libSceAjm", 1, "libSceAjm", 1, 1, sceAjmBatchJobControlBufferRa);
|
||||
|
@ -229,5 +229,5 @@ int PS4_SYSV_ABI sceAjmModuleRegister(u32 context, AjmCodecType codec_type, s64
|
||||
int PS4_SYSV_ABI sceAjmModuleUnregister();
|
||||
int PS4_SYSV_ABI sceAjmStrError();
|
||||
|
||||
void RegisterlibSceAjm(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Ajm
|
||||
|
@ -369,7 +369,7 @@ int PS4_SYSV_ABI sceAppContentGetDownloadedStoreCountry() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("AS45QoYHjc4", "libSceAppContent", 1, "libSceAppContentUtil", 1, 1, _Z5dummyv);
|
||||
LIB_FUNCTION("ZiATpP9gEkA", "libSceAppContent", 1, "libSceAppContentUtil", 1, 1,
|
||||
sceAppContentAddcontDelete);
|
||||
|
@ -119,5 +119,5 @@ int PS4_SYSV_ABI sceAppContentGetAddcontInfoByEntitlementId();
|
||||
int PS4_SYSV_ABI sceAppContentGetAddcontInfoListByIroTag();
|
||||
int PS4_SYSV_ABI sceAppContentGetDownloadedStoreCountry();
|
||||
|
||||
void RegisterlibSceAppContent(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::AppContent
|
||||
|
@ -218,7 +218,7 @@ int PS4_SYSV_ABI sceAudioInVmicWrite() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceAudioIn(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("IQtWgnrw6v8", "libSceAudioIn", 1, "libSceAudioIn", 1, 1,
|
||||
sceAudioInChangeAppModuleState);
|
||||
LIB_FUNCTION("Jh6WbHhnI68", "libSceAudioIn", 1, "libSceAudioIn", 1, 1, sceAudioInClose);
|
||||
|
@ -54,5 +54,5 @@ int PS4_SYSV_ABI sceAudioInVmicCreate();
|
||||
int PS4_SYSV_ABI sceAudioInVmicDestroy();
|
||||
int PS4_SYSV_ABI sceAudioInVmicWrite();
|
||||
|
||||
void RegisterlibSceAudioIn(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::AudioIn
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "core/libraries/audio/audioout.h"
|
||||
#include "core/libraries/audio/audioout_backend.h"
|
||||
#include "core/libraries/audio/audioout_error.h"
|
||||
#include "core/libraries/kernel/time.h"
|
||||
#include "core/libraries/libs.h"
|
||||
|
||||
namespace Libraries::AudioOut {
|
||||
@ -168,8 +169,19 @@ int PS4_SYSV_ABI sceAudioOutGetInfoOpenNum() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudioOutGetLastOutputTime() {
|
||||
LOG_ERROR(Lib_AudioOut, "(STUBBED) called");
|
||||
int PS4_SYSV_ABI sceAudioOutGetLastOutputTime(s32 handle, u64* output_time) {
|
||||
LOG_DEBUG(Lib_AudioOut, "called, handle: {}, output time: {}", handle, fmt::ptr(output_time));
|
||||
if (!output_time) {
|
||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_POINTER;
|
||||
}
|
||||
if (handle >= ports_out.size()) {
|
||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||
}
|
||||
auto& port = ports_out.at(handle - 1);
|
||||
if (!port.IsOpen()) {
|
||||
return ORBIS_AUDIO_OUT_ERROR_NOT_OPENED;
|
||||
}
|
||||
*output_time = port.last_output_time;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
@ -396,6 +408,7 @@ s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, void* ptr) {
|
||||
if (ptr != nullptr && port.IsOpen()) {
|
||||
std::memcpy(port.output_buffer, ptr, port.BufferSize());
|
||||
port.output_ready = true;
|
||||
port.last_output_time = Kernel::sceKernelGetProcessTime();
|
||||
}
|
||||
}
|
||||
port.output_cv.notify_one();
|
||||
@ -523,9 +536,24 @@ s32 PS4_SYSV_ABI sceAudioOutSetVolume(s32 handle, s32 flag, s32* vol) {
|
||||
}
|
||||
port.impl->SetVolume(port.volume);
|
||||
}
|
||||
AdjustVol();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void AdjustVol() {
|
||||
if (audio == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ports_out.size(); i++) {
|
||||
std::unique_lock lock{ports_out[i].mutex};
|
||||
if (!ports_out[i].IsOpen()) {
|
||||
continue;
|
||||
}
|
||||
ports_out[i].impl->SetVolume(ports_out[i].volume);
|
||||
}
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceAudioOutSetVolumeDown() {
|
||||
LOG_ERROR(Lib_AudioOut, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
@ -596,7 +624,7 @@ int PS4_SYSV_ABI sceAudioOutSetSystemDebugState() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceAudioOut(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("cx2dYFbzIAg", "libSceAudioOutDeviceService", 1, "libSceAudioOut", 1, 1,
|
||||
sceAudioOutDeviceIdOpen);
|
||||
LIB_FUNCTION("tKumjQSzhys", "libSceAudioDeviceControl", 1, "libSceAudioOut", 1, 1,
|
||||
|
@ -96,6 +96,7 @@ struct PortOut {
|
||||
AudioFormatInfo format_info;
|
||||
u32 sample_rate;
|
||||
u32 buffer_frames;
|
||||
u64 last_output_time;
|
||||
std::array<s32, 8> volume;
|
||||
|
||||
[[nodiscard]] bool IsOpen() const {
|
||||
@ -127,7 +128,7 @@ int PS4_SYSV_ABI sceAudioOutGetFocusEnablePid();
|
||||
int PS4_SYSV_ABI sceAudioOutGetHandleStatusInfo();
|
||||
int PS4_SYSV_ABI sceAudioOutGetInfo();
|
||||
int PS4_SYSV_ABI sceAudioOutGetInfoOpenNum();
|
||||
int PS4_SYSV_ABI sceAudioOutGetLastOutputTime();
|
||||
int PS4_SYSV_ABI sceAudioOutGetLastOutputTime(s32 handle, u64* output_time);
|
||||
int PS4_SYSV_ABI sceAudioOutGetPortState(s32 handle, OrbisAudioOutPortState* state);
|
||||
int PS4_SYSV_ABI sceAudioOutGetSimulatedBusUsableStatusByBusType();
|
||||
int PS4_SYSV_ABI sceAudioOutGetSimulatedHandleStatusInfo();
|
||||
@ -181,5 +182,6 @@ int PS4_SYSV_ABI sceAudioOutSystemControlSet();
|
||||
int PS4_SYSV_ABI sceAudioOutSparkControlSetEqCoef();
|
||||
int PS4_SYSV_ABI sceAudioOutSetSystemDebugState();
|
||||
|
||||
void RegisterlibSceAudioOut(Core::Loader::SymbolsResolver* sym);
|
||||
void AdjustVol();
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::AudioOut
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <thread>
|
||||
#include <SDL3/SDL_audio.h>
|
||||
#include <SDL3/SDL_hints.h>
|
||||
#include <common/config.h>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/audio/audioout.h"
|
||||
@ -41,6 +42,7 @@ public:
|
||||
stream = nullptr;
|
||||
return;
|
||||
}
|
||||
SDL_SetAudioStreamGain(stream, Config::getVolumeSlider() / 100.0f);
|
||||
}
|
||||
|
||||
~SDLPortBackend() override {
|
||||
@ -77,7 +79,8 @@ public:
|
||||
}
|
||||
// SDL does not have per-channel volumes, for now just take the maximum of the channels.
|
||||
const auto vol = *std::ranges::max_element(ch_volumes);
|
||||
if (!SDL_SetAudioStreamGain(stream, static_cast<float>(vol) / SCE_AUDIO_OUT_VOLUME_0DB)) {
|
||||
if (!SDL_SetAudioStreamGain(stream, static_cast<float>(vol) / SCE_AUDIO_OUT_VOLUME_0DB *
|
||||
Config::getVolumeSlider() / 100.0f)) {
|
||||
LOG_WARNING(Lib_AudioOut, "Failed to change SDL audio stream volume: {}",
|
||||
SDL_GetError());
|
||||
}
|
||||
|
@ -526,11 +526,18 @@ s32 PS4_SYSV_ABI sceAudio3dStrError() {
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceAudio3dTerminate() {
|
||||
LOG_ERROR(Lib_Audio3d, "(STUBBED) called");
|
||||
LOG_INFO(Lib_Audio3d, "called");
|
||||
if (!state) {
|
||||
return ORBIS_AUDIO3D_ERROR_NOT_READY;
|
||||
}
|
||||
|
||||
AudioOut::sceAudioOutOutput(state->audio_out_handle, nullptr);
|
||||
AudioOut::sceAudioOutClose(state->audio_out_handle);
|
||||
state.release();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceAudio3d(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(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,
|
||||
|
@ -141,5 +141,5 @@ s32 PS4_SYSV_ABI sceAudio3dSetGpuRenderer();
|
||||
s32 PS4_SYSV_ABI sceAudio3dStrError();
|
||||
s32 PS4_SYSV_ABI sceAudio3dTerminate();
|
||||
|
||||
void RegisterlibSceAudio3d(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Audio3d
|
||||
|
@ -278,7 +278,7 @@ s32 PS4_SYSV_ABI sceAvPlayerVprintf(const char* format, va_list args) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceAvPlayer(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("KMcEa+rHsIo", "libSceAvPlayer", 1, "libSceAvPlayer", 1, 0, sceAvPlayerAddSource);
|
||||
LIB_FUNCTION("x8uvuFOPZhU", "libSceAvPlayer", 1, "libSceAvPlayer", 1, 0,
|
||||
sceAvPlayerAddSourceEx);
|
||||
|
@ -290,6 +290,6 @@ enum class SceAvPlayerAvSyncMode {
|
||||
|
||||
using SceAvPlayerLogCallback = int PS4_SYSV_ABI (*)(void* p, const char* format, va_list args);
|
||||
|
||||
void RegisterlibSceAvPlayer(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
|
||||
} // namespace Libraries::AvPlayer
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
FrameBuffer(const SceAvPlayerMemAllocator& memory_replacement, u32 align, u32 size) noexcept
|
||||
: m_memory_replacement(memory_replacement),
|
||||
m_data(Allocate(memory_replacement, align, size)) {
|
||||
ASSERT_MSG(m_data, "Could not allocated frame buffer.");
|
||||
ASSERT_MSG(m_data, "Could not allocate frame buffer.");
|
||||
}
|
||||
|
||||
~FrameBuffer() {
|
||||
|
517
src/core/libraries/camera/camera.cpp
Normal file
517
src/core/libraries/camera/camera.cpp
Normal file
@ -0,0 +1,517 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/camera/camera.h"
|
||||
#include "core/libraries/camera/camera_error.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
|
||||
namespace Libraries::Camera {
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraAccGetData() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraAudioClose() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraAudioGetData() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraAudioGetData2() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraAudioOpen() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraAudioReset() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraChangeAppModuleState() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraClose(s32 handle) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraCloseByHandle() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraDeviceOpen() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetAttribute(s32 handle, OrbisCameraAttribute* pAttribute) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetAutoExposureGain(s32 handle, OrbisCameraChannel channel, u32* pEnable,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetAutoWhiteBalance(s32 handle, OrbisCameraChannel channel, u32* pEnable,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetCalibData() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetCalibDataFromDevice() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetCalibrationData() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetConfig(s32 handle, OrbisCameraConfig* pConfig) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetContrast(s32 handle, OrbisCameraChannel channel, u32* pContrast,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetDefectivePixelCancellation(s32 handle, OrbisCameraChannel channel,
|
||||
u32* pEnable, void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetDeviceConfig() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetDeviceConfigWithoutHandle() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetDeviceID() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetDeviceIDWithoutOpen() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetDeviceInfo(s32 reserved, OrbisCameraDeviceInfo* pDeviceInfo) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetExposureGain(s32 handle, OrbisCameraChannel channel,
|
||||
OrbisCameraExposureGain* pExposureGain, void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetFrameData(int handle, OrbisCameraFrameData* pFrameData) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetGamma(s32 handle, OrbisCameraChannel channel, OrbisCameraGamma* pGamma,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetHue(s32 handle, OrbisCameraChannel channel, s32* pHue, void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetLensCorrection(s32 handle, OrbisCameraChannel channel, u32* pEnable,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetMmapConnectedCount() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetProductInfo() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetRegister() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetRegistryInfo() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetSaturation(s32 handle, OrbisCameraChannel channel, u32* pSaturation,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetSharpness(s32 handle, OrbisCameraChannel channel, u32* pSharpness,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetVrCaptureInfo() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraGetWhiteBalance(s32 handle, OrbisCameraChannel channel,
|
||||
OrbisCameraWhiteBalance* pWhiteBalance, void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraInitializeRegistryCalibData() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraIsAttached(s32 index) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraIsConfigChangeDone() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraIsValidFrameData(int handle, OrbisCameraFrameData* pFrameData) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraOpen(Libraries::UserService::OrbisUserServiceUserId userId, s32 type,
|
||||
s32 index, OrbisCameraOpenParameter* pParam) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraOpenByModuleId() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraRemoveAppModuleFocus() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetAppModuleFocus() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetAttribute(s32 handle, OrbisCameraAttribute* pAttribute) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetAttributeInternal() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetAutoExposureGain(s32 handle, OrbisCameraChannel channel, u32 enable,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetAutoWhiteBalance(s32 handle, OrbisCameraChannel channel, u32 enable,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetCalibData() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetConfig(s32 handle, OrbisCameraConfig* pConfig) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetConfigInternal() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetContrast(s32 handle, OrbisCameraChannel channel, u32 contrast,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetDebugStop() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetDefectivePixelCancellation(s32 handle, OrbisCameraChannel channel,
|
||||
u32 enable, void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetDefectivePixelCancellationInternal() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetExposureGain(s32 handle, OrbisCameraChannel channel,
|
||||
OrbisCameraExposureGain* pExposureGain, void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetForceActivate() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetGamma(s32 handle, OrbisCameraChannel channel, OrbisCameraGamma* pGamma,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetHue(s32 handle, OrbisCameraChannel channel, s32 hue, void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetLensCorrection(s32 handle, OrbisCameraChannel channel, u32 enable,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetLensCorrectionInternal() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetProcessFocus() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetProcessFocusByHandle() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetRegister() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetSaturation(s32 handle, OrbisCameraChannel channel, u32 saturation,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetSharpness(s32 handle, OrbisCameraChannel channel, u32 sharpness,
|
||||
void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetTrackerMode() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetUacModeInternal() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetVideoSync(s32 handle, OrbisCameraVideoSyncParameter* pVideoSync) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetVideoSyncInternal() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraSetWhiteBalance(s32 handle, OrbisCameraChannel channel,
|
||||
OrbisCameraWhiteBalance* pWhiteBalance, void* pOption) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraStart(s32 handle, OrbisCameraStartParameter* pParam) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraStartByHandle() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraStop(s32 handle) {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraStopByHandle() {
|
||||
LOG_ERROR(Lib_Camera, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("QhjrPkRPUZQ", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAccGetData);
|
||||
LIB_FUNCTION("UFonL7xopFM", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioClose);
|
||||
LIB_FUNCTION("fkZE7Hup2ro", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioGetData);
|
||||
LIB_FUNCTION("hftC5A1C8OQ", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioGetData2);
|
||||
LIB_FUNCTION("DhqqFiBU+6g", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioOpen);
|
||||
LIB_FUNCTION("wyU98EXAYxU", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioReset);
|
||||
LIB_FUNCTION("Y0pCDajzkVQ", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraChangeAppModuleState);
|
||||
LIB_FUNCTION("OMS9LlcrvBo", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraClose);
|
||||
LIB_FUNCTION("ztqH5qNTpTk", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraCloseByHandle);
|
||||
LIB_FUNCTION("nBH6i2s4Glc", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraDeviceOpen);
|
||||
LIB_FUNCTION("0btIPD5hg5A", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetAttribute);
|
||||
LIB_FUNCTION("oEi6vM-3E2c", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraGetAutoExposureGain);
|
||||
LIB_FUNCTION("qTPRMh4eY60", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraGetAutoWhiteBalance);
|
||||
LIB_FUNCTION("hHA1frlMxYE", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetCalibData);
|
||||
LIB_FUNCTION("5Oie5RArfWs", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraGetCalibDataFromDevice);
|
||||
LIB_FUNCTION("RHYJ7GKOSMg", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraGetCalibrationData);
|
||||
LIB_FUNCTION("ZaqmGEtYuL0", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetConfig);
|
||||
LIB_FUNCTION("a5xFueMZIMs", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetContrast);
|
||||
LIB_FUNCTION("tslCukqFE+E", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraGetDefectivePixelCancellation);
|
||||
LIB_FUNCTION("DSOLCrc3Kh8", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetDeviceConfig);
|
||||
LIB_FUNCTION("n+rFeP1XXyM", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraGetDeviceConfigWithoutHandle);
|
||||
LIB_FUNCTION("jTJCdyv9GLU", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetDeviceID);
|
||||
LIB_FUNCTION("-H3UwGQvNZI", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraGetDeviceIDWithoutOpen);
|
||||
LIB_FUNCTION("WZpxnSAM-ds", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetDeviceInfo);
|
||||
LIB_FUNCTION("ObIste7hqdk", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetExposureGain);
|
||||
LIB_FUNCTION("mxgMmR+1Kr0", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetFrameData);
|
||||
LIB_FUNCTION("WVox2rwGuSc", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetGamma);
|
||||
LIB_FUNCTION("zrIUDKZx0iE", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetHue);
|
||||
LIB_FUNCTION("XqYRHc4aw3w", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraGetLensCorrection);
|
||||
LIB_FUNCTION("B260o9pSzM8", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraGetMmapConnectedCount);
|
||||
LIB_FUNCTION("ULxbwqiYYuU", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetProductInfo);
|
||||
LIB_FUNCTION("olojYZKYiYs", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetRegister);
|
||||
LIB_FUNCTION("hawKak+Auw4", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetRegistryInfo);
|
||||
LIB_FUNCTION("RTDOsWWqdME", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetSaturation);
|
||||
LIB_FUNCTION("c6Fp9M1EXXc", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetSharpness);
|
||||
LIB_FUNCTION("IAz2HgZQWzE", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetVrCaptureInfo);
|
||||
LIB_FUNCTION("HX5524E5tMY", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetWhiteBalance);
|
||||
LIB_FUNCTION("0wnf2a60FqI", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraInitializeRegistryCalibData);
|
||||
LIB_FUNCTION("p6n3Npi3YY4", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraIsAttached);
|
||||
LIB_FUNCTION("wQfd7kfRZvo", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraIsConfigChangeDone);
|
||||
LIB_FUNCTION("U3BVwQl2R5Q", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraIsValidFrameData);
|
||||
LIB_FUNCTION("BHn83xrF92E", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraOpen);
|
||||
LIB_FUNCTION("eTywOSWsEiI", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraOpenByModuleId);
|
||||
LIB_FUNCTION("py8p6kZcHmA", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraRemoveAppModuleFocus);
|
||||
LIB_FUNCTION("j5isFVIlZLk", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetAppModuleFocus);
|
||||
LIB_FUNCTION("doPlf33ab-U", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetAttribute);
|
||||
LIB_FUNCTION("96F7zp1Xo+k", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetAttributeInternal);
|
||||
LIB_FUNCTION("yfSdswDaElo", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetAutoExposureGain);
|
||||
LIB_FUNCTION("zIKL4kZleuc", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetAutoWhiteBalance);
|
||||
LIB_FUNCTION("LEMk5cTHKEA", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetCalibData);
|
||||
LIB_FUNCTION("VQ+5kAqsE2Q", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetConfig);
|
||||
LIB_FUNCTION("9+SNhbctk64", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetConfigInternal);
|
||||
LIB_FUNCTION("3i5MEzrC1pg", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetContrast);
|
||||
LIB_FUNCTION("vejouEusC7g", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetDebugStop);
|
||||
LIB_FUNCTION("jMv40y2A23g", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetDefectivePixelCancellation);
|
||||
LIB_FUNCTION("vER3cIMBHqI", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetDefectivePixelCancellationInternal);
|
||||
LIB_FUNCTION("wgBMXJJA6K4", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetExposureGain);
|
||||
LIB_FUNCTION("jeTpU0MqKU0", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetForceActivate);
|
||||
LIB_FUNCTION("lhEIsHzB8r4", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetGamma);
|
||||
LIB_FUNCTION("QI8GVJUy2ZY", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetHue);
|
||||
LIB_FUNCTION("K7W7H4ZRwbc", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetLensCorrection);
|
||||
LIB_FUNCTION("eHa3vhGu2rQ", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetLensCorrectionInternal);
|
||||
LIB_FUNCTION("lS0tM6n+Q5E", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetProcessFocus);
|
||||
LIB_FUNCTION("NVITuK83Z7o", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetProcessFocusByHandle);
|
||||
LIB_FUNCTION("8MjO05qk5hA", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetRegister);
|
||||
LIB_FUNCTION("bSKEi2PzzXI", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetSaturation);
|
||||
LIB_FUNCTION("P-7MVfzvpsM", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetSharpness);
|
||||
LIB_FUNCTION("3VJOpzKoIeM", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetTrackerMode);
|
||||
LIB_FUNCTION("nnR7KAIDPv8", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetUacModeInternal);
|
||||
LIB_FUNCTION("wpeyFwJ+UEI", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetVideoSync);
|
||||
LIB_FUNCTION("8WtmqmE4edw", "libSceCamera", 1, "libSceCamera", 1, 1,
|
||||
sceCameraSetVideoSyncInternal);
|
||||
LIB_FUNCTION("k3zPIcgFNv0", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetWhiteBalance);
|
||||
LIB_FUNCTION("9EpRYMy7rHU", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraStart);
|
||||
LIB_FUNCTION("cLxF1QtHch0", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraStartByHandle);
|
||||
LIB_FUNCTION("2G2C0nmd++M", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraStop);
|
||||
LIB_FUNCTION("+X1Kgnn3bzg", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraStopByHandle);
|
||||
};
|
||||
|
||||
} // namespace Libraries::Camera
|
308
src/core/libraries/camera/camera.h
Normal file
308
src/core/libraries/camera/camera.h
Normal file
@ -0,0 +1,308 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <core/libraries/system/userservice.h>
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::Camera {
|
||||
|
||||
constexpr int ORBIS_CAMERA_MAX_DEVICE_NUM = 2;
|
||||
constexpr int ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM = 4;
|
||||
|
||||
enum OrbisCameraChannel {
|
||||
ORBIS_CAMERA_CHANNEL_0 = 1,
|
||||
ORBIS_CAMERA_CHANNEL_1 = 2,
|
||||
ORBIS_CAMERA_CHANNEL_BOTH = 3,
|
||||
};
|
||||
|
||||
struct OrbisCameraOpenParameter {
|
||||
u32 sizeThis;
|
||||
u32 reserved1;
|
||||
u32 reserved2;
|
||||
u32 reserved3;
|
||||
};
|
||||
|
||||
enum OrbisCameraConfigType {
|
||||
ORBIS_CAMERA_CONFIG_TYPE1 = 0x01,
|
||||
ORBIS_CAMERA_CONFIG_TYPE2 = 0x02,
|
||||
ORBIS_CAMERA_CONFIG_TYPE3 = 0x03,
|
||||
ORBIS_CAMERA_CONFIG_TYPE4 = 0x04,
|
||||
ORBIS_CAMERA_CONFIG_TYPE5 = 0x05,
|
||||
ORBIS_CAMERA_CONFIG_EXTENTION = 0x10,
|
||||
};
|
||||
|
||||
enum OrbisCameraResolution {
|
||||
ORBIS_CAMERA_RESOLUTION_1280X800 = 0x0,
|
||||
ORBIS_CAMERA_RESOLUTION_640X400 = 0x1,
|
||||
ORBIS_CAMERA_RESOLUTION_320X200 = 0x2,
|
||||
ORBIS_CAMERA_RESOLUTION_160X100 = 0x3,
|
||||
ORBIS_CAMERA_RESOLUTION_320X192 = 0x4,
|
||||
ORBIS_CAMERA_RESOLUTION_SPECIFIED_WIDTH_HEIGHT,
|
||||
ORBIS_CAMERA_RESOLUTION_UNKNOWN = 0xFF,
|
||||
};
|
||||
|
||||
enum OrbisCameraFramerate {
|
||||
ORBIS_CAMERA_FRAMERATE_UNKNOWN = 0,
|
||||
ORBIS_CAMERA_FRAMERATE_7_5 = 7,
|
||||
ORBIS_CAMERA_FRAMERATE_15 = 15,
|
||||
ORBIS_CAMERA_FRAMERATE_30 = 30,
|
||||
ORBIS_CAMERA_FRAMERATE_60 = 60,
|
||||
ORBIS_CAMERA_FRAMERATE_120 = 120,
|
||||
ORBIS_CAMERA_FRAMERATE_240 = 240,
|
||||
};
|
||||
|
||||
enum OrbisCameraBaseFormat {
|
||||
ORBIS_CAMERA_FORMAT_YUV422 = 0x0,
|
||||
ORBIS_CAMERA_FORMAT_RAW16,
|
||||
ORBIS_CAMERA_FORMAT_RAW8,
|
||||
ORBIS_CAMERA_FORMAT_NO_USE = 0x10,
|
||||
ORBIS_CAMERA_FORMAT_UNKNOWN = 0xFF,
|
||||
};
|
||||
|
||||
enum OrbisCameraScaleFormat {
|
||||
ORBIS_CAMERA_SCALE_FORMAT_YUV422 = 0x0,
|
||||
ORBIS_CAMERA_SCALE_FORMAT_Y16 = 0x3,
|
||||
ORBIS_CAMERA_SCALE_FORMAT_Y8,
|
||||
ORBIS_CAMERA_SCALE_FORMAT_NO_USE = 0x10,
|
||||
ORBIS_CAMERA_SCALE_FORMAT_UNKNOWN = 0xFF,
|
||||
};
|
||||
|
||||
struct OrbisCameraFormat {
|
||||
OrbisCameraBaseFormat formatLevel0;
|
||||
OrbisCameraScaleFormat formatLevel1;
|
||||
OrbisCameraScaleFormat formatLevel2;
|
||||
OrbisCameraScaleFormat formatLevel3;
|
||||
};
|
||||
|
||||
struct OrbisCameraConfigExtention {
|
||||
OrbisCameraFormat format;
|
||||
OrbisCameraResolution resolution;
|
||||
OrbisCameraFramerate framerate;
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 reserved1;
|
||||
void* pBaseOption;
|
||||
};
|
||||
|
||||
struct OrbisCameraConfig {
|
||||
u32 sizeThis;
|
||||
OrbisCameraConfigType configType;
|
||||
OrbisCameraConfigExtention configExtention[ORBIS_CAMERA_MAX_DEVICE_NUM];
|
||||
};
|
||||
|
||||
enum OrbisCameraAecAgcTarget {
|
||||
ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_DEF = 0x00,
|
||||
ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_2_0 = 0x20,
|
||||
ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_1_6 = 0x16,
|
||||
ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_1_4 = 0x14,
|
||||
ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_1_2 = 0x12,
|
||||
ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_1_0 = 0x10,
|
||||
ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_0_8 = 0x08,
|
||||
ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_0_6 = 0x06,
|
||||
ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_0_4 = 0x04,
|
||||
ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_0_2 = 0x02,
|
||||
};
|
||||
|
||||
struct OrbisCameraDeviceInfo {
|
||||
u32 sizeThis;
|
||||
u32 infoRevision;
|
||||
u32 deviceRevision;
|
||||
u32 padding;
|
||||
};
|
||||
|
||||
struct OrbisCameraStartParameter {
|
||||
u32 sizeThis;
|
||||
u32 formatLevel[ORBIS_CAMERA_MAX_DEVICE_NUM];
|
||||
void* pStartOption;
|
||||
};
|
||||
|
||||
struct OrbisCameraVideoSyncParameter {
|
||||
u32 sizeThis;
|
||||
u32 videoSyncMode;
|
||||
void* pModeOption;
|
||||
};
|
||||
|
||||
struct OrbisCameraFramePosition {
|
||||
u32 x;
|
||||
u32 y;
|
||||
u32 xSize;
|
||||
u32 ySize;
|
||||
};
|
||||
|
||||
struct OrbisCameraAutoExposureGainTarget {
|
||||
u32 sizeThis;
|
||||
OrbisCameraAecAgcTarget target;
|
||||
};
|
||||
|
||||
struct OrbisCameraExposureGain {
|
||||
u32 exposureControl;
|
||||
u32 exposure;
|
||||
u32 gain;
|
||||
u32 mode;
|
||||
};
|
||||
|
||||
struct OrbisCameraWhiteBalance {
|
||||
u32 whiteBalanceControl;
|
||||
u32 gainRed;
|
||||
u32 gainBlue;
|
||||
u32 gainGreen;
|
||||
};
|
||||
|
||||
struct OrbisCameraGamma {
|
||||
u32 gammaControl;
|
||||
u32 value;
|
||||
u8 reserved[16];
|
||||
};
|
||||
|
||||
struct OrbisCameraMeta {
|
||||
u32 metaMode;
|
||||
u32 format[ORBIS_CAMERA_MAX_DEVICE_NUM][ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM];
|
||||
u64 frame[ORBIS_CAMERA_MAX_DEVICE_NUM];
|
||||
u64 timestamp[ORBIS_CAMERA_MAX_DEVICE_NUM];
|
||||
u32 deviceTimestamp[ORBIS_CAMERA_MAX_DEVICE_NUM];
|
||||
OrbisCameraExposureGain exposureGain[ORBIS_CAMERA_MAX_DEVICE_NUM];
|
||||
OrbisCameraWhiteBalance whiteBalance[ORBIS_CAMERA_MAX_DEVICE_NUM];
|
||||
OrbisCameraGamma gamma[ORBIS_CAMERA_MAX_DEVICE_NUM];
|
||||
u32 luminance[ORBIS_CAMERA_MAX_DEVICE_NUM];
|
||||
float acceleration_x;
|
||||
float acceleration_y;
|
||||
float acceleration_z;
|
||||
u64 vcounter;
|
||||
u32 reserved[14];
|
||||
};
|
||||
|
||||
struct OrbisCameraFrameData {
|
||||
u32 sizeThis;
|
||||
u32 readMode;
|
||||
OrbisCameraFramePosition framePosition[ORBIS_CAMERA_MAX_DEVICE_NUM]
|
||||
[ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM];
|
||||
void* pFramePointerList[ORBIS_CAMERA_MAX_DEVICE_NUM][ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM];
|
||||
u32 frameSize[ORBIS_CAMERA_MAX_DEVICE_NUM][ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM];
|
||||
u32 status[ORBIS_CAMERA_MAX_DEVICE_NUM];
|
||||
OrbisCameraMeta meta;
|
||||
void* pFramePointerListGarlic[ORBIS_CAMERA_MAX_DEVICE_NUM][ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM];
|
||||
};
|
||||
|
||||
struct OrbisCameraAttribute {
|
||||
u32 sizeThis;
|
||||
OrbisCameraChannel channel;
|
||||
OrbisCameraFramePosition framePosition;
|
||||
OrbisCameraExposureGain exposureGain;
|
||||
OrbisCameraWhiteBalance whiteBalance;
|
||||
OrbisCameraGamma gamma;
|
||||
u32 saturation;
|
||||
u32 contrast;
|
||||
u32 sharpness;
|
||||
s32 hue;
|
||||
u32 reserved1;
|
||||
u32 reserved2;
|
||||
u32 reserved3;
|
||||
u32 reserved4;
|
||||
};
|
||||
|
||||
s32 PS4_SYSV_ABI sceCameraAccGetData();
|
||||
s32 PS4_SYSV_ABI sceCameraAudioClose();
|
||||
s32 PS4_SYSV_ABI sceCameraAudioGetData();
|
||||
s32 PS4_SYSV_ABI sceCameraAudioGetData2();
|
||||
s32 PS4_SYSV_ABI sceCameraAudioOpen();
|
||||
s32 PS4_SYSV_ABI sceCameraAudioReset();
|
||||
s32 PS4_SYSV_ABI sceCameraChangeAppModuleState();
|
||||
s32 PS4_SYSV_ABI sceCameraClose(s32 handle);
|
||||
s32 PS4_SYSV_ABI sceCameraCloseByHandle();
|
||||
s32 PS4_SYSV_ABI sceCameraDeviceOpen();
|
||||
s32 PS4_SYSV_ABI sceCameraGetAttribute(s32 handle, OrbisCameraAttribute* pAttribute);
|
||||
s32 PS4_SYSV_ABI sceCameraGetAutoExposureGain(s32 handle, OrbisCameraChannel channel, u32* pEnable,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraGetAutoWhiteBalance(s32 handle, OrbisCameraChannel channel, u32* pEnable,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraGetCalibData();
|
||||
s32 PS4_SYSV_ABI sceCameraGetCalibDataFromDevice();
|
||||
s32 PS4_SYSV_ABI sceCameraGetCalibrationData();
|
||||
s32 PS4_SYSV_ABI sceCameraGetConfig(s32 handle, OrbisCameraConfig* pConfig);
|
||||
s32 PS4_SYSV_ABI sceCameraGetContrast(s32 handle, OrbisCameraChannel channel, u32* pContrast,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraGetDefectivePixelCancellation(s32 handle, OrbisCameraChannel channel,
|
||||
u32* pEnable, void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraGetDeviceConfig();
|
||||
s32 PS4_SYSV_ABI sceCameraGetDeviceConfigWithoutHandle();
|
||||
s32 PS4_SYSV_ABI sceCameraGetDeviceID();
|
||||
s32 PS4_SYSV_ABI sceCameraGetDeviceIDWithoutOpen();
|
||||
s32 PS4_SYSV_ABI sceCameraGetDeviceInfo(s32 reserved, OrbisCameraDeviceInfo* pDeviceInfo);
|
||||
s32 PS4_SYSV_ABI sceCameraGetExposureGain(s32 handle, OrbisCameraChannel channel,
|
||||
OrbisCameraExposureGain* pExposureGain, void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraGetFrameData(int handle, OrbisCameraFrameData* pFrameData);
|
||||
s32 PS4_SYSV_ABI sceCameraGetGamma(s32 handle, OrbisCameraChannel channel, OrbisCameraGamma* pGamma,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraGetHue(s32 handle, OrbisCameraChannel channel, s32* pHue, void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraGetLensCorrection(s32 handle, OrbisCameraChannel channel, u32* pEnable,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraGetMmapConnectedCount();
|
||||
s32 PS4_SYSV_ABI sceCameraGetProductInfo();
|
||||
s32 PS4_SYSV_ABI sceCameraGetRegister();
|
||||
s32 PS4_SYSV_ABI sceCameraGetRegistryInfo();
|
||||
s32 PS4_SYSV_ABI sceCameraGetSaturation(s32 handle, OrbisCameraChannel channel, u32* pSaturation,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraGetSharpness(s32 handle, OrbisCameraChannel channel, u32* pSharpness,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraGetVrCaptureInfo();
|
||||
s32 PS4_SYSV_ABI sceCameraGetWhiteBalance(s32 handle, OrbisCameraChannel channel,
|
||||
OrbisCameraWhiteBalance* pWhiteBalance, void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraInitializeRegistryCalibData();
|
||||
s32 PS4_SYSV_ABI sceCameraIsAttached(s32 index);
|
||||
s32 PS4_SYSV_ABI sceCameraIsConfigChangeDone();
|
||||
s32 PS4_SYSV_ABI sceCameraIsValidFrameData(int handle, OrbisCameraFrameData* pFrameData);
|
||||
s32 PS4_SYSV_ABI sceCameraOpen(Libraries::UserService::OrbisUserServiceUserId userId, s32 type,
|
||||
s32 index, OrbisCameraOpenParameter* pParam);
|
||||
s32 PS4_SYSV_ABI sceCameraOpenByModuleId();
|
||||
s32 PS4_SYSV_ABI sceCameraRemoveAppModuleFocus();
|
||||
s32 PS4_SYSV_ABI sceCameraSetAppModuleFocus();
|
||||
s32 PS4_SYSV_ABI sceCameraSetAttribute(s32 handle, OrbisCameraAttribute* pAttribute);
|
||||
s32 PS4_SYSV_ABI sceCameraSetAttributeInternal();
|
||||
s32 PS4_SYSV_ABI sceCameraSetAutoExposureGain(s32 handle, OrbisCameraChannel channel, u32 enable,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraSetAutoWhiteBalance(s32 handle, OrbisCameraChannel channel, u32 enable,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraSetCalibData();
|
||||
s32 PS4_SYSV_ABI sceCameraSetConfig(s32 handle, OrbisCameraConfig* pConfig);
|
||||
s32 PS4_SYSV_ABI sceCameraSetConfigInternal();
|
||||
s32 PS4_SYSV_ABI sceCameraSetContrast(s32 handle, OrbisCameraChannel channel, u32 contrast,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraSetDebugStop();
|
||||
s32 PS4_SYSV_ABI sceCameraSetDefectivePixelCancellation(s32 handle, OrbisCameraChannel channel,
|
||||
u32 enable, void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraSetDefectivePixelCancellationInternal();
|
||||
s32 PS4_SYSV_ABI sceCameraSetExposureGain(s32 handle, OrbisCameraChannel channel,
|
||||
OrbisCameraExposureGain* pExposureGain, void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraSetForceActivate();
|
||||
s32 PS4_SYSV_ABI sceCameraSetGamma(s32 handle, OrbisCameraChannel channel, OrbisCameraGamma* pGamma,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraSetHue(s32 handle, OrbisCameraChannel channel, s32 hue, void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraSetLensCorrection(s32 handle, OrbisCameraChannel channel, u32 enable,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraSetLensCorrectionInternal();
|
||||
s32 PS4_SYSV_ABI sceCameraSetProcessFocus();
|
||||
s32 PS4_SYSV_ABI sceCameraSetProcessFocusByHandle();
|
||||
s32 PS4_SYSV_ABI sceCameraSetRegister();
|
||||
s32 PS4_SYSV_ABI sceCameraSetSaturation(s32 handle, OrbisCameraChannel channel, u32 saturation,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraSetSharpness(s32 handle, OrbisCameraChannel channel, u32 sharpness,
|
||||
void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraSetTrackerMode();
|
||||
s32 PS4_SYSV_ABI sceCameraSetUacModeInternal();
|
||||
s32 PS4_SYSV_ABI sceCameraSetVideoSync(s32 handle, OrbisCameraVideoSyncParameter* pVideoSync);
|
||||
s32 PS4_SYSV_ABI sceCameraSetVideoSyncInternal();
|
||||
s32 PS4_SYSV_ABI sceCameraSetWhiteBalance(s32 handle, OrbisCameraChannel channel,
|
||||
OrbisCameraWhiteBalance* pWhiteBalance, void* pOption);
|
||||
s32 PS4_SYSV_ABI sceCameraStart(s32 handle, OrbisCameraStartParameter* pParam);
|
||||
s32 PS4_SYSV_ABI sceCameraStartByHandle();
|
||||
s32 PS4_SYSV_ABI sceCameraStop(s32 handle);
|
||||
s32 PS4_SYSV_ABI sceCameraStopByHandle();
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Camera
|
29
src/core/libraries/camera/camera_error.h
Normal file
29
src/core/libraries/camera/camera_error.h
Normal file
@ -0,0 +1,29 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
constexpr int ORBIS_CAMERA_ERROR_PARAM = 0x802E0000;
|
||||
constexpr int ORBIS_CAMERA_ERROR_ALREADY_INIT = 0x802E0001;
|
||||
constexpr int ORBIS_CAMERA_ERROR_NOT_INIT = 0x802E0002;
|
||||
constexpr int ORBIS_CAMERA_ERROR_ALREADY_OPEN = 0x802E0003;
|
||||
constexpr int ORBIS_CAMERA_ERROR_NOT_OPEN = 0x802E0004;
|
||||
constexpr int ORBIS_CAMERA_ERROR_ALREADY_START = 0x802E0005;
|
||||
constexpr int ORBIS_CAMERA_ERROR_NOT_START = 0x802E0006;
|
||||
constexpr int ORBIS_CAMERA_ERROR_FORMAT_UNKNOWN = 0x802E0007;
|
||||
constexpr int ORBIS_CAMERA_ERROR_RESOLUTION_UNKNOWN = 0x802E0008;
|
||||
constexpr int ORBIS_CAMERA_ERROR_BAD_FRAMERATE = 0x802E0009;
|
||||
constexpr int ORBIS_CAMERA_ERROR_TIMEOUT = 0x802E000A;
|
||||
constexpr int ORBIS_CAMERA_ERROR_ATTRIBUTE_UNKNOWN = 0x802E000B;
|
||||
constexpr int ORBIS_CAMERA_ERROR_BUSY = 0x802E000C;
|
||||
constexpr int ORBIS_CAMERA_ERROR_UNKNOWN_CONFIG = 0x802E000D;
|
||||
constexpr int ORBIS_CAMERA_ERROR_ALREADY_READ = 0x802E000F;
|
||||
constexpr int ORBIS_CAMERA_ERROR_NOT_CONNECTED = 0x802E0010;
|
||||
constexpr int ORBIS_CAMERA_ERROR_NOT_SUPPORTED = 0x802E0011;
|
||||
constexpr int ORBIS_CAMERA_ERROR_INVALID_CONFIG = 0x802E0013;
|
||||
constexpr int ORBIS_CAMERA_ERROR_MAX_HANDLE = 0x802E0014;
|
||||
constexpr int ORBIS_CAMERA_ERROR_MAX_PROCESS = 0x802E00FB;
|
||||
constexpr int ORBIS_CAMERA_ERROR_COPYOUT_FAILED = 0x802E00FC;
|
||||
constexpr int ORBIS_CAMERA_ERROR_COPYIN_FAILED = 0x802E00FD;
|
||||
constexpr int ORBIS_CAMERA_ERROR_KPROC_CREATE = 0x802E00FE;
|
||||
constexpr int ORBIS_CAMERA_ERROR_FATAL = 0x802E00FF;
|
27
src/core/libraries/companion/companion_error.h
Normal file
27
src/core/libraries/companion/companion_error.h
Normal file
@ -0,0 +1,27 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
// companion_httpd error codes
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_UNKNOWN = 0x80E40001;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_FATAL = 0x80E40002;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_NOMEM = 0x80E40003;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_INVALID_PARAM = 0x80E40004;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_INVALID_OPERATION = 0x80E40005;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_NOT_INITIALIZED = 0x80E40006;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_ALREADY_INITIALIZED = 0x80E40007;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_NO_EVENT = 0x80E40008;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_NOT_GENERATE_RESPONSE = 0x80E40009;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_ALREADY_STARTED = 0x80E4000A;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_NOT_STARTED = 0x80E4000B;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_ALREADY_REGISTERED = 0x80E4000;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_NOT_CONNECTED = 0x80E4000D;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_ERROR_USER_NOT_FOUND = 0x80E4000E;
|
||||
|
||||
// companion_util error codes
|
||||
constexpr u32 ORBIS_COMPANION_UTIL_INVALID_ARGUMENT = 0x80AD0004;
|
||||
constexpr u32 ORBIS_COMPANION_UTIL_INVALID_POINTER = 0x80AD0006;
|
||||
constexpr u32 ORBIS_COMPANION_UTIL_NO_EVENT = 0x80AD0008;
|
142
src/core/libraries/companion/companion_httpd.cpp
Normal file
142
src/core/libraries/companion/companion_httpd.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "companion_error.h"
|
||||
#include "core/libraries/companion/companion_httpd.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
|
||||
namespace Libraries::CompanionHttpd {
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdAddHeader(const char* key, const char* value,
|
||||
OrbisCompanionHttpdResponse* response) {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI
|
||||
sceCompanionHttpdGet2ndScreenStatus(Libraries::UserService::OrbisUserServiceUserId) {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdGetEvent(OrbisCompanionHttpdEvent* pEvent) {
|
||||
pEvent->event = ORBIS_COMPANION_HTTPD_EVENT_DISCONNECT; // disconnected
|
||||
LOG_DEBUG(Lib_CompanionHttpd, "device disconnected");
|
||||
return ORBIS_COMPANION_HTTPD_ERROR_NO_EVENT; // No events to obtain
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI
|
||||
sceCompanionHttpdGetUserId(u32 addr, Libraries::UserService::OrbisUserServiceUserId* userId) {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdInitialize() {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdInitialize2() {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdOptParamInitialize() {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdRegisterRequestBodyReceptionCallback(
|
||||
OrbisCompanionHttpdRequestBodyReceptionCallback function, void* param) {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI
|
||||
sceCompanionHttpdRegisterRequestCallback(OrbisCompanionHttpdRequestCallback function, void* param) {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdRegisterRequestCallback2(
|
||||
OrbisCompanionHttpdRequestCallback function, void* param) {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdSetBody(const char* body, u64 bodySize,
|
||||
OrbisCompanionHttpdResponse* response) {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdSetStatus(s32 status, OrbisCompanionHttpdResponse* response) {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdStart() {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdStop() {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdTerminate() {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdUnregisterRequestBodyReceptionCallback() {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdUnregisterRequestCallback() {
|
||||
LOG_ERROR(Lib_CompanionHttpd, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("8pWltDG7h6A", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdAddHeader);
|
||||
LIB_FUNCTION("B-QBMeFdNgY", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdGet2ndScreenStatus);
|
||||
LIB_FUNCTION("Vku4big+IYM", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdGetEvent);
|
||||
LIB_FUNCTION("0SySxcuVNG0", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdGetUserId);
|
||||
LIB_FUNCTION("ykNpWs3ktLY", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdInitialize);
|
||||
LIB_FUNCTION("OA6FbORefbo", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdInitialize2);
|
||||
LIB_FUNCTION("r-2-a0c7Kfc", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdOptParamInitialize);
|
||||
LIB_FUNCTION("fHNmij7kAUM", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdRegisterRequestBodyReceptionCallback);
|
||||
LIB_FUNCTION("OaWw+IVEdbI", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdRegisterRequestCallback);
|
||||
LIB_FUNCTION("-0c9TCTwnGs", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdRegisterRequestCallback2);
|
||||
LIB_FUNCTION("h3OvVxzX4qM", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdSetBody);
|
||||
LIB_FUNCTION("w7oz0AWHpT4", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdSetStatus);
|
||||
LIB_FUNCTION("k7F0FcDM-Xc", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdStart);
|
||||
LIB_FUNCTION("0SCgzfVQHpo", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdStop);
|
||||
LIB_FUNCTION("+-du9tWgE9s", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdTerminate);
|
||||
LIB_FUNCTION("ZSHiUfYK+QI", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdUnregisterRequestBodyReceptionCallback);
|
||||
LIB_FUNCTION("xweOi2QT-BE", "libSceCompanionHttpd", 1, "libSceCompanionHttpd", 1, 1,
|
||||
sceCompanionHttpdUnregisterRequestCallback);
|
||||
};
|
||||
|
||||
} // namespace Libraries::CompanionHttpd
|
91
src/core/libraries/companion/companion_httpd.h
Normal file
91
src/core/libraries/companion/companion_httpd.h
Normal file
@ -0,0 +1,91 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/network/net.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::CompanionHttpd {
|
||||
|
||||
// OrbisCompanionHttpdEvent event codes
|
||||
constexpr int ORBIS_COMPANION_HTTPD_EVENT_CONNECT = 0x10000001;
|
||||
constexpr int ORBIS_COMPANION_HTTPD_EVENT_DISCONNECT = 0x10000002;
|
||||
|
||||
struct OrbisCompanionHttpdHeader {
|
||||
char* key;
|
||||
char* value;
|
||||
struct OrbisCompanionHttpdHeader* header;
|
||||
};
|
||||
|
||||
struct OrbisCompanionHttpdRequest {
|
||||
s32 method;
|
||||
char* url;
|
||||
OrbisCompanionHttpdHeader* header;
|
||||
char* body;
|
||||
u64 bodySize;
|
||||
};
|
||||
|
||||
struct OrbisCompanionHttpdResponse {
|
||||
s32 status;
|
||||
OrbisCompanionHttpdHeader* header;
|
||||
char* body;
|
||||
u64 bodySize;
|
||||
};
|
||||
|
||||
using OrbisCompanionHttpdRequestBodyReceptionCallback =
|
||||
PS4_SYSV_ABI s32 (*)(s32 event, Libraries::UserService::OrbisUserServiceUserId userId,
|
||||
const OrbisCompanionHttpdRequest* httpRequest, void* param);
|
||||
|
||||
using OrbisCompanionHttpdRequestCallback =
|
||||
PS4_SYSV_ABI s32 (*)(Libraries::UserService::OrbisUserServiceUserId userId,
|
||||
const OrbisCompanionHttpdRequest* httpRequest,
|
||||
OrbisCompanionHttpdResponse* httpResponse, void* param);
|
||||
|
||||
struct OrbisCompanionUtilDeviceInfo {
|
||||
Libraries::UserService::OrbisUserServiceUserId userId;
|
||||
Libraries::Net::OrbisNetSockaddrIn addr;
|
||||
char reserved[236];
|
||||
};
|
||||
|
||||
struct OrbisCompanionHttpdEvent {
|
||||
s32 event;
|
||||
union {
|
||||
OrbisCompanionUtilDeviceInfo deviceInfo;
|
||||
Libraries::UserService::OrbisUserServiceUserId userId;
|
||||
char reserved[256];
|
||||
} data;
|
||||
};
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdAddHeader(const char* key, const char* value,
|
||||
OrbisCompanionHttpdResponse* response);
|
||||
s32 PS4_SYSV_ABI
|
||||
sceCompanionHttpdGet2ndScreenStatus(Libraries::UserService::OrbisUserServiceUserId userId);
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdGetEvent(OrbisCompanionHttpdEvent* pEvent);
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdGetUserId(u32 addr,
|
||||
Libraries::UserService::OrbisUserServiceUserId* userId);
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdInitialize();
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdInitialize2();
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdOptParamInitialize();
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdRegisterRequestBodyReceptionCallback(
|
||||
OrbisCompanionHttpdRequestBodyReceptionCallback function, void* param);
|
||||
s32 PS4_SYSV_ABI
|
||||
sceCompanionHttpdRegisterRequestCallback(OrbisCompanionHttpdRequestCallback function, void* param);
|
||||
s32 PS4_SYSV_ABI
|
||||
sceCompanionHttpdRegisterRequestCallback2(OrbisCompanionHttpdRequestCallback function, void* param);
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdSetBody(const char* body, u64 bodySize,
|
||||
OrbisCompanionHttpdResponse* response);
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdSetStatus(s32 status, OrbisCompanionHttpdResponse* response);
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdStart();
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdStop();
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdTerminate();
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdUnregisterRequestBodyReceptionCallback();
|
||||
s32 PS4_SYSV_ABI sceCompanionHttpdUnregisterRequestCallback();
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::CompanionHttpd
|
72
src/core/libraries/companion/companion_util.cpp
Normal file
72
src/core/libraries/companion/companion_util.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "companion_error.h"
|
||||
#include "core/libraries/companion/companion_util.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
|
||||
namespace Libraries::CompanionUtil {
|
||||
|
||||
u32 PS4_SYSV_ABI getEvent(sceCompanionUtilContext* ctx, sceCompanionUtilEvent* outEvent,
|
||||
s32 param_3) {
|
||||
if (outEvent == 0) {
|
||||
return ORBIS_COMPANION_UTIL_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (ctx == nullptr) {
|
||||
return ORBIS_COMPANION_UTIL_INVALID_POINTER;
|
||||
}
|
||||
|
||||
uint8_t* base = ctx->blob;
|
||||
int flag = *reinterpret_cast<int*>(base + 0x178);
|
||||
if (flag == 0) {
|
||||
return ORBIS_COMPANION_UTIL_NO_EVENT;
|
||||
}
|
||||
|
||||
return ORBIS_COMPANION_UTIL_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilGetEvent(sceCompanionUtilEvent* outEvent) {
|
||||
sceCompanionUtilContext* ctx = nullptr;
|
||||
u32 ret = getEvent(ctx, outEvent, 1);
|
||||
|
||||
LOG_DEBUG(Lib_CompanionUtil, "(STUBBED) called ret: {}", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilGetRemoteOskEvent() {
|
||||
LOG_ERROR(Lib_CompanionUtil, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilInitialize() {
|
||||
LOG_ERROR(Lib_CompanionUtil, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilOptParamInitialize() {
|
||||
LOG_ERROR(Lib_CompanionUtil, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilTerminate() {
|
||||
LOG_ERROR(Lib_CompanionUtil, "(STUBBED) called");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("cE5Msy11WhU", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
|
||||
sceCompanionUtilGetEvent);
|
||||
LIB_FUNCTION("MaVrz79mT5o", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
|
||||
sceCompanionUtilGetRemoteOskEvent);
|
||||
LIB_FUNCTION("xb1xlIhf0QY", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
|
||||
sceCompanionUtilInitialize);
|
||||
LIB_FUNCTION("IPN-FRSrafk", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
|
||||
sceCompanionUtilOptParamInitialize);
|
||||
LIB_FUNCTION("H1fYQd5lFAI", "libSceCompanionUtil", 1, "libSceCompanionUtil", 1, 1,
|
||||
sceCompanionUtilTerminate);
|
||||
};
|
||||
|
||||
} // namespace Libraries::CompanionUtil
|
33
src/core/libraries/companion/companion_util.h
Normal file
33
src/core/libraries/companion/companion_util.h
Normal file
@ -0,0 +1,33 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
}
|
||||
|
||||
namespace Libraries::CompanionUtil {
|
||||
|
||||
constexpr u32 ORBIS_COMPANION_UTIL_OK = 0;
|
||||
|
||||
struct sceCompanionUtilEvent {
|
||||
std::uint8_t blob[0x104]{}; /// 0x104 bytes of data, dont know what it is exactly
|
||||
};
|
||||
|
||||
struct sceCompanionUtilContext {
|
||||
std::uint8_t blob[0x27B]{}; /// 0x27B bytes of data, dont know what it is exactly
|
||||
};
|
||||
|
||||
u32 PS4_SYSV_ABI getEvent(sceCompanionUtilContext* ctx, sceCompanionUtilEvent* outEvent,
|
||||
s32 param_3);
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilGetEvent(sceCompanionUtilEvent* outEvent);
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilGetRemoteOskEvent();
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilInitialize();
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilOptParamInitialize();
|
||||
s32 PS4_SYSV_ABI sceCompanionUtilTerminate();
|
||||
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::CompanionUtil
|
@ -34,7 +34,7 @@ int PS4_SYSV_ABI Func_E7EBCE96E92F91F8() {
|
||||
return ORBIS_DISC_MAP_ERROR_NO_BITMAP_INFO;
|
||||
}
|
||||
|
||||
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("fl1eoDnwQ4s", "libSceDiscMap", 1, "libSceDiscMap", 1, 1,
|
||||
sceDiscMapGetPackageSize);
|
||||
LIB_FUNCTION("lbQKqsERhtE", "libSceDiscMap", 1, "libSceDiscMap", 1, 1,
|
||||
|
@ -18,5 +18,5 @@ int PS4_SYSV_ABI Func_8A828CAEE7EDD5E9(char* path, s64 offset, s64 nbytes, int*
|
||||
int* ret2);
|
||||
int PS4_SYSV_ABI Func_E7EBCE96E92F91F8();
|
||||
|
||||
void RegisterlibSceDiscMap(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::DiscMap
|
@ -545,7 +545,7 @@ s32 PS4_SYSV_ABI sceFiberSwitch(OrbisFiber* fiber, u64 arg_on_run_to, u64* arg_o
|
||||
return sceFiberSwitchImpl(fiber, nullptr, 0, arg_on_run_to, arg_on_run);
|
||||
}
|
||||
|
||||
void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("hVYD7Ou2pCQ", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberInitialize);
|
||||
LIB_FUNCTION("7+OJIpko9RY", "libSceFiber", 1, "libSceFiber", 1, 1,
|
||||
sceFiberInitializeImpl); // _sceFiberInitializeWithInternalOptionImpl
|
||||
|
@ -116,5 +116,5 @@ s32 PS4_SYSV_ABI sceFiberRename(OrbisFiber* fiber, const char* name);
|
||||
|
||||
s32 PS4_SYSV_ABI sceFiberGetThreadFramePointerAddress(u64* addr_frame_pointer);
|
||||
|
||||
void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Fiber
|
@ -246,7 +246,7 @@ int PS4_SYSV_ABI sceGameLiveStreamingUnregisterCallback() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceGameLiveStreaming(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("caqgDl+V9qA", "libSceGameLiveStreaming_debug", 1, "libSceGameLiveStreaming", 1, 1,
|
||||
sceGameLiveStreamingStartDebugBroadcast);
|
||||
LIB_FUNCTION("0i8Lrllxwow", "libSceGameLiveStreaming_debug", 1, "libSceGameLiveStreaming", 1, 1,
|
||||
|
@ -77,5 +77,5 @@ int PS4_SYSV_ABI sceGameLiveStreamingStopSocialFeedbackMessageFiltering();
|
||||
int PS4_SYSV_ABI sceGameLiveStreamingTerminate();
|
||||
int PS4_SYSV_ABI sceGameLiveStreamingUnregisterCallback();
|
||||
|
||||
void RegisterlibSceGameLiveStreaming(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::GameLiveStreaming
|
@ -179,7 +179,7 @@ s32 PS4_SYSV_ABI sceGnmComputeWaitOnAddress(u32* cmdbuf, u32 size, uintptr_t add
|
||||
auto* wait_reg_mem = reinterpret_cast<PM4CmdWaitRegMem*>(cmdbuf);
|
||||
wait_reg_mem->header = PM4Type3Header{PM4ItOpcode::WaitRegMem, 5};
|
||||
wait_reg_mem->raw = (is_mem << 4u) | (cmp_func & 7u);
|
||||
wait_reg_mem->poll_addr_lo = u32(addr & addr_mask);
|
||||
wait_reg_mem->poll_addr_lo_raw = u32(addr & addr_mask);
|
||||
wait_reg_mem->poll_addr_hi = u32(addr >> 32u);
|
||||
wait_reg_mem->ref = ref;
|
||||
wait_reg_mem->mask = mask;
|
||||
@ -505,9 +505,10 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti(u32* cmdbuf, u32 size, u32 da
|
||||
u32 flags) {
|
||||
LOG_TRACE(Lib_GnmDriver, "called");
|
||||
|
||||
if ((!sceKernelIsNeoMode() || !UseNeoCompatSequences) && !cmdbuf && (size == 16) &&
|
||||
(shader_stage < ShaderStages::Max) && (vertex_sgpr_offset < 0x10u) &&
|
||||
(instance_sgpr_offset < 0x10u)) {
|
||||
if ((!sceKernelIsNeoMode() || !UseNeoCompatSequences) && cmdbuf && (size == 16) &&
|
||||
(vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u) &&
|
||||
(shader_stage == ShaderStages::Vs || shader_stage == ShaderStages::Es ||
|
||||
shader_stage == ShaderStages::Ls)) {
|
||||
|
||||
cmdbuf = WriteHeader<PM4ItOpcode::Nop>(cmdbuf, 2);
|
||||
cmdbuf = WriteBody(cmdbuf, 0u);
|
||||
@ -535,10 +536,33 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti(u32* cmdbuf, u32 size, u32 da
|
||||
return -1;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti() {
|
||||
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");
|
||||
UNREACHABLE();
|
||||
return ORBIS_OK;
|
||||
int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti(u32* cmdbuf, u32 size, u32 data_offset, u32 max_count,
|
||||
u32 shader_stage, u32 vertex_sgpr_offset,
|
||||
u32 instance_sgpr_offset, u32 flags) {
|
||||
LOG_TRACE(Lib_GnmDriver, "called");
|
||||
|
||||
if (cmdbuf && (size == 11) && (vertex_sgpr_offset < 0x10u) && (instance_sgpr_offset < 0x10u) &&
|
||||
(shader_stage == ShaderStages::Vs || shader_stage == ShaderStages::Es ||
|
||||
shader_stage == ShaderStages::Ls)) {
|
||||
|
||||
const auto predicate = flags & 1 ? PM4Predicate::PredEnable : PM4Predicate::PredDisable;
|
||||
cmdbuf = WriteHeader<PM4ItOpcode::DrawIndexIndirectMulti>(
|
||||
cmdbuf, 6, PM4ShaderType::ShaderGraphics, predicate);
|
||||
|
||||
const auto sgpr_offset = indirect_sgpr_offsets[shader_stage];
|
||||
|
||||
cmdbuf[0] = data_offset;
|
||||
cmdbuf[1] = vertex_sgpr_offset == 0 ? 0 : (vertex_sgpr_offset & 0xffffu) + sgpr_offset;
|
||||
cmdbuf[2] = instance_sgpr_offset == 0 ? 0 : (instance_sgpr_offset & 0xffffu) + sgpr_offset;
|
||||
cmdbuf[3] = max_count;
|
||||
cmdbuf[4] = sizeof(DrawIndexedIndirectArgs);
|
||||
cmdbuf[5] = sceKernelIsNeoMode() ? flags & 0xe0000000u : 0;
|
||||
|
||||
cmdbuf += 6;
|
||||
WriteTrailingNop<3>(cmdbuf);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceGnmDrawIndexMultiInstanced() {
|
||||
@ -2799,7 +2823,7 @@ int PS4_SYSV_ABI Func_F916890425496553() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LOG_INFO(Lib_GnmDriver, "Initializing presenter");
|
||||
liverpool = std::make_unique<AmdGpu::Liverpool>();
|
||||
presenter = std::make_unique<Vulkan::Presenter>(*g_window, liverpool.get());
|
||||
@ -2810,7 +2834,7 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) {
|
||||
}
|
||||
|
||||
if (Config::copyGPUCmdBuffers()) {
|
||||
liverpool->reserveCopyBufferSpace();
|
||||
liverpool->ReserveCopyBufferSpace();
|
||||
}
|
||||
|
||||
Platform::IrqC::Instance()->Register(Platform::InterruptId::GpuIdle, ResetSubmissionLock,
|
||||
|
@ -51,7 +51,9 @@ s32 PS4_SYSV_ABI sceGnmDrawIndexIndirectCountMulti(u32* cmdbuf, u32 size, u32 da
|
||||
u32 max_count, u64 count_addr, u32 shader_stage,
|
||||
u32 vertex_sgpr_offset, u32 instance_sgpr_offset,
|
||||
u32 flags);
|
||||
int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti();
|
||||
int PS4_SYSV_ABI sceGnmDrawIndexIndirectMulti(u32* cmdbuf, u32 size, u32 data_offset, u32 max_count,
|
||||
u32 shader_stage, u32 vertex_sgpr_offset,
|
||||
u32 instance_sgpr_offset, u32 flags);
|
||||
int PS4_SYSV_ABI sceGnmDrawIndexMultiInstanced();
|
||||
s32 PS4_SYSV_ABI sceGnmDrawIndexOffset(u32* cmdbuf, u32 size, u32 index_offset, u32 index_count,
|
||||
u32 flags);
|
||||
@ -295,5 +297,5 @@ int PS4_SYSV_ABI Func_BFB41C057478F0BF();
|
||||
int PS4_SYSV_ABI Func_E51D44DB8151238C();
|
||||
int PS4_SYSV_ABI Func_F916890425496553();
|
||||
|
||||
void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::GnmDriver
|
||||
|
@ -939,7 +939,7 @@ s32 PS4_SYSV_ABI Func_FF2E0E53015FE231() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceHmd(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("8gH1aLgty5I", "libsceHmdReprojectionMultilayer", 1, "libSceHmd", 1, 1,
|
||||
sceHmdReprojectionStartMultilayer);
|
||||
LIB_FUNCTION("gEokC+OGI8g", "libSceHmdDistortion", 1, "libSceHmd", 1, 1,
|
||||
|
@ -199,5 +199,5 @@ s32 PS4_SYSV_ABI Func_B9A6FA0735EC7E49();
|
||||
s32 PS4_SYSV_ABI Func_FC193BD653F2AF2E();
|
||||
s32 PS4_SYSV_ABI Func_FF2E0E53015FE231();
|
||||
|
||||
void RegisterlibSceHmd(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::Hmd
|
@ -190,7 +190,7 @@ Status PS4_SYSV_ABI sceErrorDialogUpdateStatus() {
|
||||
return g_status;
|
||||
}
|
||||
|
||||
void RegisterlibSceErrorDialog(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("ekXHb1kDBl0", "libSceErrorDialog", 1, "libSceErrorDialog", 1, 1,
|
||||
sceErrorDialogClose);
|
||||
LIB_FUNCTION("t2FvHRXzgqk", "libSceErrorDialog", 1, "libSceErrorDialog", 1, 1,
|
||||
|
@ -24,5 +24,5 @@ int PS4_SYSV_ABI sceErrorDialogOpenWithReport();
|
||||
CommonDialog::Error PS4_SYSV_ABI sceErrorDialogTerminate();
|
||||
CommonDialog::Status PS4_SYSV_ABI sceErrorDialogUpdateStatus();
|
||||
|
||||
void RegisterlibSceErrorDialog(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::ErrorDialog
|
@ -18,9 +18,11 @@ static ImeUi g_ime_ui;
|
||||
class ImeHandler {
|
||||
public:
|
||||
ImeHandler(const OrbisImeKeyboardParam* param) {
|
||||
LOG_INFO(Lib_Ime, "Creating ImeHandler for keyboard");
|
||||
Init(param, false);
|
||||
}
|
||||
ImeHandler(const OrbisImeParam* param) {
|
||||
LOG_INFO(Lib_Ime, "Creating ImeHandler for IME");
|
||||
Init(param, true);
|
||||
}
|
||||
~ImeHandler() = default;
|
||||
@ -38,13 +40,18 @@ public:
|
||||
openEvent.id = (ime_mode ? OrbisImeEventId::Open : OrbisImeEventId::KeyboardOpen);
|
||||
|
||||
if (ime_mode) {
|
||||
sceImeGetPanelSize(&m_param.ime, &openEvent.param.rect.width,
|
||||
&openEvent.param.rect.height);
|
||||
LOG_INFO(Lib_Ime, "calling sceImeGetPanelSize");
|
||||
Error e = sceImeGetPanelSize(&m_param.ime, &openEvent.param.rect.width,
|
||||
&openEvent.param.rect.height);
|
||||
if (e != Error::OK) {
|
||||
LOG_ERROR(Lib_Ime, "sceImeGetPanelSize returned 0x{:X}", static_cast<u32>(e));
|
||||
}
|
||||
|
||||
openEvent.param.rect.x = m_param.ime.posx;
|
||||
openEvent.param.rect.y = m_param.ime.posy;
|
||||
} else {
|
||||
openEvent.param.resource_id_array.userId = 1;
|
||||
openEvent.param.resource_id_array.resourceId[0] = 1;
|
||||
openEvent.param.resource_id_array.user_id = 1;
|
||||
openEvent.param.resource_id_array.resource_id[0] = 1;
|
||||
}
|
||||
|
||||
// Are we supposed to call the event handler on init with
|
||||
@ -59,13 +66,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
s32 Update(OrbisImeEventHandler handler) {
|
||||
Error Update(OrbisImeEventHandler handler) {
|
||||
if (!m_ime_mode) {
|
||||
/* We don't handle any events for ImeKeyboard */
|
||||
return ORBIS_OK;
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
std::unique_lock lock{g_ime_state.queue_mutex};
|
||||
std::unique_lock<std::mutex> lock{g_ime_state.queue_mutex};
|
||||
|
||||
while (!g_ime_state.event_queue.empty()) {
|
||||
OrbisImeEvent event = g_ime_state.event_queue.front();
|
||||
@ -73,7 +80,7 @@ public:
|
||||
Execute(handler, &event, false);
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
void Execute(OrbisImeEventHandler handler, OrbisImeEvent* event, bool use_param_handler) {
|
||||
@ -94,14 +101,14 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
s32 SetText(const char16_t* text, u32 length) {
|
||||
Error SetText(const char16_t* text, u32 length) {
|
||||
g_ime_state.SetText(text, length);
|
||||
return ORBIS_OK;
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
s32 SetCaret(const OrbisImeCaret* caret) {
|
||||
Error SetCaret(const OrbisImeCaret* caret) {
|
||||
g_ime_state.SetCaret(caret->index);
|
||||
return ORBIS_OK;
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
bool IsIme() {
|
||||
@ -144,17 +151,22 @@ int PS4_SYSV_ABI sceImeCheckUpdateTextInfo() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceImeClose() {
|
||||
LOG_INFO(Lib_Ime, "(STUBBED) called");
|
||||
Error PS4_SYSV_ABI sceImeClose() {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
|
||||
if (!g_ime_handler) {
|
||||
return ORBIS_IME_ERROR_NOT_OPENED;
|
||||
return Error::NOT_OPENED;
|
||||
}
|
||||
|
||||
g_ime_handler.release();
|
||||
if (g_keyboard_handler) {
|
||||
return Error::INTERNAL;
|
||||
}
|
||||
g_ime_ui = ImeUi();
|
||||
g_ime_state = ImeState();
|
||||
return ORBIS_OK;
|
||||
|
||||
LOG_INFO(Lib_Ime, "IME closed successfully");
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeConfigGet() {
|
||||
@ -222,40 +234,87 @@ int PS4_SYSV_ABI sceImeGetPanelPositionAndForm() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
Error PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height) {
|
||||
LOG_INFO(Lib_Ime, "sceImeGetPanelSize called");
|
||||
|
||||
if (!width || !height) {
|
||||
return ORBIS_IME_ERROR_INVALID_ADDRESS;
|
||||
if (!param) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid param: NULL");
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (!width) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid *width: NULL");
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
if (!height) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid *height: NULL");
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (static_cast<u32>(param->option) & ~0x7BFF) { // Basic check for invalid options
|
||||
LOG_ERROR(Lib_Ime, "Invalid option 0x{:X}", static_cast<u32>(param->option));
|
||||
return Error::INVALID_OPTION;
|
||||
}
|
||||
|
||||
switch (param->type) {
|
||||
case OrbisImeType::Default:
|
||||
*width = 500; // dummy value
|
||||
*height = 100; // dummy value
|
||||
LOG_DEBUG(Lib_Ime, "param->type: Default ({})", static_cast<u32>(param->type));
|
||||
break;
|
||||
case OrbisImeType::BasicLatin:
|
||||
*width = 500; // dummy value
|
||||
*height = 100; // dummy value
|
||||
LOG_DEBUG(Lib_Ime, "param->type: BasicLatin ({})", static_cast<u32>(param->type));
|
||||
break;
|
||||
case OrbisImeType::Url:
|
||||
*width = 500; // dummy value
|
||||
*height = 100; // dummy value
|
||||
LOG_DEBUG(Lib_Ime, "param->type: Url ({})", static_cast<u32>(param->type));
|
||||
break;
|
||||
case OrbisImeType::Mail:
|
||||
// We set our custom sizes, commented sizes are the original ones
|
||||
*width = 500; // 793
|
||||
*height = 100; // 408
|
||||
LOG_DEBUG(Lib_Ime, "param->type: Mail ({})", static_cast<u32>(param->type));
|
||||
break;
|
||||
case OrbisImeType::Number:
|
||||
*width = 370;
|
||||
*height = 402;
|
||||
LOG_DEBUG(Lib_Ime, "param->type: Number ({})", static_cast<u32>(param->type));
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Lib_Ime, "Invalid param->type: ({})", static_cast<u32>(param->type));
|
||||
return Error::INVALID_TYPE;
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
LOG_INFO(Lib_Ime, "IME panel size: width={}, height={}", *width, *height);
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceImeKeyboardClose(s32 userId) {
|
||||
LOG_INFO(Lib_Ime, "(STUBBED) called");
|
||||
Error PS4_SYSV_ABI sceImeKeyboardClose(Libraries::UserService::OrbisUserServiceUserId userId) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
|
||||
if (!g_keyboard_handler) {
|
||||
return ORBIS_IME_ERROR_NOT_OPENED;
|
||||
LOG_ERROR(Lib_Ime, "No keyboard handler is open");
|
||||
return Error::NOT_OPENED;
|
||||
}
|
||||
|
||||
if ((userId < 0 || userId > 4) &&
|
||||
false) { // TODO: Check for valid user IDs. Disabled until user manager is ready.
|
||||
// Maybe g_keyboard_handler should hold a user ID and I must compare it here?
|
||||
LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId);
|
||||
return Error::INVALID_USER_ID;
|
||||
}
|
||||
|
||||
g_keyboard_handler.release();
|
||||
return ORBIS_OK;
|
||||
if (g_ime_handler) {
|
||||
LOG_ERROR(Lib_Ime, "failed to close keyboard handler, IME handler is still open");
|
||||
return Error::INTERNAL;
|
||||
}
|
||||
|
||||
LOG_INFO(Lib_Ime, "Keyboard handler closed successfully for user ID: {}", userId);
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeKeyboardGetInfo() {
|
||||
@ -268,25 +327,62 @@ int PS4_SYSV_ABI sceImeKeyboardGetResourceId() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param) {
|
||||
Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUserId userId,
|
||||
const OrbisImeKeyboardParam* param) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
|
||||
if (!param) {
|
||||
return ORBIS_IME_ERROR_INVALID_ADDRESS;
|
||||
}
|
||||
if (!param->arg) {
|
||||
return ORBIS_IME_ERROR_INVALID_ARG;
|
||||
LOG_ERROR(Lib_Ime, "Invalid param: NULL");
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
if (!param->handler) {
|
||||
return ORBIS_IME_ERROR_INVALID_HANDLER;
|
||||
LOG_ERROR(Lib_Ime, "Invalid param->handler: NULL");
|
||||
return Error::INVALID_HANDLER;
|
||||
}
|
||||
// seems like arg is optional, need to check if it is used in the handler
|
||||
if (!param->arg && false) { // Todo: check if arg is used in the handler, temporarily disabled
|
||||
LOG_ERROR(Lib_Ime, "Invalid param->arg: NULL");
|
||||
return Error::INVALID_ARG;
|
||||
}
|
||||
if (static_cast<u32>(param->option) & ~kValidOrbisImeKeyboardOptionMask) {
|
||||
LOG_ERROR(Lib_Ime,
|
||||
"Invalid param->option\n"
|
||||
"option: {:032b}\n"
|
||||
"validMask: {:032b}",
|
||||
static_cast<u32>(param->option), kValidOrbisImeKeyboardOptionMask);
|
||||
return Error::INVALID_OPTION;
|
||||
}
|
||||
if ((userId < 0 || userId > 4) &&
|
||||
false) { // TODO: Check for valid user IDs. Disabled until user manager is ready.
|
||||
LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId);
|
||||
return Error::INVALID_USER_ID;
|
||||
}
|
||||
for (size_t i = 0; i < sizeof(param->reserved1); ++i) {
|
||||
if (param->reserved1[i] != 0) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid reserved1: not zeroed");
|
||||
return Error::INVALID_RESERVED;
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < sizeof(param->reserved2); ++i) {
|
||||
if (param->reserved2[i] != 0) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid reserved2: not zeroed");
|
||||
return Error::INVALID_RESERVED;
|
||||
}
|
||||
}
|
||||
if (false) { // Todo: figure out what it is, always true for now
|
||||
LOG_ERROR(Lib_Ime, "USB keyboard some special kind of failure");
|
||||
return Error::CONNECTION_FAILED;
|
||||
}
|
||||
|
||||
if (g_keyboard_handler) {
|
||||
return ORBIS_IME_ERROR_BUSY;
|
||||
LOG_ERROR(Lib_Ime, "Keyboard handler is already open");
|
||||
return Error::BUSY;
|
||||
}
|
||||
|
||||
g_keyboard_handler = std::make_unique<ImeHandler>(param);
|
||||
return ORBIS_OK;
|
||||
if (!g_keyboard_handler) {
|
||||
LOG_ERROR(Lib_Ime, "Failed to create keyboard handler");
|
||||
return Error::INTERNAL; // or Error::NO_MEMORY;
|
||||
}
|
||||
LOG_INFO(Lib_Ime, "Keyboard handler created successfully for user ID: {}", userId);
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeKeyboardOpenInternal() {
|
||||
@ -304,18 +400,190 @@ int PS4_SYSV_ABI sceImeKeyboardUpdate() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const void* extended) {
|
||||
Error PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const OrbisImeParamExtended* extended) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
|
||||
if (!param) {
|
||||
return ORBIS_IME_ERROR_INVALID_ADDRESS;
|
||||
LOG_ERROR(Lib_Ime, "Invalid param: NULL");
|
||||
return Error::INVALID_ADDRESS;
|
||||
} else {
|
||||
// LOG_DEBUG values for debugging purposes
|
||||
LOG_DEBUG(Lib_Ime, "param->user_id: {}", param->user_id);
|
||||
LOG_DEBUG(Lib_Ime, "param->type: {}", static_cast<u32>(param->type));
|
||||
LOG_DEBUG(Lib_Ime, "param->supported_languages: {:064b}",
|
||||
static_cast<u64>(param->supported_languages));
|
||||
LOG_DEBUG(Lib_Ime, "param->enter_label: {}", static_cast<u32>(param->enter_label));
|
||||
LOG_DEBUG(Lib_Ime, "param->input_method: {}", static_cast<u32>(param->input_method));
|
||||
LOG_DEBUG(Lib_Ime, "param->filter: {:p}", reinterpret_cast<void*>(param->filter));
|
||||
LOG_DEBUG(Lib_Ime, "param->option: {:032b}", static_cast<u32>(param->option));
|
||||
LOG_DEBUG(Lib_Ime, "param->maxTextLength: {}", param->maxTextLength);
|
||||
LOG_DEBUG(Lib_Ime, "param->inputTextBuffer: {:p}",
|
||||
static_cast<const void*>(param->inputTextBuffer));
|
||||
LOG_DEBUG(Lib_Ime, "param->posx: {}", param->posx);
|
||||
LOG_DEBUG(Lib_Ime, "param->posy: {}", param->posy);
|
||||
LOG_DEBUG(Lib_Ime, "param->horizontal_alignment: {}",
|
||||
static_cast<u32>(param->horizontal_alignment));
|
||||
LOG_DEBUG(Lib_Ime, "param->vertical_alignment: {}",
|
||||
static_cast<u32>(param->vertical_alignment));
|
||||
LOG_DEBUG(Lib_Ime, "param->work: {:p}", param->work);
|
||||
LOG_DEBUG(Lib_Ime, "param->arg: {:p}", param->arg);
|
||||
LOG_DEBUG(Lib_Ime, "param->handler: {:p}", reinterpret_cast<void*>(param->handler));
|
||||
}
|
||||
|
||||
if (!extended) {
|
||||
LOG_INFO(Lib_Ime, "Not used extended: NULL");
|
||||
} else {
|
||||
LOG_DEBUG(Lib_Ime, "extended->option: {:032b}", static_cast<u32>(extended->option));
|
||||
LOG_DEBUG(Lib_Ime, "extended->color_base: {{{},{},{},{}}}", extended->color_base.r,
|
||||
extended->color_base.g, extended->color_base.b, extended->color_base.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended->color_line: {{{},{},{},{}}}", extended->color_line.r,
|
||||
extended->color_line.g, extended->color_line.b, extended->color_line.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended->color_text_field: {{{},{},{},{}}}",
|
||||
extended->color_text_field.r, extended->color_text_field.g,
|
||||
extended->color_text_field.b, extended->color_text_field.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended->color_preedit: {{{},{},{},{}}}", extended->color_preedit.r,
|
||||
extended->color_preedit.g, extended->color_preedit.b, extended->color_preedit.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended->color_button_default: {{{},{},{},{}}}",
|
||||
extended->color_button_default.r, extended->color_button_default.g,
|
||||
extended->color_button_default.b, extended->color_button_default.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended->color_button_function: {{{},{},{},{}}}",
|
||||
extended->color_button_function.r, extended->color_button_function.g,
|
||||
extended->color_button_function.b, extended->color_button_function.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended->color_button_symbol: {{{},{},{},{}}}",
|
||||
extended->color_button_symbol.r, extended->color_button_symbol.g,
|
||||
extended->color_button_symbol.b, extended->color_button_symbol.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended->color_text: {{{},{},{},{}}}", extended->color_text.r,
|
||||
extended->color_text.g, extended->color_text.b, extended->color_text.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended->color_special: {{{},{},{},{}}}", extended->color_special.r,
|
||||
extended->color_special.g, extended->color_special.b, extended->color_special.a);
|
||||
LOG_DEBUG(Lib_Ime, "extended->priority: {}", static_cast<u32>(extended->priority));
|
||||
LOG_DEBUG(Lib_Ime, "extended->additional_dictionary_path: {:p}",
|
||||
static_cast<const void*>(extended->additional_dictionary_path));
|
||||
LOG_DEBUG(Lib_Ime, "extended->ext_keyboard_filter: {:p}",
|
||||
reinterpret_cast<void*>(extended->ext_keyboard_filter));
|
||||
LOG_DEBUG(Lib_Ime, "extended->disable_device: {:032b}",
|
||||
static_cast<u32>(extended->disable_device));
|
||||
LOG_DEBUG(Lib_Ime, "extended->ext_keyboard_mode: {}", extended->ext_keyboard_mode);
|
||||
}
|
||||
|
||||
if (param->user_id < 1 || param->user_id > 4) { // Todo: check valid user IDs
|
||||
LOG_ERROR(Lib_Ime, "Invalid user_id: {}", static_cast<u32>(param->user_id));
|
||||
return Error::INVALID_USER_ID;
|
||||
}
|
||||
|
||||
if (!magic_enum::enum_contains(param->type)) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid type: {}", static_cast<u32>(param->type));
|
||||
return Error::INVALID_TYPE;
|
||||
}
|
||||
|
||||
if (static_cast<u64>(param->supported_languages) & ~kValidOrbisImeLanguageMask) {
|
||||
LOG_ERROR(Lib_Ime,
|
||||
"Invalid supported_languages\n"
|
||||
"supported_languages: {:064b}\n"
|
||||
"valid_mask: {:064b}",
|
||||
static_cast<u64>(param->supported_languages), kValidOrbisImeLanguageMask);
|
||||
return Error::INVALID_SUPPORTED_LANGUAGES;
|
||||
}
|
||||
|
||||
if (!magic_enum::enum_contains(param->enter_label)) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid enter_label: {}", static_cast<u32>(param->enter_label));
|
||||
return Error::INVALID_ENTER_LABEL;
|
||||
}
|
||||
|
||||
if (!magic_enum::enum_contains(param->input_method)) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid input_method: {}", static_cast<u32>(param->input_method));
|
||||
return Error::INVALID_INPUT_METHOD;
|
||||
}
|
||||
|
||||
if (static_cast<u32>(param->option) & ~kValidImeOptionMask) {
|
||||
LOG_ERROR(Lib_Ime, "option has invalid bits set (0x{:X}), mask=(0x{:X})",
|
||||
static_cast<u32>(param->option), kValidImeOptionMask);
|
||||
return Error::INVALID_OPTION;
|
||||
}
|
||||
|
||||
if (param->maxTextLength == 0 || param->maxTextLength > ORBIS_IME_DIALOG_MAX_TEXT_LENGTH) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid maxTextLength: {}", param->maxTextLength);
|
||||
return Error::INVALID_MAX_TEXT_LENGTH;
|
||||
}
|
||||
|
||||
if (!param->inputTextBuffer) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid inputTextBuffer: NULL");
|
||||
return Error::INVALID_INPUT_TEXT_BUFFER;
|
||||
}
|
||||
|
||||
bool useHighRes = True(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES);
|
||||
const float maxWidth = useHighRes ? 3840.0f : 1920.0f;
|
||||
const float maxHeight = useHighRes ? 2160.0f : 1080.0f;
|
||||
|
||||
if (param->posx < 0.0f || param->posx >= maxWidth) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid posx: {}, range: 0.0 - {}", param->posx, maxWidth);
|
||||
return Error::INVALID_POSX;
|
||||
}
|
||||
if (param->posy < 0.0f || param->posy >= maxHeight) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid posy: {}, range: 0.0 - {}", param->posy, maxHeight);
|
||||
return Error::INVALID_POSY;
|
||||
}
|
||||
|
||||
if (!magic_enum::enum_contains(param->horizontal_alignment)) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid horizontal_alignment: {}",
|
||||
static_cast<u32>(param->horizontal_alignment));
|
||||
return Error::INVALID_HORIZONTALIGNMENT;
|
||||
}
|
||||
if (!magic_enum::enum_contains(param->vertical_alignment)) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid vertical_alignment: {}",
|
||||
static_cast<u32>(param->vertical_alignment));
|
||||
return Error::INVALID_VERTICALALIGNMENT;
|
||||
}
|
||||
|
||||
if (extended) {
|
||||
u32 ext_option_value = static_cast<u32>(extended->option);
|
||||
if (ext_option_value & ~kValidImeExtOptionMask) {
|
||||
LOG_ERROR(Lib_Ime,
|
||||
"Invalid extended->option\n"
|
||||
"option: {:032b}\n"
|
||||
"valid_mask: {:032b}",
|
||||
ext_option_value, kValidImeExtOptionMask);
|
||||
return Error::INVALID_EXTENDED;
|
||||
}
|
||||
}
|
||||
|
||||
if (!param->work) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid work: NULL");
|
||||
return Error::INVALID_WORK;
|
||||
}
|
||||
|
||||
// Todo: validate arg
|
||||
if (false) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid arg: NULL");
|
||||
return Error::INVALID_ARG;
|
||||
}
|
||||
|
||||
// Todo: validate handler
|
||||
if (false) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid handler: NULL");
|
||||
return Error::INVALID_HANDLER;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(param->reserved); ++i) {
|
||||
if (param->reserved[i] != 0) {
|
||||
LOG_ERROR(Lib_Ime, "Invalid reserved: not zeroed");
|
||||
return Error::INVALID_RESERVED;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_ime_handler) {
|
||||
return ORBIS_IME_ERROR_BUSY;
|
||||
LOG_ERROR(Lib_Ime, "IME handler is already open");
|
||||
return Error::BUSY;
|
||||
}
|
||||
|
||||
g_ime_handler = std::make_unique<ImeHandler>(param);
|
||||
return ORBIS_OK;
|
||||
if (!g_ime_handler) {
|
||||
LOG_ERROR(Lib_Ime, "Failed to create IME handler");
|
||||
return Error::NO_MEMORY; // or Error::INTERNAL
|
||||
}
|
||||
|
||||
LOG_INFO(Lib_Ime, "IME handler created successfully");
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeOpenInternal() {
|
||||
@ -324,7 +592,7 @@ int PS4_SYSV_ABI sceImeOpenInternal() {
|
||||
}
|
||||
|
||||
void PS4_SYSV_ABI sceImeParamInit(OrbisImeParam* param) {
|
||||
LOG_INFO(Lib_Ime, "called");
|
||||
LOG_INFO(Lib_Ime, "sceImeParamInit called");
|
||||
|
||||
if (!param) {
|
||||
return;
|
||||
@ -339,27 +607,27 @@ int PS4_SYSV_ABI sceImeSetCandidateIndex() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret) {
|
||||
Error PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret) {
|
||||
LOG_TRACE(Lib_Ime, "called");
|
||||
|
||||
if (!g_ime_handler) {
|
||||
return ORBIS_IME_ERROR_NOT_OPENED;
|
||||
return Error::NOT_OPENED;
|
||||
}
|
||||
if (!caret) {
|
||||
return ORBIS_IME_ERROR_INVALID_ADDRESS;
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
return g_ime_handler->SetCaret(caret);
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length) {
|
||||
Error PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length) {
|
||||
LOG_TRACE(Lib_Ime, "called");
|
||||
|
||||
if (!g_ime_handler) {
|
||||
return ORBIS_IME_ERROR_NOT_OPENED;
|
||||
return Error::NOT_OPENED;
|
||||
}
|
||||
if (!text) {
|
||||
return ORBIS_IME_ERROR_INVALID_ADDRESS;
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
return g_ime_handler->SetText(text, length);
|
||||
@ -370,7 +638,7 @@ int PS4_SYSV_ABI sceImeSetTextGeometry() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) {
|
||||
Error PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) {
|
||||
if (g_ime_handler) {
|
||||
g_ime_handler->Update(handler);
|
||||
}
|
||||
@ -380,10 +648,10 @@ s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler) {
|
||||
}
|
||||
|
||||
if (!g_ime_handler || !g_keyboard_handler) {
|
||||
return ORBIS_IME_ERROR_NOT_OPENED;
|
||||
return Error::NOT_OPENED;
|
||||
}
|
||||
|
||||
return ORBIS_OK;
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceImeVshClearPreedit() {
|
||||
@ -481,7 +749,7 @@ int PS4_SYSV_ABI sceImeVshUpdateContext2() {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceIme(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("mN+ZoSN-8hQ", "libSceIme", 1, "libSceIme", 1, 1, FinalizeImeModule);
|
||||
LIB_FUNCTION("uTW+63goeJs", "libSceIme", 1, "libSceIme", 1, 1, InitializeImeModule);
|
||||
LIB_FUNCTION("Lf3DeGWC6xg", "libSceIme", 1, "libSceIme", 1, 1, sceImeCheckFilterText);
|
||||
|
@ -13,78 +13,12 @@ class SymbolsResolver;
|
||||
|
||||
namespace Libraries::Ime {
|
||||
|
||||
constexpr u32 ORBIS_IME_MAX_TEXT_LENGTH = 2048;
|
||||
|
||||
enum class OrbisImeKeyboardOption : u32 {
|
||||
Default = 0,
|
||||
Repeat = 1,
|
||||
RepeatEachKey = 2,
|
||||
AddOsk = 4,
|
||||
EffectiveWithIme = 8,
|
||||
DisableResume = 16,
|
||||
DisableCapslockWithoutShift = 32,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeyboardOption)
|
||||
|
||||
enum class OrbisImeOption : u32 {
|
||||
DEFAULT = 0,
|
||||
MULTILINE = 1,
|
||||
NO_AUTO_CAPITALIZATION = 2,
|
||||
PASSWORD = 4,
|
||||
LANGUAGES_FORCED = 8,
|
||||
EXT_KEYBOARD = 16,
|
||||
NO_LEARNING = 32,
|
||||
FIXED_POSITION = 64,
|
||||
DISABLE_RESUME = 256,
|
||||
DISABLE_AUTO_SPACE = 512,
|
||||
DISABLE_POSITION_ADJUSTMENT = 2048,
|
||||
EXPANDED_PREEDIT_BUFFER = 4096,
|
||||
USE_JAPANESE_EISUU_KEY_AS_CAPSLOCK = 8192,
|
||||
USE_2K_COORDINATES = 16384,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeOption)
|
||||
|
||||
struct OrbisImeKeyboardParam {
|
||||
OrbisImeKeyboardOption option;
|
||||
s8 reserved1[4];
|
||||
void* arg;
|
||||
OrbisImeEventHandler handler;
|
||||
s8 reserved2[8];
|
||||
};
|
||||
|
||||
struct OrbisImeParam {
|
||||
s32 user_id;
|
||||
OrbisImeType type;
|
||||
u64 supported_languages;
|
||||
OrbisImeEnterLabel enter_label;
|
||||
OrbisImeInputMethod input_method;
|
||||
OrbisImeTextFilter filter;
|
||||
OrbisImeOption option;
|
||||
u32 maxTextLength;
|
||||
char16_t* inputTextBuffer;
|
||||
float posx;
|
||||
float posy;
|
||||
OrbisImeHorizontalAlignment horizontal_alignment;
|
||||
OrbisImeVerticalAlignment vertical_alignment;
|
||||
void* work;
|
||||
void* arg;
|
||||
OrbisImeEventHandler handler;
|
||||
s8 reserved[8];
|
||||
};
|
||||
|
||||
struct OrbisImeCaret {
|
||||
f32 x;
|
||||
f32 y;
|
||||
u32 height;
|
||||
u32 index;
|
||||
};
|
||||
|
||||
int PS4_SYSV_ABI FinalizeImeModule();
|
||||
int PS4_SYSV_ABI InitializeImeModule();
|
||||
int PS4_SYSV_ABI sceImeCheckFilterText();
|
||||
int PS4_SYSV_ABI sceImeCheckRemoteEventParam();
|
||||
int PS4_SYSV_ABI sceImeCheckUpdateTextInfo();
|
||||
int PS4_SYSV_ABI sceImeClose();
|
||||
Error PS4_SYSV_ABI sceImeClose();
|
||||
int PS4_SYSV_ABI sceImeConfigGet();
|
||||
int PS4_SYSV_ABI sceImeConfigSet();
|
||||
int PS4_SYSV_ABI sceImeConfirmCandidate();
|
||||
@ -98,22 +32,23 @@ int PS4_SYSV_ABI sceImeDisableController();
|
||||
int PS4_SYSV_ABI sceImeFilterText();
|
||||
int PS4_SYSV_ABI sceImeForTestFunction();
|
||||
int PS4_SYSV_ABI sceImeGetPanelPositionAndForm();
|
||||
s32 PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height);
|
||||
s32 PS4_SYSV_ABI sceImeKeyboardClose(s32 userId);
|
||||
Error PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u32* height);
|
||||
Error PS4_SYSV_ABI sceImeKeyboardClose(Libraries::UserService::OrbisUserServiceUserId userId);
|
||||
int PS4_SYSV_ABI sceImeKeyboardGetInfo();
|
||||
int PS4_SYSV_ABI sceImeKeyboardGetResourceId();
|
||||
s32 PS4_SYSV_ABI sceImeKeyboardOpen(s32 userId, const OrbisImeKeyboardParam* param);
|
||||
Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUserId userId,
|
||||
const OrbisImeKeyboardParam* param);
|
||||
int PS4_SYSV_ABI sceImeKeyboardOpenInternal();
|
||||
int PS4_SYSV_ABI sceImeKeyboardSetMode();
|
||||
int PS4_SYSV_ABI sceImeKeyboardUpdate();
|
||||
s32 PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const void* extended);
|
||||
Error PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const OrbisImeParamExtended* extended);
|
||||
int PS4_SYSV_ABI sceImeOpenInternal();
|
||||
void PS4_SYSV_ABI sceImeParamInit(OrbisImeParam* param);
|
||||
int PS4_SYSV_ABI sceImeSetCandidateIndex();
|
||||
s32 PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret);
|
||||
s32 PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length);
|
||||
Error PS4_SYSV_ABI sceImeSetCaret(const OrbisImeCaret* caret);
|
||||
Error PS4_SYSV_ABI sceImeSetText(const char16_t* text, u32 length);
|
||||
int PS4_SYSV_ABI sceImeSetTextGeometry();
|
||||
s32 PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler);
|
||||
Error PS4_SYSV_ABI sceImeUpdate(OrbisImeEventHandler handler);
|
||||
int PS4_SYSV_ABI sceImeVshClearPreedit();
|
||||
int PS4_SYSV_ABI sceImeVshClose();
|
||||
int PS4_SYSV_ABI sceImeVshConfirmPreedit();
|
||||
@ -134,6 +69,6 @@ int PS4_SYSV_ABI sceImeVshUpdate();
|
||||
int PS4_SYSV_ABI sceImeVshUpdateContext();
|
||||
int PS4_SYSV_ABI sceImeVshUpdateContext2();
|
||||
|
||||
void RegisterlibSceIme(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
|
||||
} // namespace Libraries::Ime
|
||||
|
@ -3,9 +3,273 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <core/libraries/system/userservice.h>
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
#include "common/enum.h"
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/rtc/rtc.h"
|
||||
|
||||
constexpr u32 ORBIS_IME_MAX_TEXT_LENGTH = 2048;
|
||||
constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 2048;
|
||||
|
||||
template <typename E>
|
||||
const std::underlying_type_t<E> generate_full_mask() {
|
||||
static_assert(std::is_enum_v<E>, "E must be an enum type.");
|
||||
static_assert(magic_enum::customize::enum_range<E>::is_flags,
|
||||
"E must be marked as is_flags = true.");
|
||||
|
||||
using U = std::underlying_type_t<E>;
|
||||
const auto values = magic_enum::enum_values<E>();
|
||||
U mask = 0;
|
||||
|
||||
// Use index-based loop for better constexpr compatibility
|
||||
for (std::size_t i = 0; i < values.size(); ++i) {
|
||||
mask |= static_cast<U>(values[i]);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
enum class Error : u32 {
|
||||
OK = 0x0,
|
||||
|
||||
// ImeDialog library
|
||||
BUSY = 0x80bc0001,
|
||||
NOT_OPENED = 0x80bc0002,
|
||||
NO_MEMORY = 0x80bc0003,
|
||||
CONNECTION_FAILED = 0x80bc0004,
|
||||
TOO_MANY_REQUESTS = 0x80bc0005,
|
||||
INVALID_TEXT = 0x80bc0006,
|
||||
EVENT_OVERFLOW = 0x80bc0007,
|
||||
NOT_ACTIVE = 0x80bc0008,
|
||||
IME_SUSPENDING = 0x80bc0009,
|
||||
DEVICE_IN_USE = 0x80bc000a,
|
||||
INVALID_USER_ID = 0x80bc0010,
|
||||
INVALID_TYPE = 0x80bc0011,
|
||||
INVALID_SUPPORTED_LANGUAGES = 0x80bc0012,
|
||||
INVALID_ENTER_LABEL = 0x80bc0013,
|
||||
INVALID_INPUT_METHOD = 0x80bc0014,
|
||||
INVALID_OPTION = 0x80bc0015,
|
||||
INVALID_MAX_TEXT_LENGTH = 0x80bc0016,
|
||||
INVALID_INPUT_TEXT_BUFFER = 0x80bc0017,
|
||||
INVALID_POSX = 0x80bc0018,
|
||||
INVALID_POSY = 0x80bc0019,
|
||||
INVALID_HORIZONTALIGNMENT = 0x80bc001a,
|
||||
INVALID_VERTICALALIGNMENT = 0x80bc001b,
|
||||
INVALID_EXTENDED = 0x80bc001c,
|
||||
INVALID_KEYBOARD_TYPE = 0x80bc001d,
|
||||
INVALID_WORK = 0x80bc0020,
|
||||
INVALID_ARG = 0x80bc0021,
|
||||
INVALID_HANDLER = 0x80bc0022,
|
||||
NO_RESOURCE_ID = 0x80bc0023,
|
||||
INVALID_MODE = 0x80bc0024,
|
||||
INVALID_PARAM = 0x80bc0030,
|
||||
INVALID_ADDRESS = 0x80bc0031,
|
||||
INVALID_RESERVED = 0x80bc0032,
|
||||
INVALID_TIMING = 0x80bc0033,
|
||||
INTERNAL = 0x80bc00ff,
|
||||
|
||||
// Ime library
|
||||
DIALOG_INVALID_TITLE = 0x80bc0101,
|
||||
DIALOG_NOT_RUNNING = 0x80bc0105,
|
||||
DIALOG_NOT_FINISHED = 0x80bc0106,
|
||||
DIALOG_NOT_IN_USE = 0x80bc0107
|
||||
};
|
||||
|
||||
enum class OrbisImeOption : u32 {
|
||||
DEFAULT = 0,
|
||||
MULTILINE = 1,
|
||||
NO_AUTO_CAPITALIZATION = 2,
|
||||
PASSWORD = 4,
|
||||
LANGUAGES_FORCED = 8,
|
||||
EXT_KEYBOARD = 16,
|
||||
NO_LEARNING = 32,
|
||||
FIXED_POSITION = 64,
|
||||
DISABLE_COPY_PASTE = 128,
|
||||
DISABLE_RESUME = 256,
|
||||
DISABLE_AUTO_SPACE = 512,
|
||||
DISABLE_POSITION_ADJUSTMENT = 2048,
|
||||
EXPANDED_PREEDIT_BUFFER = 4096,
|
||||
USE_JAPANESE_EISUU_KEY_AS_CAPSLOCK = 8192,
|
||||
USE_OVER_2K_COORDINATES = 16384,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeOption);
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeOption> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
const u32 kValidImeOptionMask = generate_full_mask<OrbisImeOption>();
|
||||
|
||||
enum class OrbisImeExtOption : u32 {
|
||||
DEFAULT = 0x00000000,
|
||||
SET_PRIORITY = 0x00000002,
|
||||
PRIORITY_FULL_WIDTH = 0x00000008,
|
||||
PRIORITY_FIXED_PANEL = 0x00000010,
|
||||
DISABLE_POINTER = 0x00000040,
|
||||
ENABLE_ADDITIONAL_DICTIONARY = 0x00000080,
|
||||
DISABLE_STARTUP_SE = 0x00000100,
|
||||
DISABLE_LIST_FOR_EXT_KEYBOARD = 0x00000200,
|
||||
HIDE_KEYPANEL_IF_EXT_KEYBOARD = 0x00000400,
|
||||
INIT_EXT_KEYBOARD_MODE = 0x00000800,
|
||||
|
||||
ENABLE_ACCESSIBILITY = 0x00001000, // ImeDialog unly
|
||||
ADDITIONAL_DICTIONARY_PRIORITY_MODE = 0x00004000, // ImeDialog only
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeExtOption);
|
||||
|
||||
constexpr u32 kValidImeExtOptionMask = static_cast<u32>(
|
||||
OrbisImeExtOption::SET_PRIORITY | OrbisImeExtOption::PRIORITY_FULL_WIDTH |
|
||||
OrbisImeExtOption::PRIORITY_FIXED_PANEL | OrbisImeExtOption::DISABLE_POINTER |
|
||||
OrbisImeExtOption::ENABLE_ADDITIONAL_DICTIONARY | OrbisImeExtOption::DISABLE_STARTUP_SE |
|
||||
OrbisImeExtOption::DISABLE_LIST_FOR_EXT_KEYBOARD |
|
||||
OrbisImeExtOption::HIDE_KEYPANEL_IF_EXT_KEYBOARD | OrbisImeExtOption::INIT_EXT_KEYBOARD_MODE);
|
||||
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeExtOption> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
const u32 kValidImeDialogExtOptionMask = generate_full_mask<OrbisImeExtOption>();
|
||||
|
||||
enum class OrbisImeLanguage : u64 {
|
||||
DANISH = 0x0000000000000001,
|
||||
GERMAN = 0x0000000000000002,
|
||||
ENGLISH_US = 0x0000000000000004,
|
||||
SPANISH = 0x0000000000000008,
|
||||
FRENCH = 0x0000000000000010,
|
||||
ITALIAN = 0x0000000000000020,
|
||||
DUTCH = 0x0000000000000040,
|
||||
NORWEGIAN = 0x0000000000000080,
|
||||
POLISH = 0x0000000000000100,
|
||||
PORTUGUESE_PT = 0x0000000000000200,
|
||||
RUSSIAN = 0x0000000000000400,
|
||||
FINNISH = 0x0000000000000800,
|
||||
SWEDISH = 0x0000000000001000,
|
||||
JAPANESE = 0x0000000000002000,
|
||||
KOREAN = 0x0000000000004000,
|
||||
SIMPLIFIED_CHINESE = 0x0000000000008000,
|
||||
TRADITIONAL_CHINESE = 0x0000000000010000,
|
||||
PORTUGUESE_BR = 0x0000000000020000,
|
||||
ENGLISH_GB = 0x0000000000040000,
|
||||
TURKISH = 0x0000000000080000,
|
||||
SPANISH_LA = 0x0000000000100000,
|
||||
ARABIC = 0x0000000001000000,
|
||||
FRENCH_CA = 0x0000000002000000,
|
||||
THAI = 0x0000000004000000,
|
||||
CZECH = 0x0000000008000000,
|
||||
GREEK = 0x0000000010000000,
|
||||
INDONESIAN = 0x0000000020000000,
|
||||
VIETNAMESE = 0x0000000040000000,
|
||||
ROMANIAN = 0x0000000080000000,
|
||||
HUNGARIAN = 0x0000000100000000,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeLanguage);
|
||||
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeLanguage> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
const u64 kValidOrbisImeLanguageMask = generate_full_mask<OrbisImeLanguage>();
|
||||
|
||||
enum class OrbisImeDisableDevice : u32 {
|
||||
DEFAULT = 0x00000000,
|
||||
CONTROLLER = 0x00000001,
|
||||
EXT_KEYBOARD = 0x00000002,
|
||||
REMOTE_OSK = 0x00000004,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeDisableDevice);
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeDisableDevice> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
const u32 kValidOrbisImeDisableDeviceMask = generate_full_mask<OrbisImeDisableDevice>();
|
||||
|
||||
enum class OrbisImeInputMethodState : u32 {
|
||||
PREEDIT = 0x01000000,
|
||||
SELECTED = 0x02000000,
|
||||
NATIVE = 0x04000000,
|
||||
NATIVE2 = 0x08000000,
|
||||
FULL_WIDTH = 0x10000000,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeInputMethodState);
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeInputMethodState> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
const u32 kValidOrbisImeInputMethodStateMask = generate_full_mask<OrbisImeInputMethodState>();
|
||||
|
||||
enum class OrbisImeInitExtKeyboardMode : u32 {
|
||||
ISABLE_ARABIC_INDIC_NUMERALS = 0x00000001,
|
||||
ENABLE_FORMAT_CHARACTERS = 0x00000002,
|
||||
INPUT_METHOD_STATE_NATIVE = 0x04000000,
|
||||
INPUT_METHOD_STATE_NATIVE2 = 0x08000000,
|
||||
INPUT_METHOD_STATE_FULL_WIDTH = 0x10000000,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeInitExtKeyboardMode);
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeInitExtKeyboardMode> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
const u32 kValidOrbisImeInitExtKeyboardModeMask = generate_full_mask<OrbisImeInitExtKeyboardMode>();
|
||||
|
||||
enum class OrbisImeKeycodeState : u32 {
|
||||
KEYCODE_VALID = 0x00000001,
|
||||
CHARACTER_VALID = 0x00000002,
|
||||
WITH_IME = 0x00000004,
|
||||
FROM_OSK = 0x00000008,
|
||||
FROM_OSK_SHORTCUT = 0x00000010,
|
||||
FROM_IME_OPERATION = 0x00000020,
|
||||
REPLACE_CHARACTER = 0x00000040,
|
||||
CONTINUOUS_EVENT = 0x00000080,
|
||||
MODIFIER_L_CTRL = 0x00000100,
|
||||
MODIFIER_L_SHIFT = 0x00000200,
|
||||
MODIFIER_L_ALT = 0x00000400,
|
||||
MODIFIER_L_GUI = 0x00000800,
|
||||
MODIFIER_R_CTRL = 0x00001000,
|
||||
MODIFIER_R_SHIFT = 0x00002000,
|
||||
MODIFIER_R_ALT = 0x00004000,
|
||||
MODIFIER_R_GUI = 0x00008000,
|
||||
LED_NUM_LOCK = 0x00010000,
|
||||
LED_CAPS_LOCK = 0x00020000,
|
||||
LED_SCROLL_LOCK = 0x00040000,
|
||||
RESERVED1 = 0x00080000,
|
||||
RESERVED2 = 0x00100000,
|
||||
FROM_IME_INPUT = 0x00200000,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeycodeState);
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeKeycodeState> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
const u32 kValidOrbisImeKeycodeStateMask = generate_full_mask<OrbisImeKeycodeState>();
|
||||
|
||||
enum class OrbisImeKeyboardOption : u32 {
|
||||
Default = 0,
|
||||
Repeat = 1,
|
||||
RepeatEachKey = 2,
|
||||
AddOsk = 4,
|
||||
EffectiveWithIme = 8,
|
||||
DisableResume = 16,
|
||||
DisableCapslockWithoutShift = 32,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeKeyboardOption)
|
||||
template <>
|
||||
struct magic_enum::customize::enum_range<OrbisImeKeyboardOption> {
|
||||
static constexpr bool is_flags = true;
|
||||
};
|
||||
const u32 kValidOrbisImeKeyboardOptionMask = generate_full_mask<OrbisImeKeyboardOption>();
|
||||
|
||||
enum class OrbisImeKeyboardMode : u32 {
|
||||
Auto = 0,
|
||||
Manual = 1,
|
||||
Alphabet = 0,
|
||||
Native = 2,
|
||||
Part = 4,
|
||||
Katakana = 8,
|
||||
Hkana = 16,
|
||||
ArabicIndicNumerals = 32,
|
||||
DisableFormatCharacters = 64,
|
||||
};
|
||||
|
||||
enum class OrbisImeType : u32 {
|
||||
Default = 0,
|
||||
BasicLatin = 1,
|
||||
@ -41,6 +305,7 @@ enum class OrbisImeEventId : u32 {
|
||||
Open = 0,
|
||||
UpdateText = 1,
|
||||
UpdateCaret = 2,
|
||||
ChangeSize = 3,
|
||||
PressClose = 4,
|
||||
PressEnter = 5,
|
||||
Abort = 6,
|
||||
@ -51,10 +316,14 @@ enum class OrbisImeEventId : u32 {
|
||||
CandidateDone = 11,
|
||||
CandidateCancel = 12,
|
||||
ChangeDevice = 14,
|
||||
JumpToNextObject = 15,
|
||||
JumpToBeforeObject = 16,
|
||||
ChangeWindowType = 17,
|
||||
|
||||
ChangeInputMethodState = 18,
|
||||
|
||||
KeyboardOpen = 256,
|
||||
KeyboardKeycodeDoen = 257,
|
||||
KeyboardKeycodeDown = 257,
|
||||
KeyboardKeycodeUp = 258,
|
||||
KeyboardKeycodeRepeat = 259,
|
||||
KeyboardConnection = 260,
|
||||
@ -110,6 +379,13 @@ enum class OrbisImeDeviceType : u32 {
|
||||
RemoteOsk = 3,
|
||||
};
|
||||
|
||||
enum class OrbisImePanelPriority : u32 {
|
||||
Default = 0,
|
||||
Alphabet = 1,
|
||||
Symbol = 2,
|
||||
Accent = 3,
|
||||
};
|
||||
|
||||
struct OrbisImeRect {
|
||||
f32 x;
|
||||
f32 y;
|
||||
@ -117,8 +393,22 @@ struct OrbisImeRect {
|
||||
u32 height;
|
||||
};
|
||||
|
||||
struct OrbisImeColor {
|
||||
u8 r;
|
||||
u8 g;
|
||||
u8 b;
|
||||
u8 a;
|
||||
};
|
||||
|
||||
enum class OrbisImeTextAreaMode : u32 {
|
||||
Disable = 0,
|
||||
Edit = 1,
|
||||
Preedit = 2,
|
||||
Select = 3,
|
||||
};
|
||||
|
||||
struct OrbisImeTextAreaProperty {
|
||||
u32 mode; // OrbisImeTextAreaMode
|
||||
OrbisImeTextAreaMode mode;
|
||||
u32 index;
|
||||
s32 length;
|
||||
};
|
||||
@ -135,14 +425,14 @@ struct OrbisImeKeycode {
|
||||
char16_t character;
|
||||
u32 status;
|
||||
OrbisImeKeyboardType type;
|
||||
s32 user_id;
|
||||
Libraries::UserService::OrbisUserServiceUserId user_id;
|
||||
u32 resource_id;
|
||||
Libraries::Rtc::OrbisRtcTick timestamp;
|
||||
};
|
||||
|
||||
struct OrbisImeKeyboardResourceIdArray {
|
||||
s32 userId;
|
||||
u32 resourceId[5];
|
||||
Libraries::UserService::OrbisUserServiceUserId user_id;
|
||||
u32 resource_id[5];
|
||||
};
|
||||
|
||||
enum class OrbisImeCaretMovementDirection : u32 {
|
||||
@ -159,6 +449,16 @@ enum class OrbisImeCaretMovementDirection : u32 {
|
||||
Bottom = 10,
|
||||
};
|
||||
|
||||
enum class OrbisImePanelType : u32 {
|
||||
Hide = 0,
|
||||
Osk = 1,
|
||||
Dialog = 2,
|
||||
Candidate = 3,
|
||||
Edit = 4,
|
||||
EditAndCandidate = 5,
|
||||
Accessibility = 6,
|
||||
};
|
||||
|
||||
union OrbisImeEventParam {
|
||||
OrbisImeRect rect;
|
||||
OrbisImeEditText text;
|
||||
@ -168,6 +468,7 @@ union OrbisImeEventParam {
|
||||
char16_t* candidate_word;
|
||||
s32 candidate_index;
|
||||
OrbisImeDeviceType device_type;
|
||||
OrbisImePanelType panel_type;
|
||||
u32 input_method_state;
|
||||
s8 reserved[64];
|
||||
};
|
||||
@ -177,7 +478,84 @@ struct OrbisImeEvent {
|
||||
OrbisImeEventParam param;
|
||||
};
|
||||
|
||||
using OrbisImeExtKeyboardFilter = PS4_SYSV_ABI int (*)(const OrbisImeKeycode* srcKeycode,
|
||||
u16* outKeycode, u32* outStatus,
|
||||
void* reserved);
|
||||
|
||||
using OrbisImeTextFilter = PS4_SYSV_ABI int (*)(char16_t* outText, u32* outTextLength,
|
||||
const char16_t* srcText, u32 srcTextLength);
|
||||
|
||||
using OrbisImeEventHandler = PS4_SYSV_ABI void (*)(void* arg, const OrbisImeEvent* e);
|
||||
|
||||
struct OrbisImeKeyboardParam {
|
||||
OrbisImeKeyboardOption option;
|
||||
s8 reserved1[4];
|
||||
void* arg;
|
||||
OrbisImeEventHandler handler;
|
||||
s8 reserved2[8];
|
||||
};
|
||||
|
||||
struct OrbisImeParam {
|
||||
Libraries::UserService::OrbisUserServiceUserId user_id;
|
||||
OrbisImeType type;
|
||||
OrbisImeLanguage supported_languages;
|
||||
OrbisImeEnterLabel enter_label;
|
||||
OrbisImeInputMethod input_method;
|
||||
OrbisImeTextFilter filter;
|
||||
OrbisImeOption option;
|
||||
u32 maxTextLength;
|
||||
char16_t* inputTextBuffer;
|
||||
f32 posx;
|
||||
f32 posy;
|
||||
OrbisImeHorizontalAlignment horizontal_alignment;
|
||||
OrbisImeVerticalAlignment vertical_alignment;
|
||||
void* work;
|
||||
void* arg;
|
||||
OrbisImeEventHandler handler;
|
||||
s8 reserved[8];
|
||||
};
|
||||
|
||||
struct OrbisImeCaret {
|
||||
f32 x;
|
||||
f32 y;
|
||||
u32 height;
|
||||
u32 index;
|
||||
};
|
||||
|
||||
struct OrbisImeDialogParam {
|
||||
Libraries::UserService::OrbisUserServiceUserId user_id;
|
||||
OrbisImeType type;
|
||||
OrbisImeLanguage supported_languages;
|
||||
OrbisImeEnterLabel enter_label;
|
||||
OrbisImeInputMethod input_method;
|
||||
OrbisImeTextFilter filter;
|
||||
OrbisImeOption option;
|
||||
u32 max_text_length;
|
||||
char16_t* input_text_buffer;
|
||||
f32 posx;
|
||||
f32 posy;
|
||||
OrbisImeHorizontalAlignment horizontal_alignment;
|
||||
OrbisImeVerticalAlignment vertical_alignment;
|
||||
const char16_t* placeholder;
|
||||
const char16_t* title;
|
||||
s8 reserved[16];
|
||||
};
|
||||
|
||||
struct OrbisImeParamExtended {
|
||||
OrbisImeExtOption option;
|
||||
OrbisImeColor color_base;
|
||||
OrbisImeColor color_line;
|
||||
OrbisImeColor color_text_field;
|
||||
OrbisImeColor color_preedit;
|
||||
OrbisImeColor color_button_default;
|
||||
OrbisImeColor color_button_function;
|
||||
OrbisImeColor color_button_symbol;
|
||||
OrbisImeColor color_text;
|
||||
OrbisImeColor color_special;
|
||||
OrbisImePanelPriority priority;
|
||||
char* additional_dictionary_path;
|
||||
OrbisImeExtKeyboardFilter ext_keyboard_filter;
|
||||
OrbisImeDisableDevice disable_device;
|
||||
u32 ext_keyboard_mode;
|
||||
s8 reserved[60];
|
||||
};
|
||||
|
@ -20,19 +20,19 @@ static OrbisImeDialogResult g_ime_dlg_result{};
|
||||
static ImeDialogState g_ime_dlg_state{};
|
||||
static ImeDialogUi g_ime_dlg_ui;
|
||||
|
||||
static bool IsValidOption(OrbisImeDialogOption option, OrbisImeType type) {
|
||||
if (False(~option &
|
||||
(OrbisImeDialogOption::Multiline | OrbisImeDialogOption::NoAutoCompletion))) {
|
||||
static bool IsValidOption(OrbisImeOption option, OrbisImeType type) {
|
||||
if (False(~option & (OrbisImeOption::MULTILINE |
|
||||
OrbisImeOption::NO_AUTO_CAPITALIZATION /* NoAutoCompletion */))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (True(option & OrbisImeDialogOption::Multiline) && type != OrbisImeType::Default &&
|
||||
if (True(option & OrbisImeOption::MULTILINE) && type != OrbisImeType::Default &&
|
||||
type != OrbisImeType::BasicLatin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (True(option & OrbisImeDialogOption::NoAutoCompletion) && type != OrbisImeType::Number &&
|
||||
type != OrbisImeType::BasicLatin) {
|
||||
if (True(option & OrbisImeOption::NO_AUTO_CAPITALIZATION /* NoAutoCompletion */) &&
|
||||
type != OrbisImeType::Number && type != OrbisImeType::BasicLatin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -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 & OrbisImeOption::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() {
|
||||
@ -123,18 +149,47 @@ OrbisImeDialogStatus PS4_SYSV_ABI sceImeDialogGetStatus() {
|
||||
}
|
||||
|
||||
Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExtended* extended) {
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: entering, param={}, extended={}",
|
||||
static_cast<void*>(param), static_cast<void*>(extended));
|
||||
|
||||
if (param == nullptr) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: param is null");
|
||||
return Error::INVALID_ADDRESS;
|
||||
} else {
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.user_id = {}",
|
||||
static_cast<u32>(param->user_id));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.type = {}", static_cast<u32>(param->type));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.supported_languages = 0x{:X}",
|
||||
static_cast<u64>(param->supported_languages));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.enter_label = {}",
|
||||
static_cast<u32>(param->enter_label));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.input_method = {}",
|
||||
static_cast<u32>(param->input_method));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.filter = {}", (void*)param->filter);
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.option = 0x{:X}",
|
||||
static_cast<u32>(param->option));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.max_text_length = {}",
|
||||
param->max_text_length);
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.input_text_buffer = {}",
|
||||
(void*)param->input_text_buffer);
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.posx = {}", param->posx);
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.posy = {}", param->posy);
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.horizontal_alignment = {}",
|
||||
static_cast<u32>(param->horizontal_alignment));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.vertical_alignment = {}",
|
||||
static_cast<u32>(param->vertical_alignment));
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.placeholder = {}",
|
||||
param->placeholder ? "<non-null>" : "NULL");
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: param.title = {}",
|
||||
param->title ? "<non-null>" : "NULL");
|
||||
}
|
||||
if (g_ime_dlg_status != OrbisImeDialogStatus::None) {
|
||||
LOG_INFO(Lib_ImeDialog, "IME dialog is already running");
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: busy (status={})", (u32)g_ime_dlg_status);
|
||||
return Error::BUSY;
|
||||
}
|
||||
|
||||
if (param == nullptr) {
|
||||
LOG_INFO(Lib_ImeDialog, "called with param (NULL)");
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (!magic_enum::enum_contains(param->type)) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid param->type");
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid param->type={}", (u32)param->type);
|
||||
return Error::INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
@ -143,15 +198,15 @@ Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExt
|
||||
|
||||
if (param->posx < 0.0f ||
|
||||
param->posx >=
|
||||
MAX_X_POSITIONS[False(param->option & OrbisImeDialogOption::LargeResolution)]) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid param->posx");
|
||||
MAX_X_POSITIONS[False(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES)]) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid posx={}", param->posx);
|
||||
return Error::INVALID_POSX;
|
||||
}
|
||||
|
||||
if (param->posy < 0.0f ||
|
||||
param->posy >=
|
||||
MAX_Y_POSITIONS[False(param->option & OrbisImeDialogOption::LargeResolution)]) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid param->posy");
|
||||
MAX_Y_POSITIONS[False(param->option & OrbisImeOption::USE_OVER_2K_COORDINATES)]) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid posy={}", param->posy);
|
||||
return Error::INVALID_POSY;
|
||||
}
|
||||
|
||||
@ -166,44 +221,55 @@ Error PS4_SYSV_ABI sceImeDialogInit(OrbisImeDialogParam* param, OrbisImeParamExt
|
||||
}
|
||||
|
||||
if (!IsValidOption(param->option, param->type)) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid param->option");
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid option=0x{:X}for type={}",
|
||||
static_cast<u32>(param->option), (u32)param->type);
|
||||
return Error::INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (param->input_text_buffer == nullptr) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid param->inputTextBuffer");
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: input_text_buffer is null");
|
||||
return Error::INVALID_INPUT_TEXT_BUFFER;
|
||||
}
|
||||
|
||||
if (extended) {
|
||||
if (!magic_enum::enum_contains(extended->priority)) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid extended->priority");
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: Invalid extended->priority");
|
||||
return Error::INVALID_EXTENDED;
|
||||
}
|
||||
|
||||
// TODO: do correct extended->option validation
|
||||
|
||||
if ((extended->ext_keyboard_mode & 0xe3fffffc) != 0) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid extended->extKeyboardMode");
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: Invalid extended->extKeyboardMode");
|
||||
return Error::INVALID_EXTENDED;
|
||||
}
|
||||
|
||||
if (extended->disable_device > 7) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid extended->disableDevice");
|
||||
if (static_cast<u32>(extended->disable_device) & ~kValidOrbisImeDisableDeviceMask) {
|
||||
LOG_ERROR(Lib_ImeDialog,
|
||||
"sceImeDialogInit: disable_device has invalid bits set (0x{:X})",
|
||||
static_cast<u32>(extended->disable_device));
|
||||
return Error::INVALID_EXTENDED;
|
||||
}
|
||||
}
|
||||
|
||||
if (param->max_text_length > ORBIS_IME_DIALOG_MAX_TEXT_LENGTH) {
|
||||
LOG_INFO(Lib_ImeDialog, "Invalid param->maxTextLength");
|
||||
if (param->max_text_length == 0 || param->max_text_length > ORBIS_IME_MAX_TEXT_LENGTH) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: invalid max_text_length={}",
|
||||
param->max_text_length);
|
||||
return Error::INVALID_MAX_TEXT_LENGTH;
|
||||
}
|
||||
|
||||
// Title string validation
|
||||
if (param->title != nullptr && !std::char_traits<char16_t>::length(param->title)) {
|
||||
LOG_ERROR(Lib_ImeDialog, "sceImeDialogInit: title is empty");
|
||||
return Error::INVALID_PARAM;
|
||||
}
|
||||
|
||||
g_ime_dlg_result = {};
|
||||
g_ime_dlg_state = ImeDialogState(param, extended);
|
||||
g_ime_dlg_status = OrbisImeDialogStatus::Running;
|
||||
g_ime_dlg_ui = ImeDialogUi(&g_ime_dlg_state, &g_ime_dlg_status, &g_ime_dlg_result);
|
||||
|
||||
LOG_INFO(Lib_ImeDialog, "sceImeDialogInit: successful, status now=Running");
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
@ -245,7 +311,7 @@ Error PS4_SYSV_ABI sceImeDialogTerm() {
|
||||
return Error::OK;
|
||||
}
|
||||
|
||||
void RegisterlibSceImeDialog(Core::Loader::SymbolsResolver* sym) {
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym) {
|
||||
LIB_FUNCTION("oBmw4xrmfKs", "libSceImeDialog", 1, "libSceImeDialog", 1, 1, sceImeDialogAbort);
|
||||
LIB_FUNCTION("bX4H+sxPI-o", "libSceImeDialog", 1, "libSceImeDialog", 1, 1,
|
||||
sceImeDialogForceClose);
|
||||
|
@ -13,50 +13,6 @@ class SymbolsResolver;
|
||||
|
||||
namespace Libraries::ImeDialog {
|
||||
|
||||
constexpr u32 ORBIS_IME_DIALOG_MAX_TEXT_LENGTH = 0x78;
|
||||
|
||||
enum class Error : u32 {
|
||||
OK = 0x0,
|
||||
BUSY = 0x80bc0001,
|
||||
NOT_OPENED = 0x80bc0002,
|
||||
NO_MEMORY = 0x80bc0003,
|
||||
CONNECTION_FAILED = 0x80bc0004,
|
||||
TOO_MANY_REQUESTS = 0x80bc0005,
|
||||
INVALID_TEXT = 0x80bc0006,
|
||||
EVENT_OVERFLOW = 0x80bc0007,
|
||||
NOT_ACTIVE = 0x80bc0008,
|
||||
IME_SUSPENDING = 0x80bc0009,
|
||||
DEVICE_IN_USE = 0x80bc000a,
|
||||
INVALID_USER_ID = 0x80bc0010,
|
||||
INVALID_TYPE = 0x80bc0011,
|
||||
INVALID_SUPPORTED_LANGUAGES = 0x80bc0012,
|
||||
INVALID_ENTER_LABEL = 0x80bc0013,
|
||||
INVALID_INPUT_METHOD = 0x80bc0014,
|
||||
INVALID_OPTION = 0x80bc0015,
|
||||
INVALID_MAX_TEXT_LENGTH = 0x80bc0016,
|
||||
INVALID_INPUT_TEXT_BUFFER = 0x80bc0017,
|
||||
INVALID_POSX = 0x80bc0018,
|
||||
INVALID_POSY = 0x80bc0019,
|
||||
INVALID_HORIZONTALIGNMENT = 0x80bc001a,
|
||||
INVALID_VERTICALALIGNMENT = 0x80bc001b,
|
||||
INVALID_EXTENDED = 0x80bc001c,
|
||||
INVALID_KEYBOARD_TYPE = 0x80bc001d,
|
||||
INVALID_WORK = 0x80bc0020,
|
||||
INVALID_ARG = 0x80bc0021,
|
||||
INVALID_HANDLER = 0x80bc0022,
|
||||
NO_RESOURCE_ID = 0x80bc0023,
|
||||
INVALID_MODE = 0x80bc0024,
|
||||
INVALID_PARAM = 0x80bc0030,
|
||||
INVALID_ADDRESS = 0x80bc0031,
|
||||
INVALID_RESERVED = 0x80bc0032,
|
||||
INVALID_TIMING = 0x80bc0033,
|
||||
INTERNAL = 0x80bc00ff,
|
||||
DIALOG_INVALID_TITLE = 0x80bc0101,
|
||||
DIALOG_NOT_RUNNING = 0x80bc0105,
|
||||
DIALOG_NOT_FINISHED = 0x80bc0106,
|
||||
DIALOG_NOT_IN_USE = 0x80bc0107,
|
||||
};
|
||||
|
||||
enum class OrbisImeDialogStatus : u32 {
|
||||
None = 0,
|
||||
Running = 1,
|
||||
@ -69,93 +25,18 @@ enum class OrbisImeDialogEndStatus : u32 {
|
||||
Aborted = 2,
|
||||
};
|
||||
|
||||
enum class OrbisImeDialogOption : u32 {
|
||||
Default = 0,
|
||||
Multiline = 1,
|
||||
NoAutoCorrection = 2,
|
||||
NoAutoCompletion = 4,
|
||||
// TODO: Document missing options
|
||||
LargeResolution = 1024,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisImeDialogOption)
|
||||
|
||||
enum class OrbisImePanelPriority : u32 {
|
||||
Default = 0,
|
||||
Alphabet = 1,
|
||||
Symbol = 2,
|
||||
Accent = 3,
|
||||
};
|
||||
|
||||
struct OrbisImeColor {
|
||||
u8 r;
|
||||
u8 g;
|
||||
u8 b;
|
||||
u8 a;
|
||||
};
|
||||
|
||||
struct OrbisImeDialogResult {
|
||||
OrbisImeDialogEndStatus endstatus;
|
||||
s32 reserved[12];
|
||||
};
|
||||
|
||||
struct OrbisImeKeycode {
|
||||
u16 keycode;
|
||||
char16_t character;
|
||||
u32 status;
|
||||
OrbisImeKeyboardType type;
|
||||
s32 user_id;
|
||||
u32 resource_id;
|
||||
u64 timestamp;
|
||||
};
|
||||
|
||||
using OrbisImeExtKeyboardFilter = PS4_SYSV_ABI int (*)(const OrbisImeKeycode* srcKeycode,
|
||||
u16* outKeycode, u32* outStatus,
|
||||
void* reserved);
|
||||
|
||||
struct OrbisImeDialogParam {
|
||||
s32 user_id;
|
||||
OrbisImeType type;
|
||||
u64 supported_languages;
|
||||
OrbisImeEnterLabel enter_label;
|
||||
OrbisImeInputMethod input_method;
|
||||
OrbisImeTextFilter filter;
|
||||
OrbisImeDialogOption option;
|
||||
u32 max_text_length;
|
||||
char16_t* input_text_buffer;
|
||||
float posx;
|
||||
float posy;
|
||||
OrbisImeHorizontalAlignment horizontal_alignment;
|
||||
OrbisImeVerticalAlignment vertical_alignment;
|
||||
const char16_t* placeholder;
|
||||
const char16_t* title;
|
||||
s8 reserved[16];
|
||||
};
|
||||
|
||||
struct OrbisImeParamExtended {
|
||||
u32 option; // OrbisImeDialogOptionExtended
|
||||
OrbisImeColor color_base;
|
||||
OrbisImeColor color_line;
|
||||
OrbisImeColor color_text_field;
|
||||
OrbisImeColor color_preedit;
|
||||
OrbisImeColor color_button_default;
|
||||
OrbisImeColor color_button_function;
|
||||
OrbisImeColor color_button_symbol;
|
||||
OrbisImeColor color_text;
|
||||
OrbisImeColor color_special;
|
||||
OrbisImePanelPriority priority;
|
||||
char* additional_dictionary_path;
|
||||
OrbisImeExtKeyboardFilter ext_keyboard_filter;
|
||||
uint32_t disable_device;
|
||||
uint32_t ext_keyboard_mode;
|
||||
int8_t reserved[60];
|
||||
};
|
||||
|
||||
Error PS4_SYSV_ABI sceImeDialogAbort();
|
||||
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();
|
||||
@ -166,5 +47,5 @@ int PS4_SYSV_ABI sceImeDialogInitInternal3();
|
||||
int PS4_SYSV_ABI sceImeDialogSetPanelPosition();
|
||||
Error PS4_SYSV_ABI sceImeDialogTerm();
|
||||
|
||||
void RegisterlibSceImeDialog(Core::Loader::SymbolsResolver* sym);
|
||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||
} // namespace Libraries::ImeDialog
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user