Compare commits
200 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbe20c0eed | ||
|
|
ec288ffa62 | ||
|
|
7e18c02c7e | ||
|
|
4a505cc239 | ||
|
|
35c81106c6 | ||
|
|
1094222d3f | ||
|
|
065d0db4c9 | ||
|
|
bc51537080 | ||
|
|
b7dfcb282b | ||
|
|
78a9411766 | ||
|
|
4724f67596 | ||
|
|
e0851bb86f | ||
|
|
08e68d9563 | ||
|
|
0b6dccae51 | ||
|
|
60adfd5046 | ||
|
|
3e782d355d | ||
|
|
22a7324b69 | ||
|
|
f3b4c50909 | ||
|
|
a45f27e6e9 | ||
|
|
2f84bf0cca | ||
|
|
3e2c3e5075 | ||
|
|
154259d0a6 | ||
|
|
7d2d05ff59 | ||
|
|
f7c587c9a8 | ||
|
|
9162b30b18 | ||
|
|
14cfe37c8b | ||
|
|
a27a0ab49d | ||
|
|
0742fe07ec | ||
|
|
65a92470d3 | ||
|
|
10dc1a2da2 | ||
|
|
aad2128c32 | ||
|
|
2640678cac | ||
|
|
8b90e2d53d | ||
|
|
f87175dc7f | ||
|
|
b30444c0d0 | ||
|
|
c1da0caf15 | ||
|
|
c4a8fc5b71 | ||
|
|
8eb46b5a4c | ||
|
|
8be16d1039 | ||
|
|
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 | ||
|
|
777bf338fa | ||
|
|
3ba8d9ebff | ||
|
|
db5384e19c | ||
|
|
fd3984287b | ||
|
|
31dbea4e0b | ||
|
|
0992e784f1 | ||
|
|
c59cc1fbb7 | ||
|
|
903edc79f7 | ||
|
|
4c94c69f02 | ||
|
|
4c57c214bd | ||
|
|
1cbeea3016 | ||
|
|
0d18738192 | ||
|
|
1e7c7db29b | ||
|
|
7c098a2665 | ||
|
|
3ab539be1e | ||
|
|
b46d5e4efc |
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)
|
||||
2
.github/ISSUE_TEMPLATE/app_bug_report.yaml
vendored
@@ -70,6 +70,8 @@ body:
|
||||
- Windows 11
|
||||
- Windows 10 (64bit)
|
||||
- Linux (64bit) - Specify distro below
|
||||
- macOS 26 (Tahoe)
|
||||
- macOS 15 (Sequoia)
|
||||
- macOS 14 (Sonoma)
|
||||
- macOS 13 (Ventura)
|
||||
- macOS 12 (Monterey)
|
||||
|
||||
10
.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
|
||||
@@ -83,6 +87,8 @@ body:
|
||||
- Windows 11
|
||||
- Windows 10 (64bit)
|
||||
- Linux (64bit) - Specify distro below
|
||||
- macOS 26 (Tahoe)
|
||||
- macOS 15 (Sequoia)
|
||||
- macOS 14 (Sonoma)
|
||||
- macOS 13 (Ventura)
|
||||
- macOS 12 (Monterey)
|
||||
@@ -100,14 +106,14 @@ body:
|
||||
id: cpu
|
||||
attributes:
|
||||
label: CPU
|
||||
placeholder: "Example: i5-7600"
|
||||
placeholder: "Example: Intel i5 12400F"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: gpu
|
||||
attributes:
|
||||
label: GPU
|
||||
placeholder: "Example: GTX 1070"
|
||||
placeholder: "Example: Nvidia RTX 4060"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
|
||||
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. -->
|
||||
|
||||
57
.github/workflows/cron_publish_flatpak.yml
vendored
@@ -6,36 +6,45 @@ on:
|
||||
workflow_dispatch: # As well as manually.
|
||||
|
||||
jobs:
|
||||
check:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Check if release is needed"
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 180
|
||||
outputs:
|
||||
PCSX2_RELEASE: ${{ steps.getinfo.outputs.PCSX2_RELEASE }}
|
||||
FLATHUB_RELEASE: ${{ steps.getinfo.outputs.FLATHUB_RELEASE }}
|
||||
steps:
|
||||
- name: Get latest tag and Flathub release
|
||||
id: getinfo
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
PCSX2_RELEASE=$(gh api -H 'Accept: application/vnd.github+json' -H 'X-GitHub-Api-Version: 2022-11-28' /repos/PCSX2/pcsx2/releases | jq -r '.[0].tag_name')
|
||||
FLATHUB_RELEASE=$(curl -L -s https://flathub.org/api/v2/appstream/net.pcsx2.PCSX2 | jq -r '.releases | max_by(.version) | .version')
|
||||
echo "Latest PCSX2 release is: '${PCSX2_RELEASE}'"
|
||||
echo "Latest Flathub release is: '${FLATHUB_RELEASE}'"
|
||||
PCSX2_RELEASE=$(echo $PCSX2_RELEASE | sed 's/[^0-9]*//g')
|
||||
FLATHUB_RELEASE=$(echo $FLATHUB_RELEASE | sed 's/[^0-9]*//g')
|
||||
echo "PCSX2_RELEASE=${PCSX2_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
echo "FLATHUB_RELEASE=${FLATHUB_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# check is disabled as the flathub api does not give us beta repository information
|
||||
# Alternatively we can "flatpak remote-info or parse the appstream directly for the beta repo"
|
||||
# Maybe in the future if we don't want to publish the same version twice if we get no commits
|
||||
# for 24 hours.
|
||||
|
||||
# check:
|
||||
# if: github.repository == 'PCSX2/pcsx2'
|
||||
# name: "Check if release is needed"
|
||||
# runs-on: ubuntu-latest
|
||||
# timeout-minutes: 180
|
||||
# outputs:
|
||||
# PCSX2_RELEASE: ${{ steps.getinfo.outputs.PCSX2_RELEASE }}
|
||||
# FLATHUB_RELEASE: ${{ steps.getinfo.outputs.FLATHUB_RELEASE }}
|
||||
# steps:
|
||||
# - name: Get latest tag and Flathub release
|
||||
# id: getinfo
|
||||
# env:
|
||||
# GH_TOKEN: ${{ github.token }}
|
||||
# run: |
|
||||
# PCSX2_RELEASE=$(gh api -H 'Accept: application/vnd.github+json' -H 'X-GitHub-Api-Version: 2022-11-28' /repos/PCSX2/pcsx2/releases | jq -r '.[0].tag_name')
|
||||
# FLATHUB_RELEASE=$(curl -L -s https://flathub.org/api/v2/appstream/net.pcsx2.PCSX2 | jq -r '.releases | max_by(.version) | .version')
|
||||
# echo "Latest PCSX2 release is: '${PCSX2_RELEASE}'"
|
||||
# echo "Latest Flathub release is: '${FLATHUB_RELEASE}'"
|
||||
# PCSX2_RELEASE=$(echo $PCSX2_RELEASE | sed 's/[^0-9]*//g')
|
||||
# FLATHUB_RELEASE=$(echo $FLATHUB_RELEASE | sed 's/[^0-9]*//g')
|
||||
# echo "PCSX2_RELEASE=${PCSX2_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
# echo "FLATHUB_RELEASE=${FLATHUB_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
needs: check
|
||||
# needs: check
|
||||
# outputs are automatically compared as strings. This doesn't work in our favour
|
||||
# Use fromJson() to convert them to proper integers...
|
||||
# see: https://github.com/github/docs/pull/25870
|
||||
# and: https://github.com/orgs/community/discussions/57480
|
||||
#if: fromJson(needs.check.outputs.FLATHUB_RELEASE) < fromJson(needs.check.outputs.PCSX2_RELEASE)
|
||||
|
||||
# if: fromJson(needs.check.outputs.FLATHUB_RELEASE) < fromJson(needs.check.outputs.PCSX2_RELEASE)
|
||||
# As the check step is disabled, perform repository check here
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Build and publish Flatpak"
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
|
||||
17
.github/workflows/linux_build_flatpak.yml
vendored
@@ -54,19 +54,16 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
set-safe-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||
# 10 here, since the odds of having 10 untagged commits in a row should be slim to none
|
||||
# This is required for the tagging logic in generate-metainfo.sh
|
||||
fetch-depth: 10
|
||||
fetch-tags: true
|
||||
|
||||
# Work around container ownership issue
|
||||
- name: Set Safe Directory
|
||||
shell: bash
|
||||
run: git config --global --add safe.directory "*"
|
||||
|
||||
# Hackity hack. When running the workflow on a schedule, we don't have the tag,
|
||||
# it doesn't fetch tags, therefore we don't get a version. So grab them manually.
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch tags
|
||||
if: ${{ inputs.fetchTags }}
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Add stable release identifier file
|
||||
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
|
||||
shell: bash
|
||||
@@ -125,14 +122,14 @@ jobs:
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} flatpak ${{ hashFiles('.github/workflows/scripts/linux/flatpak/**/*.json') }}
|
||||
|
||||
|
||||
#- name: Validate build
|
||||
# run: |
|
||||
# flatpak-builder-lint repo repo
|
||||
|
||||
- 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 +138,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
|
||||
|
||||
2
.github/workflows/linux_build_qt.yml
vendored
@@ -140,9 +140,11 @@ jobs:
|
||||
-DCMAKE_CXX_COMPILER=clang++-17 \
|
||||
-DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" \
|
||||
-DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DENABLE_SETCAP=OFF \
|
||||
-DDISABLE_ADVANCE_SIMD=TRUE \
|
||||
-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \
|
||||
$ADDITIONAL_CMAKE_ARGS
|
||||
|
||||
- name: Build PCSX2
|
||||
|
||||
@@ -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": [
|
||||
|
||||
@@ -12,12 +12,24 @@ GIT_DATE=$(git log -1 --pretty=%cd --date=iso8601)
|
||||
GIT_VERSION=$(git tag --points-at HEAD)
|
||||
GIT_HASH=$(git rev-parse HEAD)
|
||||
|
||||
if [[ "${GIT_VERSION}" == "" ]]; then
|
||||
# In the odd event that we run this script before the release gets tagged.
|
||||
GIT_VERSION=$(git describe --tags)
|
||||
if [[ "${GIT_VERSION}" == "" ]]; then
|
||||
GIT_VERSION=$(git rev-parse HEAD)
|
||||
fi
|
||||
if [[ -z "${GIT_VERSION}" ]]; then
|
||||
if git branch -r --contains HEAD | grep -q 'origin/master'; then
|
||||
# Our master doesn't have a tagged commit
|
||||
# This happens when the commit is "ci skip"
|
||||
# abbrev so we have just the latest tag
|
||||
# ie v2.3.420 (Yes, that's the current master at the time of writing)
|
||||
GIT_VERSION=$(git describe --tags --abbrev=0)
|
||||
else
|
||||
# We are probably building a PR
|
||||
# Keep the short SHA in the version
|
||||
# ie v2.3.420-1-g10dc1a2da
|
||||
GIT_VERSION=$(git describe --tags)
|
||||
fi
|
||||
|
||||
if [[ -z "${GIT_VERSION}" ]]; then
|
||||
# Fallback to raw commit hash
|
||||
GIT_VERSION=$(git rev-parse HEAD)
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "GIT_DATE: ${GIT_DATE}"
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<li><a href="#googletest">GoogleTest</a></li>
|
||||
<li><a href="#harfbuzz">HarfBuzz</a></li>
|
||||
<li><a href="#jsonformoderncpp">JSON for Modern C++</a></li>
|
||||
<li><a href="#kdbindings">KDBindings</a></li>
|
||||
<li><a href="#kddockwidgets">KDDockWidgets</a></li>
|
||||
<li><a href="#kissfft">kissfft</a></li>
|
||||
<li><a href="#libbacktrace">libbacktrace</a></li>
|
||||
@@ -1910,6 +1911,7 @@ PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<!-- Transitive dependency of KDDockWidgets. -->
|
||||
<div id="jsonformoderncpp">
|
||||
<h3>JSON for Modern C++ - <a href="https://json.nlohmann.me">https://json.nlohmann.me</a></h3>
|
||||
<pre>
|
||||
@@ -1937,6 +1939,34 @@ SOFTWARE.
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<!-- Transitive dependency of KDDockWidgets. -->
|
||||
<div id="kdbindings">
|
||||
<h3>KDBindings - <a href="https://github.com/KDAB/KDBindings">https://github.com/KDAB/KDBindings</a></h3>
|
||||
<pre>
|
||||
MIT License
|
||||
|
||||
Copyright 2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||
Copyright 2021 Jeremy Burns
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div id="kddockwidgets">
|
||||
<h3>KDDockWidgets - <a href="https://github.com/KDAB/KDDockWidgets">https://github.com/KDAB/KDDockWidgets</a></h3>
|
||||
<pre>
|
||||
|
||||
|
Before Width: | Height: | Size: 38 KiB |
41
bin/resources/fullscreenui/applications-system.svg
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
|
||||
<svg
|
||||
fill="#000000"
|
||||
width="800px"
|
||||
height="800px"
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
sodipodi:docname="applications-system.svg"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#ffffff"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="1"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="0.97875"
|
||||
inkscape:cx="399.48914"
|
||||
inkscape:cy="400"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1010"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<defs
|
||||
id="defs1" />
|
||||
<path
|
||||
d="M30.015 12.97l-2.567-0.569c-0.2-0.64-0.462-1.252-0.762-1.841l1.389-2.313c0.518-0.829 0.78-2.047 0-2.829l-1.415-1.414c-0.78-0.781-2.098-0.64-2.894-0.088l-2.251 1.434c-0.584-0.303-1.195-0.563-1.829-0.768l-0.576-2.598c-0.172-0.953-1.005-1.984-2.11-1.984h-2c-1.104 0-1.781 1.047-2 2l-0.642 2.567c-0.678 0.216-1.328 0.492-1.948 0.819l-2.308-1.47c-0.795-0.552-2.114-0.692-2.894 0.088l-1.415 1.414c-0.781 0.782-0.519 2 0 2.828l1.461 2.435c-0.274 0.552-0.517 1.123-0.705 1.72l-2.566 0.569c-0.953 0.171-1.984 1.005-1.984 2.109v2c0 1.105 1.047 1.782 2 2l2.598 0.649c0.179 0.551 0.404 1.080 0.658 1.593l-1.462 2.438c-0.518 0.828-0.78 2.047 0 2.828l1.415 1.414c0.78 0.782 2.098 0.64 2.894 0.089l2.313-1.474c0.623 0.329 1.277 0.608 1.96 0.823l0.64 2.559c0.219 0.953 0.896 2 2 2h2c1.105 0 1.938-1.032 2.11-1.985l0.577-2.604c0.628-0.203 1.23-0.459 1.808-0.758l2.256 1.438c0.796 0.552 2.114 0.692 2.895-0.089l1.415-1.414c0.78-0.782 0.518-2 0-2.828l-1.39-2.317c0.279-0.549 0.521-1.12 0.716-1.714l2.599-0.649c0.953-0.219 2-0.895 2-2v-2c0-1.104-1.031-1.938-1.985-2.11zM30.001 16.939c-0.085 0.061-0.245 0.145-0.448 0.192l-3.708 0.926-0.344 1.051c-0.155 0.474-0.356 0.954-0.597 1.428l-0.502 0.986 1.959 3.267c0.125 0.2 0.183 0.379 0.201 0.485l-1.316 1.314c-0.127-0.040-0.271-0.092-0.341-0.14l-3.292-2.099-1.023 0.529c-0.493 0.256-0.999 0.468-1.503 0.631l-1.090 0.352-0.824 3.723c-0.038 0.199-0.145 0.36-0.218 0.417h-1.8c-0.061-0.085-0.145-0.245-0.191-0.448l-0.921-3.681-1.066-0.338c-0.549-0.173-1.097-0.404-1.63-0.684l-1.028-0.543-3.293 2.099c-0.135 0.091-0.279 0.143-0.409 0.143l-1.311-1.276c0.018-0.104 0.072-0.274 0.181-0.449l2.045-3.408-0.487-0.98c-0.227-0.462-0.407-0.895-0.547-1.325l-0.343-1.052-3.671-0.918c-0.231-0.052-0.398-0.139-0.485-0.2v-1.86c0.001 0.001 0.002 0.001 0.005 0.001 0.034 0 0.198-0.117 0.335-0.142l3.772-0.835 0.346-1.103c0.141-0.449 0.333-0.917 0.588-1.43l0.487-0.98-2.024-3.373c-0.125-0.201-0.184-0.38-0.201-0.485l1.315-1.314c0.128 0.041 0.271 0.093 0.34 0.14l3.354 2.138 1.027-0.542c0.527-0.278 1.073-0.507 1.622-0.682l1.063-0.338 0.912-3.649c0.053-0.231 0.138-0.398 0.2-0.485h1.859c-0.014 0.020 0.115 0.195 0.142 0.339l0.84 3.794 1.089 0.352c0.511 0.165 1.023 0.38 1.523 0.639l1.023 0.532 3.224-2.053c0.135-0.092 0.279-0.143 0.409-0.143l1.313 1.276c-0.017 0.104-0.072 0.276-0.181 0.45l-1.98 3.296 0.505 0.988c0.273 0.533 0.48 1.033 0.635 1.529l0.346 1.104 3.697 0.82c0.224 0.041 0.398 0.171 0.434 0.241zM16.013 9.99c-3.321 0-6.023 2.697-6.023 6.010s2.702 6.010 6.023 6.010 6.023-2.697 6.023-6.009c0-3.313-2.702-6.010-6.023-6.010zM16 20c-2.205 0-4-1.794-4-4s1.794-4 4-4c2.206 0 4 1.794 4 4s-1.794 4-4 4z"
|
||||
id="path1"
|
||||
style="fill:#ffffff" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
7
bin/resources/fullscreenui/back-icon.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg fill="#ffffff" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800px" height="800px" viewBox="0 0 72 72" enable-background="new 0 0 72 72" xml:space="preserve">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 13 KiB |
7
bin/resources/fullscreenui/desktop-mode.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg fill="#ffffff" width="800px" height="800px" viewBox="0 0 16 16" id="window-16px" xmlns="http://www.w3.org/2000/svg">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 19 KiB |
7
bin/resources/fullscreenui/drive-cdrom.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg fill="#ffffff" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" xml:space="preserve">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 27 KiB |
7
bin/resources/fullscreenui/exit.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" id="SVGRoot" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg" fill="#ffffff">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 48 KiB |
7
bin/resources/fullscreenui/game-list.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg height="800px" width="800px" version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" xml:space="preserve" fill="#ffffff">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 100 KiB |
7
bin/resources/fullscreenui/media-cdrom.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg fill="#ffffff" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800px" height="800px" viewBox="0 0 72 72" enable-background="new 0 0 72 72" xml:space="preserve">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 14 KiB |
9
bin/resources/fullscreenui/start-bios.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg fill="#ffffff" width="800px" height="800px" viewBox="-2 -2 24 24" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin" class="jam jam-microchip">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
||||
<g id="SVGRepo_iconCarrier">
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 22 KiB |
7
bin/resources/fullscreenui/start-file.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="800px" height="800px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="#000000">
|
||||
|
||||
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
||||
|
||||
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -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,
|
||||
@@ -467,8 +469,10 @@
|
||||
030000001008000001e5000000000000,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:Windows,
|
||||
03000000050b00000045000000000000,Nexus,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:b10,x:b2,y:b3,platform:Windows,
|
||||
03000000152000000182000000000000,NGDS,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:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
|
||||
030000007e0500006920000000000000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Windows,
|
||||
030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows,
|
||||
030000007e0500007320000000000000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Windows,
|
||||
030000007e0500001920000000000000,NSO N64 Controller,+rightx:b8,+righty:b2,-rightx:b3,-righty:b7,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Windows,
|
||||
030000007e0500001720000000000000,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:Windows,
|
||||
03000000550900001472000000000000,NVIDIA Controller,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows,
|
||||
@@ -484,7 +488,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 +695,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,17 +1002,21 @@ 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,
|
||||
030000007e0500006920000001010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Mac OS X,
|
||||
030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,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:b2,y:b3,platform:Mac OS X,
|
||||
030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,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:b2,y:b3,platform:Mac OS X,
|
||||
030000007e0500000920000010020000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X,
|
||||
050000007e05000009200000ff070000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:Mac OS X,
|
||||
030000007e0500007320000001010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Mac OS X,
|
||||
030000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Mac OS X,
|
||||
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 +1109,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 +1288,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,
|
||||
@@ -1290,6 +1300,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000558500001b06000010010000,GameSir G4 Pro,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:Linux,
|
||||
05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,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,
|
||||
03000000ac0500007a05000011010000,GameSir G5,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000373500009710000001020000,GameSir Kaleid Flux,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,
|
||||
03000000bc2000005656000011010000,GameSir T4w,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:Linux,
|
||||
03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,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,
|
||||
0500000047532047616d657061640000,GameStop Gamepad,a:b0,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:b2,y:b3,platform:Linux,
|
||||
@@ -1475,6 +1486,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux,
|
||||
03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux,
|
||||
030000007e0500006920000011010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Linux,
|
||||
060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
|
||||
060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
|
||||
060000007e0500000820000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
|
||||
@@ -1489,6 +1501,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
|
||||
050000005a1d00000218000003000000,Nokia GC 5000,a:b9,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,
|
||||
030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
|
||||
030000007e0500007320000011010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Linux,
|
||||
030000007e0500001920000011810000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux,
|
||||
050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux,
|
||||
050000007e0500001920000001800000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux,
|
||||
@@ -1600,6 +1613,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,
|
||||
@@ -1765,6 +1780,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,
|
||||
@@ -1795,6 +1811,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,
|
||||
|
||||
@@ -110,48 +110,24 @@ uint ps_convert_rgba8_16bits(PS_INPUT input) : SV_Target0
|
||||
return ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_datm1(PS_INPUT input)
|
||||
void ps_datm1(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
clip(sample_c(input.t).a - 127.5f / 255); // >= 0x80 pass
|
||||
|
||||
output.c = 0;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_datm0(PS_INPUT input)
|
||||
void ps_datm0(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
clip(127.5f / 255 - sample_c(input.t).a); // < 0x80 pass (== 0x80 should not pass)
|
||||
|
||||
output.c = 0;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_datm1_rta_correction(PS_INPUT input)
|
||||
void ps_datm1_rta_correction(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
clip(sample_c(input.t).a - 254.5f / 255); // >= 0x80 pass
|
||||
|
||||
output.c = 0;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_datm0_rta_correction(PS_INPUT input)
|
||||
void ps_datm0_rta_correction(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
clip(254.5f / 255 - sample_c(input.t).a); // < 0x80 pass (== 0x80 should not pass)
|
||||
|
||||
output.c = 0;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_rta_correction(PS_INPUT input)
|
||||
@@ -313,6 +289,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
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -104,7 +104,6 @@ void ps_datm1()
|
||||
{
|
||||
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -307,12 +306,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;
|
||||
@@ -417,6 +419,16 @@ void Host::OnCreateMemoryCardOpenRequested()
|
||||
// noop
|
||||
}
|
||||
|
||||
bool Host::InBatchMode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Host::InNoGUIMode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Host::ShouldPreferHostFileSelector()
|
||||
{
|
||||
return false;
|
||||
@@ -532,7 +544,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 +776,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 +821,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 +865,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 +880,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 +993,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 +1037,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);
|
||||
|
||||
@@ -142,12 +142,12 @@ void DockManager::switchToLayout(DockLayout::Index layout_index, bool blink_tab)
|
||||
layout.thaw();
|
||||
|
||||
int tab_index = static_cast<int>(layout_index);
|
||||
if (m_menu_bar && tab_index >= 0)
|
||||
if (tab_index >= 0 && m_menu_bar)
|
||||
m_menu_bar->onCurrentLayoutChanged(layout_index);
|
||||
}
|
||||
}
|
||||
|
||||
if (blink_tab)
|
||||
if (blink_tab && m_menu_bar)
|
||||
m_menu_bar->startBlink(m_current_layout);
|
||||
}
|
||||
|
||||
@@ -512,7 +512,8 @@ void DockManager::newLayoutClicked()
|
||||
{
|
||||
// The plus button has just been made the current tab, so set it back to the
|
||||
// one corresponding to the current layout again.
|
||||
m_menu_bar->onCurrentLayoutChanged(m_current_layout);
|
||||
if (m_menu_bar)
|
||||
m_menu_bar->onCurrentLayoutChanged(m_current_layout);
|
||||
|
||||
auto name_validator = [this](const QString& name) {
|
||||
return !hasNameConflict(name, DockLayout::INVALID_INDEX);
|
||||
|
||||
@@ -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, {
|
||||
|
||||
@@ -92,7 +92,8 @@ public Q_SLOTS:
|
||||
void refreshGridCovers();
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
private:
|
||||
void loadTableViewColumnVisibilitySettings();
|
||||
|
||||
@@ -43,7 +43,7 @@ void LogWindow::updateSettings()
|
||||
{
|
||||
std::unique_lock lock(s_log_mutex);
|
||||
|
||||
const bool new_enabled = Host::GetBaseBoolSettingValue("Logging", "EnableLogWindow", false) && !QtHost::InNoGUIMode();
|
||||
const bool new_enabled = Host::GetBaseBoolSettingValue("Logging", "EnableLogWindow", false) && !Host::InNoGUIMode();
|
||||
const bool attach_to_main = Host::GetBaseBoolSettingValue("Logging", "AttachLogWindowToMainWindow", true);
|
||||
const bool curr_enabled = Log::IsHostOutputEnabled();
|
||||
|
||||
|
||||
@@ -1130,7 +1130,7 @@ bool MainWindow::shouldHideMainWindow() const
|
||||
// NOTE: We can't use isRenderingToMain() here, because this happens post-fullscreen-switch.
|
||||
return (Host::GetBoolSettingValue("UI", "HideMainWindowWhenRunning", false) && !g_emu_thread->shouldRenderToMain()) ||
|
||||
(g_emu_thread->shouldRenderToMain() && (isRenderingFullscreen() || m_is_temporarily_windowed)) ||
|
||||
QtHost::InNoGUIMode();
|
||||
Host::InNoGUIMode();
|
||||
}
|
||||
|
||||
bool MainWindow::shouldMouseLock() const
|
||||
@@ -1306,7 +1306,7 @@ bool MainWindow::requestShutdown(bool allow_confirm, bool allow_save_to_state, b
|
||||
// reshow the main window during display updates, because otherwise fullscreen transitions and renderer switches
|
||||
// would briefly show and then hide the main window. So instead, we do it on shutdown, here. Except if we're in
|
||||
// batch mode, when we're going to exit anyway.
|
||||
if (!isRenderingToMain() && isHidden() && !QtHost::InBatchMode() && !g_emu_thread->isRunningFullscreenUI())
|
||||
if (!isRenderingToMain() && isHidden() && !Host::InBatchMode() && !g_emu_thread->isRunningFullscreenUI())
|
||||
updateWindowState(true);
|
||||
|
||||
// Clear the VM valid state early. That way we can't do anything in the UI if we take a while to shut down.
|
||||
@@ -2060,7 +2060,7 @@ void MainWindow::onVMStopped()
|
||||
updateInputRecordingActions(false);
|
||||
|
||||
// If we're closing or in batch mode, quit the whole application now.
|
||||
if (m_is_closing || QtHost::InBatchMode())
|
||||
if (m_is_closing || Host::InBatchMode())
|
||||
{
|
||||
quit();
|
||||
return;
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -602,7 +602,7 @@ void Host::CheckForSettingsChanges(const Pcsx2Config& old_config)
|
||||
|
||||
bool EmuThread::shouldRenderToMain() const
|
||||
{
|
||||
return !Host::GetBoolSettingValue("UI", "RenderToSeparateWindow", false) && !QtHost::InNoGUIMode();
|
||||
return !Host::GetBoolSettingValue("UI", "RenderToSeparateWindow", false) && !Host::InNoGUIMode();
|
||||
}
|
||||
|
||||
void EmuThread::toggleSoftwareRendering()
|
||||
@@ -1268,7 +1268,7 @@ void Host::RequestVMShutdown(bool allow_confirm, bool allow_save_state, bool def
|
||||
|
||||
// This will probably call shutdownVM() again, but by the time it runs, we'll have already shut down
|
||||
// and it'll be a noop.
|
||||
if (QtHost::InBatchMode())
|
||||
if (Host::InBatchMode())
|
||||
QMetaObject::invokeMethod(g_main_window, "requestExit", Qt::QueuedConnection, Q_ARG(bool, false));
|
||||
}
|
||||
}
|
||||
@@ -1437,12 +1437,12 @@ void Host::CommitBaseSettingChanges()
|
||||
}
|
||||
}
|
||||
|
||||
bool QtHost::InBatchMode()
|
||||
bool Host::InBatchMode()
|
||||
{
|
||||
return s_batch_mode;
|
||||
}
|
||||
|
||||
bool QtHost::InNoGUIMode()
|
||||
bool Host::InNoGUIMode()
|
||||
{
|
||||
return s_nogui_mode;
|
||||
}
|
||||
|
||||
@@ -245,12 +245,6 @@ namespace QtHost
|
||||
/// Sets the icon theme, based on the current style (light/dark).
|
||||
void SetIconThemeFromStyle();
|
||||
|
||||
/// Sets batch mode (exit after game shutdown).
|
||||
bool InBatchMode();
|
||||
|
||||
/// Sets NoGUI mode (implys batch mode, does not display main window, exits on shutdown).
|
||||
bool InNoGUIMode();
|
||||
|
||||
/// Returns true if the calling thread is the UI thread.
|
||||
bool IsOnUIThread();
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
class Error;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ bool DebugInterface::m_pause_on_entry = false;
|
||||
|
||||
bool DebugInterface::isAlive()
|
||||
{
|
||||
return VMManager::HasValidVM() && g_FrameCount > 0;
|
||||
return VMManager::HasValidVM();
|
||||
}
|
||||
|
||||
bool DebugInterface::isCpuPaused()
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -3996,8 +4034,14 @@ GSState::TextureMinMaxResult GSState::GetTextureMinMax(GIFRegTEX0 TEX0, GIFRegCL
|
||||
// If it's the start of the texture and our little adjustment is all that pushed it over, clamp it to 0.
|
||||
// This stops the border check failing when using repeat but needed less than the full texture
|
||||
// since this was making it take the full texture even though it wasn't needed.
|
||||
if (!clamp_to_tsize && ((m_vt.m_min.t.floor() == GSVector4::zero()).mask() & 0x3) == 0x3)
|
||||
st = st.max(GSVector4::zero());
|
||||
if (!clamp_to_tsize)
|
||||
{
|
||||
const u32 mask = (m_vt.m_min.t.floor() == GSVector4::zero()).mask();
|
||||
if (mask & 1) // X == 0
|
||||
st.x = st.max(GSVector4::zero()).x;
|
||||
if (mask & 2) // Y == 0
|
||||
st.y = st.max(GSVector4::zero()).y;
|
||||
}
|
||||
}
|
||||
|
||||
// draw will get scissored, adjust UVs to suit
|
||||
@@ -4193,7 +4237,10 @@ void GSState::CalcAlphaMinMax(const int tex_alpha_min, const int tex_alpha_max)
|
||||
|
||||
if (IsCoverageAlpha())
|
||||
{
|
||||
min = 128;
|
||||
// HW renderer doesn't currently support AA, so its min is 128.
|
||||
// If we add AA support to the HW renderer, this will need to be changed.
|
||||
// (Will probably only be supported with ROV/FBFetch so we would want to check for that.)
|
||||
min = GSIsHardwareRenderer() ? 128 : 0;
|
||||
max = 128;
|
||||
}
|
||||
else
|
||||
@@ -4556,14 +4603,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";
|
||||
@@ -493,6 +494,7 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int width, int height, i
|
||||
{
|
||||
ERROR_LOG("GS: Memory allocation failure for {}x{} texture. Purging pool and retrying.", size.x, size.y);
|
||||
PurgePool();
|
||||
t = CreateSurface(type, size.x, size.y, levels, format);
|
||||
if (!t)
|
||||
{
|
||||
ERROR_LOG("GS: Memory allocation failure for {}x{} texture after purging pool.", size.x, size.y);
|
||||
|
||||
@@ -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.
|
||||
@@ -934,7 +936,8 @@ public:
|
||||
__fi bool IsPresentThrottleAllowed() const { return m_allow_present_throttle; }
|
||||
|
||||
__fi GSTexture* GetCurrent() const { return m_current; }
|
||||
|
||||
__fi GSTexture* GetMAD() const { return m_mad; }
|
||||
|
||||
void Recycle(GSTexture* t);
|
||||
|
||||
/// Returns true if it's an OpenGL-based renderer.
|
||||
|
||||
@@ -118,6 +118,18 @@ bool GSRenderer::Merge(int field)
|
||||
if (!tex[0] && !tex[1])
|
||||
{
|
||||
m_real_size = GSVector2i(0, 0);
|
||||
|
||||
// Clear out the MAD buffer as some remnants of the previously shown frame came be left over, causing a flash for one frame.
|
||||
if (GSConfig.InterlaceMode == GSInterlaceMode::Automatic || GSConfig.InterlaceMode >= GSInterlaceMode::AdaptiveTFF)
|
||||
{
|
||||
GSTexture* mad_tex = g_gs_device->GetMAD();
|
||||
|
||||
if (mad_tex)
|
||||
{
|
||||
g_gs_device->ClearRenderTarget(mad_tex, 0);
|
||||
mad_tex = nullptr;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -605,72 +617,71 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
|
||||
EndPresentFrame();
|
||||
|
||||
PerformanceMetrics::Update(registers_written, fb_sprite_frame, skip_frame);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!idle_frame)
|
||||
g_gs_device->AgePool();
|
||||
|
||||
|
||||
g_perfmon.EndFrame(idle_frame);
|
||||
|
||||
if ((g_perfmon.GetFrame() & 0x1f) == 0)
|
||||
g_perfmon.Update();
|
||||
|
||||
// Little bit ugly, but we can't do CAS inside the render pass.
|
||||
GSVector4i src_rect;
|
||||
GSVector4 src_uv, draw_rect;
|
||||
GSTexture* current = g_gs_device->GetCurrent();
|
||||
if (current && !blank_frame)
|
||||
else
|
||||
{
|
||||
src_rect = CalculateDrawSrcRect(current, m_real_size);
|
||||
src_uv = GSVector4(src_rect) / GSVector4(current->GetSize()).xyxy();
|
||||
draw_rect = CalculateDrawDstRect(g_gs_device->GetWindowWidth(), g_gs_device->GetWindowHeight(),
|
||||
src_rect, current->GetSize(), s_display_alignment, g_gs_device->UsesLowerLeftOrigin(),
|
||||
GetVideoMode() == GSVideoMode::SDTV_480P);
|
||||
s_last_draw_rect = draw_rect;
|
||||
if (!idle_frame)
|
||||
g_gs_device->AgePool();
|
||||
|
||||
if (GSConfig.CASMode != GSCASMode::Disabled)
|
||||
{
|
||||
static bool cas_log_once = false;
|
||||
if (g_gs_device->Features().cas_sharpening)
|
||||
{
|
||||
// sharpen only if the IR is higher than the display resolution
|
||||
const bool sharpen_only = (GSConfig.CASMode == GSCASMode::SharpenOnly ||
|
||||
(current->GetWidth() > g_gs_device->GetWindowWidth() &&
|
||||
current->GetHeight() > g_gs_device->GetWindowHeight()));
|
||||
g_gs_device->CAS(current, src_rect, src_uv, draw_rect, sharpen_only);
|
||||
}
|
||||
else if (!cas_log_once)
|
||||
{
|
||||
Host::AddIconOSDMessage("CASUnsupported", ICON_FA_EXCLAMATION_TRIANGLE,
|
||||
TRANSLATE_SV("GS",
|
||||
"CAS is not available, your graphics driver does not support the required functionality."),
|
||||
10.0f);
|
||||
cas_log_once = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_perfmon.EndFrame(idle_frame);
|
||||
|
||||
if (BeginPresentFrame(false))
|
||||
{
|
||||
if ((g_perfmon.GetFrame() & 0x1f) == 0)
|
||||
g_perfmon.Update();
|
||||
|
||||
// Little bit ugly, but we can't do CAS inside the render pass.
|
||||
GSVector4i src_rect;
|
||||
GSVector4 src_uv, draw_rect;
|
||||
GSTexture* current = g_gs_device->GetCurrent();
|
||||
if (current && !blank_frame)
|
||||
{
|
||||
const u64 current_time = Common::Timer::GetCurrentValue();
|
||||
const float shader_time = static_cast<float>(Common::Timer::ConvertValueToSeconds(current_time - m_shader_time_start));
|
||||
src_rect = CalculateDrawSrcRect(current, m_real_size);
|
||||
src_uv = GSVector4(src_rect) / GSVector4(current->GetSize()).xyxy();
|
||||
draw_rect = CalculateDrawDstRect(g_gs_device->GetWindowWidth(), g_gs_device->GetWindowHeight(),
|
||||
src_rect, current->GetSize(), s_display_alignment, g_gs_device->UsesLowerLeftOrigin(),
|
||||
GetVideoMode() == GSVideoMode::SDTV_480P);
|
||||
s_last_draw_rect = draw_rect;
|
||||
|
||||
g_gs_device->PresentRect(current, src_uv, nullptr, draw_rect,
|
||||
s_tv_shader_indices[GSConfig.TVShader], shader_time, GSConfig.LinearPresent != GSPostBilinearMode::Off);
|
||||
if (GSConfig.CASMode != GSCASMode::Disabled)
|
||||
{
|
||||
static bool cas_log_once = false;
|
||||
if (g_gs_device->Features().cas_sharpening)
|
||||
{
|
||||
// sharpen only if the IR is higher than the display resolution
|
||||
const bool sharpen_only = (GSConfig.CASMode == GSCASMode::SharpenOnly ||
|
||||
(current->GetWidth() > g_gs_device->GetWindowWidth() &&
|
||||
current->GetHeight() > g_gs_device->GetWindowHeight()));
|
||||
g_gs_device->CAS(current, src_rect, src_uv, draw_rect, sharpen_only);
|
||||
}
|
||||
else if (!cas_log_once)
|
||||
{
|
||||
Host::AddIconOSDMessage("CASUnsupported", ICON_FA_EXCLAMATION_TRIANGLE,
|
||||
TRANSLATE_SV("GS", "CAS is not available, your graphics driver does not support the required functionality."),
|
||||
10.0f);
|
||||
cas_log_once = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EndPresentFrame();
|
||||
if (BeginPresentFrame(false))
|
||||
{
|
||||
if (current && !blank_frame)
|
||||
{
|
||||
const u64 current_time = Common::Timer::GetCurrentValue();
|
||||
const float shader_time = static_cast<float>(Common::Timer::ConvertValueToSeconds(current_time - m_shader_time_start));
|
||||
|
||||
if (GSConfig.OsdShowGPU)
|
||||
PerformanceMetrics::OnGPUPresent(g_gs_device->GetAndResetAccumulatedGPUTime());
|
||||
g_gs_device->PresentRect(current, src_uv, nullptr, draw_rect,
|
||||
s_tv_shader_indices[GSConfig.TVShader], shader_time, GSConfig.LinearPresent != GSPostBilinearMode::Off);
|
||||
}
|
||||
|
||||
EndPresentFrame();
|
||||
|
||||
if (GSConfig.OsdShowGPU)
|
||||
PerformanceMetrics::OnGPUPresent(g_gs_device->GetAndResetAccumulatedGPUTime());
|
||||
}
|
||||
|
||||
PerformanceMetrics::Update(registers_written, fb_sprite_frame, false);
|
||||
}
|
||||
|
||||
PerformanceMetrics::Update(registers_written, fb_sprite_frame, false);
|
||||
|
||||
// snapshot
|
||||
if (!m_snapshot.empty())
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
@@ -922,23 +822,6 @@ bool GSHwHack::GSC_MetalGearSolid3(GSRendererHW& r, int& skip)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_HitmanBloodMoney(GSRendererHW& r, int& skip)
|
||||
{
|
||||
// The game does a stupid thing where it backs up the last 2 pages of the framebuffer with shuffles, uploads a CT32 texture to it
|
||||
// then copies the RGB back (keeping the new alpha only). It's pretty gross, I have no idea why they didn't just upload a new alpha.
|
||||
// This is a real pain to emulate with the current state of things, so let's just clear the dirty area from the upload and pretend it wasn't there.
|
||||
|
||||
// Catch the first draw of the copy back.
|
||||
if (RFBP > 0 && RTPSM == PSMT8H && RFPSM == PSMCT32)
|
||||
{
|
||||
GSTextureCache::Target* target = g_texture_cache->FindOverlappingTarget(RFBP, RFBP + 1);
|
||||
if (target)
|
||||
target->m_dirty.clear();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GSHwHack::OI_PointListPalette(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t)
|
||||
{
|
||||
const u32 n_vertices = r.m_vertex.next;
|
||||
@@ -1413,13 +1296,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),
|
||||
@@ -1431,7 +1311,6 @@ const GSHwHack::Entry<GSRendererHW::GSC_Ptr> GSHwHack::s_get_skip_count_function
|
||||
CRC_F(GSC_NFSUndercover),
|
||||
CRC_F(GSC_PolyphonyDigitalGames),
|
||||
CRC_F(GSC_MetalGearSolid3),
|
||||
CRC_F(GSC_HitmanBloodMoney),
|
||||
CRC_F(GSC_Battlefield2),
|
||||
|
||||
// Channel Effect
|
||||
|
||||
@@ -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);
|
||||
@@ -29,7 +26,6 @@ public:
|
||||
static bool GSC_Battlefield2(GSRendererHW& r, int& skip);
|
||||
static bool GSC_PolyphonyDigitalGames(GSRendererHW& r, int& skip);
|
||||
static bool GSC_MetalGearSolid3(GSRendererHW& r, int& skip);
|
||||
static bool GSC_HitmanBloodMoney(GSRendererHW& r, int& skip);
|
||||
|
||||
static bool OI_PointListPalette(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||
static bool OI_DBZBTGames(GSRendererHW& r, GSTexture* rt, GSTexture* ds, GSTextureCache::Source* t);
|
||||
|
||||