mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-13 15:19:11 +00:00
Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ce1ac5e86 | ||
|
|
b4628b80e2 | ||
|
|
2f022a462d | ||
|
|
f5505daaca | ||
|
|
8c1ec863da | ||
|
|
604f8d9398 | ||
|
|
19e974bf21 | ||
|
|
7031f5968e | ||
|
|
ff8869262f | ||
|
|
683e5f3b04 | ||
|
|
08fe66a97f | ||
|
|
bc44865cda | ||
|
|
a42ae46553 | ||
|
|
a4c3c665fe | ||
|
|
caccc05fb2 | ||
|
|
8238ecf88a | ||
|
|
8bbb3956a2 | ||
|
|
f466352dde | ||
|
|
430f2e4700 | ||
|
|
6c7c5eb59c | ||
|
|
493cda07c0 | ||
|
|
eda6be746f | ||
|
|
ed9ffbfb64 | ||
|
|
5cabd6ddd8 | ||
|
|
f06e126330 | ||
|
|
715eb512c9 | ||
|
|
87e09b613b | ||
|
|
6c08c6983b | ||
|
|
6bd74ef769 | ||
|
|
bf34665a8f | ||
|
|
2d17ab8e4b | ||
|
|
db9921baf2 | ||
|
|
17fab7fdf1 | ||
|
|
0cd6248eee | ||
|
|
a1973438db | ||
|
|
a7376dd41f | ||
|
|
6b6294a750 | ||
|
|
999960a6e6 | ||
|
|
6805baffb2 | ||
|
|
109b239ddf | ||
|
|
1714647343 | ||
|
|
794d593a02 | ||
|
|
b34556702e | ||
|
|
a0e7f7fb65 | ||
|
|
8f37cfb739 | ||
|
|
d17a4fb8cc | ||
|
|
4fa435490c | ||
|
|
11229c1dc0 | ||
|
|
455cd37aae | ||
|
|
e7194af881 | ||
|
|
08878385e1 | ||
|
|
81098da509 | ||
|
|
5fedf9daea | ||
|
|
23d0fc6493 | ||
|
|
5c7f802233 | ||
|
|
54b5520c1a | ||
|
|
02f9aef34a | ||
|
|
8de385a4f1 | ||
|
|
110a735a04 | ||
|
|
74c0ea8432 | ||
|
|
af147debc6 | ||
|
|
1020c3150f | ||
|
|
0134b8c3a8 | ||
|
|
6fb64a8054 | ||
|
|
6d0b179d24 | ||
|
|
68fca2552f | ||
|
|
0e6dea1059 | ||
|
|
8a8ee395c5 | ||
|
|
a8f4a20b24 | ||
|
|
505e80e756 | ||
|
|
ad99bda08d | ||
|
|
a35c9f3586 | ||
|
|
cad027845f | ||
|
|
6c5a84dc99 | ||
|
|
937d50cb00 | ||
|
|
905c536ef4 | ||
|
|
528a060709 | ||
|
|
6e27842562 | ||
|
|
71f343d2d6 | ||
|
|
a6f5e4c7dc | ||
|
|
98ceb6e43e | ||
|
|
eeee6ad0ee | ||
|
|
5d8027f0c0 | ||
|
|
1eead6a5ee | ||
|
|
419ea140ab | ||
|
|
976d12f4e6 | ||
|
|
50a3081084 | ||
|
|
525d24a7fc | ||
|
|
51c96b8ee6 | ||
|
|
2b1c0b4f82 | ||
|
|
eb18382396 | ||
|
|
fa489c023e | ||
|
|
f01b6295dd | ||
|
|
be80276ec3 | ||
|
|
71e81c836c | ||
|
|
ddb59edd3e | ||
|
|
7bd3eb485f | ||
|
|
0eff74223a | ||
|
|
1e949c5813 |
2
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
2
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
@@ -35,7 +35,7 @@ body:
|
|||||||
required: true
|
required: true
|
||||||
- label: I have disabled all patches and cheats and the issue is still present.
|
- label: I have disabled all patches and cheats and the issue is still present.
|
||||||
required: true
|
required: true
|
||||||
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadPS4/wiki/I.-Quick-start-%5BUsers%5D#4-adding-modules) installed.
|
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadPS4/wiki/I.-Quick-start-%5BUsers%5D#4-dumping-firmware-modules) installed.
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: desc
|
id: desc
|
||||||
|
|||||||
33
.github/linux-appimage-qt.sh
vendored
33
.github/linux-appimage-qt.sh
vendored
@@ -1,33 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [[ -z $GITHUB_WORKSPACE ]]; then
|
|
||||||
GITHUB_WORKSPACE="${PWD%/*}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
export Qt6_DIR="/usr/lib/qt6"
|
|
||||||
export PATH="$Qt6_DIR/bin:$PATH"
|
|
||||||
export EXTRA_QT_PLUGINS="waylandcompositor"
|
|
||||||
export EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so"
|
|
||||||
|
|
||||||
# Prepare Tools for building the AppImage
|
|
||||||
wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
|
||||||
wget -q https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
|
|
||||||
wget -q https://github.com/linuxdeploy/linuxdeploy-plugin-checkrt/releases/download/continuous/linuxdeploy-plugin-checkrt-x86_64.sh
|
|
||||||
|
|
||||||
chmod a+x linuxdeploy-x86_64.AppImage
|
|
||||||
chmod a+x linuxdeploy-plugin-qt-x86_64.AppImage
|
|
||||||
chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh
|
|
||||||
|
|
||||||
# Build AppImage
|
|
||||||
./linuxdeploy-x86_64.AppImage --appdir AppDir
|
|
||||||
./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir
|
|
||||||
|
|
||||||
cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin
|
|
||||||
|
|
||||||
./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/dist/net.shadps4.shadPS4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --plugin qt
|
|
||||||
rm AppDir/usr/plugins/multimedia/libgstreamermediaplugin.so
|
|
||||||
./linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage
|
|
||||||
mv shadPS4-x86_64.AppImage Shadps4-qt.AppImage
|
|
||||||
238
.github/workflows/build.yml
vendored
238
.github/workflows/build.yml
vendored
@@ -17,14 +17,14 @@ jobs:
|
|||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: fsfe/reuse-action@v5
|
- uses: fsfe/reuse-action@v5
|
||||||
|
|
||||||
clang-format:
|
clang-format:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Install
|
- name: Install
|
||||||
@@ -45,7 +45,7 @@ jobs:
|
|||||||
shorthash: ${{ steps.vars.outputs.shorthash }}
|
shorthash: ${{ steps.vars.outputs.shorthash }}
|
||||||
fullhash: ${{ steps.vars.outputs.fullhash }}
|
fullhash: ${{ steps.vars.outputs.fullhash }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- name: Get date and git hash
|
- name: Get date and git hash
|
||||||
id: vars
|
id: vars
|
||||||
run: |
|
run: |
|
||||||
@@ -60,7 +60,7 @@ jobs:
|
|||||||
runs-on: windows-2025
|
runs-on: windows-2025
|
||||||
needs: get-info
|
needs: get-info
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ jobs:
|
|||||||
${{ env.cache-name }}-
|
${{ env.cache-name }}-
|
||||||
|
|
||||||
- name: Cache CMake Build
|
- name: Cache CMake Build
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||||
env:
|
env:
|
||||||
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
||||||
with:
|
with:
|
||||||
@@ -95,69 +95,11 @@ jobs:
|
|||||||
name: shadps4-win64-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
name: shadps4-win64-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
||||||
path: ${{github.workspace}}/build/shadPS4.exe
|
path: ${{github.workspace}}/build/shadPS4.exe
|
||||||
|
|
||||||
windows-qt:
|
|
||||||
runs-on: windows-2025
|
|
||||||
needs: get-info
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Setup Qt
|
|
||||||
uses: jurplel/install-qt-action@v4
|
|
||||||
with:
|
|
||||||
version: 6.9.2
|
|
||||||
host: windows
|
|
||||||
target: desktop
|
|
||||||
arch: win64_msvc2022_64
|
|
||||||
archives: qtbase qttools
|
|
||||||
modules: qtmultimedia
|
|
||||||
|
|
||||||
- name: Cache CMake Configuration
|
|
||||||
uses: actions/cache@v4
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-ninja-cache-cmake-configuration
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
${{github.workspace}}/build
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ env.cache-name }}-
|
|
||||||
|
|
||||||
- name: Cache CMake Build
|
|
||||||
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: 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
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $env:NUMBER_OF_PROCESSORS
|
|
||||||
|
|
||||||
- name: Deploy and Package
|
|
||||||
run: |
|
|
||||||
mkdir upload
|
|
||||||
mkdir upload/qtplugins
|
|
||||||
move build/shadPS4.exe upload
|
|
||||||
cp dist/qt.conf upload/qt.conf
|
|
||||||
windeployqt --plugindir upload/qtplugins --no-compiler-runtime --no-system-d3d-compiler --no-system-dxc-compiler --dir upload upload/shadPS4.exe
|
|
||||||
Compress-Archive -Path upload/* -DestinationPath shadps4-win64-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}.zip
|
|
||||||
|
|
||||||
- name: Upload Windows Qt artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: shadps4-win64-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
|
||||||
path: upload/
|
|
||||||
|
|
||||||
macos-sdl:
|
macos-sdl:
|
||||||
runs-on: macos-15
|
runs-on: macos-15
|
||||||
needs: get-info
|
needs: get-info
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
@@ -178,7 +120,7 @@ jobs:
|
|||||||
${{ env.cache-name }}-
|
${{ env.cache-name }}-
|
||||||
|
|
||||||
- name: Cache CMake Build
|
- name: Cache CMake Build
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||||
env:
|
env:
|
||||||
cache-name: ${{runner.os}}-sdl-cache-cmake-build
|
cache-name: ${{runner.os}}-sdl-cache-cmake-build
|
||||||
with:
|
with:
|
||||||
@@ -204,72 +146,11 @@ jobs:
|
|||||||
name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
||||||
path: upload/
|
path: upload/
|
||||||
|
|
||||||
macos-qt:
|
|
||||||
runs-on: macos-15
|
|
||||||
needs: get-info
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
|
|
||||||
- name: Setup latest Xcode
|
|
||||||
uses: maxim-lobanov/setup-xcode@v1
|
|
||||||
with:
|
|
||||||
xcode-version: latest
|
|
||||||
|
|
||||||
- name: Setup Qt
|
|
||||||
uses: jurplel/install-qt-action@v4
|
|
||||||
with:
|
|
||||||
version: 6.9.2
|
|
||||||
host: mac
|
|
||||||
target: desktop
|
|
||||||
arch: clang_64
|
|
||||||
archives: qtbase qttools
|
|
||||||
modules: qtmultimedia
|
|
||||||
|
|
||||||
- name: Cache CMake Configuration
|
|
||||||
uses: actions/cache@v4
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-cache-cmake-configuration
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
${{github.workspace}}/build
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ env.cache-name }}-
|
|
||||||
|
|
||||||
- name: Cache CMake Build
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
|
||||||
env:
|
|
||||||
cache-name: ${{runner.os}}-qt-cache-cmake-build
|
|
||||||
with:
|
|
||||||
append-timestamp: false
|
|
||||||
create-symlink: true
|
|
||||||
key: ${{env.cache-name}}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
variant: sccache
|
|
||||||
|
|
||||||
- name: Configure CMake
|
|
||||||
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_OSX_ARCHITECTURES=x86_64 -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(sysctl -n hw.ncpu)
|
|
||||||
|
|
||||||
- name: Package and Upload macOS Qt artifact
|
|
||||||
run: |
|
|
||||||
mkdir upload
|
|
||||||
mv ${{github.workspace}}/build/shadps4.app upload
|
|
||||||
macdeployqt upload/shadps4.app
|
|
||||||
tar cf shadps4-macos-qt.tar.gz -C upload .
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: shadps4-macos-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
|
||||||
path: shadps4-macos-qt.tar.gz
|
|
||||||
|
|
||||||
linux-sdl:
|
linux-sdl:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: get-info
|
needs: get-info
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
@@ -293,7 +174,7 @@ jobs:
|
|||||||
${{ env.cache-name }}-
|
${{ env.cache-name }}-
|
||||||
|
|
||||||
- name: Cache CMake Build
|
- name: Cache CMake Build
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||||
env:
|
env:
|
||||||
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
cache-name: ${{ runner.os }}-sdl-cache-cmake-build
|
||||||
with:
|
with:
|
||||||
@@ -326,63 +207,11 @@ jobs:
|
|||||||
name: shadps4-linux-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
name: shadps4-linux-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
||||||
path: Shadps4-sdl.AppImage
|
path: Shadps4-sdl.AppImage
|
||||||
|
|
||||||
linux-qt:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs: get-info
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
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-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
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-cache-cmake-configuration
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
${{github.workspace}}/build
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ env.cache-name }}-
|
|
||||||
|
|
||||||
- name: Cache CMake Build
|
|
||||||
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: Configure CMake
|
|
||||||
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)
|
|
||||||
|
|
||||||
- name: Run AppImage packaging script
|
|
||||||
run: ./.github/linux-appimage-qt.sh
|
|
||||||
|
|
||||||
- name: Package and Upload Linux Qt artifact
|
|
||||||
run: |
|
|
||||||
tar cf shadps4-linux-qt.tar.gz -C ${{github.workspace}}/build shadps4
|
|
||||||
- uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: shadps4-linux-qt-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}
|
|
||||||
path: Shadps4-qt.AppImage
|
|
||||||
|
|
||||||
linux-sdl-gcc:
|
linux-sdl-gcc:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: get-info
|
needs: get-info
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
@@ -401,7 +230,7 @@ jobs:
|
|||||||
${{ env.cache-name }}-
|
${{ env.cache-name }}-
|
||||||
|
|
||||||
- name: Cache CMake Build
|
- name: Cache CMake Build
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
uses: hendrikmuhs/ccache-action@v1.2.19
|
||||||
env:
|
env:
|
||||||
cache-name: ${{ runner.os }}-sdl-gcc-cache-cmake-build
|
cache-name: ${{ runner.os }}-sdl-gcc-cache-cmake-build
|
||||||
with:
|
with:
|
||||||
@@ -414,52 +243,21 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)
|
||||||
|
|
||||||
linux-qt-gcc:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs: get-info
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
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 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
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-gcc-cache-cmake-configuration
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
${{github.workspace}}/build
|
|
||||||
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ env.cache-name }}-
|
|
||||||
|
|
||||||
- name: Cache CMake Build
|
|
||||||
uses: hendrikmuhs/ccache-action@v1.2.18
|
|
||||||
env:
|
|
||||||
cache-name: ${{ runner.os }}-qt-gcc-cache-cmake-build
|
|
||||||
with:
|
|
||||||
append-timestamp: false
|
|
||||||
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_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)
|
|
||||||
|
|
||||||
pre-release:
|
pre-release:
|
||||||
if: github.ref == 'refs/heads/main' && github.repository == 'shadps4-emu/shadPS4' && github.event_name == 'push'
|
if: github.ref == 'refs/heads/main' && github.repository == 'shadps4-emu/shadPS4' && github.event_name == 'push'
|
||||||
needs: [get-info, windows-sdl, windows-qt, macos-sdl, macos-qt, linux-sdl, linux-qt]
|
needs: [get-info, windows-sdl, macos-sdl, linux-sdl]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v5
|
||||||
with:
|
with:
|
||||||
path: ./artifacts
|
path: ./artifacts
|
||||||
|
|
||||||
|
- name: Make SDL artifacts executable
|
||||||
|
run: |
|
||||||
|
chmod -R a+x ./artifacts/shadps4-linux-sdl-*
|
||||||
|
chmod -R a+x ./artifacts/shadps4-macos-sdl-*
|
||||||
|
|
||||||
- name: Compress individual directories (without parent directory)
|
- name: Compress individual directories (without parent directory)
|
||||||
run: |
|
run: |
|
||||||
cd ./artifacts
|
cd ./artifacts
|
||||||
|
|||||||
11
.github/workflows/scripts/update_translation.sh
vendored
11
.github/workflows/scripts/update_translation.sh
vendored
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
sudo apt-get -y install qt6-l10n-tools python3
|
|
||||||
|
|
||||||
SCRIPT_PATH="src/qt_gui/translations/update_translation.sh"
|
|
||||||
|
|
||||||
chmod +x "$SCRIPT_PATH"
|
|
||||||
|
|
||||||
PATH=/usr/lib/qt6/bin:$PATH "$SCRIPT_PATH"
|
|
||||||
30
.github/workflows/update_translation.yml
vendored
30
.github/workflows/update_translation.yml
vendored
@@ -1,30 +0,0 @@
|
|||||||
name: Update Translation
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: "0 0 * * *" # Every day at 12am UTC.
|
|
||||||
workflow_dispatch: # As well as manually.
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
update:
|
|
||||||
if: github.repository == 'shadps4-emu/shadPS4'
|
|
||||||
name: "Update Translation"
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set execution permissions for the script
|
|
||||||
run: chmod +x ./.github/workflows/scripts/update_translation.sh
|
|
||||||
|
|
||||||
- name: Update Base Translation
|
|
||||||
run: ./.github/workflows/scripts/update_translation.sh
|
|
||||||
|
|
||||||
- name: Create Pull Request
|
|
||||||
uses: peter-evans/create-pull-request@v7
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.SHADPS4_TOKEN_REPO }}
|
|
||||||
title: "Qt GUI: Update Translation"
|
|
||||||
commit-message: "[ci skip] Qt GUI: Update Translation."
|
|
||||||
body: "Daily update of translation sources."
|
|
||||||
branch: update-translation
|
|
||||||
delete-branch: true
|
|
||||||
24
.gitmodules
vendored
24
.gitmodules
vendored
@@ -91,18 +91,6 @@
|
|||||||
path = externals/libpng
|
path = externals/libpng
|
||||||
url = https://github.com/pnggroup/libpng
|
url = https://github.com/pnggroup/libpng
|
||||||
shallow = true
|
shallow = true
|
||||||
[submodule "externals/MoltenVK/SPIRV-Cross"]
|
|
||||||
path = externals/MoltenVK/SPIRV-Cross
|
|
||||||
url = https://github.com/KhronosGroup/SPIRV-Cross
|
|
||||||
shallow = true
|
|
||||||
[submodule "externals/MoltenVK/MoltenVK"]
|
|
||||||
path = externals/MoltenVK/MoltenVK
|
|
||||||
url = https://github.com/KhronosGroup/MoltenVK
|
|
||||||
shallow = true
|
|
||||||
[submodule "externals/MoltenVK/cereal"]
|
|
||||||
path = externals/MoltenVK/cereal
|
|
||||||
url = https://github.com/USCiLab/cereal
|
|
||||||
shallow = true
|
|
||||||
[submodule "externals/ext-libusb"]
|
[submodule "externals/ext-libusb"]
|
||||||
path = externals/ext-libusb
|
path = externals/ext-libusb
|
||||||
url = https://github.com/shadps4-emu/ext-libusb.git
|
url = https://github.com/shadps4-emu/ext-libusb.git
|
||||||
@@ -113,3 +101,15 @@
|
|||||||
path = externals/hwinfo
|
path = externals/hwinfo
|
||||||
url = https://github.com/shadps4-emu/ext-hwinfo
|
url = https://github.com/shadps4-emu/ext-hwinfo
|
||||||
shallow = true
|
shallow = true
|
||||||
|
[submodule "externals/ext-wepoll"]
|
||||||
|
path = externals/ext-wepoll
|
||||||
|
url = https://github.com/shadps4-emu/ext-wepoll.git
|
||||||
|
shallow = true
|
||||||
|
branch = dist
|
||||||
|
[submodule "externals/MoltenVK"]
|
||||||
|
path = externals/MoltenVK
|
||||||
|
url = https://github.com/KhronosGroup/MoltenVK.git
|
||||||
|
shallow = true
|
||||||
|
[submodule "externals/json"]
|
||||||
|
path = externals/json
|
||||||
|
url = https://github.com/nlohmann/json.git
|
||||||
|
|||||||
22
CMakeDarwinPresets.json
Normal file
22
CMakeDarwinPresets.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"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}",
|
||||||
|
"CMAKE_OSX_ARCHITECTURES": "x86_64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
258
CMakeLists.txt
258
CMakeLists.txt
@@ -31,7 +31,6 @@ if(UNIX AND NOT APPLE)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(ENABLE_QT_GUI "Enable the Qt GUI. If not selected then the emulator uses a minimal SDL-based UI instead" OFF)
|
|
||||||
option(ENABLE_DISCORD_RPC "Enable the Discord RPC integration" ON)
|
option(ENABLE_DISCORD_RPC "Enable the Discord RPC integration" ON)
|
||||||
option(ENABLE_UPDATER "Enables the options to updater" ON)
|
option(ENABLE_UPDATER "Enables the options to updater" ON)
|
||||||
|
|
||||||
@@ -203,8 +202,8 @@ execute_process(
|
|||||||
|
|
||||||
# Set Version
|
# Set Version
|
||||||
set(EMULATOR_VERSION_MAJOR "0")
|
set(EMULATOR_VERSION_MAJOR "0")
|
||||||
set(EMULATOR_VERSION_MINOR "11")
|
set(EMULATOR_VERSION_MINOR "12")
|
||||||
set(EMULATOR_VERSION_PATCH "0")
|
set(EMULATOR_VERSION_PATCH "5")
|
||||||
|
|
||||||
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_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}")
|
||||||
|
|
||||||
@@ -215,15 +214,11 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_
|
|||||||
message("-- end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}, link: ${GIT_REMOTE_URL}")
|
message("-- end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}, link: ${GIT_REMOTE_URL}")
|
||||||
|
|
||||||
string(TOLOWER "${GIT_REMOTE_URL}" GIT_REMOTE_URL_LOWER)
|
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")
|
if(NOT (GIT_REMOTE_URL_LOWER MATCHES "shadps4-emu/shadps4" AND (GIT_BRANCH STREQUAL "main" OR "$ENV{GITHUB_REF}" MATCHES "refs/tags/")))
|
||||||
message(STATUS "not main, disabling auto update")
|
message(STATUS "not main, disabling auto update")
|
||||||
set(ENABLE_UPDATER OFF)
|
set(ENABLE_UPDATER OFF)
|
||||||
endif()
|
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")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
find_package(Boost 1.84.0 CONFIG)
|
find_package(Boost 1.84.0 CONFIG)
|
||||||
find_package(FFmpeg 5.1.2 MODULE)
|
find_package(FFmpeg 5.1.2 MODULE)
|
||||||
@@ -237,7 +232,7 @@ find_package(SDL3 3.1.2 CONFIG)
|
|||||||
find_package(stb MODULE)
|
find_package(stb MODULE)
|
||||||
find_package(toml11 4.2.0 CONFIG)
|
find_package(toml11 4.2.0 CONFIG)
|
||||||
find_package(tsl-robin-map 1.3.0 CONFIG)
|
find_package(tsl-robin-map 1.3.0 CONFIG)
|
||||||
find_package(VulkanHeaders 1.4.324 CONFIG)
|
find_package(VulkanHeaders 1.4.329 CONFIG)
|
||||||
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
|
||||||
find_package(xbyak 7.07 CONFIG)
|
find_package(xbyak 7.07 CONFIG)
|
||||||
find_package(xxHash 0.8.2 MODULE)
|
find_package(xxHash 0.8.2 MODULE)
|
||||||
@@ -262,30 +257,6 @@ endif()
|
|||||||
add_subdirectory(externals)
|
add_subdirectory(externals)
|
||||||
include_directories(src)
|
include_directories(src)
|
||||||
|
|
||||||
if(ENABLE_QT_GUI)
|
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools Network Multimedia)
|
|
||||||
qt_standard_project_setup()
|
|
||||||
set(CMAKE_AUTORCC ON)
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
|
||||||
set(CMAKE_AUTOUIC ON)
|
|
||||||
|
|
||||||
set(QT_TRANSLATIONS "${PROJECT_SOURCE_DIR}/src/qt_gui/translations")
|
|
||||||
file(GLOB_RECURSE TRANSLATIONS_TS ${QT_TRANSLATIONS}/*.ts)
|
|
||||||
|
|
||||||
set_source_files_properties(${TRANSLATIONS_TS} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/translations")
|
|
||||||
qt_add_translation(TRANSLATIONS_QM ${TRANSLATIONS_TS})
|
|
||||||
|
|
||||||
set(TRANSLATIONS_QRC ${CMAKE_CURRENT_BINARY_DIR}/translations/translations.qrc)
|
|
||||||
file(WRITE ${TRANSLATIONS_QRC} "<RCC><qresource prefix=\"translations\">\n")
|
|
||||||
foreach (QM ${TRANSLATIONS_QM})
|
|
||||||
get_filename_component(QM_FILE ${QM} NAME)
|
|
||||||
file(APPEND ${TRANSLATIONS_QRC} "<file>${QM_FILE}</file>\n")
|
|
||||||
endforeach (QM)
|
|
||||||
file(APPEND ${TRANSLATIONS_QRC} "</qresource></RCC>")
|
|
||||||
|
|
||||||
qt_add_resources(TRANSLATIONS ${TRANSLATIONS_QRC})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
set(AJM_LIB src/core/libraries/ajm/ajm.cpp
|
||||||
src/core/libraries/ajm/ajm.h
|
src/core/libraries/ajm/ajm.h
|
||||||
src/core/libraries/ajm/ajm_at9.cpp
|
src/core/libraries/ajm/ajm_at9.cpp
|
||||||
@@ -380,6 +351,10 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
|
|||||||
src/core/libraries/network/net_ctl_codes.h
|
src/core/libraries/network/net_ctl_codes.h
|
||||||
src/core/libraries/network/net_util.cpp
|
src/core/libraries/network/net_util.cpp
|
||||||
src/core/libraries/network/net_util.h
|
src/core/libraries/network/net_util.h
|
||||||
|
src/core/libraries/network/net_epoll.cpp
|
||||||
|
src/core/libraries/network/net_epoll.h
|
||||||
|
src/core/libraries/network/net_resolver.cpp
|
||||||
|
src/core/libraries/network/net_resolver.h
|
||||||
src/core/libraries/network/net_error.h
|
src/core/libraries/network/net_error.h
|
||||||
src/core/libraries/network/net.h
|
src/core/libraries/network/net.h
|
||||||
src/core/libraries/network/ssl.cpp
|
src/core/libraries/network/ssl.cpp
|
||||||
@@ -486,6 +461,12 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
|
|||||||
src/core/libraries/mouse/mouse.h
|
src/core/libraries/mouse/mouse.h
|
||||||
src/core/libraries/web_browser_dialog/webbrowserdialog.cpp
|
src/core/libraries/web_browser_dialog/webbrowserdialog.cpp
|
||||||
src/core/libraries/web_browser_dialog/webbrowserdialog.h
|
src/core/libraries/web_browser_dialog/webbrowserdialog.h
|
||||||
|
src/core/libraries/font/font.cpp
|
||||||
|
src/core/libraries/font/font.h
|
||||||
|
src/core/libraries/font/fontft.cpp
|
||||||
|
src/core/libraries/font/fontft.h
|
||||||
|
src/core/libraries/font/font_error.h
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
|
set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
|
||||||
@@ -557,6 +538,13 @@ set(RANDOM_LIB src/core/libraries/random/random.cpp
|
|||||||
|
|
||||||
set(USBD_LIB src/core/libraries/usbd/usbd.cpp
|
set(USBD_LIB src/core/libraries/usbd/usbd.cpp
|
||||||
src/core/libraries/usbd/usbd.h
|
src/core/libraries/usbd/usbd.h
|
||||||
|
src/core/libraries/usbd/usb_backend.h
|
||||||
|
src/core/libraries/usbd/emulated/dimensions.cpp
|
||||||
|
src/core/libraries/usbd/emulated/dimensions.h
|
||||||
|
src/core/libraries/usbd/emulated/infinity.cpp
|
||||||
|
src/core/libraries/usbd/emulated/infinity.h
|
||||||
|
src/core/libraries/usbd/emulated/skylander.cpp
|
||||||
|
src/core/libraries/usbd/emulated/skylander.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(FIBER_LIB src/core/libraries/fiber/fiber_context.s
|
set(FIBER_LIB src/core/libraries/fiber/fiber_context.s
|
||||||
@@ -596,6 +584,8 @@ set(NP_LIBS src/core/libraries/np/np_error.h
|
|||||||
src/core/libraries/np/np_auth.h
|
src/core/libraries/np/np_auth.h
|
||||||
src/core/libraries/np/np_profile_dialog.cpp
|
src/core/libraries/np/np_profile_dialog.cpp
|
||||||
src/core/libraries/np/np_profile_dialog.h
|
src/core/libraries/np/np_profile_dialog.h
|
||||||
|
src/core/libraries/np/np_sns_facebook_dialog.cpp
|
||||||
|
src/core/libraries/np/np_sns_facebook_dialog.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp
|
||||||
@@ -637,6 +627,7 @@ set(COMPANION_LIBS src/core/libraries/companion/companion_httpd.cpp
|
|||||||
)
|
)
|
||||||
set(DEV_TOOLS src/core/devtools/layer.cpp
|
set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||||
src/core/devtools/layer.h
|
src/core/devtools/layer.h
|
||||||
|
src/core/devtools/layer_extra.cpp
|
||||||
src/core/devtools/options.cpp
|
src/core/devtools/options.cpp
|
||||||
src/core/devtools/options.h
|
src/core/devtools/options.h
|
||||||
src/core/devtools/gcn/gcn_context_regs.cpp
|
src/core/devtools/gcn/gcn_context_regs.cpp
|
||||||
@@ -763,6 +754,8 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
src/core/file_sys/devices/deci_tty6_device.h
|
src/core/file_sys/devices/deci_tty6_device.h
|
||||||
src/core/file_sys/devices/random_device.cpp
|
src/core/file_sys/devices/random_device.cpp
|
||||||
src/core/file_sys/devices/random_device.h
|
src/core/file_sys/devices/random_device.h
|
||||||
|
src/core/file_sys/devices/rng_device.cpp
|
||||||
|
src/core/file_sys/devices/rng_device.h
|
||||||
src/core/file_sys/devices/urandom_device.cpp
|
src/core/file_sys/devices/urandom_device.cpp
|
||||||
src/core/file_sys/devices/urandom_device.h
|
src/core/file_sys/devices/urandom_device.h
|
||||||
src/core/file_sys/devices/srandom_device.cpp
|
src/core/file_sys/devices/srandom_device.cpp
|
||||||
@@ -820,6 +813,8 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
${DEV_TOOLS}
|
${DEV_TOOLS}
|
||||||
src/core/debug_state.cpp
|
src/core/debug_state.cpp
|
||||||
src/core/debug_state.h
|
src/core/debug_state.h
|
||||||
|
src/core/debugger.cpp
|
||||||
|
src/core/debugger.h
|
||||||
src/core/linker.cpp
|
src/core/linker.cpp
|
||||||
src/core/linker.h
|
src/core/linker.h
|
||||||
src/core/memory.cpp
|
src/core/memory.cpp
|
||||||
@@ -841,10 +836,10 @@ if (ARCHITECTURE STREQUAL "x86_64")
|
|||||||
src/core/cpu_patches.h)
|
src/core/cpu_patches.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
set(SHADER_RECOMPILER src/shader_recompiler/profile.h
|
||||||
src/shader_recompiler/profile.h
|
|
||||||
src/shader_recompiler/recompiler.cpp
|
src/shader_recompiler/recompiler.cpp
|
||||||
src/shader_recompiler/recompiler.h
|
src/shader_recompiler/recompiler.h
|
||||||
|
src/shader_recompiler/resource.h
|
||||||
src/shader_recompiler/info.h
|
src/shader_recompiler/info.h
|
||||||
src/shader_recompiler/params.h
|
src/shader_recompiler/params.h
|
||||||
src/shader_recompiler/runtime_info.h
|
src/shader_recompiler/runtime_info.h
|
||||||
@@ -942,17 +937,24 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
|
|||||||
src/shader_recompiler/ir/value.h
|
src/shader_recompiler/ir/value.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
|
set(VIDEO_CORE src/video_core/amdgpu/cb_db_extent.h
|
||||||
|
src/video_core/amdgpu/liverpool.cpp
|
||||||
src/video_core/amdgpu/liverpool.h
|
src/video_core/amdgpu/liverpool.h
|
||||||
src/video_core/amdgpu/pixel_format.cpp
|
src/video_core/amdgpu/pixel_format.cpp
|
||||||
src/video_core/amdgpu/pixel_format.h
|
src/video_core/amdgpu/pixel_format.h
|
||||||
src/video_core/amdgpu/pm4_cmds.h
|
src/video_core/amdgpu/pm4_cmds.h
|
||||||
src/video_core/amdgpu/pm4_opcodes.h
|
src/video_core/amdgpu/pm4_opcodes.h
|
||||||
|
src/video_core/amdgpu/regs_color.h
|
||||||
|
src/video_core/amdgpu/regs_depth.h
|
||||||
|
src/video_core/amdgpu/regs.cpp
|
||||||
|
src/video_core/amdgpu/regs.h
|
||||||
|
src/video_core/amdgpu/regs_primitive.h
|
||||||
|
src/video_core/amdgpu/regs_shader.h
|
||||||
|
src/video_core/amdgpu/regs_texture.h
|
||||||
|
src/video_core/amdgpu/regs_vertex.h
|
||||||
src/video_core/amdgpu/resource.h
|
src/video_core/amdgpu/resource.h
|
||||||
src/video_core/amdgpu/tiling.cpp
|
src/video_core/amdgpu/tiling.cpp
|
||||||
src/video_core/amdgpu/tiling.h
|
src/video_core/amdgpu/tiling.h
|
||||||
src/video_core/amdgpu/types.h
|
|
||||||
src/video_core/amdgpu/default_context.cpp
|
|
||||||
src/video_core/buffer_cache/buffer.cpp
|
src/video_core/buffer_cache/buffer.cpp
|
||||||
src/video_core/buffer_cache/buffer.h
|
src/video_core/buffer_cache/buffer.h
|
||||||
src/video_core/buffer_cache/buffer_cache.cpp
|
src/video_core/buffer_cache/buffer_cache.cpp
|
||||||
@@ -1049,112 +1051,26 @@ set(EMULATOR src/emulator.cpp
|
|||||||
src/sdl_window.cpp
|
src/sdl_window.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# The above is shared in SDL and Qt version (TODO share them all)
|
add_executable(shadps4
|
||||||
|
${AUDIO_CORE}
|
||||||
if(ENABLE_QT_GUI)
|
${IMGUI}
|
||||||
qt_add_resources(RESOURCE_FILES src/shadps4.qrc)
|
${INPUT}
|
||||||
|
${COMMON}
|
||||||
if (ENABLE_UPDATER)
|
${CORE}
|
||||||
set(UPDATER src/qt_gui/check_update.cpp
|
${SHADER_RECOMPILER}
|
||||||
src/qt_gui/check_update.h
|
${VIDEO_CORE}
|
||||||
)
|
${EMULATOR}
|
||||||
endif()
|
src/main.cpp
|
||||||
|
src/emulator.cpp
|
||||||
set(QT_GUI src/qt_gui/about_dialog.cpp
|
src/emulator.h
|
||||||
src/qt_gui/about_dialog.h
|
src/sdl_window.h
|
||||||
src/qt_gui/about_dialog.ui
|
src/sdl_window.cpp
|
||||||
src/qt_gui/background_music_player.cpp
|
|
||||||
src/qt_gui/background_music_player.h
|
|
||||||
src/qt_gui/cheats_patches.cpp
|
|
||||||
src/qt_gui/cheats_patches.h
|
|
||||||
src/qt_gui/compatibility_info.cpp
|
|
||||||
src/qt_gui/compatibility_info.h
|
|
||||||
src/qt_gui/control_settings.cpp
|
|
||||||
src/qt_gui/control_settings.h
|
|
||||||
src/qt_gui/control_settings.ui
|
|
||||||
src/qt_gui/kbm_gui.cpp
|
|
||||||
src/qt_gui/kbm_gui.h
|
|
||||||
src/qt_gui/kbm_gui.ui
|
|
||||||
src/qt_gui/main_window_ui.h
|
|
||||||
src/qt_gui/main_window.cpp
|
|
||||||
src/qt_gui/main_window.h
|
|
||||||
src/qt_gui/gui_context_menus.h
|
|
||||||
src/qt_gui/game_list_utils.h
|
|
||||||
src/qt_gui/game_info.cpp
|
|
||||||
src/qt_gui/game_info.h
|
|
||||||
src/qt_gui/game_list_frame.cpp
|
|
||||||
src/qt_gui/game_list_frame.h
|
|
||||||
src/qt_gui/game_grid_frame.cpp
|
|
||||||
src/qt_gui/game_grid_frame.h
|
|
||||||
src/qt_gui/game_install_dialog.cpp
|
|
||||||
src/qt_gui/game_install_dialog.h
|
|
||||||
src/qt_gui/trophy_viewer.cpp
|
|
||||||
src/qt_gui/trophy_viewer.h
|
|
||||||
src/qt_gui/elf_viewer.cpp
|
|
||||||
src/qt_gui/elf_viewer.h
|
|
||||||
src/qt_gui/kbm_config_dialog.cpp
|
|
||||||
src/qt_gui/kbm_config_dialog.h
|
|
||||||
src/qt_gui/kbm_help_dialog.cpp
|
|
||||||
src/qt_gui/kbm_help_dialog.h
|
|
||||||
src/qt_gui/main_window_themes.cpp
|
|
||||||
src/qt_gui/main_window_themes.h
|
|
||||||
src/qt_gui/log_presets_dialog.cpp
|
|
||||||
src/qt_gui/log_presets_dialog.h
|
|
||||||
src/qt_gui/settings_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
|
|
||||||
src/qt_gui/hotkeys.h
|
|
||||||
src/qt_gui/hotkeys.cpp
|
|
||||||
src/qt_gui/hotkeys.ui
|
|
||||||
${EMULATOR}
|
|
||||||
${RESOURCE_FILES}
|
|
||||||
${TRANSLATIONS}
|
|
||||||
${UPDATER}
|
|
||||||
)
|
)
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ENABLE_QT_GUI)
|
|
||||||
qt_add_executable(shadps4
|
|
||||||
${AUDIO_CORE}
|
|
||||||
${IMGUI}
|
|
||||||
${INPUT}
|
|
||||||
${QT_GUI}
|
|
||||||
${COMMON}
|
|
||||||
${CORE}
|
|
||||||
${SHADER_RECOMPILER}
|
|
||||||
${VIDEO_CORE}
|
|
||||||
${EMULATOR}
|
|
||||||
src/images/shadPS4.icns
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
add_executable(shadps4
|
|
||||||
${AUDIO_CORE}
|
|
||||||
${IMGUI}
|
|
||||||
${INPUT}
|
|
||||||
${COMMON}
|
|
||||||
${CORE}
|
|
||||||
${SHADER_RECOMPILER}
|
|
||||||
${VIDEO_CORE}
|
|
||||||
${EMULATOR}
|
|
||||||
src/main.cpp
|
|
||||||
src/emulator.cpp
|
|
||||||
src/emulator.h
|
|
||||||
src/sdl_window.h
|
|
||||||
src/sdl_window.cpp
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
create_target_directory_groups(shadps4)
|
create_target_directory_groups(shadps4)
|
||||||
|
|
||||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn half::half ZLIB::ZLIB PNG::PNG)
|
||||||
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers libusb::usb lfreist-hwinfo::hwinfo)
|
target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator LibAtrac9 sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::glslang SDL3::SDL3 pugixml::pugixml stb::headers libusb::usb lfreist-hwinfo::hwinfo nlohmann_json::nlohmann_json)
|
||||||
|
|
||||||
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h")
|
||||||
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h")
|
||||||
@@ -1174,22 +1090,11 @@ endif()
|
|||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
# Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
|
# Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers.
|
||||||
if (ENABLE_QT_GUI)
|
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path")
|
||||||
set(MVK_BUNDLE_PATH "Resources/vulkan/icd.d")
|
set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../${MVK_BUNDLE_PATH}")
|
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/MoltenVK/libMoltenVK.dylib)
|
||||||
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_DST ${CMAKE_CURRENT_BINARY_DIR})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib)
|
|
||||||
set(MVK_DYLIB_DST ${MVK_DST}/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_SRC ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK/icd/MoltenVK_icd.json)
|
||||||
set(MVK_ICD_DST ${MVK_DST}/MoltenVK_icd.json)
|
set(MVK_ICD_DST ${MVK_DST}/MoltenVK_icd.json)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
@@ -1206,23 +1111,15 @@ if (APPLE)
|
|||||||
|
|
||||||
if (ARCHITECTURE STREQUAL "x86_64")
|
if (ARCHITECTURE STREQUAL "x86_64")
|
||||||
# Reserve system-managed memory space.
|
# Reserve system-managed memory space.
|
||||||
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)
|
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,-segaddr,USER_AREA,0x7000000000,-image_base,0x700000000000)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Replacement for std::chrono::time_zone
|
# Replacement for std::chrono::time_zone
|
||||||
target_link_libraries(shadps4 PRIVATE date::date-tz epoll-shim)
|
target_link_libraries(shadps4 PRIVATE date::date-tz epoll-shim)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_QT_GUI)
|
|
||||||
target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network Qt6::Multimedia)
|
|
||||||
add_definitions(-DENABLE_QT_GUI)
|
|
||||||
if (ENABLE_UPDATER)
|
|
||||||
add_definitions(-DENABLE_UPDATER)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(shadps4 PRIVATE mincore)
|
target_link_libraries(shadps4 PRIVATE mincore wepoll)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
# MSVC likes putting opinions on what people can use, disable:
|
# MSVC likes putting opinions on what people can use, disable:
|
||||||
@@ -1256,6 +1153,13 @@ if (WIN32)
|
|||||||
else()
|
else()
|
||||||
target_link_options(shadps4 PRIVATE -Wl,--stack,2097152)
|
target_link_options(shadps4 PRIVATE -Wl,--stack,2097152)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Change base image address
|
||||||
|
if (MSVC)
|
||||||
|
target_link_options(shadps4 PRIVATE /BASE:0x700000000000)
|
||||||
|
else()
|
||||||
|
target_link_options(shadps4 PRIVATE -Wl,--image-base=0x700000000000)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
@@ -1291,25 +1195,6 @@ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/imgui/renderer)
|
|||||||
add_dependencies(shadps4 ImGui_Resources)
|
add_dependencies(shadps4 ImGui_Resources)
|
||||||
target_include_directories(shadps4 PRIVATE ${IMGUI_RESOURCES_INCLUDE})
|
target_include_directories(shadps4 PRIVATE ${IMGUI_RESOURCES_INCLUDE})
|
||||||
|
|
||||||
if (ENABLE_QT_GUI)
|
|
||||||
set_target_properties(shadps4 PROPERTIES
|
|
||||||
# WIN32_EXECUTABLE ON
|
|
||||||
MACOSX_BUNDLE ON
|
|
||||||
MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/dist/MacOSBundleInfo.plist.in"
|
|
||||||
MACOSX_BUNDLE_ICON_FILE "shadPS4.icns"
|
|
||||||
MACOSX_BUNDLE_SHORT_VERSION_STRING "${APP_VERSION}"
|
|
||||||
)
|
|
||||||
|
|
||||||
set_source_files_properties(src/images/shadPS4.icns PROPERTIES
|
|
||||||
MACOSX_PACKAGE_LOCATION Resources)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
|
||||||
if (ENABLE_QT_GUI)
|
|
||||||
find_package(OpenSSL REQUIRED)
|
|
||||||
target_link_libraries(shadps4 PRIVATE ${OPENSSL_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Discord RPC
|
# Discord RPC
|
||||||
if (ENABLE_DISCORD_RPC)
|
if (ENABLE_DISCORD_RPC)
|
||||||
@@ -1318,10 +1203,3 @@ endif()
|
|||||||
|
|
||||||
# Install rules
|
# Install rules
|
||||||
install(TARGETS shadps4 BUNDLE DESTINATION .)
|
install(TARGETS shadps4 BUNDLE DESTINATION .)
|
||||||
|
|
||||||
if (ENABLE_QT_GUI AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
install(FILES "dist/net.shadps4.shadPS4.desktop" DESTINATION "share/applications")
|
|
||||||
install(FILES "dist/net.shadps4.shadPS4.metainfo.xml" DESTINATION "share/metainfo")
|
|
||||||
install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps" RENAME "net.shadps4.shadPS4.png")
|
|
||||||
install(FILES "src/images/net.shadps4.shadPS4.svg" DESTINATION "share/icons/hicolor/scalable/apps")
|
|
||||||
endif()
|
|
||||||
|
|||||||
@@ -15,15 +15,6 @@
|
|||||||
"CMAKE_BUILD_TYPE": "Debug"
|
"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",
|
"name": "x64-Clang-Release",
|
||||||
"displayName": "Clang x64 Release",
|
"displayName": "Clang x64 Release",
|
||||||
@@ -32,15 +23,6 @@
|
|||||||
"CMAKE_BUILD_TYPE": "Release"
|
"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",
|
"name": "x64-Clang-RelWithDebInfo",
|
||||||
"displayName": "Clang x64 RelWithDebInfo",
|
"displayName": "Clang x64 RelWithDebInfo",
|
||||||
@@ -48,15 +30,6 @@
|
|||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
"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,18 +12,6 @@
|
|||||||
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
||||||
"intelliSenseMode": "windows-clang-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",
|
"name": "x64-Clang-Debug",
|
||||||
"generator": "Ninja",
|
"generator": "Ninja",
|
||||||
@@ -36,18 +24,6 @@
|
|||||||
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
||||||
"intelliSenseMode": "windows-clang-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",
|
"name": "x64-Clang-RelWithDebInfo",
|
||||||
"generator": "Ninja",
|
"generator": "Ninja",
|
||||||
@@ -59,18 +35,6 @@
|
|||||||
"ctestCommandArgs": "",
|
"ctestCommandArgs": "",
|
||||||
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
"inheritEnvironments": [ "clang_cl_x64_x64" ],
|
||||||
"intelliSenseMode": "windows-clang-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"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
31
README.md
31
README.md
@@ -36,6 +36,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
|||||||
|
|
||||||
**shadPS4** is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++.
|
**shadPS4** is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> This is the emulator core, which does not include a GUI. If you just want to use the emulator as an end user, download the [**QtLauncher**](https://github.com/shadps4-emu/shadps4-qtlauncher/releases) instead.
|
||||||
|
|
||||||
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).\
|
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 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 discuss shadPS4 development, suggest ideas or to ask for help, join our [**Discord server**](https://discord.gg/bFJxfftGW6).\
|
||||||
@@ -55,9 +58,6 @@ This project began for fun. Given our limited free time, it may take some time b
|
|||||||
|
|
||||||
# Building
|
# Building
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> If you want to use shadPS4 to play your games, you don't have to follow the build instructions, you can simply download the emulator from either the [**release tab**](https://github.com/shadps4-emu/shadPS4/releases) or the [**action tab**](https://github.com/shadps4-emu/shadPS4/actions).
|
|
||||||
|
|
||||||
## Windows
|
## Windows
|
||||||
|
|
||||||
Check the build instructions for [**Windows**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-windows.md).
|
Check the build instructions for [**Windows**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/building-windows.md).
|
||||||
@@ -73,6 +73,22 @@ Check the build instructions for [**macOS**](https://github.com/shadps4-emu/shad
|
|||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> macOS users need at least macOS 15.4 to run shadPS4. Due to GPU issues there are currently heavy bugs on Intel Macs.
|
> macOS users need at least macOS 15.4 to run shadPS4. Due to GPU issues there are currently heavy bugs on Intel Macs.
|
||||||
|
|
||||||
|
# Usage examples
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> For a user-friendly GUI, download the [**QtLauncher**](https://github.com/shadps4-emu/shadps4-qtlauncher/releases).
|
||||||
|
|
||||||
|
To get the list of all available commands and also a more detailed description of what each command does, please refer to the `--help` flag's output.
|
||||||
|
|
||||||
|
Below is a list of commonly used command patterns:
|
||||||
|
```sh
|
||||||
|
shadPS4 CUSA00001 # Searches for a game folder called CUSA00001 in the list of game install folders, and boots it.
|
||||||
|
shadPS4 --fullscreen true --config-clean CUSA00001 # the game argument is always the last one,
|
||||||
|
shadPS4 -g CUSA00001 --fullscreen true --config-clean # ...unless manually specified otherwise.
|
||||||
|
shadPS4 /path/to/game.elf # Boots a PS4 ELF file directly. Useful if you want to boot an executable that is not named eboot.bin.
|
||||||
|
shadPS4 CUSA00001 -- -flag1 -flag2 # Passes '-flag1' and '-flag2' to the game executable in argv.
|
||||||
|
```
|
||||||
|
|
||||||
# Debugging and reporting issues
|
# Debugging and reporting issues
|
||||||
|
|
||||||
For more information on how to test, debug and report issues with the emulator or games, read the [**Debugging documentation**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md).
|
For more information on how to test, debug and report issues with the emulator or games, read the [**Debugging documentation**](https://github.com/shadps4-emu/shadPS4/blob/main/documents/Debugging/Debugging.md).
|
||||||
@@ -160,15 +176,6 @@ Logo is done by [**Xphalnos**](https://github.com/Xphalnos)
|
|||||||
If you want to contribute, please read 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 :)
|
Open a PR and we'll check it :)
|
||||||
|
|
||||||
# Translations
|
|
||||||
|
|
||||||
If you want to translate shadPS4 to your language we use [**Crowdin**](https://crowdin.com/project/shadps4-emulator).
|
|
||||||
# Contributors
|
|
||||||
|
|
||||||
<a href="https://github.com/shadps4-emu/shadPS4/graphs/contributors">
|
|
||||||
<img src="https://contrib.rocks/image?repo=shadps4-emu/shadPS4&max=24">
|
|
||||||
</a>
|
|
||||||
|
|
||||||
|
|
||||||
# Special Thanks
|
# Special Thanks
|
||||||
|
|
||||||
|
|||||||
10
REUSE.toml
10
REUSE.toml
@@ -5,13 +5,12 @@ path = [
|
|||||||
"REUSE.toml",
|
"REUSE.toml",
|
||||||
"crowdin.yml",
|
"crowdin.yml",
|
||||||
"CMakeSettings.json",
|
"CMakeSettings.json",
|
||||||
|
"CMakeDarwinPresets.json",
|
||||||
"CMakeLinuxPresets.json",
|
"CMakeLinuxPresets.json",
|
||||||
"CMakeWindowsPresets.json",
|
"CMakeWindowsPresets.json",
|
||||||
"CMakePresets.json",
|
"CMakePresets.json",
|
||||||
".github/FUNDING.yml",
|
".github/FUNDING.yml",
|
||||||
".github/shadps4.png",
|
".github/shadps4.png",
|
||||||
".github/workflows/scripts/update_translation.sh",
|
|
||||||
".github/workflows/update_translation.yml",
|
|
||||||
".gitmodules",
|
".gitmodules",
|
||||||
"dist/MacOSBundleInfo.plist.in",
|
"dist/MacOSBundleInfo.plist.in",
|
||||||
"dist/net.shadps4.shadPS4.desktop",
|
"dist/net.shadps4.shadPS4.desktop",
|
||||||
@@ -75,9 +74,7 @@ path = [
|
|||||||
"src/images/trophy.wav",
|
"src/images/trophy.wav",
|
||||||
"src/images/hotkey.png",
|
"src/images/hotkey.png",
|
||||||
"src/images/game_settings.png",
|
"src/images/game_settings.png",
|
||||||
"src/shadps4.qrc",
|
|
||||||
"src/shadps4.rc",
|
"src/shadps4.rc",
|
||||||
"src/qt_gui/translations/update_translation.sh",
|
|
||||||
]
|
]
|
||||||
precedence = "aggregate"
|
precedence = "aggregate"
|
||||||
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
||||||
@@ -133,8 +130,3 @@ SPDX-License-Identifier = "MIT"
|
|||||||
path = "src/video_core/host_shaders/fsr/*"
|
path = "src/video_core/host_shaders/fsr/*"
|
||||||
SPDX-FileCopyrightText = "Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved."
|
SPDX-FileCopyrightText = "Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved."
|
||||||
SPDX-License-Identifier = "MIT"
|
SPDX-License-Identifier = "MIT"
|
||||||
|
|
||||||
[[annotations]]
|
|
||||||
path = "dist/qt.conf"
|
|
||||||
SPDX-FileCopyrightText = "shadPS4 Emulator Project"
|
|
||||||
SPDX-License-Identifier = "GPL-2.0-or-later"
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
# 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()
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
files:
|
|
||||||
- source: /src/qt_gui/translations/en_US.ts
|
|
||||||
translation: /%original_path%/%locale_with_underscore%.ts
|
|
||||||
6
dist/net.shadps4.shadPS4.metainfo.xml
vendored
6
dist/net.shadps4.shadPS4.metainfo.xml
vendored
@@ -37,6 +37,12 @@
|
|||||||
<category translate="no">Game</category>
|
<category translate="no">Game</category>
|
||||||
</categories>
|
</categories>
|
||||||
<releases>
|
<releases>
|
||||||
|
<release version="0.12.5" date="2025-11-07">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.12.5</url>
|
||||||
|
</release>
|
||||||
|
<release version="0.12.0" date="2025-10-31">
|
||||||
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.12.0</url>
|
||||||
|
</release>
|
||||||
<release version="0.11.0" date="2025-09-18">
|
<release version="0.11.0" date="2025-09-18">
|
||||||
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.11.0</url>
|
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.11.0</url>
|
||||||
</release>
|
</release>
|
||||||
|
|||||||
2
dist/qt.conf
vendored
2
dist/qt.conf
vendored
@@ -1,2 +0,0 @@
|
|||||||
[Paths]
|
|
||||||
plugins = "./qtplugins"
|
|
||||||
@@ -11,6 +11,13 @@ This document covers information about debugging, troubleshooting and reporting
|
|||||||
|
|
||||||
This section will guide you through setting up tools for debugging the emulator. This list will likely expand as more tools and platforms receive consistent setups.
|
This section will guide you through setting up tools for debugging the emulator. This list will likely expand as more tools and platforms receive consistent setups.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Linux</summary>
|
||||||
|
|
||||||
|
RenderDoc doesn't work with Wayland, so to use it you have to run the emulator with `SDL_VIDEODRIVER=x11` set.
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Windows and Visual Studio</summary>
|
<summary>Windows and Visual Studio</summary>
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ First and foremost, Clang 18 is the **recommended compiler** as it is used for o
|
|||||||
sudo apt install build-essential clang git cmake libasound2-dev \
|
sudo apt install build-essential clang git cmake libasound2-dev \
|
||||||
libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev \
|
libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev \
|
||||||
libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev \
|
libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev \
|
||||||
qt6-base-dev qt6-tools-dev qt6-multimedia-dev libvulkan-dev \
|
libvulkan-dev vulkan-validationlayers libpng-dev
|
||||||
vulkan-validationlayers libpng-dev
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Fedora
|
#### Fedora
|
||||||
@@ -27,8 +26,6 @@ sudo apt install build-essential clang git cmake libasound2-dev \
|
|||||||
sudo dnf install clang git cmake libatomic alsa-lib-devel \
|
sudo dnf install clang git cmake libatomic alsa-lib-devel \
|
||||||
pipewire-jack-audio-connection-kit-devel openal-soft-devel \
|
pipewire-jack-audio-connection-kit-devel openal-soft-devel \
|
||||||
openssl-devel libevdev-devel libudev-devel libXext-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 libuuid-devel
|
vulkan-devel vulkan-validation-layers libpng-devel libuuid-devel
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -36,8 +33,7 @@ sudo dnf install clang git cmake libatomic alsa-lib-devel \
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo pacman -S base-devel clang git cmake sndio jack2 openal \
|
sudo pacman -S base-devel clang git cmake sndio jack2 openal \
|
||||||
qt6-base qt6-declarative qt6-multimedia qt6-tools sdl2 \
|
sdl2 vulkan-validation-layers libpng
|
||||||
vulkan-validation-layers libpng
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: The `shadps4-git` AUR package is not maintained by any of the developers, and it uses the default compiler, which is often set to GCC. Use at your own discretion.
|
**Note**: The `shadps4-git` AUR package is not maintained by any of the developers, and it uses the default compiler, which is often set to GCC. Use at your own discretion.
|
||||||
@@ -48,9 +44,7 @@ sudo pacman -S base-devel clang git cmake sndio jack2 openal \
|
|||||||
sudo zypper install clang git cmake libasound2 libpulse-devel \
|
sudo zypper install clang git cmake libasound2 libpulse-devel \
|
||||||
libsndio7 libjack-devel openal-soft-devel libopenssl-devel \
|
libsndio7 libjack-devel openal-soft-devel libopenssl-devel \
|
||||||
zlib-devel libedit-devel systemd-devel libevdev-devel \
|
zlib-devel libedit-devel systemd-devel libevdev-devel \
|
||||||
qt6-base-devel qt6-multimedia-devel qt6-svg-devel \
|
vulkan-devel vulkan-validationlayers libpng-devel
|
||||||
qt6-linguist-devel qt6-gui-private-devel vulkan-devel \
|
|
||||||
vulkan-validationlayers libpng-devel
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### NixOS
|
#### NixOS
|
||||||
@@ -90,12 +84,12 @@ There are 3 options you can choose from. Option 1 is **highly recommended**.
|
|||||||
1. Generate the build directory in the shadPS4 directory.
|
1. Generate the build directory in the shadPS4 directory.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmake -S . -B build/ -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
cmake -S . -B build/ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||||
```
|
```
|
||||||
|
|
||||||
To disable the Qt GUI, remove the `-DENABLE_QT_GUI=ON` flag. To change the build type (for debugging), add `-DCMAKE_BUILD_TYPE=Debug`.
|
To change the build type (for debugging), add `-DCMAKE_BUILD_TYPE=Debug`.
|
||||||
|
|
||||||
2. Use CMake to build the project:
|
1. Use CMake to build the project:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cmake --build ./build --parallel$(nproc)
|
cmake --build ./build --parallel$(nproc)
|
||||||
@@ -103,18 +97,12 @@ cmake --build ./build --parallel$(nproc)
|
|||||||
|
|
||||||
If your computer freezes during this step, this could be caused by excessive system resource usage. In that case, remove `--parallel$(nproc)`.
|
If your computer freezes during this step, this could be caused by excessive system resource usage. In that case, remove `--parallel$(nproc)`.
|
||||||
|
|
||||||
Now run the emulator. If Qt was enabled at configure time:
|
Now run the emulator to get the list of options:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./build/shadps4
|
./build/shadps4
|
||||||
```
|
```
|
||||||
|
|
||||||
Otherwise, specify the path to your game's boot file:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./build/shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also specify the Game ID as an argument for which game to boot, as long as the folder containing the games is specified in config.toml (example: Bloodborne (US) is CUSA00900).
|
You can also specify the Game ID as an argument for which game to boot, as long as the folder containing the games is specified in config.toml (example: Bloodborne (US) is CUSA00900).
|
||||||
#### Option 2: Configuring with cmake-gui
|
#### Option 2: Configuring with cmake-gui
|
||||||
|
|
||||||
@@ -142,10 +130,6 @@ Go to Settings, filter by `@ext:ms-vscode.cmake-tools configure` and disable thi
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
If you wish to build with the Qt GUI, add `-DENABLE_QT_GUI=ON` to the configure arguments:
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
On the CMake tab, change the options as you wish, but make sure that it looks similar to or exactly like this:
|
On the CMake tab, change the options as you wish, but make sure that it looks similar to or exactly like this:
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -24,21 +24,6 @@ eval $(/opt/homebrew/bin/brew shellenv)
|
|||||||
brew install clang-format cmake
|
brew install clang-format cmake
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, install x86_64 Qt. You can skip these steps and move on to **Cloning and compiling** if you do not intend to build the Qt GUI.
|
|
||||||
|
|
||||||
**If you are on an ARM Mac:**
|
|
||||||
```
|
|
||||||
# Installs x86_64 Homebrew to /usr/local
|
|
||||||
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
||||||
# Installs libraries.
|
|
||||||
arch -x86_64 /usr/local/bin/brew install qt@6
|
|
||||||
```
|
|
||||||
|
|
||||||
**If you are on an x86_64 Mac:**
|
|
||||||
```
|
|
||||||
brew install qt@6
|
|
||||||
```
|
|
||||||
|
|
||||||
### Cloning and compiling:
|
### Cloning and compiling:
|
||||||
|
|
||||||
Clone the repository recursively:
|
Clone the repository recursively:
|
||||||
@@ -52,8 +37,6 @@ Generate the build directory in the shadPS4 directory:
|
|||||||
cmake -S . -B build/ -DCMAKE_OSX_ARCHITECTURES=x86_64
|
cmake -S . -B build/ -DCMAKE_OSX_ARCHITECTURES=x86_64
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to build the Qt GUI, add `-DENABLE_QT_GUI=ON` to the end of this command as well.
|
|
||||||
|
|
||||||
Enter the directory:
|
Enter the directory:
|
||||||
```
|
```
|
||||||
cd build/
|
cd build/
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<!--
|
<!--
|
||||||
SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project
|
SPDX-FileCopyrightText: 2025 shadPS4 Emulator Project
|
||||||
SPDX-License-Identifier: GPL-2.0-or-later
|
SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
-->
|
-->
|
||||||
|
|
||||||
# Build shadPS4 for Windows
|
# Build shadPS4 for Windows
|
||||||
|
|
||||||
This tutorial reads as if you have none of the prerequisites already installed. If you do, just ignore the steps regarding installation.
|
This tutorial reads as if you have none of the prerequisites already installed. If you do, just ignore the steps regarding installation.
|
||||||
If you are building to contribute to the project, please omit `--depth 1` from the git invocations.
|
> [!WARNING]
|
||||||
|
> If you are trying to compile older builds for testing, do not provide the `--depth 1` flag in `git clone`.
|
||||||
|
> This flag omits the commit history from your clone, saving storage space while preventing you from testing older commits.
|
||||||
|
|
||||||
Note: **ARM64 is not supported!** As of writing, it will not build nor run. The instructions with respect to ARM64 are for developers only.
|
Note: **ARM64 is not supported!** As of writing, it will not build nor run. The instructions with respect to ARM64 are for developers only.
|
||||||
|
|
||||||
@@ -20,23 +22,6 @@ Once you are within the installer:
|
|||||||
2. Go to "Individual Components" tab then search and select both `C++ Clang Compiler for Windows` and `MSBuild support for LLVM`
|
2. Go to "Individual Components" tab then search and select both `C++ Clang Compiler for Windows` and `MSBuild support for LLVM`
|
||||||
3. Continue the installation
|
3. Continue the installation
|
||||||
|
|
||||||
### (Prerequisite) Download [**Qt**](https://doc.qt.io/qt-6/get-and-install-qt.html)
|
|
||||||
|
|
||||||
Beware, this requires you to create a Qt account. If you do not want to do this, please follow the MSYS2/MinGW compilation method instead.
|
|
||||||
|
|
||||||
1. Under the current, non beta version of Qt, select the option `MSVC 2022 64-bit` or similar, as well as `QT Multimedia`.
|
|
||||||
If you are on Windows on ARM / Qualcomm Snapdragon Elite X, select `MSVC 2022 ARM64` instead.
|
|
||||||
|
|
||||||
Go through the installation normally. If you know what you are doing, you may unselect individual components that eat up too much disk space.
|
|
||||||
|
|
||||||
2. Download and install [Qt Visual Studio Tools](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
|
|
||||||
|
|
||||||
Once you are finished, you will have to configure Qt within Visual Studio:
|
|
||||||
|
|
||||||
1. Tools -> Options -> Qt -> Versions
|
|
||||||
2. Add a new Qt version and navigate it to the correct folder. Should look like so: `C:\Qt\<QtVersion>\msvc2022_64`
|
|
||||||
3. Enable the default checkmark on the new version you just created.
|
|
||||||
|
|
||||||
### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win)
|
### (Prerequisite) Download [**Git for Windows**](https://git-scm.com/download/win)
|
||||||
|
|
||||||
Go through the Git for Windows installation as normal
|
Go through the Git for Windows installation as normal
|
||||||
@@ -77,13 +62,10 @@ Normal x86-based computers, follow:
|
|||||||
1. Open "MSYS2 MINGW64" from your new applications
|
1. Open "MSYS2 MINGW64" from your new applications
|
||||||
2. Run `pacman -Syu`, let it complete;
|
2. Run `pacman -Syu`, let it complete;
|
||||||
3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-rapidjson mingw-w64-x86_64-ninja mingw-w64-x86_64-ffmpeg`
|
3. Run `pacman -S --needed git mingw-w64-x86_64-binutils mingw-w64-x86_64-clang mingw-w64-x86_64-cmake mingw-w64-x86_64-rapidjson mingw-w64-x86_64-ninja mingw-w64-x86_64-ffmpeg`
|
||||||
1. Optional (Qt only): run `pacman -S --needed mingw-w64-x86_64-qt6-base mingw-w64-x86_64-qt6-tools mingw-w64-x86_64-qt6-multimedia`
|
|
||||||
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
||||||
5. Run `cd shadPS4`
|
5. Run `cd shadPS4`
|
||||||
6. Run `cmake -S . -B build -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"`
|
6. Run `cmake -S . -B build -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"`
|
||||||
1. Optional (Qt only): add `-DENABLE_QT_GUI=ON`
|
|
||||||
7. Run `cmake --build build`
|
7. Run `cmake --build build`
|
||||||
1. Optional (Qt only): run `windeployqt6 build/shadps4.exe`
|
|
||||||
8. To run the finished product, run `./build/shadPS4.exe`
|
8. To run the finished product, run `./build/shadPS4.exe`
|
||||||
|
|
||||||
ARM64-based computers, follow:
|
ARM64-based computers, follow:
|
||||||
@@ -95,9 +77,7 @@ ARM64-based computers, follow:
|
|||||||
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
4. Run `git clone --depth 1 --recursive https://github.com/shadps4-emu/shadPS4`
|
||||||
5. Run `cd shadPS4`
|
5. Run `cd shadPS4`
|
||||||
6. Run `cmake -S . -B build -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"`
|
6. Run `cmake -S . -B build -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_CXX_FLAGS="-O2 -march=native"`
|
||||||
1. Optional (Qt only): add `-DENABLE_QT_GUI=ON`
|
|
||||||
7. Run `cmake --build build`
|
7. Run `cmake --build build`
|
||||||
1. Optional (Qt only): run `windeployqt6 build/shadps4.exe`
|
|
||||||
8. To run the finished product, run `./build/shadPS4.exe`
|
8. To run the finished product, run `./build/shadPS4.exe`
|
||||||
|
|
||||||
## Note on MSYS2 builds
|
## Note on MSYS2 builds
|
||||||
|
|||||||
11
externals/CMakeLists.txt
vendored
11
externals/CMakeLists.txt
vendored
@@ -231,6 +231,8 @@ if (APPLE)
|
|||||||
|
|
||||||
# MoltenVK
|
# MoltenVK
|
||||||
if (NOT TARGET MoltenVK)
|
if (NOT TARGET MoltenVK)
|
||||||
|
set(MVK_EXCLUDE_SPIRV_TOOLS ON)
|
||||||
|
set(MVK_USE_METAL_PRIVATE_API ON)
|
||||||
add_subdirectory(MoltenVK)
|
add_subdirectory(MoltenVK)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -238,3 +240,12 @@ if (APPLE)
|
|||||||
add_subdirectory(epoll-shim)
|
add_subdirectory(epoll-shim)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
#windows only
|
||||||
|
if (WIN32)
|
||||||
|
add_subdirectory(ext-wepoll)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#nlohmann json
|
||||||
|
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
||||||
|
add_subdirectory(json)
|
||||||
|
|||||||
1
externals/MoltenVK
vendored
Submodule
1
externals/MoltenVK
vendored
Submodule
Submodule externals/MoltenVK added at b23d425346
93
externals/MoltenVK/CMakeLists.txt
vendored
93
externals/MoltenVK/CMakeLists.txt
vendored
@@ -1,93 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
# Prepare MoltenVK Git revision
|
|
||||||
find_package(Git)
|
|
||||||
if(GIT_FOUND)
|
|
||||||
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
|
|
||||||
OUTPUT_VARIABLE MVK_GIT_REV
|
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK
|
|
||||||
ERROR_QUIET
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
|
||||||
endif()
|
|
||||||
set(MVK_GENERATED_INCLUDES ${CMAKE_CURRENT_BINARY_DIR}/Generated)
|
|
||||||
file(WRITE ${MVK_GENERATED_INCLUDES}/mvkGitRevDerived.h "static const char* mvkRevString = \"${MVK_GIT_REV}\";")
|
|
||||||
message(STATUS "MoltenVK revision: ${MVK_GIT_REV}")
|
|
||||||
|
|
||||||
# Prepare MoltenVK version
|
|
||||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/MoltenVK/MoltenVK/API/mvk_private_api.h MVK_PRIVATE_API)
|
|
||||||
string(REGEX MATCH "#define MVK_VERSION_MAJOR [0-9]+" MVK_VERSION_MAJOR_LINE "${MVK_PRIVATE_API}")
|
|
||||||
string(REGEX MATCH "[0-9]+" MVK_VERSION_MAJOR "${MVK_VERSION_MAJOR_LINE}")
|
|
||||||
string(REGEX MATCH "#define MVK_VERSION_MINOR [0-9]+" MVK_VERSION_MINOR_LINE "${MVK_PRIVATE_API}")
|
|
||||||
string(REGEX MATCH "[0-9]+" MVK_VERSION_MINOR "${MVK_VERSION_MINOR_LINE}")
|
|
||||||
string(REGEX MATCH "#define MVK_VERSION_PATCH [0-9]+" MVK_VERSION_PATCH_LINE "${MVK_PRIVATE_API}")
|
|
||||||
string(REGEX MATCH "[0-9]+" MVK_VERSION_PATCH "${MVK_VERSION_PATCH_LINE}")
|
|
||||||
set(MVK_VERSION "${MVK_VERSION_MAJOR}.${MVK_VERSION_MINOR}.${MVK_VERSION_PATCH}")
|
|
||||||
message(STATUS "MoltenVK version: ${MVK_VERSION}")
|
|
||||||
|
|
||||||
# Find required system libraries
|
|
||||||
find_library(APPKIT_LIBRARY AppKit REQUIRED)
|
|
||||||
find_library(FOUNDATION_LIBRARY Foundation REQUIRED)
|
|
||||||
find_library(IOKIT_LIBRARY IOKit REQUIRED)
|
|
||||||
find_library(IOSURFACE_LIBRARY IOSurface REQUIRED)
|
|
||||||
find_library(METAL_LIBRARY Metal REQUIRED)
|
|
||||||
find_library(QUARTZCORE_LIBRARY QuartzCore REQUIRED)
|
|
||||||
|
|
||||||
# cereal
|
|
||||||
option(SKIP_PORTABILITY_TEST "" ON)
|
|
||||||
option(BUILD_DOC "" OFF)
|
|
||||||
option(BUILD_SANDBOX "" OFF)
|
|
||||||
option(SKIP_PERFORMANCE_COMPARISON "" ON)
|
|
||||||
option(SPIRV_CROSS_SKIP_INSTALL "" ON)
|
|
||||||
add_subdirectory(cereal)
|
|
||||||
|
|
||||||
# SPIRV-Cross
|
|
||||||
option(SPIRV_CROSS_CLI "" OFF)
|
|
||||||
option(SPIRV_CROSS_ENABLE_TESTS "" OFF)
|
|
||||||
option(SPIRV_CROSS_ENABLE_HLSL "" OFF)
|
|
||||||
option(SPIRV_CROSS_ENABLE_CPP "" OFF)
|
|
||||||
option(SPIRV_CROSS_SKIP_INSTALL "" ON)
|
|
||||||
add_subdirectory(SPIRV-Cross)
|
|
||||||
|
|
||||||
# Common
|
|
||||||
set(MVK_COMMON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/Common)
|
|
||||||
file(GLOB_RECURSE MVK_COMMON_SOURCES CONFIGURE_DEPENDS
|
|
||||||
${MVK_COMMON_DIR}/*.cpp
|
|
||||||
${MVK_COMMON_DIR}/*.m
|
|
||||||
${MVK_COMMON_DIR}/*.mm)
|
|
||||||
set(MVK_COMMON_INCLUDES ${MVK_COMMON_DIR})
|
|
||||||
|
|
||||||
add_library(MoltenVKCommon STATIC ${MVK_COMMON_SOURCES})
|
|
||||||
target_include_directories(MoltenVKCommon PUBLIC ${MVK_COMMON_INCLUDES})
|
|
||||||
target_compile_options(MoltenVKCommon PRIVATE -w)
|
|
||||||
|
|
||||||
# MoltenVKShaderConverter
|
|
||||||
set(MVK_SHADER_CONVERTER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/MoltenVKShaderConverter)
|
|
||||||
file(GLOB_RECURSE MVK_SHADER_CONVERTER_SOURCES CONFIGURE_DEPENDS
|
|
||||||
${MVK_SHADER_CONVERTER_DIR}/MoltenVKShaderConverter/*.cpp
|
|
||||||
${MVK_SHADER_CONVERTER_DIR}/MoltenVKShaderConverter/*.m
|
|
||||||
${MVK_SHADER_CONVERTER_DIR}/MoltenVKShaderConverter/*.mm)
|
|
||||||
set(MVK_SHADER_CONVERTER_INCLUDES ${MVK_SHADER_CONVERTER_DIR} ${MVK_SHADER_CONVERTER_DIR}/include)
|
|
||||||
|
|
||||||
add_library(MoltenVKShaderConverter STATIC ${MVK_SHADER_CONVERTER_SOURCES})
|
|
||||||
target_include_directories(MoltenVKShaderConverter PUBLIC ${MVK_SHADER_CONVERTER_INCLUDES})
|
|
||||||
target_compile_options(MoltenVKShaderConverter PRIVATE -w)
|
|
||||||
target_link_libraries(MoltenVKShaderConverter PRIVATE spirv-cross-msl spirv-cross-reflect MoltenVKCommon)
|
|
||||||
target_compile_definitions(MoltenVKShaderConverter PRIVATE MVK_EXCLUDE_SPIRV_TOOLS=1)
|
|
||||||
|
|
||||||
# MoltenVK
|
|
||||||
set(MVK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK/MoltenVK)
|
|
||||||
file(GLOB_RECURSE MVK_SOURCES CONFIGURE_DEPENDS
|
|
||||||
${MVK_DIR}/MoltenVK/*.cpp
|
|
||||||
${MVK_DIR}/MoltenVK/*.m
|
|
||||||
${MVK_DIR}/MoltenVK/*.mm)
|
|
||||||
file(GLOB MVK_SRC_INCLUDES LIST_DIRECTORIES ON ${MVK_DIR}/MoltenVK/*)
|
|
||||||
set(MVK_INCLUDES ${MVK_SRC_INCLUDES} ${MVK_GENERATED_INCLUDES} ${MVK_DIR}/include)
|
|
||||||
|
|
||||||
add_library(MoltenVK SHARED ${MVK_SOURCES})
|
|
||||||
target_include_directories(MoltenVK PRIVATE ${MVK_INCLUDES})
|
|
||||||
target_compile_options(MoltenVK PRIVATE -w)
|
|
||||||
target_link_libraries(MoltenVK PRIVATE
|
|
||||||
${APPKIT_LIBRARY} ${FOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${IOSURFACE_LIBRARY} ${METAL_LIBRARY} ${QUARTZCORE_LIBRARY}
|
|
||||||
Vulkan::Headers cereal::cereal spirv-cross-msl MoltenVKCommon MoltenVKShaderConverter)
|
|
||||||
target_compile_definitions(MoltenVK PRIVATE MVK_FRAMEWORK_VERSION=${MVK_VERSION} MVK_USE_METAL_PRIVATE_API=1)
|
|
||||||
1
externals/MoltenVK/MoltenVK
vendored
1
externals/MoltenVK/MoltenVK
vendored
Submodule externals/MoltenVK/MoltenVK deleted from 712fbb808d
1
externals/MoltenVK/SPIRV-Cross
vendored
1
externals/MoltenVK/SPIRV-Cross
vendored
Submodule externals/MoltenVK/SPIRV-Cross deleted from 0a88b2d5c0
1
externals/MoltenVK/cereal
vendored
1
externals/MoltenVK/cereal
vendored
Submodule externals/MoltenVK/cereal deleted from a56bad8bbb
1
externals/ext-wepoll
vendored
Submodule
1
externals/ext-wepoll
vendored
Submodule
Submodule externals/ext-wepoll added at d3bb810353
1
externals/json
vendored
Submodule
1
externals/json
vendored
Submodule
Submodule externals/json added at 55f93686c0
2
externals/vulkan-headers
vendored
2
externals/vulkan-headers
vendored
Submodule externals/vulkan-headers updated: a01329f307...33d7f51258
@@ -17,7 +17,6 @@ pkgs.mkShell {
|
|||||||
pkgs.alsa-lib
|
pkgs.alsa-lib
|
||||||
pkgs.libpulseaudio
|
pkgs.libpulseaudio
|
||||||
pkgs.openal
|
pkgs.openal
|
||||||
pkgs.openssl
|
|
||||||
pkgs.zlib
|
pkgs.zlib
|
||||||
pkgs.libedit
|
pkgs.libedit
|
||||||
pkgs.udev
|
pkgs.udev
|
||||||
@@ -25,9 +24,6 @@ pkgs.mkShell {
|
|||||||
pkgs.SDL2
|
pkgs.SDL2
|
||||||
pkgs.jack2
|
pkgs.jack2
|
||||||
pkgs.sndio
|
pkgs.sndio
|
||||||
pkgs.qt6.qtbase
|
|
||||||
pkgs.qt6.qttools
|
|
||||||
pkgs.qt6.qtmultimedia
|
|
||||||
|
|
||||||
pkgs.vulkan-headers
|
pkgs.vulkan-headers
|
||||||
pkgs.vulkan-utility-libraries
|
pkgs.vulkan-utility-libraries
|
||||||
@@ -44,16 +40,12 @@ pkgs.mkShell {
|
|||||||
pkgs.xorg.xcbutilwm
|
pkgs.xorg.xcbutilwm
|
||||||
pkgs.sdl3
|
pkgs.sdl3
|
||||||
pkgs.stb
|
pkgs.stb
|
||||||
pkgs.qt6.qtwayland
|
|
||||||
pkgs.wayland-protocols
|
pkgs.wayland-protocols
|
||||||
pkgs.libpng
|
pkgs.libpng
|
||||||
];
|
];
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
echo "Entering shadPS4 dev shell"
|
echo "Entering shadPS4 dev shell"
|
||||||
export QT_QPA_PLATFORM="wayland"
|
|
||||||
export QT_PLUGIN_PATH="${pkgs.qt6.qtwayland}/lib/qt-6/plugins:${pkgs.qt6.qtbase}/lib/qt-6/plugins"
|
|
||||||
export QML2_IMPORT_PATH="${pkgs.qt6.qtbase}/lib/qt-6/qml"
|
|
||||||
export CMAKE_PREFIX_PATH="${pkgs.vulkan-headers}:$CMAKE_PREFIX_PATH"
|
export CMAKE_PREFIX_PATH="${pkgs.vulkan-headers}:$CMAKE_PREFIX_PATH"
|
||||||
|
|
||||||
# OpenGL
|
# OpenGL
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <fmt/xchar.h> // for wstring support
|
#include <fmt/xchar.h> // for wstring support
|
||||||
#include <toml.hpp>
|
#include <toml.hpp>
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
#include "common/logging/formatter.h"
|
#include "common/logging/formatter.h"
|
||||||
#include "common/path_util.h"
|
#include "common/path_util.h"
|
||||||
@@ -74,18 +75,34 @@ std::optional<T> get_optional(const toml::value& v, const std::string& key) {
|
|||||||
|
|
||||||
namespace Config {
|
namespace Config {
|
||||||
|
|
||||||
|
ConfigMode config_mode = ConfigMode::Default;
|
||||||
|
|
||||||
|
void setConfigMode(ConfigMode mode) {
|
||||||
|
config_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ConfigEntry {
|
class ConfigEntry {
|
||||||
public:
|
public:
|
||||||
|
const T default_value;
|
||||||
T base_value;
|
T base_value;
|
||||||
optional<T> game_specific_value;
|
optional<T> game_specific_value;
|
||||||
ConfigEntry(const T& t = T()) : base_value(t), game_specific_value(nullopt) {}
|
ConfigEntry(const T& t = T()) : default_value(t), base_value(t), game_specific_value(nullopt) {}
|
||||||
ConfigEntry operator=(const T& t) {
|
ConfigEntry operator=(const T& t) {
|
||||||
base_value = t;
|
base_value = t;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
const T get() const {
|
const T get() const {
|
||||||
return game_specific_value.has_value() ? *game_specific_value : base_value;
|
switch (config_mode) {
|
||||||
|
case ConfigMode::Default:
|
||||||
|
return game_specific_value.value_or(base_value);
|
||||||
|
case ConfigMode::Global:
|
||||||
|
return base_value;
|
||||||
|
case ConfigMode::Clean:
|
||||||
|
return default_value;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void setFromToml(const toml::value& v, const std::string& key, bool is_game_specific = false) {
|
void setFromToml(const toml::value& v, const std::string& key, bool is_game_specific = false) {
|
||||||
if (is_game_specific) {
|
if (is_game_specific) {
|
||||||
@@ -115,19 +132,18 @@ public:
|
|||||||
static ConfigEntry<int> volumeSlider(100);
|
static ConfigEntry<int> volumeSlider(100);
|
||||||
static ConfigEntry<bool> isNeo(false);
|
static ConfigEntry<bool> isNeo(false);
|
||||||
static ConfigEntry<bool> isDevKit(false);
|
static ConfigEntry<bool> isDevKit(false);
|
||||||
|
static ConfigEntry<int> extraDmemInMbytes(0);
|
||||||
static ConfigEntry<bool> isPSNSignedIn(false);
|
static ConfigEntry<bool> isPSNSignedIn(false);
|
||||||
static ConfigEntry<bool> isTrophyPopupDisabled(false);
|
static ConfigEntry<bool> isTrophyPopupDisabled(false);
|
||||||
static ConfigEntry<double> trophyNotificationDuration(6.0);
|
static ConfigEntry<double> trophyNotificationDuration(6.0);
|
||||||
static ConfigEntry<string> logFilter("");
|
static ConfigEntry<string> logFilter("");
|
||||||
static ConfigEntry<string> logType("sync");
|
static ConfigEntry<string> logType("sync");
|
||||||
static ConfigEntry<string> userName("shadPS4");
|
static ConfigEntry<string> userName("shadPS4");
|
||||||
static ConfigEntry<string> chooseHomeTab("General");
|
|
||||||
static ConfigEntry<bool> isShowSplash(false);
|
static ConfigEntry<bool> isShowSplash(false);
|
||||||
static ConfigEntry<string> isSideTrophy("right");
|
static ConfigEntry<string> isSideTrophy("right");
|
||||||
static ConfigEntry<bool> isConnectedToNetwork(false);
|
static ConfigEntry<bool> isConnectedToNetwork(false);
|
||||||
static bool enableDiscordRPC = false;
|
static bool enableDiscordRPC = false;
|
||||||
static bool checkCompatibilityOnStartup = false;
|
static std::filesystem::path sys_modules_path = {};
|
||||||
static bool compatibilityData = false;
|
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
static ConfigEntry<int> cursorState(HideCursorState::Idle);
|
static ConfigEntry<int> cursorState(HideCursorState::Idle);
|
||||||
@@ -168,6 +184,7 @@ static ConfigEntry<int> rcasAttenuation(250);
|
|||||||
// Vulkan
|
// Vulkan
|
||||||
static ConfigEntry<s32> gpuId(-1);
|
static ConfigEntry<s32> gpuId(-1);
|
||||||
static ConfigEntry<bool> vkValidation(false);
|
static ConfigEntry<bool> vkValidation(false);
|
||||||
|
static ConfigEntry<bool> vkValidationCore(true);
|
||||||
static ConfigEntry<bool> vkValidationSync(false);
|
static ConfigEntry<bool> vkValidationSync(false);
|
||||||
static ConfigEntry<bool> vkValidationGpu(false);
|
static ConfigEntry<bool> vkValidationGpu(false);
|
||||||
static ConfigEntry<bool> vkCrashDiagnostic(false);
|
static ConfigEntry<bool> vkCrashDiagnostic(false);
|
||||||
@@ -183,7 +200,6 @@ static ConfigEntry<bool> isFpsColor(true);
|
|||||||
static ConfigEntry<bool> logEnabled(true);
|
static ConfigEntry<bool> logEnabled(true);
|
||||||
|
|
||||||
// GUI
|
// GUI
|
||||||
static bool load_game_size = true;
|
|
||||||
static std::vector<GameInstallDir> settings_install_dirs = {};
|
static std::vector<GameInstallDir> settings_install_dirs = {};
|
||||||
std::vector<bool> install_dirs_enabled = {};
|
std::vector<bool> install_dirs_enabled = {};
|
||||||
std::filesystem::path settings_addon_install_dir = {};
|
std::filesystem::path settings_addon_install_dir = {};
|
||||||
@@ -192,15 +208,39 @@ std::filesystem::path save_data_path = {};
|
|||||||
// Settings
|
// Settings
|
||||||
ConfigEntry<u32> m_language(1); // english
|
ConfigEntry<u32> m_language(1); // english
|
||||||
|
|
||||||
|
// USB Device
|
||||||
|
static ConfigEntry<int> usbDeviceBackend(UsbBackendType::Real);
|
||||||
|
|
||||||
// Keys
|
// Keys
|
||||||
static string trophyKey = "";
|
static string trophyKey = "";
|
||||||
|
|
||||||
// Config version, used to determine if a user's config file is outdated.
|
// Config version, used to determine if a user's config file is outdated.
|
||||||
static string config_version = Common::g_scm_rev;
|
static string config_version = Common::g_scm_rev;
|
||||||
|
|
||||||
// These two entries aren't stored in the config
|
// These entries aren't stored in the config
|
||||||
static bool overrideControllerColor = false;
|
static bool overrideControllerColor = false;
|
||||||
static int controllerCustomColorRGB[3] = {0, 0, 255};
|
static int controllerCustomColorRGB[3] = {0, 0, 255};
|
||||||
|
static bool isGameRunning = false;
|
||||||
|
static bool load_auto_patches = true;
|
||||||
|
|
||||||
|
bool getGameRunning() {
|
||||||
|
return isGameRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setGameRunning(bool running) {
|
||||||
|
isGameRunning = running;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::filesystem::path getSysModulesPath() {
|
||||||
|
if (sys_modules_path.empty()) {
|
||||||
|
return Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
||||||
|
}
|
||||||
|
return sys_modules_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSysModulesPath(const std::filesystem::path& path) {
|
||||||
|
sys_modules_path = path;
|
||||||
|
}
|
||||||
|
|
||||||
int getVolumeSlider() {
|
int getVolumeSlider() {
|
||||||
return volumeSlider.get();
|
return volumeSlider.get();
|
||||||
@@ -247,10 +287,6 @@ void setTrophyKey(string key) {
|
|||||||
trophyKey = key;
|
trophyKey = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetLoadGameSizeEnabled() {
|
|
||||||
return load_game_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::path GetSaveDataPath() {
|
std::filesystem::path GetSaveDataPath() {
|
||||||
if (save_data_path.empty()) {
|
if (save_data_path.empty()) {
|
||||||
return Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "savedata";
|
return Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "savedata";
|
||||||
@@ -262,10 +298,6 @@ void setVolumeSlider(int volumeValue, bool is_game_specific) {
|
|||||||
volumeSlider.set(volumeValue, is_game_specific);
|
volumeSlider.set(volumeValue, is_game_specific);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLoadGameSizeEnabled(bool enable) {
|
|
||||||
load_game_size = enable;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isNeoModeConsole() {
|
bool isNeoModeConsole() {
|
||||||
return isNeo.get();
|
return isNeo.get();
|
||||||
}
|
}
|
||||||
@@ -274,6 +306,16 @@ bool isDevKitConsole() {
|
|||||||
return isDevKit.get();
|
return isDevKit.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getExtraDmemInMbytes() {
|
||||||
|
return extraDmemInMbytes.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setExtraDmemInMbytes(int value, bool is_game_specific) {
|
||||||
|
// Disable setting in global config
|
||||||
|
is_game_specific ? extraDmemInMbytes.game_specific_value = value
|
||||||
|
: extraDmemInMbytes.base_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool getIsFullscreen() {
|
bool getIsFullscreen() {
|
||||||
return isFullscreen.get();
|
return isFullscreen.get();
|
||||||
}
|
}
|
||||||
@@ -350,10 +392,6 @@ string getUserName() {
|
|||||||
return userName.get();
|
return userName.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
string getChooseHomeTab() {
|
|
||||||
return chooseHomeTab.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getUseSpecialPad() {
|
bool getUseSpecialPad() {
|
||||||
return useSpecialPad.get();
|
return useSpecialPad.get();
|
||||||
}
|
}
|
||||||
@@ -433,6 +471,10 @@ bool vkValidationEnabled() {
|
|||||||
return vkValidation.get();
|
return vkValidation.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vkValidationCoreEnabled() {
|
||||||
|
return vkValidationCore.get();
|
||||||
|
}
|
||||||
|
|
||||||
bool vkValidationSyncEnabled() {
|
bool vkValidationSyncEnabled() {
|
||||||
return vkValidationSync.get();
|
return vkValidationSync.get();
|
||||||
}
|
}
|
||||||
@@ -465,14 +507,6 @@ void setVkGuestMarkersEnabled(bool enable, bool is_game_specific) {
|
|||||||
vkGuestMarkers.set(enable, is_game_specific);
|
vkGuestMarkers.set(enable, is_game_specific);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool getCompatibilityEnabled() {
|
|
||||||
return compatibilityData;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getCheckCompatibilityOnStartup() {
|
|
||||||
return checkCompatibilityOnStartup;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool getIsConnectedToNetwork() {
|
bool getIsConnectedToNetwork() {
|
||||||
return isConnectedToNetwork.get();
|
return isConnectedToNetwork.get();
|
||||||
}
|
}
|
||||||
@@ -557,6 +591,14 @@ void setVkSyncValidation(bool enable, bool is_game_specific) {
|
|||||||
vkValidationSync.set(enable, is_game_specific);
|
vkValidationSync.set(enable, is_game_specific);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setVkCoreValidation(bool enable, bool is_game_specific) {
|
||||||
|
vkValidationCore.set(enable, is_game_specific);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setVkGpuValidation(bool enable, bool is_game_specific) {
|
||||||
|
vkValidationGpu.set(enable, is_game_specific);
|
||||||
|
}
|
||||||
|
|
||||||
void setRdocEnabled(bool enable, bool is_game_specific) {
|
void setRdocEnabled(bool enable, bool is_game_specific) {
|
||||||
rdocEnable.set(enable, is_game_specific);
|
rdocEnable.set(enable, is_game_specific);
|
||||||
}
|
}
|
||||||
@@ -637,10 +679,6 @@ void setUserName(const string& name, bool is_game_specific) {
|
|||||||
userName.set(name, is_game_specific);
|
userName.set(name, is_game_specific);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setChooseHomeTab(const string& type, bool is_game_specific) {
|
|
||||||
chooseHomeTab.set(type, is_game_specific);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setUseSpecialPad(bool use) {
|
void setUseSpecialPad(bool use) {
|
||||||
useSpecialPad.base_value = use;
|
useSpecialPad.base_value = use;
|
||||||
}
|
}
|
||||||
@@ -653,14 +691,6 @@ void setIsMotionControlsEnabled(bool use, bool is_game_specific) {
|
|||||||
isMotionControlsEnabled.set(use, is_game_specific);
|
isMotionControlsEnabled.set(use, is_game_specific);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCompatibilityEnabled(bool use) {
|
|
||||||
compatibilityData = use;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCheckCompatibilityOnStartup(bool use) {
|
|
||||||
checkCompatibilityOnStartup = use;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled) {
|
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled) {
|
||||||
for (const auto& install_dir : settings_install_dirs) {
|
for (const auto& install_dir : settings_install_dirs) {
|
||||||
if (install_dir.path == dir) {
|
if (install_dir.path == dir) {
|
||||||
@@ -790,6 +820,21 @@ void setRcasAttenuation(int value, bool is_game_specific) {
|
|||||||
rcasAttenuation.set(value, is_game_specific);
|
rcasAttenuation.set(value, is_game_specific);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getUsbDeviceBackend() {
|
||||||
|
return usbDeviceBackend.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setUsbDeviceBackend(int value, bool is_game_specific) {
|
||||||
|
usbDeviceBackend.set(value, is_game_specific);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getLoadAutoPatches() {
|
||||||
|
return load_auto_patches;
|
||||||
|
}
|
||||||
|
void setLoadAutoPatches(bool enable) {
|
||||||
|
load_auto_patches = enable;
|
||||||
|
}
|
||||||
|
|
||||||
void load(const std::filesystem::path& path, bool is_game_specific) {
|
void load(const std::filesystem::path& path, bool is_game_specific) {
|
||||||
// If the configuration file does not exist, create it and return, unless it is game specific
|
// If the configuration file does not exist, create it and return, unless it is game specific
|
||||||
std::error_code error;
|
std::error_code error;
|
||||||
@@ -818,6 +863,9 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
volumeSlider.setFromToml(general, "volumeSlider", is_game_specific);
|
volumeSlider.setFromToml(general, "volumeSlider", is_game_specific);
|
||||||
isNeo.setFromToml(general, "isPS4Pro", is_game_specific);
|
isNeo.setFromToml(general, "isPS4Pro", is_game_specific);
|
||||||
isDevKit.setFromToml(general, "isDevKit", is_game_specific);
|
isDevKit.setFromToml(general, "isDevKit", is_game_specific);
|
||||||
|
if (is_game_specific) { // do not get this value from the base config
|
||||||
|
extraDmemInMbytes.setFromToml(general, "extraDmemInMbytes", is_game_specific);
|
||||||
|
}
|
||||||
isPSNSignedIn.setFromToml(general, "isPSNSignedIn", is_game_specific);
|
isPSNSignedIn.setFromToml(general, "isPSNSignedIn", is_game_specific);
|
||||||
isTrophyPopupDisabled.setFromToml(general, "isTrophyPopupDisabled", is_game_specific);
|
isTrophyPopupDisabled.setFromToml(general, "isTrophyPopupDisabled", is_game_specific);
|
||||||
trophyNotificationDuration.setFromToml(general, "trophyNotificationDuration",
|
trophyNotificationDuration.setFromToml(general, "trophyNotificationDuration",
|
||||||
@@ -828,13 +876,10 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
userName.setFromToml(general, "userName", is_game_specific);
|
userName.setFromToml(general, "userName", is_game_specific);
|
||||||
isShowSplash.setFromToml(general, "showSplash", is_game_specific);
|
isShowSplash.setFromToml(general, "showSplash", is_game_specific);
|
||||||
isSideTrophy.setFromToml(general, "sideTrophy", is_game_specific);
|
isSideTrophy.setFromToml(general, "sideTrophy", is_game_specific);
|
||||||
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", compatibilityData);
|
|
||||||
checkCompatibilityOnStartup = toml::find_or<bool>(general, "checkCompatibilityOnStartup",
|
|
||||||
checkCompatibilityOnStartup);
|
|
||||||
|
|
||||||
isConnectedToNetwork.setFromToml(general, "isConnectedToNetwork", is_game_specific);
|
isConnectedToNetwork.setFromToml(general, "isConnectedToNetwork", is_game_specific);
|
||||||
chooseHomeTab.setFromToml(general, "chooseHomeTab", is_game_specific);
|
|
||||||
defaultControllerID.setFromToml(general, "defaultControllerID", is_game_specific);
|
defaultControllerID.setFromToml(general, "defaultControllerID", is_game_specific);
|
||||||
|
sys_modules_path = toml::find_fs_path_or(general, "sysModulesPath", sys_modules_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.contains("Input")) {
|
if (data.contains("Input")) {
|
||||||
@@ -847,6 +892,7 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
isMotionControlsEnabled.setFromToml(input, "isMotionControlsEnabled", is_game_specific);
|
isMotionControlsEnabled.setFromToml(input, "isMotionControlsEnabled", is_game_specific);
|
||||||
useUnifiedInputConfig.setFromToml(input, "useUnifiedInputConfig", is_game_specific);
|
useUnifiedInputConfig.setFromToml(input, "useUnifiedInputConfig", is_game_specific);
|
||||||
backgroundControllerInput.setFromToml(input, "backgroundControllerInput", is_game_specific);
|
backgroundControllerInput.setFromToml(input, "backgroundControllerInput", is_game_specific);
|
||||||
|
usbDeviceBackend.setFromToml(input, "usbDeviceBackend", is_game_specific);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.contains("Audio")) {
|
if (data.contains("Audio")) {
|
||||||
@@ -886,6 +932,7 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
|
|
||||||
gpuId.setFromToml(vk, "gpuId", is_game_specific);
|
gpuId.setFromToml(vk, "gpuId", is_game_specific);
|
||||||
vkValidation.setFromToml(vk, "validation", is_game_specific);
|
vkValidation.setFromToml(vk, "validation", is_game_specific);
|
||||||
|
vkValidationCore.setFromToml(vk, "validation_core", is_game_specific);
|
||||||
vkValidationSync.setFromToml(vk, "validation_sync", is_game_specific);
|
vkValidationSync.setFromToml(vk, "validation_sync", is_game_specific);
|
||||||
vkValidationGpu.setFromToml(vk, "validation_gpu", is_game_specific);
|
vkValidationGpu.setFromToml(vk, "validation_gpu", is_game_specific);
|
||||||
vkCrashDiagnostic.setFromToml(vk, "crashDiagnostic", is_game_specific);
|
vkCrashDiagnostic.setFromToml(vk, "crashDiagnostic", is_game_specific);
|
||||||
@@ -909,8 +956,6 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
if (data.contains("GUI")) {
|
if (data.contains("GUI")) {
|
||||||
const toml::value& gui = data.at("GUI");
|
const toml::value& gui = data.at("GUI");
|
||||||
|
|
||||||
load_game_size = toml::find_or<bool>(gui, "loadGameSizeEnabled", load_game_size);
|
|
||||||
|
|
||||||
const auto install_dir_array =
|
const auto install_dir_array =
|
||||||
toml::find_or<std::vector<std::u8string>>(gui, "installDirs", {});
|
toml::find_or<std::vector<std::u8string>>(gui, "installDirs", {});
|
||||||
|
|
||||||
@@ -955,8 +1000,8 @@ void load(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
|
|
||||||
void sortTomlSections(toml::ordered_value& data) {
|
void sortTomlSections(toml::ordered_value& data) {
|
||||||
toml::ordered_value ordered_data;
|
toml::ordered_value ordered_data;
|
||||||
std::vector<string> section_order = {"General", "Input", "GPU", "Vulkan",
|
std::vector<string> section_order = {"General", "Input", "Audio", "GPU", "Vulkan",
|
||||||
"Debug", "Keys", "GUI", "Settings"};
|
"Debug", "Keys", "GUI", "Settings"};
|
||||||
|
|
||||||
for (const auto& section : section_order) {
|
for (const auto& section : section_order) {
|
||||||
if (data.contains(section)) {
|
if (data.contains(section)) {
|
||||||
@@ -1014,11 +1059,13 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
logFilter.setTomlValue(data, "General", "logFilter", is_game_specific);
|
logFilter.setTomlValue(data, "General", "logFilter", is_game_specific);
|
||||||
logType.setTomlValue(data, "General", "logType", is_game_specific);
|
logType.setTomlValue(data, "General", "logType", is_game_specific);
|
||||||
userName.setTomlValue(data, "General", "userName", is_game_specific);
|
userName.setTomlValue(data, "General", "userName", is_game_specific);
|
||||||
chooseHomeTab.setTomlValue(data, "General", "chooseHomeTab", is_game_specific);
|
|
||||||
isShowSplash.setTomlValue(data, "General", "showSplash", is_game_specific);
|
isShowSplash.setTomlValue(data, "General", "showSplash", is_game_specific);
|
||||||
isSideTrophy.setTomlValue(data, "General", "sideTrophy", is_game_specific);
|
isSideTrophy.setTomlValue(data, "General", "sideTrophy", is_game_specific);
|
||||||
isNeo.setTomlValue(data, "General", "isPS4Pro", is_game_specific);
|
isNeo.setTomlValue(data, "General", "isPS4Pro", is_game_specific);
|
||||||
isDevKit.setTomlValue(data, "General", "isDevKit", is_game_specific);
|
isDevKit.setTomlValue(data, "General", "isDevKit", is_game_specific);
|
||||||
|
if (is_game_specific) {
|
||||||
|
extraDmemInMbytes.setTomlValue(data, "General", "extraDmemInMbytes", is_game_specific);
|
||||||
|
}
|
||||||
isPSNSignedIn.setTomlValue(data, "General", "isPSNSignedIn", is_game_specific);
|
isPSNSignedIn.setTomlValue(data, "General", "isPSNSignedIn", is_game_specific);
|
||||||
isConnectedToNetwork.setTomlValue(data, "General", "isConnectedToNetwork", is_game_specific);
|
isConnectedToNetwork.setTomlValue(data, "General", "isConnectedToNetwork", is_game_specific);
|
||||||
|
|
||||||
@@ -1028,6 +1075,7 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
is_game_specific);
|
is_game_specific);
|
||||||
backgroundControllerInput.setTomlValue(data, "Input", "backgroundControllerInput",
|
backgroundControllerInput.setTomlValue(data, "Input", "backgroundControllerInput",
|
||||||
is_game_specific);
|
is_game_specific);
|
||||||
|
usbDeviceBackend.setTomlValue(data, "Input", "usbDeviceBackend", is_game_specific);
|
||||||
|
|
||||||
micDevice.setTomlValue(data, "Audio", "micDevice", is_game_specific);
|
micDevice.setTomlValue(data, "Audio", "micDevice", is_game_specific);
|
||||||
mainOutputDevice.setTomlValue(data, "Audio", "mainOutputDevice", is_game_specific);
|
mainOutputDevice.setTomlValue(data, "Audio", "mainOutputDevice", is_game_specific);
|
||||||
@@ -1053,6 +1101,8 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
gpuId.setTomlValue(data, "Vulkan", "gpuId", is_game_specific);
|
gpuId.setTomlValue(data, "Vulkan", "gpuId", is_game_specific);
|
||||||
vkValidation.setTomlValue(data, "Vulkan", "validation", is_game_specific);
|
vkValidation.setTomlValue(data, "Vulkan", "validation", is_game_specific);
|
||||||
vkValidationSync.setTomlValue(data, "Vulkan", "validation_sync", is_game_specific);
|
vkValidationSync.setTomlValue(data, "Vulkan", "validation_sync", is_game_specific);
|
||||||
|
vkValidationCore.setTomlValue(data, "Vulkan", "validation_core", is_game_specific);
|
||||||
|
vkValidationGpu.setTomlValue(data, "Vulkan", "validation_gpu", is_game_specific);
|
||||||
vkCrashDiagnostic.setTomlValue(data, "Vulkan", "crashDiagnostic", is_game_specific);
|
vkCrashDiagnostic.setTomlValue(data, "Vulkan", "crashDiagnostic", is_game_specific);
|
||||||
vkHostMarkers.setTomlValue(data, "Vulkan", "hostMarkers", is_game_specific);
|
vkHostMarkers.setTomlValue(data, "Vulkan", "hostMarkers", is_game_specific);
|
||||||
vkGuestMarkers.setTomlValue(data, "Vulkan", "guestMarkers", is_game_specific);
|
vkGuestMarkers.setTomlValue(data, "Vulkan", "guestMarkers", is_game_specific);
|
||||||
@@ -1098,12 +1148,10 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
|
|
||||||
// Non game-specific entries
|
// Non game-specific entries
|
||||||
data["General"]["enableDiscordRPC"] = enableDiscordRPC;
|
data["General"]["enableDiscordRPC"] = enableDiscordRPC;
|
||||||
data["General"]["compatibilityEnabled"] = compatibilityData;
|
data["General"]["sysModulesPath"] = string{fmt::UTF(sys_modules_path.u8string()).data};
|
||||||
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
|
|
||||||
data["GUI"]["installDirs"] = install_dirs;
|
data["GUI"]["installDirs"] = install_dirs;
|
||||||
data["GUI"]["installDirsEnabled"] = install_dirs_enabled;
|
data["GUI"]["installDirsEnabled"] = install_dirs_enabled;
|
||||||
data["GUI"]["saveDataPath"] = string{fmt::UTF(save_data_path.u8string()).data};
|
data["GUI"]["saveDataPath"] = string{fmt::UTF(save_data_path.u8string()).data};
|
||||||
data["GUI"]["loadGameSizeEnabled"] = load_game_size;
|
|
||||||
data["GUI"]["addonInstallDir"] =
|
data["GUI"]["addonInstallDir"] =
|
||||||
string{fmt::UTF(settings_addon_install_dir.u8string()).data};
|
string{fmt::UTF(settings_addon_install_dir.u8string()).data};
|
||||||
data["Debug"]["ConfigVersion"] = config_version;
|
data["Debug"]["ConfigVersion"] = config_version;
|
||||||
@@ -1117,7 +1165,6 @@ void save(const std::filesystem::path& path, bool is_game_specific) {
|
|||||||
data["GPU"]["internalScreenWidth"] = internalScreenWidth.base_value;
|
data["GPU"]["internalScreenWidth"] = internalScreenWidth.base_value;
|
||||||
data["GPU"]["internalScreenHeight"] = internalScreenHeight.base_value;
|
data["GPU"]["internalScreenHeight"] = internalScreenHeight.base_value;
|
||||||
data["GPU"]["patchShaders"] = shouldPatchShaders.base_value;
|
data["GPU"]["patchShaders"] = shouldPatchShaders.base_value;
|
||||||
data["Vulkan"]["validation_gpu"] = vkValidationGpu.base_value;
|
|
||||||
data["Debug"]["FPSColor"] = isFpsColor.base_value;
|
data["Debug"]["FPSColor"] = isFpsColor.base_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1141,6 +1188,7 @@ void setDefaultValues(bool is_game_specific) {
|
|||||||
isPSNSignedIn.set(false, is_game_specific);
|
isPSNSignedIn.set(false, is_game_specific);
|
||||||
isConnectedToNetwork.set(false, is_game_specific);
|
isConnectedToNetwork.set(false, is_game_specific);
|
||||||
directMemoryAccessEnabled.set(false, is_game_specific);
|
directMemoryAccessEnabled.set(false, is_game_specific);
|
||||||
|
extraDmemInMbytes.set(0, is_game_specific);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Entries with game-specific settings that are in both the game-specific and global GUI
|
// Entries with game-specific settings that are in both the game-specific and global GUI
|
||||||
@@ -1151,7 +1199,6 @@ void setDefaultValues(bool is_game_specific) {
|
|||||||
logFilter.set("", is_game_specific);
|
logFilter.set("", is_game_specific);
|
||||||
logType.set("sync", is_game_specific);
|
logType.set("sync", is_game_specific);
|
||||||
userName.set("shadPS4", is_game_specific);
|
userName.set("shadPS4", is_game_specific);
|
||||||
chooseHomeTab.set("General", is_game_specific);
|
|
||||||
isShowSplash.set(false, is_game_specific);
|
isShowSplash.set(false, is_game_specific);
|
||||||
isSideTrophy.set("right", is_game_specific);
|
isSideTrophy.set("right", is_game_specific);
|
||||||
|
|
||||||
@@ -1160,6 +1207,7 @@ void setDefaultValues(bool is_game_specific) {
|
|||||||
cursorHideTimeout.set(5, is_game_specific);
|
cursorHideTimeout.set(5, is_game_specific);
|
||||||
isMotionControlsEnabled.set(true, is_game_specific);
|
isMotionControlsEnabled.set(true, is_game_specific);
|
||||||
backgroundControllerInput.set(false, is_game_specific);
|
backgroundControllerInput.set(false, is_game_specific);
|
||||||
|
usbDeviceBackend.set(UsbBackendType::Real, is_game_specific);
|
||||||
|
|
||||||
// GS - Audio
|
// GS - Audio
|
||||||
micDevice.set("Default Device", is_game_specific);
|
micDevice.set("Default Device", is_game_specific);
|
||||||
@@ -1182,6 +1230,7 @@ void setDefaultValues(bool is_game_specific) {
|
|||||||
// GS - Vulkan
|
// GS - Vulkan
|
||||||
gpuId.set(-1, is_game_specific);
|
gpuId.set(-1, is_game_specific);
|
||||||
vkValidation.set(false, is_game_specific);
|
vkValidation.set(false, is_game_specific);
|
||||||
|
vkValidationCore.set(true, is_game_specific);
|
||||||
vkValidationSync.set(false, is_game_specific);
|
vkValidationSync.set(false, is_game_specific);
|
||||||
vkValidationGpu.set(false, is_game_specific);
|
vkValidationGpu.set(false, is_game_specific);
|
||||||
vkCrashDiagnostic.set(false, is_game_specific);
|
vkCrashDiagnostic.set(false, is_game_specific);
|
||||||
@@ -1203,8 +1252,6 @@ void setDefaultValues(bool is_game_specific) {
|
|||||||
|
|
||||||
// General
|
// General
|
||||||
enableDiscordRPC = false;
|
enableDiscordRPC = false;
|
||||||
compatibilityData = false;
|
|
||||||
checkCompatibilityOnStartup = false;
|
|
||||||
|
|
||||||
// Input
|
// Input
|
||||||
useSpecialPad.base_value = false;
|
useSpecialPad.base_value = false;
|
||||||
@@ -1223,9 +1270,6 @@ void setDefaultValues(bool is_game_specific) {
|
|||||||
internalScreenWidth.base_value = 1280;
|
internalScreenWidth.base_value = 1280;
|
||||||
internalScreenHeight.base_value = 720;
|
internalScreenHeight.base_value = 720;
|
||||||
|
|
||||||
// GUI
|
|
||||||
load_game_size = true;
|
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
isFpsColor.base_value = true;
|
isFpsColor.base_value = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,13 @@
|
|||||||
|
|
||||||
namespace Config {
|
namespace Config {
|
||||||
|
|
||||||
|
enum class ConfigMode {
|
||||||
|
Default,
|
||||||
|
Global,
|
||||||
|
Clean,
|
||||||
|
};
|
||||||
|
void setConfigMode(ConfigMode mode);
|
||||||
|
|
||||||
struct GameInstallDir {
|
struct GameInstallDir {
|
||||||
std::filesystem::path path;
|
std::filesystem::path path;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
@@ -20,6 +27,8 @@ void load(const std::filesystem::path& path, bool is_game_specific = false);
|
|||||||
void save(const std::filesystem::path& path, bool is_game_specific = false);
|
void save(const std::filesystem::path& path, bool is_game_specific = false);
|
||||||
void resetGameSpecificValue(std::string entry);
|
void resetGameSpecificValue(std::string entry);
|
||||||
|
|
||||||
|
bool getGameRunning();
|
||||||
|
void setGameRunning(bool running);
|
||||||
int getVolumeSlider();
|
int getVolumeSlider();
|
||||||
void setVolumeSlider(int volumeValue, bool is_game_specific = false);
|
void setVolumeSlider(int volumeValue, bool is_game_specific = false);
|
||||||
std::string getTrophyKey();
|
std::string getTrophyKey();
|
||||||
@@ -72,6 +81,10 @@ bool vkValidationEnabled();
|
|||||||
void setVkValidation(bool enable, bool is_game_specific = false);
|
void setVkValidation(bool enable, bool is_game_specific = false);
|
||||||
bool vkValidationSyncEnabled();
|
bool vkValidationSyncEnabled();
|
||||||
void setVkSyncValidation(bool enable, bool is_game_specific = false);
|
void setVkSyncValidation(bool enable, bool is_game_specific = false);
|
||||||
|
bool vkValidationGpuEnabled();
|
||||||
|
void setVkGpuValidation(bool enable, bool is_game_specific = false);
|
||||||
|
bool vkValidationCoreEnabled();
|
||||||
|
void setVkCoreValidation(bool enable, bool is_game_specific = false);
|
||||||
bool getVkCrashDiagnosticEnabled();
|
bool getVkCrashDiagnosticEnabled();
|
||||||
void setVkCrashDiagnosticEnabled(bool enable, bool is_game_specific = false);
|
void setVkCrashDiagnosticEnabled(bool enable, bool is_game_specific = false);
|
||||||
bool getVkHostMarkersEnabled();
|
bool getVkHostMarkersEnabled();
|
||||||
@@ -90,11 +103,10 @@ double getTrophyNotificationDuration();
|
|||||||
void setTrophyNotificationDuration(double newTrophyNotificationDuration,
|
void setTrophyNotificationDuration(double newTrophyNotificationDuration,
|
||||||
bool is_game_specific = false);
|
bool is_game_specific = false);
|
||||||
int getCursorHideTimeout();
|
int getCursorHideTimeout();
|
||||||
void setCursorHideTimeout(int newcursorHideTimeout);
|
|
||||||
std::string getMainOutputDevice();
|
std::string getMainOutputDevice();
|
||||||
void setMainOutputDevice(std::string device);
|
void setMainOutputDevice(std::string device, bool is_game_specific = false);
|
||||||
std::string getPadSpkOutputDevice();
|
std::string getPadSpkOutputDevice();
|
||||||
void setPadSpkOutputDevice(std::string device);
|
void setPadSpkOutputDevice(std::string device, bool is_game_specific = false);
|
||||||
std::string getMicDevice();
|
std::string getMicDevice();
|
||||||
void setCursorHideTimeout(int newcursorHideTimeout, bool is_game_specific = false);
|
void setCursorHideTimeout(int newcursorHideTimeout, bool is_game_specific = false);
|
||||||
void setMicDevice(std::string device, bool is_game_specific = false);
|
void setMicDevice(std::string device, bool is_game_specific = false);
|
||||||
@@ -115,7 +127,8 @@ void setNeoMode(bool enable, bool is_game_specific = false);
|
|||||||
bool isDevKitConsole();
|
bool isDevKitConsole();
|
||||||
void setDevKitConsole(bool enable, bool is_game_specific = false);
|
void setDevKitConsole(bool enable, bool is_game_specific = false);
|
||||||
|
|
||||||
bool vkValidationGpuEnabled(); // no set
|
int getExtraDmemInMbytes();
|
||||||
|
void setExtraDmemInMbytes(int value, bool is_game_specific = false);
|
||||||
bool getIsMotionControlsEnabled();
|
bool getIsMotionControlsEnabled();
|
||||||
void setIsMotionControlsEnabled(bool use, bool is_game_specific = false);
|
void setIsMotionControlsEnabled(bool use, bool is_game_specific = false);
|
||||||
std::string getDefaultControllerID();
|
std::string getDefaultControllerID();
|
||||||
@@ -133,16 +146,18 @@ void setRcasAttenuation(int value, bool is_game_specific = false);
|
|||||||
bool getIsConnectedToNetwork();
|
bool getIsConnectedToNetwork();
|
||||||
void setConnectedToNetwork(bool enable, bool is_game_specific = false);
|
void setConnectedToNetwork(bool enable, bool is_game_specific = false);
|
||||||
void setUserName(const std::string& name, bool is_game_specific = false);
|
void setUserName(const std::string& name, bool is_game_specific = false);
|
||||||
void setChooseHomeTab(const std::string& type, bool is_game_specific = false);
|
std::filesystem::path getSysModulesPath();
|
||||||
|
void setSysModulesPath(const std::filesystem::path& path);
|
||||||
|
bool getLoadAutoPatches();
|
||||||
|
void setLoadAutoPatches(bool enable);
|
||||||
|
|
||||||
|
enum UsbBackendType : int { Real, SkylandersPortal, InfinityBase, DimensionsToypad };
|
||||||
|
int getUsbDeviceBackend();
|
||||||
|
void setUsbDeviceBackend(int value, bool is_game_specific = false);
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
bool GetLoadGameSizeEnabled();
|
|
||||||
std::filesystem::path GetSaveDataPath();
|
std::filesystem::path GetSaveDataPath();
|
||||||
void setLoadGameSizeEnabled(bool enable);
|
|
||||||
bool getCompatibilityEnabled();
|
|
||||||
bool getCheckCompatibilityOnStartup();
|
|
||||||
std::string getUserName();
|
std::string getUserName();
|
||||||
std::string getChooseHomeTab();
|
|
||||||
bool GetUseUnifiedInputConfig();
|
bool GetUseUnifiedInputConfig();
|
||||||
void SetUseUnifiedInputConfig(bool use);
|
void SetUseUnifiedInputConfig(bool use);
|
||||||
bool GetOverrideControllerColor();
|
bool GetOverrideControllerColor();
|
||||||
@@ -152,8 +167,6 @@ void SetControllerCustomColor(int r, int b, int g);
|
|||||||
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
|
void setGameInstallDirs(const std::vector<std::filesystem::path>& dirs_config);
|
||||||
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
|
void setAllGameInstallDirs(const std::vector<GameInstallDir>& dirs_config);
|
||||||
void setSaveDataPath(const std::filesystem::path& path);
|
void setSaveDataPath(const std::filesystem::path& path);
|
||||||
void setCompatibilityEnabled(bool use);
|
|
||||||
void setCheckCompatibilityOnStartup(bool use);
|
|
||||||
// Gui
|
// Gui
|
||||||
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true);
|
bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true);
|
||||||
void removeGameInstallDir(const std::filesystem::path& dir);
|
void removeGameInstallDir(const std::filesystem::path& dir);
|
||||||
|
|||||||
@@ -40,28 +40,30 @@ namespace {
|
|||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FileAccessMode::Read:
|
case FileAccessMode::Read:
|
||||||
return L"rb";
|
return L"rb";
|
||||||
case FileAccessMode::Write:
|
|
||||||
return L"wb";
|
|
||||||
case FileAccessMode::Append:
|
case FileAccessMode::Append:
|
||||||
return L"ab";
|
return L"ab";
|
||||||
|
case FileAccessMode::Write:
|
||||||
case FileAccessMode::ReadWrite:
|
case FileAccessMode::ReadWrite:
|
||||||
return L"r+b";
|
return L"r+b";
|
||||||
case FileAccessMode::ReadAppend:
|
case FileAccessMode::ReadAppend:
|
||||||
return L"a+b";
|
return L"a+b";
|
||||||
|
case FileAccessMode::Create:
|
||||||
|
return L"wb";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FileType::TextFile:
|
case FileType::TextFile:
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FileAccessMode::Read:
|
case FileAccessMode::Read:
|
||||||
return L"r";
|
return L"r";
|
||||||
case FileAccessMode::Write:
|
|
||||||
return L"w";
|
|
||||||
case FileAccessMode::Append:
|
case FileAccessMode::Append:
|
||||||
return L"a";
|
return L"a";
|
||||||
|
case FileAccessMode::Write:
|
||||||
case FileAccessMode::ReadWrite:
|
case FileAccessMode::ReadWrite:
|
||||||
return L"r+";
|
return L"r+";
|
||||||
case FileAccessMode::ReadAppend:
|
case FileAccessMode::ReadAppend:
|
||||||
return L"a+";
|
return L"a+";
|
||||||
|
case FileAccessMode::Create:
|
||||||
|
return L"w";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -91,28 +93,30 @@ namespace {
|
|||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FileAccessMode::Read:
|
case FileAccessMode::Read:
|
||||||
return "rb";
|
return "rb";
|
||||||
case FileAccessMode::Write:
|
|
||||||
return "wb";
|
|
||||||
case FileAccessMode::Append:
|
case FileAccessMode::Append:
|
||||||
return "ab";
|
return "ab";
|
||||||
|
case FileAccessMode::Write:
|
||||||
case FileAccessMode::ReadWrite:
|
case FileAccessMode::ReadWrite:
|
||||||
return "r+b";
|
return "r+b";
|
||||||
case FileAccessMode::ReadAppend:
|
case FileAccessMode::ReadAppend:
|
||||||
return "a+b";
|
return "a+b";
|
||||||
|
case FileAccessMode::Create:
|
||||||
|
return "wb";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FileType::TextFile:
|
case FileType::TextFile:
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case FileAccessMode::Read:
|
case FileAccessMode::Read:
|
||||||
return "r";
|
return "r";
|
||||||
case FileAccessMode::Write:
|
|
||||||
return "w";
|
|
||||||
case FileAccessMode::Append:
|
case FileAccessMode::Append:
|
||||||
return "a";
|
return "a";
|
||||||
|
case FileAccessMode::Write:
|
||||||
case FileAccessMode::ReadWrite:
|
case FileAccessMode::ReadWrite:
|
||||||
return "r+";
|
return "r+";
|
||||||
case FileAccessMode::ReadAppend:
|
case FileAccessMode::ReadAppend:
|
||||||
return "a+";
|
return "a+";
|
||||||
|
case FileAccessMode::Create:
|
||||||
|
return "w";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,9 +21,8 @@ enum class FileAccessMode {
|
|||||||
*/
|
*/
|
||||||
Read = 1 << 0,
|
Read = 1 << 0,
|
||||||
/**
|
/**
|
||||||
* If the file at path exists, the existing contents of the file are erased.
|
* If the file at path exists, it opens the file for writing.
|
||||||
* The empty file is then opened for writing.
|
* If the file at path does not exist, it fails to open the file.
|
||||||
* If the file at path does not exist, it creates and opens a new empty file for writing.
|
|
||||||
*/
|
*/
|
||||||
Write = 1 << 1,
|
Write = 1 << 1,
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +41,12 @@ enum class FileAccessMode {
|
|||||||
* reading and appending.
|
* reading and appending.
|
||||||
*/
|
*/
|
||||||
ReadAppend = Read | Append,
|
ReadAppend = Read | Append,
|
||||||
|
/**
|
||||||
|
* If the file at path exists, the existing contents of the file are erased.
|
||||||
|
* The empty file is then opened for writing.
|
||||||
|
* If the file at path does not exist, it creates and opens a new empty file for writing.
|
||||||
|
*/
|
||||||
|
Create = 1 << 3,
|
||||||
};
|
};
|
||||||
DECLARE_ENUM_FLAG_OPERATORS(FileAccessMode);
|
DECLARE_ENUM_FLAG_OPERATORS(FileAccessMode);
|
||||||
|
|
||||||
@@ -102,6 +107,11 @@ public:
|
|||||||
return file != nullptr;
|
return file != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsWriteOnly() const {
|
||||||
|
return file_access_mode == FileAccessMode::Append ||
|
||||||
|
file_access_mode == FileAccessMode::Write;
|
||||||
|
}
|
||||||
|
|
||||||
uintptr_t GetFileMapping();
|
uintptr_t GetFileMapping();
|
||||||
|
|
||||||
int Open(const std::filesystem::path& path, FileAccessMode mode,
|
int Open(const std::filesystem::path& path, FileAccessMode mode,
|
||||||
@@ -210,7 +220,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static size_t WriteBytes(const std::filesystem::path path, const auto& data) {
|
static size_t WriteBytes(const std::filesystem::path path, const auto& data) {
|
||||||
IOFile out(path, FileAccessMode::Write);
|
IOFile out(path, FileAccessMode::Create);
|
||||||
return out.Write(data);
|
return out.Write(data);
|
||||||
}
|
}
|
||||||
std::FILE* file = nullptr;
|
std::FILE* file = nullptr;
|
||||||
|
|||||||
@@ -61,8 +61,9 @@ private:
|
|||||||
*/
|
*/
|
||||||
class FileBackend {
|
class FileBackend {
|
||||||
public:
|
public:
|
||||||
explicit FileBackend(const std::filesystem::path& filename)
|
explicit FileBackend(const std::filesystem::path& filename, bool should_append = false)
|
||||||
: file{filename, FS::FileAccessMode::Write, FS::FileType::TextFile} {}
|
: file{filename, should_append ? FS::FileAccessMode::Append : FS::FileAccessMode::Create,
|
||||||
|
FS::FileType::TextFile} {}
|
||||||
|
|
||||||
~FileBackend() = default;
|
~FileBackend() = default;
|
||||||
|
|
||||||
@@ -145,6 +146,11 @@ public:
|
|||||||
initialization_in_progress_suppress_logging = false;
|
initialization_in_progress_suppress_logging = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ResetInstance() {
|
||||||
|
initialization_in_progress_suppress_logging = true;
|
||||||
|
instance.reset();
|
||||||
|
}
|
||||||
|
|
||||||
static bool IsActive() {
|
static bool IsActive() {
|
||||||
return instance != nullptr;
|
return instance != nullptr;
|
||||||
}
|
}
|
||||||
@@ -157,6 +163,10 @@ public:
|
|||||||
instance->StopBackendThread();
|
instance->StopBackendThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetAppend() {
|
||||||
|
should_append = true;
|
||||||
|
}
|
||||||
|
|
||||||
Impl(const Impl&) = delete;
|
Impl(const Impl&) = delete;
|
||||||
Impl& operator=(const Impl&) = delete;
|
Impl& operator=(const Impl&) = delete;
|
||||||
|
|
||||||
@@ -218,7 +228,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Impl(const std::filesystem::path& file_backend_filename, const Filter& filter_)
|
Impl(const std::filesystem::path& file_backend_filename, const Filter& filter_)
|
||||||
: filter{filter_}, file_backend{file_backend_filename} {}
|
: filter{filter_}, file_backend{file_backend_filename, should_append} {}
|
||||||
|
|
||||||
~Impl() = default;
|
~Impl() = default;
|
||||||
|
|
||||||
@@ -264,6 +274,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
|
static inline std::unique_ptr<Impl, decltype(&Deleter)> instance{nullptr, Deleter};
|
||||||
|
static inline bool should_append{false};
|
||||||
|
|
||||||
Filter filter;
|
Filter filter;
|
||||||
DebuggerBackend debugger_backend{};
|
DebuggerBackend debugger_backend{};
|
||||||
@@ -292,6 +303,11 @@ void Stop() {
|
|||||||
Impl::Stop();
|
Impl::Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Denitializer() {
|
||||||
|
Impl::Stop();
|
||||||
|
Impl::ResetInstance();
|
||||||
|
}
|
||||||
|
|
||||||
void SetGlobalFilter(const Filter& filter) {
|
void SetGlobalFilter(const Filter& filter) {
|
||||||
Impl::Instance().SetGlobalFilter(filter);
|
Impl::Instance().SetGlobalFilter(filter);
|
||||||
}
|
}
|
||||||
@@ -300,6 +316,10 @@ void SetColorConsoleBackendEnabled(bool enabled) {
|
|||||||
Impl::Instance().SetColorConsoleBackendEnabled(enabled);
|
Impl::Instance().SetColorConsoleBackendEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetAppend() {
|
||||||
|
Impl::SetAppend();
|
||||||
|
}
|
||||||
|
|
||||||
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
|
||||||
unsigned int line_num, const char* function, const char* format,
|
unsigned int line_num, const char* function, const char* format,
|
||||||
const fmt::format_args& args) {
|
const fmt::format_args& args) {
|
||||||
|
|||||||
@@ -21,9 +21,14 @@ void Start();
|
|||||||
/// Explictily stops the logger thread and flushes the buffers
|
/// Explictily stops the logger thread and flushes the buffers
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
|
/// Closes log files and stops the logger
|
||||||
|
void Denitializer();
|
||||||
|
|
||||||
/// The global filter will prevent any messages from even being processed if they are filtered.
|
/// The global filter will prevent any messages from even being processed if they are filtered.
|
||||||
void SetGlobalFilter(const Filter& filter);
|
void SetGlobalFilter(const Filter& filter);
|
||||||
|
|
||||||
void SetColorConsoleBackendEnabled(bool enabled);
|
void SetColorConsoleBackendEnabled(bool enabled);
|
||||||
|
|
||||||
|
void SetAppend();
|
||||||
|
|
||||||
} // namespace Common::Log
|
} // namespace Common::Log
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Lib, NpTrophy) \
|
SUB(Lib, NpTrophy) \
|
||||||
SUB(Lib, NpWebApi) \
|
SUB(Lib, NpWebApi) \
|
||||||
SUB(Lib, NpProfileDialog) \
|
SUB(Lib, NpProfileDialog) \
|
||||||
|
SUB(Lib, NpSnsFacebookDialog) \
|
||||||
SUB(Lib, Screenshot) \
|
SUB(Lib, Screenshot) \
|
||||||
SUB(Lib, LibCInternal) \
|
SUB(Lib, LibCInternal) \
|
||||||
SUB(Lib, AppContent) \
|
SUB(Lib, AppContent) \
|
||||||
@@ -139,6 +140,8 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Lib, NpParty) \
|
SUB(Lib, NpParty) \
|
||||||
SUB(Lib, Zlib) \
|
SUB(Lib, Zlib) \
|
||||||
SUB(Lib, Hmd) \
|
SUB(Lib, Hmd) \
|
||||||
|
SUB(Lib, Font) \
|
||||||
|
SUB(Lib, FontFt) \
|
||||||
SUB(Lib, HmdSetupDialog) \
|
SUB(Lib, HmdSetupDialog) \
|
||||||
SUB(Lib, SigninDialog) \
|
SUB(Lib, SigninDialog) \
|
||||||
SUB(Lib, Camera) \
|
SUB(Lib, Camera) \
|
||||||
|
|||||||
@@ -29,99 +29,102 @@ enum class Level : u8 {
|
|||||||
* filter.cpp.
|
* filter.cpp.
|
||||||
*/
|
*/
|
||||||
enum class Class : u8 {
|
enum class Class : u8 {
|
||||||
Log, ///< Messages about the log system itself
|
Log, ///< Messages about the log system itself
|
||||||
Common, ///< Library routines
|
Common, ///< Library routines
|
||||||
Common_Filesystem, ///< Filesystem interface library
|
Common_Filesystem, ///< Filesystem interface library
|
||||||
Common_Memory, ///< Memory mapping and management functions
|
Common_Memory, ///< Memory mapping and management functions
|
||||||
Core, ///< LLE emulation core
|
Core, ///< LLE emulation core
|
||||||
Core_Linker, ///< The module linker
|
Core_Linker, ///< The module linker
|
||||||
Core_Devices, ///< Devices emulation
|
Core_Devices, ///< Devices emulation
|
||||||
Config, ///< Emulator configuration (including commandline)
|
Config, ///< Emulator configuration (including commandline)
|
||||||
Debug, ///< Debugging tools
|
Debug, ///< Debugging tools
|
||||||
Kernel, ///< The HLE implementation of the PS4 kernel.
|
Kernel, ///< The HLE implementation of the PS4 kernel.
|
||||||
Kernel_Pthread, ///< The pthread implementation of the kernel.
|
Kernel_Pthread, ///< The pthread implementation of the kernel.
|
||||||
Kernel_Fs, ///< The filesystem implementation of the kernel.
|
Kernel_Fs, ///< The filesystem implementation of the kernel.
|
||||||
Kernel_Vmm, ///< The virtual memory implementation of the kernel.
|
Kernel_Vmm, ///< The virtual memory implementation of the kernel.
|
||||||
Kernel_Event, ///< The event management implementation of the kernel.
|
Kernel_Event, ///< The event management implementation of the kernel.
|
||||||
Kernel_Sce, ///< The sony specific interfaces provided by the kernel.
|
Kernel_Sce, ///< The sony specific interfaces provided by the kernel.
|
||||||
Lib, ///< HLE implementation of system library. Each major library
|
Lib, ///< HLE implementation of system library. Each major library
|
||||||
///< should have its own subclass.
|
///< should have its own subclass.
|
||||||
Lib_LibC, ///< The LibC implementation.
|
Lib_LibC, ///< The LibC implementation.
|
||||||
Lib_LibcInternal, ///< The LibcInternal implementation.
|
Lib_LibcInternal, ///< The LibcInternal implementation.
|
||||||
Lib_Kernel, ///< The LibKernel implementation.
|
Lib_Kernel, ///< The LibKernel implementation.
|
||||||
Lib_Pad, ///< The LibScePad implementation.
|
Lib_Pad, ///< The LibScePad implementation.
|
||||||
Lib_SystemGesture, ///< The LibSceSystemGesture implementation.
|
Lib_SystemGesture, ///< The LibSceSystemGesture implementation.
|
||||||
Lib_GnmDriver, ///< The LibSceGnmDriver implementation.
|
Lib_GnmDriver, ///< The LibSceGnmDriver implementation.
|
||||||
Lib_SystemService, ///< The LibSceSystemService implementation.
|
Lib_SystemService, ///< The LibSceSystemService implementation.
|
||||||
Lib_UserService, ///< The LibSceUserService implementation.
|
Lib_UserService, ///< The LibSceUserService implementation.
|
||||||
Lib_VideoOut, ///< The LibSceVideoOut implementation.
|
Lib_VideoOut, ///< The LibSceVideoOut implementation.
|
||||||
Lib_CommonDlg, ///< The LibSceCommonDialog implementation.
|
Lib_CommonDlg, ///< The LibSceCommonDialog implementation.
|
||||||
Lib_MsgDlg, ///< The LibSceMsgDialog implementation.
|
Lib_MsgDlg, ///< The LibSceMsgDialog implementation.
|
||||||
Lib_AudioOut, ///< The LibSceAudioOut implementation.
|
Lib_AudioOut, ///< The LibSceAudioOut implementation.
|
||||||
Lib_AudioIn, ///< The LibSceAudioIn implementation.
|
Lib_AudioIn, ///< The LibSceAudioIn implementation.
|
||||||
Lib_Move, ///< The LibSceMove implementation.
|
Lib_Move, ///< The LibSceMove implementation.
|
||||||
Lib_Net, ///< The LibSceNet implementation.
|
Lib_Net, ///< The LibSceNet implementation.
|
||||||
Lib_NetCtl, ///< The LibSceNetCtl implementation.
|
Lib_NetCtl, ///< The LibSceNetCtl implementation.
|
||||||
Lib_SaveData, ///< The LibSceSaveData implementation.
|
Lib_SaveData, ///< The LibSceSaveData implementation.
|
||||||
Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation.
|
Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation.
|
||||||
Lib_Ssl, ///< The LibSceSsl implementation.
|
Lib_Ssl, ///< The LibSceSsl implementation.
|
||||||
Lib_Ssl2, ///< The LibSceSsl2 implementation.
|
Lib_Ssl2, ///< The LibSceSsl2 implementation.
|
||||||
Lib_Http, ///< The LibSceHttp implementation.
|
Lib_Http, ///< The LibSceHttp implementation.
|
||||||
Lib_Http2, ///< The LibSceHttp2 implementation.
|
Lib_Http2, ///< The LibSceHttp2 implementation.
|
||||||
Lib_SysModule, ///< The LibSceSysModule implementation
|
Lib_SysModule, ///< The LibSceSysModule implementation
|
||||||
Lib_NpCommon, ///< The LibSceNpCommon implementation
|
Lib_NpCommon, ///< The LibSceNpCommon implementation
|
||||||
Lib_NpAuth, ///< The LibSceNpAuth implementation
|
Lib_NpAuth, ///< The LibSceNpAuth implementation
|
||||||
Lib_NpManager, ///< The LibSceNpManager implementation
|
Lib_NpManager, ///< The LibSceNpManager implementation
|
||||||
Lib_NpScore, ///< The LibSceNpScore implementation
|
Lib_NpScore, ///< The LibSceNpScore implementation
|
||||||
Lib_NpTrophy, ///< The LibSceNpTrophy implementation
|
Lib_NpTrophy, ///< The LibSceNpTrophy implementation
|
||||||
Lib_NpWebApi, ///< The LibSceWebApi implementation
|
Lib_NpWebApi, ///< The LibSceWebApi implementation
|
||||||
Lib_NpProfileDialog, ///< The LibSceNpProfileDialog implementation
|
Lib_NpProfileDialog, ///< The LibSceNpProfileDialog implementation
|
||||||
Lib_Screenshot, ///< The LibSceScreenshot implementation
|
Lib_NpSnsFacebookDialog, ///< The LibSceNpSnsFacebookDialog implementation
|
||||||
Lib_LibCInternal, ///< The LibCInternal implementation.
|
Lib_Screenshot, ///< The LibSceScreenshot implementation
|
||||||
Lib_AppContent, ///< The LibSceAppContent implementation.
|
Lib_LibCInternal, ///< The LibCInternal implementation.
|
||||||
Lib_Rtc, ///< The LibSceRtc implementation.
|
Lib_AppContent, ///< The LibSceAppContent implementation.
|
||||||
Lib_DiscMap, ///< The LibSceDiscMap implementation.
|
Lib_Rtc, ///< The LibSceRtc implementation.
|
||||||
Lib_Png, ///< The LibScePng implementation.
|
Lib_DiscMap, ///< The LibSceDiscMap implementation.
|
||||||
Lib_Jpeg, ///< The LibSceJpeg implementation.
|
Lib_Png, ///< The LibScePng implementation.
|
||||||
Lib_PlayGo, ///< The LibScePlayGo implementation.
|
Lib_Jpeg, ///< The LibSceJpeg implementation.
|
||||||
Lib_PlayGoDialog, ///< The LibScePlayGoDialog implementation.
|
Lib_PlayGo, ///< The LibScePlayGo implementation.
|
||||||
Lib_Random, ///< The LibSceRandom implementation.
|
Lib_PlayGoDialog, ///< The LibScePlayGoDialog implementation.
|
||||||
Lib_Usbd, ///< The LibSceUsbd implementation.
|
Lib_Random, ///< The LibSceRandom implementation.
|
||||||
Lib_Ajm, ///< The LibSceAjm implementation.
|
Lib_Usbd, ///< The LibSceUsbd implementation.
|
||||||
Lib_ErrorDialog, ///< The LibSceErrorDialog implementation.
|
Lib_Ajm, ///< The LibSceAjm implementation.
|
||||||
Lib_ImeDialog, ///< The LibSceImeDialog implementation.
|
Lib_ErrorDialog, ///< The LibSceErrorDialog implementation.
|
||||||
Lib_AvPlayer, ///< The LibSceAvPlayer implementation.
|
Lib_ImeDialog, ///< The LibSceImeDialog implementation.
|
||||||
Lib_Ngs2, ///< The LibSceNgs2 implementation.
|
Lib_AvPlayer, ///< The LibSceAvPlayer implementation.
|
||||||
Lib_Audio3d, ///< The LibSceAudio3d implementation.
|
Lib_Ngs2, ///< The LibSceNgs2 implementation.
|
||||||
Lib_Ime, ///< The LibSceIme implementation
|
Lib_Audio3d, ///< The LibSceAudio3d implementation.
|
||||||
Lib_GameLiveStreaming, ///< The LibSceGameLiveStreaming implementation
|
Lib_Ime, ///< The LibSceIme implementation
|
||||||
Lib_Remoteplay, ///< The LibSceRemotePlay implementation
|
Lib_GameLiveStreaming, ///< The LibSceGameLiveStreaming implementation
|
||||||
Lib_SharePlay, ///< The LibSceSharePlay implemenation
|
Lib_Remoteplay, ///< The LibSceRemotePlay implementation
|
||||||
Lib_Fiber, ///< The LibSceFiber implementation.
|
Lib_SharePlay, ///< The LibSceSharePlay implemenation
|
||||||
Lib_Vdec2, ///< The LibSceVideodec2 implementation.
|
Lib_Fiber, ///< The LibSceFiber implementation.
|
||||||
Lib_Videodec, ///< The LibSceVideodec implementation.
|
Lib_Vdec2, ///< The LibSceVideodec2 implementation.
|
||||||
Lib_Voice, ///< The LibSceVoice implementation.
|
Lib_Videodec, ///< The LibSceVideodec implementation.
|
||||||
Lib_RazorCpu, ///< The LibRazorCpu implementation.
|
Lib_Voice, ///< The LibSceVoice implementation.
|
||||||
Lib_Mouse, ///< The LibSceMouse implementation
|
Lib_RazorCpu, ///< The LibRazorCpu implementation.
|
||||||
Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation
|
Lib_Mouse, ///< The LibSceMouse implementation
|
||||||
Lib_NpParty, ///< The LibSceNpParty implementation
|
Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation
|
||||||
Lib_Zlib, ///< The LibSceZlib implementation.
|
Lib_NpParty, ///< The LibSceNpParty implementation
|
||||||
Lib_Hmd, ///< The LibSceHmd implementation.
|
Lib_Zlib, ///< The LibSceZlib implementation.
|
||||||
Lib_HmdSetupDialog, ///< The LibSceHmdSetupDialog implementation.
|
Lib_Hmd, ///< The LibSceHmd implementation.
|
||||||
Lib_SigninDialog, ///< The LibSigninDialog implementation.
|
Lib_HmdSetupDialog, ///< The LibSceHmdSetupDialog implementation.
|
||||||
Lib_Camera, ///< The LibCamera implementation.
|
Lib_SigninDialog, ///< The LibSigninDialog implementation.
|
||||||
Lib_CompanionHttpd, ///< The LibCompanionHttpd implementation.
|
Lib_Camera, ///< The LibCamera implementation.
|
||||||
Lib_CompanionUtil, ///< The LibCompanionUtil implementation.
|
Lib_CompanionHttpd, ///< The LibCompanionHttpd implementation.
|
||||||
Lib_VrTracker, ///< The LibSceVrTracker implementation.
|
Lib_CompanionUtil, ///< The LibCompanionUtil implementation.
|
||||||
Frontend, ///< Emulator UI
|
Lib_VrTracker, ///< The LibSceVrTracker implementation.
|
||||||
Render, ///< Video Core
|
Lib_Font, ///< The libSceFont implementation.
|
||||||
Render_Vulkan, ///< Vulkan backend
|
Lib_FontFt, ///< The libSceFontFt implementation.
|
||||||
Render_Recompiler, ///< Shader recompiler
|
Frontend, ///< Emulator UI
|
||||||
ImGui, ///< ImGui
|
Render, ///< Video Core
|
||||||
Loader, ///< ROM loader
|
Render_Vulkan, ///< Vulkan backend
|
||||||
Input, ///< Input emulation
|
Render_Recompiler, ///< Shader recompiler
|
||||||
Tty, ///< Debug output from emu
|
ImGui, ///< ImGui
|
||||||
Count ///< Total number of logging classes
|
Loader, ///< ROM loader
|
||||||
|
Input, ///< Input emulation
|
||||||
|
Tty, ///< Debug output from emu
|
||||||
|
Count ///< Total number of logging classes
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Common::Log
|
} // namespace Common::Log
|
||||||
|
|||||||
@@ -3,20 +3,12 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
#include <pugixml.hpp>
|
#include <pugixml.hpp>
|
||||||
#ifdef ENABLE_QT_GUI
|
#include "common/config.h"
|
||||||
#include <QDir>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QJsonArray>
|
|
||||||
#include <QJsonDocument>
|
|
||||||
#include <QJsonObject>
|
|
||||||
#include <QListView>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QString>
|
|
||||||
#include <QXmlStreamReader>
|
|
||||||
#endif
|
|
||||||
#include "common/elf_info.h"
|
#include "common/elf_info.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/path_util.h"
|
#include "common/path_util.h"
|
||||||
@@ -28,7 +20,7 @@ namespace MemoryPatcher {
|
|||||||
EXPORT uintptr_t g_eboot_address;
|
EXPORT uintptr_t g_eboot_address;
|
||||||
uint64_t g_eboot_image_size;
|
uint64_t g_eboot_image_size;
|
||||||
std::string g_game_serial;
|
std::string g_game_serial;
|
||||||
std::string patchFile;
|
std::string patch_file;
|
||||||
bool patches_applied = false;
|
bool patches_applied = false;
|
||||||
std::vector<patchInfo> pending_patches;
|
std::vector<patchInfo> pending_patches;
|
||||||
|
|
||||||
@@ -122,256 +114,104 @@ std::string convertValueToHex(const std::string type, const std::string valueStr
|
|||||||
|
|
||||||
void ApplyPendingPatches();
|
void ApplyPendingPatches();
|
||||||
|
|
||||||
void OnGameLoaded() {
|
void ApplyPatchesFromXML(std::filesystem::path path) {
|
||||||
if (!patchFile.empty()) {
|
pugi::xml_document doc;
|
||||||
std::filesystem::path patchDir = Common::FS::GetUserPath(Common::FS::PathType::PatchesDir);
|
pugi::xml_parse_result result = doc.load_file(path.c_str());
|
||||||
|
|
||||||
auto filePath = (patchDir / patchFile).native();
|
auto* param_sfo = Common::Singleton<PSF>::Instance();
|
||||||
|
auto app_version = param_sfo->GetString("APP_VER").value_or("Unknown version");
|
||||||
|
|
||||||
pugi::xml_document doc;
|
if (result) {
|
||||||
pugi::xml_parse_result result = doc.load_file(filePath.c_str());
|
auto patchXML = doc.child("Patch");
|
||||||
|
for (pugi::xml_node_iterator it = patchXML.children().begin();
|
||||||
|
it != patchXML.children().end(); ++it) {
|
||||||
|
|
||||||
auto* param_sfo = Common::Singleton<PSF>::Instance();
|
if (std::string(it->name()) == "Metadata") {
|
||||||
auto app_version = param_sfo->GetString("APP_VER").value_or("Unknown version");
|
if (std::string(it->attribute("isEnabled").value()) == "true") {
|
||||||
|
std::string currentPatchName = it->attribute("Name").value();
|
||||||
|
std::string metadataAppVer = it->attribute("AppVer").value();
|
||||||
|
bool versionMatches = metadataAppVer == app_version;
|
||||||
|
|
||||||
if (result) {
|
auto patchList = it->first_child();
|
||||||
auto patchXML = doc.child("Patch");
|
for (pugi::xml_node_iterator patchLineIt = patchList.children().begin();
|
||||||
for (pugi::xml_node_iterator it = patchXML.children().begin();
|
patchLineIt != patchList.children().end(); ++patchLineIt) {
|
||||||
it != patchXML.children().end(); ++it) {
|
|
||||||
|
|
||||||
if (std::string(it->name()) == "Metadata") {
|
std::string type = patchLineIt->attribute("Type").value();
|
||||||
if (std::string(it->attribute("isEnabled").value()) == "true") {
|
if (!versionMatches && type != "mask" && type != "mask_jump32")
|
||||||
std::string currentPatchName = it->attribute("Name").value();
|
continue;
|
||||||
std::string metadataAppVer = it->attribute("AppVer").value();
|
|
||||||
bool versionMatches = metadataAppVer == app_version;
|
|
||||||
|
|
||||||
auto patchList = it->first_child();
|
std::string address = patchLineIt->attribute("Address").value();
|
||||||
for (pugi::xml_node_iterator patchLineIt = patchList.children().begin();
|
std::string patchValue = patchLineIt->attribute("Value").value();
|
||||||
patchLineIt != patchList.children().end(); ++patchLineIt) {
|
std::string maskOffsetStr = patchLineIt->attribute("Offset").value();
|
||||||
|
std::string targetStr = "";
|
||||||
std::string type = patchLineIt->attribute("Type").value();
|
std::string sizeStr = "";
|
||||||
if (!versionMatches && type != "mask" && type != "mask_jump32")
|
if (type == "mask_jump32") {
|
||||||
continue;
|
targetStr = patchLineIt->attribute("Target").value();
|
||||||
|
sizeStr = patchLineIt->attribute("Size").value();
|
||||||
std::string currentPatchName = it->attribute("Name").value();
|
} else {
|
||||||
|
patchValue = convertValueToHex(type, patchValue);
|
||||||
for (pugi::xml_node_iterator patchLineIt = patchList.children().begin();
|
|
||||||
patchLineIt != patchList.children().end(); ++patchLineIt) {
|
|
||||||
|
|
||||||
std::string type = patchLineIt->attribute("Type").value();
|
|
||||||
std::string address = patchLineIt->attribute("Address").value();
|
|
||||||
std::string patchValue = patchLineIt->attribute("Value").value();
|
|
||||||
std::string maskOffsetStr =
|
|
||||||
patchLineIt->attribute("Offset").value();
|
|
||||||
std::string targetStr = "";
|
|
||||||
std::string sizeStr = "";
|
|
||||||
if (type == "mask_jump32") {
|
|
||||||
targetStr = patchLineIt->attribute("Target").value();
|
|
||||||
sizeStr = patchLineIt->attribute("Size").value();
|
|
||||||
} else {
|
|
||||||
patchValue = convertValueToHex(type, patchValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool littleEndian = false;
|
|
||||||
|
|
||||||
if (type == "bytes16" || type == "bytes32" || type == "bytes64") {
|
|
||||||
littleEndian = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None;
|
|
||||||
int maskOffsetValue = 0;
|
|
||||||
|
|
||||||
if (type == "mask")
|
|
||||||
patchMask = MemoryPatcher::PatchMask::Mask;
|
|
||||||
|
|
||||||
if (type == "mask_jump32")
|
|
||||||
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
|
|
||||||
|
|
||||||
if ((type == "mask" || type == "mask_jump32") &&
|
|
||||||
!maskOffsetStr.empty()) {
|
|
||||||
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryPatcher::PatchMemory(currentPatchName, address, patchValue,
|
|
||||||
targetStr, sizeStr, false, littleEndian,
|
|
||||||
patchMask, maskOffsetValue);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool littleEndian = false;
|
||||||
|
if (type == "bytes16" || type == "bytes32" || type == "bytes64") {
|
||||||
|
littleEndian = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None;
|
||||||
|
int maskOffsetValue = 0;
|
||||||
|
|
||||||
|
if (type == "mask")
|
||||||
|
patchMask = MemoryPatcher::PatchMask::Mask;
|
||||||
|
|
||||||
|
if (type == "mask_jump32")
|
||||||
|
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
|
||||||
|
|
||||||
|
if ((type == "mask" || type == "mask_jump32") && !maskOffsetStr.empty()) {
|
||||||
|
maskOffsetValue = std::stoi(maskOffsetStr, 0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemoryPatcher::PatchMemory(currentPatchName, address, patchValue, targetStr,
|
||||||
|
sizeStr, false, littleEndian, patchMask,
|
||||||
|
maskOffsetValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_ERROR(Loader, "Could not parse patch XML: {}", result.description());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnGameLoaded() {
|
||||||
|
std::filesystem::path patch_dir = Common::FS::GetUserPath(Common::FS::PathType::PatchesDir);
|
||||||
|
if (!patch_file.empty()) {
|
||||||
|
|
||||||
|
auto file_path = (patch_dir / patch_file).native();
|
||||||
|
if (std::filesystem::exists(patch_file)) {
|
||||||
|
ApplyPatchesFromXML(patch_file);
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR(Loader, "couldnt patch parse xml : {}", result.description());
|
ApplyPatchesFromXML(file_path);
|
||||||
|
}
|
||||||
|
} else if (Config::getLoadAutoPatches()) {
|
||||||
|
for (auto const& repo : std::filesystem::directory_iterator(patch_dir)) {
|
||||||
|
if (!repo.is_directory()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::ifstream json_file{repo.path() / "files.json"};
|
||||||
|
nlohmann::json available_patches = nlohmann::json::parse(json_file);
|
||||||
|
std::filesystem::path game_patch_file;
|
||||||
|
for (auto const& [filename, serials] : available_patches.items()) {
|
||||||
|
if (std::find(serials.begin(), serials.end(), g_game_serial) != serials.end()) {
|
||||||
|
game_patch_file = repo.path() / filename;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (std::filesystem::exists(game_patch_file)) {
|
||||||
|
ApplyPatchesFromXML(game_patch_file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ApplyPendingPatches();
|
ApplyPendingPatches();
|
||||||
|
|
||||||
#ifdef ENABLE_QT_GUI
|
|
||||||
// We use the QT headers for the xml and json parsing, this define is only true on QT builds
|
|
||||||
QString patchDir;
|
|
||||||
Common::FS::PathToQString(patchDir, Common::FS::GetUserPath(Common::FS::PathType::PatchesDir));
|
|
||||||
QDir dir(patchDir);
|
|
||||||
QStringList folders = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
|
|
||||||
|
|
||||||
for (const QString& folder : folders) {
|
|
||||||
QString filesJsonPath = patchDir + "/" + folder + "/files.json";
|
|
||||||
|
|
||||||
QFile jsonFile(filesJsonPath);
|
|
||||||
if (!jsonFile.open(QIODevice::ReadOnly)) {
|
|
||||||
LOG_ERROR(Loader, "Unable to open files.json for reading in repository {}",
|
|
||||||
folder.toStdString());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray jsonData = jsonFile.readAll();
|
|
||||||
jsonFile.close();
|
|
||||||
|
|
||||||
QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
|
|
||||||
QJsonObject jsonObject = jsonDoc.object();
|
|
||||||
|
|
||||||
QString selectedFileName;
|
|
||||||
QString serial = QString::fromStdString(g_game_serial);
|
|
||||||
|
|
||||||
for (auto it = jsonObject.constBegin(); it != jsonObject.constEnd(); ++it) {
|
|
||||||
QString filePath = it.key();
|
|
||||||
QJsonArray idsArray = it.value().toArray();
|
|
||||||
|
|
||||||
if (idsArray.contains(QJsonValue(serial))) {
|
|
||||||
selectedFileName = filePath;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedFileName.isEmpty()) {
|
|
||||||
LOG_ERROR(Loader, "No patch file found for the current serial in repository {}",
|
|
||||||
folder.toStdString());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString filePath = patchDir + "/" + folder + "/" + selectedFileName;
|
|
||||||
QFile file(filePath);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
||||||
LOG_ERROR(Loader, "Unable to open the file for reading.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray xmlData = file.readAll();
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
QString newXmlData;
|
|
||||||
|
|
||||||
QXmlStreamReader xmlReader(xmlData);
|
|
||||||
|
|
||||||
bool isEnabled = false;
|
|
||||||
std::string currentPatchName;
|
|
||||||
|
|
||||||
auto* param_sfo = Common::Singleton<PSF>::Instance();
|
|
||||||
auto app_version = param_sfo->GetString("APP_VER").value_or("Unknown version");
|
|
||||||
bool versionMatches = true;
|
|
||||||
|
|
||||||
while (!xmlReader.atEnd()) {
|
|
||||||
xmlReader.readNext();
|
|
||||||
|
|
||||||
if (xmlReader.isStartElement()) {
|
|
||||||
QJsonArray patchLines;
|
|
||||||
if (xmlReader.name() == QStringLiteral("Metadata")) {
|
|
||||||
QString name = xmlReader.attributes().value("Name").toString();
|
|
||||||
currentPatchName = name.toStdString();
|
|
||||||
|
|
||||||
QString appVer = xmlReader.attributes().value("AppVer").toString();
|
|
||||||
|
|
||||||
// Check and update the isEnabled attribute
|
|
||||||
isEnabled = false;
|
|
||||||
for (const QXmlStreamAttribute& attr : xmlReader.attributes()) {
|
|
||||||
if (attr.name() == QStringLiteral("isEnabled")) {
|
|
||||||
isEnabled = (attr.value().toString() == "true");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
versionMatches = (appVer.toStdString() == app_version);
|
|
||||||
|
|
||||||
} else if (xmlReader.name() == QStringLiteral("PatchList")) {
|
|
||||||
QJsonArray linesArray;
|
|
||||||
while (!xmlReader.atEnd() &&
|
|
||||||
!(xmlReader.tokenType() == QXmlStreamReader::EndElement &&
|
|
||||||
xmlReader.name() == QStringLiteral("PatchList"))) {
|
|
||||||
xmlReader.readNext();
|
|
||||||
if (xmlReader.tokenType() == QXmlStreamReader::StartElement &&
|
|
||||||
xmlReader.name() == QStringLiteral("Line")) {
|
|
||||||
QXmlStreamAttributes attributes = xmlReader.attributes();
|
|
||||||
QJsonObject lineObject;
|
|
||||||
lineObject["Type"] = attributes.value("Type").toString();
|
|
||||||
lineObject["Address"] = attributes.value("Address").toString();
|
|
||||||
lineObject["Value"] = attributes.value("Value").toString();
|
|
||||||
lineObject["Offset"] = attributes.value("Offset").toString();
|
|
||||||
if (lineObject["Type"].toString() == "mask_jump32") {
|
|
||||||
lineObject["Target"] = attributes.value("Target").toString();
|
|
||||||
lineObject["Size"] = attributes.value("Size").toString();
|
|
||||||
}
|
|
||||||
linesArray.append(lineObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
patchLines = linesArray;
|
|
||||||
if (isEnabled) {
|
|
||||||
foreach (const QJsonValue& value, patchLines) {
|
|
||||||
QJsonObject lineObject = value.toObject();
|
|
||||||
QString type = lineObject["Type"].toString();
|
|
||||||
|
|
||||||
if ((type != "mask" && type != "mask_jump32") && !versionMatches)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
QString address = lineObject["Address"].toString();
|
|
||||||
QString patchValue = lineObject["Value"].toString();
|
|
||||||
QString maskOffsetStr = lineObject["Offset"].toString();
|
|
||||||
|
|
||||||
QString targetStr;
|
|
||||||
QString sizeStr;
|
|
||||||
|
|
||||||
if (type == "mask_jump32") {
|
|
||||||
targetStr = lineObject["Target"].toString();
|
|
||||||
sizeStr = lineObject["Size"].toString();
|
|
||||||
} else {
|
|
||||||
patchValue = QString::fromStdString(convertValueToHex(
|
|
||||||
type.toStdString(), patchValue.toStdString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool littleEndian = false;
|
|
||||||
|
|
||||||
if (type == "bytes16" || type == "bytes32" || type == "bytes64")
|
|
||||||
littleEndian = true;
|
|
||||||
|
|
||||||
MemoryPatcher::PatchMask patchMask = MemoryPatcher::PatchMask::None;
|
|
||||||
int maskOffsetValue = 0;
|
|
||||||
|
|
||||||
if (type == "mask")
|
|
||||||
patchMask = MemoryPatcher::PatchMask::Mask;
|
|
||||||
|
|
||||||
if (type == "mask_jump32")
|
|
||||||
patchMask = MemoryPatcher::PatchMask::Mask_Jump32;
|
|
||||||
|
|
||||||
if ((type == "mask" || type == "mask_jump32") &&
|
|
||||||
!maskOffsetStr.toStdString().empty()) {
|
|
||||||
maskOffsetValue = std::stoi(maskOffsetStr.toStdString(), 0, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryPatcher::PatchMemory(
|
|
||||||
currentPatchName, address.toStdString(), patchValue.toStdString(),
|
|
||||||
targetStr.toStdString(), sizeStr.toStdString(), false, littleEndian,
|
|
||||||
patchMask, maskOffsetValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlReader.hasError()) {
|
|
||||||
LOG_ERROR(Loader, "Failed to parse XML for {}", g_game_serial);
|
|
||||||
} else {
|
|
||||||
LOG_INFO(Loader, "Patches loaded successfully, repository: {}", folder.toStdString());
|
|
||||||
}
|
|
||||||
ApplyPendingPatches();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPatchToQueue(patchInfo patchToAdd) {
|
void AddPatchToQueue(patchInfo patchToAdd) {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace MemoryPatcher {
|
|||||||
extern EXPORT uintptr_t g_eboot_address;
|
extern EXPORT uintptr_t g_eboot_address;
|
||||||
extern uint64_t g_eboot_image_size;
|
extern uint64_t g_eboot_image_size;
|
||||||
extern std::string g_game_serial;
|
extern std::string g_game_serial;
|
||||||
extern std::string patchFile;
|
extern std::string patch_file;
|
||||||
|
|
||||||
enum PatchMask : uint8_t {
|
enum PatchMask : uint8_t {
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -1,20 +1,14 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <half.hpp>
|
#include <half.hpp>
|
||||||
|
|
||||||
#include "common/number_utils.h"
|
#include "common/number_utils.h"
|
||||||
#include "video_core/amdgpu/pixel_format.h"
|
|
||||||
#include "video_core/amdgpu/types.h"
|
|
||||||
|
|
||||||
#define UF11_EXPONENT_SHIFT 6
|
constexpr u32 UF11_EXPONENT_SHIFT = 6;
|
||||||
#define UF10_EXPONENT_SHIFT 5
|
constexpr u32 UF10_EXPONENT_SHIFT = 5;
|
||||||
|
constexpr u32 RGB9E5_MANTISSA_BITS = 9;
|
||||||
#define RGB9E5_MANTISSA_BITS 9
|
constexpr u32 RGB9E5_EXP_BIAS = 1;
|
||||||
#define RGB9E5_EXP_BIAS 1
|
constexpr u32 F32_INFINITY = 0x7f800000;
|
||||||
|
|
||||||
#define F32_INFINITY 0x7f800000
|
|
||||||
|
|
||||||
namespace NumberUtils {
|
namespace NumberUtils {
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_QT_GUI
|
|
||||||
#include <QString>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Common::FS {
|
namespace Common::FS {
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
@@ -88,13 +84,6 @@ static std::optional<std::filesystem::path> GetBundleParentDirectory() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static auto UserPaths = [] {
|
static auto UserPaths = [] {
|
||||||
#if defined(__APPLE__) && defined(ENABLE_QT_GUI)
|
|
||||||
// Set the current path to the directory containing the app bundle.
|
|
||||||
if (const auto bundle_dir = GetBundleParentDirectory()) {
|
|
||||||
std::filesystem::current_path(*bundle_dir);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Try the portable user directory first.
|
// Try the portable user directory first.
|
||||||
auto user_dir = std::filesystem::current_path() / PORTABLE_DIR;
|
auto user_dir = std::filesystem::current_path() / PORTABLE_DIR;
|
||||||
if (!std::filesystem::exists(user_dir)) {
|
if (!std::filesystem::exists(user_dir)) {
|
||||||
@@ -229,22 +218,4 @@ std::optional<fs::path> FindGameByID(const fs::path& dir, const std::string& gam
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_QT_GUI
|
|
||||||
void PathToQString(QString& result, const std::filesystem::path& path) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
result = QString::fromStdWString(path.wstring());
|
|
||||||
#else
|
|
||||||
result = QString::fromStdString(path.string());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::path PathFromQString(const QString& path) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
return std::filesystem::path(path.toStdWString());
|
|
||||||
#else
|
|
||||||
return std::filesystem::path(path.toStdString());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace Common::FS
|
} // namespace Common::FS
|
||||||
|
|||||||
@@ -7,10 +7,6 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifdef ENABLE_QT_GUI
|
|
||||||
class QString; // to avoid including <QString> in this header
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Common::FS {
|
namespace Common::FS {
|
||||||
|
|
||||||
enum class PathType {
|
enum class PathType {
|
||||||
@@ -99,25 +95,6 @@ constexpr auto LOG_FILE = "shad_log.txt";
|
|||||||
*/
|
*/
|
||||||
void SetUserPath(PathType user_path, const std::filesystem::path& new_path);
|
void SetUserPath(PathType user_path, const std::filesystem::path& new_path);
|
||||||
|
|
||||||
#ifdef ENABLE_QT_GUI
|
|
||||||
/**
|
|
||||||
* Converts an std::filesystem::path to a QString.
|
|
||||||
* The native underlying string of a path is wstring on Windows and string on POSIX.
|
|
||||||
*
|
|
||||||
* @param result The resulting QString
|
|
||||||
* @param path The path to convert
|
|
||||||
*/
|
|
||||||
void PathToQString(QString& result, const std::filesystem::path& path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a QString to an std::filesystem::path.
|
|
||||||
* The native underlying string of a path is wstring on Windows and string on POSIX.
|
|
||||||
*
|
|
||||||
* @param path The path to convert
|
|
||||||
*/
|
|
||||||
[[nodiscard]] std::filesystem::path PathFromQString(const QString& path);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively searches for a game directory by its ID.
|
* Recursively searches for a game directory by its ID.
|
||||||
* Limits search depth to prevent excessive filesystem traversal.
|
* Limits search depth to prevent excessive filesystem traversal.
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <boost/icl/separate_interval_set.hpp>
|
|
||||||
#include "common/alignment.h"
|
#include "common/alignment.h"
|
||||||
#include "common/arch.h"
|
#include "common/arch.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/config.h"
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "core/address_space.h"
|
#include "core/address_space.h"
|
||||||
#include "core/libraries/kernel/memory.h"
|
#include "core/libraries/kernel/memory.h"
|
||||||
@@ -23,22 +23,70 @@
|
|||||||
// Reserve space for the system address space using a zerofill section.
|
// Reserve space for the system address space using a zerofill section.
|
||||||
asm(".zerofill SYSTEM_MANAGED,SYSTEM_MANAGED,__SYSTEM_MANAGED,0x7FFBFC000");
|
asm(".zerofill SYSTEM_MANAGED,SYSTEM_MANAGED,__SYSTEM_MANAGED,0x7FFBFC000");
|
||||||
asm(".zerofill SYSTEM_RESERVED,SYSTEM_RESERVED,__SYSTEM_RESERVED,0x7C0004000");
|
asm(".zerofill SYSTEM_RESERVED,SYSTEM_RESERVED,__SYSTEM_RESERVED,0x7C0004000");
|
||||||
|
asm(".zerofill USER_AREA,USER_AREA,__USER_AREA,0x5F9000000000");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
static constexpr size_t BackingSize = SCE_KERNEL_TOTAL_MEM_PRO;
|
// Constants used for mapping address space.
|
||||||
|
constexpr VAddr SYSTEM_MANAGED_MIN = 0x400000ULL;
|
||||||
|
constexpr VAddr SYSTEM_MANAGED_MAX = 0x7FFFFBFFFULL;
|
||||||
|
constexpr VAddr SYSTEM_RESERVED_MIN = 0x7FFFFC000ULL;
|
||||||
|
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
||||||
|
// Commpage ranges from 0xFC0000000 - 0xFFFFFFFFF, so decrease the system reserved maximum.
|
||||||
|
constexpr VAddr SYSTEM_RESERVED_MAX = 0xFBFFFFFFFULL;
|
||||||
|
// GPU-reserved memory ranges from 0x1000000000 - 0x6FFFFFFFFF, so increase the user minimum.
|
||||||
|
constexpr VAddr USER_MIN = 0x7000000000ULL;
|
||||||
|
#else
|
||||||
|
constexpr VAddr SYSTEM_RESERVED_MAX = 0xFFFFFFFFFULL;
|
||||||
|
constexpr VAddr USER_MIN = 0x1000000000ULL;
|
||||||
|
#endif
|
||||||
|
#if defined(__linux__)
|
||||||
|
// Linux maps the shadPS4 executable around here, so limit the user maximum
|
||||||
|
constexpr VAddr USER_MAX = 0x54FFFFFFFFFFULL;
|
||||||
|
#else
|
||||||
|
constexpr VAddr USER_MAX = 0x5FFFFFFFFFFFULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Constants for the sizes of the ranges in address space.
|
||||||
|
static constexpr u64 SystemManagedSize = SYSTEM_MANAGED_MAX - SYSTEM_MANAGED_MIN + 1;
|
||||||
|
static constexpr u64 SystemReservedSize = SYSTEM_RESERVED_MAX - SYSTEM_RESERVED_MIN + 1;
|
||||||
|
static constexpr u64 UserSize = USER_MAX - USER_MIN + 1;
|
||||||
|
|
||||||
|
// Required backing file size for mapping physical address space.
|
||||||
|
static u64 BackingSize = ORBIS_KERNEL_TOTAL_MEM_DEV_PRO;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
[[nodiscard]] constexpr u64 ToWindowsProt(Core::MemoryProt prot) {
|
[[nodiscard]] constexpr u64 ToWindowsProt(Core::MemoryProt prot) {
|
||||||
if (True(prot & Core::MemoryProt::CpuReadWrite) ||
|
const bool read =
|
||||||
True(prot & Core::MemoryProt::GpuReadWrite)) {
|
True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead);
|
||||||
return PAGE_READWRITE;
|
const bool write =
|
||||||
} else if (True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead)) {
|
True(prot & Core::MemoryProt::CpuWrite) || True(prot & Core::MemoryProt::GpuWrite);
|
||||||
return PAGE_READONLY;
|
const bool execute = True(prot & Core::MemoryProt::CpuExec);
|
||||||
|
|
||||||
|
if (write && !read) {
|
||||||
|
// While write-only CPU mappings aren't possible, write-only GPU mappings are.
|
||||||
|
LOG_WARNING(Core, "Converting write-only mapping to read-write");
|
||||||
|
}
|
||||||
|
|
||||||
|
// All cases involving execute permissions have separate permissions.
|
||||||
|
if (execute) {
|
||||||
|
if (write) {
|
||||||
|
return PAGE_EXECUTE_READWRITE;
|
||||||
|
} else if (read && !write) {
|
||||||
|
return PAGE_EXECUTE_READ;
|
||||||
|
} else {
|
||||||
|
return PAGE_EXECUTE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return PAGE_NOACCESS;
|
if (write) {
|
||||||
|
return PAGE_READWRITE;
|
||||||
|
} else if (read && !write) {
|
||||||
|
return PAGE_READONLY;
|
||||||
|
} else {
|
||||||
|
return PAGE_NOACCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,70 +98,100 @@ struct MemoryRegion {
|
|||||||
|
|
||||||
struct AddressSpace::Impl {
|
struct AddressSpace::Impl {
|
||||||
Impl() : process{GetCurrentProcess()} {
|
Impl() : process{GetCurrentProcess()} {
|
||||||
// Allocate virtual address placeholder for our address space.
|
// Determine the system's page alignment
|
||||||
MEM_ADDRESS_REQUIREMENTS req{};
|
SYSTEM_INFO sys_info{};
|
||||||
MEM_EXTENDED_PARAMETER param{};
|
GetSystemInfo(&sys_info);
|
||||||
req.LowestStartingAddress = reinterpret_cast<PVOID>(SYSTEM_MANAGED_MIN);
|
u64 alignment = sys_info.dwAllocationGranularity;
|
||||||
// The ending address must align to page boundary - 1
|
|
||||||
// https://stackoverflow.com/questions/54223343/virtualalloc2-with-memextendedparameteraddressrequirements-always-produces-error
|
|
||||||
req.HighestEndingAddress = reinterpret_cast<PVOID>(USER_MIN + UserSize - 1);
|
|
||||||
req.Alignment = 0;
|
|
||||||
param.Type = MemExtendedParameterAddressRequirements;
|
|
||||||
param.Pointer = &req;
|
|
||||||
|
|
||||||
// Typically, lower parts of system managed area is already reserved in windows.
|
// Determine the host OS build number
|
||||||
// If reservation fails attempt again by reducing the area size a little bit.
|
// Retrieve module handle for ntdll
|
||||||
// System managed is about 31GB in size so also cap the number of times we can reduce it
|
auto ntdll_handle = GetModuleHandleW(L"ntdll.dll");
|
||||||
// to a reasonable amount.
|
ASSERT_MSG(ntdll_handle, "Failed to retrieve ntdll handle");
|
||||||
static constexpr size_t ReductionOnFail = 1_GB;
|
|
||||||
static constexpr size_t MaxReductions = 10;
|
|
||||||
|
|
||||||
size_t virtual_size = SystemManagedSize + SystemReservedSize + UserSize;
|
// Get the RtlGetVersion function
|
||||||
for (u32 i = 0; i < MaxReductions; i++) {
|
s64(WINAPI * RtlGetVersion)(LPOSVERSIONINFOW);
|
||||||
virtual_base = static_cast<u8*>(VirtualAlloc2(process, NULL, virtual_size,
|
*(FARPROC*)&RtlGetVersion = GetProcAddress(ntdll_handle, "RtlGetVersion");
|
||||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
|
ASSERT_MSG(RtlGetVersion, "failed to retrieve function pointer for RtlGetVersion");
|
||||||
PAGE_NOACCESS, ¶m, 1));
|
|
||||||
if (virtual_base) {
|
// Call RtlGetVersion
|
||||||
break;
|
RTL_OSVERSIONINFOW os_version_info{};
|
||||||
}
|
RtlGetVersion(&os_version_info);
|
||||||
virtual_size -= ReductionOnFail;
|
|
||||||
|
u64 supported_user_max = USER_MAX;
|
||||||
|
// This is the build number for Windows 11 22H2
|
||||||
|
static constexpr s32 AffectedBuildNumber = 22621;
|
||||||
|
if (os_version_info.dwBuildNumber <= AffectedBuildNumber) {
|
||||||
|
// Older Windows builds have an issue with VirtualAlloc2 on higher addresses.
|
||||||
|
// To prevent regressions, limit the maximum address we reserve for this platform.
|
||||||
|
supported_user_max = 0x11000000000ULL;
|
||||||
|
LOG_WARNING(Core, "Windows 10 detected, reducing user max to {:#x} to avoid problems",
|
||||||
|
supported_user_max);
|
||||||
}
|
}
|
||||||
ASSERT_MSG(virtual_base, "Unable to reserve virtual address space: {}",
|
|
||||||
Common::GetLastErrorMsg());
|
|
||||||
|
|
||||||
|
// Determine the free address ranges we can access.
|
||||||
|
VAddr next_addr = SYSTEM_MANAGED_MIN;
|
||||||
|
MEMORY_BASIC_INFORMATION info{};
|
||||||
|
while (next_addr <= supported_user_max) {
|
||||||
|
ASSERT_MSG(VirtualQuery(reinterpret_cast<PVOID>(next_addr), &info, sizeof(info)),
|
||||||
|
"Failed to query memory information for address {:#x}", next_addr);
|
||||||
|
|
||||||
|
// Ensure logic uses values aligned to bage boundaries.
|
||||||
|
next_addr = reinterpret_cast<VAddr>(info.BaseAddress) + info.RegionSize;
|
||||||
|
next_addr = Common::AlignUp(next_addr, alignment);
|
||||||
|
|
||||||
|
// Prevent size from going past supported_user_max
|
||||||
|
u64 size = info.RegionSize;
|
||||||
|
if (next_addr > supported_user_max) {
|
||||||
|
size -= (next_addr - supported_user_max);
|
||||||
|
}
|
||||||
|
size = Common::AlignDown(size, alignment);
|
||||||
|
|
||||||
|
// Check for free memory areas
|
||||||
|
// Restrict region size to avoid overly fragmenting the virtual memory space.
|
||||||
|
if (info.State == MEM_FREE && info.RegionSize > 0x1000000) {
|
||||||
|
VAddr addr = Common::AlignUp(reinterpret_cast<VAddr>(info.BaseAddress), alignment);
|
||||||
|
regions.emplace(addr, MemoryRegion{addr, size, false});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reserve all detected free regions.
|
||||||
|
for (auto region : regions) {
|
||||||
|
auto addr = static_cast<u8*>(VirtualAlloc2(
|
||||||
|
process, reinterpret_cast<PVOID>(region.second.base), region.second.size,
|
||||||
|
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, NULL, 0));
|
||||||
|
// All marked regions should reserve fine since they're free.
|
||||||
|
ASSERT_MSG(addr, "Unable to reserve virtual address space: {}",
|
||||||
|
Common::GetLastErrorMsg());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set these constants to ensure code relying on them works.
|
||||||
|
// These do not fully encapsulate the state of the address space.
|
||||||
|
system_managed_base = reinterpret_cast<u8*>(regions.begin()->first);
|
||||||
|
system_managed_size = SystemManagedSize - (regions.begin()->first - SYSTEM_MANAGED_MIN);
|
||||||
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
||||||
system_reserved_size = SystemReservedSize;
|
system_reserved_size = SystemReservedSize;
|
||||||
system_managed_base = virtual_base;
|
|
||||||
system_managed_size = system_reserved_base - virtual_base;
|
|
||||||
user_base = reinterpret_cast<u8*>(USER_MIN);
|
user_base = reinterpret_cast<u8*>(USER_MIN);
|
||||||
user_size = virtual_base + virtual_size - user_base;
|
user_size = supported_user_max - USER_MIN - 1;
|
||||||
|
|
||||||
LOG_INFO(Kernel_Vmm, "System managed virtual memory region: {} - {}",
|
// Increase BackingSize to account for config options.
|
||||||
fmt::ptr(system_managed_base),
|
BackingSize += Config::getExtraDmemInMbytes() * 1_MB;
|
||||||
fmt::ptr(system_managed_base + system_managed_size - 1));
|
|
||||||
LOG_INFO(Kernel_Vmm, "System reserved virtual memory region: {} - {}",
|
|
||||||
fmt::ptr(system_reserved_base),
|
|
||||||
fmt::ptr(system_reserved_base + system_reserved_size - 1));
|
|
||||||
LOG_INFO(Kernel_Vmm, "User virtual memory region: {} - {}", fmt::ptr(user_base),
|
|
||||||
fmt::ptr(user_base + user_size - 1));
|
|
||||||
|
|
||||||
// Initializer placeholder tracker
|
|
||||||
const uintptr_t system_managed_addr = reinterpret_cast<uintptr_t>(system_managed_base);
|
|
||||||
regions.emplace(system_managed_addr,
|
|
||||||
MemoryRegion{system_managed_addr, virtual_size, false});
|
|
||||||
|
|
||||||
// Allocate backing file that represents the total physical memory.
|
// Allocate backing file that represents the total physical memory.
|
||||||
backing_handle =
|
backing_handle = CreateFileMapping2(INVALID_HANDLE_VALUE, nullptr, FILE_MAP_ALL_ACCESS,
|
||||||
CreateFileMapping2(INVALID_HANDLE_VALUE, nullptr, FILE_MAP_WRITE | FILE_MAP_READ,
|
PAGE_EXECUTE_READWRITE, SEC_COMMIT, BackingSize,
|
||||||
PAGE_READWRITE, SEC_COMMIT, BackingSize, nullptr, nullptr, 0);
|
nullptr, nullptr, 0);
|
||||||
|
|
||||||
ASSERT_MSG(backing_handle, "{}", Common::GetLastErrorMsg());
|
ASSERT_MSG(backing_handle, "{}", Common::GetLastErrorMsg());
|
||||||
// Allocate a virtual memory for the backing file map as placeholder
|
// Allocate a virtual memory for the backing file map as placeholder
|
||||||
backing_base = static_cast<u8*>(VirtualAlloc2(process, nullptr, BackingSize,
|
backing_base = static_cast<u8*>(VirtualAlloc2(process, nullptr, BackingSize,
|
||||||
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
|
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
|
||||||
PAGE_NOACCESS, nullptr, 0));
|
PAGE_NOACCESS, nullptr, 0));
|
||||||
|
ASSERT_MSG(backing_base, "{}", Common::GetLastErrorMsg());
|
||||||
|
|
||||||
// Map backing placeholder. This will commit the pages
|
// Map backing placeholder. This will commit the pages
|
||||||
void* const ret = MapViewOfFile3(backing_handle, process, backing_base, 0, BackingSize,
|
void* const ret =
|
||||||
MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, nullptr, 0);
|
MapViewOfFile3(backing_handle, process, backing_base, 0, BackingSize,
|
||||||
|
MEM_REPLACE_PLACEHOLDER, PAGE_EXECUTE_READWRITE, nullptr, 0);
|
||||||
ASSERT_MSG(ret == backing_base, "{}", Common::GetLastErrorMsg());
|
ASSERT_MSG(ret == backing_base, "{}", Common::GetLastErrorMsg());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +232,12 @@ struct AddressSpace::Impl {
|
|||||||
ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg());
|
ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg());
|
||||||
} else {
|
} else {
|
||||||
ptr = MapViewOfFile3(backing, process, reinterpret_cast<PVOID>(virtual_addr),
|
ptr = MapViewOfFile3(backing, process, reinterpret_cast<PVOID>(virtual_addr),
|
||||||
phys_addr, size, MEM_REPLACE_PLACEHOLDER, prot, nullptr, 0);
|
phys_addr, size, MEM_REPLACE_PLACEHOLDER,
|
||||||
|
PAGE_EXECUTE_READWRITE, nullptr, 0);
|
||||||
|
ASSERT_MSG(ptr, "MapViewOfFile3 failed. {}", Common::GetLastErrorMsg());
|
||||||
|
DWORD resultvar;
|
||||||
|
bool ret = VirtualProtect(ptr, size, prot, &resultvar);
|
||||||
|
ASSERT_MSG(ret, "VirtualProtect failed. {}", Common::GetLastErrorMsg());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ptr =
|
ptr =
|
||||||
@@ -296,17 +379,33 @@ struct AddressSpace::Impl {
|
|||||||
void Protect(VAddr virtual_addr, size_t size, bool read, bool write, bool execute) {
|
void Protect(VAddr virtual_addr, size_t size, bool read, bool write, bool execute) {
|
||||||
DWORD new_flags{};
|
DWORD new_flags{};
|
||||||
|
|
||||||
if (read && write && execute) {
|
if (write && !read) {
|
||||||
new_flags = PAGE_EXECUTE_READWRITE;
|
// While write-only CPU protection isn't possible, write-only GPU protection is.
|
||||||
} else if (read && write) {
|
LOG_WARNING(Core, "Converting write-only protection to read-write");
|
||||||
new_flags = PAGE_READWRITE;
|
}
|
||||||
} else if (read && !write) {
|
|
||||||
new_flags = PAGE_READONLY;
|
// All cases involving execute permissions have separate permissions.
|
||||||
} else if (execute && !read && !write) {
|
if (execute) {
|
||||||
new_flags = PAGE_EXECUTE;
|
// If there's some form of write protection requested, provide read-write permissions.
|
||||||
} else if (!read && !write && !execute) {
|
if (write) {
|
||||||
new_flags = PAGE_NOACCESS;
|
new_flags = PAGE_EXECUTE_READWRITE;
|
||||||
|
} else if (read && !write) {
|
||||||
|
new_flags = PAGE_EXECUTE_READ;
|
||||||
|
} else {
|
||||||
|
new_flags = PAGE_EXECUTE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (write) {
|
||||||
|
new_flags = PAGE_READWRITE;
|
||||||
|
} else if (read && !write) {
|
||||||
|
new_flags = PAGE_READONLY;
|
||||||
|
} else {
|
||||||
|
new_flags = PAGE_NOACCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no flags are assigned, then something's gone wrong.
|
||||||
|
if (new_flags == 0) {
|
||||||
LOG_CRITICAL(Common_Memory,
|
LOG_CRITICAL(Common_Memory,
|
||||||
"Unsupported protection flag combination for address {:#x}, size {}, "
|
"Unsupported protection flag combination for address {:#x}, size {}, "
|
||||||
"read={}, write={}, execute={}",
|
"read={}, write={}, execute={}",
|
||||||
@@ -326,12 +425,20 @@ struct AddressSpace::Impl {
|
|||||||
DWORD old_flags{};
|
DWORD old_flags{};
|
||||||
if (!VirtualProtectEx(process, LPVOID(range_addr), range_size, new_flags, &old_flags)) {
|
if (!VirtualProtectEx(process, LPVOID(range_addr), range_size, new_flags, &old_flags)) {
|
||||||
UNREACHABLE_MSG(
|
UNREACHABLE_MSG(
|
||||||
"Failed to change virtual memory protection for address {:#x}, size {}",
|
"Failed to change virtual memory protection for address {:#x}, size {:#x}",
|
||||||
range_addr, range_size);
|
range_addr, range_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::icl::interval_set<VAddr> GetUsableRegions() {
|
||||||
|
boost::icl::interval_set<VAddr> reserved_regions;
|
||||||
|
for (auto region : regions) {
|
||||||
|
reserved_regions.insert({region.second.base, region.second.base + region.second.size});
|
||||||
|
}
|
||||||
|
return reserved_regions;
|
||||||
|
}
|
||||||
|
|
||||||
HANDLE process{};
|
HANDLE process{};
|
||||||
HANDLE backing_handle{};
|
HANDLE backing_handle{};
|
||||||
u8* backing_base{};
|
u8* backing_base{};
|
||||||
@@ -356,62 +463,73 @@ enum PosixPageProtection {
|
|||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] constexpr PosixPageProtection ToPosixProt(Core::MemoryProt prot) {
|
[[nodiscard]] constexpr PosixPageProtection ToPosixProt(Core::MemoryProt prot) {
|
||||||
if (True(prot & Core::MemoryProt::CpuReadWrite) ||
|
const bool read =
|
||||||
True(prot & Core::MemoryProt::GpuReadWrite)) {
|
True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead);
|
||||||
if (True(prot & Core::MemoryProt::CpuExec)) {
|
const bool write =
|
||||||
|
True(prot & Core::MemoryProt::CpuWrite) || True(prot & Core::MemoryProt::GpuWrite);
|
||||||
|
const bool execute = True(prot & Core::MemoryProt::CpuExec);
|
||||||
|
|
||||||
|
if (write && !read) {
|
||||||
|
// While write-only CPU mappings aren't possible, write-only GPU mappings are.
|
||||||
|
LOG_WARNING(Core, "Converting write-only mapping to read-write");
|
||||||
|
}
|
||||||
|
|
||||||
|
// All cases involving execute permissions have separate permissions.
|
||||||
|
if (execute) {
|
||||||
|
if (write) {
|
||||||
return PAGE_EXECUTE_READWRITE;
|
return PAGE_EXECUTE_READWRITE;
|
||||||
} else {
|
} else if (read && !write) {
|
||||||
return PAGE_READWRITE;
|
|
||||||
}
|
|
||||||
} else if (True(prot & Core::MemoryProt::CpuRead) || True(prot & Core::MemoryProt::GpuRead)) {
|
|
||||||
if (True(prot & Core::MemoryProt::CpuExec)) {
|
|
||||||
return PAGE_EXECUTE_READ;
|
return PAGE_EXECUTE_READ;
|
||||||
} else {
|
} else {
|
||||||
return PAGE_READONLY;
|
return PAGE_EXECUTE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return PAGE_NOACCESS;
|
if (write) {
|
||||||
|
return PAGE_READWRITE;
|
||||||
|
} else if (read && !write) {
|
||||||
|
return PAGE_READONLY;
|
||||||
|
} else {
|
||||||
|
return PAGE_NOACCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AddressSpace::Impl {
|
struct AddressSpace::Impl {
|
||||||
Impl() {
|
Impl() {
|
||||||
|
BackingSize += Config::getExtraDmemInMbytes() * 1_MB;
|
||||||
// Allocate virtual address placeholder for our address space.
|
// Allocate virtual address placeholder for our address space.
|
||||||
system_managed_size = SystemManagedSize;
|
system_managed_size = SystemManagedSize;
|
||||||
system_reserved_size = SystemReservedSize;
|
system_reserved_size = SystemReservedSize;
|
||||||
user_size = UserSize;
|
user_size = UserSize;
|
||||||
|
|
||||||
constexpr int protection_flags = PROT_READ | PROT_WRITE;
|
constexpr int protection_flags = PROT_READ | PROT_WRITE;
|
||||||
constexpr int base_map_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE;
|
constexpr int map_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED;
|
||||||
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
||||||
// On ARM64 Macs under Rosetta 2, we run into limitations due to the commpage from
|
// On ARM64 Macs, we run into limitations due to the commpage from 0xFC0000000 - 0xFFFFFFFFF
|
||||||
// 0xFC0000000 - 0xFFFFFFFFF and the GPU carveout region from 0x1000000000 - 0x6FFFFFFFFF.
|
// and the GPU carveout region from 0x1000000000 - 0x6FFFFFFFFF. Because this creates gaps
|
||||||
// We can allocate the system managed region, as well as system reserved if reduced in size
|
// in the available virtual memory region, we map memory space using three distinct parts.
|
||||||
// slightly, but we cannot map the user region where we want, so we must let the OS put it
|
system_managed_base =
|
||||||
// wherever possible and hope the game won't rely on its location.
|
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN),
|
||||||
system_managed_base = reinterpret_cast<u8*>(
|
system_managed_size, protection_flags, map_flags, -1, 0));
|
||||||
mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN), system_managed_size, protection_flags,
|
system_reserved_base =
|
||||||
base_map_flags | MAP_FIXED, -1, 0));
|
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_RESERVED_MIN),
|
||||||
system_reserved_base = reinterpret_cast<u8*>(
|
system_reserved_size, protection_flags, map_flags, -1, 0));
|
||||||
mmap(reinterpret_cast<void*>(SYSTEM_RESERVED_MIN), system_reserved_size,
|
user_base = reinterpret_cast<u8*>(
|
||||||
protection_flags, base_map_flags | MAP_FIXED, -1, 0));
|
mmap(reinterpret_cast<void*>(USER_MIN), user_size, protection_flags, map_flags, -1, 0));
|
||||||
// Cannot guarantee enough space for these areas at the desired addresses, so not MAP_FIXED.
|
|
||||||
user_base = reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(USER_MIN), user_size,
|
|
||||||
protection_flags, base_map_flags, -1, 0));
|
|
||||||
#else
|
#else
|
||||||
const auto virtual_size = system_managed_size + system_reserved_size + user_size;
|
const auto virtual_size = system_managed_size + system_reserved_size + user_size;
|
||||||
#if defined(ARCH_X86_64)
|
#if defined(ARCH_X86_64)
|
||||||
const auto virtual_base =
|
const auto virtual_base =
|
||||||
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN), virtual_size,
|
reinterpret_cast<u8*>(mmap(reinterpret_cast<void*>(SYSTEM_MANAGED_MIN), virtual_size,
|
||||||
protection_flags, base_map_flags | MAP_FIXED, -1, 0));
|
protection_flags, map_flags, -1, 0));
|
||||||
system_managed_base = virtual_base;
|
system_managed_base = virtual_base;
|
||||||
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
|
||||||
user_base = reinterpret_cast<u8*>(USER_MIN);
|
user_base = reinterpret_cast<u8*>(USER_MIN);
|
||||||
#else
|
#else
|
||||||
// Map memory wherever possible and instruction translation can handle offsetting to the
|
// Map memory wherever possible and instruction translation can handle offsetting to the
|
||||||
// base.
|
// base.
|
||||||
const auto virtual_base = reinterpret_cast<u8*>(
|
const auto virtual_base =
|
||||||
mmap(nullptr, virtual_size, protection_flags, base_map_flags, -1, 0));
|
reinterpret_cast<u8*>(mmap(nullptr, virtual_size, protection_flags, map_flags, -1, 0));
|
||||||
system_managed_base = virtual_base;
|
system_managed_base = virtual_base;
|
||||||
system_reserved_base = virtual_base + SYSTEM_RESERVED_MIN - SYSTEM_MANAGED_MIN;
|
system_reserved_base = virtual_base + SYSTEM_RESERVED_MIN - SYSTEM_MANAGED_MIN;
|
||||||
user_base = virtual_base + USER_MIN - SYSTEM_MANAGED_MIN;
|
user_base = virtual_base + USER_MIN - SYSTEM_MANAGED_MIN;
|
||||||
@@ -579,9 +697,9 @@ void AddressSpace::Unmap(VAddr virtual_addr, size_t size, VAddr start_in_vma, VA
|
|||||||
// the entire allocation and remap the portions outside of the requested unmapping range.
|
// the entire allocation and remap the portions outside of the requested unmapping range.
|
||||||
impl->Unmap(virtual_addr, size, has_backing && !readonly_file);
|
impl->Unmap(virtual_addr, size, has_backing && !readonly_file);
|
||||||
|
|
||||||
// TODO: Determine if any titles require partial unmapping support for flexible allocations.
|
// TODO: Determine if any titles require partial unmapping support for un-backed allocations.
|
||||||
ASSERT_MSG(has_backing || (start_in_vma == 0 && end_in_vma == size),
|
ASSERT_MSG(has_backing || (start_in_vma == 0 && end_in_vma == size),
|
||||||
"Partial unmapping of flexible allocations is not supported");
|
"Partial unmapping of un-backed allocations is not supported");
|
||||||
|
|
||||||
if (start_in_vma != 0) {
|
if (start_in_vma != 0) {
|
||||||
Map(virtual_addr, start_in_vma, 0, phys_base, is_exec);
|
Map(virtual_addr, start_in_vma, 0, phys_base, is_exec);
|
||||||
@@ -602,4 +720,22 @@ void AddressSpace::Protect(VAddr virtual_addr, size_t size, MemoryPermission per
|
|||||||
return impl->Protect(virtual_addr, size, read, write, execute);
|
return impl->Protect(virtual_addr, size, read, write, execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::icl::interval_set<VAddr> AddressSpace::GetUsableRegions() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
// On Windows, we need to obtain the accessible intervals from the implementation's regions.
|
||||||
|
return impl->GetUsableRegions();
|
||||||
|
#else
|
||||||
|
// On Linux and Mac, the memory space is fully represented by the three major regions
|
||||||
|
boost::icl::interval_set<VAddr> reserved_regions;
|
||||||
|
VAddr system_managed_addr = reinterpret_cast<VAddr>(system_managed_base);
|
||||||
|
VAddr system_reserved_addr = reinterpret_cast<VAddr>(system_reserved_base);
|
||||||
|
VAddr user_addr = reinterpret_cast<VAddr>(user_base);
|
||||||
|
|
||||||
|
reserved_regions.insert({system_managed_addr, system_managed_addr + system_managed_size});
|
||||||
|
reserved_regions.insert({system_reserved_addr, system_reserved_addr + system_reserved_size});
|
||||||
|
reserved_regions.insert({user_addr, user_addr + user_size});
|
||||||
|
return reserved_regions;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Core
|
} // namespace Core
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <boost/icl/separate_interval_set.hpp>
|
||||||
#include "common/arch.h"
|
#include "common/arch.h"
|
||||||
#include "common/enum.h"
|
#include "common/enum.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
@@ -20,22 +21,6 @@ enum class MemoryPermission : u32 {
|
|||||||
};
|
};
|
||||||
DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission)
|
DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission)
|
||||||
|
|
||||||
constexpr VAddr SYSTEM_MANAGED_MIN = 0x00000400000ULL;
|
|
||||||
constexpr VAddr SYSTEM_MANAGED_MAX = 0x07FFFFBFFFULL;
|
|
||||||
constexpr VAddr SYSTEM_RESERVED_MIN = 0x07FFFFC000ULL;
|
|
||||||
#if defined(__APPLE__) && defined(ARCH_X86_64)
|
|
||||||
// Can only comfortably reserve the first 0x7C0000000 of system reserved space.
|
|
||||||
constexpr VAddr SYSTEM_RESERVED_MAX = 0xFBFFFFFFFULL;
|
|
||||||
#else
|
|
||||||
constexpr VAddr SYSTEM_RESERVED_MAX = 0xFFFFFFFFFULL;
|
|
||||||
#endif
|
|
||||||
constexpr VAddr USER_MIN = 0x1000000000ULL;
|
|
||||||
constexpr VAddr USER_MAX = 0xFBFFFFFFFFULL;
|
|
||||||
|
|
||||||
static constexpr size_t SystemManagedSize = SYSTEM_MANAGED_MAX - SYSTEM_MANAGED_MIN + 1;
|
|
||||||
static constexpr size_t SystemReservedSize = SYSTEM_RESERVED_MAX - SYSTEM_RESERVED_MIN + 1;
|
|
||||||
static constexpr size_t UserSize = 1ULL << 40;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the user virtual address space backed by a dmem memory block
|
* Represents the user virtual address space backed by a dmem memory block
|
||||||
*/
|
*/
|
||||||
@@ -100,6 +85,9 @@ public:
|
|||||||
|
|
||||||
void Protect(VAddr virtual_addr, size_t size, MemoryPermission perms);
|
void Protect(VAddr virtual_addr, size_t size, MemoryPermission perms);
|
||||||
|
|
||||||
|
// Returns an interval set containing all usable regions.
|
||||||
|
boost::icl::interval_set<VAddr> GetUsableRegions();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Impl;
|
struct Impl;
|
||||||
std::unique_ptr<Impl> impl;
|
std::unique_ptr<Impl> impl;
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ std::optional<RegDump*> DebugStateImpl::GetRegDump(uintptr_t base_addr, uintptr_
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
||||||
const AmdGpu::Liverpool::Regs& regs) {
|
const AmdGpu::Regs& regs) {
|
||||||
std::scoped_lock lock{frame_dump_list_mutex};
|
std::scoped_lock lock{frame_dump_list_mutex};
|
||||||
|
|
||||||
auto dump = GetRegDump(base_addr, header_addr);
|
auto dump = GetRegDump(base_addr, header_addr);
|
||||||
@@ -170,15 +170,14 @@ void DebugStateImpl::PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
|||||||
for (int i = 0; i < RegDump::MaxShaderStages; i++) {
|
for (int i = 0; i < RegDump::MaxShaderStages; i++) {
|
||||||
if ((*dump)->regs.stage_enable.IsStageEnabled(i)) {
|
if ((*dump)->regs.stage_enable.IsStageEnabled(i)) {
|
||||||
auto stage = (*dump)->regs.ProgramForStage(i);
|
auto stage = (*dump)->regs.ProgramForStage(i);
|
||||||
if (stage->address_lo != 0) {
|
if (stage->address) {
|
||||||
const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(stage->Address<u32*>());
|
const auto params = AmdGpu::GetParams(*stage);
|
||||||
auto code = stage->Code();
|
|
||||||
(*dump)->stages[i] = PipelineShaderProgramDump{
|
(*dump)->stages[i] = PipelineShaderProgramDump{
|
||||||
.name = Vulkan::PipelineCache::GetShaderName(Shader::StageFromIndex(i),
|
.name = Vulkan::PipelineCache::GetShaderName(Shader::StageFromIndex(i),
|
||||||
info.shader_hash),
|
params.hash),
|
||||||
.hash = info.shader_hash,
|
.hash = params.hash,
|
||||||
.user_data = *stage,
|
.user_data = *stage,
|
||||||
.code = std::vector<u32>{code.begin(), code.end()},
|
.code = std::vector<u32>{params.code.begin(), params.code.end()},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,12 +197,12 @@ void DebugStateImpl::PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_a
|
|||||||
auto& cs = (*dump)->regs.cs_program;
|
auto& cs = (*dump)->regs.cs_program;
|
||||||
cs = cs_state;
|
cs = cs_state;
|
||||||
|
|
||||||
const auto& info = AmdGpu::Liverpool::SearchBinaryInfo(cs.Address<u32*>());
|
const auto params = AmdGpu::GetParams(cs);
|
||||||
(*dump)->cs_data = PipelineComputerProgramDump{
|
(*dump)->cs_data = PipelineComputerProgramDump{
|
||||||
.name = Vulkan::PipelineCache::GetShaderName(Shader::Stage::Compute, info.shader_hash),
|
.name = Vulkan::PipelineCache::GetShaderName(Shader::Stage::Compute, params.hash),
|
||||||
.hash = info.shader_hash,
|
.hash = params.hash,
|
||||||
.cs_program = cs,
|
.cs_program = cs,
|
||||||
.code = std::vector<u32>{cs.Code().begin(), cs.Code().end()},
|
.code = std::vector<u32>{params.code.begin(), params.code.end()},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,9 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
|
#include "shader_recompiler/runtime_info.h"
|
||||||
|
#include "video_core/amdgpu/regs.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_common.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
@@ -54,21 +56,21 @@ struct QueueDump {
|
|||||||
struct PipelineShaderProgramDump {
|
struct PipelineShaderProgramDump {
|
||||||
std::string name;
|
std::string name;
|
||||||
u64 hash;
|
u64 hash;
|
||||||
Vulkan::Liverpool::ShaderProgram user_data{};
|
AmdGpu::ShaderProgram user_data{};
|
||||||
std::vector<u32> code{};
|
std::vector<u32> code{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PipelineComputerProgramDump {
|
struct PipelineComputerProgramDump {
|
||||||
std::string name;
|
std::string name;
|
||||||
u64 hash;
|
u64 hash;
|
||||||
Vulkan::Liverpool::ComputeProgram cs_program{};
|
AmdGpu::ComputeProgram cs_program{};
|
||||||
std::vector<u32> code{};
|
std::vector<u32> code{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RegDump {
|
struct RegDump {
|
||||||
bool is_compute{false};
|
bool is_compute{false};
|
||||||
static constexpr size_t MaxShaderStages = 5;
|
static constexpr size_t MaxShaderStages = 5;
|
||||||
Vulkan::Liverpool::Regs regs{};
|
AmdGpu::Regs regs;
|
||||||
std::array<PipelineShaderProgramDump, MaxShaderStages> stages{};
|
std::array<PipelineShaderProgramDump, MaxShaderStages> stages{};
|
||||||
PipelineComputerProgramDump cs_data{};
|
PipelineComputerProgramDump cs_data{};
|
||||||
};
|
};
|
||||||
@@ -219,9 +221,8 @@ public:
|
|||||||
|
|
||||||
void PushQueueDump(QueueDump dump);
|
void PushQueueDump(QueueDump dump);
|
||||||
|
|
||||||
void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr,
|
void PushRegsDump(uintptr_t base_addr, uintptr_t header_addr, const AmdGpu::Regs& regs);
|
||||||
const AmdGpu::Liverpool::Regs& regs);
|
using CsState = AmdGpu::ComputeProgram;
|
||||||
using CsState = AmdGpu::Liverpool::ComputeProgram;
|
|
||||||
void PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_addr, const CsState& cs_state);
|
void PushRegsDumpCompute(uintptr_t base_addr, uintptr_t header_addr, const CsState& cs_state);
|
||||||
|
|
||||||
void CollectShader(const std::string& name, Shader::LogicalStage l_stage,
|
void CollectShader(const std::string& name, Shader::LogicalStage l_stage,
|
||||||
|
|||||||
99
src/core/debugger.cpp
Normal file
99
src/core/debugger.cpp
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "debugger.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <debugapi.h>
|
||||||
|
#elif defined(__linux__)
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool Core::Debugger::IsDebuggerAttached() {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return IsDebuggerPresent();
|
||||||
|
#elif defined(__linux__)
|
||||||
|
std::ifstream status_file("/proc/self/status");
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(status_file, line)) {
|
||||||
|
if (line.starts_with("TracerPid:")) {
|
||||||
|
std::string tracer_pid = line.substr(10);
|
||||||
|
tracer_pid.erase(0, tracer_pid.find_first_not_of(" \t"));
|
||||||
|
return tracer_pid != "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
int mib[4];
|
||||||
|
struct kinfo_proc info;
|
||||||
|
size_t size = sizeof(info);
|
||||||
|
|
||||||
|
mib[0] = CTL_KERN;
|
||||||
|
mib[1] = KERN_PROC;
|
||||||
|
mib[2] = KERN_PROC_PID;
|
||||||
|
mib[3] = getpid();
|
||||||
|
|
||||||
|
if (sysctl(mib, 4, &info, &size, nullptr, 0) == 0) {
|
||||||
|
return (info.kp_proc.p_flag & P_TRACED) != 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
#error "Unsupported platform"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Debugger::WaitForDebuggerAttach() {
|
||||||
|
int count = 0;
|
||||||
|
while (!IsDebuggerAttached()) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||||
|
if (--count <= 0) {
|
||||||
|
count = 10;
|
||||||
|
std::cerr << "Waiting for debugger to attach..." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int Core::Debugger::GetCurrentPid() {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return GetCurrentProcessId();
|
||||||
|
#elif defined(__APPLE__) || defined(__linux__)
|
||||||
|
return getpid();
|
||||||
|
#else
|
||||||
|
#error "Unsupported platform"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Debugger::WaitForPid(int pid) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
HANDLE process_handle = OpenProcess(SYNCHRONIZE, FALSE, pid);
|
||||||
|
if (process_handle != nullptr) {
|
||||||
|
std::cerr << "Waiting for process " << pid << " to exit..." << std::endl;
|
||||||
|
WaitForSingleObject(process_handle, INFINITE);
|
||||||
|
CloseHandle(process_handle);
|
||||||
|
}
|
||||||
|
#elif defined(__linux__)
|
||||||
|
std::string proc_path = "/proc/" + std::to_string(pid);
|
||||||
|
|
||||||
|
while (std::filesystem::exists(proc_path)) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
std::cerr << "Waiting for process " << pid << " to exit..." << std::endl;
|
||||||
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
while (kill(pid, 0) == 0) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
std::cerr << "Waiting for process " << pid << " to exit..." << std::endl;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error "Unsupported platform"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
16
src/core/debugger.h
Normal file
16
src/core/debugger.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Core::Debugger {
|
||||||
|
|
||||||
|
bool IsDebuggerAttached();
|
||||||
|
|
||||||
|
void WaitForDebuggerAttach();
|
||||||
|
|
||||||
|
int GetCurrentPid();
|
||||||
|
|
||||||
|
void WaitForPid(int pid);
|
||||||
|
|
||||||
|
} // namespace Core::Debugger
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "layer.h"
|
#include "layer.h"
|
||||||
@@ -460,12 +460,12 @@ void L::Draw() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void L::TextCentered(const std::string& text) {
|
void L::TextCentered(const std::string& text) {
|
||||||
float window_width = ImGui::GetWindowSize().x;
|
float window_width = GetWindowSize().x;
|
||||||
float text_width = ImGui::CalcTextSize(text.c_str()).x;
|
float text_width = CalcTextSize(text.c_str()).x;
|
||||||
float text_indentation = (window_width - text_width) * 0.5f;
|
float text_indentation = (window_width - text_width) * 0.5f;
|
||||||
|
|
||||||
ImGui::SameLine(text_indentation);
|
SameLine(text_indentation);
|
||||||
ImGui::Text("%s", text.c_str());
|
Text("%s", text.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Overlay {
|
namespace Overlay {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -9,18 +9,20 @@
|
|||||||
namespace Core::Devtools {
|
namespace Core::Devtools {
|
||||||
|
|
||||||
class Layer final : public ImGui::Layer {
|
class Layer final : public ImGui::Layer {
|
||||||
|
|
||||||
static void DrawMenuBar();
|
|
||||||
|
|
||||||
static void DrawAdvanced();
|
|
||||||
|
|
||||||
static void DrawSimple();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void SetupSettings();
|
static void SetupSettings();
|
||||||
|
|
||||||
void Draw() override;
|
void Draw() override;
|
||||||
void TextCentered(const std::string& text);
|
|
||||||
|
// Must be inside a window
|
||||||
|
static void DrawNullGpuNotice();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void DrawMenuBar();
|
||||||
|
static void DrawAdvanced();
|
||||||
|
static void DrawSimple();
|
||||||
|
|
||||||
|
static void TextCentered(const std::string& text);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core::Devtools
|
} // namespace Core::Devtools
|
||||||
|
|||||||
95
src/core/devtools/layer_extra.cpp
Normal file
95
src/core/devtools/layer_extra.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "layer.h"
|
||||||
|
|
||||||
|
#include "imgui/imgui_std.h"
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <imgui_internal.h>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <numbers>
|
||||||
|
|
||||||
|
namespace Core::Devtools {
|
||||||
|
|
||||||
|
void Layer::DrawNullGpuNotice() {
|
||||||
|
|
||||||
|
auto* window = ImGui::GetCurrentWindow();
|
||||||
|
if (window->SkipItems) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr std::string_view mainNotice = "Null GPU is enabled";
|
||||||
|
constexpr std::string_view detailsNotice =
|
||||||
|
"Disable the nullGpu config to show the game display";
|
||||||
|
|
||||||
|
auto displaySize = window->Size;
|
||||||
|
|
||||||
|
ImVec2 targetSize = displaySize * 0.7f;
|
||||||
|
|
||||||
|
float minFontSize = 1.0f;
|
||||||
|
float maxFontSize = 200.0f;
|
||||||
|
float optimalFontSize = minFontSize;
|
||||||
|
|
||||||
|
static auto lastSize = ImVec2(-1, -1);
|
||||||
|
static float lastFontSize = -1.0f;
|
||||||
|
|
||||||
|
auto* font = ImGui::GetIO().Fonts->Fonts[IMGUI_FONT_TEXT_BIG];
|
||||||
|
|
||||||
|
if (lastSize != targetSize) {
|
||||||
|
while (maxFontSize - minFontSize > 0.1f) {
|
||||||
|
float testFontSize = (minFontSize + maxFontSize) / 2.0f;
|
||||||
|
|
||||||
|
ImVec2 textSize = font->CalcTextSizeA(testFontSize, FLT_MAX, 0.0f, &mainNotice.front(),
|
||||||
|
&mainNotice.back() + 1);
|
||||||
|
|
||||||
|
if (textSize.x <= targetSize.x && textSize.y <= targetSize.y) {
|
||||||
|
optimalFontSize = testFontSize;
|
||||||
|
minFontSize = testFontSize;
|
||||||
|
} else {
|
||||||
|
maxFontSize = testFontSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastSize = targetSize;
|
||||||
|
lastFontSize = optimalFontSize;
|
||||||
|
} else {
|
||||||
|
optimalFontSize = lastFontSize;
|
||||||
|
}
|
||||||
|
ImVec2 textSize = font->CalcTextSizeA(optimalFontSize, FLT_MAX, 0.0f, &mainNotice.front(),
|
||||||
|
&mainNotice.back() + 1);
|
||||||
|
|
||||||
|
ImVec2 textPos = (displaySize - textSize) * 0.5f + window->Pos;
|
||||||
|
|
||||||
|
const float scale = optimalFontSize / font->FontSize;
|
||||||
|
double timeAnim = -std::numbers::pi * ImGui::GetTime();
|
||||||
|
int i = 0;
|
||||||
|
for (auto ch : mainNotice) {
|
||||||
|
double colorTime = sin(timeAnim + i * std::numbers::pi / 6.0) / 2.0 + 0.5;
|
||||||
|
int color = (int)(200 * colorTime) + 55;
|
||||||
|
|
||||||
|
double posTime = sin(timeAnim + i * std::numbers::pi / 15.0) / 2.0 + 0.5;
|
||||||
|
|
||||||
|
auto pos = textPos;
|
||||||
|
pos.y += 10.0 * (posTime < 0.5 ? std::pow(2.0, 20.0 * posTime - 10.0) / 2.0
|
||||||
|
: (2.0 - std::pow(2.0, -20.0 * posTime + 10.0)) / 2.0);
|
||||||
|
|
||||||
|
window->DrawList->AddText(font, optimalFontSize, pos, IM_COL32(color, color, color, 255),
|
||||||
|
&ch, &ch + 1);
|
||||||
|
textPos.x += font->FindGlyph(ch)->AdvanceX * scale;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
font = ImGui::GetIO().Fonts->Fonts[IMGUI_FONT_TEXT];
|
||||||
|
|
||||||
|
textPos.y += textSize.y + 1.0;
|
||||||
|
|
||||||
|
optimalFontSize *= 0.2;
|
||||||
|
textSize = font->CalcTextSizeA(optimalFontSize, FLT_MAX, 0.0f, &detailsNotice.front(),
|
||||||
|
&detailsNotice.back() + 1);
|
||||||
|
textPos.x = window->Pos.x + (window->Size.x - textSize.x) * 0.5f;
|
||||||
|
window->DrawList->AddText(font, optimalFontSize, textPos, IM_COL32(200, 200, 200, 255),
|
||||||
|
&detailsNotice.front(), &detailsNotice.back() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::Devtools
|
||||||
@@ -65,7 +65,7 @@ static HdrType GetNext(HdrType this_pm4, uint32_t n) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParsePolygonControl(u32 value, bool begin_table) {
|
void ParsePolygonControl(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<AmdGpu::Liverpool::PolygonControl const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::PolygonControl const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("PA_SU_SC_MODE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("PA_SU_SC_MODE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -73,80 +73,80 @@ void ParsePolygonControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("CULL_FRONT");
|
Text("CULL_FRONT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.cull_front.Value());
|
Text("%X", reg.cull_front);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("CULL_BACK");
|
Text("CULL_BACK");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.cull_back.Value());
|
Text("%X", reg.cull_back);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FACE");
|
Text("FACE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.front_face.Value()).data());
|
Text("%s", enum_name(reg.front_face).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLY_MODE");
|
Text("POLY_MODE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_polygon_mode.Value());
|
Text("%X", reg.enable_polygon_mode);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLYMODE_FRONT_PTYPE");
|
Text("POLYMODE_FRONT_PTYPE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.polygon_mode_front.Value()).data());
|
Text("%s", enum_name(reg.polygon_mode_front).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLYMODE_BACK_PTYPE");
|
Text("POLYMODE_BACK_PTYPE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.polygon_mode_back.Value()).data());
|
Text("%s", enum_name(reg.polygon_mode_back).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLY_OFFSET_FRONT_ENABLE");
|
Text("POLY_OFFSET_FRONT_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_polygon_offset_front.Value());
|
Text("%X", reg.enable_polygon_offset_front);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLY_OFFSET_BACK_ENABLE");
|
Text("POLY_OFFSET_BACK_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_polygon_offset_back.Value());
|
Text("%X", reg.enable_polygon_offset_back);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("POLY_OFFSET_PARA_ENABLE");
|
Text("POLY_OFFSET_PARA_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_polygon_offset_para.Value());
|
Text("%X", reg.enable_polygon_offset_para);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VTX_WINDOW_OFFSET_ENABLE");
|
Text("VTX_WINDOW_OFFSET_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_window_offset.Value());
|
Text("%X", reg.enable_window_offset);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("PROVOKING_VTX_LAST");
|
Text("PROVOKING_VTX_LAST");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.provoking_vtx_last.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.provoking_vtx_last),
|
||||||
enum_name(reg.provoking_vtx_last.Value()).data());
|
enum_name(reg.provoking_vtx_last).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("PERSP_CORR_DIS");
|
Text("PERSP_CORR_DIS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.persp_corr_dis.Value());
|
Text("%X", reg.persp_corr_dis);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MULTI_PRIM_IB_ENA");
|
Text("MULTI_PRIM_IB_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.multi_prim_ib_ena.Value());
|
Text("%X", reg.multi_prim_ib_ena);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -155,7 +155,7 @@ void ParsePolygonControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseAaConfig(u32 value, bool begin_table) {
|
void ParseAaConfig(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<Liverpool::AaConfig const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::AaConfig const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("PA_SC_AA_CONFIG", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("PA_SC_AA_CONFIG", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -163,31 +163,31 @@ void ParseAaConfig(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MSAA_NUM_SAMPLES");
|
Text("MSAA_NUM_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.msaa_num_samples.Value());
|
Text("%X", reg.msaa_num_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("AA_MASK_CENTROID_DTMN");
|
Text("AA_MASK_CENTROID_DTMN");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.aa_mask_centroid_dtmn.Value());
|
Text("%X", reg.aa_mask_centroid_dtmn);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MAX_SAMPLE_DIST");
|
Text("MAX_SAMPLE_DIST");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.max_sample_dst.Value());
|
Text("%X", reg.max_sample_dst);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MSAA_EXPOSED_SAMPLES");
|
Text("MSAA_EXPOSED_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.msaa_exposed_samples.Value());
|
Text("%X", reg.msaa_exposed_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DETAIL_TO_EXPOSED_MODE");
|
Text("DETAIL_TO_EXPOSED_MODE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.detail_to_exposed_mode.Value());
|
Text("%X", reg.detail_to_exposed_mode);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -196,7 +196,7 @@ void ParseAaConfig(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseViewportControl(u32 value, bool begin_table) {
|
void ParseViewportControl(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<Liverpool::ViewportControl const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::ViewportControl const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("PA_CL_VTE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("PA_CL_VTE_CNTL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -204,61 +204,61 @@ void ParseViewportControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_X_SCALE_ENA");
|
Text("VPORT_X_SCALE_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.xscale_enable.Value());
|
Text("%X", reg.xscale_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_X_OFFSET_ENA");
|
Text("VPORT_X_OFFSET_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.yoffset_enable.Value());
|
Text("%X", reg.yoffset_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_Y_SCALE_ENA");
|
Text("VPORT_Y_SCALE_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.yscale_enable.Value());
|
Text("%X", reg.yscale_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_Y_OFFSET_ENA");
|
Text("VPORT_Y_OFFSET_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.yoffset_enable.Value());
|
Text("%X", reg.yoffset_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_Z_SCALE_ENA");
|
Text("VPORT_Z_SCALE_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.zscale_enable.Value());
|
Text("%X", reg.zscale_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VPORT_Z_OFFSET_ENA");
|
Text("VPORT_Z_OFFSET_ENA");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.zoffset_enable.Value());
|
Text("%X", reg.zoffset_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VTX_XY_FMT");
|
Text("VTX_XY_FMT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.xy_transformed.Value());
|
Text("%X", reg.xy_transformed);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VTX_Z_FMT");
|
Text("VTX_Z_FMT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.z_transformed.Value());
|
Text("%X", reg.z_transformed);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("VTX_W0_FMT");
|
Text("VTX_W0_FMT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.w_transformed.Value());
|
Text("%X", reg.w_transformed);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("PERFCOUNTER_REF");
|
Text("PERFCOUNTER_REF");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.perfcounter_ref.Value());
|
Text("%X", reg.perfcounter_ref);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -267,7 +267,7 @@ void ParseViewportControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseColorControl(u32 value, bool begin_table) {
|
void ParseColorControl(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<Liverpool::ColorControl const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::ColorControl const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("CB_COLOR_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("CB_COLOR_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -275,25 +275,25 @@ void ParseColorControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DISABLE_DUAL_QUAD__VI");
|
Text("DISABLE_DUAL_QUAD__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.disable_dual_quad.Value());
|
Text("%X", reg.disable_dual_quad);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DEGAMMA_ENABLE");
|
Text("DEGAMMA_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.degamma_enable.Value());
|
Text("%X", reg.degamma_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MODE");
|
Text("MODE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.mode.Value(), enum_name(reg.mode.Value()).data());
|
Text("%X (%s)", static_cast<u32>(reg.mode), enum_name(reg.mode).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ROP3");
|
Text("ROP3");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", static_cast<u32>(reg.rop3.Value()));
|
Text("%X", static_cast<u32>(reg.rop3));
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -302,7 +302,7 @@ void ParseColorControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseColor0Info(u32 value, bool begin_table) {
|
void ParseColor0Info(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<Liverpool::ColorBuffer::Color0Info const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::ColorBuffer::Color0Info const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("CB_COLOR_INFO", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("CB_COLOR_INFO", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -310,109 +310,109 @@ void ParseColor0Info(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ENDIAN");
|
Text("ENDIAN");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.endian.Value()).data());
|
Text("%s", enum_name(reg.endian).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FORMAT");
|
Text("FORMAT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.format.Value()).data());
|
Text("%s", enum_name(AmdGpu::DataFormat(reg.format)).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("LINEAR_GENERAL");
|
Text("LINEAR_GENERAL");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.linear_general.Value());
|
Text("%X", reg.linear_general);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("NUMBER_TYPE");
|
Text("NUMBER_TYPE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.number_type.Value()).data());
|
Text("%s", enum_name(AmdGpu::NumberFormat(reg.number_type)).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COMP_SWAP");
|
Text("COMP_SWAP");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.comp_swap.Value()).data());
|
Text("%s", enum_name(reg.comp_swap).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FAST_CLEAR");
|
Text("FAST_CLEAR");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.fast_clear.Value());
|
Text("%X", reg.fast_clear);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COMPRESSION");
|
Text("COMPRESSION");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.compression.Value());
|
Text("%X", reg.compression);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("BLEND_CLAMP");
|
Text("BLEND_CLAMP");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.blend_clamp.Value());
|
Text("%X", reg.blend_clamp);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("BLEND_BYPASS");
|
Text("BLEND_BYPASS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.blend_bypass.Value());
|
Text("%X", reg.blend_bypass);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("SIMPLE_FLOAT");
|
Text("SIMPLE_FLOAT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.simple_float.Value());
|
Text("%X", reg.simple_float);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ROUND_MODE");
|
Text("ROUND_MODE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.round_mode.Value(), enum_name(reg.round_mode.Value()).data());
|
Text("%X (%s)", static_cast<u32>(reg.round_mode), enum_name(reg.round_mode).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("CMASK_IS_LINEAR");
|
Text("CMASK_IS_LINEAR");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.cmask_is_linear.Value());
|
Text("%X", reg.cmask_is_linear);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("BLEND_OPT_DONT_RD_DST");
|
Text("BLEND_OPT_DONT_RD_DST");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.blend_opt_dont_rd_dst.Value());
|
Text("%X", reg.blend_opt_dont_rd_dst);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("BLEND_OPT_DISCARD_PIXEL");
|
Text("BLEND_OPT_DISCARD_PIXEL");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.blend_opt_discard_pixel.Value());
|
Text("%X", reg.blend_opt_discard_pixel);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FMASK_COMPRESSION_DISABLE__CI__VI");
|
Text("FMASK_COMPRESSION_DISABLE__CI__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.fmask_compression_disable_ci.Value());
|
Text("%X", reg.fmask_compression_disable_ci);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FMASK_COMPRESS_1FRAG_ONLY__VI");
|
Text("FMASK_COMPRESS_1FRAG_ONLY__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.fmask_compress_1frag_only.Value());
|
Text("%X", reg.fmask_compress_1frag_only);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DCC_ENABLE__VI");
|
Text("DCC_ENABLE__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.dcc_enable.Value());
|
Text("%X", reg.dcc_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("CMASK_ADDR_TYPE__VI");
|
Text("CMASK_ADDR_TYPE__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.cmask_addr_type.Value());
|
Text("%X", reg.cmask_addr_type);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -421,7 +421,7 @@ void ParseColor0Info(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseColor0Attrib(u32 value, bool begin_table) {
|
void ParseColor0Attrib(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<Liverpool::ColorBuffer::Color0Attrib const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::ColorBuffer::Color0Attrib const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("CB_COLOR_ATTRIB", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("CB_COLOR_ATTRIB", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -429,37 +429,37 @@ void ParseColor0Attrib(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("TILE_MODE_INDEX");
|
Text("TILE_MODE_INDEX");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%s", enum_name(reg.tile_mode_index.Value()).data());
|
Text("%s", enum_name(reg.tile_mode_index).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FMASK_TILE_MODE_INDEX");
|
Text("FMASK_TILE_MODE_INDEX");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.fmask_tile_mode_index.Value());
|
Text("%X", reg.fmask_tile_mode_index);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FMASK_BANK_HEIGHT");
|
Text("FMASK_BANK_HEIGHT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.fmask_bank_height.Value());
|
Text("%X", reg.fmask_bank_height);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("NUM_SAMPLES");
|
Text("NUM_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.num_samples_log2.Value());
|
Text("%X", reg.num_samples_log2);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("NUM_FRAGMENTS");
|
Text("NUM_FRAGMENTS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.num_fragments_log2.Value());
|
Text("%X", reg.num_fragments_log2);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FORCE_DST_ALPHA_1");
|
Text("FORCE_DST_ALPHA_1");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.force_dst_alpha_1.Value());
|
Text("%X", reg.force_dst_alpha_1);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -468,7 +468,7 @@ void ParseColor0Attrib(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseBlendControl(u32 value, bool begin_table) {
|
void ParseBlendControl(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<Liverpool::BlendControl const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::BlendControl const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("CB_BLEND_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("CB_BLEND_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -476,59 +476,59 @@ void ParseBlendControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COLOR_SRCBLEND");
|
Text("COLOR_SRCBLEND");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.color_src_factor.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.color_src_factor),
|
||||||
enum_name(reg.color_src_factor.Value()).data());
|
enum_name(reg.color_src_factor).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COLOR_COMB_FCN");
|
Text("COLOR_COMB_FCN");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.color_func.Value(), enum_name(reg.color_func.Value()).data());
|
Text("%X (%s)", static_cast<u32>(reg.color_func), enum_name(reg.color_func).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COLOR_DESTBLEND");
|
Text("COLOR_DESTBLEND");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.color_dst_factor.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.color_dst_factor),
|
||||||
enum_name(reg.color_dst_factor.Value()).data());
|
enum_name(reg.color_dst_factor).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALPHA_SRCBLEND");
|
Text("ALPHA_SRCBLEND");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.alpha_src_factor.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.alpha_src_factor),
|
||||||
enum_name(reg.alpha_src_factor.Value()).data());
|
enum_name(reg.alpha_src_factor).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALPHA_COMB_FCN");
|
Text("ALPHA_COMB_FCN");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.alpha_func.Value(), enum_name(reg.alpha_func.Value()).data());
|
Text("%X (%s)", static_cast<u32>(reg.alpha_func), enum_name(reg.alpha_func).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALPHA_DESTBLEND");
|
Text("ALPHA_DESTBLEND");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.alpha_dst_factor.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.alpha_dst_factor),
|
||||||
enum_name(reg.alpha_dst_factor.Value()).data());
|
enum_name(reg.alpha_dst_factor).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("SEPARATE_ALPHA_BLEND");
|
Text("SEPARATE_ALPHA_BLEND");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.separate_alpha_blend.Value());
|
Text("%X", reg.separate_alpha_blend);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ENABLE");
|
Text("ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable.Value());
|
Text("%X", reg.enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DISABLE_ROP3");
|
Text("DISABLE_ROP3");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.disable_rop3.Value());
|
Text("%X", reg.disable_rop3);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -537,7 +537,7 @@ void ParseBlendControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseDepthRenderControl(u32 value, bool begin_table) {
|
void ParseDepthRenderControl(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<Liverpool::DepthRenderControl const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::DepthRenderControl const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("DB_RENDER_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("DB_RENDER_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -545,61 +545,61 @@ void ParseDepthRenderControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DEPTH_CLEAR_ENABLE");
|
Text("DEPTH_CLEAR_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_clear_enable.Value());
|
Text("%X", reg.depth_clear_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCIL_CLEAR_ENABLE");
|
Text("STENCIL_CLEAR_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.stencil_clear_enable.Value());
|
Text("%X", reg.stencil_clear_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DEPTH_COPY");
|
Text("DEPTH_COPY");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_clear_enable.Value());
|
Text("%X", reg.depth_clear_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCIL_COPY");
|
Text("STENCIL_COPY");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.stencil_copy.Value());
|
Text("%X", reg.stencil_copy);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("RESUMMARIZE_ENABLE");
|
Text("RESUMMARIZE_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.resummarize_enable.Value());
|
Text("%X", reg.resummarize_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCIL_COMPRESS_DISABLE");
|
Text("STENCIL_COMPRESS_DISABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.stencil_compress_disable.Value());
|
Text("%X", reg.stencil_compress_disable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DEPTH_COMPRESS_DISABLE");
|
Text("DEPTH_COMPRESS_DISABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_compress_disable.Value());
|
Text("%X", reg.depth_compress_disable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COPY_CENTROID");
|
Text("COPY_CENTROID");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.copy_centroid.Value());
|
Text("%X", reg.copy_centroid);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("COPY_SAMPLE");
|
Text("COPY_SAMPLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.copy_sample.Value());
|
Text("%X", reg.copy_sample);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DECOMPRESS_ENABLE__VI");
|
Text("DECOMPRESS_ENABLE__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.decompress_enable.Value());
|
Text("%X", reg.decompress_enable);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -608,7 +608,7 @@ void ParseDepthRenderControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseDepthControl(u32 value, bool begin_table) {
|
void ParseDepthControl(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<Liverpool::DepthControl const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::DepthControl const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -616,63 +616,63 @@ void ParseDepthControl(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCIL_ENABLE");
|
Text("STENCIL_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.stencil_enable.Value());
|
Text("%X", reg.stencil_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("Z_ENABLE");
|
Text("Z_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_enable.Value());
|
Text("%X", reg.depth_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("Z_WRITE_ENABLE");
|
Text("Z_WRITE_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_write_enable.Value());
|
Text("%X", reg.depth_write_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DEPTH_BOUNDS_ENABLE");
|
Text("DEPTH_BOUNDS_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.depth_bounds_enable.Value());
|
Text("%X", reg.depth_bounds_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ZFUNC");
|
Text("ZFUNC");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.depth_func.Value(), enum_name(reg.depth_func.Value()).data());
|
Text("%X (%s)", static_cast<u32>(reg.depth_func), enum_name(reg.depth_func).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("BACKFACE_ENABLE");
|
Text("BACKFACE_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.backface_enable.Value());
|
Text("%X", reg.backface_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCILFUNC");
|
Text("STENCILFUNC");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.stencil_ref_func.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.stencil_ref_func),
|
||||||
enum_name(reg.stencil_ref_func.Value()).data());
|
enum_name(reg.stencil_ref_func).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STENCILFUNC_BF");
|
Text("STENCILFUNC_BF");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.stencil_bf_func.Value(),
|
Text("%X (%s)", static_cast<u32>(reg.stencil_bf_func),
|
||||||
enum_name(reg.stencil_bf_func.Value()).data());
|
enum_name(reg.stencil_bf_func).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ENABLE_COLOR_WRITES_ON_DEPTH_FAIL");
|
Text("ENABLE_COLOR_WRITES_ON_DEPTH_FAIL");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_color_writes_on_depth_fail.Value());
|
Text("%X", reg.enable_color_writes_on_depth_fail);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DISABLE_COLOR_WRITES_ON_DEPTH_PASS");
|
Text("DISABLE_COLOR_WRITES_ON_DEPTH_PASS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.disable_color_writes_on_depth_pass.Value());
|
Text("%X", reg.disable_color_writes_on_depth_pass);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -681,7 +681,7 @@ void ParseDepthControl(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseEqaa(u32 value, bool begin_table) {
|
void ParseEqaa(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<Liverpool::Eqaa const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::Eqaa const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -689,73 +689,73 @@ void ParseEqaa(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MAX_ANCHOR_SAMPLES");
|
Text("MAX_ANCHOR_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.max_anchor_samples.Value());
|
Text("%X", reg.max_anchor_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("PS_ITER_SAMPLES");
|
Text("PS_ITER_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.ps_iter_samples.Value());
|
Text("%X", reg.ps_iter_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("MASK_EXPORT_NUM_SAMPLES");
|
Text("MASK_EXPORT_NUM_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.mask_export_num_samples.Value());
|
Text("%X", reg.mask_export_num_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALPHA_TO_MASK_NUM_SAMPLES");
|
Text("ALPHA_TO_MASK_NUM_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.alpha_to_mask_num_samples.Value());
|
Text("%X", reg.alpha_to_mask_num_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("HIGH_QUALITY_INTERSECTIONS");
|
Text("HIGH_QUALITY_INTERSECTIONS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.high_quality_intersections.Value());
|
Text("%X", reg.high_quality_intersections);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("INCOHERENT_EQAA_READS");
|
Text("INCOHERENT_EQAA_READS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.incoherent_eqaa_reads.Value());
|
Text("%X", reg.incoherent_eqaa_reads);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("INTERPOLATE_COMP_Z");
|
Text("INTERPOLATE_COMP_Z");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.interpolate_comp_z.Value());
|
Text("%X", reg.interpolate_comp_z);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("INTERPOLATE_SRC_Z");
|
Text("INTERPOLATE_SRC_Z");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.interpolate_src_z.Value());
|
Text("%X", reg.interpolate_src_z);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("STATIC_ANCHOR_ASSOCIATIONS");
|
Text("STATIC_ANCHOR_ASSOCIATIONS");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.static_anchor_associations.Value());
|
Text("%X", reg.static_anchor_associations);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALPHA_TO_MASK_EQAA_DISABLE");
|
Text("ALPHA_TO_MASK_EQAA_DISABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.alpha_to_mask_eqaa_disable.Value());
|
Text("%X", reg.alpha_to_mask_eqaa_disable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("OVERRASTERIZATION_AMOUNT");
|
Text("OVERRASTERIZATION_AMOUNT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.overrasterization_amount.Value());
|
Text("%X", reg.overrasterization_amount);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ENABLE_POSTZ_OVERRASTERIZATION");
|
Text("ENABLE_POSTZ_OVERRASTERIZATION");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.enable_postz_overrasterization.Value());
|
Text("%X", reg.enable_postz_overrasterization);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
@@ -764,7 +764,7 @@ void ParseEqaa(u32 value, bool begin_table) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ParseZInfo(u32 value, bool begin_table) {
|
void ParseZInfo(u32 value, bool begin_table) {
|
||||||
auto const reg = reinterpret_cast<Liverpool::DepthBuffer::ZInfo const&>(value);
|
auto const reg = reinterpret_cast<AmdGpu::DepthBuffer::ZInfo const&>(value);
|
||||||
|
|
||||||
if (!begin_table ||
|
if (!begin_table ||
|
||||||
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
BeginTable("DB_DEPTH_CONTROL", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
|
||||||
@@ -772,61 +772,61 @@ void ParseZInfo(u32 value, bool begin_table) {
|
|||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("FORMAT");
|
Text("FORMAT");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X (%s)", (u32)reg.format.Value(), enum_name(reg.format.Value()).data());
|
Text("%X (%s)", static_cast<u32>(reg.format), enum_name(reg.format).data());
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("NUM_SAMPLES");
|
Text("NUM_SAMPLES");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.num_samples.Value());
|
Text("%X", reg.num_samples);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("TILE_SPLIT__CI__VI");
|
Text("TILE_SPLIT__CI__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.tile_split.Value());
|
Text("%X", reg.tile_split);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("TILE_MODE_INDEX");
|
Text("TILE_MODE_INDEX");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", static_cast<u32>(reg.tile_mode_index.Value()));
|
Text("%X", static_cast<u32>(reg.tile_mode_index));
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("DECOMPRESS_ON_N_ZPLANES__VI");
|
Text("DECOMPRESS_ON_N_ZPLANES__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.decompress_on_n_zplanes.Value());
|
Text("%X", reg.decompress_on_n_zplanes);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ALLOW_EXPCLEAR");
|
Text("ALLOW_EXPCLEAR");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.allow_expclear.Value());
|
Text("%X", reg.allow_expclear);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("READ_SIZE");
|
Text("READ_SIZE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.read_size.Value());
|
Text("%X", reg.read_size);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("TILE_SURFACE_ENABLE");
|
Text("TILE_SURFACE_ENABLE");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.tile_surface_en.Value());
|
Text("%X", reg.tile_surface_enable);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("CLEAR_DISALLOWED__VI");
|
Text("CLEAR_DISALLOWED__VI");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.clear_disallowed.Value());
|
Text("%X", reg.clear_disallowed);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableSetColumnIndex(0);
|
TableSetColumnIndex(0);
|
||||||
Text("ZRANGE_PRECISION");
|
Text("ZRANGE_PRECISION");
|
||||||
TableSetColumnIndex(1);
|
TableSetColumnIndex(1);
|
||||||
Text("%X", reg.zrange_precision.Value());
|
Text("%X", reg.zrange_precision);
|
||||||
|
|
||||||
if (begin_table) {
|
if (begin_table) {
|
||||||
EndTable();
|
EndTable();
|
||||||
|
|||||||
@@ -5,14 +5,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "imgui_memory_editor.h"
|
#include "core/devtools/widget/imgui_memory_editor.h"
|
||||||
#include "reg_view.h"
|
#include "core/devtools/widget/reg_view.h"
|
||||||
|
|
||||||
namespace AmdGpu {
|
namespace AmdGpu {
|
||||||
union PM4Type3Header;
|
union PM4Type3Header;
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ inline std::string RunDisassembler(const std::string& disassembler_cli, const T&
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cli.replace(pos, src_arg.size(), "\"" + bin_path.string() + "\"");
|
cli.replace(pos, src_arg.size(), "\"" + bin_path.string() + "\"");
|
||||||
Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Write);
|
Common::FS::IOFile file(bin_path, Common::FS::FileAccessMode::Create);
|
||||||
file.Write(shader_code);
|
file.Write(shader_code);
|
||||||
file.Close();
|
file.Close();
|
||||||
|
|
||||||
|
|||||||
@@ -118,11 +118,12 @@ void FrameDumpViewer::Draw() {
|
|||||||
SameLine();
|
SameLine();
|
||||||
BeginDisabled(selected_cmd == -1);
|
BeginDisabled(selected_cmd == -1);
|
||||||
if (SmallButton("Dump cmd")) {
|
if (SmallButton("Dump cmd")) {
|
||||||
auto now_time = fmt::localtime(std::time(nullptr));
|
auto time = std::time(nullptr);
|
||||||
|
auto now_time = *std::localtime(&time);
|
||||||
const auto fname = fmt::format("{:%F %H-%M-%S} {}_{}_{}.bin", now_time,
|
const auto fname = fmt::format("{:%F %H-%M-%S} {}_{}_{}.bin", now_time,
|
||||||
magic_enum::enum_name(selected_queue_type),
|
magic_enum::enum_name(selected_queue_type),
|
||||||
selected_submit_num, selected_queue_num2);
|
selected_submit_num, selected_queue_num2);
|
||||||
Common::FS::IOFile file(fname, Common::FS::FileAccessMode::Write);
|
Common::FS::IOFile file(fname, Common::FS::FileAccessMode::Create);
|
||||||
const auto& data = frame_dump->queues[selected_cmd].data;
|
const auto& data = frame_dump->queues[selected_cmd].data;
|
||||||
if (file.IsOpen()) {
|
if (file.IsOpen()) {
|
||||||
DebugState.ShowDebugMessage(fmt::format("Dumping cmd as {}", fname));
|
DebugState.ShowDebugMessage(fmt::format("Dumping cmd as {}", fname));
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ bool MemoryMapViewer::Iterator::DrawLine() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto m = dmem.it->second;
|
auto m = dmem.it->second;
|
||||||
if (m.is_free) {
|
if (m.dma_type == DMAType::Free) {
|
||||||
++dmem.it;
|
++dmem.it;
|
||||||
return DrawLine();
|
return DrawLine();
|
||||||
}
|
}
|
||||||
@@ -56,7 +56,7 @@ bool MemoryMapViewer::Iterator::DrawLine() {
|
|||||||
auto type = static_cast<::Libraries::Kernel::MemoryTypes>(m.memory_type);
|
auto type = static_cast<::Libraries::Kernel::MemoryTypes>(m.memory_type);
|
||||||
Text("%s", magic_enum::enum_name(type).data());
|
Text("%s", magic_enum::enum_name(type).data());
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
Text("%d", m.is_pooled);
|
Text("%d", m.dma_type == DMAType::Pooled || m.dma_type == DMAType::Committed);
|
||||||
++dmem.it;
|
++dmem.it;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "common/config.h"
|
||||||
#include "common/elf_info.h"
|
#include "common/elf_info.h"
|
||||||
#include "common/path_util.h"
|
#include "common/path_util.h"
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ public:
|
|||||||
bool open = false;
|
bool open = false;
|
||||||
|
|
||||||
static bool IsSystemModule(const std::filesystem::path& path) {
|
static bool IsSystemModule(const std::filesystem::path& path) {
|
||||||
const auto sys_modules_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
const auto sys_modules_path = Config::getSysModulesPath();
|
||||||
|
|
||||||
const auto abs_path = std::filesystem::absolute(path).lexically_normal();
|
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 abs_sys_path = std::filesystem::absolute(sys_modules_path).lexically_normal();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ using magic_enum::enum_name;
|
|||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
void RegPopup::DrawColorBuffer(const AmdGpu::ColorBuffer& buffer) {
|
||||||
if (BeginTable("COLOR_BUFFER", 2, ImGuiTableFlags_Borders)) {
|
if (BeginTable("COLOR_BUFFER", 2, ImGuiTableFlags_Borders)) {
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
|||||||
if (TreeNode("Color0Info")) {
|
if (TreeNode("Color0Info")) {
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ParseColor0Info(buffer.info.u32all, false);
|
ParseColor0Info(buffer.info.raw, false);
|
||||||
TreePop();
|
TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
|||||||
if (TreeNode("Color0Attrib")) {
|
if (TreeNode("Color0Attrib")) {
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
TableNextColumn();
|
TableNextColumn();
|
||||||
ParseColor0Attrib(buffer.attrib.u32all, false);
|
ParseColor0Attrib(buffer.attrib.raw, false);
|
||||||
TreePop();
|
TreePop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,9 +75,8 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegPopup::DrawDepthBuffer(const DepthBuffer& depth_data) {
|
void RegPopup::DrawDepthBuffer(const AmdGpu::DepthBuffer& buffer,
|
||||||
const auto& [depth_buffer, depth_control] = depth_data;
|
const AmdGpu::DepthControl control) {
|
||||||
|
|
||||||
SeparatorText("Depth buffer");
|
SeparatorText("Depth buffer");
|
||||||
|
|
||||||
if (BeginTable("DEPTH_BUFFER", 2, ImGuiTableFlags_Borders)) {
|
if (BeginTable("DEPTH_BUFFER", 2, ImGuiTableFlags_Borders)) {
|
||||||
@@ -85,31 +84,31 @@ void RegPopup::DrawDepthBuffer(const DepthBuffer& depth_data) {
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
DrawValueRowList(
|
DrawValueRowList(
|
||||||
"Z_INFO.FORMAT", depth_buffer.z_info.format,
|
"Z_INFO.FORMAT", buffer.z_info.format,
|
||||||
"Z_INFO.NUM_SAMPLES", depth_buffer.z_info.num_samples,
|
"Z_INFO.NUM_SAMPLES", buffer.z_info.num_samples,
|
||||||
"Z_INFO.TILE_SPLIT", depth_buffer.z_info.tile_split,
|
"Z_INFO.TILE_SPLIT", buffer.z_info.tile_split,
|
||||||
"Z_INFO.TILE_MODE_INDEX", depth_buffer.z_info.tile_mode_index,
|
"Z_INFO.TILE_MODE_INDEX", buffer.z_info.tile_mode_index,
|
||||||
"Z_INFO.DECOMPRESS_ON_N_ZPLANES", depth_buffer.z_info.decompress_on_n_zplanes,
|
"Z_INFO.DECOMPRESS_ON_N_ZPLANES", buffer.z_info.decompress_on_n_zplanes,
|
||||||
"Z_INFO.ALLOW_EXPCLEAR", depth_buffer.z_info.allow_expclear,
|
"Z_INFO.ALLOW_EXPCLEAR", buffer.z_info.allow_expclear,
|
||||||
"Z_INFO.READ_SIZE", depth_buffer.z_info.read_size,
|
"Z_INFO.READ_SIZE", buffer.z_info.read_size,
|
||||||
"Z_INFO.TILE_SURFACE_EN", depth_buffer.z_info.tile_surface_en,
|
"Z_INFO.TILE_SURFACE_ENABLE", buffer.z_info.tile_surface_enable,
|
||||||
"Z_INFO.CLEAR_DISALLOWED", depth_buffer.z_info.clear_disallowed,
|
"Z_INFO.CLEAR_DISALLOWED", buffer.z_info.clear_disallowed,
|
||||||
"Z_INFO.ZRANGE_PRECISION", depth_buffer.z_info.zrange_precision,
|
"Z_INFO.ZRANGE_PRECISION", buffer.z_info.zrange_precision,
|
||||||
"STENCIL_INFO.FORMAT", depth_buffer.stencil_info.format,
|
"STENCIL_INFO.FORMAT", buffer.stencil_info.format,
|
||||||
"Z_READ_BASE", depth_buffer.z_read_base,
|
"Z_READ_BASE", buffer.z_read_base,
|
||||||
"STENCIL_READ_BASE", depth_buffer.stencil_read_base,
|
"STENCIL_READ_BASE", buffer.stencil_read_base,
|
||||||
"Z_WRITE_BASE", depth_buffer.z_write_base,
|
"Z_WRITE_BASE", buffer.z_write_base,
|
||||||
"STENCIL_WRITE_BASE", depth_buffer.stencil_write_base,
|
"STENCIL_WRITE_BASE", buffer.stencil_write_base,
|
||||||
"DEPTH_SIZE.PITCH_TILE_MAX", depth_buffer.depth_size.pitch_tile_max,
|
"DEPTH_SIZE.PITCH_TILE_MAX", buffer.depth_size.pitch_tile_max,
|
||||||
"DEPTH_SIZE.HEIGHT_TILE_MAX", depth_buffer.depth_size.height_tile_max,
|
"DEPTH_SIZE.HEIGHT_TILE_MAX", buffer.depth_size.height_tile_max,
|
||||||
"DEPTH_SLICE.TILE_MAX", depth_buffer.depth_slice.tile_max,
|
"DEPTH_SLICE.TILE_MAX", buffer.depth_slice.tile_max,
|
||||||
"Pitch()", depth_buffer.Pitch(),
|
"Pitch()", buffer.Pitch(),
|
||||||
"Height()", depth_buffer.Height(),
|
"Height()", buffer.Height(),
|
||||||
"DepthAddress()", depth_buffer.DepthAddress(),
|
"DepthAddress()", buffer.DepthAddress(),
|
||||||
"StencilAddress()", depth_buffer.StencilAddress(),
|
"StencilAddress()", buffer.StencilAddress(),
|
||||||
"NumSamples()", depth_buffer.NumSamples(),
|
"NumSamples()", buffer.NumSamples(),
|
||||||
"NumBits()", depth_buffer.NumBits(),
|
"NumBits()", buffer.NumBits(),
|
||||||
"GetDepthSliceSize()", depth_buffer.GetDepthSliceSize()
|
"GetDepthSliceSize()", buffer.GetDepthSliceSize()
|
||||||
);
|
);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -121,16 +120,16 @@ void RegPopup::DrawDepthBuffer(const DepthBuffer& depth_data) {
|
|||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
DrawValueRowList(
|
DrawValueRowList(
|
||||||
"STENCIL_ENABLE", depth_control.stencil_enable,
|
"STENCIL_ENABLE", control.stencil_enable,
|
||||||
"DEPTH_ENABLE", depth_control.depth_enable,
|
"DEPTH_ENABLE", control.depth_enable,
|
||||||
"DEPTH_WRITE_ENABLE", depth_control.depth_write_enable,
|
"DEPTH_WRITE_ENABLE", control.depth_write_enable,
|
||||||
"DEPTH_BOUNDS_ENABLE", depth_control.depth_bounds_enable,
|
"DEPTH_BOUNDS_ENABLE", control.depth_bounds_enable,
|
||||||
"DEPTH_FUNC", depth_control.depth_func,
|
"DEPTH_FUNC", control.depth_func,
|
||||||
"BACKFACE_ENABLE", depth_control.backface_enable,
|
"BACKFACE_ENABLE", control.backface_enable,
|
||||||
"STENCIL_FUNC", depth_control.stencil_ref_func,
|
"STENCIL_FUNC", control.stencil_ref_func,
|
||||||
"STENCIL_FUNC_BF", depth_control.stencil_bf_func,
|
"STENCIL_FUNC_BF", control.stencil_bf_func,
|
||||||
"ENABLE_COLOR_WRITES_ON_DEPTH_FAIL", depth_control.enable_color_writes_on_depth_fail,
|
"ENABLE_COLOR_WRITES_ON_DEPTH_FAIL", control.enable_color_writes_on_depth_fail,
|
||||||
"DISABLE_COLOR_WRITES_ON_DEPTH_PASS", depth_control.disable_color_writes_on_depth_pass
|
"DISABLE_COLOR_WRITES_ON_DEPTH_PASS", control.disable_color_writes_on_depth_pass
|
||||||
);
|
);
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -143,15 +142,17 @@ RegPopup::RegPopup() {
|
|||||||
id = unique_id++;
|
id = unique_id++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegPopup::SetData(const std::string& base_title, AmdGpu::Liverpool::ColorBuffer color_buffer,
|
void RegPopup::SetData(const std::string& base_title, AmdGpu::ColorBuffer color_buffer, u32 cb_id) {
|
||||||
u32 cb_id) {
|
this->type = DataType::Color;
|
||||||
this->data = color_buffer;
|
this->color = color_buffer;
|
||||||
this->title = fmt::format("{}/CB #{}", base_title, cb_id);
|
this->title = fmt::format("{}/CB #{}", base_title, cb_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegPopup::SetData(const std::string& base_title, AmdGpu::Liverpool::DepthBuffer depth_buffer,
|
void RegPopup::SetData(const std::string& base_title, AmdGpu::DepthBuffer depth_buffer,
|
||||||
AmdGpu::Liverpool::DepthControl depth_control) {
|
AmdGpu::DepthControl depth_control) {
|
||||||
this->data = std::make_tuple(depth_buffer, depth_control);
|
this->type = DataType::Depth;
|
||||||
|
this->depth.buffer = depth_buffer;
|
||||||
|
this->depth.control = depth_control;
|
||||||
this->title = fmt::format("{}/Depth", base_title);
|
this->title = fmt::format("{}/Depth", base_title);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,10 +162,10 @@ void RegPopup::SetPos(ImVec2 pos, bool auto_resize) {
|
|||||||
Begin(name, &open, flags);
|
Begin(name, &open, flags);
|
||||||
SetWindowPos(pos);
|
SetWindowPos(pos);
|
||||||
if (auto_resize) {
|
if (auto_resize) {
|
||||||
if (std::holds_alternative<AmdGpu::Liverpool::ColorBuffer>(data)) {
|
if (type == DataType::Color) {
|
||||||
SetWindowSize({365.0f, 520.0f});
|
SetWindowSize({365.0f, 520.0f});
|
||||||
KeepWindowInside();
|
KeepWindowInside();
|
||||||
} else if (std::holds_alternative<DepthBuffer>(data)) {
|
} else if (type == DataType::Depth) {
|
||||||
SetWindowSize({404.0f, 543.0f});
|
SetWindowSize({404.0f, 543.0f});
|
||||||
KeepWindowInside();
|
KeepWindowInside();
|
||||||
}
|
}
|
||||||
@@ -182,10 +183,10 @@ void RegPopup::Draw() {
|
|||||||
moved = true;
|
moved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto* buffer = std::get_if<AmdGpu::Liverpool::ColorBuffer>(&data)) {
|
if (type == DataType::Color) {
|
||||||
DrawColorBuffer(*buffer);
|
DrawColorBuffer(color);
|
||||||
} else if (const auto* depth_data = std::get_if<DepthBuffer>(&data)) {
|
} else if (type == DataType::Depth) {
|
||||||
DrawDepthBuffer(*depth_data);
|
DrawDepthBuffer(depth.buffer, depth.control);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
End();
|
End();
|
||||||
|
|||||||
@@ -3,12 +3,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <variant>
|
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
#include "video_core/amdgpu/regs_color.h"
|
||||||
|
#include "video_core/amdgpu/regs_depth.h"
|
||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
@@ -16,15 +14,24 @@ class RegPopup {
|
|||||||
int id;
|
int id;
|
||||||
ImGuiWindowFlags flags{ImGuiWindowFlags_NoSavedSettings};
|
ImGuiWindowFlags flags{ImGuiWindowFlags_NoSavedSettings};
|
||||||
|
|
||||||
using DepthBuffer = std::tuple<AmdGpu::Liverpool::DepthBuffer, AmdGpu::Liverpool::DepthControl>;
|
|
||||||
|
|
||||||
ImVec2 last_pos;
|
ImVec2 last_pos;
|
||||||
std::variant<AmdGpu::Liverpool::ColorBuffer, DepthBuffer> data;
|
AmdGpu::ColorBuffer color;
|
||||||
|
struct {
|
||||||
|
AmdGpu::DepthBuffer buffer;
|
||||||
|
AmdGpu::DepthControl control;
|
||||||
|
} depth;
|
||||||
|
enum class DataType {
|
||||||
|
None = 0,
|
||||||
|
Color = 1,
|
||||||
|
Depth = 2,
|
||||||
|
};
|
||||||
|
DataType type{};
|
||||||
std::string title{};
|
std::string title{};
|
||||||
|
|
||||||
static void DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer);
|
static void DrawColorBuffer(const AmdGpu::ColorBuffer& buffer);
|
||||||
|
|
||||||
static void DrawDepthBuffer(const DepthBuffer& depth_data);
|
static void DrawDepthBuffer(const AmdGpu::DepthBuffer& buffer,
|
||||||
|
const AmdGpu::DepthControl control);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool open = false;
|
bool open = false;
|
||||||
@@ -32,11 +39,10 @@ public:
|
|||||||
|
|
||||||
RegPopup();
|
RegPopup();
|
||||||
|
|
||||||
void SetData(const std::string& base_title, AmdGpu::Liverpool::ColorBuffer color_buffer,
|
void SetData(const std::string& base_title, AmdGpu::ColorBuffer color_buffer, u32 cb_id);
|
||||||
u32 cb_id);
|
|
||||||
|
|
||||||
void SetData(const std::string& base_title, AmdGpu::Liverpool::DepthBuffer depth_buffer,
|
void SetData(const std::string& base_title, AmdGpu::DepthBuffer depth_buffer,
|
||||||
AmdGpu::Liverpool::DepthControl depth_control);
|
AmdGpu::DepthControl depth_control);
|
||||||
|
|
||||||
void SetPos(ImVec2 pos, bool auto_resize = false);
|
void SetPos(ImVec2 pos, bool auto_resize = false);
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace Core::Devtools::Widget {
|
|||||||
|
|
||||||
void RegView::ProcessShader(int shader_id) {
|
void RegView::ProcessShader(int shader_id) {
|
||||||
std::vector<u32> shader_code;
|
std::vector<u32> shader_code;
|
||||||
Vulkan::Liverpool::UserData user_data;
|
AmdGpu::UserData user_data;
|
||||||
if (data.is_compute) {
|
if (data.is_compute) {
|
||||||
shader_code = data.cs_data.code;
|
shader_code = data.cs_data.code;
|
||||||
user_data = data.cs_data.cs_program.user_data;
|
user_data = data.cs_data.cs_program.user_data;
|
||||||
@@ -129,7 +129,7 @@ void RegView::DrawGraphicsRegs() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int cb = 0; cb < AmdGpu::Liverpool::NumColorBuffers; ++cb) {
|
for (int cb = 0; cb < AmdGpu::NUM_COLOR_BUFFERS; ++cb) {
|
||||||
PushID(cb);
|
PushID(cb);
|
||||||
|
|
||||||
TableNextRow();
|
TableNextRow();
|
||||||
@@ -246,8 +246,7 @@ void RegView::SetData(DebugStateType::RegDump _data, const std::string& base_tit
|
|||||||
default_reg_popup.SetData(title, regs.depth_buffer, regs.depth_control);
|
default_reg_popup.SetData(title, regs.depth_buffer, regs.depth_control);
|
||||||
default_reg_popup.open = true;
|
default_reg_popup.open = true;
|
||||||
}
|
}
|
||||||
} else if (last_selected_cb >= 0 &&
|
} else if (last_selected_cb >= 0 && last_selected_cb < AmdGpu::NUM_COLOR_BUFFERS) {
|
||||||
last_selected_cb < AmdGpu::Liverpool::NumColorBuffers) {
|
|
||||||
const auto& buffer = regs.color_buffers[last_selected_cb];
|
const auto& buffer = regs.color_buffers[last_selected_cb];
|
||||||
const bool has_cb = buffer && regs.color_target_mask.GetMask(last_selected_cb);
|
const bool has_cb = buffer && regs.color_target_mask.GetMask(last_selected_cb);
|
||||||
if (has_cb) {
|
if (has_cb) {
|
||||||
@@ -348,7 +347,7 @@ void RegView::Draw() {
|
|||||||
} else {
|
} else {
|
||||||
shader->hex_view.DrawContents(shader->user_data.data(),
|
shader->hex_view.DrawContents(shader->user_data.data(),
|
||||||
shader->user_data.size() *
|
shader->user_data.size() *
|
||||||
sizeof(Vulkan::Liverpool::UserData::value_type));
|
sizeof(AmdGpu::UserData::value_type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
End();
|
End();
|
||||||
|
|||||||
@@ -2,17 +2,18 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/debug_state.h"
|
#include "core/debug_state.h"
|
||||||
#include "imgui_memory_editor.h"
|
#include "core/devtools/widget/imgui_memory_editor.h"
|
||||||
#include "reg_popup.h"
|
#include "core/devtools/widget/reg_popup.h"
|
||||||
#include "text_editor.h"
|
#include "core/devtools/widget/text_editor.h"
|
||||||
|
|
||||||
namespace Core::Devtools::Widget {
|
namespace Core::Devtools::Widget {
|
||||||
|
|
||||||
struct ShaderCache {
|
struct ShaderCache {
|
||||||
MemoryEditor hex_view;
|
MemoryEditor hex_view;
|
||||||
TextEditor dis_view;
|
TextEditor dis_view;
|
||||||
Vulkan::Liverpool::UserData user_data;
|
AmdGpu::UserData user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RegView {
|
class RegView {
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ bool PSF::Open(const std::vector<u8>& psf_buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PSF::Encode(const std::filesystem::path& filepath) const {
|
bool PSF::Encode(const std::filesystem::path& filepath) const {
|
||||||
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Write);
|
Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Create);
|
||||||
if (!file.IsOpen()) {
|
if (!file.IsOpen()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit
|
|||||||
|
|
||||||
const auto user_key_str = Config::getTrophyKey();
|
const auto user_key_str = Config::getTrophyKey();
|
||||||
if (user_key_str.size() != 32) {
|
if (user_key_str.size() != 32) {
|
||||||
LOG_CRITICAL(Common_Filesystem, "Trophy decryption key is not specified");
|
LOG_INFO(Common_Filesystem, "Trophy decryption key is not specified");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit
|
|||||||
TrpEntry entry;
|
TrpEntry entry;
|
||||||
file.Read(entry);
|
file.Read(entry);
|
||||||
std::string_view name(entry.entry_name);
|
std::string_view name(entry.entry_name);
|
||||||
if (entry.flag == 0 && name.find("TROP") != std::string::npos) { // PNG
|
if (entry.flag == 0) { // PNG
|
||||||
if (!file.Seek(entry.entry_pos)) {
|
if (!file.Seek(entry.entry_pos)) {
|
||||||
LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry offset");
|
LOG_CRITICAL(Common_Filesystem, "Failed to seek to TRP entry offset");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "base_device.h"
|
#include "core/file_sys/devices/base_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <core/libraries/kernel/orbis_error.h>
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "common/va_ctx.h"
|
#include "common/va_ctx.h"
|
||||||
|
#include "core/libraries/kernel/orbis_error.h"
|
||||||
|
|
||||||
namespace Libraries::Kernel {
|
namespace Libraries::Kernel {
|
||||||
struct OrbisKernelStat;
|
struct OrbisKernelStat;
|
||||||
@@ -20,27 +20,27 @@ public:
|
|||||||
|
|
||||||
virtual ~BaseDevice() = 0;
|
virtual ~BaseDevice() = 0;
|
||||||
|
|
||||||
virtual int ioctl(u64 cmd, Common::VaCtx* args) {
|
virtual s32 ioctl(u64 cmd, Common::VaCtx* args) {
|
||||||
return ORBIS_KERNEL_ERROR_ENOTTY;
|
return ORBIS_KERNEL_ERROR_ENOTTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual s64 write(const void* buf, size_t nbytes) {
|
virtual s64 write(const void* buf, u64 nbytes) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual size_t readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
virtual s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual size_t writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
virtual s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) {
|
virtual s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual size_t pwritev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) {
|
virtual s64 pwritev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,11 +48,11 @@ public:
|
|||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual s64 read(void* buf, size_t nbytes) {
|
virtual s64 read(void* buf, u64 nbytes) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
virtual s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,15 +60,15 @@ public:
|
|||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int ftruncate(s64 length) {
|
virtual s32 ftruncate(s64 length) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int getdents(void* buf, u32 nbytes, s64* basep) {
|
virtual s64 getdents(void* buf, u32 nbytes, s64* basep) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual s64 pwrite(const void* buf, size_t nbytes, u64 offset) {
|
virtual s64 pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||||
return ORBIS_KERNEL_ERROR_EBADF;
|
return ORBIS_KERNEL_ERROR_EBADF;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,72 +2,71 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "console_device.h"
|
#include "core/file_sys/devices/console_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
std::shared_ptr<BaseDevice> ConsoleDevice::Create(u32 handle, const char*, int, u16) {
|
std::shared_ptr<BaseDevice> ConsoleDevice::Create(u32 handle, const char*, s32, u16) {
|
||||||
return std::shared_ptr<BaseDevice>(
|
return std::static_pointer_cast<BaseDevice>(std::make_shared<ConsoleDevice>(handle));
|
||||||
reinterpret_cast<Devices::BaseDevice*>(new ConsoleDevice(handle)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConsoleDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
s32 ConsoleDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called, cmd = {:#x}", cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 ConsoleDevice::write(const void* buf, size_t nbytes) {
|
s64 ConsoleDevice::write(const void* buf, u64 nbytes) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ConsoleDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 ConsoleDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ConsoleDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 ConsoleDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 ConsoleDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) {
|
s64 ConsoleDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 ConsoleDevice::lseek(s64 offset, int whence) {
|
s64 ConsoleDevice::lseek(s64 offset, s32 whence) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 ConsoleDevice::read(void* buf, size_t nbytes) {
|
s64 ConsoleDevice::read(void* buf, u64 nbytes) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConsoleDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
s32 ConsoleDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 ConsoleDevice::fsync() {
|
s32 ConsoleDevice::fsync() {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConsoleDevice::ftruncate(s64 length) {
|
s32 ConsoleDevice::ftruncate(s64 length) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConsoleDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
s64 ConsoleDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 ConsoleDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
s64 ConsoleDevice::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,31 +3,31 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "base_device.h"
|
#include "core/file_sys/devices/base_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
class ConsoleDevice final : BaseDevice {
|
class ConsoleDevice final : public BaseDevice {
|
||||||
u32 handle;
|
u32 handle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
|
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||||
explicit ConsoleDevice(u32 handle) : handle(handle) {}
|
explicit ConsoleDevice(u32 handle) : handle(handle) {}
|
||||||
|
|
||||||
~ConsoleDevice() override = default;
|
~ConsoleDevice() override = default;
|
||||||
|
|
||||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||||
s64 write(const void* buf, size_t nbytes) override;
|
s64 write(const void* buf, u64 nbytes) override;
|
||||||
size_t readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
size_t writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) override;
|
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||||
s64 lseek(s64 offset, int whence) override;
|
s64 lseek(s64 offset, s32 whence) override;
|
||||||
s64 read(void* buf, size_t nbytes) override;
|
s64 read(void* buf, u64 nbytes) override;
|
||||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||||
s32 fsync() override;
|
s32 fsync() override;
|
||||||
int ftruncate(s64 length) override;
|
s32 ftruncate(s64 length) override;
|
||||||
int getdents(void* buf, u32 nbytes, s64* basep) override;
|
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core::Devices
|
} // namespace Core::Devices
|
||||||
@@ -2,72 +2,71 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "deci_tty6_device.h"
|
#include "core/file_sys/devices/deci_tty6_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
std::shared_ptr<BaseDevice> DeciTty6Device::Create(u32 handle, const char*, int, u16) {
|
std::shared_ptr<BaseDevice> DeciTty6Device::Create(u32 handle, const char*, s32, u16) {
|
||||||
return std::shared_ptr<BaseDevice>(
|
return std::static_pointer_cast<BaseDevice>(std::make_shared<DeciTty6Device>(handle));
|
||||||
reinterpret_cast<Devices::BaseDevice*>(new DeciTty6Device(handle)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeciTty6Device::ioctl(u64 cmd, Common::VaCtx* args) {
|
s32 DeciTty6Device::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called, cmd = {:#x}", cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 DeciTty6Device::write(const void* buf, size_t nbytes) {
|
s64 DeciTty6Device::write(const void* buf, u64 nbytes) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t DeciTty6Device::writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 DeciTty6Device::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t DeciTty6Device::readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 DeciTty6Device::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 DeciTty6Device::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) {
|
s64 DeciTty6Device::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 DeciTty6Device::lseek(s64 offset, int whence) {
|
s64 DeciTty6Device::lseek(s64 offset, s32 whence) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 DeciTty6Device::read(void* buf, size_t nbytes) {
|
s64 DeciTty6Device::read(void* buf, u64 nbytes) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeciTty6Device::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
s32 DeciTty6Device::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 DeciTty6Device::fsync() {
|
s32 DeciTty6Device::fsync() {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeciTty6Device::ftruncate(s64 length) {
|
s32 DeciTty6Device::ftruncate(s64 length) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DeciTty6Device::getdents(void* buf, u32 nbytes, s64* basep) {
|
s64 DeciTty6Device::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 DeciTty6Device::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
s64 DeciTty6Device::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,31 +3,31 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "base_device.h"
|
#include "core/file_sys/devices/base_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
class DeciTty6Device final : BaseDevice {
|
class DeciTty6Device final : public BaseDevice {
|
||||||
u32 handle;
|
u32 handle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
|
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||||
explicit DeciTty6Device(u32 handle) : handle(handle) {}
|
explicit DeciTty6Device(u32 handle) : handle(handle) {}
|
||||||
|
|
||||||
~DeciTty6Device() override = default;
|
~DeciTty6Device() override = default;
|
||||||
|
|
||||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||||
s64 write(const void* buf, size_t nbytes) override;
|
s64 write(const void* buf, u64 nbytes) override;
|
||||||
size_t readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
size_t writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) override;
|
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||||
s64 lseek(s64 offset, int whence) override;
|
s64 lseek(s64 offset, s32 whence) override;
|
||||||
s64 read(void* buf, size_t nbytes) override;
|
s64 read(void* buf, u64 nbytes) override;
|
||||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||||
s32 fsync() override;
|
s32 fsync() override;
|
||||||
int ftruncate(s64 length) override;
|
s32 ftruncate(s64 length) override;
|
||||||
int getdents(void* buf, u32 nbytes, s64* basep) override;
|
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core::Devices
|
} // namespace Core::Devices
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
#include "core/file_sys/devices/logger.h"
|
||||||
#include "core/libraries/kernel/file_system.h"
|
#include "core/libraries/kernel/file_system.h"
|
||||||
#include "logger.h"
|
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
@@ -11,13 +11,13 @@ Logger::Logger(std::string prefix, bool is_err) : prefix(std::move(prefix)), is_
|
|||||||
|
|
||||||
Logger::~Logger() = default;
|
Logger::~Logger() = default;
|
||||||
|
|
||||||
s64 Logger::write(const void* buf, size_t nbytes) {
|
s64 Logger::write(const void* buf, u64 nbytes) {
|
||||||
log(static_cast<const char*>(buf), nbytes);
|
log(static_cast<const char*>(buf), nbytes);
|
||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t Logger::writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 Logger::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
size_t total_written = 0;
|
u64 total_written = 0;
|
||||||
for (int i = 0; i < iovcnt; i++) {
|
for (int i = 0; i < iovcnt; i++) {
|
||||||
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
|
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
|
||||||
total_written += iov[i].iov_len;
|
total_written += iov[i].iov_len;
|
||||||
@@ -25,7 +25,7 @@ size_t Logger::writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt
|
|||||||
return total_written;
|
return total_written;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 Logger::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
s64 Logger::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||||
log(static_cast<const char*>(buf), nbytes);
|
log(static_cast<const char*>(buf), nbytes);
|
||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ s32 Logger::fsync() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::log(const char* buf, size_t nbytes) {
|
void Logger::log(const char* buf, u64 nbytes) {
|
||||||
std::scoped_lock lock{mtx};
|
std::scoped_lock lock{mtx};
|
||||||
const char* end = buf + nbytes;
|
const char* end = buf + nbytes;
|
||||||
for (const char* it = buf; it < end; ++it) {
|
for (const char* it = buf; it < end; ++it) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base_device.h"
|
#include "core/file_sys/devices/base_device.h"
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -23,14 +23,14 @@ public:
|
|||||||
|
|
||||||
~Logger() override;
|
~Logger() override;
|
||||||
|
|
||||||
s64 write(const void* buf, size_t nbytes) override;
|
s64 write(const void* buf, u64 nbytes) override;
|
||||||
size_t writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||||
|
|
||||||
s32 fsync() override;
|
s32 fsync() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void log(const char* buf, size_t nbytes);
|
void log(const char* buf, u64 nbytes);
|
||||||
void log_flush();
|
void log_flush();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "base_device.h"
|
#include "core/file_sys/devices/base_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
@@ -14,35 +14,35 @@ public:
|
|||||||
|
|
||||||
~NopDevice() override = default;
|
~NopDevice() override = default;
|
||||||
|
|
||||||
int ioctl(u64 cmd, Common::VaCtx* args) override {
|
s32 ioctl(u64 cmd, Common::VaCtx* args) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 write(const void* buf, size_t nbytes) override {
|
s64 write(const void* buf, u64 nbytes) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override {
|
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override {
|
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) override {
|
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 lseek(s64 offset, int whence) override {
|
s64 lseek(s64 offset, s32 whence) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 read(void* buf, size_t nbytes) override {
|
s64 read(void* buf, u64 nbytes) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override {
|
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,15 +50,15 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ftruncate(s64 length) override {
|
s32 ftruncate(s64 length) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getdents(void* buf, u32 nbytes, s64* basep) override {
|
s64 getdents(void* buf, u32 nbytes, s64* basep) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override {
|
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,75 +4,75 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "random_device.h"
|
#include "core/file_sys/devices/random_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
std::shared_ptr<BaseDevice> RandomDevice::Create(u32 handle, const char*, int, u16) {
|
std::shared_ptr<BaseDevice> RandomDevice::Create(u32 handle, const char*, s32, u16) {
|
||||||
std::srand(std::time(nullptr));
|
std::srand(std::time(nullptr));
|
||||||
return std::shared_ptr<BaseDevice>(
|
return std::static_pointer_cast<BaseDevice>(std::make_shared<RandomDevice>(handle));
|
||||||
reinterpret_cast<Devices::BaseDevice*>(new RandomDevice(handle)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int RandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
s32 RandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called, cmd = {:#x}", cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 RandomDevice::write(const void* buf, size_t nbytes) {
|
s64 RandomDevice::write(const void* buf, u64 nbytes) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RandomDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 RandomDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RandomDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 RandomDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 RandomDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) {
|
s64 RandomDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 RandomDevice::lseek(s64 offset, int whence) {
|
s64 RandomDevice::lseek(s64 offset, s32 whence) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 RandomDevice::read(void* buf, size_t nbytes) {
|
s64 RandomDevice::read(void* buf, u64 nbytes) {
|
||||||
auto rbuf = static_cast<char*>(buf);
|
auto rbuf = static_cast<s8*>(buf);
|
||||||
for (size_t i = 0; i < nbytes; i++) {
|
for (u64 i = 0; i < nbytes; i++) {
|
||||||
rbuf[i] = std::rand() & 0xFF;
|
rbuf[i] = std::rand() & 0xFF;
|
||||||
}
|
}
|
||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
s32 RandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 RandomDevice::fsync() {
|
s32 RandomDevice::fsync() {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RandomDevice::ftruncate(s64 length) {
|
s32 RandomDevice::ftruncate(s64 length) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int RandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
s64 RandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 RandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
s64 RandomDevice::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,31 +3,31 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "base_device.h"
|
#include "core/file_sys/devices/base_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
class RandomDevice final : BaseDevice {
|
class RandomDevice final : public BaseDevice {
|
||||||
u32 handle;
|
u32 handle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
|
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||||
explicit RandomDevice(u32 handle) : handle(handle) {}
|
explicit RandomDevice(u32 handle) : handle(handle) {}
|
||||||
|
|
||||||
~RandomDevice() override = default;
|
~RandomDevice() override = default;
|
||||||
|
|
||||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||||
s64 write(const void* buf, size_t nbytes) override;
|
s64 write(const void* buf, u64 nbytes) override;
|
||||||
size_t readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
size_t writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) override;
|
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||||
s64 lseek(s64 offset, int whence) override;
|
s64 lseek(s64 offset, s32 whence) override;
|
||||||
s64 read(void* buf, size_t nbytes) override;
|
s64 read(void* buf, u64 nbytes) override;
|
||||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||||
s32 fsync() override;
|
s32 fsync() override;
|
||||||
int ftruncate(s64 length) override;
|
s32 ftruncate(s64 length) override;
|
||||||
int getdents(void* buf, u32 nbytes, s64* basep) override;
|
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core::Devices
|
} // namespace Core::Devices
|
||||||
87
src/core/file_sys/devices/rng_device.cpp
Normal file
87
src/core/file_sys/devices/rng_device.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <ctime>
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/file_sys/devices/rng_device.h"
|
||||||
|
|
||||||
|
namespace Core::Devices {
|
||||||
|
|
||||||
|
std::shared_ptr<BaseDevice> RngDevice::Create(u32 handle, const char*, s32, u16) {
|
||||||
|
std::srand(std::time(nullptr));
|
||||||
|
return std::static_pointer_cast<BaseDevice>(std::make_shared<RngDevice>(handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 RngDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||||
|
LOG_INFO(Kernel_Pthread, "called, cmd = {:#x}", cmd);
|
||||||
|
// Both commands are for generating a random number
|
||||||
|
if (cmd == 0x40445301 || cmd == 0x40445302) {
|
||||||
|
auto& data = *vaArgPtr<GetRandomArgs>(&args->va_list);
|
||||||
|
data.result = 0;
|
||||||
|
for (u64 i = 0; i < 64; i++) {
|
||||||
|
data.buf[i] = std::rand();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ENOIOCTL
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 RngDevice::write(const void* buf, u64 nbytes) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 RngDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 RngDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 RngDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 RngDevice::lseek(s64 offset, s32 whence) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 RngDevice::read(void* buf, u64 nbytes) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 RngDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 RngDevice::fsync() {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 RngDevice::ftruncate(s64 length) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 RngDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 RngDevice::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Core::Devices
|
||||||
39
src/core/file_sys/devices/rng_device.h
Normal file
39
src/core/file_sys/devices/rng_device.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <memory>
|
||||||
|
#include "core/file_sys/devices/base_device.h"
|
||||||
|
|
||||||
|
namespace Core::Devices {
|
||||||
|
|
||||||
|
class RngDevice final : public BaseDevice {
|
||||||
|
u32 handle;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||||
|
explicit RngDevice(u32 handle) : handle(handle) {}
|
||||||
|
|
||||||
|
~RngDevice() override = default;
|
||||||
|
|
||||||
|
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||||
|
s64 write(const void* buf, u64 nbytes) override;
|
||||||
|
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
|
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
|
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||||
|
s64 lseek(s64 offset, s32 whence) override;
|
||||||
|
s64 read(void* buf, u64 nbytes) override;
|
||||||
|
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||||
|
s32 fsync() override;
|
||||||
|
s32 ftruncate(s64 length) override;
|
||||||
|
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||||
|
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct GetRandomArgs {
|
||||||
|
s32 result;
|
||||||
|
s8 buf[64];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Core::Devices
|
||||||
@@ -4,76 +4,75 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "srandom_device.h"
|
#include "core/file_sys/devices/srandom_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
std::shared_ptr<BaseDevice> SRandomDevice::Create(u32 handle, const char*, int, u16) {
|
std::shared_ptr<BaseDevice> SRandomDevice::Create(u32 handle, const char*, s32, u16) {
|
||||||
std::srand(std::time(nullptr));
|
std::srand(std::time(nullptr));
|
||||||
return std::shared_ptr<BaseDevice>(
|
return std::static_pointer_cast<BaseDevice>(std::make_shared<SRandomDevice>(handle));
|
||||||
reinterpret_cast<Devices::BaseDevice*>(new SRandomDevice(handle)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SRandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
s32 SRandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called, cmd = {:#x}", cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 SRandomDevice::write(const void* buf, size_t nbytes) {
|
s64 SRandomDevice::write(const void* buf, u64 nbytes) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SRandomDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 SRandomDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SRandomDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 SRandomDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 SRandomDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) {
|
s64 SRandomDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 SRandomDevice::lseek(s64 offset, int whence) {
|
s64 SRandomDevice::lseek(s64 offset, s32 whence) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 SRandomDevice::read(void* buf, size_t nbytes) {
|
s64 SRandomDevice::read(void* buf, u64 nbytes) {
|
||||||
auto rbuf = static_cast<char*>(buf);
|
auto rbuf = static_cast<s8*>(buf);
|
||||||
for (size_t i = 0; i < nbytes; i++) {
|
for (u64 i = 0; i < nbytes; i++) {
|
||||||
rbuf[i] = std::rand();
|
rbuf[i] = std::rand();
|
||||||
}
|
}
|
||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SRandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
s32 SRandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 SRandomDevice::fsync() {
|
s32 SRandomDevice::fsync() {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return s32();
|
|
||||||
}
|
|
||||||
|
|
||||||
int SRandomDevice::ftruncate(s64 length) {
|
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SRandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
s32 SRandomDevice::ftruncate(s64 length) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 SRandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
s64 SRandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 SRandomDevice::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||||
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,31 +3,31 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "base_device.h"
|
#include "core/file_sys/devices/base_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
class SRandomDevice final : BaseDevice {
|
class SRandomDevice final : public BaseDevice {
|
||||||
u32 handle;
|
u32 handle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
|
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||||
explicit SRandomDevice(u32 handle) : handle(handle) {}
|
explicit SRandomDevice(u32 handle) : handle(handle) {}
|
||||||
|
|
||||||
~SRandomDevice() override = default;
|
~SRandomDevice() override = default;
|
||||||
|
|
||||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||||
s64 write(const void* buf, size_t nbytes) override;
|
s64 write(const void* buf, u64 nbytes) override;
|
||||||
size_t readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
size_t writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) override;
|
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||||
s64 lseek(s64 offset, int whence) override;
|
s64 lseek(s64 offset, s32 whence) override;
|
||||||
s64 read(void* buf, size_t nbytes) override;
|
s64 read(void* buf, u64 nbytes) override;
|
||||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||||
s32 fsync() override;
|
s32 fsync() override;
|
||||||
int ftruncate(s64 length) override;
|
s32 ftruncate(s64 length) override;
|
||||||
int getdents(void* buf, u32 nbytes, s64* basep) override;
|
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core::Devices
|
} // namespace Core::Devices
|
||||||
@@ -4,76 +4,75 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "urandom_device.h"
|
#include "core/file_sys/devices/urandom_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
std::shared_ptr<BaseDevice> URandomDevice::Create(u32 handle, const char*, int, u16) {
|
std::shared_ptr<BaseDevice> URandomDevice::Create(u32 handle, const char*, s32, u16) {
|
||||||
std::srand(std::time(nullptr));
|
std::srand(std::time(nullptr));
|
||||||
return std::shared_ptr<BaseDevice>(
|
return std::static_pointer_cast<BaseDevice>(std::make_shared<URandomDevice>(handle));
|
||||||
reinterpret_cast<Devices::BaseDevice*>(new URandomDevice(handle)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int URandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
s32 URandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called, cmd = {:#x}", cmd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 URandomDevice::write(const void* buf, size_t nbytes) {
|
s64 URandomDevice::write(const void* buf, u64 nbytes) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t URandomDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 URandomDevice::writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t URandomDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) {
|
s64 URandomDevice::readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 URandomDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) {
|
s64 URandomDevice::preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 URandomDevice::lseek(s64 offset, int whence) {
|
s64 URandomDevice::lseek(s64 offset, s32 whence) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 URandomDevice::read(void* buf, size_t nbytes) {
|
s64 URandomDevice::read(void* buf, u64 nbytes) {
|
||||||
auto rbuf = static_cast<char*>(buf);
|
auto rbuf = static_cast<s8*>(buf);
|
||||||
for (size_t i = 0; i < nbytes; i++) {
|
for (u64 i = 0; i < nbytes; i++) {
|
||||||
rbuf[i] = std::rand() & 0xFF;
|
rbuf[i] = std::rand() & 0xFF;
|
||||||
}
|
}
|
||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
int URandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
s32 URandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 URandomDevice::fsync() {
|
s32 URandomDevice::fsync() {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int URandomDevice::ftruncate(s64 length) {
|
s32 URandomDevice::ftruncate(s64 length) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int URandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
s64 URandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 URandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
|
s64 URandomDevice::pwrite(const void* buf, u64 nbytes, s64 offset) {
|
||||||
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
|
LOG_ERROR(Kernel_Fs, "(STUBBED) called");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,31 +3,31 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "base_device.h"
|
#include "core/file_sys/devices/base_device.h"
|
||||||
|
|
||||||
namespace Core::Devices {
|
namespace Core::Devices {
|
||||||
|
|
||||||
class URandomDevice final : BaseDevice {
|
class URandomDevice final : public BaseDevice {
|
||||||
u32 handle;
|
u32 handle;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
|
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, s32, u16);
|
||||||
explicit URandomDevice(u32 handle) : handle(handle) {}
|
explicit URandomDevice(u32 handle) : handle(handle) {}
|
||||||
|
|
||||||
~URandomDevice() override = default;
|
~URandomDevice() override = default;
|
||||||
|
|
||||||
int ioctl(u64 cmd, Common::VaCtx* args) override;
|
s32 ioctl(u64 cmd, Common::VaCtx* args) override;
|
||||||
s64 write(const void* buf, size_t nbytes) override;
|
s64 write(const void* buf, u64 nbytes) override;
|
||||||
size_t readv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 readv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
size_t writev(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt) override;
|
s64 writev(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt) override;
|
||||||
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, int iovcnt, u64 offset) override;
|
s64 preadv(const Libraries::Kernel::OrbisKernelIovec* iov, s32 iovcnt, s64 offset) override;
|
||||||
s64 lseek(s64 offset, int whence) override;
|
s64 lseek(s64 offset, s32 whence) override;
|
||||||
s64 read(void* buf, size_t nbytes) override;
|
s64 read(void* buf, u64 nbytes) override;
|
||||||
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
s32 fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
|
||||||
s32 fsync() override;
|
s32 fsync() override;
|
||||||
int ftruncate(s64 length) override;
|
s32 ftruncate(s64 length) override;
|
||||||
int getdents(void* buf, u32 nbytes, s64* basep) override;
|
s64 getdents(void* buf, u32 nbytes, s64* basep) override;
|
||||||
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
|
s64 pwrite(const void* buf, u64 nbytes, s64 offset) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core::Devices
|
} // namespace Core::Devices
|
||||||
@@ -235,6 +235,30 @@ File* HandleTable::GetSocket(int d) {
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File* HandleTable::GetEpoll(int d) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
|
if (d < 0 || d >= m_files.size()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto file = m_files.at(d);
|
||||||
|
if (file->type != Core::FileSys::FileType::Epoll) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
File* HandleTable::GetResolver(int d) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
|
if (d < 0 || d >= m_files.size()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto file = m_files.at(d);
|
||||||
|
if (file->type != Core::FileSys::FileType::Resolver) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
File* HandleTable::GetFile(const std::filesystem::path& host_name) {
|
File* HandleTable::GetFile(const std::filesystem::path& host_name) {
|
||||||
for (auto* file : m_files) {
|
for (auto* file : m_files) {
|
||||||
if (file != nullptr && file->m_host_name == host_name) {
|
if (file != nullptr && file->m_host_name == host_name) {
|
||||||
|
|||||||
@@ -15,7 +15,9 @@
|
|||||||
|
|
||||||
namespace Libraries::Net {
|
namespace Libraries::Net {
|
||||||
struct Socket;
|
struct Socket;
|
||||||
}
|
struct Epoll;
|
||||||
|
struct Resolver;
|
||||||
|
} // namespace Libraries::Net
|
||||||
|
|
||||||
namespace Core::FileSys {
|
namespace Core::FileSys {
|
||||||
|
|
||||||
@@ -78,6 +80,8 @@ enum class FileType {
|
|||||||
Directory,
|
Directory,
|
||||||
Device,
|
Device,
|
||||||
Socket,
|
Socket,
|
||||||
|
Epoll,
|
||||||
|
Resolver
|
||||||
};
|
};
|
||||||
|
|
||||||
struct File {
|
struct File {
|
||||||
@@ -90,6 +94,8 @@ struct File {
|
|||||||
std::shared_ptr<Directories::BaseDirectory> directory; // only valid for type == Directory
|
std::shared_ptr<Directories::BaseDirectory> directory; // only valid for type == Directory
|
||||||
std::shared_ptr<Devices::BaseDevice> device; // only valid for type == Device
|
std::shared_ptr<Devices::BaseDevice> device; // only valid for type == Device
|
||||||
std::shared_ptr<Libraries::Net::Socket> socket; // only valid for type == Socket
|
std::shared_ptr<Libraries::Net::Socket> socket; // only valid for type == Socket
|
||||||
|
std::shared_ptr<Libraries::Net::Epoll> epoll; // only valid for type == Epoll
|
||||||
|
std::shared_ptr<Libraries::Net::Resolver> resolver; // only valid for type == Resolver
|
||||||
};
|
};
|
||||||
|
|
||||||
class HandleTable {
|
class HandleTable {
|
||||||
@@ -101,6 +107,8 @@ public:
|
|||||||
void DeleteHandle(int d);
|
void DeleteHandle(int d);
|
||||||
File* GetFile(int d);
|
File* GetFile(int d);
|
||||||
File* GetSocket(int d);
|
File* GetSocket(int d);
|
||||||
|
File* GetEpoll(int d);
|
||||||
|
File* GetResolver(int d);
|
||||||
File* GetFile(const std::filesystem::path& host_name);
|
File* GetFile(const std::filesystem::path& host_name);
|
||||||
int GetFileDescriptor(File* file);
|
int GetFileDescriptor(File* file);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "ipc.h"
|
#include "ipc.h"
|
||||||
@@ -8,12 +8,19 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#include "common/config.h"
|
||||||
#include "common/memory_patcher.h"
|
#include "common/memory_patcher.h"
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "core/debug_state.h"
|
#include "core/debug_state.h"
|
||||||
|
#include "core/debugger.h"
|
||||||
|
#include "core/libraries/audio/audioout.h"
|
||||||
#include "input/input_handler.h"
|
#include "input/input_handler.h"
|
||||||
#include "sdl_window.h"
|
#include "sdl_window.h"
|
||||||
|
#include "src/core/libraries/usbd/usbd.h"
|
||||||
|
#include "video_core/renderer_vulkan/vk_presenter.h"
|
||||||
|
|
||||||
|
extern std::unique_ptr<Vulkan::Presenter> presenter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protocol summary:
|
* Protocol summary:
|
||||||
@@ -40,6 +47,7 @@
|
|||||||
* Command list:
|
* Command list:
|
||||||
* - CAPABILITIES:
|
* - CAPABILITIES:
|
||||||
* - ENABLE_MEMORY_PATCH: enables PATCH_MEMORY command
|
* - ENABLE_MEMORY_PATCH: enables PATCH_MEMORY command
|
||||||
|
* - ENABLE_EMU_CONTROL: enables PAUSE, RESUME, STOP, TOGGLE_FULLSCREEN commands
|
||||||
* - INPUT CMD:
|
* - INPUT CMD:
|
||||||
* - RUN: start the emulator execution
|
* - RUN: start the emulator execution
|
||||||
* - START: start the game execution
|
* - START: start the game execution
|
||||||
@@ -53,7 +61,7 @@
|
|||||||
* - STOP: stop and quit the emulator
|
* - STOP: stop and quit the emulator
|
||||||
* - TOGGLE_FULLSCREEN: enable / disable fullscreen
|
* - TOGGLE_FULLSCREEN: enable / disable fullscreen
|
||||||
* - OUTPUT CMD:
|
* - OUTPUT CMD:
|
||||||
* - N/A
|
* - RESTART(argn: number, argv: ...string): Request restart of the emulator, must call STOP
|
||||||
**/
|
**/
|
||||||
|
|
||||||
void IPC::Init() {
|
void IPC::Init() {
|
||||||
@@ -63,6 +71,8 @@ void IPC::Init() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Config::setLoadAutoPatches(false);
|
||||||
|
|
||||||
input_thread = std::jthread([this] {
|
input_thread = std::jthread([this] {
|
||||||
Common::SetCurrentThreadName("IPC Read thread");
|
Common::SetCurrentThreadName("IPC Read thread");
|
||||||
this->InputLoop();
|
this->InputLoop();
|
||||||
@@ -81,6 +91,15 @@ void IPC::Init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IPC::SendRestart(const std::vector<std::string>& args) {
|
||||||
|
std::cerr << ";RESTART\n";
|
||||||
|
std::cerr << ";" << args.size() << "\n";
|
||||||
|
for (const auto& arg : args) {
|
||||||
|
std::cerr << ";" << arg << "\n";
|
||||||
|
}
|
||||||
|
std::cerr.flush();
|
||||||
|
}
|
||||||
|
|
||||||
void IPC::InputLoop() {
|
void IPC::InputLoop() {
|
||||||
auto next_str = [&] -> const std::string& {
|
auto next_str = [&] -> const std::string& {
|
||||||
static std::string line_buffer;
|
static std::string line_buffer;
|
||||||
@@ -130,6 +149,68 @@ void IPC::InputLoop() {
|
|||||||
SDL_memset(&event, 0, sizeof(event));
|
SDL_memset(&event, 0, sizeof(event));
|
||||||
event.type = SDL_EVENT_TOGGLE_FULLSCREEN;
|
event.type = SDL_EVENT_TOGGLE_FULLSCREEN;
|
||||||
SDL_PushEvent(&event);
|
SDL_PushEvent(&event);
|
||||||
|
} else if (cmd == "ADJUST_VOLUME") {
|
||||||
|
int value = static_cast<int>(next_u64());
|
||||||
|
bool is_game_specific = next_u64() != 0;
|
||||||
|
Config::setVolumeSlider(value, is_game_specific);
|
||||||
|
Libraries::AudioOut::AdjustVol();
|
||||||
|
} else if (cmd == "SET_FSR") {
|
||||||
|
bool use_fsr = next_u64() != 0;
|
||||||
|
if (presenter) {
|
||||||
|
presenter->GetFsrSettingsRef().enable = use_fsr;
|
||||||
|
}
|
||||||
|
} else if (cmd == "SET_RCAS") {
|
||||||
|
bool use_rcas = next_u64() != 0;
|
||||||
|
if (presenter) {
|
||||||
|
presenter->GetFsrSettingsRef().use_rcas = use_rcas;
|
||||||
|
}
|
||||||
|
} else if (cmd == "SET_RCAS_ATTENUATION") {
|
||||||
|
int value = static_cast<int>(next_u64());
|
||||||
|
if (presenter) {
|
||||||
|
presenter->GetFsrSettingsRef().rcas_attenuation =
|
||||||
|
static_cast<float>(value / 1000.0f);
|
||||||
|
}
|
||||||
|
} else if (cmd == "USB_LOAD_FIGURE") {
|
||||||
|
const auto ref = Libraries::Usbd::usb_backend->GetImplRef();
|
||||||
|
if (ref) {
|
||||||
|
ref->LoadFigure(next_str(), next_u64(), next_u64());
|
||||||
|
}
|
||||||
|
} else if (cmd == "USB_REMOVE_FIGURE") {
|
||||||
|
const auto ref = Libraries::Usbd::usb_backend->GetImplRef();
|
||||||
|
if (ref) {
|
||||||
|
ref->RemoveFigure(next_u64(), next_u64(), next_u64() != 0);
|
||||||
|
}
|
||||||
|
} else if (cmd == "USB_MOVE_FIGURE") {
|
||||||
|
const auto ref = Libraries::Usbd::usb_backend->GetImplRef();
|
||||||
|
if (ref) {
|
||||||
|
const u8 new_pad = next_u64();
|
||||||
|
const u8 new_index = next_u64();
|
||||||
|
const u8 old_pad = next_u64();
|
||||||
|
const u8 old_index = next_u64();
|
||||||
|
ref->MoveFigure(new_pad, new_index, old_pad, old_index);
|
||||||
|
}
|
||||||
|
} else if (cmd == "USB_TEMP_REMOVE_FIGURE") {
|
||||||
|
const auto ref = Libraries::Usbd::usb_backend->GetImplRef();
|
||||||
|
if (ref) {
|
||||||
|
const u8 index = next_u64();
|
||||||
|
ref->TempRemoveFigure(index);
|
||||||
|
}
|
||||||
|
} else if (cmd == "USB_CANCEL_REMOVE_FIGURE") {
|
||||||
|
const auto ref = Libraries::Usbd::usb_backend->GetImplRef();
|
||||||
|
if (ref) {
|
||||||
|
const u8 index = next_u64();
|
||||||
|
ref->CancelRemoveFigure(index);
|
||||||
|
}
|
||||||
|
} else if (cmd == "RELOAD_INPUTS") {
|
||||||
|
std::string config = next_str();
|
||||||
|
Input::ParseInputConfig(config);
|
||||||
|
} else if (cmd == "SET_ACTIVE_CONTROLLER") {
|
||||||
|
std::string active_controller = next_str();
|
||||||
|
GamepadSelect::SetSelectedGamepad(active_controller);
|
||||||
|
SDL_Event checkGamepad;
|
||||||
|
SDL_memset(&checkGamepad, 0, sizeof(checkGamepad));
|
||||||
|
checkGamepad.type = SDL_EVENT_CHANGE_CONTROLLER;
|
||||||
|
SDL_PushEvent(&checkGamepad);
|
||||||
} else {
|
} else {
|
||||||
std::cerr << ";UNKNOWN CMD: " << cmd << std::endl;
|
std::cerr << ";UNKNOWN CMD: " << cmd << std::endl;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
#include "common/singleton.h"
|
#include "common/singleton.h"
|
||||||
|
|
||||||
#include <semaphore>
|
#include <semaphore>
|
||||||
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class IPC {
|
class IPC {
|
||||||
bool enabled{false};
|
bool enabled{false};
|
||||||
@@ -34,6 +36,8 @@ public:
|
|||||||
start_semaphore.acquire();
|
start_semaphore.acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SendRestart(const std::vector<std::string>& args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[noreturn]] void InputLoop();
|
[[noreturn]] void InputLoop();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,15 +10,51 @@ extern "C" {
|
|||||||
#include <libatrac9.h>
|
#include <libatrac9.h>
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace Libraries::Ajm {
|
namespace Libraries::Ajm {
|
||||||
|
|
||||||
|
struct ChunkHeader {
|
||||||
|
u32 tag;
|
||||||
|
u32 length;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ChunkHeader) == 8);
|
||||||
|
|
||||||
|
struct AudioFormat {
|
||||||
|
u16 fmt_type;
|
||||||
|
u16 num_channels;
|
||||||
|
u32 avg_sample_rate;
|
||||||
|
u32 avg_byte_rate;
|
||||||
|
u16 block_align;
|
||||||
|
u16 bits_per_sample;
|
||||||
|
u16 ext_size;
|
||||||
|
union {
|
||||||
|
u16 valid_bits_per_sample;
|
||||||
|
u16 samples_per_block;
|
||||||
|
u16 reserved;
|
||||||
|
};
|
||||||
|
u32 channel_mask;
|
||||||
|
u8 guid[16];
|
||||||
|
u32 version;
|
||||||
|
u8 config_data[4];
|
||||||
|
u32 reserved2;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(AudioFormat) == 52);
|
||||||
|
|
||||||
|
struct SampleData {
|
||||||
|
u32 sample_length;
|
||||||
|
u32 encoder_delay;
|
||||||
|
u32 encoder_delay2;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SampleData) == 12);
|
||||||
|
|
||||||
|
struct RIFFHeader {
|
||||||
|
u32 riff;
|
||||||
|
u32 size;
|
||||||
|
u32 wave;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(RIFFHeader) == 12);
|
||||||
|
|
||||||
AjmAt9Decoder::AjmAt9Decoder(AjmFormatEncoding format, AjmAt9CodecFlags flags)
|
AjmAt9Decoder::AjmAt9Decoder(AjmFormatEncoding format, AjmAt9CodecFlags flags)
|
||||||
: m_format(format), m_flags(flags), m_handle(Atrac9GetHandle()) {
|
: m_format(format), m_flags(flags), m_handle(Atrac9GetHandle()) {}
|
||||||
ASSERT_MSG(m_handle, "Atrac9GetHandle failed");
|
|
||||||
AjmAt9Decoder::Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
AjmAt9Decoder::~AjmAt9Decoder() {
|
AjmAt9Decoder::~AjmAt9Decoder() {
|
||||||
Atrac9ReleaseHandle(m_handle);
|
Atrac9ReleaseHandle(m_handle);
|
||||||
@@ -42,6 +78,7 @@ void AjmAt9Decoder::Initialize(const void* buffer, u32 buffer_size) {
|
|||||||
AjmAt9Decoder::Reset();
|
AjmAt9Decoder::Reset();
|
||||||
m_pcm_buffer.resize(m_codec_info.frameSamples * m_codec_info.channels * GetPCMSize(m_format),
|
m_pcm_buffer.resize(m_codec_info.frameSamples * m_codec_info.channels * GetPCMSize(m_format),
|
||||||
0);
|
0);
|
||||||
|
m_is_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AjmAt9Decoder::GetInfo(void* out_info) const {
|
void AjmAt9Decoder::GetInfo(void* out_info) const {
|
||||||
@@ -52,8 +89,64 @@ void AjmAt9Decoder::GetInfo(void* out_info) const {
|
|||||||
info->next_frame_size = static_cast<Atrac9Handle*>(m_handle)->Config.FrameBytes;
|
info->next_frame_size = static_cast<Atrac9Handle*>(m_handle)->Config.FrameBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<u32, u32> AjmAt9Decoder::ProcessData(std::span<u8>& in_buf, SparseOutputBuffer& output,
|
u8 g_at9_guid[] = {0xD2, 0x42, 0xE1, 0x47, 0xBA, 0x36, 0x8D, 0x4D,
|
||||||
AjmInstanceGapless& gapless) {
|
0x88, 0xFC, 0x61, 0x65, 0x4F, 0x8C, 0x83, 0x6C};
|
||||||
|
|
||||||
|
void AjmAt9Decoder::ParseRIFFHeader(std::span<u8>& in_buf, AjmInstanceGapless& gapless) {
|
||||||
|
auto* header = reinterpret_cast<RIFFHeader*>(in_buf.data());
|
||||||
|
in_buf = in_buf.subspan(sizeof(RIFFHeader));
|
||||||
|
|
||||||
|
ASSERT(header->riff == 'FFIR');
|
||||||
|
ASSERT(header->wave == 'EVAW');
|
||||||
|
|
||||||
|
auto* chunk = reinterpret_cast<ChunkHeader*>(in_buf.data());
|
||||||
|
in_buf = in_buf.subspan(sizeof(ChunkHeader));
|
||||||
|
while (chunk->tag != 'atad') {
|
||||||
|
switch (chunk->tag) {
|
||||||
|
case ' tmf': {
|
||||||
|
ASSERT(chunk->length == sizeof(AudioFormat));
|
||||||
|
auto* fmt = reinterpret_cast<AudioFormat*>(in_buf.data());
|
||||||
|
|
||||||
|
ASSERT(fmt->fmt_type == 0xFFFE);
|
||||||
|
ASSERT(memcmp(fmt->guid, g_at9_guid, 16) == 0);
|
||||||
|
AjmDecAt9InitializeParameters init_params = {};
|
||||||
|
std::memcpy(init_params.config_data, fmt->config_data, ORBIS_AT9_CONFIG_DATA_SIZE);
|
||||||
|
Initialize(&init_params, sizeof(init_params));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'tcaf': {
|
||||||
|
ASSERT(chunk->length == sizeof(SampleData));
|
||||||
|
auto* samples = reinterpret_cast<SampleData*>(in_buf.data());
|
||||||
|
|
||||||
|
gapless.init.total_samples = samples->sample_length;
|
||||||
|
gapless.init.skip_samples = samples->encoder_delay;
|
||||||
|
gapless.Reset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
in_buf = in_buf.subspan(chunk->length);
|
||||||
|
|
||||||
|
chunk = reinterpret_cast<ChunkHeader*>(in_buf.data());
|
||||||
|
in_buf = in_buf.subspan(sizeof(ChunkHeader));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tuple<u32, u32, bool> AjmAt9Decoder::ProcessData(std::span<u8>& in_buf,
|
||||||
|
SparseOutputBuffer& output,
|
||||||
|
AjmInstanceGapless& gapless) {
|
||||||
|
bool is_reset = false;
|
||||||
|
if (True(m_flags & AjmAt9CodecFlags::ParseRiffHeader) &&
|
||||||
|
*reinterpret_cast<u32*>(in_buf.data()) == 'FFIR') {
|
||||||
|
ParseRIFFHeader(in_buf, gapless);
|
||||||
|
is_reset = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_is_initialized) {
|
||||||
|
return {0, 0, is_reset};
|
||||||
|
}
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int bytes_used = 0;
|
int bytes_used = 0;
|
||||||
switch (m_format) {
|
switch (m_format) {
|
||||||
@@ -118,7 +211,7 @@ std::tuple<u32, u32> AjmAt9Decoder::ProcessData(std::span<u8>& in_buf, SparseOut
|
|||||||
m_num_frames = 0;
|
m_num_frames = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {1, samples_written};
|
return {1, m_codec_info.frameSamples, is_reset};
|
||||||
}
|
}
|
||||||
|
|
||||||
AjmSidebandFormat AjmAt9Decoder::GetFormat() const {
|
AjmSidebandFormat AjmAt9Decoder::GetFormat() const {
|
||||||
@@ -134,12 +227,13 @@ AjmSidebandFormat AjmAt9Decoder::GetFormat() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 AjmAt9Decoder::GetNextFrameSize(const AjmInstanceGapless& gapless) const {
|
u32 AjmAt9Decoder::GetNextFrameSize(const AjmInstanceGapless& gapless) const {
|
||||||
const auto max_samples =
|
const auto skip_samples =
|
||||||
|
std::min<u32>(gapless.current.skip_samples, m_codec_info.frameSamples);
|
||||||
|
const auto samples =
|
||||||
gapless.init.total_samples != 0
|
gapless.init.total_samples != 0
|
||||||
? std::min(gapless.current.total_samples, u32(m_codec_info.frameSamples))
|
? std::min<u32>(gapless.current.total_samples, m_codec_info.frameSamples - skip_samples)
|
||||||
: m_codec_info.frameSamples;
|
: m_codec_info.frameSamples;
|
||||||
const auto skip_samples = std::min(u32(gapless.current.skip_samples), max_samples);
|
return samples * m_codec_info.channels * GetPCMSize(m_format);
|
||||||
return (max_samples - skip_samples) * m_codec_info.channels * GetPCMSize(m_format);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Ajm
|
} // namespace Libraries::Ajm
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "libatrac9.h"
|
#include "libatrac9.h"
|
||||||
|
|
||||||
#include <span>
|
#include <span>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace Libraries::Ajm {
|
namespace Libraries::Ajm {
|
||||||
|
|
||||||
@@ -36,8 +37,8 @@ struct AjmAt9Decoder final : AjmCodec {
|
|||||||
void GetInfo(void* out_info) const override;
|
void GetInfo(void* out_info) const override;
|
||||||
AjmSidebandFormat GetFormat() const override;
|
AjmSidebandFormat GetFormat() const override;
|
||||||
u32 GetNextFrameSize(const AjmInstanceGapless& gapless) const override;
|
u32 GetNextFrameSize(const AjmInstanceGapless& gapless) const override;
|
||||||
std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
std::tuple<u32, u32, bool> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||||
AjmInstanceGapless& gapless) override;
|
AjmInstanceGapless& gapless) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class T>
|
template <class T>
|
||||||
@@ -49,8 +50,12 @@ private:
|
|||||||
return output.Write(pcm_data.subspan(0, pcm_size));
|
return output.Write(pcm_data.subspan(0, pcm_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParseRIFFHeader(std::span<u8>& input, AjmInstanceGapless& gapless);
|
||||||
|
|
||||||
const AjmFormatEncoding m_format;
|
const AjmFormatEncoding m_format;
|
||||||
const AjmAt9CodecFlags m_flags;
|
const AjmAt9CodecFlags m_flags;
|
||||||
|
|
||||||
|
bool m_is_initialized{};
|
||||||
void* m_handle{};
|
void* m_handle{};
|
||||||
u8 m_config_data[ORBIS_AT9_CONFIG_DATA_SIZE]{};
|
u8 m_config_data[ORBIS_AT9_CONFIG_DATA_SIZE]{};
|
||||||
u32 m_superframe_bytes_remain{};
|
u32 m_superframe_bytes_remain{};
|
||||||
|
|||||||
@@ -52,21 +52,22 @@ AjmInstance::AjmInstance(AjmCodecType codec_type, AjmInstanceFlags flags) : m_fl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AjmInstance::Reset() {
|
||||||
|
m_total_samples = 0;
|
||||||
|
m_gapless.Reset();
|
||||||
|
m_codec->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
void AjmInstance::ExecuteJob(AjmJob& job) {
|
void AjmInstance::ExecuteJob(AjmJob& job) {
|
||||||
const auto control_flags = job.flags.control_flags;
|
const auto control_flags = job.flags.control_flags;
|
||||||
if (True(control_flags & AjmJobControlFlags::Reset)) {
|
if (True(control_flags & AjmJobControlFlags::Reset)) {
|
||||||
LOG_TRACE(Lib_Ajm, "Resetting instance {}", job.instance_id);
|
LOG_TRACE(Lib_Ajm, "Resetting instance {}", job.instance_id);
|
||||||
m_format = {};
|
Reset();
|
||||||
m_gapless = {};
|
|
||||||
m_resample_parameters = {};
|
|
||||||
m_total_samples = 0;
|
|
||||||
m_codec->Reset();
|
|
||||||
}
|
}
|
||||||
if (job.input.init_params.has_value()) {
|
if (job.input.init_params.has_value()) {
|
||||||
LOG_TRACE(Lib_Ajm, "Initializing instance {}", job.instance_id);
|
LOG_TRACE(Lib_Ajm, "Initializing instance {}", job.instance_id);
|
||||||
auto& params = job.input.init_params.value();
|
auto& params = job.input.init_params.value();
|
||||||
m_codec->Initialize(¶ms, sizeof(params));
|
m_codec->Initialize(¶ms, sizeof(params));
|
||||||
is_initialized = true;
|
|
||||||
}
|
}
|
||||||
if (job.input.resample_parameters.has_value()) {
|
if (job.input.resample_parameters.has_value()) {
|
||||||
LOG_ERROR(Lib_Ajm, "Unimplemented: resample parameters");
|
LOG_ERROR(Lib_Ajm, "Unimplemented: resample parameters");
|
||||||
@@ -78,20 +79,37 @@ void AjmInstance::ExecuteJob(AjmJob& job) {
|
|||||||
}
|
}
|
||||||
if (job.input.gapless_decode.has_value()) {
|
if (job.input.gapless_decode.has_value()) {
|
||||||
auto& params = job.input.gapless_decode.value();
|
auto& params = job.input.gapless_decode.value();
|
||||||
if (params.total_samples != 0) {
|
|
||||||
const auto max = std::max(params.total_samples, m_gapless.init.total_samples);
|
|
||||||
m_gapless.current.total_samples += max - m_gapless.init.total_samples;
|
|
||||||
m_gapless.init.total_samples = max;
|
|
||||||
}
|
|
||||||
if (params.skip_samples != 0) {
|
|
||||||
const auto max = std::max(params.skip_samples, m_gapless.init.skip_samples);
|
|
||||||
m_gapless.current.skip_samples += max - m_gapless.init.skip_samples;
|
|
||||||
m_gapless.init.skip_samples = max;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_initialized) {
|
const auto samples_processed =
|
||||||
return;
|
m_gapless.init.total_samples - m_gapless.current.total_samples;
|
||||||
|
if (params.total_samples != 0 || params.skip_samples == 0) {
|
||||||
|
if (params.total_samples >= samples_processed) {
|
||||||
|
const auto sample_difference =
|
||||||
|
s64(m_gapless.init.total_samples) - params.total_samples;
|
||||||
|
|
||||||
|
m_gapless.init.total_samples = params.total_samples;
|
||||||
|
m_gapless.current.total_samples -= sample_difference;
|
||||||
|
} else {
|
||||||
|
LOG_WARNING(Lib_Ajm, "ORBIS_AJM_RESULT_INVALID_PARAMETER");
|
||||||
|
job.output.p_result->result = ORBIS_AJM_RESULT_INVALID_PARAMETER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto samples_skipped = m_gapless.init.skip_samples - m_gapless.current.skip_samples;
|
||||||
|
if (params.skip_samples != 0 || params.total_samples == 0) {
|
||||||
|
if (params.skip_samples >= samples_skipped) {
|
||||||
|
const auto sample_difference =
|
||||||
|
s32(m_gapless.init.skip_samples) - params.skip_samples;
|
||||||
|
|
||||||
|
m_gapless.init.skip_samples = params.skip_samples;
|
||||||
|
m_gapless.current.skip_samples -= sample_difference;
|
||||||
|
} else {
|
||||||
|
LOG_WARNING(Lib_Ajm, "ORBIS_AJM_RESULT_INVALID_PARAMETER");
|
||||||
|
job.output.p_result->result = ORBIS_AJM_RESULT_INVALID_PARAMETER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!job.input.buffer.empty() && !job.output.buffers.empty()) {
|
if (!job.input.buffer.empty() && !job.output.buffers.empty()) {
|
||||||
@@ -104,12 +122,23 @@ void AjmInstance::ExecuteJob(AjmJob& job) {
|
|||||||
while (!in_buf.empty() && !out_buf.IsEmpty() && !m_gapless.IsEnd()) {
|
while (!in_buf.empty() && !out_buf.IsEmpty() && !m_gapless.IsEnd()) {
|
||||||
if (!HasEnoughSpace(out_buf)) {
|
if (!HasEnoughSpace(out_buf)) {
|
||||||
if (job.output.p_mframe == nullptr || frames_decoded == 0) {
|
if (job.output.p_mframe == nullptr || frames_decoded == 0) {
|
||||||
|
LOG_WARNING(Lib_Ajm, "ORBIS_AJM_RESULT_NOT_ENOUGH_ROOM ({} < {})",
|
||||||
|
out_buf.Size(), m_codec->GetNextFrameSize(m_gapless));
|
||||||
job.output.p_result->result = ORBIS_AJM_RESULT_NOT_ENOUGH_ROOM;
|
job.output.p_result->result = ORBIS_AJM_RESULT_NOT_ENOUGH_ROOM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto [nframes, nsamples] = m_codec->ProcessData(in_buf, out_buf, m_gapless);
|
const auto [nframes, nsamples, reset] =
|
||||||
|
m_codec->ProcessData(in_buf, out_buf, m_gapless);
|
||||||
|
if (reset) {
|
||||||
|
m_total_samples = 0;
|
||||||
|
}
|
||||||
|
if (!nframes) {
|
||||||
|
LOG_WARNING(Lib_Ajm, "ORBIS_AJM_RESULT_NOT_INITIALIZED");
|
||||||
|
job.output.p_result->result = ORBIS_AJM_RESULT_NOT_INITIALIZED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
frames_decoded += nframes;
|
frames_decoded += nframes;
|
||||||
m_total_samples += nsamples;
|
m_total_samples += nsamples;
|
||||||
|
|
||||||
@@ -118,10 +147,10 @@ void AjmInstance::ExecuteJob(AjmJob& job) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_gapless.IsEnd()) {
|
const auto total_decoded_samples = m_total_samples;
|
||||||
|
if (m_flags.gapless_loop && m_gapless.IsEnd()) {
|
||||||
in_buf = in_buf.subspan(in_buf.size());
|
in_buf = in_buf.subspan(in_buf.size());
|
||||||
m_gapless.current.total_samples = m_gapless.init.total_samples;
|
m_gapless.Reset();
|
||||||
m_gapless.current.skip_samples = m_gapless.init.skip_samples;
|
|
||||||
m_codec->Reset();
|
m_codec->Reset();
|
||||||
}
|
}
|
||||||
if (job.output.p_mframe) {
|
if (job.output.p_mframe) {
|
||||||
@@ -130,7 +159,7 @@ void AjmInstance::ExecuteJob(AjmJob& job) {
|
|||||||
if (job.output.p_stream) {
|
if (job.output.p_stream) {
|
||||||
job.output.p_stream->input_consumed = in_size - in_buf.size();
|
job.output.p_stream->input_consumed = in_size - in_buf.size();
|
||||||
job.output.p_stream->output_written = out_size - out_buf.Size();
|
job.output.p_stream->output_written = out_size - out_buf.Size();
|
||||||
job.output.p_stream->total_decoded_samples = m_total_samples;
|
job.output.p_stream->total_decoded_samples = total_decoded_samples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,12 @@ struct AjmInstanceGapless {
|
|||||||
bool IsEnd() const {
|
bool IsEnd() const {
|
||||||
return init.total_samples != 0 && current.total_samples == 0;
|
return init.total_samples != 0 && current.total_samples == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Reset() {
|
||||||
|
current.total_samples = init.total_samples;
|
||||||
|
current.skip_samples = init.skip_samples;
|
||||||
|
current.skipped_samples = 0;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class AjmCodec {
|
class AjmCodec {
|
||||||
@@ -76,8 +82,8 @@ public:
|
|||||||
virtual void GetInfo(void* out_info) const = 0;
|
virtual void GetInfo(void* out_info) const = 0;
|
||||||
virtual AjmSidebandFormat GetFormat() const = 0;
|
virtual AjmSidebandFormat GetFormat() const = 0;
|
||||||
virtual u32 GetNextFrameSize(const AjmInstanceGapless& gapless) const = 0;
|
virtual u32 GetNextFrameSize(const AjmInstanceGapless& gapless) const = 0;
|
||||||
virtual std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
virtual std::tuple<u32, u32, bool> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||||
AjmInstanceGapless& gapless) = 0;
|
AjmInstanceGapless& gapless) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AjmInstance {
|
class AjmInstance {
|
||||||
@@ -89,6 +95,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool HasEnoughSpace(const SparseOutputBuffer& output) const;
|
bool HasEnoughSpace(const SparseOutputBuffer& output) const;
|
||||||
std::optional<u32> GetNumRemainingSamples() const;
|
std::optional<u32> GetNumRemainingSamples() const;
|
||||||
|
void Reset();
|
||||||
|
|
||||||
AjmInstanceFlags m_flags{};
|
AjmInstanceFlags m_flags{};
|
||||||
AjmSidebandFormat m_format{};
|
AjmSidebandFormat m_format{};
|
||||||
@@ -96,7 +103,6 @@ private:
|
|||||||
AjmSidebandResampleParameters m_resample_parameters{};
|
AjmSidebandResampleParameters m_resample_parameters{};
|
||||||
u32 m_total_samples{};
|
u32 m_total_samples{};
|
||||||
std::unique_ptr<AjmCodec> m_codec;
|
std::unique_ptr<AjmCodec> m_codec;
|
||||||
bool is_initialized = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Libraries::Ajm
|
} // namespace Libraries::Ajm
|
||||||
|
|||||||
@@ -138,8 +138,9 @@ void AjmMp3Decoder::GetInfo(void* out_info) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOutputBuffer& output,
|
std::tuple<u32, u32, bool> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf,
|
||||||
AjmInstanceGapless& gapless) {
|
SparseOutputBuffer& output,
|
||||||
|
AjmInstanceGapless& gapless) {
|
||||||
AVPacket* pkt = av_packet_alloc();
|
AVPacket* pkt = av_packet_alloc();
|
||||||
|
|
||||||
if ((!m_header.has_value() || m_frame_samples == 0) && in_buf.size() >= 4) {
|
if ((!m_header.has_value() || m_frame_samples == 0) && in_buf.size() >= 4) {
|
||||||
@@ -155,7 +156,7 @@ std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOut
|
|||||||
in_buf = in_buf.subspan(ret);
|
in_buf = in_buf.subspan(ret);
|
||||||
|
|
||||||
u32 frames_decoded = 0;
|
u32 frames_decoded = 0;
|
||||||
u32 samples_written = 0;
|
u32 samples_decoded = 0;
|
||||||
|
|
||||||
if (pkt->size) {
|
if (pkt->size) {
|
||||||
// Send the packet with the compressed data to the decoder
|
// Send the packet with the compressed data to the decoder
|
||||||
@@ -176,6 +177,7 @@ std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOut
|
|||||||
UNREACHABLE_MSG("Error during decoding");
|
UNREACHABLE_MSG("Error during decoding");
|
||||||
}
|
}
|
||||||
frame = ConvertAudioFrame(frame);
|
frame = ConvertAudioFrame(frame);
|
||||||
|
samples_decoded += u32(frame->nb_samples);
|
||||||
|
|
||||||
frames_decoded += 1;
|
frames_decoded += 1;
|
||||||
u32 skip_samples = 0;
|
u32 skip_samples = 0;
|
||||||
@@ -205,7 +207,6 @@ std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOut
|
|||||||
}
|
}
|
||||||
|
|
||||||
const auto samples = pcm_written / m_codec_context->ch_layout.nb_channels;
|
const auto samples = pcm_written / m_codec_context->ch_layout.nb_channels;
|
||||||
samples_written += samples;
|
|
||||||
gapless.current.skipped_samples += frame->nb_samples - samples;
|
gapless.current.skipped_samples += frame->nb_samples - samples;
|
||||||
if (gapless.init.total_samples != 0) {
|
if (gapless.init.total_samples != 0) {
|
||||||
gapless.current.total_samples -= samples;
|
gapless.current.total_samples -= samples;
|
||||||
@@ -217,7 +218,7 @@ std::tuple<u32, u32> AjmMp3Decoder::ProcessData(std::span<u8>& in_buf, SparseOut
|
|||||||
|
|
||||||
av_packet_free(&pkt);
|
av_packet_free(&pkt);
|
||||||
|
|
||||||
return {frames_decoded, samples_written};
|
return {frames_decoded, samples_decoded, false};
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 AjmMp3Decoder::GetNextFrameSize(const AjmInstanceGapless& gapless) const {
|
u32 AjmMp3Decoder::GetNextFrameSize(const AjmInstanceGapless& gapless) const {
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ public:
|
|||||||
void GetInfo(void* out_info) const override;
|
void GetInfo(void* out_info) const override;
|
||||||
AjmSidebandFormat GetFormat() const override;
|
AjmSidebandFormat GetFormat() const override;
|
||||||
u32 GetNextFrameSize(const AjmInstanceGapless& gapless) const override;
|
u32 GetNextFrameSize(const AjmInstanceGapless& gapless) const override;
|
||||||
std::tuple<u32, u32> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
std::tuple<u32, u32, bool> ProcessData(std::span<u8>& input, SparseOutputBuffer& output,
|
||||||
AjmInstanceGapless& gapless) override;
|
AjmInstanceGapless& gapless) override;
|
||||||
|
|
||||||
static int ParseMp3Header(const u8* buf, u32 stream_size, int parse_ofl,
|
static int ParseMp3Header(const u8* buf, u32 stream_size, int parse_ofl,
|
||||||
AjmDecMp3ParseFrame* frame);
|
AjmDecMp3ParseFrame* frame);
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ static void AudioOutputThread(PortOut* port, const std::stop_token& stop) {
|
|||||||
timer.Start();
|
timer.Start();
|
||||||
{
|
{
|
||||||
std::unique_lock lock{port->mutex};
|
std::unique_lock lock{port->mutex};
|
||||||
if (port->output_cv.wait(lock, stop, [&] { return port->output_ready; })) {
|
if (port->output_ready) {
|
||||||
port->impl->Output(port->output_buffer);
|
port->impl->Output(port->output_buffer);
|
||||||
port->output_ready = false;
|
port->output_ready = false;
|
||||||
}
|
}
|
||||||
@@ -413,7 +413,6 @@ s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, void* ptr) {
|
|||||||
samples_sent = port.buffer_frames * port.format_info.num_channels;
|
samples_sent = port.buffer_frames * port.format_info.num_channels;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
port.output_cv.notify_one();
|
|
||||||
return samples_sent;
|
return samples_sent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,23 +9,22 @@
|
|||||||
|
|
||||||
namespace Libraries::AvPlayer {
|
namespace Libraries::AvPlayer {
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerAddSource(SceAvPlayerHandle handle, const char* filename) {
|
s32 PS4_SYSV_ABI sceAvPlayerAddSource(AvPlayerHandle handle, const char* filename) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "filename = {}", filename);
|
LOG_TRACE(Lib_AvPlayer, "filename = {}", filename);
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
const auto res = handle->AddSource(filename);
|
return handle->AddSource(filename);
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerAddSourceEx(SceAvPlayerHandle handle, SceAvPlayerUriType uriType,
|
s32 PS4_SYSV_ABI sceAvPlayerAddSourceEx(AvPlayerHandle handle, AvPlayerUriType uri_type,
|
||||||
SceAvPlayerSourceDetails* sourceDetails) {
|
AvPlayerSourceDetails* source_details) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr || uri_type != AvPlayerUriType::Source) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
const auto path = std::string_view(source_details->uri.name, source_details->uri.length);
|
||||||
|
return handle->AddSourceEx(path, source_details->source_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceAvPlayerChangeStream() {
|
int PS4_SYSV_ABI sceAvPlayerChangeStream() {
|
||||||
@@ -33,28 +32,24 @@ int PS4_SYSV_ABI sceAvPlayerChangeStream() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerClose(SceAvPlayerHandle handle) {
|
s32 PS4_SYSV_ABI sceAvPlayerClose(AvPlayerHandle handle) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning ORBIS_AVPLAYER_ERROR_INVALID_PARAMS");
|
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
delete handle;
|
delete handle;
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning ORBIS_OK");
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 PS4_SYSV_ABI sceAvPlayerCurrentTime(SceAvPlayerHandle handle) {
|
u64 PS4_SYSV_ABI sceAvPlayerCurrentTime(AvPlayerHandle handle) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
const auto res = handle->CurrentTime();
|
return handle->CurrentTime();
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerDisableStream(SceAvPlayerHandle handle, u32 stream_id) {
|
s32 PS4_SYSV_ABI sceAvPlayerDisableStream(AvPlayerHandle handle, u32 stream_id) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called");
|
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
@@ -62,60 +57,49 @@ s32 PS4_SYSV_ABI sceAvPlayerDisableStream(SceAvPlayerHandle handle, u32 stream_i
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerEnableStream(SceAvPlayerHandle handle, u32 stream_id) {
|
s32 PS4_SYSV_ABI sceAvPlayerEnableStream(AvPlayerHandle handle, u32 stream_id) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "stream_id = {}", stream_id);
|
LOG_TRACE(Lib_AvPlayer, "stream_id = {}", stream_id);
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
const auto res = handle->EnableStream(stream_id);
|
return handle->EnableStream(stream_id);
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PS4_SYSV_ABI sceAvPlayerGetAudioData(SceAvPlayerHandle handle, SceAvPlayerFrameInfo* p_info) {
|
bool PS4_SYSV_ABI sceAvPlayerGetAudioData(AvPlayerHandle handle, AvPlayerFrameInfo* p_info) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr || p_info == nullptr) {
|
if (handle == nullptr || p_info == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return false;
|
||||||
}
|
}
|
||||||
const auto res = handle->GetAudioData(*p_info);
|
return handle->GetAudioData(*p_info);
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerGetStreamInfo(SceAvPlayerHandle handle, u32 stream_id,
|
s32 PS4_SYSV_ABI sceAvPlayerGetStreamInfo(AvPlayerHandle handle, u32 stream_id,
|
||||||
SceAvPlayerStreamInfo* p_info) {
|
AvPlayerStreamInfo* p_info) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "stream_id = {}", stream_id);
|
LOG_TRACE(Lib_AvPlayer, "stream_id = {}", stream_id);
|
||||||
if (handle == nullptr || p_info == nullptr) {
|
if (handle == nullptr || p_info == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
const auto res = handle->GetStreamInfo(stream_id, *p_info);
|
return handle->GetStreamInfo(stream_id, *p_info);
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PS4_SYSV_ABI sceAvPlayerGetVideoData(SceAvPlayerHandle handle,
|
bool PS4_SYSV_ABI sceAvPlayerGetVideoData(AvPlayerHandle handle, AvPlayerFrameInfo* video_info) {
|
||||||
SceAvPlayerFrameInfo* video_info) {
|
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr || video_info == nullptr) {
|
if (handle == nullptr || video_info == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return false;
|
||||||
}
|
}
|
||||||
const auto res = handle->GetVideoData(*video_info);
|
return handle->GetVideoData(*video_info);
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PS4_SYSV_ABI sceAvPlayerGetVideoDataEx(SceAvPlayerHandle handle,
|
bool PS4_SYSV_ABI sceAvPlayerGetVideoDataEx(AvPlayerHandle handle,
|
||||||
SceAvPlayerFrameInfoEx* video_info) {
|
AvPlayerFrameInfoEx* video_info) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr || video_info == nullptr) {
|
if (handle == nullptr || video_info == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return false;
|
||||||
}
|
}
|
||||||
const auto res = handle->GetVideoData(*video_info);
|
return handle->GetVideoData(*video_info);
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SceAvPlayerHandle PS4_SYSV_ABI sceAvPlayerInit(SceAvPlayerInitData* data) {
|
AvPlayerHandle PS4_SYSV_ABI sceAvPlayerInit(AvPlayerInitData* data) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (data == nullptr) {
|
if (data == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -125,15 +109,14 @@ SceAvPlayerHandle PS4_SYSV_ABI sceAvPlayerInit(SceAvPlayerInitData* data) {
|
|||||||
data->memory_replacement.allocate_texture == nullptr ||
|
data->memory_replacement.allocate_texture == nullptr ||
|
||||||
data->memory_replacement.deallocate == nullptr ||
|
data->memory_replacement.deallocate == nullptr ||
|
||||||
data->memory_replacement.deallocate_texture == nullptr) {
|
data->memory_replacement.deallocate_texture == nullptr) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "All allocators are required for AVPlayer Initialisation.");
|
LOG_ERROR(Lib_AvPlayer, "All allocators are required for AvPlayer Initialisation.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new AvPlayer(*data);
|
return new AvPlayer(*data);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerInitEx(const SceAvPlayerInitDataEx* p_data,
|
s32 PS4_SYSV_ABI sceAvPlayerInitEx(const AvPlayerInitDataEx* p_data, AvPlayerHandle* p_player) {
|
||||||
SceAvPlayerHandle* p_player) {
|
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (p_data == nullptr || p_player == nullptr) {
|
if (p_data == nullptr || p_player == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
@@ -143,11 +126,11 @@ s32 PS4_SYSV_ABI sceAvPlayerInitEx(const SceAvPlayerInitDataEx* p_data,
|
|||||||
p_data->memory_replacement.allocate_texture == nullptr ||
|
p_data->memory_replacement.allocate_texture == nullptr ||
|
||||||
p_data->memory_replacement.deallocate == nullptr ||
|
p_data->memory_replacement.deallocate == nullptr ||
|
||||||
p_data->memory_replacement.deallocate_texture == nullptr) {
|
p_data->memory_replacement.deallocate_texture == nullptr) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "All allocators are required for AVPlayer Initialisation.");
|
LOG_ERROR(Lib_AvPlayer, "All allocators are required for AvPlayer Initialisation.");
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SceAvPlayerInitData data = {};
|
AvPlayerInitData data = {};
|
||||||
data.memory_replacement = p_data->memory_replacement;
|
data.memory_replacement = p_data->memory_replacement;
|
||||||
data.file_replacement = p_data->file_replacement;
|
data.file_replacement = p_data->file_replacement;
|
||||||
data.event_replacement = p_data->event_replacement;
|
data.event_replacement = p_data->event_replacement;
|
||||||
@@ -159,18 +142,15 @@ s32 PS4_SYSV_ABI sceAvPlayerInitEx(const SceAvPlayerInitDataEx* p_data,
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PS4_SYSV_ABI sceAvPlayerIsActive(SceAvPlayerHandle handle) {
|
bool PS4_SYSV_ABI sceAvPlayerIsActive(AvPlayerHandle handle) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning false");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto res = handle->IsActive();
|
return handle->IsActive();
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerJumpToTime(SceAvPlayerHandle handle, uint64_t time) {
|
s32 PS4_SYSV_ABI sceAvPlayerJumpToTime(AvPlayerHandle handle, uint64_t time) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called, time (msec) = {}", time);
|
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called, time (msec) = {}", time);
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
@@ -178,22 +158,20 @@ s32 PS4_SYSV_ABI sceAvPlayerJumpToTime(SceAvPlayerHandle handle, uint64_t time)
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerPause(SceAvPlayerHandle handle) {
|
s32 PS4_SYSV_ABI sceAvPlayerPause(AvPlayerHandle handle) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return handle->Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerPostInit(SceAvPlayerHandle handle, SceAvPlayerPostInitData* data) {
|
s32 PS4_SYSV_ABI sceAvPlayerPostInit(AvPlayerHandle handle, AvPlayerPostInitData* data) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr || data == nullptr) {
|
if (handle == nullptr || data == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
const auto res = handle->PostInit(*data);
|
return handle->PostInit(*data);
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerPrintf(const char* format, ...) {
|
s32 PS4_SYSV_ABI sceAvPlayerPrintf(const char* format, ...) {
|
||||||
@@ -201,29 +179,28 @@ s32 PS4_SYSV_ABI sceAvPlayerPrintf(const char* format, ...) {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerResume(SceAvPlayerHandle handle) {
|
s32 PS4_SYSV_ABI sceAvPlayerResume(AvPlayerHandle handle) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return handle->Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerSetAvSyncMode(SceAvPlayerHandle handle,
|
s32 PS4_SYSV_ABI sceAvPlayerSetAvSyncMode(AvPlayerHandle handle, AvPlayerAvSyncMode sync_mode) {
|
||||||
SceAvPlayerAvSyncMode sync_mode) {
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called");
|
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return handle->SetAvSyncMode(sync_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerSetLogCallback(SceAvPlayerLogCallback log_cb, void* user_data) {
|
s32 PS4_SYSV_ABI sceAvPlayerSetLogCallback(AvPlayerLogCallback log_cb, void* user_data) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called");
|
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerSetLooping(SceAvPlayerHandle handle, bool loop_flag) {
|
s32 PS4_SYSV_ABI sceAvPlayerSetLooping(AvPlayerHandle handle, bool loop_flag) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called, looping = {}", loop_flag);
|
LOG_TRACE(Lib_AvPlayer, "called, looping = {}", loop_flag);
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
@@ -234,43 +211,36 @@ s32 PS4_SYSV_ABI sceAvPlayerSetLooping(SceAvPlayerHandle handle, bool loop_flag)
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerSetTrickSpeed(SceAvPlayerHandle handle, s32 trick_speed) {
|
s32 PS4_SYSV_ABI sceAvPlayerSetTrickSpeed(AvPlayerHandle handle, s32 trick_speed) {
|
||||||
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called");
|
LOG_ERROR(Lib_AvPlayer, "(STUBBED) called speed = {}", trick_speed);
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerStart(SceAvPlayerHandle handle) {
|
s32 PS4_SYSV_ABI sceAvPlayerStart(AvPlayerHandle handle) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
const auto res = handle->Start();
|
return handle->Start();
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerStop(SceAvPlayerHandle handle) {
|
s32 PS4_SYSV_ABI sceAvPlayerStop(AvPlayerHandle handle) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning ORBIS_AVPLAYER_ERROR_INVALID_PARAMS");
|
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
const auto res = handle->Stop();
|
return handle->Stop();
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerStreamCount(SceAvPlayerHandle handle) {
|
s32 PS4_SYSV_ABI sceAvPlayerStreamCount(AvPlayerHandle handle) {
|
||||||
LOG_TRACE(Lib_AvPlayer, "called");
|
LOG_TRACE(Lib_AvPlayer, "called");
|
||||||
if (handle == nullptr) {
|
if (handle == nullptr) {
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
const auto res = handle->GetStreamCount();
|
return handle->GetStreamCount();
|
||||||
LOG_TRACE(Lib_AvPlayer, "returning {}", res);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceAvPlayerVprintf(const char* format, va_list args) {
|
s32 PS4_SYSV_ABI sceAvPlayerVprintf(const char* format, va_list args) {
|
||||||
|
|||||||
@@ -16,38 +16,38 @@ namespace Libraries::AvPlayer {
|
|||||||
|
|
||||||
class AvPlayer;
|
class AvPlayer;
|
||||||
|
|
||||||
using SceAvPlayerHandle = AvPlayer*;
|
using AvPlayerHandle = AvPlayer*;
|
||||||
|
|
||||||
enum class SceAvPlayerUriType : u32 {
|
enum class AvPlayerUriType : u32 {
|
||||||
Source = 0,
|
Source = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerUri {
|
struct AvPlayerUri {
|
||||||
const char* name;
|
const char* name;
|
||||||
u32 length;
|
u32 length;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SceAvPlayerSourceType {
|
enum class AvPlayerSourceType {
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
FileMp4 = 1,
|
FileMp4 = 1,
|
||||||
Hls = 8,
|
Hls = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SceAvPlayerStreamType : u32 {
|
enum class AvPlayerStreamType : u32 {
|
||||||
Video,
|
Video,
|
||||||
Audio,
|
Audio,
|
||||||
TimedText,
|
TimedText,
|
||||||
Unknown,
|
Unknown,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerSourceDetails {
|
struct AvPlayerSourceDetails {
|
||||||
SceAvPlayerUri uri;
|
AvPlayerUri uri;
|
||||||
u8 reserved1[64];
|
u8 reserved1[64];
|
||||||
SceAvPlayerSourceType source_type;
|
AvPlayerSourceType source_type;
|
||||||
u8 reserved2[44];
|
u8 reserved2[44];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerAudio {
|
struct AvPlayerAudio {
|
||||||
u16 channel_count;
|
u16 channel_count;
|
||||||
u8 reserved1[2];
|
u8 reserved1[2];
|
||||||
u32 sample_rate;
|
u32 sample_rate;
|
||||||
@@ -55,50 +55,50 @@ struct SceAvPlayerAudio {
|
|||||||
u8 language_code[4];
|
u8 language_code[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerVideo {
|
struct AvPlayerVideo {
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
f32 aspect_ratio;
|
f32 aspect_ratio;
|
||||||
char language_code[4];
|
char language_code[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerTextPosition {
|
struct AvPlayerTextPosition {
|
||||||
u16 top;
|
u16 top;
|
||||||
u16 left;
|
u16 left;
|
||||||
u16 bottom;
|
u16 bottom;
|
||||||
u16 right;
|
u16 right;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerTimedText {
|
struct AvPlayerTimedText {
|
||||||
u8 language_code[4];
|
u8 language_code[4];
|
||||||
u16 text_size;
|
u16 text_size;
|
||||||
u16 font_size;
|
u16 font_size;
|
||||||
SceAvPlayerTextPosition position;
|
AvPlayerTextPosition position;
|
||||||
};
|
};
|
||||||
|
|
||||||
union SceAvPlayerStreamDetails {
|
union AvPlayerStreamDetails {
|
||||||
u8 reserved[16];
|
u8 reserved[16];
|
||||||
SceAvPlayerAudio audio;
|
AvPlayerAudio audio;
|
||||||
SceAvPlayerVideo video;
|
AvPlayerVideo video;
|
||||||
SceAvPlayerTimedText subs;
|
AvPlayerTimedText subs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerFrameInfo {
|
struct AvPlayerFrameInfo {
|
||||||
u8* pData;
|
u8* p_data;
|
||||||
u8 reserved[4];
|
u8 reserved[4];
|
||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
SceAvPlayerStreamDetails details;
|
AvPlayerStreamDetails details;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerStreamInfo {
|
struct AvPlayerStreamInfo {
|
||||||
SceAvPlayerStreamType type;
|
AvPlayerStreamType type;
|
||||||
u8 reserved[4];
|
u8 reserved[4];
|
||||||
SceAvPlayerStreamDetails details;
|
AvPlayerStreamDetails details;
|
||||||
u64 duration;
|
u64 duration;
|
||||||
u64 start_time;
|
u64 start_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerAudioEx {
|
struct AvPlayerAudioEx {
|
||||||
u16 channel_count;
|
u16 channel_count;
|
||||||
u8 reserved[2];
|
u8 reserved[2];
|
||||||
u32 sample_rate;
|
u32 sample_rate;
|
||||||
@@ -107,7 +107,7 @@ struct SceAvPlayerAudioEx {
|
|||||||
u8 reserved1[64];
|
u8 reserved1[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerVideoEx {
|
struct AvPlayerVideoEx {
|
||||||
u32 width;
|
u32 width;
|
||||||
u32 height;
|
u32 height;
|
||||||
f32 aspect_ratio;
|
f32 aspect_ratio;
|
||||||
@@ -124,53 +124,53 @@ struct SceAvPlayerVideoEx {
|
|||||||
u8 reserved1[37];
|
u8 reserved1[37];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerTimedTextEx {
|
struct AvPlayerTimedTextEx {
|
||||||
u8 language_code[4];
|
u8 language_code[4];
|
||||||
u8 reserved[12];
|
u8 reserved[12];
|
||||||
u8 reserved1[64];
|
u8 reserved1[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
union SceAvPlayerStreamDetailsEx {
|
union AvPlayerStreamDetailsEx {
|
||||||
SceAvPlayerAudioEx audio;
|
AvPlayerAudioEx audio;
|
||||||
SceAvPlayerVideoEx video;
|
AvPlayerVideoEx video;
|
||||||
SceAvPlayerTimedTextEx subs;
|
AvPlayerTimedTextEx subs;
|
||||||
u8 reserved1[80];
|
u8 reserved1[80];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerFrameInfoEx {
|
struct AvPlayerFrameInfoEx {
|
||||||
void* pData;
|
void* p_data;
|
||||||
u8 reserved[4];
|
u8 reserved[4];
|
||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
SceAvPlayerStreamDetailsEx details;
|
AvPlayerStreamDetailsEx details;
|
||||||
};
|
};
|
||||||
|
|
||||||
using SceAvPlayerAllocate = void* PS4_SYSV_ABI (*)(void* p, u32 align, u32 size);
|
using AvPlayerAllocate = void* PS4_SYSV_ABI (*)(void* p, u32 align, u32 size);
|
||||||
using SceAvPlayerDeallocate = void PS4_SYSV_ABI (*)(void* p, void* mem);
|
using AvPlayerDeallocate = void PS4_SYSV_ABI (*)(void* p, void* mem);
|
||||||
using SceAvPlayerAllocateTexture = void* PS4_SYSV_ABI (*)(void* p, u32 align, u32 size);
|
using AvPlayerAllocateTexture = void* PS4_SYSV_ABI (*)(void* p, u32 align, u32 size);
|
||||||
using SceAvPlayerDeallocateTexture = void PS4_SYSV_ABI (*)(void* p, void* mem);
|
using AvPlayerDeallocateTexture = void PS4_SYSV_ABI (*)(void* p, void* mem);
|
||||||
|
|
||||||
struct SceAvPlayerMemAllocator {
|
struct AvPlayerMemAllocator {
|
||||||
void* object_ptr;
|
void* object_ptr;
|
||||||
SceAvPlayerAllocate allocate;
|
AvPlayerAllocate allocate;
|
||||||
SceAvPlayerDeallocate deallocate;
|
AvPlayerDeallocate deallocate;
|
||||||
SceAvPlayerAllocateTexture allocate_texture;
|
AvPlayerAllocateTexture allocate_texture;
|
||||||
SceAvPlayerDeallocateTexture deallocate_texture;
|
AvPlayerDeallocateTexture deallocate_texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
using SceAvPlayerOpenFile = s32 PS4_SYSV_ABI (*)(void* p, const char* name);
|
using AvPlayerOpenFile = s32 PS4_SYSV_ABI (*)(void* p, const char* name);
|
||||||
using SceAvPlayerCloseFile = s32 PS4_SYSV_ABI (*)(void* p);
|
using AvPlayerCloseFile = s32 PS4_SYSV_ABI (*)(void* p);
|
||||||
using SceAvPlayerReadOffsetFile = s32 PS4_SYSV_ABI (*)(void* p, u8* buf, u64 pos, u32 len);
|
using AvPlayerReadOffsetFile = s32 PS4_SYSV_ABI (*)(void* p, u8* buf, u64 pos, u32 len);
|
||||||
using SceAvPlayerSizeFile = u64 PS4_SYSV_ABI (*)(void* p);
|
using AvPlayerSizeFile = u64 PS4_SYSV_ABI (*)(void* p);
|
||||||
|
|
||||||
struct SceAvPlayerFileReplacement {
|
struct AvPlayerFileReplacement {
|
||||||
void* object_ptr;
|
void* object_ptr;
|
||||||
SceAvPlayerOpenFile open;
|
AvPlayerOpenFile open;
|
||||||
SceAvPlayerCloseFile close;
|
AvPlayerCloseFile close;
|
||||||
SceAvPlayerReadOffsetFile readOffset;
|
AvPlayerReadOffsetFile read_offset;
|
||||||
SceAvPlayerSizeFile size;
|
AvPlayerSizeFile size;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SceAvPlayerEvents {
|
enum class AvPlayerEvents {
|
||||||
StateStop = 0x01,
|
StateStop = 0x01,
|
||||||
StateReady = 0x02,
|
StateReady = 0x02,
|
||||||
StatePlay = 0x03,
|
StatePlay = 0x03,
|
||||||
@@ -182,26 +182,26 @@ enum class SceAvPlayerEvents {
|
|||||||
DrmError = 0x40,
|
DrmError = 0x40,
|
||||||
};
|
};
|
||||||
|
|
||||||
using SceAvPlayerEventCallback = void PS4_SYSV_ABI (*)(void* p, SceAvPlayerEvents event, s32 src_id,
|
using AvPlayerEventCallback = void PS4_SYSV_ABI (*)(void* p, AvPlayerEvents event, s32 src_id,
|
||||||
void* data);
|
void* data);
|
||||||
|
|
||||||
struct SceAvPlayerEventReplacement {
|
struct AvPlayerEventReplacement {
|
||||||
void* object_ptr;
|
void* object_ptr;
|
||||||
SceAvPlayerEventCallback event_callback;
|
AvPlayerEventCallback event_callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SceAvPlayerDebuglevels {
|
enum class AvPlayerDebuglevels {
|
||||||
None,
|
None,
|
||||||
Info,
|
Info,
|
||||||
Warnings,
|
Warnings,
|
||||||
All,
|
All,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerInitData {
|
struct AvPlayerInitData {
|
||||||
SceAvPlayerMemAllocator memory_replacement;
|
AvPlayerMemAllocator memory_replacement;
|
||||||
SceAvPlayerFileReplacement file_replacement;
|
AvPlayerFileReplacement file_replacement;
|
||||||
SceAvPlayerEventReplacement event_replacement;
|
AvPlayerEventReplacement event_replacement;
|
||||||
SceAvPlayerDebuglevels debug_level;
|
AvPlayerDebuglevels debug_level;
|
||||||
u32 base_priority;
|
u32 base_priority;
|
||||||
s32 num_output_video_framebuffers;
|
s32 num_output_video_framebuffers;
|
||||||
bool auto_start;
|
bool auto_start;
|
||||||
@@ -209,13 +209,13 @@ struct SceAvPlayerInitData {
|
|||||||
const char* default_language;
|
const char* default_language;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerInitDataEx {
|
struct AvPlayerInitDataEx {
|
||||||
size_t this_size;
|
size_t this_size;
|
||||||
SceAvPlayerMemAllocator memory_replacement;
|
AvPlayerMemAllocator memory_replacement;
|
||||||
SceAvPlayerFileReplacement file_replacement;
|
AvPlayerFileReplacement file_replacement;
|
||||||
SceAvPlayerEventReplacement event_replacement;
|
AvPlayerEventReplacement event_replacement;
|
||||||
const char* default_language;
|
const char* default_language;
|
||||||
SceAvPlayerDebuglevels debug_level;
|
AvPlayerDebuglevels debug_level;
|
||||||
u32 audio_decoder_priority;
|
u32 audio_decoder_priority;
|
||||||
u32 audio_decoder_affinity;
|
u32 audio_decoder_affinity;
|
||||||
u32 video_decoder_priority;
|
u32 video_decoder_priority;
|
||||||
@@ -233,25 +233,25 @@ struct SceAvPlayerInitDataEx {
|
|||||||
u8 reserved[3];
|
u8 reserved[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SceAvPlayerVideoDecoderType {
|
enum class AvPlayerVideoDecoderType {
|
||||||
Default = 0,
|
Default = 0,
|
||||||
Reserved1,
|
Reserved1,
|
||||||
Software,
|
Software,
|
||||||
Software2,
|
Software2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SceAvPlayerAudioDecoderType {
|
enum class AvPlayerAudioDecoderType {
|
||||||
Default = 0,
|
Default = 0,
|
||||||
Reserved1,
|
Reserved1,
|
||||||
Reserved2,
|
Reserved2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerDecoderInit {
|
struct AvPlayerDecoderInit {
|
||||||
union {
|
union {
|
||||||
SceAvPlayerVideoDecoderType video_type;
|
AvPlayerVideoDecoderType video_type;
|
||||||
SceAvPlayerAudioDecoderType audio_type;
|
AvPlayerAudioDecoderType audio_type;
|
||||||
u8 reserved[4];
|
u8 reserved[4];
|
||||||
} decoderType;
|
} decoder_type;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
s32 cpu_affinity_mask;
|
s32 cpu_affinity_mask;
|
||||||
@@ -261,34 +261,34 @@ struct SceAvPlayerDecoderInit {
|
|||||||
u8 compute_queue_id;
|
u8 compute_queue_id;
|
||||||
u8 enable_interlaced;
|
u8 enable_interlaced;
|
||||||
u8 reserved[16];
|
u8 reserved[16];
|
||||||
} avcSw2;
|
} avc_sw2;
|
||||||
struct {
|
struct {
|
||||||
u8 audio_channel_order;
|
u8 audio_channel_order;
|
||||||
u8 reserved[27];
|
u8 reserved[27];
|
||||||
} aac;
|
} aac;
|
||||||
u8 reserved[28];
|
u8 reserved[28];
|
||||||
} decoderParams;
|
} decoder_params;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerHTTPCtx {
|
struct AvPlayerHTTPCtx {
|
||||||
u32 http_context_id;
|
u32 http_context_id;
|
||||||
u32 ssl_context_id;
|
u32 ssl_context_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SceAvPlayerPostInitData {
|
struct AvPlayerPostInitData {
|
||||||
u32 demux_video_buffer_size;
|
u32 demux_video_buffer_size;
|
||||||
SceAvPlayerDecoderInit video_decoder_init;
|
AvPlayerDecoderInit video_decoder_init;
|
||||||
SceAvPlayerDecoderInit audio_decoder_init;
|
AvPlayerDecoderInit audio_decoder_init;
|
||||||
SceAvPlayerHTTPCtx http_context;
|
AvPlayerHTTPCtx http_context;
|
||||||
u8 reserved[56];
|
u8 reserved[56];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SceAvPlayerAvSyncMode {
|
enum class AvPlayerAvSyncMode {
|
||||||
Default = 0,
|
Default = 0,
|
||||||
None,
|
None,
|
||||||
};
|
};
|
||||||
|
|
||||||
using SceAvPlayerLogCallback = int PS4_SYSV_ABI (*)(void* p, const char* format, va_list args);
|
using AvPlayerLogCallback = int PS4_SYSV_ABI (*)(void* p, const char* format, va_list args);
|
||||||
|
|
||||||
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
void RegisterLib(Core::Loader::SymbolsResolver* sym);
|
||||||
|
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ static bool iequals(std::string_view l, std::string_view r) {
|
|||||||
return std::ranges::equal(l, r, [](u8 a, u8 b) { return std::tolower(a) == std::tolower(b); });
|
return std::ranges::equal(l, r, [](u8 a, u8 b) { return std::tolower(a) == std::tolower(b); });
|
||||||
}
|
}
|
||||||
|
|
||||||
SceAvPlayerSourceType GetSourceType(std::string_view path) {
|
AvPlayerSourceType GetSourceType(std::string_view path) {
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
return SceAvPlayerSourceType::Unknown;
|
return AvPlayerSourceType::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view name = path;
|
std::string_view name = path;
|
||||||
@@ -25,14 +25,14 @@ SceAvPlayerSourceType GetSourceType(std::string_view path) {
|
|||||||
// -> schema://server.domain/path/to/file.ext/and/beyond
|
// -> schema://server.domain/path/to/file.ext/and/beyond
|
||||||
name = path.substr(0, path.find_first_of("?#"));
|
name = path.substr(0, path.find_first_of("?#"));
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
return SceAvPlayerSourceType::Unknown;
|
return AvPlayerSourceType::Unknown;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// schema://server.domain/path/to/file.ext/and/beyond -> .ext/and/beyond
|
// schema://server.domain/path/to/file.ext/and/beyond -> .ext/and/beyond
|
||||||
auto ext = name.substr(name.rfind('.'));
|
auto ext = name.substr(name.rfind('.'));
|
||||||
if (ext.empty()) {
|
if (ext.empty()) {
|
||||||
return SceAvPlayerSourceType::Unknown;
|
return AvPlayerSourceType::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
// .ext/and/beyond -> .ext
|
// .ext/and/beyond -> .ext
|
||||||
@@ -40,14 +40,14 @@ SceAvPlayerSourceType GetSourceType(std::string_view path) {
|
|||||||
|
|
||||||
if (iequals(ext, ".mp4") || iequals(ext, ".m4v") || iequals(ext, ".m3d") ||
|
if (iequals(ext, ".mp4") || iequals(ext, ".m4v") || iequals(ext, ".m3d") ||
|
||||||
iequals(ext, ".m4a") || iequals(ext, ".mov")) {
|
iequals(ext, ".m4a") || iequals(ext, ".mov")) {
|
||||||
return SceAvPlayerSourceType::FileMp4;
|
return AvPlayerSourceType::FileMp4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iequals(ext, ".m3u8")) {
|
if (iequals(ext, ".m3u8")) {
|
||||||
return SceAvPlayerSourceType::Hls;
|
return AvPlayerSourceType::Hls;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SceAvPlayerSourceType::Unknown;
|
return AvPlayerSourceType::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::AvPlayer
|
} // namespace Libraries::AvPlayer
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
namespace Libraries::AvPlayer {
|
namespace Libraries::AvPlayer {
|
||||||
|
|
||||||
enum class AvState {
|
enum class AvState {
|
||||||
|
Unknown,
|
||||||
Initial,
|
Initial,
|
||||||
AddingSource,
|
AddingSource,
|
||||||
Ready,
|
Ready,
|
||||||
@@ -64,6 +65,10 @@ public:
|
|||||||
m_queue.emplace(std::forward<T>(value));
|
m_queue.emplace(std::forward<T>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T& Front() {
|
||||||
|
return m_queue.front();
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<T> Pop() {
|
std::optional<T> Pop() {
|
||||||
if (Size() == 0) {
|
if (Size() == 0) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
@@ -84,6 +89,6 @@ private:
|
|||||||
std::queue<T> m_queue{};
|
std::queue<T> m_queue{};
|
||||||
};
|
};
|
||||||
|
|
||||||
SceAvPlayerSourceType GetSourceType(std::string_view path);
|
AvPlayerSourceType GetSourceType(std::string_view path);
|
||||||
|
|
||||||
} // namespace Libraries::AvPlayer
|
} // namespace Libraries::AvPlayer
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class IDataStreamer {
|
|||||||
public:
|
public:
|
||||||
virtual ~IDataStreamer() = default;
|
virtual ~IDataStreamer() = default;
|
||||||
virtual bool Init(std::string_view path) = 0;
|
virtual bool Init(std::string_view path) = 0;
|
||||||
|
virtual void Reset() = 0;
|
||||||
virtual AVIOContext* GetContext() = 0;
|
virtual AVIOContext* GetContext() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ constexpr u32 AVPLAYER_AVIO_BUFFER_SIZE = 4096;
|
|||||||
|
|
||||||
namespace Libraries::AvPlayer {
|
namespace Libraries::AvPlayer {
|
||||||
|
|
||||||
AvPlayerFileStreamer::AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement)
|
AvPlayerFileStreamer::AvPlayerFileStreamer(const AvPlayerFileReplacement& file_replacement)
|
||||||
: m_file_replacement(file_replacement) {}
|
: m_file_replacement(file_replacement) {}
|
||||||
|
|
||||||
AvPlayerFileStreamer::~AvPlayerFileStreamer() {
|
AvPlayerFileStreamer::~AvPlayerFileStreamer() {
|
||||||
@@ -43,6 +43,10 @@ bool AvPlayerFileStreamer::Init(std::string_view path) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvPlayerFileStreamer::Reset() {
|
||||||
|
m_position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
s32 AvPlayerFileStreamer::ReadPacket(void* opaque, u8* buffer, s32 size) {
|
s32 AvPlayerFileStreamer::ReadPacket(void* opaque, u8* buffer, s32 size) {
|
||||||
const auto self = reinterpret_cast<AvPlayerFileStreamer*>(opaque);
|
const auto self = reinterpret_cast<AvPlayerFileStreamer*>(opaque);
|
||||||
if (self->m_position >= self->m_file_size) {
|
if (self->m_position >= self->m_file_size) {
|
||||||
@@ -51,7 +55,7 @@ s32 AvPlayerFileStreamer::ReadPacket(void* opaque, u8* buffer, s32 size) {
|
|||||||
if (self->m_position + size > self->m_file_size) {
|
if (self->m_position + size > self->m_file_size) {
|
||||||
size = self->m_file_size - self->m_position;
|
size = self->m_file_size - self->m_position;
|
||||||
}
|
}
|
||||||
const auto read_offset = self->m_file_replacement.readOffset;
|
const auto read_offset = self->m_file_replacement.read_offset;
|
||||||
const auto ptr = self->m_file_replacement.object_ptr;
|
const auto ptr = self->m_file_replacement.object_ptr;
|
||||||
const auto bytes_read = read_offset(ptr, buffer, self->m_position, size);
|
const auto bytes_read = read_offset(ptr, buffer, self->m_position, size);
|
||||||
if (bytes_read == 0 && size != 0) {
|
if (bytes_read == 0 && size != 0) {
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ namespace Libraries::AvPlayer {
|
|||||||
|
|
||||||
class AvPlayerFileStreamer : public IDataStreamer {
|
class AvPlayerFileStreamer : public IDataStreamer {
|
||||||
public:
|
public:
|
||||||
AvPlayerFileStreamer(const SceAvPlayerFileReplacement& file_replacement);
|
AvPlayerFileStreamer(const AvPlayerFileReplacement& file_replacement);
|
||||||
~AvPlayerFileStreamer();
|
~AvPlayerFileStreamer();
|
||||||
|
|
||||||
bool Init(std::string_view path) override;
|
bool Init(std::string_view path) override;
|
||||||
|
void Reset() override;
|
||||||
|
|
||||||
AVIOContext* GetContext() override {
|
AVIOContext* GetContext() override {
|
||||||
return m_avio_context;
|
return m_avio_context;
|
||||||
@@ -26,7 +27,7 @@ private:
|
|||||||
static s32 ReadPacket(void* opaque, u8* buffer, s32 size);
|
static s32 ReadPacket(void* opaque, u8* buffer, s32 size);
|
||||||
static s64 Seek(void* opaque, s64 buffer, int whence);
|
static s64 Seek(void* opaque, s64 buffer, int whence);
|
||||||
|
|
||||||
SceAvPlayerFileReplacement m_file_replacement;
|
AvPlayerFileReplacement m_file_replacement;
|
||||||
|
|
||||||
int m_fd = -1;
|
int m_fd = -1;
|
||||||
u64 m_position{};
|
u64 m_position{};
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ int PS4_SYSV_ABI AvPlayer::ReadOffsetFile(void* handle, u8* buffer, u64 position
|
|||||||
auto const self = reinterpret_cast<AvPlayer*>(handle);
|
auto const self = reinterpret_cast<AvPlayer*>(handle);
|
||||||
std::lock_guard guard(self->m_file_io_mutex);
|
std::lock_guard guard(self->m_file_io_mutex);
|
||||||
|
|
||||||
const auto read_offset = self->m_init_data_original.file_replacement.readOffset;
|
const auto read_offset = self->m_init_data_original.file_replacement.read_offset;
|
||||||
const auto ptr = self->m_init_data_original.file_replacement.object_ptr;
|
const auto ptr = self->m_init_data_original.file_replacement.object_ptr;
|
||||||
return Core::ExecuteGuest(read_offset, ptr, buffer, position, length);
|
return Core::ExecuteGuest(read_offset, ptr, buffer, position, length);
|
||||||
}
|
}
|
||||||
@@ -72,38 +72,46 @@ u64 PS4_SYSV_ABI AvPlayer::SizeFile(void* handle) {
|
|||||||
return Core::ExecuteGuest(size, ptr);
|
return Core::ExecuteGuest(size, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SceAvPlayerInitData AvPlayer::StubInitData(const SceAvPlayerInitData& data) {
|
AvPlayerInitData AvPlayer::StubInitData(const AvPlayerInitData& data) {
|
||||||
SceAvPlayerInitData result = data;
|
AvPlayerInitData result = data;
|
||||||
result.memory_replacement.object_ptr = this;
|
result.memory_replacement.object_ptr = this;
|
||||||
result.memory_replacement.allocate = &AvPlayer::Allocate;
|
result.memory_replacement.allocate = &AvPlayer::Allocate;
|
||||||
result.memory_replacement.deallocate = &AvPlayer::Deallocate;
|
result.memory_replacement.deallocate = &AvPlayer::Deallocate;
|
||||||
result.memory_replacement.allocate_texture = &AvPlayer::AllocateTexture;
|
result.memory_replacement.allocate_texture = &AvPlayer::AllocateTexture;
|
||||||
result.memory_replacement.deallocate_texture = &AvPlayer::DeallocateTexture;
|
result.memory_replacement.deallocate_texture = &AvPlayer::DeallocateTexture;
|
||||||
if (data.file_replacement.open == nullptr || data.file_replacement.close == nullptr ||
|
if (data.file_replacement.open == nullptr || data.file_replacement.close == nullptr ||
|
||||||
data.file_replacement.readOffset == nullptr || data.file_replacement.size == nullptr) {
|
data.file_replacement.read_offset == nullptr || data.file_replacement.size == nullptr) {
|
||||||
result.file_replacement = {};
|
result.file_replacement = {};
|
||||||
} else {
|
} else {
|
||||||
result.file_replacement.object_ptr = this;
|
result.file_replacement.object_ptr = this;
|
||||||
result.file_replacement.open = &AvPlayer::OpenFile;
|
result.file_replacement.open = &AvPlayer::OpenFile;
|
||||||
result.file_replacement.close = &AvPlayer::CloseFile;
|
result.file_replacement.close = &AvPlayer::CloseFile;
|
||||||
result.file_replacement.readOffset = &AvPlayer::ReadOffsetFile;
|
result.file_replacement.read_offset = &AvPlayer::ReadOffsetFile;
|
||||||
result.file_replacement.size = &AvPlayer::SizeFile;
|
result.file_replacement.size = &AvPlayer::SizeFile;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AvPlayer::AvPlayer(const SceAvPlayerInitData& data)
|
AvPlayer::AvPlayer(const AvPlayerInitData& data)
|
||||||
: m_init_data(StubInitData(data)), m_init_data_original(data),
|
: m_init_data(StubInitData(data)), m_init_data_original(data),
|
||||||
m_state(std::make_unique<AvPlayerState>(m_init_data)) {}
|
m_state(std::make_unique<AvPlayerState>(m_init_data)) {}
|
||||||
|
|
||||||
s32 AvPlayer::PostInit(const SceAvPlayerPostInitData& data) {
|
s32 AvPlayer::PostInit(const AvPlayerPostInitData& data) {
|
||||||
m_state->PostInit(data);
|
m_state->PostInit(data);
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 AvPlayer::AddSource(std::string_view path) {
|
s32 AvPlayer::AddSource(std::string_view path) {
|
||||||
if (path.empty()) {
|
return AddSourceEx(path, AvPlayerSourceType::Unknown);
|
||||||
return ORBIS_AVPLAYER_ERROR_INVALID_PARAMS;
|
}
|
||||||
|
|
||||||
|
s32 AvPlayer::AddSourceEx(std::string_view path, AvPlayerSourceType source_type) {
|
||||||
|
if (source_type == AvPlayerSourceType::Unknown) {
|
||||||
|
source_type = GetSourceType(path);
|
||||||
|
}
|
||||||
|
if (source_type == AvPlayerSourceType::Hls) {
|
||||||
|
LOG_ERROR(Lib_AvPlayer, "HTTP Live Streaming is not implemented");
|
||||||
|
return ORBIS_AVPLAYER_ERROR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
if (!m_state->AddSource(path, GetSourceType(path))) {
|
if (!m_state->AddSource(path, GetSourceType(path))) {
|
||||||
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||||
@@ -122,7 +130,7 @@ s32 AvPlayer::GetStreamCount() {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 AvPlayer::GetStreamInfo(u32 stream_index, SceAvPlayerStreamInfo& info) {
|
s32 AvPlayer::GetStreamInfo(u32 stream_index, AvPlayerStreamInfo& info) {
|
||||||
if (!m_state->GetStreamInfo(stream_index, info)) {
|
if (!m_state->GetStreamInfo(stream_index, info)) {
|
||||||
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
@@ -140,27 +148,49 @@ s32 AvPlayer::EnableStream(u32 stream_index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 AvPlayer::Start() {
|
s32 AvPlayer::Start() {
|
||||||
if (!m_state->Start()) {
|
if (m_state == nullptr || !m_state->Start()) {
|
||||||
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||||
}
|
}
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AvPlayer::GetVideoData(SceAvPlayerFrameInfo& video_info) {
|
s32 AvPlayer::Pause() {
|
||||||
|
if (m_state == nullptr || !m_state->Pause()) {
|
||||||
|
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 AvPlayer::Resume() {
|
||||||
|
if (m_state == nullptr || !m_state->Resume()) {
|
||||||
|
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 AvPlayer::SetAvSyncMode(AvPlayerAvSyncMode sync_mode) {
|
||||||
|
if (m_state == nullptr) {
|
||||||
|
return ORBIS_AVPLAYER_ERROR_OPERATION_FAILED;
|
||||||
|
}
|
||||||
|
m_state->SetAvSyncMode(sync_mode);
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AvPlayer::GetVideoData(AvPlayerFrameInfo& video_info) {
|
||||||
if (m_state == nullptr) {
|
if (m_state == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return m_state->GetVideoData(video_info);
|
return m_state->GetVideoData(video_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AvPlayer::GetVideoData(SceAvPlayerFrameInfoEx& video_info) {
|
bool AvPlayer::GetVideoData(AvPlayerFrameInfoEx& video_info) {
|
||||||
if (m_state == nullptr) {
|
if (m_state == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return m_state->GetVideoData(video_info);
|
return m_state->GetVideoData(video_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AvPlayer::GetAudioData(SceAvPlayerFrameInfo& audio_info) {
|
bool AvPlayer::GetAudioData(AvPlayerFrameInfo& audio_info) {
|
||||||
if (m_state == nullptr) {
|
if (m_state == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user