mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
145 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76e6208d1b | ||
|
|
bc09080ba5 | ||
|
|
a6eb257a3a | ||
|
|
e62450d255 | ||
|
|
1aa922f700 | ||
|
|
4c9d2f99b1 | ||
|
|
f6e899b570 | ||
|
|
695c39fba2 | ||
|
|
e5616cff98 | ||
|
|
76d5994c1e | ||
|
|
cbb40832a1 | ||
|
|
e4bdcde1ca | ||
|
|
863e119ff4 | ||
|
|
2ccf6dc872 | ||
|
|
24ebf1b4f1 | ||
|
|
ed2832434c | ||
|
|
5e160fca8f | ||
|
|
a0ef82e221 | ||
|
|
3e7ac3d66c | ||
|
|
730e6fa737 | ||
|
|
cdfcd9fddd | ||
|
|
b6930c10b9 | ||
|
|
852734580d | ||
|
|
d1dc6a9c1d | ||
|
|
4fa6d3ed3f | ||
|
|
92e190ad6c | ||
|
|
da4fcffef4 | ||
|
|
1a5731dd8e | ||
|
|
e764c5cd4e | ||
|
|
e23b247947 | ||
|
|
3d7792436f | ||
|
|
d8187fbea4 | ||
|
|
02259ad0a5 | ||
|
|
220a68df9a | ||
|
|
2ced24f69e | ||
|
|
ec91d0dc74 | ||
|
|
46874f4673 | ||
|
|
9eac47dc6c | ||
|
|
9e3fd5c2e0 | ||
|
|
ae4be6e2b1 | ||
|
|
434df49a7d | ||
|
|
c939c0fcd5 | ||
|
|
952c39f324 | ||
|
|
0fea7e2a70 | ||
|
|
c1baab68d0 | ||
|
|
ccef18f7a9 | ||
|
|
8cb056bde3 | ||
|
|
6ecaaee9e0 | ||
|
|
c5f916bda0 | ||
|
|
52a9a4649c | ||
|
|
d2219b4dbd | ||
|
|
155f603245 | ||
|
|
cb7630a6ab | ||
|
|
284fba1ce3 | ||
|
|
aa4bd6c88c | ||
|
|
623993930b | ||
|
|
dbf2c854c6 | ||
|
|
25351bc05c | ||
|
|
27cc5f499c | ||
|
|
b7c2f39a17 | ||
|
|
3541c1ccf8 | ||
|
|
7a05738d11 | ||
|
|
686220ae0c | ||
|
|
cf380d36b9 | ||
|
|
50bc0193ac | ||
|
|
2162a72831 | ||
|
|
313666f85b | ||
|
|
e9d79263b4 | ||
|
|
4ede6d65fd | ||
|
|
14d2eee371 | ||
|
|
717f370be0 | ||
|
|
d05e4b9727 | ||
|
|
697c53b4d8 | ||
|
|
d9b58ec3ce | ||
|
|
6c8b37d7ca | ||
|
|
39f43e766d | ||
|
|
5379a13944 | ||
|
|
cd0c1607ef | ||
|
|
26a4f71385 | ||
|
|
06b3e6ad71 | ||
|
|
79d22a8d77 | ||
|
|
9914212600 | ||
|
|
765f55e67b | ||
|
|
2d922cc035 | ||
|
|
42e0625ab3 | ||
|
|
c72e894fc7 | ||
|
|
5bc2342d47 | ||
|
|
ea2b0b5e59 | ||
|
|
d70cc0221a | ||
|
|
b12587b44e | ||
|
|
c4708bdc35 | ||
|
|
1fa2c0bf50 | ||
|
|
b4c70d357a | ||
|
|
f18262ee96 | ||
|
|
c1f1761482 | ||
|
|
067c3eea16 | ||
|
|
6957cc7001 | ||
|
|
7dea23eea8 | ||
|
|
319ec1f774 | ||
|
|
2079532e83 | ||
|
|
de1d646fe9 | ||
|
|
4bc3ab6285 | ||
|
|
1adc9cbb49 | ||
|
|
7cdf5eefc9 | ||
|
|
c7ee72647d | ||
|
|
5434af348e | ||
|
|
169cea0f01 | ||
|
|
a8f3ec8184 | ||
|
|
7796b2a12b | ||
|
|
d9cffd58ba | ||
|
|
e566386240 | ||
|
|
45af1e172f | ||
|
|
768b2e52a6 | ||
|
|
7abd2009b0 | ||
|
|
46f075e891 | ||
|
|
832c381ac4 | ||
|
|
e021282264 | ||
|
|
2a60d385c6 | ||
|
|
4d37e35675 | ||
|
|
df3868a280 | ||
|
|
0799bb8cf1 | ||
|
|
69048dede4 | ||
|
|
76df6d1f43 | ||
|
|
2d03b21f2b | ||
|
|
62cbd44933 | ||
|
|
44c8f6d8b0 | ||
|
|
f3fc1dd59c | ||
|
|
708931e48b | ||
|
|
81800d2883 | ||
|
|
d0411d7ddf | ||
|
|
70e232cab3 | ||
|
|
f90396bda4 | ||
|
|
ae8808b86e | ||
|
|
8d5b827432 | ||
|
|
cb672697e7 | ||
|
|
0bae9fc29b | ||
|
|
49c8b68700 | ||
|
|
1e2fcd17e0 | ||
|
|
468b9d2655 | ||
|
|
a3305ff791 | ||
|
|
814b0d5873 | ||
|
|
863f3e82ac | ||
|
|
529c756458 | ||
|
|
67b98dbdaa | ||
|
|
a16981cbe5 |
54
.github/CONTRIBUTING.md
vendored
54
.github/CONTRIBUTING.md
vendored
@@ -1,54 +0,0 @@
|
||||
# So you want to contribute to PCSX2? Great
|
||||
|
||||
As a first step, please review these links as they'll help you understand how the development of PCSX2 works.
|
||||
|
||||
* [Just Starting Out](#just-starting-out)
|
||||
* [Issue Reporting](#issue-reporting)
|
||||
* [Pull Request Guidelines](#pull-request-guidelines)
|
||||
* [General Documentation And Coding Strategies](#general-documentation-and-coding-strategies)
|
||||
* [Tasks](#tasks)
|
||||
|
||||
## Just Starting Out
|
||||
|
||||
* If you're unfamilar with git, check out this [brief introduction to Git](https://github.com/PCSX2/pcsx2/wiki/07-Git-survival-guide)
|
||||
* [How to build PCSX2 for Windows](https://github.com/PCSX2/pcsx2/wiki/12-Building-on-Windows)
|
||||
* [How to build PCSX2 for Linux](https://github.com/PCSX2/pcsx2/wiki/10-Building-on-Linux)
|
||||
|
||||
## Issue Reporting
|
||||
|
||||
* [How to write a useful issue](https://github.com/PCSX2/pcsx2/wiki/How-to-create-useful-and-valid-issues)
|
||||
|
||||
## Pull Request Guidelines
|
||||
|
||||
The following is a list of *general* style recommendations that will make reviewing and merging easier:
|
||||
|
||||
* Commit Messages
|
||||
* Please try to prefix your commit message, indicating what area of the project was modified.
|
||||
* For example `gs: message...`.
|
||||
* Looking at the project's commit history will help with keeping prefixes consistent overtime, *there is no strictly enforced list*.
|
||||
|
||||
* Try to keep messages brief and informative
|
||||
|
||||
* Remove unnecessary commits and squash commits together when appropriate.
|
||||
* If you are not familiar with rebasing with git, check out the following resources:
|
||||
* CLI - https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history
|
||||
* GUI (SourceTree) - https://www.atlassian.com/blog/sourcetree/interactive-rebase-sourcetree
|
||||
|
||||
* Code Styling and Formatting
|
||||
* [Consult the style guide](https://github.com/tadanokojin/pcsx2/blob/coding-guide/pcsx2/Docs/Coding_Guidelines.md)
|
||||
|
||||
* Run `clang-format` using the configuration file in the root of the repository
|
||||
* Visual Studio Setup - https://devblogs.microsoft.com/cppblog/clangformat-support-in-visual-studio-2017-15-7-preview-1/
|
||||
* IMPORTANT - if you are running `clang-format` on unrelated changes (ie. formatting an entire file), please do so in a separate commit.
|
||||
* If you cannot scope your `clang-format` to just your changes and do not want to format unrelated code. Try your best to stick with the existing formatting already established in the file in question.
|
||||
|
||||
## General Documentation And Coding Strategies
|
||||
|
||||
* [Commenting Etiquette](https://github.com/PCSX2/pcsx2/wiki/06-Commenting-Etiquette)
|
||||
|
||||
* [Coding style](https://github.com/PCSX2/pcsx2/wiki/Code-Formatting-Guidelines)
|
||||
* [More comprehensive style-guide (Currently in Draft)](https://github.com/tadanokojin/pcsx2/blob/coding-guide/pcsx2/Docs/Coding_Guidelines.md)
|
||||
|
||||
## Tasks
|
||||
|
||||
* [Issues](https://github.com/PCSX2/pcsx2/issues)
|
||||
4
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
4
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
@@ -66,6 +66,10 @@ body:
|
||||
|
||||
Performance issues as a result of not meeting our hardware requirements are not valid.
|
||||
|
||||
Please read our troubleshooting pages and our issue reporting guide.
|
||||
- [Troubleshooting page](https://pcsx2.net/docs/category/troubleshooting).
|
||||
- [Issue reporting guide](https://pcsx2.net/docs/troubleshooting/identify).
|
||||
|
||||
We are **not** accepting issues related to the **libretro** core. The libretro core is being maintained separately at this time
|
||||
- type: input
|
||||
id: rev
|
||||
|
||||
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -6,3 +6,6 @@
|
||||
|
||||
### Suggested Testing Steps
|
||||
<!-- If applicable, including examples you've already tested with / recommendations for how to test further is very helpful! -->
|
||||
|
||||
### Did you use AI to help find, test, or implement this issue or feature?
|
||||
<!-- Answer yes or no. If you answer yes, please provide a brief explanation how. -->
|
||||
|
||||
4
.github/workflows/linux_build_flatpak.yml
vendored
4
.github/workflows/linux_build_flatpak.yml
vendored
@@ -132,7 +132,7 @@ jobs:
|
||||
|
||||
- name: Push to Flathub (beta)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == false || inputs.stableBuild == 'false') }}
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: beta
|
||||
@@ -141,7 +141,7 @@ jobs:
|
||||
|
||||
- name: Push to Flathub (stable)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == true || inputs.stableBuild == 'true') }}
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: stable
|
||||
|
||||
@@ -18,7 +18,7 @@ LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBPNG=1.6.48
|
||||
LIBWEBP=1.5.0
|
||||
SDL=SDL3-3.2.12
|
||||
SDL=SDL3-3.2.14
|
||||
QT=6.9.0
|
||||
LZ4=1.10.0
|
||||
ZSTD=1.5.7
|
||||
@@ -39,7 +39,7 @@ fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96 $SDL.tar.gz
|
||||
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
c1800c2ea835801af04a05d4a32321d79a93954ee3ae2172bbeacf13d1f0598c qtbase-everywhere-src-$QT.tar.xz
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.12.tar.gz",
|
||||
"sha256": "9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96"
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.14.tar.gz",
|
||||
"sha256": "b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -11,10 +11,9 @@
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"type": "git",
|
||||
"url": "https://github.com/sammycage/plutovg.git",
|
||||
"tag": "v0.0.13",
|
||||
"sha256": "5e4712cf873b0c7829a4a6157763e2ad3ac49164"
|
||||
"tag": "v0.0.13"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -12,10 +12,9 @@
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"type": "git",
|
||||
"url": "https://github.com/sammycage/plutosvg.git",
|
||||
"tag": "v0.0.6",
|
||||
"sha256": "c5388fa96feca1f1376a3d0485d5e35159452707"
|
||||
"tag": "v0.0.6"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -11,7 +11,7 @@ merge_binaries() {
|
||||
"
|
||||
pushd "$X86DIR"
|
||||
for X86BIN in $(find . -type f \( -name '*.dylib' -o -name '*.a' -o -perm +111 \)); do
|
||||
if file "$X86DIR/$X86BIN" | grep "Mach-O " >/dev/null; then
|
||||
if file "$X86DIR/$X86BIN" | grep "Mach-O.*x86_64" >/dev/null; then
|
||||
ARMBIN="${ARMDIR}/${X86BIN}"
|
||||
echo "Merge $ARMBIN to $X86BIN..."
|
||||
lipo -create "$X86BIN" "$ARMBIN" -o "$X86BIN"
|
||||
@@ -40,7 +40,7 @@ fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
SDL=SDL3-3.2.12
|
||||
SDL=SDL3-3.2.14
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.48
|
||||
@@ -79,7 +79,7 @@ CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96 $SDL.tar.gz
|
||||
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
|
||||
@@ -112,11 +112,11 @@ curl -C - -L \
|
||||
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
|
||||
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
|
||||
-O "https://github.com/KhronosGroup/MoltenVK/archive/refs/tags/v$MOLTENVK.tar.gz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
|
||||
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
|
||||
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
|
||||
@@ -213,8 +213,11 @@ echo "Installing libjpegturbo..."
|
||||
rm -fr "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
tar xf "libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
|
||||
cd "libjpeg-turbo-$LIBJPEGTURBO"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build-arm64
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_X64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build
|
||||
make -C build "-j$NPROCS"
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build-arm64
|
||||
make -C build-arm64 "-j$NPROCS"
|
||||
merge_binaries $(realpath build) $(realpath build-arm64)
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
@@ -380,7 +383,7 @@ echo "Building PlutoVG..."
|
||||
rm -fr "plutovg-$PLUTOVG"
|
||||
tar xf "plutovg-$PLUTOVG.tar.gz"
|
||||
cd "plutovg-$PLUTOVG"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPLUTOVG_BUILD_EXAMPLES=OFF -B build
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DBUILD_SHARED_LIBS=ON -DPLUTOVG_BUILD_EXAMPLES=OFF -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
@@ -389,7 +392,7 @@ echo "Building PlutoSVG..."
|
||||
rm -fr "plutosvg-$PLUTOSVG"
|
||||
tar xf "plutosvg-$PLUTOSVG.tar.gz"
|
||||
cd "plutosvg-$PLUTOSVG"
|
||||
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build
|
||||
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
@@ -22,7 +22,7 @@ fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
SDL=SDL3-3.2.12
|
||||
SDL=SDL3-3.2.14
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.48
|
||||
@@ -59,7 +59,7 @@ CMAKE_COMMON=(
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96 $SDL.tar.gz
|
||||
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
|
||||
|
||||
@@ -66,7 +66,7 @@ const embed = new MessageEmbed()
|
||||
.setDescription("To download the latest or previous builds, [visit the official downloads page](https://pcsx2.net/downloads/).")
|
||||
.addFields(
|
||||
{ name: 'Version', value: releaseInfo.tag_name, inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://github.com/PCSX2/pcsx2/wiki/Nightly-Build-Usage-Guide)', inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://pcsx2.net/docs/category/setup)', inline: true },
|
||||
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
|
||||
);
|
||||
console.log(embed);
|
||||
|
||||
@@ -46,7 +46,7 @@ set FREETYPE=2.13.3
|
||||
set HARFBUZZ=11.2.0
|
||||
set LIBJPEGTURBO=3.1.0
|
||||
set LIBPNG=1648
|
||||
set SDL=SDL3-3.2.12
|
||||
set SDL=SDL3-3.2.14
|
||||
set QT=6.9.0
|
||||
set QTMINOR=6.9
|
||||
set LZ4=1.10.0
|
||||
@@ -68,7 +68,7 @@ call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuz
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1648.zip 2e5f080360f77376eb2bfa9e2ed773b9c7728159aba47b638ad53ca839379040 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" ebf1efd71527afbca6bdf2b0310caf726d00cc102c0e59ac86c1f8cd201f9593 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 46a17d3ea71fe2580a7f43ca7da286c5b9106dd761e2fd5533bb113e5d86b633 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 513df15a6365a40f6230ec9463ad8c71b824e181d4b661dac9707e103b24ae0c || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" d428fd17a0d3f92c48a30f1d23806bf20352fbce2e80e5bbee27fa80576480ee || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 54bf06afeb67035f1c6afcd00beec755c0d776626b4cce9ab56992a55215ba69 || goto error
|
||||
@@ -246,12 +246,21 @@ cmake --build . --parallel || goto error
|
||||
ninja install || goto error
|
||||
cd ..\.. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
|
||||
) else (
|
||||
rem kddockwidgets slightly changes the name of the dll depending on if CMAKE_BUILD_TYPE or CMAKE_CONFIGURATION_TYPES is used
|
||||
rem The dll name being kddockwidgets-qt62.dll or kddockwidgets-qt62.dll respectively
|
||||
rem Always use CMAKE_CONFIGURATION_TYPES to give consistant naming
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES=Release -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=Release -G "Ninja Multi-Config"
|
||||
)
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rmdir /S /Q "KDDockWidgets-%KDDOCKWIDGETS%"
|
||||
%SEVENZIP% x "KDDockWidgets-%KDDOCKWIDGETS%.zip" || goto error
|
||||
cd "KDDockWidgets-%KDDOCKWIDGETS%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\kddockwidgets-dodgy-include.patch" || goto error
|
||||
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja || goto error
|
||||
cmake -B build %ARM64TOOLCHAIN% -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets %KDDOCKWIDGETSBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
@@ -44,7 +44,7 @@ set FREETYPE=2.13.3
|
||||
set HARFBUZZ=11.2.0
|
||||
set LIBJPEGTURBO=3.1.0
|
||||
set LIBPNG=1648
|
||||
set SDL=SDL3-3.2.12
|
||||
set SDL=SDL3-3.2.14
|
||||
set QT=6.9.0
|
||||
set QTMINOR=6.9
|
||||
set LZ4=1.10.0
|
||||
@@ -66,7 +66,7 @@ call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuz
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1648.zip 2e5f080360f77376eb2bfa9e2ed773b9c7728159aba47b638ad53ca839379040 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" ebf1efd71527afbca6bdf2b0310caf726d00cc102c0e59ac86c1f8cd201f9593 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 46a17d3ea71fe2580a7f43ca7da286c5b9106dd761e2fd5533bb113e5d86b633 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 513df15a6365a40f6230ec9463ad8c71b824e181d4b661dac9707e103b24ae0c || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" d428fd17a0d3f92c48a30f1d23806bf20352fbce2e80e5bbee27fa80576480ee || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 54bf06afeb67035f1c6afcd00beec755c0d776626b4cce9ab56992a55215ba69 || goto error
|
||||
@@ -250,12 +250,21 @@ cmake --build . --parallel || goto error
|
||||
ninja install || goto error
|
||||
cd ..\.. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
|
||||
) else (
|
||||
rem kddockwidgets slightly changes the name of the dll depending on if CMAKE_BUILD_TYPE or CMAKE_CONFIGURATION_TYPES is used
|
||||
rem The dll name being kddockwidgets-qt62.dll or kddockwidgets-qt62.dll respectively
|
||||
rem Always use CMAKE_CONFIGURATION_TYPES to give consistant naming
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES=Release -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=Release -G "Ninja Multi-Config"
|
||||
)
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rmdir /S /Q "KDDockWidgets-%KDDOCKWIDGETS%"
|
||||
%SEVENZIP% x "KDDockWidgets-%KDDOCKWIDGETS%.zip" || goto error
|
||||
cd "KDDockWidgets-%KDDOCKWIDGETS%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\kddockwidgets-dodgy-include.patch" || goto error
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja || goto error
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets %KDDOCKWIDGETSBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
2
.github/workflows/triage_pr.yml
vendored
2
.github/workflows/triage_pr.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
pr-message: |-
|
||||
## Thank you for submitting a contribution to PCSX2
|
||||
|
||||
As this is your first pull request, [please be aware of the contributing guidelines](https://github.com/PCSX2/pcsx2/blob/master/.github/CONTRIBUTING.md).
|
||||
As this is your first pull request, [please be aware of the contributing guidelines](https://pcsx2.net/docs/contributing/).
|
||||
|
||||
Additionally, as per recent changes in GitHub Actions, your pull request will need to be approved by a maintainer before GitHub Actions can run against it. [You can find more information about this change here.](https://github.blog/2021-04-22-github-actions-update-helping-maintainers-combat-bad-actors/)
|
||||
|
||||
|
||||
@@ -62,10 +62,12 @@ endif()
|
||||
|
||||
# gsrunner
|
||||
if(ENABLE_GSRUNNER)
|
||||
if (NOT WIN32)
|
||||
message(WARNING "GSRunner is only supported on Windows and may not build on your system")
|
||||
if (NOT WIN32 AND NOT APPLE)
|
||||
message(WARNING "GSRunner is only supported on Windows and macOS and may not build on your system")
|
||||
endif()
|
||||
add_subdirectory(pcsx2-gsrunner)
|
||||
else()
|
||||
add_subdirectory(pcsx2-gsrunner EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@@ -24,4 +24,4 @@ Please note that a BIOS dump from a legitimately-owned PS2 console is required t
|
||||
|
||||
PCSX2 supports translation into other languages using [Crowdin](https://crowdin.com/project/pcsx2-emulator).
|
||||
|
||||
See the [Contributing Guidelines](https://github.com/PCSX2/pcsx2/blob/master/.github/CONTRIBUTING.md) or visit the [GitHub Wiki](https://github.com/PCSX2/pcsx2/wiki) for more info on how to contribute.
|
||||
See the [Contribution Guide](https://pcsx2.net/docs/contributing/) for more info on how to contribute.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -154,6 +154,7 @@
|
||||
03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,
|
||||
030000005a1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
|
||||
030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
|
||||
030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
|
||||
030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
@@ -336,6 +337,7 @@
|
||||
03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows,
|
||||
03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows,
|
||||
03000000242f00000a20000000000000,Hyperkin Scout,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000242e00000a20000000000000,Hyperkin Scout Premium SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows,
|
||||
03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
|
||||
03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
@@ -418,7 +420,7 @@
|
||||
03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
|
||||
0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000242e0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
|
||||
03000000242f0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
|
||||
03000000242f0000f400000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
|
||||
03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows,
|
||||
030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
|
||||
@@ -484,7 +486,7 @@
|
||||
030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
|
||||
0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,
|
||||
03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
@@ -691,6 +693,7 @@
|
||||
03000000317300000100000000000000,Sony DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000666600006706000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
|
||||
03000000e30500009605000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000fe1400002a23000000000000,Sony PlayStation Adapter,a:b0,b:b1,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,x:b2,y:b3,platform:Windows,
|
||||
030000004c050000da0c000000000000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000632500002306000000000000,Sony PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000f0250000c183000000000000,Sony PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -997,6 +1000,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c62400002b89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000853200008906000000010000,Nacon Revolution X Unlimited,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000632500007505000000020000,NeoGeo mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X,
|
||||
030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
@@ -1008,6 +1012,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X,
|
||||
030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
030000006f0e00000901000002010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
|
||||
030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
03000000d620000011a7000000020000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1100,6 +1105,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,
|
||||
050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,
|
||||
030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4~,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000006f0e00000104000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000c6240000045d000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1278,7 +1284,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000006f0e00008401000011010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006f0e00008101000011010000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03005036852100000201000010010000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000852100000201000010010000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
05000000b40400001224000001010000,Flydigi APEX 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b20,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
@@ -1601,6 +1607,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
0300132d9b2800006500000001010000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
|
||||
030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
|
||||
030000009b2800006000000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
|
||||
030000009b2800006100000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux,
|
||||
030000009b2800006400000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux,
|
||||
030000009b2800008000000020020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux,
|
||||
030000009b2800008000000001010000,Raphnet Wii Classic Adapter V3,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux,
|
||||
03000000f8270000bf0b000011010000,Razer Kishi,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
@@ -1766,6 +1774,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000dd02000003020000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
@@ -1796,6 +1805,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000130b000022050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000200b000013050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000200b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
|
||||
@@ -313,6 +313,127 @@ float ps_convert_rgb5a1_float16_biln(PS_INPUT input) : SV_Depth
|
||||
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
// Convert a RGB5A1 texture into a 8 bits packed texture
|
||||
// Input column: 16x2 RGB5A1 pixels
|
||||
// 0: 16 RGBA
|
||||
// 1: 16 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 16 R5G2
|
||||
// 1: 16 R5G2
|
||||
// 2: 16 G2B5A1
|
||||
// 3: 16 G2B5A1
|
||||
uint2 pos = uint2(input.p.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uint2 column = (pos & ~uint2(0u, 3u)) / uint2(1,2);
|
||||
uint2 subcolumn = (pos & uint2(0u, 1u));
|
||||
column.x -= (column.x / 128) * 64;
|
||||
column.y += (column.y / 32) * 32;
|
||||
|
||||
uint PSM = uint(DOFFSET);
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((PSM & 0x8) != 0) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32) != 0)
|
||||
{
|
||||
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32;
|
||||
}
|
||||
|
||||
if ((pos.x & 64) != 0)
|
||||
{
|
||||
column.x -= 32;
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 16;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32) != 0)
|
||||
{
|
||||
column.y -= 16;
|
||||
column.x += 32;
|
||||
}
|
||||
|
||||
if ((pos.x & 96) != 0)
|
||||
{
|
||||
uint multi = (pos.x & 96) / 32;
|
||||
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96);
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 32;
|
||||
}
|
||||
}
|
||||
|
||||
uint2 coord = column | subcolumn;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uint SBW = uint(EMODA);
|
||||
uint DBW = uint(EMODC);
|
||||
uint2 block_xy = coord / uint2(64,64);
|
||||
uint block_num = (block_xy.y * (DBW / 128)) + block_xy.x;
|
||||
uint2 block_offset = uint2((block_num % (SBW / 64)) * 64, (block_num / (SBW / 64)) * 64);
|
||||
coord = (coord % uint2(64, 64)) + block_offset;
|
||||
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
uint is_col13 = pos.y & 2u;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
|
||||
float ScaleFactor = BGColor.x;
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uint2(float2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uint(ScaleFactor);
|
||||
|
||||
float4 pixel = Texture.Load(int3(int2(coord), 0));
|
||||
uint4 denorm_c = (uint4)(pixel * 255.5f);
|
||||
if ((pos.y & 2u) == 0u)
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
float sel0 = (float)(((green << 5) | red) & 0xFF) / 255.0f;
|
||||
|
||||
output.c = (float4)(sel0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
float sel0 = (float)((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
|
||||
|
||||
output.c = (float4)(sel0);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
@@ -397,7 +397,11 @@ float4 fetch_raw_color(int2 xy)
|
||||
|
||||
float4 fetch_c(int2 uv)
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return RtTexture.Load(int3(uv, 0));
|
||||
#else
|
||||
return Texture.Load(int3(uv, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -237,9 +237,131 @@ void ps_convert_rgb5a1_float16_biln()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_8i
|
||||
uniform uint SBW;
|
||||
uniform uint DBW;
|
||||
uniform uint PSM;
|
||||
uniform float ScaleFactor;
|
||||
|
||||
void ps_convert_rgb5a1_8i()
|
||||
{
|
||||
// Convert a RGB5A1 texture into a 8 bits packed texture
|
||||
// Input column: 16x2 RGB5A1 pixels
|
||||
// 0: 16 RGBA
|
||||
// 1: 16 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 16 R5G2
|
||||
// 1: 16 R5G2
|
||||
// 2: 16 G2B5A1
|
||||
// 3: 16 G2B5A1
|
||||
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1,2);
|
||||
uvec2 subcolumn = (pos & uvec2(0u, 1u));
|
||||
column.x -= (column.x / 128) * 64;
|
||||
column.y += (column.y / 32) * 32;
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((PSM & 0x8) != 0) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32) != 0)
|
||||
{
|
||||
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32;
|
||||
}
|
||||
|
||||
if ((pos.x & 64) != 0)
|
||||
{
|
||||
column.x -= 32;
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 16;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32) != 0)
|
||||
{
|
||||
column.y -= 16;
|
||||
column.x += 32;
|
||||
}
|
||||
|
||||
if ((pos.x & 96) != 0)
|
||||
{
|
||||
uint multi = (pos.x & 96) / 32;
|
||||
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96);
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 32;
|
||||
}
|
||||
}
|
||||
uvec2 coord = column | subcolumn;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 64u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 64u);
|
||||
coord = (coord % uvec2(64u, 64u)) + block_offset;
|
||||
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
uint is_col13 = pos.y & 2u;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
|
||||
|
||||
uvec4 denorm_c = uvec4(pixel * 255.5f);
|
||||
if ((pos.y & 2u) == 0u)
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
float sel0 = float(((green << 5) | red) & 0xFF) / 255.0f;
|
||||
|
||||
SV_Target0 = vec4(sel0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
float sel0 = float((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
|
||||
|
||||
SV_Target0 = vec4(sel0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba_8i
|
||||
uniform uint SBW;
|
||||
uniform uint DBW;
|
||||
uniform uint PSM;
|
||||
uniform float ScaleFactor;
|
||||
|
||||
void ps_convert_rgba_8i()
|
||||
|
||||
@@ -330,7 +330,11 @@ vec4 fetch_raw_color()
|
||||
|
||||
vec4 fetch_c(ivec2 uv)
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return sample_from_rt();
|
||||
#else
|
||||
return texelFetch(TextureSampler, ivec2(uv), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -307,12 +307,138 @@ void ps_convert_rgb5a1_float16_biln()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgb5a1_8i
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uint SBW;
|
||||
uint DBW;
|
||||
uint PSM;
|
||||
float cb_pad1;
|
||||
float ScaleFactor;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
void ps_convert_rgb5a1_8i()
|
||||
{
|
||||
// Convert a RGB5A1 texture into a 8 bits packed texture
|
||||
// Input column: 16x2 RGB5A1 pixels
|
||||
// 0: 16 RGBA
|
||||
// 1: 16 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 16 R5G2
|
||||
// 1: 16 R5G2
|
||||
// 2: 16 G2B5A1
|
||||
// 3: 16 G2B5A1
|
||||
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1,2);
|
||||
uvec2 subcolumn = (pos & uvec2(0u, 1u));
|
||||
column.x -= (column.x / 128) * 64;
|
||||
column.y += (column.y / 32) * 32;
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((PSM & 0x8) != 0) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32) != 0)
|
||||
{
|
||||
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32;
|
||||
}
|
||||
|
||||
if ((pos.x & 64) != 0)
|
||||
{
|
||||
column.x -= 32;
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 16;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32) != 0)
|
||||
{
|
||||
column.y -= 16;
|
||||
column.x += 32;
|
||||
}
|
||||
|
||||
if ((pos.x & 96) != 0)
|
||||
{
|
||||
uint multi = (pos.x & 96) / 32;
|
||||
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96);
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 32;
|
||||
}
|
||||
}
|
||||
uvec2 coord = column | subcolumn;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uvec2 block_xy = coord / uvec2(64u, 64u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 64u);
|
||||
coord = (coord % uvec2(64u, 64u)) + block_offset;
|
||||
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
uint is_col13 = pos.y & 2u;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
|
||||
if (floor(ScaleFactor) != ScaleFactor)
|
||||
coord = uvec2(vec2(coord) * ScaleFactor);
|
||||
else
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
|
||||
uvec4 denorm_c = uvec4(pixel * 255.5f);
|
||||
if ((pos.y & 2u) == 0u)
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
float sel0 = float(((green << 5) | red) & 0xFF) / 255.0f;
|
||||
|
||||
o_col0 = vec4(sel0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
float sel0 = float((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
|
||||
|
||||
o_col0 = vec4(sel0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_rgba_8i
|
||||
layout(push_constant) uniform cb10
|
||||
{
|
||||
uint SBW;
|
||||
uint DBW;
|
||||
uvec2 cb_pad1;
|
||||
uint PSM;
|
||||
float cb_pad1;
|
||||
float ScaleFactor;
|
||||
vec3 cb_pad2;
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@ include(GNUInstallDirs)
|
||||
# Misc option
|
||||
#-------------------------------------------------------------------------------
|
||||
option(ENABLE_TESTS "Enables building the unit tests" ON)
|
||||
option(ENABLE_GSRUNNER "Enables building the GSRunner" OFF)
|
||||
option(ENABLE_GSRUNNER "Enables building the GSRunner by default. It can still be built with `make pcsx2-gsrunner` otherwise." OFF)
|
||||
option(LTO_PCSX2_CORE "Enable LTO/IPO/LTCG on the subset of pcsx2 that benefits most from it but not anything else")
|
||||
option(USE_VTUNE "Plug VTUNE to profile GS JIT.")
|
||||
option(PACKAGE_MODE "Use this option to ease packaging of PCSX2 (developer/distribution option)")
|
||||
@@ -64,10 +64,13 @@ set(CMAKE_SHARED_LINKER_FLAGS_DEVEL "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}
|
||||
CACHE STRING "Flags used for linking shared libraries during development builds" FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}"
|
||||
CACHE STRING "Flags used for linking executables during development builds" FORCE)
|
||||
# Exclude Debug from the configurations we can import from
|
||||
set(CMAKE_MAP_IMPORTED_CONFIG_DEVEL "RelWithDebInfo" "Release" "MinSizeRel" "None" "NoConfig" ""
|
||||
CACHE STRING "Configurations used when importing packages for development builds" FORCE)
|
||||
if(CMAKE_CONFIGURATION_TYPES)
|
||||
list(INSERT CMAKE_CONFIGURATION_TYPES 0 Devel)
|
||||
endif()
|
||||
mark_as_advanced(CMAKE_C_FLAGS_DEVEL CMAKE_CXX_FLAGS_DEVEL CMAKE_LINKER_FLAGS_DEVEL CMAKE_SHARED_LINKER_FLAGS_DEVEL CMAKE_EXE_LINKER_FLAGS_DEVEL)
|
||||
mark_as_advanced(CMAKE_C_FLAGS_DEVEL CMAKE_CXX_FLAGS_DEVEL CMAKE_LINKER_FLAGS_DEVEL CMAKE_SHARED_LINKER_FLAGS_DEVEL CMAKE_EXE_LINKER_FLAGS_DEVEL CMAKE_MAP_IMPORTED_CONFIG_DEVEL)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Select the architecture
|
||||
|
||||
@@ -120,7 +120,7 @@ add_subdirectory(3rdparty/demangler EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/ccc EXCLUDE_FROM_ALL)
|
||||
|
||||
# The docking system for the debugger.
|
||||
find_package(KDDockWidgets-qt6 REQUIRED)
|
||||
find_package(KDDockWidgets-qt6 2.0.0 REQUIRED)
|
||||
# Add an extra include path to work around a broken include directive.
|
||||
# TODO: Remove this the next time we update KDDockWidgets.
|
||||
get_target_property(KDDOCKWIDGETS_INCLUDE_DIRECTORY KDAB::kddockwidgets INTERFACE_INCLUDE_DIRECTORIES)
|
||||
|
||||
@@ -31,6 +31,19 @@ namespace CocoaTools
|
||||
bool DelayedLaunch(std::string_view file);
|
||||
/// Open a Finder window to the given URL
|
||||
bool ShowInFinder(std::string_view file);
|
||||
/// Get the path to the resources directory of the current application
|
||||
std::optional<std::string> GetResourcePath();
|
||||
|
||||
/// Create a window
|
||||
void* CreateWindow(std::string_view title, uint32_t width, uint32_t height);
|
||||
/// Destroy a window
|
||||
void DestroyWindow(void* window);
|
||||
/// Make a WindowInfo from the given window
|
||||
void GetWindowInfoFromWindow(WindowInfo* wi, void* window);
|
||||
/// Run cocoa event loop
|
||||
void RunCocoaEventLoop(bool wait_forever = false);
|
||||
/// Posts an event to the main telling `RunCocoaEventLoop(true)` to exit
|
||||
void StopMainThreadEventLoop();
|
||||
}
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
@@ -224,5 +224,103 @@ bool CocoaTools::DelayedLaunch(std::string_view file)
|
||||
bool CocoaTools::ShowInFinder(std::string_view file)
|
||||
{
|
||||
return [[NSWorkspace sharedWorkspace] selectFile:NSStringFromStringView(file)
|
||||
inFileViewerRootedAtPath:nil];
|
||||
inFileViewerRootedAtPath:@""];
|
||||
}
|
||||
|
||||
std::optional<std::string> CocoaTools::GetResourcePath()
|
||||
{ @autoreleasepool {
|
||||
if (NSBundle* bundle = [NSBundle mainBundle])
|
||||
{
|
||||
NSString* rsrc = [bundle resourcePath];
|
||||
NSString* root = [bundle bundlePath];
|
||||
if ([rsrc isEqualToString:root])
|
||||
rsrc = [rsrc stringByAppendingString:@"/resources"];
|
||||
return [rsrc UTF8String];
|
||||
}
|
||||
return std::nullopt;
|
||||
}}
|
||||
|
||||
// MARK: - GSRunner
|
||||
|
||||
void* CocoaTools::CreateWindow(std::string_view title, u32 width, u32 height)
|
||||
{
|
||||
if (!NSApp)
|
||||
{
|
||||
[NSApplication sharedApplication];
|
||||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
[NSApp finishLaunching];
|
||||
}
|
||||
constexpr NSWindowStyleMask style = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable;
|
||||
NSScreen* mainScreen = [NSScreen mainScreen];
|
||||
// Center the window on the screen, because why not
|
||||
NSRect screenFrame = [mainScreen frame];
|
||||
NSRect viewFrame = screenFrame;
|
||||
viewFrame.size = NSMakeSize(width, height);
|
||||
viewFrame.origin.x += (screenFrame.size.width - viewFrame.size.width) / 2;
|
||||
viewFrame.origin.y += (screenFrame.size.height - viewFrame.size.height) / 2;
|
||||
NSWindow* window = [[NSWindow alloc]
|
||||
initWithContentRect:viewFrame
|
||||
styleMask:style
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:NO];
|
||||
[window setTitle:NSStringFromStringView(title)];
|
||||
[window makeKeyAndOrderFront:window];
|
||||
return (__bridge_retained void*)window;
|
||||
}
|
||||
|
||||
void CocoaTools::DestroyWindow(void* window)
|
||||
{
|
||||
(void)(__bridge_transfer NSWindow*)window;
|
||||
}
|
||||
|
||||
void CocoaTools::GetWindowInfoFromWindow(WindowInfo* wi, void* cf_window)
|
||||
{
|
||||
if (cf_window)
|
||||
{
|
||||
NSWindow* window = (__bridge NSWindow*)cf_window;
|
||||
float scale = [window backingScaleFactor];
|
||||
NSView* view = [window contentView];
|
||||
NSRect dims = [view frame];
|
||||
wi->type = WindowInfo::Type::MacOS;
|
||||
wi->window_handle = (__bridge void*)view;
|
||||
wi->surface_width = dims.size.width * scale;
|
||||
wi->surface_height = dims.size.height * scale;
|
||||
wi->surface_scale = scale;
|
||||
}
|
||||
else
|
||||
{
|
||||
wi->type = WindowInfo::Type::Surfaceless;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr short STOP_EVENT_LOOP = 0x100;
|
||||
|
||||
void CocoaTools::RunCocoaEventLoop(bool forever)
|
||||
{
|
||||
NSDate* end = forever ? [NSDate distantFuture] : [NSDate distantPast];
|
||||
[NSApplication sharedApplication]; // Ensure NSApp is initialized
|
||||
while (true)
|
||||
{ @autoreleasepool {
|
||||
NSEvent* ev = [NSApp nextEventMatchingMask:NSEventMaskAny
|
||||
untilDate:end
|
||||
inMode:NSDefaultRunLoopMode
|
||||
dequeue:YES];
|
||||
if (!ev || ([ev type] == NSEventTypeApplicationDefined && [ev subtype] == STOP_EVENT_LOOP))
|
||||
break;
|
||||
[NSApp sendEvent:ev];
|
||||
}}
|
||||
}
|
||||
|
||||
void CocoaTools::StopMainThreadEventLoop()
|
||||
{ @autoreleasepool {
|
||||
NSEvent* ev = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
|
||||
location:{}
|
||||
modifierFlags:0
|
||||
timestamp:0
|
||||
windowNumber:0
|
||||
context:nil
|
||||
subtype:STOP_EVENT_LOOP
|
||||
data1:0
|
||||
data2:0];
|
||||
[NSApp postEvent:ev atStart:NO];
|
||||
}}
|
||||
|
||||
@@ -437,7 +437,7 @@ std::unique_ptr<SharedMemoryMappingArea> SharedMemoryMappingArea::Create(size_t
|
||||
{
|
||||
pxAssertRel(Common::IsAlignedPow2(size, __pagesize), "Size is page aligned");
|
||||
|
||||
mach_vm_address_t alloc;
|
||||
mach_vm_address_t alloc = 0;
|
||||
const kern_return_t res =
|
||||
mach_vm_map(mach_task_self(), &alloc, size, 0, VM_FLAGS_ANYWHERE,
|
||||
MEMORY_OBJECT_NULL, 0, false, VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_NONE);
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>$(DepsLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);freetype.lib;jpeg.lib;libpng16.lib;libwebp.lib;lz4.lib;SDL3.lib;zlib.lib;zstd.lib;kddockwidgets-qt62.lib;plutovg.lib;plutosvg.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);freetype.lib;jpeg.lib;libpng16.lib;libwebp.lib;lz4.lib;SDL3.lib;zlib.lib;zstd.lib;plutovg.lib;plutosvg.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="$(Configuration.Contains(Debug))">%(AdditionalDependencies);kddockwidgets-qt6d.lib;</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="!$(Configuration.Contains(Debug))">%(AdditionalDependencies);kddockwidgets-qt6.lib;</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<DepsDLLs Include="$(DepsBinDir)freetype.dll" />
|
||||
@@ -19,7 +21,8 @@
|
||||
<DepsDLLs Include="$(DepsBinDir)shaderc_shared.dll" />
|
||||
<DepsDLLs Include="$(DepsBinDir)zlib1.dll" />
|
||||
<DepsDLLs Include="$(DepsBinDir)zstd.dll" />
|
||||
<DepsDLLs Include="$(DepsBinDir)kddockwidgets-qt62.dll" />
|
||||
<DepsDLLs Condition="$(Configuration.Contains(Debug))" Include="$(DepsBinDir)kddockwidgets-qt6d.dll" />
|
||||
<DepsDLLs Condition="!$(Configuration.Contains(Debug))" Include="$(DepsBinDir)kddockwidgets-qt6.dll" />
|
||||
<DepsDLLs Include="$(DepsBinDir)plutovg.dll" />
|
||||
<DepsDLLs Include="$(DepsBinDir)plutosvg.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "fmt/format.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/CocoaTools.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/CrashHandler.h"
|
||||
#include "common/FileSystem.h"
|
||||
@@ -56,7 +57,8 @@ namespace GSRunner
|
||||
static bool CreatePlatformWindow();
|
||||
static void DestroyPlatformWindow();
|
||||
static std::optional<WindowInfo> GetPlatformWindowInfo();
|
||||
static void PumpPlatformMessages();
|
||||
static void PumpPlatformMessages(bool forever = false);
|
||||
static void StopPlatformMessagePump();
|
||||
} // namespace GSRunner
|
||||
|
||||
static constexpr u32 WINDOW_WIDTH = 640;
|
||||
@@ -532,7 +534,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
{
|
||||
std::string str(argv[++i]);
|
||||
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "dump", true);
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "DumpGSData", true);
|
||||
|
||||
if (str.find("rt") != std::string::npos)
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveRT", true);
|
||||
@@ -764,7 +766,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s_settings_interface.GetBoolValue("EmuCore/GS", "dump") && !dumpdir.empty())
|
||||
if (s_settings_interface.GetBoolValue("EmuCore/GS", "DumpGSData") && !dumpdir.empty())
|
||||
{
|
||||
if (s_settings_interface.GetStringValue("EmuCore/GS", "HWDumpDirectory").empty())
|
||||
s_settings_interface.SetStringValue("EmuCore/GS", "HWDumpDirectory", dumpdir.c_str());
|
||||
@@ -809,6 +811,22 @@ void GSRunner::DumpStats()
|
||||
#define main real_main
|
||||
#endif
|
||||
|
||||
static void CPUThreadMain(VMBootParameters* params) {
|
||||
if (VMManager::Initialize(*params))
|
||||
{
|
||||
// run until end
|
||||
GSDumpReplayer::SetLoopCount(s_loop_count);
|
||||
VMManager::SetState(VMState::Running);
|
||||
while (VMManager::GetState() == VMState::Running)
|
||||
VMManager::Execute();
|
||||
VMManager::Shutdown(false);
|
||||
GSRunner::DumpStats();
|
||||
}
|
||||
|
||||
VMManager::Internal::CPUThreadShutdown();
|
||||
GSRunner::StopPlatformMessagePump();
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
CrashHandler::Install();
|
||||
@@ -837,16 +855,9 @@ int main(int argc, char* argv[])
|
||||
VMManager::ApplySettings();
|
||||
GSDumpReplayer::SetIsDumpRunner(true);
|
||||
|
||||
if (VMManager::Initialize(params))
|
||||
{
|
||||
// run until end
|
||||
GSDumpReplayer::SetLoopCount(s_loop_count);
|
||||
VMManager::SetState(VMState::Running);
|
||||
while (VMManager::GetState() == VMState::Running)
|
||||
VMManager::Execute();
|
||||
VMManager::Shutdown(false);
|
||||
GSRunner::DumpStats();
|
||||
}
|
||||
std::thread cputhread(CPUThreadMain, ¶ms);
|
||||
GSRunner::PumpPlatformMessages(/*forever=*/true);
|
||||
cputhread.join();
|
||||
|
||||
VMManager::Internal::CPUThreadShutdown();
|
||||
GSRunner::DestroyPlatformWindow();
|
||||
@@ -859,9 +870,6 @@ void Host::PumpMessagesOnCPUThread()
|
||||
// update GS thread copy of frame number
|
||||
MTGS::RunOnGSThread([frame_number = GSDumpReplayer::GetFrameNumber()]() { s_dump_frame_number = frame_number; });
|
||||
MTGS::RunOnGSThread([loop_number = GSDumpReplayer::GetLoopCount()]() { s_loop_number = loop_number; });
|
||||
|
||||
// process any window messages (but we shouldn't really have any)
|
||||
GSRunner::PumpPlatformMessages();
|
||||
}
|
||||
|
||||
s32 Host::Internal::GetTranslatedStringImpl(
|
||||
@@ -975,16 +983,32 @@ std::optional<WindowInfo> GSRunner::GetPlatformWindowInfo()
|
||||
return wi;
|
||||
}
|
||||
|
||||
void GSRunner::PumpPlatformMessages()
|
||||
static constexpr int SHUTDOWN_MSG = WM_APP + 0x100;
|
||||
static DWORD MainThreadID;
|
||||
|
||||
void GSRunner::PumpPlatformMessages(bool forever)
|
||||
{
|
||||
MSG msg;
|
||||
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
while (true)
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == SHUTDOWN_MSG)
|
||||
return;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
if (!forever)
|
||||
return;
|
||||
WaitMessage();
|
||||
}
|
||||
}
|
||||
|
||||
void GSRunner::StopPlatformMessagePump()
|
||||
{
|
||||
PostThreadMessageW(MainThreadID, SHUTDOWN_MSG, 0, 0);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||
@@ -1003,7 +1027,51 @@ int wmain(int argc, wchar_t** argv)
|
||||
u8_argptrs.push_back(u8_args[i].data());
|
||||
u8_argptrs.push_back(nullptr);
|
||||
|
||||
MainThreadID = GetCurrentThreadId();
|
||||
|
||||
return real_main(argc, u8_argptrs.data());
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
static void* s_window;
|
||||
static WindowInfo s_wi;
|
||||
|
||||
bool GSRunner::CreatePlatformWindow()
|
||||
{
|
||||
pxAssertRel(!s_window, "Tried to create window when there already was one!");
|
||||
s_window = CocoaTools::CreateWindow("PCSX2 GS Runner", WINDOW_WIDTH, WINDOW_HEIGHT);
|
||||
CocoaTools::GetWindowInfoFromWindow(&s_wi, s_window);
|
||||
PumpPlatformMessages();
|
||||
return s_window;
|
||||
}
|
||||
|
||||
void GSRunner::DestroyPlatformWindow()
|
||||
{
|
||||
if (s_window) {
|
||||
CocoaTools::DestroyWindow(s_window);
|
||||
s_window = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> GSRunner::GetPlatformWindowInfo()
|
||||
{
|
||||
WindowInfo wi;
|
||||
if (s_window)
|
||||
wi = s_wi;
|
||||
else
|
||||
wi.type = WindowInfo::Type::Surfaceless;
|
||||
return wi;
|
||||
}
|
||||
|
||||
void GSRunner::PumpPlatformMessages(bool forever)
|
||||
{
|
||||
CocoaTools::RunCocoaEventLoop(forever);
|
||||
}
|
||||
|
||||
void GSRunner::StopPlatformMessagePump()
|
||||
{
|
||||
CocoaTools::StopMainThreadEventLoop();
|
||||
}
|
||||
|
||||
#endif // _WIN32 / __APPLE__
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "CoverDownloadDialog.h"
|
||||
#include "QtUtils.h"
|
||||
|
||||
#include "pcsx2/GameList.h"
|
||||
|
||||
@@ -11,7 +12,7 @@ CoverDownloadDialog::CoverDownloadDialog(QWidget* parent /*= nullptr*/)
|
||||
: QDialog(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
m_ui.coverIcon->setPixmap(QIcon::fromTheme("artboard-2-line").pixmap(32));
|
||||
QtUtils::SetScalableIcon(m_ui.coverIcon, QIcon::fromTheme(QStringLiteral("artboard-2-line")), QSize(32, 32));
|
||||
updateEnabled();
|
||||
|
||||
connect(m_ui.start, &QPushButton::clicked, this, &CoverDownloadDialog::onStartClicked);
|
||||
|
||||
@@ -149,7 +149,9 @@ DockTabBar::DockTabBar(KDDockWidgets::Core::TabBar* controller, QWidget* parent)
|
||||
// that ends up taking ownerhsip of the style for the entire application!
|
||||
if (QProxyStyle* proxy_style = qobject_cast<QProxyStyle*>(style()))
|
||||
{
|
||||
proxy_style->baseStyle()->setParent(qApp);
|
||||
if (proxy_style->baseStyle() == qApp->style())
|
||||
proxy_style->baseStyle()->setParent(qApp);
|
||||
|
||||
proxy_style->setBaseStyle(QStyleFactory::create(qApp->style()->name()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <kddockwidgets/Config.h>
|
||||
#include <kddockwidgets/core/Group.h>
|
||||
#include <kddockwidgets/core/Platform.h>
|
||||
#include <kddockwidgets/core/indicators/SegmentedDropIndicatorOverlay.h>
|
||||
#include <kddockwidgets/qtwidgets/ViewFactory.h>
|
||||
|
||||
|
||||
@@ -311,7 +311,7 @@ void searchWorker(DebugInterface* cpu, std::vector<SearchResult>& searchResults,
|
||||
const auto readValue = readValueAtAddress<T>(cpu, addr);
|
||||
|
||||
const bool doesMatch = handleSearchComparison(searchComparison, addr, &searchResult, searchValue, readValue);
|
||||
if (!doesMatch)
|
||||
if (doesMatch)
|
||||
searchResult = MemorySearchView::SearchResult(addr, QVariant::fromValue(readValue), searchType);
|
||||
|
||||
return !doesMatch;
|
||||
|
||||
@@ -65,16 +65,17 @@ void ThreadView::openContextMenu(QPoint pos)
|
||||
|
||||
void ThreadView::onDoubleClick(const QModelIndex& index)
|
||||
{
|
||||
auto real_index = m_proxy_model->mapToSource(index);
|
||||
switch (index.column())
|
||||
{
|
||||
case ThreadModel::ThreadColumns::ENTRY:
|
||||
{
|
||||
goToInMemoryView(m_model->data(index, Qt::UserRole).toUInt(), true);
|
||||
goToInDisassembler(m_model->data(real_index, Qt::UserRole).toUInt(), true);
|
||||
break;
|
||||
}
|
||||
default: // Default to PC
|
||||
{
|
||||
QModelIndex pc_index = m_model->index(index.row(), ThreadModel::ThreadColumns::PC);
|
||||
QModelIndex pc_index = m_model->index(real_index.row(), ThreadModel::ThreadColumns::PC);
|
||||
goToInDisassembler(m_model->data(pc_index, Qt::UserRole).toUInt(), true);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -52,12 +52,12 @@ DisplayWidget::~DisplayWidget()
|
||||
|
||||
int DisplayWidget::scaledWindowWidth() const
|
||||
{
|
||||
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * QtUtils::GetDevicePixelRatioForWidget(this))), 1);
|
||||
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * devicePixelRatioF())), 1);
|
||||
}
|
||||
|
||||
int DisplayWidget::scaledWindowHeight() const
|
||||
{
|
||||
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * QtUtils::GetDevicePixelRatioForWidget(this))), 1);
|
||||
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * devicePixelRatioF())), 1);
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> DisplayWidget::getWindowInfo()
|
||||
@@ -268,7 +268,7 @@ bool DisplayWidget::event(QEvent* event)
|
||||
|
||||
if (!m_relative_mouse_enabled)
|
||||
{
|
||||
const qreal dpr = QtUtils::GetDevicePixelRatioForWidget(this);
|
||||
const qreal dpr = devicePixelRatioF();
|
||||
const QPoint mouse_pos = mouse_event->pos();
|
||||
|
||||
const float scaled_x = static_cast<float>(static_cast<qreal>(mouse_pos.x()) * dpr);
|
||||
@@ -349,13 +349,12 @@ bool DisplayWidget::event(QEvent* event)
|
||||
return true;
|
||||
}
|
||||
|
||||
// According to https://bugreports.qt.io/browse/QTBUG-95925 the recommended practice for handling DPI change is responding to paint events
|
||||
case QEvent::Paint:
|
||||
case QEvent::DevicePixelRatioChange:
|
||||
case QEvent::Resize:
|
||||
{
|
||||
QWidget::event(event);
|
||||
|
||||
const float dpr = QtUtils::GetDevicePixelRatioForWidget(this);
|
||||
const float dpr = devicePixelRatioF();
|
||||
const u32 scaled_width = static_cast<u32>(std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * dpr)), 1));
|
||||
const u32 scaled_height = static_cast<u32>(std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * dpr)), 1));
|
||||
|
||||
|
||||
@@ -25,17 +25,17 @@ static constexpr int COVER_ART_HEIGHT = 512;
|
||||
static constexpr int COVER_ART_SPACING = 32;
|
||||
static constexpr int MIN_COVER_CACHE_SIZE = 256;
|
||||
|
||||
static int DPRScale(int size, float dpr)
|
||||
static int DPRScale(int size, qreal dpr)
|
||||
{
|
||||
return static_cast<int>(static_cast<float>(size) * dpr);
|
||||
return static_cast<int>(static_cast<qreal>(size) * dpr);
|
||||
}
|
||||
|
||||
static int DPRUnscale(int size, float dpr)
|
||||
static int DPRUnscale(int size, qreal dpr)
|
||||
{
|
||||
return static_cast<int>(static_cast<float>(size) / dpr);
|
||||
return static_cast<int>(static_cast<qreal>(size) / dpr);
|
||||
}
|
||||
|
||||
static void resizeAndPadPixmap(QPixmap* pm, int expected_width, int expected_height, float dpr)
|
||||
static void resizeAndPadPixmap(QPixmap* pm, int expected_width, int expected_height, qreal dpr)
|
||||
{
|
||||
const int dpr_expected_width = DPRScale(expected_width, dpr);
|
||||
const int dpr_expected_height = DPRScale(expected_height, dpr);
|
||||
@@ -71,9 +71,8 @@ static void resizeAndPadPixmap(QPixmap* pm, int expected_width, int expected_hei
|
||||
}
|
||||
|
||||
static QPixmap createPlaceholderImage(const QPixmap& placeholder_pixmap, int width, int height, float scale,
|
||||
const std::string& title)
|
||||
qreal dpr, const std::string& title)
|
||||
{
|
||||
const float dpr = qApp->devicePixelRatio();
|
||||
QPixmap pm(placeholder_pixmap.copy());
|
||||
pm.setDevicePixelRatio(dpr);
|
||||
if (pm.isNull())
|
||||
@@ -113,9 +112,10 @@ const char* GameListModel::getColumnName(Column col)
|
||||
return s_column_names[static_cast<int>(col)];
|
||||
}
|
||||
|
||||
GameListModel::GameListModel(float cover_scale, bool show_cover_titles, QObject* parent /* = nullptr */)
|
||||
GameListModel::GameListModel(float cover_scale, bool show_cover_titles, qreal dpr, QObject* parent /* = nullptr */)
|
||||
: QAbstractTableModel(parent)
|
||||
, m_show_titles_for_covers(show_cover_titles)
|
||||
, m_dpr{dpr}
|
||||
{
|
||||
loadSettings();
|
||||
loadCommonImages();
|
||||
@@ -160,6 +160,13 @@ void GameListModel::updateCacheSize(int width, int height)
|
||||
m_cover_pixmap_cache.SetMaxCapacity(static_cast<int>(std::max(num_columns * num_rows, MIN_COVER_CACHE_SIZE)));
|
||||
}
|
||||
|
||||
void GameListModel::setDevicePixelRatio(qreal dpr)
|
||||
{
|
||||
m_dpr = dpr;
|
||||
loadCommonImages();
|
||||
refreshCovers();
|
||||
}
|
||||
|
||||
void GameListModel::loadOrGenerateCover(const GameList::Entry* ge)
|
||||
{
|
||||
// Why this counter: Every time we change the cover scale, we increment the counter variable. This way if the scale is changed
|
||||
@@ -173,12 +180,11 @@ void GameListModel::loadOrGenerateCover(const GameList::Entry* ge)
|
||||
const std::string cover_path(GameList::GetCoverImagePathForEntry(&entry));
|
||||
if (!cover_path.empty())
|
||||
{
|
||||
const float dpr = qApp->devicePixelRatio();
|
||||
image = QPixmap(QString::fromStdString(cover_path));
|
||||
if (!image.isNull())
|
||||
{
|
||||
image.setDevicePixelRatio(dpr);
|
||||
resizeAndPadPixmap(&image, getCoverArtWidth(), getCoverArtHeight(), dpr);
|
||||
image.setDevicePixelRatio(m_dpr);
|
||||
resizeAndPadPixmap(&image, getCoverArtWidth(), getCoverArtHeight(), m_dpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,7 +192,7 @@ void GameListModel::loadOrGenerateCover(const GameList::Entry* ge)
|
||||
const std::string& title = entry.GetTitle(m_prefer_english_titles);
|
||||
|
||||
if (image.isNull())
|
||||
image = createPlaceholderImage(m_placeholder_pixmap, getCoverArtWidth(), getCoverArtHeight(), m_cover_scale, title);
|
||||
image = createPlaceholderImage(m_placeholder_pixmap, getCoverArtWidth(), getCoverArtHeight(), m_cover_scale, m_dpr, title);
|
||||
|
||||
if (m_cover_scale_counter.load(std::memory_order_acquire) != counter)
|
||||
image = {};
|
||||
@@ -440,7 +446,7 @@ bool GameListModel::titlesLessThan(int left_row, int right_row) const
|
||||
const GameList::Entry* left = GameList::GetEntryByIndex(left_row);
|
||||
const GameList::Entry* right = GameList::GetEntryByIndex(right_row);
|
||||
return QtHost::LocaleSensitiveCompare(QString::fromStdString(left->GetTitleSort(m_prefer_english_titles)),
|
||||
QString::fromStdString(right->GetTitleSort(m_prefer_english_titles))) < 0;
|
||||
QString::fromStdString(right->GetTitleSort(m_prefer_english_titles))) < 0;
|
||||
}
|
||||
|
||||
bool GameListModel::lessThan(const QModelIndex& left_index, const QModelIndex& right_index, int column) const
|
||||
@@ -569,16 +575,16 @@ QIcon GameListModel::getIconForType(GameList::EntryType type)
|
||||
QIcon GameListModel::getIconForRegion(GameList::Region region)
|
||||
{
|
||||
return QIcon(
|
||||
QStringLiteral("%1/icons/flags/%2.svg").arg(QtHost::GetResourcesBasePath()).arg(GameList::RegionToString(region)));
|
||||
QStringLiteral("%1/icons/flags/%2.svg").arg(QtHost::GetResourcesBasePath()).arg(GameList::RegionToString(region, false)));
|
||||
}
|
||||
|
||||
void GameListModel::loadThemeSpecificImages()
|
||||
{
|
||||
for (u32 type = 0; type < static_cast<u32>(GameList::EntryType::Count); type++)
|
||||
m_type_pixmaps[type] = getIconForType(static_cast<GameList::EntryType>(type)).pixmap(QSize(24, 24));
|
||||
m_type_pixmaps[type] = getIconForType(static_cast<GameList::EntryType>(type)).pixmap(QSize(24, 24), m_dpr);
|
||||
|
||||
for (u32 i = 0; i < static_cast<u32>(GameList::Region::Count); i++)
|
||||
m_region_pixmaps[i] = getIconForRegion(static_cast<GameList::Region>(i)).pixmap(QSize(36, 26));
|
||||
m_region_pixmaps[i] = getIconForRegion(static_cast<GameList::Region>(i)).pixmap(QSize(36, 26), m_dpr);
|
||||
}
|
||||
|
||||
void GameListModel::loadCommonImages()
|
||||
@@ -587,7 +593,7 @@ void GameListModel::loadCommonImages()
|
||||
|
||||
const QString base_path(QtHost::GetResourcesBasePath());
|
||||
for (u32 i = 1; i < GameList::CompatibilityRatingCount; i++)
|
||||
m_compatibility_pixmaps[i].load(QStringLiteral("%1/icons/star-%2.svg").arg(base_path).arg(i - 1));
|
||||
m_compatibility_pixmaps[i] = QIcon((QStringLiteral("%1/icons/star-%2.svg").arg(base_path).arg(i - 1))).pixmap(QSize(88, 16), m_dpr);
|
||||
|
||||
m_placeholder_pixmap.load(QStringLiteral("%1/cover-placeholder.png").arg(base_path));
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
static QIcon getIconForType(GameList::EntryType type);
|
||||
static QIcon getIconForRegion(GameList::Region region);
|
||||
|
||||
GameListModel(float cover_scale, bool show_cover_titles, QObject* parent = nullptr);
|
||||
GameListModel(float cover_scale, bool show_cover_titles, qreal dpr, QObject* parent = nullptr);
|
||||
~GameListModel();
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
@@ -71,6 +71,8 @@ public:
|
||||
void refreshCovers();
|
||||
void updateCacheSize(int width, int height);
|
||||
|
||||
void setDevicePixelRatio(qreal dpr);
|
||||
|
||||
Q_SIGNALS:
|
||||
void coverScaleChanged();
|
||||
|
||||
@@ -94,6 +96,7 @@ private:
|
||||
std::array<QPixmap, static_cast<u32>(GameList::Region::Count)> m_region_pixmaps;
|
||||
QPixmap m_placeholder_pixmap;
|
||||
QPixmap m_loading_pixmap;
|
||||
qreal m_dpr;
|
||||
|
||||
std::array<QPixmap, static_cast<int>(GameList::CompatibilityRatingCount)> m_compatibility_pixmaps;
|
||||
mutable LRUCache<std::string, QPixmap> m_cover_pixmap_cache;
|
||||
|
||||
@@ -128,22 +128,25 @@ namespace
|
||||
const int pix_width = static_cast<int>(pix.width() / pix.devicePixelRatio());
|
||||
const int pix_height = static_cast<int>(pix.height() / pix.devicePixelRatio());
|
||||
|
||||
// Clip the pixmaps so they don't extend outside the column
|
||||
painter->save();
|
||||
painter->setClipRect(option.rect);
|
||||
|
||||
// Draw the icon, using code derived from QItemDelegate::drawDecoration()
|
||||
const bool enabled = option.state & QStyle::State_Enabled;
|
||||
const QPoint p = QPoint((r.width() - pix_width) / 2, (r.height() - pix_height) / 2);
|
||||
if (option.state & QStyle::State_Selected)
|
||||
{
|
||||
// See QItemDelegate::selectedPixmap()
|
||||
QString key = QString::fromStdString(fmt::format("{:016X}-{:d}", pix.cacheKey(), enabled));
|
||||
// See QItemDelegate::selectedPixmap()
|
||||
QColor color = option.palette.color(enabled ? QPalette::Normal : QPalette::Disabled, QPalette::Highlight);
|
||||
color.setAlphaF(0.3f);
|
||||
|
||||
QString key = QString::fromStdString(fmt::format("{:016X}-{:d}-{:08X}", pix.cacheKey(), enabled, color.rgba()));
|
||||
QPixmap pm;
|
||||
if (!QPixmapCache::find(key, &pm))
|
||||
{
|
||||
QImage img = pix.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
|
||||
QColor color = option.palette.color(enabled ? QPalette::Normal : QPalette::Disabled,
|
||||
QPalette::Highlight);
|
||||
color.setAlphaF(0.3f);
|
||||
|
||||
QPainter tinted_painter(&img);
|
||||
tinted_painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
|
||||
tinted_painter.fillRect(0, 0, img.width(), img.height(), color);
|
||||
@@ -159,6 +162,9 @@ namespace
|
||||
{
|
||||
painter->drawPixmap(r.topLeft() + p, pix);
|
||||
}
|
||||
|
||||
// Restore the old clip path.
|
||||
painter->restore();
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
@@ -174,22 +180,27 @@ void GameListWidget::initialize()
|
||||
{
|
||||
const float cover_scale = Host::GetBaseFloatSettingValue("UI", "GameListCoverArtScale", 0.45f);
|
||||
const bool show_cover_titles = Host::GetBaseBoolSettingValue("UI", "GameListShowCoverTitles", true);
|
||||
m_model = new GameListModel(cover_scale, show_cover_titles, this);
|
||||
m_model = new GameListModel(cover_scale, show_cover_titles, devicePixelRatioF(), this);
|
||||
m_model->updateCacheSize(width(), height());
|
||||
|
||||
m_sort_model = new GameListSortModel(m_model);
|
||||
m_sort_model->setSourceModel(m_model);
|
||||
|
||||
m_ui.setupUi(this);
|
||||
|
||||
for (u32 type = 0; type < static_cast<u32>(GameList::EntryType::Count); type++)
|
||||
{
|
||||
m_ui.filterType->addItem(GameListModel::getIconForType(static_cast<GameList::EntryType>(type)),
|
||||
qApp->translate("GameList", GameList::EntryTypeToDisplayString(static_cast<GameList::EntryType>(type))));
|
||||
if (type != static_cast<u32>(GameList::EntryType::Invalid))
|
||||
{
|
||||
m_ui.filterType->addItem(GameListModel::getIconForType(static_cast<GameList::EntryType>(type)),
|
||||
GameList::EntryTypeToString(static_cast<GameList::EntryType>(type), true));
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 region = 0; region < static_cast<u32>(GameList::Region::Count); region++)
|
||||
{
|
||||
m_ui.filterRegion->addItem(GameListModel::getIconForRegion(static_cast<GameList::Region>(region)),
|
||||
qApp->translate("GameList", GameList::RegionToString(static_cast<GameList::Region>(region))));
|
||||
GameList::RegionToString(static_cast<GameList::Region>(region), true));
|
||||
}
|
||||
|
||||
connect(m_ui.viewGameList, &QPushButton::clicked, this, &GameListWidget::showGameList);
|
||||
@@ -547,6 +558,18 @@ void GameListWidget::resizeEvent(QResizeEvent* event)
|
||||
m_model->updateCacheSize(width(), height());
|
||||
}
|
||||
|
||||
bool GameListWidget::event(QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::DevicePixelRatioChange)
|
||||
{
|
||||
m_model->setDevicePixelRatio(devicePixelRatioF());
|
||||
QWidget::event(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
void GameListWidget::resizeTableViewColumnsToFit()
|
||||
{
|
||||
QtUtils::ResizeColumnsForTableView(m_table_view, {
|
||||
|
||||
@@ -93,6 +93,7 @@ public Q_SLOTS:
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
private:
|
||||
void loadTableViewColumnVisibilitySettings();
|
||||
|
||||
@@ -103,9 +103,9 @@
|
||||
<addaction name="actionMemoryCardSettings"/>
|
||||
<addaction name="actionDEV9Settings"/>
|
||||
<addaction name="actionFolderSettings"/>
|
||||
<addaction name="actionAchievementSettings"/>
|
||||
<addaction name="actionControllerSettings"/>
|
||||
<addaction name="actionHotkeySettings"/>
|
||||
<addaction name="actionAchievementSettings"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionAddGameDirectory"/>
|
||||
<addaction name="actionScanForNewGames"/>
|
||||
|
||||
@@ -254,15 +254,6 @@ namespace QtUtils
|
||||
widget->resize(width, height);
|
||||
}
|
||||
|
||||
qreal GetDevicePixelRatioForWidget(const QWidget* widget)
|
||||
{
|
||||
const QScreen* screen_for_ratio = widget->screen();
|
||||
if (!screen_for_ratio)
|
||||
screen_for_ratio = QGuiApplication::primaryScreen();
|
||||
|
||||
return screen_for_ratio ? screen_for_ratio->devicePixelRatio() : static_cast<qreal>(1);
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> GetWindowInfoForWidget(QWidget* widget)
|
||||
{
|
||||
WindowInfo wi;
|
||||
@@ -303,7 +294,7 @@ namespace QtUtils
|
||||
}
|
||||
#endif
|
||||
|
||||
const qreal dpr = GetDevicePixelRatioForWidget(widget);
|
||||
const qreal dpr = widget->devicePixelRatioF();
|
||||
wi.surface_width = static_cast<u32>(static_cast<qreal>(widget->width()) * dpr);
|
||||
wi.surface_height = static_cast<u32>(static_cast<qreal>(widget->height()) * dpr);
|
||||
wi.surface_scale = static_cast<float>(dpr);
|
||||
@@ -374,4 +365,37 @@ namespace QtUtils
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class IconVariableDpiFilter : QObject
|
||||
{
|
||||
public:
|
||||
explicit IconVariableDpiFilter(QLabel* lbl, const QIcon& icon, const QSize& size, QObject* parent = nullptr)
|
||||
: QObject(parent)
|
||||
, m_lbl{lbl}
|
||||
, m_icn{icon}
|
||||
, m_size{size}
|
||||
{
|
||||
lbl->installEventFilter(this);
|
||||
m_lbl->setPixmap(m_icn.pixmap(m_size, m_lbl->devicePixelRatioF()));
|
||||
}
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject* object, QEvent* event) override
|
||||
{
|
||||
if (object == m_lbl && event->type() == QEvent::DevicePixelRatioChange)
|
||||
m_lbl->setPixmap(m_icn.pixmap(m_size, m_lbl->devicePixelRatioF()));
|
||||
// Don't block the event
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
QLabel* m_lbl;
|
||||
QIcon m_icn;
|
||||
QSize m_size;
|
||||
};
|
||||
|
||||
void SetScalableIcon(QLabel* lbl, const QIcon& icon, const QSize& size)
|
||||
{
|
||||
new IconVariableDpiFilter(lbl, icon, size, lbl);
|
||||
}
|
||||
} // namespace QtUtils
|
||||
|
||||
@@ -20,6 +20,7 @@ class QAction;
|
||||
class QComboBox;
|
||||
class QFileInfo;
|
||||
class QFrame;
|
||||
class QIcon;
|
||||
class QLabel;
|
||||
class QKeyEvent;
|
||||
class QSlider;
|
||||
@@ -82,9 +83,6 @@ namespace QtUtils
|
||||
/// Adjusts the fixed size for a window if it's not resizeable.
|
||||
void ResizePotentiallyFixedSizeWindow(QWidget* widget, int width, int height);
|
||||
|
||||
/// Returns the pixel ratio/scaling factor for a widget.
|
||||
qreal GetDevicePixelRatioForWidget(const QWidget* widget);
|
||||
|
||||
/// Returns the common window info structure for a Qt widget.
|
||||
std::optional<WindowInfo> GetWindowInfoForWidget(QWidget* widget);
|
||||
|
||||
@@ -102,4 +100,8 @@ namespace QtUtils
|
||||
bool IsLightTheme(const QPalette& palette);
|
||||
|
||||
bool IsCompositorManagerRunning();
|
||||
|
||||
/// Sets the scalable icon to a given label (svg icons, or icons with multiple size pixmaps)
|
||||
/// The icon will then be reloaded on DPR changes using an event filter
|
||||
void SetScalableIcon(QLabel* lbl, const QIcon& icon, const QSize& size);
|
||||
} // namespace QtUtils
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "AchievementLoginDialog.h"
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
|
||||
#include "pcsx2/Achievements.h"
|
||||
|
||||
@@ -15,7 +16,7 @@ AchievementLoginDialog::AchievementLoginDialog(QWidget* parent, Achievements::Lo
|
||||
, m_reason(reason)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
m_ui.loginIcon->setPixmap(QIcon::fromTheme("login-box-line").pixmap(32));
|
||||
QtUtils::SetScalableIcon(m_ui.loginIcon, QIcon::fromTheme(QStringLiteral("login-box-line")), QSize(32, 32));
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
// Adjust text if needed based on reason.
|
||||
@@ -116,7 +117,6 @@ void AchievementLoginDialog::processLoginResult(bool result, const QString& mess
|
||||
g_emu_thread->resetVM();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
done(0);
|
||||
|
||||
@@ -342,7 +342,7 @@ void AudioSettingsWidget::onExpansionSettingsClicked()
|
||||
QDialog dlg(QtUtils::GetRootWidget(this));
|
||||
Ui::AudioExpansionSettingsDialog dlgui;
|
||||
dlgui.setupUi(&dlg);
|
||||
dlgui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("volume-up-line")).pixmap(32, 32));
|
||||
QtUtils::SetScalableIcon(dlgui.icon, QIcon::fromTheme(QStringLiteral("volume-up-line")), QSize(32, 32));
|
||||
|
||||
SettingsInterface* sif = m_dialog->getSettingsInterface();
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.blockSize, "SPU2/Output", "ExpandBlockSize",
|
||||
@@ -431,7 +431,7 @@ void AudioSettingsWidget::onStretchSettingsClicked()
|
||||
QDialog dlg(QtUtils::GetRootWidget(this));
|
||||
Ui::AudioStretchSettingsDialog dlgui;
|
||||
dlgui.setupUi(&dlg);
|
||||
dlgui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("volume-up-line")).pixmap(32, 32));
|
||||
QtUtils::SetScalableIcon(dlgui.icon, QIcon::fromTheme(QStringLiteral("volume-up-line")), QSize(32, 32));
|
||||
|
||||
SettingsInterface* sif = m_dialog->getSettingsInterface();
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.sequenceLength, "SPU2/Output", "StretchSequenceLengthMS",
|
||||
|
||||
@@ -170,7 +170,7 @@ ControllerMouseSettingsDialog::ControllerMouseSettingsDialog(QWidget* parent, Co
|
||||
|
||||
SettingsInterface* sif = dialog->getProfileSettingsInterface();
|
||||
|
||||
m_ui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("mouse-line")).pixmap(32, 32));
|
||||
QtUtils::SetScalableIcon(m_ui.icon, QIcon::fromTheme(QStringLiteral("mouse-line")), QSize(32, 32));
|
||||
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileFloat(sif, m_ui.pointerXSpeedSlider, "Pad", "PointerXSpeed", 40.0f);
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileFloat(sif, m_ui.pointerYSpeedSlider, "Pad", "PointerYSpeed", 40.0f);
|
||||
@@ -202,11 +202,10 @@ ControllerMappingSettingsDialog::ControllerMappingSettingsDialog(ControllerSetti
|
||||
|
||||
SettingsInterface* sif = parent->getProfileSettingsInterface();
|
||||
|
||||
m_ui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("settings-3-line")).pixmap(32, 32));
|
||||
QtUtils::SetScalableIcon(m_ui.icon, QIcon::fromTheme(QStringLiteral("settings-3-line")), QSize(32, 32));
|
||||
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.ignoreInversion, "InputSources", "IgnoreInversion", false);
|
||||
|
||||
connect(m_ui.buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &QDialog::accept);
|
||||
}
|
||||
|
||||
ControllerMappingSettingsDialog::~ControllerMappingSettingsDialog() = default;
|
||||
|
||||
@@ -33,7 +33,7 @@ GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsWindo
|
||||
for (int i = 0; i < m_ui.region->count(); i++)
|
||||
{
|
||||
m_ui.region->setItemIcon(i,
|
||||
QIcon(QStringLiteral("%1/icons/flags/%2.svg").arg(base_path).arg(GameList::RegionToString(static_cast<GameList::Region>(i)))));
|
||||
QIcon(QStringLiteral("%1/icons/flags/%2.svg").arg(base_path).arg(GameList::RegionToString(static_cast<GameList::Region>(i), false))));
|
||||
}
|
||||
|
||||
m_entry_path = entry->path;
|
||||
@@ -73,16 +73,17 @@ void GameSummaryWidget::populateDetails(const GameList::Entry* entry)
|
||||
m_ui.type->setCurrentIndex(static_cast<int>(entry->type));
|
||||
m_ui.region->setCurrentIndex(static_cast<int>(entry->region));
|
||||
//: First arg is a GameList compat; second is a string with space followed by star rating OR empty if Unknown compat
|
||||
m_ui.compatibility->setText(tr("%0%1")
|
||||
.arg(GameList::EntryCompatibilityRatingToString(entry->compatibility_rating))
|
||||
.arg([entry]() {
|
||||
if (entry->compatibility_rating == GameList::CompatibilityRating::Unknown)
|
||||
return QStringLiteral("");
|
||||
m_ui.compatibility->setText(
|
||||
tr("%0%1")
|
||||
.arg(GameList::EntryCompatibilityRatingToString(entry->compatibility_rating, true))
|
||||
.arg([entry]() {
|
||||
if (entry->compatibility_rating == GameList::CompatibilityRating::Unknown)
|
||||
return QStringLiteral("");
|
||||
|
||||
const qsizetype compatibility_value = static_cast<qsizetype>(entry->compatibility_rating);
|
||||
//: First arg is filled-in stars for game compatibility; second is empty stars; should be swapped for RTL languages
|
||||
return tr(" %0%1").arg(QStringLiteral("★").repeated(compatibility_value - 1)).arg(QStringLiteral("☆").repeated(6 - compatibility_value));
|
||||
}()));
|
||||
const qsizetype compatibility_value = static_cast<qsizetype>(entry->compatibility_rating);
|
||||
//: First arg is filled-in stars for game compatibility; second is empty stars; should be swapped for RTL languages
|
||||
return tr(" %0%1").arg(QStringLiteral("★").repeated(compatibility_value - 1)).arg(QStringLiteral("☆").repeated(6 - compatibility_value));
|
||||
}()));
|
||||
|
||||
int row = 0;
|
||||
m_ui.detailsFormLayout->getWidgetPosition(m_ui.titleSort, &row, nullptr);
|
||||
@@ -156,7 +157,7 @@ void GameSummaryWidget::onDiscPathChanged(const QString& value)
|
||||
|
||||
// force rescan of elf to update the serial
|
||||
g_main_window->rescanFile(m_entry_path);
|
||||
|
||||
|
||||
auto lock = GameList::GetLock();
|
||||
const GameList::Entry* entry = GameList::GetEntryForPath(m_entry_path.c_str());
|
||||
if (entry)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
#include "Settings/MemoryCardCreateDialog.h"
|
||||
#include "QtUtils.h"
|
||||
|
||||
#include "pcsx2/SIO/Memcard/MemoryCardFile.h"
|
||||
|
||||
@@ -16,7 +17,7 @@ MemoryCardCreateDialog::MemoryCardCreateDialog(QWidget* parent /* = nullptr */)
|
||||
: QDialog(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
m_ui.icon->setPixmap(QIcon::fromTheme("memcard-line").pixmap(m_ui.icon->width()));
|
||||
QtUtils::SetScalableIcon(m_ui.icon, QIcon::fromTheme(QStringLiteral("memcard-line")), QSize(m_ui.icon->width(), m_ui.icon->width()));
|
||||
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtGui/QPalette>
|
||||
#include <QtGui/QPixmapCache>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QStyle>
|
||||
#include <QtWidgets/QStyleFactory>
|
||||
@@ -43,6 +44,12 @@ void QtHost::UpdateApplicationTheme()
|
||||
|
||||
SetStyleFromSettings();
|
||||
SetIconThemeFromStyle();
|
||||
|
||||
// Qt generates tinted versions of icons and stores them in QPixmapCache
|
||||
// The key used does not seem to include the theme (or tint colour).
|
||||
// This can cause icons tinted for wrong theme to be used for selected/disabled.
|
||||
// As a workaround, reset the pixmap cache to clear icons tinted for the old theme.
|
||||
QPixmapCache::clear();
|
||||
}
|
||||
|
||||
bool QtHost::IsDarkApplicationTheme()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1455,7 +1455,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode, bool transition_t
|
||||
}
|
||||
isSeeking = true;
|
||||
}
|
||||
else if(!drive_speed_change_cycles)
|
||||
else if (!drive_speed_change_cycles)
|
||||
{
|
||||
CDVD_LOG("CdSeek Begin > Contiguous block without seek - delta=%d sectors", delta);
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ bool IOCtlSrc::ReadDVDInfo()
|
||||
{
|
||||
Console.Warning("IOCTL_DVD_READ_STRUCTURE not supported");
|
||||
}
|
||||
else if(GetLastError() != ERROR_UNRECOGNIZED_MEDIA) // ERROR_UNRECOGNIZED_MEDIA means probably a CD or no disc
|
||||
else if (GetLastError() != ERROR_UNRECOGNIZED_MEDIA) // ERROR_UNRECOGNIZED_MEDIA means probably a CD or no disc
|
||||
{
|
||||
Console.Warning("IOCTL Unknown Error %d", GetLastError());
|
||||
}
|
||||
|
||||
@@ -1237,9 +1237,16 @@ fixup_file_properties(PCSX2)
|
||||
force_include_last(PCSX2_FLAGS "/(usr|local)/include/?$")
|
||||
|
||||
if (APPLE)
|
||||
find_library(APPKIT_LIBRARY AppKit)
|
||||
find_library(IOKIT_LIBRARY IOKit)
|
||||
find_library(METAL_LIBRARY Metal)
|
||||
find_library(QUARTZCORE_LIBRARY QuartzCore)
|
||||
target_link_libraries(PCSX2_FLAGS INTERFACE ${METAL_LIBRARY} ${QUARTZCORE_LIBRARY})
|
||||
target_link_libraries(PCSX2_FLAGS INTERFACE
|
||||
${APPKIT_LIBRARY}
|
||||
${IOKIT_LIBRARY}
|
||||
${METAL_LIBRARY}
|
||||
${QUARTZCORE_LIBRARY}
|
||||
)
|
||||
endif()
|
||||
|
||||
set_property(GLOBAL PROPERTY PCSX2_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
@@ -1286,7 +1293,11 @@ function(setup_main_executable target)
|
||||
|
||||
# Copy dependency libraries.
|
||||
set(DEPS_BINDIR "${CMAKE_SOURCE_DIR}/deps/bin")
|
||||
set(DEPS_TO_COPY freetype.dll harfbuzz.dll jpeg62.dll libpng16.dll libsharpyuv.dll libwebp.dll lz4.dll SDL3.dll shaderc_shared.dll zlib1.dll zstd.dll kddockwidgets-qt62.dll plutovg.dll plutosvg.dll)
|
||||
set(DEPS_TO_COPY freetype.dll harfbuzz.dll jpeg62.dll libpng16.dll libsharpyuv.dll libwebp.dll lz4.dll SDL3.dll shaderc_shared.dll zlib1.dll zstd.dll plutovg.dll plutosvg.dll)
|
||||
set(DEPS_TO_COPY
|
||||
$<IF:$<CONFIG:Debug>,kddockwidgets-qt6d.dll,kddockwidgets-qt6.dll>
|
||||
${DEPS_TO_COPY}
|
||||
)
|
||||
foreach(DEP_TO_COPY ${DEPS_TO_COPY})
|
||||
install(FILES "${DEPS_BINDIR}/${DEP_TO_COPY}" DESTINATION "${CMAKE_SOURCE_DIR}/bin")
|
||||
endforeach()
|
||||
|
||||
@@ -33,7 +33,7 @@ struct BreakPoint
|
||||
bool temporary = false;
|
||||
bool stepping = false;
|
||||
|
||||
bool hasCond;
|
||||
bool hasCond = false;
|
||||
BreakPointCond cond;
|
||||
BreakPointCpu cpu;
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
|
||||
cpuClearInt( 10 );
|
||||
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
|
||||
}
|
||||
else if(channel == 2)
|
||||
else if (channel == 2)
|
||||
{
|
||||
cpuClearInt( 11 );
|
||||
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
|
||||
@@ -274,7 +274,7 @@ static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
|
||||
{
|
||||
func();
|
||||
}
|
||||
else if(reg.chcr.STR)
|
||||
else if (reg.chcr.STR)
|
||||
{
|
||||
//DevCon.Warning(L"32bit %s DMA Start while DMAC Disabled\n", ChcrName(mem));
|
||||
QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted
|
||||
|
||||
@@ -20,7 +20,11 @@ There are a number of ways to help the project, whether it be bug reporting, gam
|
||||
|
||||
* Want to make changes to emulator code? [Check out the issue tracker](https://github.com/PCSX2/pcsx2/issues), or [fork the PCSX2 repository and work on your own ideas](https://github.com/PCSX2/pcsx2).
|
||||
* Want to patch games? [Check out the cheats and patches forum thread for inspiration](https://forums.pcsx2.net/Thread-Post-your-PCSX2-cheats-patches-here). There are other threads to find as well, [such as those dedicated to 60 FPS patches](https://forums.pcsx2.net/Thread-60-fps-codes) or [widescreen patches](https://forums.pcsx2.net/Thread-PCSX2-Widescreen-Game-Patches).
|
||||
<<<<<<< HEAD
|
||||
* Want to report bugs you have discovered in your games? Head over to [the Bug Reporting section of the PCSX2 forums](https://forums.pcsx2.net/Forum-Bug-reporting), to [the PCSX2 Discord](https://pcsx2.net/discord), or to [the GitHub issues section](https://github.com/PCSX2/pcsx2/issues).
|
||||
=======
|
||||
* Want to report bugs you have discovered in your games? [Head over to the Bug Reporting section of the PCSX2 forums](https://forums.pcsx2.net/Forum-Bug-reporting). Also check out our [Issue reporting guide](https://pcsx2.net/docs/troubleshooting/identify) for info on how to better report to us issues.
|
||||
>>>>>>> 091a4ee5a (docs: update in order to redirect from the GH wiki to our website)
|
||||
* Want to update us on the compatibility of your games? [Take a look at the Public Compatibility List on the PCSX2 forums](https://forums.pcsx2.net/Forum-Public-compatibility-list)
|
||||
* Want to improve the PCSX2 wiki? [Here is how to contribute](https://wiki.pcsx2.net/How_to_contribute)
|
||||
|
||||
@@ -120,9 +124,7 @@ If you are using a disc:
|
||||
Fast Boot, enabled by default, will directly mount and launch the game without first launching the PS2 BIOS. You may disable this in Settings > BIOS > Fast Boot if you wish to see the BIOS startup animation or if Fast Boot is causing an issue.
|
||||
|
||||
### Question 18: How do I build the PCSX2 source code?
|
||||
* [Windows build guide](https://github.com/PCSX2/pcsx2/wiki/12-Building-on-Windows)
|
||||
* [Linux build guide](https://github.com/PCSX2/pcsx2/wiki/10-Building-on-Linux)
|
||||
* [macOS build guide](https://github.com/PCSX2/pcsx2/wiki/11-Building-on-MacOS)
|
||||
Have a nice [building guide](https://pcsx2.net/docs/advanced/building) :) .
|
||||
|
||||
### Question 19: When will the next version be released?
|
||||
It will be released when it is ready. Please don't waste your time and ours asking when.
|
||||
|
||||
@@ -249,7 +249,6 @@ void CTC1() {
|
||||
|
||||
void CVT_S() {
|
||||
_FdValf_ = (float)_FsValSl_;
|
||||
_FdValf_ = fpuDouble( _FdValUl_ );
|
||||
}
|
||||
|
||||
void CVT_W() {
|
||||
|
||||
@@ -339,7 +339,7 @@ void GSClut::Read(const GIFRegTEX0& TEX0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(TEX0.CPSM == PSMCT16 || TEX0.CPSM == PSMCT16S)
|
||||
else if (TEX0.CPSM == PSMCT16 || TEX0.CPSM == PSMCT16S)
|
||||
{
|
||||
switch(TEX0.PSM)
|
||||
{
|
||||
@@ -462,7 +462,8 @@ void GSClut::GetAlphaMinMax32(int& amin_out, int& amax_out)
|
||||
{
|
||||
// call only after Read32
|
||||
|
||||
pxAssert(!m_read.dirty);
|
||||
if (m_read.dirty)
|
||||
GL_INS("GSClut: GetAlphaMinMax32 m_read.dirty");
|
||||
|
||||
if (m_read.adirty)
|
||||
{
|
||||
|
||||
@@ -70,6 +70,7 @@ GSLocalMemory::GSLocalMemory()
|
||||
psm.wfa = &GSLocalMemory::WritePixel32;
|
||||
psm.bpp = psm.trbpp = 32;
|
||||
psm.pal = 0;
|
||||
psm.cs = GSVector2i(8, 2);
|
||||
psm.bs = GSVector2i(8, 8);
|
||||
psm.pgs = GSVector2i(64, 32);
|
||||
psm.msk = 0xff;
|
||||
@@ -197,6 +198,11 @@ GSLocalMemory::GSLocalMemory()
|
||||
m_psm[PSMCT16].fmt = m_psm[PSMZ16].fmt = PSM_FMT_16;
|
||||
m_psm[PSMCT16S].fmt = m_psm[PSMZ16S].fmt = PSM_FMT_16;
|
||||
|
||||
m_psm[PSGPU24].cs = GSVector2i(16, 2);
|
||||
m_psm[PSMCT16].cs = m_psm[PSMCT16S].bs = GSVector2i(16, 2);
|
||||
m_psm[PSMT8].cs = GSVector2i(16, 4);
|
||||
m_psm[PSMT4].cs = GSVector2i(32, 4);
|
||||
m_psm[PSMZ16].cs = m_psm[PSMZ16S].bs = GSVector2i(16, 2);
|
||||
|
||||
m_psm[PSGPU24].bs = GSVector2i(16, 8);
|
||||
m_psm[PSMCT16].bs = m_psm[PSMCT16S].bs = GSVector2i(16, 8);
|
||||
@@ -440,6 +446,13 @@ std::vector<GSVector2i>* GSLocalMemory::GetPage2TileMap(const GIFRegTEX0& TEX0)
|
||||
return p2t;
|
||||
}
|
||||
|
||||
u32 GSLocalMemory::IsPageAlignedMasked(u32 psm, const GSVector4i& rc)
|
||||
{
|
||||
const psm_t& psm_s = m_psm[psm];
|
||||
const GSVector4i pgmsk = GSVector4i(psm_s.pgs).xyxy() - GSVector4i(1);
|
||||
return ((rc & pgmsk) == GSVector4i::zero()).mask();
|
||||
}
|
||||
|
||||
bool GSLocalMemory::IsPageAligned(u32 psm, const GSVector4i& rc)
|
||||
{
|
||||
const psm_t& psm_s = m_psm[psm];
|
||||
|
||||
@@ -460,7 +460,7 @@ public:
|
||||
readTexture rtx, rtxP;
|
||||
readTextureBlock rtxb, rtxbP;
|
||||
u16 bpp, trbpp, pal, fmt;
|
||||
GSVector2i bs, pgs;
|
||||
GSVector2i cs, bs, pgs;
|
||||
u8 msk, depth;
|
||||
u32 fmsk;
|
||||
};
|
||||
@@ -524,6 +524,7 @@ public:
|
||||
GSPixelOffset4* GetPixelOffset4(const GIFRegFRAME& FRAME, const GIFRegZBUF& ZBUF);
|
||||
std::vector<GSVector2i>* GetPage2TileMap(const GIFRegTEX0& TEX0);
|
||||
static bool HasOverlap(u32 src_bp, u32 src_bw, u32 src_psm, GSVector4i src_rect, u32 dst_bp, u32 dst_bw, u32 dst_psm, GSVector4i dst_rect);
|
||||
static u32 IsPageAlignedMasked(u32 psm, const GSVector4i& rc);
|
||||
static bool IsPageAligned(u32 psm, const GSVector4i& rc);
|
||||
static u32 GetStartBlockAddress(u32 bp, u32 bw, u32 psm, GSVector4i rect);
|
||||
static u32 GetEndBlockAddress(u32 bp, u32 bw, u32 psm, GSVector4i rect);
|
||||
|
||||
@@ -32,7 +32,7 @@ static __fi bool IsFirstProvokingVertex()
|
||||
return (GSIsHardwareRenderer() && !g_gs_device->Features().provoking_vertex_last);
|
||||
}
|
||||
|
||||
constexpr int GSState::GetSaveStateSize()
|
||||
constexpr int GSState::GetSaveStateSize(int version)
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
@@ -78,6 +78,19 @@ constexpr int GSState::GetSaveStateSize()
|
||||
|
||||
size += sizeof(m_tr.x);
|
||||
size += sizeof(m_tr.y);
|
||||
if (version >= 9)
|
||||
{
|
||||
size += sizeof(m_tr.w);
|
||||
size += sizeof(m_tr.h);
|
||||
size += sizeof(m_tr.m_blit);
|
||||
size += sizeof(m_tr.m_pos);
|
||||
size += sizeof(m_tr.m_reg);
|
||||
size += sizeof(m_tr.rect);
|
||||
size += sizeof(m_tr.total);
|
||||
size += sizeof(m_tr.start);
|
||||
size += sizeof(m_tr.end);
|
||||
size += sizeof(m_tr.write);
|
||||
}
|
||||
size += GSLocalMemory::m_vmsize;
|
||||
size += (sizeof(GIFPath::tag) + sizeof(GIFPath::reg)) * 4 /* std::size(GSState::m_path) */; // std::size won't work without an instance.
|
||||
size += sizeof(m_q);
|
||||
@@ -1445,10 +1458,10 @@ void GSState::GIFRegHandlerTRXDIR(const GIFReg* RESTRICT r)
|
||||
switch (m_env.TRXDIR.XDIR)
|
||||
{
|
||||
case 0: // host -> local
|
||||
m_tr.Init(m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, m_env.BITBLTBUF, true);
|
||||
m_tr.Init(m_env.TRXPOS, m_env.TRXREG, m_env.BITBLTBUF, true);
|
||||
break;
|
||||
case 1: // local -> host
|
||||
m_tr.Init(m_env.TRXPOS.SSAX, m_env.TRXPOS.SSAY, m_env.BITBLTBUF, false);
|
||||
m_tr.Init(m_env.TRXPOS, m_env.TRXREG, m_env.BITBLTBUF, false);
|
||||
break;
|
||||
case 2: // local -> local
|
||||
CheckWriteOverlap(true, true);
|
||||
@@ -1549,16 +1562,13 @@ void GSState::FlushWrite()
|
||||
|
||||
GSVector4i r;
|
||||
|
||||
r.left = m_env.TRXPOS.DSAX;
|
||||
r.top = m_env.TRXPOS.DSAY;
|
||||
r.right = r.left + m_env.TRXREG.RRW;
|
||||
r.bottom = r.top + m_env.TRXREG.RRH;
|
||||
r = m_tr.rect;
|
||||
|
||||
InvalidateVideoMem(m_env.BITBLTBUF, r);
|
||||
|
||||
const GSLocalMemory::writeImage wi = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].wi;
|
||||
|
||||
wi(m_mem, m_tr.x, m_tr.y, &m_tr.buff[m_tr.start], len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG);
|
||||
wi(m_mem, m_tr.x, m_tr.y, &m_tr.buff[m_tr.start], len, m_tr.m_blit, m_tr.m_pos, m_tr.m_reg);
|
||||
|
||||
m_tr.start += len;
|
||||
|
||||
@@ -1931,12 +1941,9 @@ void GSState::Write(const u8* mem, int len)
|
||||
if (m_env.TRXDIR.XDIR == 3)
|
||||
return;
|
||||
|
||||
const int w = m_env.TRXREG.RRW;
|
||||
const int h = m_env.TRXREG.RRH;
|
||||
|
||||
CheckWriteOverlap(true, false);
|
||||
|
||||
if (!m_tr.Update(w, h, GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].trbpp, len))
|
||||
if (!m_tr.Update(m_tr.w, m_tr.h, GSLocalMemory::m_psm[m_tr.m_blit.DPSM].trbpp, len))
|
||||
{
|
||||
m_env.TRXDIR.XDIR = 3;
|
||||
return;
|
||||
@@ -1949,10 +1956,7 @@ void GSState::Write(const u8* mem, int len)
|
||||
{
|
||||
GSVector4i r;
|
||||
|
||||
r.left = m_env.TRXPOS.DSAX;
|
||||
r.top = m_env.TRXPOS.DSAY;
|
||||
r.right = r.left + m_env.TRXREG.RRW;
|
||||
r.bottom = r.top + m_env.TRXREG.RRH;
|
||||
r = m_tr.rect;
|
||||
|
||||
s_last_transfer_draw_n = s_n;
|
||||
// Store the transfer for preloading new RT's.
|
||||
@@ -1974,15 +1978,15 @@ void GSState::Write(const u8* mem, int len)
|
||||
|
||||
GL_CACHE("Write! %u ... => 0x%x W:%d F:%s (DIR %d%d), dPos(%d %d) size(%d %d) draw %d", s_transfer_n,
|
||||
blit.DBP, blit.DBW, psm_str(blit.DPSM),
|
||||
m_env.TRXPOS.DIRX, m_env.TRXPOS.DIRY,
|
||||
m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, w, h, s_n);
|
||||
m_tr.m_pos.DIRX, m_tr.m_pos.DIRY,
|
||||
m_tr.x, m_tr.y, m_tr.w, m_tr.h, s_n);
|
||||
|
||||
if (len >= m_tr.total)
|
||||
{
|
||||
// received all data in one piece, no need to buffer it
|
||||
InvalidateVideoMem(blit, r);
|
||||
|
||||
psm.wi(m_mem, m_tr.x, m_tr.y, mem, m_tr.total, blit, m_env.TRXPOS, m_env.TRXREG);
|
||||
psm.wi(m_mem, m_tr.x, m_tr.y, mem, m_tr.total, blit, m_tr.m_pos, m_tr.m_reg);
|
||||
|
||||
m_tr.start = m_tr.end = m_tr.total;
|
||||
|
||||
@@ -2260,7 +2264,7 @@ void GSState::Move()
|
||||
vm[doff] = (vm[doff] & 0xff000000) | (vm[soff] & 0x00ffffff);
|
||||
});
|
||||
}
|
||||
else // if(spsm.trbpp == 16)
|
||||
else // if (spsm.trbpp == 16)
|
||||
{
|
||||
u16* vm = m_mem.vm16();
|
||||
copy(dpo.assertSizesMatch(GSLocalMemory::swizzle16), spo.assertSizesMatch(GSLocalMemory::swizzle16), [vm](u32 doff, u32 soff)
|
||||
@@ -2334,7 +2338,7 @@ void GSState::ReadLocalMemoryUnsync(u8* mem, int qwc, GIFRegBITBLTBUF BITBLTBUF,
|
||||
GSTransferBuffer tb;
|
||||
|
||||
if(m_tr.end >= m_tr.total || m_tr.write == true)
|
||||
tb.Init(TRXPOS.SSAX, TRXPOS.SSAY, BITBLTBUF, false);
|
||||
tb.Init(TRXPOS, TRXREG, BITBLTBUF, false);
|
||||
|
||||
int len = qwc * 16;
|
||||
if (!tb.Update(w, h, bpp, len))
|
||||
@@ -2578,13 +2582,14 @@ static void ReadState(T* dst, u8*& src, size_t len = sizeof(T))
|
||||
|
||||
int GSState::Freeze(freezeData* fd, bool sizeonly)
|
||||
{
|
||||
const u32 version = STATE_VERSION;
|
||||
if (sizeonly)
|
||||
{
|
||||
fd->size = GetSaveStateSize();
|
||||
fd->size = GetSaveStateSize(version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!fd->data || fd->size < GetSaveStateSize())
|
||||
if (!fd->data || fd->size < GetSaveStateSize(version))
|
||||
return -1;
|
||||
|
||||
Flush(GSFlushReason::SAVESTATE);
|
||||
@@ -2593,7 +2598,6 @@ int GSState::Freeze(freezeData* fd, bool sizeonly)
|
||||
ReadbackTextureCache();
|
||||
|
||||
u8* data = fd->data;
|
||||
const u32 version = STATE_VERSION;
|
||||
|
||||
WriteState(data, &version);
|
||||
WriteState(data, &m_env.PRIM);
|
||||
@@ -2636,6 +2640,18 @@ int GSState::Freeze(freezeData* fd, bool sizeonly)
|
||||
data += sizeof(GIFReg); // obsolite
|
||||
WriteState(data, &m_tr.x);
|
||||
WriteState(data, &m_tr.y);
|
||||
// Version 9 up.
|
||||
WriteState(data, &m_tr.w);
|
||||
WriteState(data, &m_tr.h);
|
||||
WriteState(data, &m_tr.m_blit);
|
||||
WriteState(data, &m_tr.m_pos);
|
||||
WriteState(data, &m_tr.m_reg);
|
||||
WriteState(data, &m_tr.rect);
|
||||
WriteState(data, &m_tr.total);
|
||||
WriteState(data, &m_tr.start);
|
||||
WriteState(data, &m_tr.end);
|
||||
WriteState(data, &m_tr.write);
|
||||
// End of version 9 changes.
|
||||
WriteState(data, m_mem.m_vm8, m_mem.m_vmsize);
|
||||
|
||||
for (GIFPath& path : m_path)
|
||||
@@ -2663,15 +2679,15 @@ int GSState::Defrost(const freezeData* fd)
|
||||
if (!fd || !fd->data || fd->size == 0)
|
||||
return -1;
|
||||
|
||||
if (fd->size < GetSaveStateSize())
|
||||
return -1;
|
||||
|
||||
u8* data = fd->data;
|
||||
|
||||
u32 version;
|
||||
|
||||
ReadState(&version, data);
|
||||
|
||||
if (fd->size < GetSaveStateSize(version))
|
||||
return -1;
|
||||
|
||||
if (version > STATE_VERSION)
|
||||
{
|
||||
Console.Error("GS: Savestate version is incompatible. Load aborted.");
|
||||
@@ -2701,12 +2717,6 @@ int GSState::Defrost(const freezeData* fd)
|
||||
ReadState(&m_env.TRXPOS, data);
|
||||
ReadState(&m_env.TRXREG, data);
|
||||
ReadState(&m_env.TRXREG, data); // obsolete
|
||||
// Technically this value ought to be saved like m_tr.x/y (break
|
||||
// compatibility) but so far only a single game (Motocross Mania) really
|
||||
// depends on this value (i.e != BITBLTBUF) Savestates are likely done at
|
||||
// VSYNC, so not in the middle of a texture transfer, therefore register
|
||||
// will be set again properly
|
||||
m_tr.m_blit = m_env.BITBLTBUF;
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
@@ -2742,9 +2752,36 @@ int GSState::Defrost(const freezeData* fd)
|
||||
data += sizeof(GIFReg); // obsolite
|
||||
ReadState(&m_tr.x, data);
|
||||
ReadState(&m_tr.y, data);
|
||||
ReadState(m_mem.m_vm8, data, m_mem.m_vmsize);
|
||||
|
||||
m_tr.total = 0; // TODO: restore transfer state
|
||||
if (version >= 9)
|
||||
{
|
||||
ReadState(&m_tr.w, data);
|
||||
ReadState(&m_tr.h, data);
|
||||
ReadState(&m_tr.m_blit, data);
|
||||
ReadState(&m_tr.m_pos, data);
|
||||
ReadState(&m_tr.m_reg, data);
|
||||
ReadState(&m_tr.rect, data);
|
||||
ReadState(&m_tr.total, data);
|
||||
ReadState(&m_tr.start, data);
|
||||
ReadState(&m_tr.end, data);
|
||||
ReadState(&m_tr.write, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tr.w = m_env.TRXREG.RRW;
|
||||
m_tr.h = m_env.TRXREG.RRH;
|
||||
m_tr.m_blit = m_env.BITBLTBUF;
|
||||
m_tr.m_pos = m_env.TRXPOS;
|
||||
m_tr.m_reg = m_env.TRXREG;
|
||||
// Assume the last transfer was a write (but nuke it).
|
||||
m_tr.rect = GSVector4i(m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, m_env.TRXPOS.DSAX + m_tr.w, m_env.TRXPOS.DSAY + m_tr.h);
|
||||
m_tr.total = 0;
|
||||
m_tr.start = 0;
|
||||
m_tr.end = 0;
|
||||
m_tr.write = true;
|
||||
}
|
||||
|
||||
ReadState(m_mem.m_vm8, data, m_mem.m_vmsize);
|
||||
|
||||
for (GIFPath& path : m_path)
|
||||
{
|
||||
@@ -3140,7 +3177,8 @@ bool GSState::SpriteDrawWithoutGaps()
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((std::abs(dpX - first_dpX) >= 16 && (i + 2) < m_vertex.next) || std::abs(this_start_X - last_pX) >= 16)
|
||||
const int dpY = v[i + 1].XYZ.Y - v[i].XYZ.Y;
|
||||
if ((std::abs(dpY - first_dpY) >= 16 && (i + 2) < m_vertex.next) || std::abs(this_start_X - last_pX) >= 16)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -4562,14 +4600,19 @@ GSState::GSTransferBuffer::~GSTransferBuffer()
|
||||
_aligned_free(buff);
|
||||
}
|
||||
|
||||
void GSState::GSTransferBuffer::Init(int tx, int ty, const GIFRegBITBLTBUF& blit, bool is_write)
|
||||
void GSState::GSTransferBuffer::Init(GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG, const GIFRegBITBLTBUF& blit, bool is_write)
|
||||
{
|
||||
x = tx;
|
||||
y = ty;
|
||||
x = is_write ? TRXPOS.DSAX : TRXPOS.SSAX;
|
||||
y = is_write ? TRXPOS.DSAY : TRXPOS.SSAY;
|
||||
w = TRXREG.RRW;
|
||||
h = TRXREG.RRH;
|
||||
rect = GSVector4i(x, y, x + w, y + h);
|
||||
total = 0;
|
||||
start = 0;
|
||||
end = 0;
|
||||
m_blit = blit;
|
||||
m_pos = TRXPOS;
|
||||
m_reg = TRXREG;
|
||||
write = is_write;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
GSState();
|
||||
virtual ~GSState();
|
||||
|
||||
static constexpr int GetSaveStateSize();
|
||||
static constexpr int GetSaveStateSize(int version);
|
||||
|
||||
private:
|
||||
// RESTRICT prevents multiple loads of the same part of the register when accessing its bitfields (the compiler is happy to know that memory writes in-between will not go there)
|
||||
@@ -108,15 +108,19 @@ private:
|
||||
struct GSTransferBuffer
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
int w = 0, h = 0;
|
||||
int start = 0, end = 0, total = 0;
|
||||
u8* buff = nullptr;
|
||||
GSVector4i rect = GSVector4i::zero();
|
||||
GIFRegBITBLTBUF m_blit = {};
|
||||
GIFRegTRXPOS m_pos = {};
|
||||
GIFRegTRXREG m_reg = {};
|
||||
bool write = false;
|
||||
|
||||
GSTransferBuffer();
|
||||
~GSTransferBuffer();
|
||||
|
||||
void Init(int tx, int ty, const GIFRegBITBLTBUF& blit, bool write);
|
||||
void Init(GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG, const GIFRegBITBLTBUF& blit, bool is_write);
|
||||
bool Update(int tw, int th, int bpp, int& len);
|
||||
|
||||
} m_tr;
|
||||
@@ -259,7 +263,7 @@ public:
|
||||
static int s_last_transfer_draw_n;
|
||||
static int s_transfer_n;
|
||||
|
||||
static constexpr u32 STATE_VERSION = 8;
|
||||
static constexpr u32 STATE_VERSION = 9;
|
||||
|
||||
enum REG_DIRTY
|
||||
{
|
||||
|
||||
@@ -68,6 +68,7 @@ const char* shaderName(ShaderConvert value)
|
||||
case ShaderConvert::DEPTH_COPY: return "ps_depth_copy";
|
||||
case ShaderConvert::DOWNSAMPLE_COPY: return "ps_downsample_copy";
|
||||
case ShaderConvert::RGBA_TO_8I: return "ps_convert_rgba_8i";
|
||||
case ShaderConvert::RGB5A1_TO_8I: return "ps_convert_rgb5a1_8i";
|
||||
case ShaderConvert::CLUT_4: return "ps_convert_clut_4";
|
||||
case ShaderConvert::CLUT_8: return "ps_convert_clut_8";
|
||||
case ShaderConvert::YUV: return "ps_yuv";
|
||||
|
||||
@@ -44,6 +44,7 @@ enum class ShaderConvert
|
||||
DEPTH_COPY,
|
||||
DOWNSAMPLE_COPY,
|
||||
RGBA_TO_8I,
|
||||
RGB5A1_TO_8I,
|
||||
CLUT_4,
|
||||
CLUT_8,
|
||||
YUV,
|
||||
@@ -372,6 +373,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
|
||||
// Others ways to fetch the texture
|
||||
u32 channel : 3;
|
||||
u32 channel_fb : 1;
|
||||
|
||||
// Dithering
|
||||
u32 dither : 2;
|
||||
@@ -410,7 +412,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
{
|
||||
const u32 sw_blend_bits = blend_a | blend_b | blend_d;
|
||||
const bool sw_blend_needs_rt = (sw_blend_bits != 0 && ((sw_blend_bits | blend_c) & 1u)) || ((a_masked & blend_c) != 0);
|
||||
return tex_is_fb || fbmask || (date > 0 && date != 3) || sw_blend_needs_rt;
|
||||
return channel_fb || tex_is_fb || fbmask || (date > 0 && date != 3) || sw_blend_needs_rt;
|
||||
}
|
||||
|
||||
/// Disables color output from the pixel shader, this is done when all channels are masked.
|
||||
|
||||
@@ -1236,36 +1236,18 @@ void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
|
||||
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
|
||||
D3D11_BOX box = {(UINT)r.left, (UINT)r.top, 0U, (UINT)r.right, (UINT)r.bottom, 1U};
|
||||
D3D11_BOX box = {static_cast<UINT>(r.left), static_cast<UINT>(r.top), 0U, static_cast<UINT>(r.right), static_cast<UINT>(r.bottom), 1U};
|
||||
|
||||
// DX api isn't happy if we pass a box for depth copy
|
||||
// It complains that depth/multisample must be a full copy
|
||||
// and asks us to use a NULL for the box
|
||||
// DX11 doesn't support partial depth copy so we need to
|
||||
// either pass a nullptr D3D11_BOX for a full depth copy or use CopyResource instead.
|
||||
// Alternatively use shader copy StretchRect, or full depth copy with
|
||||
// adjusting the scissor and UVs in the shader.
|
||||
const bool depth = (sTex->GetType() == GSTexture::Type::DepthStencil);
|
||||
auto pBox = depth ? nullptr : &box;
|
||||
const u32 x = depth ? 0 : destX;
|
||||
const u32 y = depth ? 0 : destY;
|
||||
|
||||
m_ctx->CopySubresourceRegion(*(GSTexture11*)dTex, 0, destX, destY, 0, *(GSTexture11*)sTex, 0, pBox);
|
||||
}
|
||||
|
||||
void GSDevice11::CloneTexture(GSTexture* src, GSTexture** dest, const GSVector4i& rect)
|
||||
{
|
||||
pxAssertMsg(src->GetType() == GSTexture::Type::DepthStencil || src->GetType() == GSTexture::Type::RenderTarget, "Source is RT or DS.");
|
||||
CommitClear(src);
|
||||
|
||||
const int w = src->GetWidth();
|
||||
const int h = src->GetHeight();
|
||||
|
||||
if (src->GetType() == GSTexture::Type::DepthStencil)
|
||||
{
|
||||
// DX11 requires that you copy the entire depth buffer.
|
||||
*dest = CreateDepthStencil(w, h, src->GetFormat(), false);
|
||||
CopyRect(src, *dest, GSVector4i(0, 0, w, h), 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest = CreateRenderTarget(w, h, src->GetFormat(), false);
|
||||
CopyRect(src, *dest, rect, rect.left, rect.top);
|
||||
}
|
||||
m_ctx->CopySubresourceRegion(*(GSTexture11*)dTex, 0, x, y, 0, *(GSTexture11*)sTex, 0, pBox);
|
||||
}
|
||||
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
|
||||
@@ -1435,14 +1417,14 @@ void GSDevice11::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offs
|
||||
{
|
||||
float scale;
|
||||
float pad1[3];
|
||||
u32 SBW, DBW, pad3;
|
||||
u32 SBW, DBW, SPSM;
|
||||
};
|
||||
|
||||
const Uniforms cb = {sScale, {}, SBW, DBW};
|
||||
const Uniforms cb = {sScale, {}, SBW, DBW, SPSM};
|
||||
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
|
||||
|
||||
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
|
||||
const ShaderConvert shader = ShaderConvert::RGBA_TO_8I;
|
||||
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
|
||||
StretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
|
||||
}
|
||||
|
||||
@@ -2495,20 +2477,9 @@ D3D_SHADER_MACRO* GSDevice11::ShaderMacro::GetPtr()
|
||||
return (D3D_SHADER_MACRO*)mout.data();
|
||||
}
|
||||
|
||||
/// Checks that we weren't sent things we declared we don't support
|
||||
/// Clears things we don't support that can be quietly disabled
|
||||
static void preprocessSel(GSDevice11::PSSelector& sel)
|
||||
{
|
||||
pxAssert(sel.write_rg == 0); // Not supported, shouldn't be sent
|
||||
}
|
||||
|
||||
void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
{
|
||||
pxAssert(!config.require_full_barrier); // We always specify no support so it shouldn't request this
|
||||
preprocessSel(config.ps);
|
||||
|
||||
GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();
|
||||
|
||||
const GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();
|
||||
GSTexture* colclip_rt = g_gs_device->GetColorClipTexture();
|
||||
|
||||
if (colclip_rt)
|
||||
@@ -2536,15 +2507,17 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
{
|
||||
config.colclip_update_area = config.drawarea;
|
||||
|
||||
const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
colclip_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip);
|
||||
if (!colclip_rt)
|
||||
{
|
||||
Console.Warning("D3D11: Failed to allocate ColorClip render target, aborting draw.");
|
||||
return;
|
||||
}
|
||||
|
||||
g_gs_device->SetColorClipTexture(colclip_rt);
|
||||
// Warning: StretchRect must be called before BeginScene otherwise
|
||||
// vertices will be overwritten. Trust me you don't want to do that.
|
||||
|
||||
const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, false);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
}
|
||||
@@ -2555,12 +2528,16 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
{
|
||||
primid_tex = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::PrimID, false);
|
||||
if (!primid_tex)
|
||||
{
|
||||
Console.WriteLn("D3D11: Failed to allocate DATE image, aborting draw.");
|
||||
return;
|
||||
}
|
||||
|
||||
StretchRect(colclip_rt ? colclip_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
|
||||
primid_tex, GSVector4(config.drawarea), m_date.primid_init_ps[static_cast<u8>(config.datm)].get(), nullptr, false);
|
||||
}
|
||||
else if (config.destination_alpha != GSHWDrawConfig::DestinationAlphaMode::Off)
|
||||
else if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil ||
|
||||
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne)
|
||||
{
|
||||
const GSVector4 src = GSVector4(config.drawarea) / GSVector4(config.ds->GetSize()).xyxy();
|
||||
const GSVector4 dst = src * 2.0f - 1.0f;
|
||||
@@ -2630,21 +2607,39 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
PSSetShaderResource(1, config.pal);
|
||||
}
|
||||
|
||||
GSTexture* rt_copy = nullptr;
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported.
|
||||
GSTexture* draw_rt_clone = nullptr;
|
||||
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt))
|
||||
{
|
||||
// Bind the RT.This way special effect can use it.
|
||||
// Do not always bind the rt when it's not needed,
|
||||
// only bind it when effects use it such as fbmask emulation currently
|
||||
// because we copy the frame buffer and it is quite slow.
|
||||
CloneTexture(colclip_rt ? colclip_rt : config.rt, &rt_copy, config.drawarea);
|
||||
if (rt_copy)
|
||||
// Requires a copy of the RT.
|
||||
// Used as "bind rt" flag when texture barrier is unsupported for tex is fb.
|
||||
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true);
|
||||
if (draw_rt_clone)
|
||||
{
|
||||
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
if (config.require_one_barrier)
|
||||
PSSetShaderResource(2, rt_copy);
|
||||
PSSetShaderResource(2, draw_rt_clone);
|
||||
if (config.tex && config.tex == config.rt)
|
||||
PSSetShaderResource(0, rt_copy);
|
||||
PSSetShaderResource(0, draw_rt_clone);
|
||||
}
|
||||
else
|
||||
Console.Warning("D3D11: Failed to allocate temp texture for RT copy.");
|
||||
|
||||
}
|
||||
|
||||
GSTexture* draw_ds_clone = nullptr;
|
||||
|
||||
if (config.tex && config.tex == config.ds)
|
||||
{
|
||||
// DX requires a copy when sampling the depth buffer.
|
||||
draw_ds_clone = CreateDepthStencil(rtsize.x, rtsize.y, config.ds->GetFormat(), false);
|
||||
if (draw_ds_clone)
|
||||
{
|
||||
CopyRect(config.ds, draw_ds_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
PSSetShaderResource(0, draw_ds_clone);
|
||||
}
|
||||
else
|
||||
Console.Warning("D3D11: Failed to allocate temp texture for DS copy.");
|
||||
}
|
||||
|
||||
SetupVS(config.vs, &config.cb_vs);
|
||||
@@ -2681,7 +2676,6 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
if (config.alpha_second_pass.enable)
|
||||
{
|
||||
preprocessSel(config.alpha_second_pass.ps);
|
||||
if (config.cb_ps.FogColor_AREF.a != config.alpha_second_pass.ps_aref)
|
||||
{
|
||||
config.cb_ps.FogColor_AREF.a = config.alpha_second_pass.ps_aref;
|
||||
@@ -2697,8 +2691,12 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
DrawIndexedPrimitive();
|
||||
}
|
||||
|
||||
if (rt_copy)
|
||||
Recycle(rt_copy);
|
||||
if (draw_rt_clone)
|
||||
Recycle(draw_rt_clone);
|
||||
|
||||
if (draw_ds_clone)
|
||||
Recycle(draw_ds_clone);
|
||||
|
||||
if (primid_tex)
|
||||
Recycle(primid_tex);
|
||||
|
||||
|
||||
@@ -291,7 +291,6 @@ public:
|
||||
std::unique_ptr<GSDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format) override;
|
||||
|
||||
void CommitClear(GSTexture* t);
|
||||
void CloneTexture(GSTexture* src, GSTexture** dest, const GSVector4i& rect);
|
||||
|
||||
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
|
||||
|
||||
|
||||
@@ -703,11 +703,17 @@ bool GSDevice12::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
if (!AcquireWindow(true) || (m_window_info.type != WindowInfo::Type::Surfaceless && !CreateSwapChain()))
|
||||
return false;
|
||||
|
||||
if (!CreateNullTexture())
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to create dummy texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
std::optional<std::string> shader = ReadShaderSource("shaders/dx11/tfx.fx");
|
||||
if (!shader.has_value())
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to read shaders/dx11/tfx.fxf.");
|
||||
Host::ReportErrorAsync("GS", "Failed to read shaders/dx11/tfx.fx.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -717,12 +723,6 @@ bool GSDevice12::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
if (!m_shader_cache.Open(m_feature_level, GSConfig.UseDebugDevice))
|
||||
Console.Warning("D3D12: Shader cache failed to open.");
|
||||
|
||||
if (!CreateNullTexture())
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to create dummy texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateRootSignatures())
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to create pipeline layouts");
|
||||
@@ -1087,7 +1087,14 @@ GSDevice::PresentResult GSDevice12::BeginPresent(bool frame_skip)
|
||||
return PresentResult::DeviceLost;
|
||||
|
||||
if (frame_skip || !m_swap_chain)
|
||||
{
|
||||
if (!m_swap_chain)
|
||||
{
|
||||
ExecuteCommandList(WaitType::None);
|
||||
InvalidateCachedState();
|
||||
}
|
||||
return PresentResult::FrameSkipped;
|
||||
}
|
||||
|
||||
// Check if we lost exclusive fullscreen. If so, notify the host, so it can switch to windowed mode.
|
||||
// This might get called repeatedly if it takes a while to switch back, that's the host's problem.
|
||||
@@ -1479,15 +1486,15 @@ void GSDevice12::ConvertToIndexedTexture(
|
||||
{
|
||||
float scale;
|
||||
float pad1[3];
|
||||
u32 SBW, DBW, pad2;
|
||||
u32 SBW, DBW, SPSM;
|
||||
};
|
||||
|
||||
const Uniforms cb = {sScale, {}, SBW, DBW};
|
||||
const Uniforms cb = {sScale, {}, SBW, DBW, SPSM};
|
||||
SetUtilityRootSignature();
|
||||
SetUtilityPushConstants(&cb, sizeof(cb));
|
||||
|
||||
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
|
||||
const ShaderConvert shader = ShaderConvert::RGBA_TO_8I;
|
||||
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
|
||||
DoStretchRect(static_cast<GSTexture12*>(sTex), GSVector4::zero(), static_cast<GSTexture12*>(dTex), dRect,
|
||||
m_convert[static_cast<int>(shader)].get(), false, true);
|
||||
}
|
||||
@@ -3821,6 +3828,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
GSTexture12* draw_rt = static_cast<GSTexture12*>(config.rt);
|
||||
GSTexture12* draw_ds = static_cast<GSTexture12*>(config.ds);
|
||||
GSTexture12* draw_rt_clone = nullptr;
|
||||
GSTexture12* draw_ds_clone = nullptr;
|
||||
|
||||
// Align the render area to 128x128, hopefully avoiding render pass restarts for small render area changes (e.g. Ratchet and Clank).
|
||||
const GSVector2i rtsize(config.rt ? config.rt->GetSize() : config.ds->GetSize());
|
||||
@@ -3841,7 +3849,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
colclip_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
|
||||
draw_rt = static_cast<GSTexture12*>(config.rt);
|
||||
OMSetRenderTargets(draw_rt, draw_ds, config.scissor);
|
||||
OMSetRenderTargets(draw_rt, draw_ds, config.colclip_update_area);
|
||||
|
||||
// if this target was cleared and never drawn to, perform the clear as part of the resolve here.
|
||||
BeginRenderPass(GetLoadOpForTexture(draw_rt), D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE,
|
||||
@@ -3876,7 +3884,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
// bind textures before checking the render pass, in case we need to transition them
|
||||
if (config.tex)
|
||||
{
|
||||
PSSetShaderResource(0, config.tex, config.tex != config.rt);
|
||||
PSSetShaderResource(0, config.tex, config.tex != config.rt && config.tex != config.ds);
|
||||
PSSetSampler(config.sampler);
|
||||
}
|
||||
if (config.pal)
|
||||
@@ -3900,15 +3908,16 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
}
|
||||
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported.
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt))
|
||||
{
|
||||
// requires a copy of the RT
|
||||
// Requires a copy of the RT.
|
||||
// Used as "bind rt" flag when texture barrier is unsupported for tex is fb.
|
||||
draw_rt_clone = static_cast<GSTexture12*>(CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true));
|
||||
if (draw_rt_clone)
|
||||
{
|
||||
EndRenderPass();
|
||||
|
||||
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
|
||||
GL_PUSH("D3D12: Copy RT to temp texture {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
|
||||
draw_rt_clone->SetState(GSTexture::State::Invalidated);
|
||||
@@ -3918,6 +3927,27 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
if (config.tex && config.tex == config.rt)
|
||||
PSSetShaderResource(0, draw_rt_clone, true);
|
||||
}
|
||||
else
|
||||
Console.Warning("D3D12: Failed to allocate temp texture for RT copy.");
|
||||
}
|
||||
|
||||
if (config.tex && config.tex == config.ds)
|
||||
{
|
||||
// DX requires a copy when sampling the depth buffer.
|
||||
draw_ds_clone = static_cast<GSTexture12*>(CreateDepthStencil(rtsize.x, rtsize.y, config.ds->GetFormat(), false));
|
||||
if (draw_ds_clone)
|
||||
{
|
||||
EndRenderPass();
|
||||
|
||||
GL_PUSH("D3D12: Copy DS to temp texture {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
|
||||
draw_ds_clone->SetState(GSTexture::State::Invalidated);
|
||||
CopyRect(config.ds, draw_ds_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
PSSetShaderResource(0, draw_ds_clone, true);
|
||||
}
|
||||
else
|
||||
Console.Warning("D3D12: Failed to allocate temp texture for DS copy.");
|
||||
}
|
||||
|
||||
// Switch to colclip target for colclip hw rendering
|
||||
@@ -3932,7 +3962,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
colclip_rt = static_cast<GSTexture12*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false));
|
||||
if (!colclip_rt)
|
||||
{
|
||||
Console.WriteLn("D3D12: Failed to allocate ColorClip render target, aborting draw.");
|
||||
Console.Warning("D3D12: Failed to allocate ColorClip render target, aborting draw.");
|
||||
|
||||
if (date_image)
|
||||
Recycle(date_image);
|
||||
@@ -4012,6 +4042,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
// rt -> colclip hw blit if enabled
|
||||
if (colclip_rt && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve) && config.rt->GetState() == GSTexture::State::Dirty)
|
||||
{
|
||||
OMSetRenderTargets(draw_rt, draw_ds, GSVector4i::loadh(rtsize));
|
||||
SetUtilityTexture(static_cast<GSTexture12*>(config.rt), m_point_sampler_cpu);
|
||||
SetPipeline(m_colclip_setup_pipelines[pipe.ds].get());
|
||||
|
||||
@@ -4021,8 +4052,10 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
|
||||
GL_POP();
|
||||
}
|
||||
|
||||
// Restore original scissor, not sure if needed since the render pass has already been started. But to be safe.
|
||||
OMSetRenderTargets(draw_rt, draw_ds, config.scissor);
|
||||
}
|
||||
// VB/IB upload, if we did DATE setup and it's not colclip hw this has already been done
|
||||
SetPrimitiveTopology(s_primitive_topology_mapping[static_cast<u8>(config.topology)]);
|
||||
if (!date_image || colclip_rt)
|
||||
@@ -4066,6 +4099,9 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
if (draw_rt_clone)
|
||||
Recycle(draw_rt_clone);
|
||||
|
||||
if (draw_ds_clone)
|
||||
Recycle(draw_ds_clone);
|
||||
|
||||
if (date_image)
|
||||
Recycle(date_image);
|
||||
|
||||
@@ -4082,7 +4118,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
colclip_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
|
||||
draw_rt = static_cast<GSTexture12*>(config.rt);
|
||||
OMSetRenderTargets(draw_rt, draw_ds, config.scissor);
|
||||
OMSetRenderTargets(draw_rt, draw_ds, config.colclip_update_area);
|
||||
|
||||
// if this target was cleared and never drawn to, perform the clear as part of the resolve here.
|
||||
BeginRenderPass(GetLoadOpForTexture(draw_rt), D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE,
|
||||
|
||||
@@ -184,40 +184,6 @@ bool GSHwHack::GSC_NamcoGames(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
{
|
||||
if (r.IsPossibleChannelShuffle() && !(RTBP0 & 31))
|
||||
{
|
||||
GSVertex* v = &r.m_vertex.buff[0];
|
||||
|
||||
// Make sure we're detecting the right effect.
|
||||
if (((v[1].XYZ.X - v[0].XYZ.X) >> 4) != 8 || ((v[1].XYZ.Y - v[0].XYZ.Y) >> 4) != 14)
|
||||
return false;
|
||||
|
||||
GSTextureCache::Target* rt = g_texture_cache->LookupTarget(GIFRegTEX0::Create(RTBP0, RFBW, RFPSM),
|
||||
GSVector2i(1, 1), r.GetTextureScaleFactor(), GSTextureCache::RenderTarget);
|
||||
if (!rt)
|
||||
return false;
|
||||
|
||||
GL_INS("GSC_NamcoGames(): HLE channel shuffle");
|
||||
|
||||
// have to set up the palette ourselves too, since GSC executes before it does
|
||||
r.m_mem.m_clut.Read32(RTEX0, r.m_draw_env->TEXA);
|
||||
std::shared_ptr<GSTextureCache::Palette> palette =
|
||||
g_texture_cache->LookupPaletteObject(r.m_mem.m_clut, GSLocalMemory::m_psm[RTEX0.PSM].pal, true);
|
||||
if (!palette)
|
||||
return false;
|
||||
|
||||
GSHWDrawConfig& conf = r.BeginHLEHardwareDraw(
|
||||
rt->GetTexture(), nullptr, rt->GetScale(), rt->GetTexture(), rt->GetScale(), rt->GetUnscaledRect());
|
||||
conf.pal = palette->GetPaletteGSTexture();
|
||||
conf.ps.channel = ChannelFetch_RGB;
|
||||
conf.colormask.wa = false;
|
||||
r.EndHLEHardwareDraw(false);
|
||||
|
||||
// 12 pages: 2 calls by channel, 3 channels, 1 blit
|
||||
skip = 12 * (3 + 3 + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!s_nativeres && r.PRIM->PRIM == GS_SPRITE && RTME && RTEX0.TFX == 1 && RFPSM == RTPSM && RTPSM == PSMCT32 && RFBMSK == 0xFF000000 && r.m_index.tail > 2)
|
||||
{
|
||||
GSVertex* v = &r.m_vertex.buff[0];
|
||||
@@ -431,31 +397,6 @@ bool GSHwHack::GSC_TalesOfLegendia(GSRendererHW& r, int& skip)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_Kunoichi(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
{
|
||||
if (!RTME && (RFBP == 0x0 || RFBP == 0x00700 || RFBP == 0x00800) && RFPSM == PSMCT32 && RFBMSK == 0x00FFFFFF)
|
||||
{
|
||||
// Removes depth effects(shadows) not rendered correctly on all renders.
|
||||
skip = 3;
|
||||
}
|
||||
if (RTME && (RFBP == 0x0700 || RFBP == 0) && RTBP0 == 0x0e00 && RTPSM == 0 && RFBMSK == 0)
|
||||
{
|
||||
skip = 1; // Removes black screen (not needed anymore maybe)?
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RTME && (RFBP == 0x0e00) && RFPSM == PSMCT32 && RFBMSK == 0xFF000000)
|
||||
{
|
||||
skip = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_ZettaiZetsumeiToshi2(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
@@ -505,27 +446,6 @@ bool GSHwHack::GSC_ZettaiZetsumeiToshi2(GSRendererHW& r, int& skip)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_SakuraWarsSoLongMyLove(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
{
|
||||
if (RTME == 0 && RFBP != RTBP0 && RTBP0 && RFBMSK == 0x00FFFFFF)
|
||||
{
|
||||
skip = 3; // Remove darkness
|
||||
}
|
||||
else if (RTME == 0 && RFBP == RTBP0 && (RTBP0 == 0x1200 || RTBP0 == 0x1180 || RTBP0 == 0) && RFBMSK == 0x00FFFFFF)
|
||||
{
|
||||
skip = 3; // Remove darkness
|
||||
}
|
||||
else if (RTME && (RFBP == 0 || RFBP == 0x1180) && RFPSM == PSMCT32 && RTBP0 == 0x3F3F && RTPSM == PSMT8)
|
||||
{
|
||||
skip = 1; // Floodlight
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_UltramanFightingEvolution(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
@@ -557,26 +477,6 @@ bool GSHwHack::GSC_TalesofSymphonia(GSRendererHW& r, int& skip)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_Simple2000Vol114(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
{
|
||||
if (!s_nativeres && RTME == 0 && (RFBP == 0x1500) && (RTBP0 == 0x2c97 || RTBP0 == 0x2ace || RTBP0 == 0x03d0 || RTBP0 == 0x2448) && (RFBMSK == 0x0000))
|
||||
{
|
||||
// Don't enable hack on native res if crc is below aggressive.
|
||||
// Upscaling issues, removes glow/blur effect which fixes ghosting.
|
||||
skip = 1;
|
||||
}
|
||||
if (RTME && (RFBP == 0x0e00) && (RTBP0 == 0x1000) && (RFBMSK == 0x0000))
|
||||
{
|
||||
// Depth shadows.
|
||||
skip = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_UrbanReign(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
@@ -1413,13 +1313,10 @@ bool GSHwHack::MV_Ico(GSRendererHW& r)
|
||||
#define CRC_F(name) { #name, &GSHwHack::name }
|
||||
|
||||
const GSHwHack::Entry<GSRendererHW::GSC_Ptr> GSHwHack::s_get_skip_count_functions[] = {
|
||||
CRC_F(GSC_Kunoichi),
|
||||
CRC_F(GSC_Manhunt2),
|
||||
CRC_F(GSC_MidnightClub3),
|
||||
CRC_F(GSC_SacredBlaze),
|
||||
CRC_F(GSC_GuitarHero),
|
||||
CRC_F(GSC_SakuraWarsSoLongMyLove),
|
||||
CRC_F(GSC_Simple2000Vol114),
|
||||
CRC_F(GSC_SFEX3),
|
||||
CRC_F(GSC_DTGames),
|
||||
CRC_F(GSC_TalesOfLegendia),
|
||||
|
||||
@@ -16,12 +16,9 @@ public:
|
||||
static bool GSC_BlackAndBurnoutSky(GSRendererHW& r, int& skip);
|
||||
static bool GSC_MidnightClub3(GSRendererHW& r, int& skip);
|
||||
static bool GSC_TalesOfLegendia(GSRendererHW& r, int& skip);
|
||||
static bool GSC_Kunoichi(GSRendererHW& r, int& skip);
|
||||
static bool GSC_ZettaiZetsumeiToshi2(GSRendererHW& r, int& skip);
|
||||
static bool GSC_SakuraWarsSoLongMyLove(GSRendererHW& r, int& skip);
|
||||
static bool GSC_UltramanFightingEvolution(GSRendererHW& r, int& skip);
|
||||
static bool GSC_TalesofSymphonia(GSRendererHW& r, int& skip);
|
||||
static bool GSC_Simple2000Vol114(GSRendererHW& r, int& skip);
|
||||
static bool GSC_UrbanReign(GSRendererHW& r, int& skip);
|
||||
static bool GSC_SteambotChronicles(GSRendererHW& r, int& skip);
|
||||
static bool GSC_BlueTongueGames(GSRendererHW& r, int& skip);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -129,6 +129,7 @@ private:
|
||||
bool ContinueSplitClear();
|
||||
void FinishSplitClear();
|
||||
|
||||
bool NeedsBlending();
|
||||
bool IsRTWritten();
|
||||
bool IsDepthAlwaysPassing();
|
||||
bool IsUsingCsInBlend();
|
||||
@@ -222,8 +223,8 @@ public:
|
||||
GSVector4i ComputeBoundingBox(const GSVector2i& rtsize, float rtscale);
|
||||
void MergeSprite(GSTextureCache::Source* tex);
|
||||
float GetTextureScaleFactor() override;
|
||||
GSVector2i GetValidSize(const GSTextureCache::Source* tex = nullptr);
|
||||
GSVector2i GetTargetSize(const GSTextureCache::Source* tex = nullptr, const bool can_expand = true);
|
||||
GSVector2i GetValidSize(const GSTextureCache::Source* tex = nullptr, const bool is_shuffle = false);
|
||||
GSVector2i GetTargetSize(const GSTextureCache::Source* tex = nullptr, const bool can_expand = true, const bool is_shuffle = false);
|
||||
|
||||
void Reset(bool hardware_reset) override;
|
||||
void UpdateSettings(const Pcsx2Config::GSOptions& old_config) override;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -209,7 +209,7 @@ public:
|
||||
struct TempZAddress
|
||||
{
|
||||
u32 ZBP;
|
||||
u32 offset;
|
||||
int offset;
|
||||
GSVector4i rect_since;
|
||||
};
|
||||
|
||||
@@ -441,7 +441,7 @@ protected:
|
||||
std::unique_ptr<GSDownloadTexture> m_uint16_download_texture;
|
||||
std::unique_ptr<GSDownloadTexture> m_uint32_download_texture;
|
||||
|
||||
Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t, bool half_right, int x_offset, int y_offset, const GSVector2i* lod, const GSVector4i* src_range, GSTexture* gpu_clut, SourceRegion region);
|
||||
Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t, int x_offset, int y_offset, const GSVector2i* lod, const GSVector4i* src_range, GSTexture* gpu_clut, SourceRegion region);
|
||||
|
||||
bool PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size, bool is_frame,
|
||||
bool preload, bool preserve_target, const GSVector4i draw_rect, Target* dst, GSTextureCache::Source* src = nullptr);
|
||||
@@ -494,8 +494,8 @@ public:
|
||||
GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, float* scale, const GSVector2i& size);
|
||||
std::shared_ptr<Palette> LookupPaletteObject(const u32* clut, u16 pal, bool need_gs_texture);
|
||||
|
||||
Source* LookupSource(const bool is_color, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear, const u32 frame_fbp = 0xFFFFFFFF, bool req_color = true, bool req_alpha = true);
|
||||
Source* LookupDepthSource(const bool is_depth, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const u32 frame_fbp = 0xFFFFFFFF, bool req_color = true, bool req_alpha = true, bool palette = false);
|
||||
Source* LookupSource(const bool is_color, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear, const GIFRegFRAME& frame, bool req_color = true, bool req_alpha = true);
|
||||
Source* LookupDepthSource(const bool is_depth, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const GIFRegFRAME& frame, bool req_color = true, bool req_alpha = true, bool palette = false);
|
||||
|
||||
Target* FindTargetOverlap(Target* target, int type, int psm);
|
||||
void CombineAlignedInsideTargets(Target* target, GSTextureCache::Source* src = nullptr);
|
||||
|
||||
@@ -270,56 +270,57 @@ std::string GSTextureReplacements::GetDumpFilename(const TextureName& name, u32
|
||||
return ret;
|
||||
|
||||
const std::string game_dir(GetGameTextureDirectory());
|
||||
if (!FileSystem::DirectoryExists(game_dir.c_str()))
|
||||
const std::string game_subdir(Path::Combine(game_dir, TEXTURE_DUMP_SUBDIRECTORY_NAME));
|
||||
|
||||
if (!FileSystem::DirectoryExists(game_subdir.c_str()))
|
||||
{
|
||||
// create both dumps and replacements
|
||||
if (!FileSystem::CreateDirectoryPath(game_dir.c_str(), false) ||
|
||||
!FileSystem::EnsureDirectoryExists(Path::Combine(game_dir, "dumps").c_str(), false) ||
|
||||
!FileSystem::EnsureDirectoryExists(Path::Combine(game_dir, "replacements").c_str(), false))
|
||||
!FileSystem::EnsureDirectoryExists(game_subdir.c_str(), false) ||
|
||||
!FileSystem::EnsureDirectoryExists(Path::Combine(game_dir, TEXTURE_REPLACEMENT_SUBDIRECTORY_NAME).c_str(), false))
|
||||
{
|
||||
// if it fails to create, we're not going to be able to use it anyway
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string game_subdir(Path::Combine(game_dir, TEXTURE_DUMP_SUBDIRECTORY_NAME));
|
||||
|
||||
std::string filename;
|
||||
if (name.HasRegion())
|
||||
{
|
||||
if (name.HasPalette())
|
||||
{
|
||||
filename = (level > 0) ?
|
||||
StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_CLUT_FORMAT_STRING "-mip%u.png",
|
||||
name.TEX0Hash, name.CLUTHash, name.region_width, name.region_height, name.bits, level) :
|
||||
StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_CLUT_FORMAT_STRING ".png",
|
||||
name.TEX0Hash, name.CLUTHash, name.region_width, name.region_height, name.bits);
|
||||
filename = (level > 0)
|
||||
? StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_CLUT_FORMAT_STRING "-mip%u.png",
|
||||
name.TEX0Hash, name.CLUTHash, name.region_width, name.region_height, name.bits, level)
|
||||
: StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_CLUT_FORMAT_STRING ".png",
|
||||
name.TEX0Hash, name.CLUTHash, name.region_width, name.region_height, name.bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = (level > 0) ? StringUtil::StdStringFromFormat(
|
||||
TEXTURE_FILENAME_REGION_FORMAT_STRING "-mip%u.png", name.TEX0Hash,
|
||||
name.region_width, name.region_height, name.bits, level) :
|
||||
StringUtil::StdStringFromFormat(
|
||||
TEXTURE_FILENAME_REGION_FORMAT_STRING ".png", name.TEX0Hash,
|
||||
name.region_width, name.region_height, name.bits);
|
||||
filename = (level > 0)
|
||||
? StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_FORMAT_STRING "-mip%u.png",
|
||||
name.TEX0Hash, name.region_width, name.region_height, name.bits, level)
|
||||
: StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_FORMAT_STRING ".png",
|
||||
name.TEX0Hash, name.region_width, name.region_height, name.bits);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name.HasPalette())
|
||||
{
|
||||
filename = (level > 0) ? StringUtil::StdStringFromFormat(TEXTURE_FILENAME_CLUT_FORMAT_STRING "-mip%u.png",
|
||||
name.TEX0Hash, name.CLUTHash, name.bits, level) :
|
||||
StringUtil::StdStringFromFormat(TEXTURE_FILENAME_CLUT_FORMAT_STRING ".png",
|
||||
name.TEX0Hash, name.CLUTHash, name.bits);
|
||||
filename = (level > 0)
|
||||
? StringUtil::StdStringFromFormat(TEXTURE_FILENAME_CLUT_FORMAT_STRING "-mip%u.png",
|
||||
name.TEX0Hash, name.CLUTHash, name.bits, level)
|
||||
: StringUtil::StdStringFromFormat(TEXTURE_FILENAME_CLUT_FORMAT_STRING ".png",
|
||||
name.TEX0Hash, name.CLUTHash, name.bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
filename = (level > 0) ? StringUtil::StdStringFromFormat(
|
||||
TEXTURE_FILENAME_FORMAT_STRING "-mip%u.png", name.TEX0Hash, name.bits, level) :
|
||||
StringUtil::StdStringFromFormat(
|
||||
TEXTURE_FILENAME_FORMAT_STRING ".png", name.TEX0Hash, name.bits);
|
||||
filename = (level > 0)
|
||||
? StringUtil::StdStringFromFormat(TEXTURE_FILENAME_FORMAT_STRING "-mip%u.png",
|
||||
name.TEX0Hash, name.bits, level)
|
||||
: StringUtil::StdStringFromFormat(TEXTURE_FILENAME_FORMAT_STRING ".png",
|
||||
name.TEX0Hash, name.bits);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,6 +350,28 @@ void GSTextureReplacements::GameChanged()
|
||||
ClearDumpedTextureList();
|
||||
}
|
||||
|
||||
/// If the given file exists in the given directory, but with a different case than the original file, write its path to `*output` and return true.
|
||||
static bool GetWrongCasePath(std::string* output, const char* dir, std::string_view file, FileSystem::FindResultsArray* reuseme)
|
||||
{
|
||||
if (FileSystem::FindFiles(dir, "*", FILESYSTEM_FIND_FOLDERS | FILESYSTEM_FIND_HIDDEN_FILES, reuseme))
|
||||
{
|
||||
for (const FILESYSTEM_FIND_DATA& fd : *reuseme)
|
||||
{
|
||||
std::string_view name = Path::GetFileName(fd.FileName);
|
||||
if (name.size() != file.size())
|
||||
continue;
|
||||
if (0 == strncmp(name.data(), file.data(), name.size()))
|
||||
continue;
|
||||
if (0 == StringUtil::Strncasecmp(name.data(), file.data(), name.size()))
|
||||
{
|
||||
*output = fd.FileName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GSTextureReplacements::ReloadReplacementMap()
|
||||
{
|
||||
SyncWorkerThread();
|
||||
@@ -368,9 +391,27 @@ void GSTextureReplacements::ReloadReplacementMap()
|
||||
if (s_current_serial.empty() || !GSConfig.LoadTextureReplacements)
|
||||
return;
|
||||
|
||||
const std::string replacement_dir(Path::Combine(GetGameTextureDirectory(), TEXTURE_REPLACEMENT_SUBDIRECTORY_NAME));
|
||||
const std::string texture_dir = GetGameTextureDirectory();
|
||||
const std::string replacement_dir(Path::Combine(texture_dir, TEXTURE_REPLACEMENT_SUBDIRECTORY_NAME));
|
||||
|
||||
FileSystem::FindResultsArray files;
|
||||
|
||||
// For some reason texture pack authors think it's a good idea to rename the replacements directory to something with the wrong case...
|
||||
std::string wrong_case_path;
|
||||
const std::string* right_case_path = nullptr;
|
||||
if (GetWrongCasePath(&wrong_case_path, EmuFolders::Textures.c_str(), s_current_serial, &files))
|
||||
right_case_path = &texture_dir;
|
||||
else if (GetWrongCasePath(&wrong_case_path, texture_dir.c_str(), TEXTURE_REPLACEMENT_SUBDIRECTORY_NAME, &files))
|
||||
right_case_path = &replacement_dir;
|
||||
if (right_case_path)
|
||||
{
|
||||
Host::AddKeyedOSDMessage("TextureReplacementDirCaseMismatch",
|
||||
fmt::format(TRANSLATE_FS("TextureReplacement", "Texture replacement directory {} will not work on case sensitive filesystems.\n"
|
||||
"Rename it to {} to remove this warning."),
|
||||
wrong_case_path, *right_case_path),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
}
|
||||
|
||||
if (!FileSystem::FindFiles(replacement_dir.c_str(), "*", FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES | FILESYSTEM_FIND_RECURSIVE, &files))
|
||||
return;
|
||||
|
||||
|
||||
@@ -1713,12 +1713,12 @@ void GSDeviceMTL::UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX,
|
||||
|
||||
void GSDeviceMTL::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM)
|
||||
{ @autoreleasepool {
|
||||
const ShaderConvert shader = ShaderConvert::RGBA_TO_8I;
|
||||
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
|
||||
id<MTLRenderPipelineState> pipeline = m_convert_pipeline[static_cast<int>(shader)];
|
||||
if (!pipeline)
|
||||
[NSException raise:@"StretchRect Missing Pipeline" format:@"No pipeline for %d", static_cast<int>(shader)];
|
||||
|
||||
GSMTLIndexedConvertPSUniform uniform = { sScale, SBW, DBW };
|
||||
GSMTLIndexedConvertPSUniform uniform = { sScale, SBW, DBW, SPSM };
|
||||
|
||||
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
|
||||
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, pipeline, false, LoadAction::DontCareIfFull, &uniform, sizeof(uniform));
|
||||
|
||||
@@ -4,12 +4,19 @@
|
||||
#include "GSMTLDeviceInfo.h"
|
||||
#include "GS/GS.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/Path.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
static id<MTLLibrary> loadMainLibrary(id<MTLDevice> dev, NSString* name)
|
||||
{
|
||||
NSString* path = [[NSBundle mainBundle] pathForResource:name ofType:@"metallib"];
|
||||
if (!path)
|
||||
{
|
||||
std::string ssname = std::string([name UTF8String]) + ".metallib";
|
||||
std::string sspath = Path::Combine(EmuFolders::Resources, ssname);
|
||||
path = [[NSString alloc] initWithBytes:sspath.data() length:sspath.length() encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
return path ? [dev newLibraryWithFile:path error:nullptr] : nullptr;
|
||||
}
|
||||
|
||||
@@ -24,6 +31,8 @@ static MRCOwned<id<MTLLibrary>> loadMainLibrary(id<MTLDevice> dev)
|
||||
if (@available(macOS 10.14, iOS 12.0, *))
|
||||
if (id<MTLLibrary> lib = loadMainLibrary(dev, @"Metal21"))
|
||||
return MRCTransfer(lib);
|
||||
if (id<MTLLibrary> lib = loadMainLibrary(dev, @"default"))
|
||||
return MRCTransfer(lib);
|
||||
return MRCTransfer([dev newDefaultLibrary]);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ struct GSMTLIndexedConvertPSUniform
|
||||
float scale;
|
||||
uint sbw;
|
||||
uint dbw;
|
||||
uint psm;
|
||||
};
|
||||
|
||||
struct GSMTLDownsamplePSUniform
|
||||
|
||||
@@ -296,6 +296,121 @@ fragment DepthOut ps_convert_rgb5a1_float16_biln(ConvertShaderData data [[stage_
|
||||
return res.sample_biln<rgb5a1_to_depth16>(data.t);
|
||||
}
|
||||
|
||||
fragment float4 ps_convert_rgb5a1_8i(ConvertShaderData data [[stage_in]], DirectReadTextureIn<float> res,
|
||||
constant GSMTLIndexedConvertPSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
|
||||
{
|
||||
// Convert a RGB5A1 texture into a 8 bits packed texture
|
||||
// Input column: 16x2 RGB5A1 pixels
|
||||
// 0: 16 RGBA
|
||||
// 1: 16 RGBA
|
||||
// Output column: 16x4 Index pixels
|
||||
// 0: 16 R5G2
|
||||
// 1: 16 R5G2
|
||||
// 2: 16 G2B5A1
|
||||
// 3: 16 G2B5A1
|
||||
uint2 pos = uint2(data.p.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uint2 column = (pos & ~uint2(0u, 3u)) / uint2(1,2);
|
||||
uint2 subcolumn = (pos & uint2(0u, 1u));
|
||||
column.x -= (column.x / 128) * 64;
|
||||
column.y += (column.y / 32) * 32;
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((uniform.psm & 0x8) != 0) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32) != 0)
|
||||
{
|
||||
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32;
|
||||
}
|
||||
|
||||
if ((pos.x & 64) != 0)
|
||||
{
|
||||
column.x -= 32;
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
}
|
||||
|
||||
if ((uniform.psm & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 16;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32) != 0)
|
||||
{
|
||||
column.y -= 16;
|
||||
column.x += 32;
|
||||
}
|
||||
|
||||
if ((pos.x & 96) != 0)
|
||||
{
|
||||
uint multi = (pos.x & 96) / 32;
|
||||
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96);
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
}
|
||||
|
||||
if ((uniform.psm & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 32;
|
||||
}
|
||||
}
|
||||
|
||||
uint2 coord = column | subcolumn;
|
||||
|
||||
// Compensate for potentially differing page pitch.
|
||||
uint2 block_xy = coord / uint2(64, 64);
|
||||
uint block_num = (block_xy.y * (uniform.dbw / 128)) + block_xy.x;
|
||||
uint2 block_offset = uint2((block_num % (uniform.sbw / 64)) * 64, (block_num / (uniform.sbw / 64)) * 64);
|
||||
coord = (coord % uint2(64, 64)) + block_offset;
|
||||
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4;
|
||||
uint is_col13 = pos.y & 2;
|
||||
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||
|
||||
if (any(floor(uniform.scale) != uniform.scale))
|
||||
coord = uint2(float2(coord) * uniform.scale);
|
||||
else
|
||||
coord = mul24(coord, uint2(uniform.scale));
|
||||
|
||||
float4 pixel = res.tex.read(coord);
|
||||
|
||||
uint4 denorm_c = (uint4)(pixel * 255.5f);
|
||||
if ((pos.y & 2u) == 0u)
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
float sel0 = (float)(((green << 5) | red) & 0xFF) / 255.0f;
|
||||
|
||||
return float4(sel0);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
float sel0 = (float)((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
|
||||
|
||||
return float4(sel0);
|
||||
}
|
||||
}
|
||||
|
||||
fragment float4 ps_convert_rgba_8i(ConvertShaderData data [[stage_in]], DirectReadTextureIn<float> res,
|
||||
constant GSMTLIndexedConvertPSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
|
||||
{
|
||||
|
||||
@@ -350,10 +350,11 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
return false;
|
||||
m_convert.ps[i].SetFormattedName("Convert pipe %s", name);
|
||||
|
||||
if (static_cast<ShaderConvert>(i) == ShaderConvert::RGBA_TO_8I)
|
||||
if (static_cast<ShaderConvert>(i) == ShaderConvert::RGBA_TO_8I || static_cast<ShaderConvert>(i) == ShaderConvert::RGB5A1_TO_8I)
|
||||
{
|
||||
m_convert.ps[i].RegisterUniform("SBW");
|
||||
m_convert.ps[i].RegisterUniform("DBW");
|
||||
m_convert.ps[i].RegisterUniform("PSM");
|
||||
m_convert.ps[i].RegisterUniform("ScaleFactor");
|
||||
}
|
||||
else if (static_cast<ShaderConvert>(i) == ShaderConvert::YUV)
|
||||
@@ -1594,12 +1595,13 @@ void GSDeviceOGL::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 off
|
||||
{
|
||||
CommitClear(sTex, false);
|
||||
|
||||
const ShaderConvert shader = ShaderConvert::RGBA_TO_8I;
|
||||
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
|
||||
GLProgram& prog = m_convert.ps[static_cast<int>(shader)];
|
||||
prog.Bind();
|
||||
prog.Uniform1ui(0, SBW);
|
||||
prog.Uniform1ui(1, DBW);
|
||||
prog.Uniform1f(2, sScale);
|
||||
prog.Uniform1ui(2, SPSM);
|
||||
prog.Uniform1f(3, sScale);
|
||||
|
||||
OMSetDepthStencilState(m_convert.dss);
|
||||
OMSetBlendState(false);
|
||||
@@ -2424,7 +2426,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
const GSVector4 dRect(config.colclip_update_area);
|
||||
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
|
||||
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
|
||||
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
Recycle(colclip_rt);
|
||||
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
@@ -2444,6 +2446,14 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
config.colclip_update_area = config.drawarea;
|
||||
|
||||
colclip_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false);
|
||||
|
||||
if (!colclip_rt)
|
||||
{
|
||||
Console.Warning("GL: Failed to allocate ColorClip render target, aborting draw.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
OMSetRenderTargets(colclip_rt, config.ds, nullptr);
|
||||
|
||||
g_gs_device->SetColorClipTexture(colclip_rt);
|
||||
@@ -2451,6 +2461,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, false);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2462,6 +2473,11 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
break; // No setup
|
||||
case GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking:
|
||||
primid_texture = InitPrimDateTexture(colclip_rt ? colclip_rt : config.rt, config.drawarea, config.datm);
|
||||
if (!primid_texture)
|
||||
{
|
||||
Console.WriteLn("GL: Failed to allocate DATE image, aborting draw.");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case GSHWDrawConfig::DestinationAlphaMode::StencilOne:
|
||||
if (m_features.texture_barrier)
|
||||
@@ -2489,12 +2505,17 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
if (config.require_one_barrier && !m_features.texture_barrier)
|
||||
{
|
||||
// Requires a copy of the RT
|
||||
// Requires a copy of the RT.
|
||||
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true);
|
||||
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}",
|
||||
config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
if (draw_rt_clone)
|
||||
{
|
||||
GL_PUSH("GL: Copy RT to temp texture {%d,%d %dx%d}",
|
||||
config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
}
|
||||
else
|
||||
Console.Warning("GL: Failed to allocate temp texture for RT copy.");
|
||||
}
|
||||
|
||||
IASetVertexBuffer(config.verts, config.nverts);
|
||||
@@ -2563,7 +2584,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
if (check_barrier && ((config.tex && (config.tex == config.ds || config.tex == config.rt)) || ((psel.ps.IsFeedbackLoop() || psel.ps.blend_c == 1) && GLState::rt == config.rt)))
|
||||
{
|
||||
// Ensure all depth writes are finished before sampling
|
||||
GL_INS("Texture barrier to flush depth or rt before reading");
|
||||
GL_INS("GL: Texture barrier to flush depth or rt before reading");
|
||||
glTextureBarrier();
|
||||
}
|
||||
// additional non-pipeline config stuff
|
||||
@@ -2710,7 +2731,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
const GSVector4 dRect(config.colclip_update_area);
|
||||
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
|
||||
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
|
||||
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
Recycle(colclip_rt);
|
||||
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
|
||||
@@ -1491,7 +1491,7 @@ __ri void GSDrawScanline::CDrawScanline(int pixels, int left, int top, const GSV
|
||||
case 2: break;
|
||||
}
|
||||
|
||||
if(!(sel.fpsm == 1 && sel.abc == 1))
|
||||
if (!(sel.fpsm == 1 && sel.abc == 1))
|
||||
{
|
||||
switch(sel.abc)
|
||||
{
|
||||
|
||||
@@ -562,7 +562,7 @@ L("loop");
|
||||
|
||||
L("step");
|
||||
|
||||
// if(steps <= 0) break;
|
||||
// if (steps <= 0) break;
|
||||
|
||||
if (!m_sel.edge)
|
||||
{
|
||||
@@ -768,7 +768,7 @@ void GSDrawScanlineCodeGenerator::Init()
|
||||
cvttps2dq(xym6, vt);
|
||||
|
||||
// s = vti.xxxx() + m_local.d[skip].s;
|
||||
// t = vti.yyyy(); if(!sprite) t += m_local.d[skip].t;
|
||||
// t = vti.yyyy(); if (!sprite) t += m_local.d[skip].t;
|
||||
|
||||
pshufd(s, xym6, _MM_SHUFFLE(0, 0, 0, 0));
|
||||
pshufd(t, xym6, _MM_SHUFFLE(1, 1, 1, 1));
|
||||
@@ -925,7 +925,7 @@ void GSDrawScanlineCodeGenerator::Step()
|
||||
// GSVector4i stq = m_local.d4.stq;
|
||||
|
||||
// s += stq.xxxx();
|
||||
// if(!sprite) t += st.yyyy();
|
||||
// if (!sprite) t += st.yyyy();
|
||||
|
||||
broadcasti128(stq, _rip_local_d(stq));
|
||||
|
||||
@@ -2096,7 +2096,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
|
||||
|
||||
clamp16(_ga, tmp);
|
||||
|
||||
// if(!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
// if (!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
|
||||
if (!m_sel.tcc)
|
||||
{
|
||||
@@ -2109,7 +2109,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
|
||||
|
||||
case TFX_DECAL:
|
||||
|
||||
// if(!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
// if (!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
if (!m_sel.tcc)
|
||||
{
|
||||
// GSVector4i ga = iip ? gaf : m_local.c.ga;
|
||||
@@ -2139,7 +2139,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
|
||||
|
||||
case TFX_HIGHLIGHT2:
|
||||
|
||||
// if(!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
// if (!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
|
||||
if (!m_sel.tcc)
|
||||
{
|
||||
@@ -2990,8 +2990,8 @@ void GSDrawScanlineCodeGenerator::WritePixel(const XYm& src_, const AddressReg&
|
||||
{
|
||||
if (fast)
|
||||
{
|
||||
// if(fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
|
||||
// if(fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
|
||||
// if (fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
|
||||
// if (fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
|
||||
|
||||
test(mask, 0x0000000f << shift);
|
||||
je("@f");
|
||||
@@ -3020,10 +3020,10 @@ void GSDrawScanlineCodeGenerator::WritePixel(const XYm& src_, const AddressReg&
|
||||
}
|
||||
else
|
||||
{
|
||||
// if(fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
|
||||
// if(fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
|
||||
// if(fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
|
||||
// if(fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
|
||||
// if (fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
|
||||
// if (fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
|
||||
// if (fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
|
||||
// if (fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
|
||||
|
||||
test(mask, 0x00000003 << shift);
|
||||
je("@f");
|
||||
|
||||
@@ -158,7 +158,7 @@ void GSDrawScanlineCodeGenerator::Generate()
|
||||
Label exit;
|
||||
armAsm->Bind(&m_step_label);
|
||||
|
||||
// if(steps <= 0) break;
|
||||
// if (steps <= 0) break;
|
||||
|
||||
if (!m_sel.edge)
|
||||
{
|
||||
@@ -332,7 +332,7 @@ void GSDrawScanlineCodeGenerator::Init()
|
||||
armAsm->Fcvtzs(v6.V4S(), v4.V4S());
|
||||
|
||||
// s = vti.xxxx() + m_local.d[skip].s;
|
||||
// t = vti.yyyy(); if(!sprite) t += m_local.d[skip].t;
|
||||
// t = vti.yyyy(); if (!sprite) t += m_local.d[skip].t;
|
||||
|
||||
armAsm->Dup(_temp_s.V4S(), v6.V4S(), 0);
|
||||
armAsm->Dup(_temp_t.V4S(), v6.V4S(), 1);
|
||||
@@ -485,7 +485,7 @@ void GSDrawScanlineCodeGenerator::Step()
|
||||
// GSVector4i stq = m_local.d4.stq;
|
||||
|
||||
// s += stq.xxxx();
|
||||
// if(!sprite) t += stq.yyyy();
|
||||
// if (!sprite) t += stq.yyyy();
|
||||
|
||||
armAsm->Dup(_vscratch.V4S(), _d4_stq.V4S(), 0);
|
||||
if (m_sel.prim != GS_SPRITE_CLASS || m_sel.mmin)
|
||||
@@ -1394,7 +1394,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
|
||||
modulate16(v6, _temp_ga, 1);
|
||||
clamp16(v6, v3);
|
||||
|
||||
// if(!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
// if (!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
|
||||
if (!m_sel.tcc)
|
||||
{
|
||||
@@ -1407,7 +1407,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
|
||||
|
||||
case TFX_DECAL:
|
||||
|
||||
// if(!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
// if (!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
|
||||
if (!m_sel.tcc)
|
||||
{
|
||||
@@ -1435,7 +1435,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
|
||||
|
||||
case TFX_HIGHLIGHT2:
|
||||
|
||||
// if(!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
// if (!tcc) gat = gat.mix16(ga.srl16(7));
|
||||
|
||||
if (!m_sel.tcc)
|
||||
{
|
||||
@@ -2158,8 +2158,8 @@ void GSDrawScanlineCodeGenerator::WritePixel(const VRegister& src, const Registe
|
||||
{
|
||||
if (fast)
|
||||
{
|
||||
// if(fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
|
||||
// if(fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
|
||||
// if (fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
|
||||
// if (fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
|
||||
|
||||
Label skip_low, skip_high;
|
||||
armAsm->Lsl(_wscratch, addr, 1); // *2
|
||||
@@ -2177,10 +2177,10 @@ void GSDrawScanlineCodeGenerator::WritePixel(const VRegister& src, const Registe
|
||||
}
|
||||
else
|
||||
{
|
||||
// if(fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
|
||||
// if(fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
|
||||
// if(fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
|
||||
// if(fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
|
||||
// if (fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
|
||||
// if (fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
|
||||
// if (fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
|
||||
// if (fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
|
||||
|
||||
Label skip_0, skip_1, skip_2, skip_3;
|
||||
|
||||
|
||||
@@ -444,9 +444,9 @@ void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const u16* index)
|
||||
|
||||
m1 = (y0011 == y1221).mask() & 7;
|
||||
|
||||
// if(i == 0) => y0 < y1 < y2
|
||||
// if(i == 1) => y0 == y1 < y2
|
||||
// if(i == 4) => y0 < y1 == y2
|
||||
// if (i == 0) => y0 < y1 < y2
|
||||
// if (i == 1) => y0 == y1 < y2
|
||||
// if (i == 4) => y0 < y1 == y2
|
||||
|
||||
if (m1 == 7) // y0 == y1 == y2
|
||||
return;
|
||||
@@ -623,9 +623,9 @@ void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const u16* index)
|
||||
|
||||
m1 = (y0011 == y1221).mask() & 7;
|
||||
|
||||
// if(i == 0) => y0 < y1 < y2
|
||||
// if(i == 1) => y0 == y1 < y2
|
||||
// if(i == 4) => y0 < y1 == y2
|
||||
// if (i == 0) => y0 < y1 < y2
|
||||
// if (i == 1) => y0 == y1 < y2
|
||||
// if (i == 4) => y0 < y1 == y2
|
||||
|
||||
if (m1 == 7)
|
||||
return; // y0 == y1 == y2
|
||||
|
||||
@@ -94,7 +94,7 @@ void GSRendererSW::VSync(u32 field, bool registers_written, bool idle_frame)
|
||||
m_tc->IncAge();
|
||||
|
||||
m_draw_transfers.clear();
|
||||
// if((m_perfmon.GetFrame() & 255) == 0) m_rl->PrintStats();
|
||||
// if ((m_perfmon.GetFrame() & 255) == 0) m_rl->PrintStats();
|
||||
}
|
||||
|
||||
GSTexture* GSRendererSW::GetOutput(int i, float& scale, int& y_offset)
|
||||
|
||||
@@ -515,7 +515,7 @@ void GSSetupPrimCodeGenerator::Color()
|
||||
pshufd(xym1, xym0, _MM_SHUFFLE(1, 0, 3, 2));
|
||||
punpcklwd(xym0, xym1);
|
||||
|
||||
// if(!tme) c = c.srl16(7);
|
||||
// if (!tme) c = c.srl16(7);
|
||||
|
||||
if (m_sel.tfx == TFX_NONE)
|
||||
{
|
||||
|
||||
@@ -322,7 +322,7 @@ void GSSetupPrimCodeGenerator::Color()
|
||||
armAsm->Ext(v1.V16B(), v0.V16B(), v0.V16B(), 8);
|
||||
armAsm->Zip1(v0.V8H(), v0.V8H(), v1.V8H());
|
||||
|
||||
// if(!tme) c = c.srl16(7);
|
||||
// if (!tme) c = c.srl16(7);
|
||||
|
||||
if (m_sel.tfx == TFX_NONE)
|
||||
armAsm->Ushr(v0.V8H(), v0.V8H(), 7);
|
||||
|
||||
@@ -2059,6 +2059,12 @@ bool GSDeviceVK::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateNullTexture())
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to create dummy texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
std::optional<std::string> shader = ReadShaderSource("shaders/vulkan/tfx.glsl");
|
||||
if (!shader.has_value())
|
||||
@@ -2070,12 +2076,6 @@ bool GSDeviceVK::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
m_tfx_source = std::move(*shader);
|
||||
}
|
||||
|
||||
if (!CreateNullTexture())
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to create dummy texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreatePipelineLayouts())
|
||||
{
|
||||
Host::ReportErrorAsync("GS", "Failed to create pipeline layouts");
|
||||
@@ -3158,15 +3158,16 @@ void GSDeviceVK::ConvertToIndexedTexture(
|
||||
{
|
||||
u32 SBW;
|
||||
u32 DBW;
|
||||
u32 pad1[2];
|
||||
u32 PSM;
|
||||
u32 pad1[1];
|
||||
float ScaleFactor;
|
||||
float pad2[3];
|
||||
};
|
||||
|
||||
const Uniforms uniforms = {SBW, DBW, {}, sScale, {}};
|
||||
const Uniforms uniforms = {SBW, DBW, SPSM, {}, sScale, {}};
|
||||
SetUtilityPushConstants(&uniforms, sizeof(uniforms));
|
||||
|
||||
const ShaderConvert shader = ShaderConvert::RGBA_TO_8I;
|
||||
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
|
||||
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
|
||||
DoStretchRect(static_cast<GSTextureVK*>(sTex), GSVector4::zero(), static_cast<GSTextureVK*>(dTex), dRect,
|
||||
m_convert[static_cast<int>(shader)], false, true);
|
||||
@@ -5291,8 +5292,12 @@ void GSDeviceVK::SetPipeline(VkPipeline pipeline)
|
||||
|
||||
void GSDeviceVK::SetInitialState(VkCommandBuffer cmdbuf)
|
||||
{
|
||||
const VkDeviceSize buffer_offset = 0;
|
||||
vkCmdBindVertexBuffers(cmdbuf, 0, 1, m_vertex_stream_buffer.GetBufferPtr(), &buffer_offset);
|
||||
VkBuffer buffer = *m_vertex_stream_buffer.GetBufferPtr();
|
||||
if (buffer != VK_NULL_HANDLE)
|
||||
{
|
||||
constexpr VkDeviceSize buffer_offset = 0;
|
||||
vkCmdBindVertexBuffers(cmdbuf, 0, 1, &buffer, &buffer_offset);
|
||||
}
|
||||
}
|
||||
|
||||
__ri void GSDeviceVK::ApplyBaseState(u32 flags, VkCommandBuffer cmdbuf)
|
||||
@@ -5625,7 +5630,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
date_image = SetupPrimitiveTrackingDATE(config);
|
||||
if (!date_image)
|
||||
{
|
||||
Console.WriteLn("Failed to allocate DATE image, aborting draw.");
|
||||
Console.WriteLn("VK: Failed to allocate DATE image, aborting draw.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5726,12 +5731,14 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
{
|
||||
EndRenderPass();
|
||||
|
||||
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
|
||||
GL_PUSH("VK: Copy RT to temp texture for fbmask {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
|
||||
CopyRect(draw_rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
PSSetShaderResource(2, draw_rt_clone, true);
|
||||
}
|
||||
else
|
||||
Console.Warning("VK: Failed to allocate temp texture for RT copy.");
|
||||
}
|
||||
|
||||
// Switch to colclip target for colclip hw rendering
|
||||
@@ -5744,7 +5751,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
colclip_rt = static_cast<GSTextureVK*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false));
|
||||
if (!colclip_rt)
|
||||
{
|
||||
Console.WriteLn("Failed to allocate ColorClip render target, aborting draw.");
|
||||
Console.Warning("VK: Failed to allocate ColorClip render target, aborting draw.");
|
||||
|
||||
if (date_image)
|
||||
Recycle(date_image);
|
||||
|
||||
@@ -379,8 +379,8 @@ void GSDumpReplayer::RenderUI()
|
||||
do \
|
||||
{ \
|
||||
text_size = font->CalcTextSizeA(font->FontSize, std::numeric_limits<float>::max(), -1.0f, (text), nullptr, nullptr); \
|
||||
dl->AddText(font, font->FontSize, ImVec2(margin + shadow_offset, position_y + shadow_offset), IM_COL32(0, 0, 0, 100), (text)); \
|
||||
dl->AddText(font, font->FontSize, ImVec2(margin, position_y), color, (text)); \
|
||||
dl->AddText(font, font->FontSize, ImVec2(GSConfig.OsdPerformancePos == OsdOverlayPos::TopLeft ? ImGuiManager::GetWindowWidth() - margin - text_size.x + shadow_offset : margin + shadow_offset, position_y + shadow_offset), IM_COL32(0, 0, 0, 100), (text)); \
|
||||
dl->AddText(font, font->FontSize, ImVec2(GSConfig.OsdPerformancePos == OsdOverlayPos::TopLeft ? ImGuiManager::GetWindowWidth() - margin - text_size.x : margin, position_y), color, (text)); \
|
||||
position_y += text_size.y + spacing; \
|
||||
} while (0)
|
||||
|
||||
|
||||
@@ -91,42 +91,98 @@ static std::recursive_mutex s_mutex;
|
||||
static GameList::CacheMap s_cache_map;
|
||||
static std::FILE* s_cache_write_stream = nullptr;
|
||||
|
||||
const char* GameList::EntryTypeToString(EntryType type)
|
||||
const char* GameList::EntryTypeToString(EntryType type, bool translate)
|
||||
{
|
||||
static std::array<const char*, static_cast<int>(EntryType::Count)> names = {{"PS2Disc", "PS1Disc", "ELF"}};
|
||||
return names[static_cast<int>(type)];
|
||||
static constexpr std::array<const char*, static_cast<int>(EntryType::Count)> names = {
|
||||
TRANSLATE_NOOP("GameList", "PS2 Disc"),
|
||||
TRANSLATE_NOOP("GameList", "PS1 Disc"),
|
||||
TRANSLATE_NOOP("GameList", "ELF"),
|
||||
TRANSLATE_NOOP("GameList", "Invalid"),
|
||||
};
|
||||
|
||||
const char* name = names.at(static_cast<int>(type));
|
||||
if (translate)
|
||||
name = TRANSLATE("GameList", name);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
const char* GameList::EntryTypeToDisplayString(EntryType type)
|
||||
const char* GameList::RegionToString(Region region, bool translate)
|
||||
{
|
||||
static std::array<const char*, static_cast<int>(EntryType::Count)> names = {{TRANSLATE("GameList", "PS2 Disc"), TRANSLATE("GameList", "PS1 Disc"), TRANSLATE("GameList", "ELF")}};
|
||||
return names[static_cast<int>(type)];
|
||||
static constexpr std::array<const char*, static_cast<int>(Region::Count)> names = {
|
||||
TRANSLATE_NOOP("GameList", "NTSC-B"),
|
||||
TRANSLATE_NOOP("GameList", "NTSC-C"),
|
||||
TRANSLATE_NOOP("GameList", "NTSC-HK"),
|
||||
TRANSLATE_NOOP("GameList", "NTSC-J"),
|
||||
TRANSLATE_NOOP("GameList", "NTSC-K"),
|
||||
TRANSLATE_NOOP("GameList", "NTSC-T"),
|
||||
TRANSLATE_NOOP("GameList", "NTSC-U"),
|
||||
TRANSLATE_NOOP("GameList", "Other"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-A"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-AF"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-AU"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-BE"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-E"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-F"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-FI"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-G"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-GR"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-I"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-IN"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-M"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-NL"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-NO"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-P"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-PL"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-R"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-S"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-SC"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-SW"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-SWI"),
|
||||
TRANSLATE_NOOP("GameList", "PAL-UK"),
|
||||
};
|
||||
|
||||
const char* name = names.at(static_cast<int>(region));
|
||||
if (translate)
|
||||
name = TRANSLATE("GameList", name);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
const char* GameList::RegionToString(Region region)
|
||||
const char* GameList::EntryCompatibilityRatingToString(CompatibilityRating rating, bool translate)
|
||||
{
|
||||
static std::array<const char*, static_cast<int>(Region::Count)> names = {{"NTSC-B", "NTSC-C", "NTSC-HK", "NTSC-J", "NTSC-K", "NTSC-T",
|
||||
"NTSC-U", TRANSLATE("GameList", "Other"), "PAL-A", "PAL-AF", "PAL-AU", "PAL-BE", "PAL-E", "PAL-F", "PAL-FI", "PAL-G", "PAL-GR", "PAL-I", "PAL-IN", "PAL-M",
|
||||
"PAL-NL", "PAL-NO", "PAL-P", "PAL-PL", "PAL-R", "PAL-S", "PAL-SC", "PAL-SW", "PAL-SWI", "PAL-UK"}};
|
||||
|
||||
return names[static_cast<int>(region)];
|
||||
}
|
||||
|
||||
const char* GameList::EntryCompatibilityRatingToString(CompatibilityRating rating)
|
||||
{
|
||||
// clang-format off
|
||||
const char* name = "";
|
||||
switch (rating)
|
||||
{
|
||||
case CompatibilityRating::Unknown: return TRANSLATE("GameList", "Unknown");
|
||||
case CompatibilityRating::Nothing: return TRANSLATE("GameList", "Nothing");
|
||||
case CompatibilityRating::Intro: return TRANSLATE("GameList", "Intro");
|
||||
case CompatibilityRating::Menu: return TRANSLATE("GameList", "Menu");
|
||||
case CompatibilityRating::InGame: return TRANSLATE("GameList", "In-Game");
|
||||
case CompatibilityRating::Playable: return TRANSLATE("GameList", "Playable");
|
||||
case CompatibilityRating::Perfect: return TRANSLATE("GameList", "Perfect");
|
||||
default: return "";
|
||||
case CompatibilityRating::Unknown:
|
||||
name = TRANSLATE_NOOP("GameList", "Unknown");
|
||||
break;
|
||||
case CompatibilityRating::Nothing:
|
||||
name = TRANSLATE_NOOP("GameList", "Nothing");
|
||||
break;
|
||||
case CompatibilityRating::Intro:
|
||||
name = TRANSLATE_NOOP("GameList", "Intro");
|
||||
break;
|
||||
case CompatibilityRating::Menu:
|
||||
name = TRANSLATE_NOOP("GameList", "Menu");
|
||||
break;
|
||||
case CompatibilityRating::InGame:
|
||||
name = TRANSLATE_NOOP("GameList", "In-Game");
|
||||
break;
|
||||
case CompatibilityRating::Playable:
|
||||
name = TRANSLATE_NOOP("GameList", "Playable");
|
||||
break;
|
||||
case CompatibilityRating::Perfect:
|
||||
name = TRANSLATE_NOOP("GameList", "Perfect");
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
if (translate)
|
||||
name = TRANSLATE("GameList", name);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
bool GameList::IsScannableFilename(const std::string_view path)
|
||||
@@ -591,15 +647,18 @@ void GameList::ScanDirectory(const char* path, bool recursive, bool only_cache,
|
||||
Console.WriteLn("Scanning %s%s", path, recursive ? " (recursively)" : "");
|
||||
|
||||
progress->PushState();
|
||||
progress->SetStatusText(fmt::format(
|
||||
recursive ? TRANSLATE_FS("GameList", "Scanning directory {} (recursively)...") :
|
||||
TRANSLATE_FS("GameList", "Scanning directory {}..."),
|
||||
path).c_str());
|
||||
|
||||
if (recursive)
|
||||
progress->SetStatusText(
|
||||
fmt::format(TRANSLATE_FS("GameList", "Scanning directory {} (recursively)..."), path).c_str());
|
||||
else
|
||||
progress->SetStatusText(
|
||||
fmt::format(TRANSLATE_FS("GameList", "Scanning directory {}..."), path).c_str());
|
||||
|
||||
FileSystem::FindResultsArray files;
|
||||
FileSystem::FindFiles(path, "*",
|
||||
recursive ? (FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES | FILESYSTEM_FIND_RECURSIVE) :
|
||||
(FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES),
|
||||
(FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES),
|
||||
&files, progress);
|
||||
|
||||
u32 files_scanned = 0;
|
||||
@@ -622,7 +681,7 @@ void GameList::ScanDirectory(const char* path, bool recursive, bool only_cache,
|
||||
}
|
||||
|
||||
const std::string_view filename = Path::GetFileName(ffd.FileName);
|
||||
progress->SetStatusText(fmt::format(TRANSLATE_FS("GameList","Scanning {}..."), filename.data()).c_str());
|
||||
progress->SetStatusText(fmt::format(TRANSLATE_FS("GameList", "Scanning {}..."), filename.data()).c_str());
|
||||
ScanFile(std::move(ffd.FileName), ffd.ModificationTime, lock, played_time_map, custom_attributes_ini);
|
||||
progress->SetProgressValue(files_scanned);
|
||||
}
|
||||
@@ -1300,7 +1359,7 @@ bool GameList::DownloadCovers(const std::vector<std::string>& url_templates, boo
|
||||
continue;
|
||||
}
|
||||
|
||||
progress->SetStatusText(fmt::format(TRANSLATE_FS("GameList","Downloading cover for {0} [{1}]..."), entry->title, entry->serial).c_str());
|
||||
progress->SetStatusText(fmt::format(TRANSLATE_FS("GameList", "Downloading cover for {0} [{1}]..."), entry->title, entry->serial).c_str());
|
||||
}
|
||||
|
||||
// we could actually do a few in parallel here...
|
||||
|
||||
@@ -104,10 +104,9 @@ namespace GameList
|
||||
__fi bool IsDisc() const { return (type == EntryType::PS1Disc || type == EntryType::PS2Disc); }
|
||||
};
|
||||
|
||||
const char* EntryTypeToString(EntryType type);
|
||||
const char* EntryTypeToDisplayString(EntryType type);
|
||||
const char* RegionToString(Region region);
|
||||
const char* EntryCompatibilityRatingToString(CompatibilityRating rating);
|
||||
const char* EntryTypeToString(EntryType type, bool translate);
|
||||
const char* RegionToString(Region region, bool translate);
|
||||
const char* EntryCompatibilityRatingToString(CompatibilityRating rating, bool translate);
|
||||
|
||||
/// Fills in boot parameters (iso or elf) based on the game list entry.
|
||||
void FillBootParametersForEntry(VMBootParameters* params, const Entry* entry);
|
||||
|
||||
@@ -857,7 +857,7 @@ void AudioStreamParameters::LoadSave(SettingsWrapper& wrap, const char* section)
|
||||
wrap.EnumEntry(section, "ExpansionMode", expansion_mode, &AudioStream::ParseExpansionMode, &AudioStream::GetExpansionModeName, DEFAULT_EXPANSION_MODE);
|
||||
minimal_output_latency = wrap.EntryBitBool(section, "OutputLatencyMinimal", DEFAULT_OUTPUT_LATENCY_MINIMAL);
|
||||
buffer_ms = static_cast<u16>(std::clamp<int>(wrap.EntryBitfield(section, "BufferMS", buffer_ms, DEFAULT_BUFFER_MS), 0, std::numeric_limits<u16>::max()));
|
||||
output_latency_ms = static_cast<u16>(std::clamp<int>(wrap.EntryBitfield(section, "OutputLatencyMS", buffer_ms, DEFAULT_OUTPUT_LATENCY_MS), 0, std::numeric_limits<u16>::max()));
|
||||
output_latency_ms = static_cast<u16>(std::clamp<int>(wrap.EntryBitfield(section, "OutputLatencyMS", output_latency_ms, DEFAULT_OUTPUT_LATENCY_MS), 0, std::numeric_limits<u16>::max()));
|
||||
|
||||
stretch_sequence_length_ms = static_cast<u16>(std::clamp<int>(wrap.EntryBitfield(section, "StretchSequenceLengthMS", DEFAULT_STRETCH_SEQUENCE_LENGTH), 0, std::numeric_limits<u16>::max()));
|
||||
stretch_seekwindow_ms = static_cast<u16>(std::clamp<int>(wrap.EntryBitfield(section, "StretchSeekWindowMS", DEFAULT_STRETCH_SEEKWINDOW), 0, std::numeric_limits<u16>::max()));
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
#define ipumsk( src ) ( (src) & 0xff )
|
||||
#define ipucase( src ) case ipumsk(src)
|
||||
|
||||
#define IPU_INT_TO( cycles ) if(!(cpuRegs.interrupt & (1<<4))) CPU_INT( DMAC_TO_IPU, cycles )
|
||||
#define IPU_INT_TO( cycles ) if (!(cpuRegs.interrupt & (1<<4))) CPU_INT( DMAC_TO_IPU, cycles )
|
||||
#define IPU_INT_FROM( cycles ) CPU_INT( DMAC_FROM_IPU, cycles )
|
||||
#define IPU_INT_PROCESS( cycles ) if(!(cpuRegs.interrupt & (1 << IPU_PROCESS))) CPU_INT( IPU_PROCESS, cycles )
|
||||
#define IPU_INT_PROCESS( cycles ) if (!(cpuRegs.interrupt & (1 << IPU_PROCESS))) CPU_INT( IPU_PROCESS, cycles )
|
||||
//
|
||||
// Bitfield Structures
|
||||
//
|
||||
|
||||
@@ -203,10 +203,10 @@ namespace FullscreenUI
|
||||
Graphics,
|
||||
Audio,
|
||||
MemoryCard,
|
||||
Folders,
|
||||
Achievements,
|
||||
Controller,
|
||||
Hotkey,
|
||||
Achievements,
|
||||
Folders,
|
||||
Advanced,
|
||||
Patches,
|
||||
Cheats,
|
||||
@@ -322,10 +322,10 @@ namespace FullscreenUI
|
||||
static void DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_advanced_settings);
|
||||
static void DrawAudioSettingsPage();
|
||||
static void DrawMemoryCardSettingsPage();
|
||||
static void DrawFoldersSettingsPage();
|
||||
static void DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& settings_lock);
|
||||
static void DrawControllerSettingsPage();
|
||||
static void DrawHotkeySettingsPage();
|
||||
static void DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& settings_lock);
|
||||
static void DrawFoldersSettingsPage();
|
||||
static void DrawAdvancedSettingsPage();
|
||||
static void DrawPatchesOrCheatsSettingsPage(bool cheats);
|
||||
static void DrawGameFixesSettingsPage();
|
||||
@@ -613,7 +613,7 @@ void FullscreenUI::ApplyLayoutSettings(const SettingsInterface* bsi)
|
||||
|
||||
const InputLayout layout = ImGuiFullscreen::GetGamepadLayout();
|
||||
|
||||
if (sdl2_nintendo_mode == "true" || (sdl2_nintendo_mode == "auto") && layout == InputLayout::Nintendo)
|
||||
if ((sdl2_nintendo_mode == "true" || sdl2_nintendo_mode == "auto") && layout == InputLayout::Nintendo)
|
||||
{
|
||||
// Apply
|
||||
ImGuiManager::SwapGamepadNorthWest(true);
|
||||
@@ -3067,10 +3067,10 @@ void FullscreenUI::DrawSettingsWindow()
|
||||
ICON_PF_PICTURE,
|
||||
ICON_PF_SOUND,
|
||||
ICON_PF_MEMORY_CARD,
|
||||
ICON_FA_FOLDER_OPEN,
|
||||
ICON_FA_TROPHY,
|
||||
ICON_PF_GAMEPAD_ALT,
|
||||
ICON_PF_KEYBOARD_ALT,
|
||||
ICON_FA_TROPHY,
|
||||
ICON_FA_FOLDER_OPEN,
|
||||
ICON_FA_EXCLAMATION_TRIANGLE,
|
||||
};
|
||||
static constexpr const char* per_game_icons[] = {
|
||||
@@ -3090,10 +3090,10 @@ void FullscreenUI::DrawSettingsWindow()
|
||||
SettingsPage::Graphics,
|
||||
SettingsPage::Audio,
|
||||
SettingsPage::MemoryCard,
|
||||
SettingsPage::Folders,
|
||||
SettingsPage::Achievements,
|
||||
SettingsPage::Controller,
|
||||
SettingsPage::Hotkey,
|
||||
SettingsPage::Achievements,
|
||||
SettingsPage::Folders,
|
||||
SettingsPage::Advanced,
|
||||
};
|
||||
static constexpr SettingsPage per_game_pages[] = {
|
||||
@@ -3114,10 +3114,10 @@ void FullscreenUI::DrawSettingsWindow()
|
||||
FSUI_NSTR("Graphics Settings"),
|
||||
FSUI_NSTR("Audio Settings"),
|
||||
FSUI_NSTR("Memory Card Settings"),
|
||||
FSUI_NSTR("Folder Settings"),
|
||||
FSUI_NSTR("Achievements Settings"),
|
||||
FSUI_NSTR("Controller Settings"),
|
||||
FSUI_NSTR("Hotkey Settings"),
|
||||
FSUI_NSTR("Achievements Settings"),
|
||||
FSUI_NSTR("Folder Settings"),
|
||||
FSUI_NSTR("Advanced Settings"),
|
||||
FSUI_NSTR("Patches"),
|
||||
FSUI_NSTR("Cheats"),
|
||||
@@ -3240,20 +3240,20 @@ void FullscreenUI::DrawSettingsWindow()
|
||||
DrawMemoryCardSettingsPage();
|
||||
break;
|
||||
|
||||
case SettingsPage::Controller:
|
||||
DrawControllerSettingsPage();
|
||||
break;
|
||||
|
||||
case SettingsPage::Hotkey:
|
||||
DrawHotkeySettingsPage();
|
||||
case SettingsPage::Folders:
|
||||
DrawFoldersSettingsPage();
|
||||
break;
|
||||
|
||||
case SettingsPage::Achievements:
|
||||
DrawAchievementsSettingsPage(lock);
|
||||
break;
|
||||
|
||||
case SettingsPage::Folders:
|
||||
DrawFoldersSettingsPage();
|
||||
case SettingsPage::Controller:
|
||||
DrawControllerSettingsPage();
|
||||
break;
|
||||
|
||||
case SettingsPage::Hotkey:
|
||||
DrawHotkeySettingsPage();
|
||||
break;
|
||||
|
||||
case SettingsPage::Patches:
|
||||
@@ -3316,15 +3316,15 @@ void FullscreenUI::DrawSummarySettingsPage()
|
||||
CopyTextToClipboard(FSUI_STR("Game serial copied to clipboard."), s_game_settings_entry->serial);
|
||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_CODE, "CRC"), fmt::format("{:08X}", s_game_settings_entry->crc).c_str(), true))
|
||||
CopyTextToClipboard(FSUI_STR("Game CRC copied to clipboard."), fmt::format("{:08X}", s_game_settings_entry->crc));
|
||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_BOX, "Type"), GameList::EntryTypeToDisplayString(s_game_settings_entry->type), true))
|
||||
CopyTextToClipboard(FSUI_STR("Game type copied to clipboard."), GameList::EntryTypeToDisplayString(s_game_settings_entry->type));
|
||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_GLOBE, "Region"), GameList::RegionToString(s_game_settings_entry->region), true))
|
||||
CopyTextToClipboard(FSUI_STR("Game region copied to clipboard."), GameList::RegionToString(s_game_settings_entry->region));
|
||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_BOX, "Type"), GameList::EntryTypeToString(s_game_settings_entry->type, true), true))
|
||||
CopyTextToClipboard(FSUI_STR("Game type copied to clipboard."), GameList::EntryTypeToString(s_game_settings_entry->type, true));
|
||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_GLOBE, "Region"), GameList::RegionToString(s_game_settings_entry->region, true), true))
|
||||
CopyTextToClipboard(FSUI_STR("Game region copied to clipboard."), GameList::RegionToString(s_game_settings_entry->region, true));
|
||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_STAR, "Compatibility Rating"),
|
||||
GameList::EntryCompatibilityRatingToString(s_game_settings_entry->compatibility_rating), true))
|
||||
GameList::EntryCompatibilityRatingToString(s_game_settings_entry->compatibility_rating, true), true))
|
||||
{
|
||||
CopyTextToClipboard(FSUI_STR("Game compatibility copied to clipboard."),
|
||||
GameList::EntryCompatibilityRatingToString(s_game_settings_entry->compatibility_rating));
|
||||
GameList::EntryCompatibilityRatingToString(s_game_settings_entry->compatibility_rating, true));
|
||||
}
|
||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_FOLDER_OPEN, "Path"), s_game_settings_entry->path.c_str(), true))
|
||||
CopyTextToClipboard(FSUI_STR("Game path copied to clipboard."), s_game_settings_entry->path);
|
||||
@@ -3559,7 +3559,7 @@ void FullscreenUI::DrawInterfaceSettingsPage()
|
||||
|
||||
MenuHeading(FSUI_CSTR("Integration"));
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_USER_CIRCLE, "Enable Discord Presence"),
|
||||
FSUI_CSTR("Shows the game you are currently playing as part of your profile on Discord."), "UI", "DiscordPresence", false);
|
||||
FSUI_CSTR("Shows the game you are currently playing as part of your profile on Discord."), "EmuCore", "EnableDiscordPresence", false);
|
||||
|
||||
MenuHeading(FSUI_CSTR("Game Display"));
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_TV, "Start Fullscreen"),
|
||||
@@ -5738,9 +5738,12 @@ u32 FullscreenUI::PopulateSaveStateListEntries(const std::string& title, const s
|
||||
if (InitializeSaveStateListEntry(&li, title, serial, crc, i) || !s_save_state_selector_loading)
|
||||
s_save_state_selector_slots.push_back(std::move(li));
|
||||
|
||||
SaveStateListEntry bli;
|
||||
if (InitializeSaveStateListEntry(&bli, title, serial, crc, i, true) || !s_save_state_selector_loading)
|
||||
s_save_state_selector_slots.push_back(std::move(bli));
|
||||
if (s_save_state_selector_loading)
|
||||
{
|
||||
SaveStateListEntry bli;
|
||||
if (InitializeSaveStateListEntry(&bli, title, serial, crc, i, true))
|
||||
s_save_state_selector_slots.push_back(std::move(bli));
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<u32>(s_save_state_selector_slots.size());
|
||||
@@ -6456,9 +6459,9 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
||||
|
||||
summary.clear();
|
||||
if (entry->serial.empty())
|
||||
fmt::format_to(std::back_inserter(summary), "{} - ", GameList::RegionToString(entry->region));
|
||||
fmt::format_to(std::back_inserter(summary), "{} - ", GameList::RegionToString(entry->region, true));
|
||||
else
|
||||
fmt::format_to(std::back_inserter(summary), "{} - {} - ", entry->serial, GameList::RegionToString(entry->region));
|
||||
fmt::format_to(std::back_inserter(summary), "{} - {} - ", entry->serial, GameList::RegionToString(entry->region, true));
|
||||
|
||||
const std::string_view filename(Path::GetFileName(entry->path));
|
||||
summary.append(filename);
|
||||
@@ -6560,12 +6563,12 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
||||
|
||||
// region
|
||||
{
|
||||
std::string flag_texture(fmt::format("icons/flags/{}.svg", GameList::RegionToString(selected_entry->region)));
|
||||
std::string flag_texture(fmt::format("icons/flags/{}.svg", GameList::RegionToString(selected_entry->region, false)));
|
||||
ImGui::TextUnformatted(FSUI_CSTR("Region: "));
|
||||
ImGui::SameLine();
|
||||
DrawCachedSvgTextureAsync(flag_texture, LayoutScale(23.0f, 16.0f), SvgScaling::Fit);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(" (%s)", GameList::RegionToString(selected_entry->region));
|
||||
ImGui::Text(" (%s)", GameList::RegionToString(selected_entry->region, true));
|
||||
}
|
||||
|
||||
// compatibility
|
||||
@@ -6576,7 +6579,7 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
||||
DrawSvgTexture(s_game_compatibility_textures[static_cast<u32>(selected_entry->compatibility_rating) - 1].get(), LayoutScale(64.0f, 16.0f));
|
||||
ImGui::SameLine();
|
||||
}
|
||||
ImGui::Text(" (%s)", GameList::EntryCompatibilityRatingToString(selected_entry->compatibility_rating));
|
||||
ImGui::Text(" (%s)", GameList::EntryCompatibilityRatingToString(selected_entry->compatibility_rating, true));
|
||||
|
||||
// play time
|
||||
ImGui::TextUnformatted(
|
||||
@@ -7302,7 +7305,7 @@ void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& se
|
||||
};
|
||||
OpenFileSelector(FSUI_ICONSTR(ICON_FA_FOLDER_OPEN, "Select Leaderboard Submit Sound"), false, std::move(callback), GetAudioFileFilters());
|
||||
}
|
||||
|
||||
|
||||
MenuHeading(FSUI_CSTR("Account"));
|
||||
if (bsi->ContainsValue("Achievements", "Token"))
|
||||
{
|
||||
@@ -7897,10 +7900,10 @@ TRANSLATE_NOOP("FullscreenUI", "Emulation Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Graphics Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Audio Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Memory Card Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Folder Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Achievements Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Controller Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Hotkey Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Achievements Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Folder Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Advanced Settings");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Patches");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Cheats");
|
||||
|
||||
@@ -394,6 +394,8 @@ __ri void ImGuiManager::DrawSettingsOverlay(float scale, float margin, float spa
|
||||
APPEND("IVU ");
|
||||
if (EmuConfig.Speedhacks.vuThread)
|
||||
APPEND("MTVU ");
|
||||
if (EmuConfig.GS.VsyncEnable)
|
||||
APPEND("VSYNC ");
|
||||
|
||||
APPEND("EER={} EEC={} VUR={} VUC={} VQS={} ", static_cast<unsigned>(EmuConfig.Cpu.FPUFPCR.GetRoundMode()),
|
||||
EmuConfig.Cpu.Recompiler.GetEEClampMode(), static_cast<unsigned>(EmuConfig.Cpu.VU0FPCR.GetRoundMode()),
|
||||
|
||||
@@ -1615,7 +1615,7 @@ void InputManager::CloseSources()
|
||||
{
|
||||
for (u32 i = FIRST_EXTERNAL_INPUT_SOURCE; i < LAST_EXTERNAL_INPUT_SOURCE; i++)
|
||||
{
|
||||
if (s_input_sources[i]->IsInitialized())
|
||||
if (s_input_sources[i] && s_input_sources[i]->IsInitialized())
|
||||
{
|
||||
s_input_sources[i]->Shutdown();
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ static void execI()
|
||||
#if 0
|
||||
static long int print_me = 0;
|
||||
// Based on cycle
|
||||
// if( cpuRegs.cycle > 0x4f24d714 )
|
||||
// if ( cpuRegs.cycle > 0x4f24d714 )
|
||||
// Or dump from a particular PC (useful to debug handler/syscall)
|
||||
if (pc == 0x80000000)
|
||||
{
|
||||
|
||||
@@ -641,7 +641,7 @@ namespace R3000A
|
||||
|
||||
for (size_t i = 0; i < handles.size(); i++)
|
||||
{
|
||||
if (handles[i].fd_index == (u32) fd - firstfd)
|
||||
if (handles[i].fd_index == (u32)fd - firstfd)
|
||||
{
|
||||
handles.erase(handles.begin() + i);
|
||||
break;
|
||||
@@ -951,8 +951,12 @@ namespace R3000A
|
||||
if (!ConsoleLogging.iopConsole.IsActive())
|
||||
return 1;
|
||||
|
||||
char tmp[1024], tmp2[1024];
|
||||
// maximum allowed size for our buffer before we truncate
|
||||
const unsigned int max_len = 4096;
|
||||
char tmp[max_len], tmp2[max_len];
|
||||
char* ptmp = tmp;
|
||||
unsigned int printed_bytes = 0;
|
||||
unsigned int remaining_buf = max_len - 1;
|
||||
int n = 1, i = 0, j = 0;
|
||||
|
||||
while (fmt[i])
|
||||
@@ -963,21 +967,32 @@ namespace R3000A
|
||||
j = 0;
|
||||
tmp2[j++] = '%';
|
||||
_start:
|
||||
switch (fmt[++i])
|
||||
// let's check whether this is our null terminator
|
||||
// before allowing the parser to proceed
|
||||
if (fmt[i + 1])
|
||||
{
|
||||
case '.':
|
||||
case 'l':
|
||||
tmp2[j++] = fmt[i];
|
||||
goto _start;
|
||||
default:
|
||||
if (fmt[i] >= '0' && fmt[i] <= '9')
|
||||
{
|
||||
switch (fmt[++i])
|
||||
{
|
||||
case '.':
|
||||
case 'l':
|
||||
if (j >= max_len)
|
||||
break;
|
||||
tmp2[j++] = fmt[i];
|
||||
goto _start;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (fmt[i] >= '0' && fmt[i] <= '9')
|
||||
{
|
||||
if (j >= max_len)
|
||||
break;
|
||||
tmp2[j++] = fmt[i];
|
||||
goto _start;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j >= max_len)
|
||||
break;
|
||||
tmp2[j++] = fmt[i];
|
||||
tmp2[j] = 0;
|
||||
|
||||
@@ -985,7 +1000,9 @@ namespace R3000A
|
||||
{
|
||||
case 'f':
|
||||
case 'F':
|
||||
ptmp += sprintf(ptmp, tmp2, (float)iopMemRead32(sp + n * 4));
|
||||
printed_bytes = snprintf(ptmp, remaining_buf, tmp2, (float)iopMemRead32(sp + n * 4));
|
||||
remaining_buf -= printed_bytes;
|
||||
ptmp += printed_bytes;
|
||||
n++;
|
||||
break;
|
||||
|
||||
@@ -995,7 +1012,9 @@ namespace R3000A
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
ptmp += sprintf(ptmp, tmp2, (double)iopMemRead32(sp + n * 4));
|
||||
printed_bytes = snprintf(ptmp, remaining_buf, tmp2, (double)iopMemRead32(sp + n * 4));
|
||||
remaining_buf -= printed_bytes;
|
||||
ptmp += printed_bytes;
|
||||
n++;
|
||||
break;
|
||||
|
||||
@@ -1007,19 +1026,27 @@ namespace R3000A
|
||||
case 'O':
|
||||
case 'x':
|
||||
case 'X':
|
||||
ptmp += sprintf(ptmp, tmp2, (u32)iopMemRead32(sp + n * 4));
|
||||
case 'u':
|
||||
case 'U':
|
||||
printed_bytes = snprintf(ptmp, remaining_buf, tmp2, (u32)iopMemRead32(sp + n * 4));
|
||||
remaining_buf -= printed_bytes;
|
||||
ptmp += printed_bytes;
|
||||
n++;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
ptmp += sprintf(ptmp, tmp2, (u8)iopMemRead32(sp + n * 4));
|
||||
printed_bytes = snprintf(ptmp, remaining_buf, tmp2, (u8)iopMemRead32(sp + n * 4));
|
||||
remaining_buf -= printed_bytes;
|
||||
ptmp += printed_bytes;
|
||||
n++;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
{
|
||||
std::string s = iopMemReadString(iopMemRead32(sp + n * 4));
|
||||
ptmp += sprintf(ptmp, tmp2, s.data());
|
||||
printed_bytes = snprintf(ptmp, remaining_buf, tmp2, s.data());
|
||||
remaining_buf -= printed_bytes;
|
||||
ptmp += printed_bytes;
|
||||
n++;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define G_GC(reg)
|
||||
#endif
|
||||
|
||||
#define SUM_FLAG if(gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000;
|
||||
#define SUM_FLAG if (gteFLAG & 0x7F87E000) gteFLAG |= 0x80000000;
|
||||
|
||||
#ifdef _MSC_VER_
|
||||
#pragma warning(disable:4244)
|
||||
|
||||
@@ -356,7 +356,7 @@ void ba0W16(u32 mem, u16 value)
|
||||
s_ba_command_executing = true;
|
||||
s_ba_error_detected = false;
|
||||
}
|
||||
else if(s_ba[0x2] == 0x42) // Read Mode
|
||||
else if (s_ba[0x2] == 0x42) // Read Mode
|
||||
{
|
||||
int size = (s_ba[masked_mem] & 0xF);
|
||||
|
||||
@@ -406,7 +406,7 @@ u16 ba0R16(u32 mem)
|
||||
|
||||
void MyMemCheck(u32 mem)
|
||||
{
|
||||
if( mem == 0x1c02f2a0 )
|
||||
if ( mem == 0x1c02f2a0 )
|
||||
Console.WriteLn("yo; (mem == 0x1c02f2a0) in MyMemCheck...");
|
||||
}
|
||||
|
||||
|
||||
@@ -1898,6 +1898,7 @@ Pcsx2Config::Pcsx2Config()
|
||||
UseSavestateSelector = true;
|
||||
BackupSavestate = true;
|
||||
WarnAboutUnsafeSettings = true;
|
||||
EnableDiscordPresence = false;
|
||||
ManuallySetRealTimeClock = false;
|
||||
|
||||
// To be moved to FileMemoryCard pluign (someday)
|
||||
@@ -2083,17 +2084,16 @@ void Pcsx2Config::ClearInvalidPerGameConfiguration(SettingsInterface* si)
|
||||
void EmuFolders::SetAppRoot()
|
||||
{
|
||||
std::string program_path = FileSystem::GetProgramPath();
|
||||
Console.WriteLnFmt("Program Path: {}", program_path);
|
||||
AppRoot = Path::Canonicalize(Path::GetDirectory(program_path));
|
||||
#ifdef __APPLE__
|
||||
const auto bundle_path = CocoaTools::GetNonTranslocatedBundlePath();
|
||||
if (bundle_path.has_value())
|
||||
{
|
||||
// On macOS, override with the bundle path if launched from a bundle.
|
||||
program_path = bundle_path.value();
|
||||
AppRoot = StringUtil::EndsWithNoCase(*bundle_path, ".app") ? Path::GetDirectory(*bundle_path) : *bundle_path;
|
||||
}
|
||||
#endif
|
||||
Console.WriteLnFmt("Program Path: {}", program_path);
|
||||
|
||||
AppRoot = Path::Canonicalize(Path::GetDirectory(program_path));
|
||||
|
||||
// logging of directories in case something goes wrong super early
|
||||
Console.WriteLnFmt("AppRoot Directory: {}", AppRoot);
|
||||
@@ -2110,8 +2110,10 @@ bool EmuFolders::SetResourcesDirectory()
|
||||
#endif
|
||||
#else
|
||||
// On macOS, this is in the bundle resources directory.
|
||||
const std::string program_path = FileSystem::GetProgramPath();
|
||||
Resources = Path::Canonicalize(Path::Combine(Path::GetDirectory(program_path), "../Resources"));
|
||||
if (auto resources = CocoaTools::GetResourcePath())
|
||||
Resources = *resources;
|
||||
else
|
||||
Resources = Path::Combine(AppRoot, "resources");
|
||||
#endif
|
||||
|
||||
Console.WriteLnFmt("Resources Directory: {}", Resources);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user