mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-08-11 16:40:27 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9dbf2c5e9 | ||
|
|
c22f794a20 | ||
|
|
972135e184 | ||
|
|
96fad124ac | ||
|
|
ce7c466041 | ||
|
|
db0c7ca907 | ||
|
|
9f62ecdb33 | ||
|
|
f91f257a7d | ||
|
|
28a197b8cd | ||
|
|
9d2d8c0713 | ||
|
|
b431f1dc0d | ||
|
|
67eb2975f6 | ||
|
|
4192de7dac | ||
|
|
82cecc89e2 | ||
|
|
113e264617 | ||
|
|
a705a69022 | ||
|
|
d757360f4e | ||
|
|
cc978daeef | ||
|
|
d38ad1df94 | ||
|
|
1fd7bcf9a9 | ||
|
|
06abb70624 | ||
|
|
78e20868df | ||
|
|
e52766d047 | ||
|
|
224460e62d | ||
|
|
3c408de5c9 | ||
|
|
ea803ff2d4 | ||
|
|
14a0786982 | ||
|
|
1dbccb5e3d | ||
|
|
adca796d94 | ||
|
|
732aa96656 | ||
|
|
6beaec8ba1 | ||
|
|
2ae78f6e2f | ||
|
|
a889acb332 | ||
|
|
81236209db | ||
|
|
52266d7ac0 | ||
|
|
ab4592b8e9 | ||
|
|
7cda571d72 | ||
|
|
d0ce4c52b0 | ||
|
|
64ed6f5572 | ||
|
|
987bebffc7 | ||
|
|
e9c3807509 | ||
|
|
db642b05c0 | ||
|
|
7da904aa00 | ||
|
|
8c09daa22d | ||
|
|
7ebc04bc34 | ||
|
|
9254403a51 | ||
|
|
b4250965e6 | ||
|
|
3fbe704e21 | ||
|
|
4bfbc355a2 | ||
|
|
4d22102fd1 | ||
|
|
129efbda40 | ||
|
|
828fb8972c | ||
|
|
29b97209fe | ||
|
|
9c71bec4a0 | ||
|
|
1bc24c8d7c | ||
|
|
76ae5f3b12 | ||
|
|
7a6c0c6b4b | ||
|
|
db42792abf | ||
|
|
131f16b731 | ||
|
|
16e47f1d6b | ||
|
|
79e1fd1ea4 | ||
|
|
0c3cc59228 | ||
|
|
15db9e1778 | ||
|
|
19cf29e5cf | ||
|
|
d51d51b3cc | ||
|
|
c40e132284 | ||
|
|
f8f54bd892 | ||
|
|
5302cdcf2b | ||
|
|
8fe9282bd9 | ||
|
|
07ed213b1f | ||
|
|
8a1b8d2091 | ||
|
|
034ef5692c | ||
|
|
b9b9405c35 | ||
|
|
ca8d4f9ff0 | ||
|
|
0dc39a66d7 | ||
|
|
55e73bb4b9 | ||
|
|
6f9164b986 | ||
|
|
8d27c32418 | ||
|
|
a17a7ad1ec | ||
|
|
585868f930 | ||
|
|
795d0a6682 | ||
|
|
3c0b7f7724 | ||
|
|
ff23f87010 | ||
|
|
989fca99c6 | ||
|
|
b44e10df3c | ||
|
|
c9e9f92c93 | ||
|
|
bb1a366989 | ||
|
|
1458511756 | ||
|
|
3ebfc81727 | ||
|
|
8d0d59175d | ||
|
|
a46b3f2ed9 | ||
|
|
cb224789e2 | ||
|
|
cd4d829f9f | ||
|
|
faa25f2a96 | ||
|
|
36e8f49b63 | ||
|
|
e2a4657777 | ||
|
|
261b3f7e5c | ||
|
|
d6ba2aa76a | ||
|
|
fb135a87ab | ||
|
|
286fabaddc | ||
|
|
a79ad44370 | ||
|
|
2046a9b414 | ||
|
|
c77d8b3709 | ||
|
|
7b428bb6b0 | ||
|
|
6986030cd9 | ||
|
|
cc9b9a1935 | ||
|
|
2b7eeba55c | ||
|
|
c87dd99824 | ||
|
|
fbd837eadb | ||
|
|
7c9c8e197c | ||
|
|
0366929231 | ||
|
|
10d5261153 | ||
|
|
3278856764 | ||
|
|
ff5a9e0ea1 | ||
|
|
59b0c09443 | ||
|
|
ae772e6a74 | ||
|
|
0a58783a86 | ||
|
|
6f6de13fd4 | ||
|
|
89dcb78efa | ||
|
|
703c02c32c | ||
|
|
adcfca4db3 | ||
|
|
c359223fd4 | ||
|
|
c4c7d26bb3 | ||
|
|
c06bc16b22 | ||
|
|
f7bc05c735 | ||
|
|
ff02d41992 | ||
|
|
ec180e2771 | ||
|
|
dffa9e0b8c | ||
|
|
497e06bcd9 | ||
|
|
4c67c165fa | ||
|
|
2c175c0c7e | ||
|
|
6babbc1ff9 | ||
|
|
8af9aace3c | ||
|
|
601b75b611 | ||
|
|
350037fc75 | ||
|
|
f6bcfc3abd | ||
|
|
a480c972f7 | ||
|
|
581ded2c93 | ||
|
|
06176e291a | ||
|
|
14ee1b40d0 | ||
|
|
9acb98a2c8 | ||
|
|
daf50df337 | ||
|
|
c4d136383c | ||
|
|
5b5016bfd4 | ||
|
|
02352ab231 | ||
|
|
a4909d3575 | ||
|
|
fbb50e2895 | ||
|
|
0e4bf501f1 | ||
|
|
89b97456b7 | ||
|
|
fc4112c459 | ||
|
|
b6923f49b1 |
@@ -0,0 +1,41 @@
|
||||
name: 📦 Publish Flathub Release
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # Every day at 12am UTC.
|
||||
workflow_dispatch: # As well as manually.
|
||||
|
||||
jobs:
|
||||
check:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Check if release is needed"
|
||||
runs-on: ubuntu-latest
|
||||
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}'"
|
||||
echo "PCSX2_RELEASE=${PCSX2_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
echo "FLATHUB_RELEASE=${FLATHUB_RELEASE}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
build:
|
||||
needs: check
|
||||
if: needs.check.outputs.FLATHUB_RELEASE < needs.check.outputs.PCSX2_RELEASE
|
||||
name: "Build and publish Flatpak"
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: true
|
||||
branch: stable
|
||||
secrets: inherit
|
||||
|
||||
@@ -2,8 +2,8 @@ name: 📝 Validate GameDB
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
branches-ignore:
|
||||
- "l10n_master"
|
||||
paths:
|
||||
- '**/GameIndex.yaml'
|
||||
pull_request:
|
||||
|
||||
@@ -20,6 +20,10 @@ on:
|
||||
cmakeflags:
|
||||
required: true
|
||||
type: string
|
||||
branch:
|
||||
required: false
|
||||
type: string
|
||||
default: "stable"
|
||||
publish:
|
||||
required: false
|
||||
type: boolean
|
||||
@@ -45,6 +49,13 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
# 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.
|
||||
- name: Fetch tags
|
||||
if: inputs.publish == true
|
||||
id: fetch-tags
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
@@ -73,7 +84,7 @@ jobs:
|
||||
run: |
|
||||
./.github/workflows/scripts/linux/generate-metainfo.sh .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml
|
||||
cat .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml
|
||||
appstream-util validate .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml
|
||||
flatpak run org.freedesktop.appstream-glib validate .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml
|
||||
|
||||
- name: Build Flatpak
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@v6.1
|
||||
@@ -83,8 +94,29 @@ jobs:
|
||||
arch: x86_64
|
||||
build-bundle: true
|
||||
verbose: true
|
||||
mirror-screenshots-url: https://dl.flathub.org/repo/screenshots
|
||||
branch: ${{ inputs.branch }}
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} ${{ inputs.detail }} flatpak ${{ hashFiles('.github/workflows/scripts/linux/flatpak/**/*.json') }}
|
||||
|
||||
# TODO: Push to flathub
|
||||
- name: Commit screenshots to OSTree
|
||||
run: |
|
||||
ostree commit --repo=repo --canonical-permissions --branch=screenshots/x86_64 flatpak_app/screenshots
|
||||
|
||||
- name: Push to Flathub beta
|
||||
if: inputs.publish == true && inputs.branch == 'beta'
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@v6.1
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: beta
|
||||
token: ${{ secrets.FLATHUB_BETA_TOKEN }}
|
||||
|
||||
- name: Push to Flathub stable
|
||||
if: inputs.publish == true && inputs.branch == 'stable'
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@v6.1
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: stable
|
||||
token: ${{ secrets.FLATHUB_TOKEN }}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ name: 🐧 Linux Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
branches-ignore:
|
||||
- "l10n_master"
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
@@ -11,6 +11,7 @@ on:
|
||||
jobs:
|
||||
build_linux_qt:
|
||||
name: "AppImage"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
@@ -20,9 +21,11 @@ jobs:
|
||||
secrets: inherit
|
||||
build_linux_flatpak:
|
||||
name: "Flatpak"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: false
|
||||
secrets: inherit
|
||||
|
||||
@@ -102,8 +102,8 @@ jobs:
|
||||
env:
|
||||
COMPILER: ${{ inputs.compiler }}
|
||||
ADDITIONAL_CMAKE_ARGS: ${{ inputs.cmakeflags }}
|
||||
CLANG_PATH: /usr/bin/clang-12
|
||||
CLANGXX_PATH: /usr/bin/clang++-12
|
||||
CLANG_PATH: /usr/bin/clang-16
|
||||
CLANGXX_PATH: /usr/bin/clang++-16
|
||||
run: |
|
||||
DEPS_PREFIX="$HOME/deps" .github/workflows/scripts/linux/generate-cmake-qt.sh
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: macos-11.0
|
||||
default: macos-13
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
@@ -42,6 +42,9 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Use Xcode 14.3.1
|
||||
run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
|
||||
@@ -2,8 +2,8 @@ name: 🍎 MacOS Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
branches-ignore:
|
||||
- "l10n_master"
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
@@ -11,6 +11,7 @@ on:
|
||||
jobs:
|
||||
build_macos_qt:
|
||||
name: "Defaults"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/macos_build.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
|
||||
@@ -26,7 +26,8 @@ jobs:
|
||||
jobName: "Flatpak"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: true
|
||||
branch: "stable"
|
||||
publish: false
|
||||
secrets: inherit
|
||||
|
||||
# Windows
|
||||
|
||||
@@ -61,7 +61,6 @@ declare -a SYSLIBS=(
|
||||
"libwrap.so.0"
|
||||
"libharfbuzz.so.0"
|
||||
"libFLAC.so.8"
|
||||
"libSoundTouch.so.1"
|
||||
"libXau.so.6"
|
||||
"libXcomposite.so.1"
|
||||
"libXcursor.so.1"
|
||||
@@ -287,7 +286,7 @@ Plugins = ../lib/plugins
|
||||
EOF
|
||||
|
||||
echo "Copy desktop/icon..."
|
||||
cp "$PCSX2DIR/pcsx2/Resources/AppIcon64.png" "$OUTDIR/PCSX2.png"
|
||||
cp "$PCSX2DIR/bin/resources/icons/AppIconLarge.png" "$OUTDIR/PCSX2.png"
|
||||
cp "$SCRIPTDIR/pcsx2-qt.desktop" "$OUTDIR/PCSX2.desktop"
|
||||
cp "$SCRIPTDIR/AppRun-qt" "$OUTDIR/AppRun"
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"name": "soundtouch",
|
||||
"buildsystem": "cmake-ninja",
|
||||
"build-options": {
|
||||
"strip": true
|
||||
},
|
||||
"sources": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://codeberg.org/soundtouch/soundtouch.git",
|
||||
"tag": "2.3.2",
|
||||
"commit": "29fba832a7920a04eab956b3990c50e13d8c93f9"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
"/bin",
|
||||
"/include",
|
||||
"/lib/*.a",
|
||||
"/lib/*.la",
|
||||
"/lib/cmake",
|
||||
"/lib/pkgconfig",
|
||||
"/share/doc"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.llvm16"
|
||||
],
|
||||
"add-build-extensions": {
|
||||
"add-extensions": {
|
||||
"org.freedesktop.Platform.ffmpeg-full": {
|
||||
"directory": "lib/ffmpeg",
|
||||
"version": "22.08",
|
||||
"add-ld-path": "."
|
||||
"add-ld-path": ".",
|
||||
"autodownload": true
|
||||
}
|
||||
},
|
||||
"command": "pcsx2-qt",
|
||||
@@ -26,7 +27,6 @@
|
||||
"modules": [
|
||||
"modules/10-libpcap.json",
|
||||
"modules/11-libaio.json",
|
||||
"modules/12-soundtouch.json",
|
||||
"modules/20-sdl2.json",
|
||||
"modules/21-libbacktrace.json",
|
||||
{
|
||||
@@ -56,7 +56,7 @@
|
||||
"cd build && ninja unittests && cd .."
|
||||
],
|
||||
"post-install": [
|
||||
"install -Dm644 bin/resources/icons/AppIconLarge.png ${FLATPAK_DEST}/share/icons/hicolor/256x256/apps/net.pcsx2.PCSX2.png",
|
||||
"install -Dm644 bin/resources/icons/AppIconLarge.png ${FLATPAK_DEST}/share/icons/hicolor/512x512/apps/net.pcsx2.PCSX2.png",
|
||||
"install -Dm644 .github/workflows/scripts/linux/pcsx2-qt.desktop ${FLATPAK_DEST}/share/applications/net.pcsx2.PCSX2.desktop",
|
||||
"desktop-file-edit --set-key=Icon --set-value=net.pcsx2.PCSX2 ${FLATPAK_DEST}/share/applications/net.pcsx2.PCSX2.desktop",
|
||||
"install -Dm644 .github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.metainfo.xml ${FLATPAK_DEST}/share/metainfo/net.pcsx2.PCSX2.metainfo.xml"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
@@ -3,22 +3,30 @@
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Output file must be provided as a parameter"
|
||||
exit 1
|
||||
echo "Output file must be provided as a parameter"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
OUTFILE=$1
|
||||
GIT_DATE=$(git log -1 --pretty=%cd --date=short)
|
||||
GIT_VERSION=$(git tag --points-at HEAD)
|
||||
GIT_HASH=$(git rev-parse HEAD)
|
||||
|
||||
if [[ "${GIT_VERSION}" == "" ]]; then
|
||||
GIT_VERSION=$(git rev-parse HEAD)
|
||||
# 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
|
||||
fi
|
||||
|
||||
echo "GIT_DATE: ${GIT_DATE}"
|
||||
echo "GIT_VERSION: ${GIT_VERSION}"
|
||||
echo "GIT_HASH: ${GIT_HASH}"
|
||||
|
||||
cp "${SCRIPTDIR}"/pcsx2-qt.metainfo.xml.in "${OUTFILE}"
|
||||
|
||||
sed -i -e "s/@GIT_VERSION@/${GIT_VERSION}/" "${OUTFILE}"
|
||||
sed -i -e "s/@GIT_DATE@/${GIT_DATE}/" "${OUTFILE}"
|
||||
sed -i -e "s/@GIT_HASH@/${GIT_HASH}/" "${OUTFILE}"
|
||||
|
||||
|
||||
@@ -8,12 +8,21 @@ set -e
|
||||
ARCH=x86_64
|
||||
KDE_BRANCH=6.5
|
||||
BRANCH=22.08
|
||||
FLAT_MANAGER_CLIENT_DIR="$HOME/.local/bin"
|
||||
|
||||
# Build packages.
|
||||
# Build packages. Mostly needed for flat-manager-client.
|
||||
declare -a BUILD_PACKAGES=(
|
||||
"flatpak"
|
||||
"flatpak-builder"
|
||||
"appstream-util"
|
||||
"python3-aiohttp"
|
||||
"python3-tenacity"
|
||||
"python3-gi"
|
||||
"gobject-introspection"
|
||||
"libappstream-glib8"
|
||||
"libappstream-glib-dev"
|
||||
"libappstream-dev"
|
||||
"gir1.2-ostree-1.0"
|
||||
)
|
||||
|
||||
# Flatpak runtimes and SDKs.
|
||||
@@ -22,6 +31,7 @@ declare -a FLATPAK_PACKAGES=(
|
||||
"org.kde.Sdk/${ARCH}/${KDE_BRANCH}"
|
||||
"org.freedesktop.Platform.ffmpeg-full/${ARCH}/${BRANCH}"
|
||||
"org.freedesktop.Sdk.Extension.llvm16/${ARCH}/${BRANCH}"
|
||||
"org.freedesktop.appstream-glib/${ARCH}/stable"
|
||||
)
|
||||
|
||||
retry_command sudo apt-get -qq update
|
||||
@@ -36,3 +46,10 @@ sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub
|
||||
echo "Will install the following packages for building - ${FLATPAK_PACKAGES[*]}"
|
||||
retry_command sudo flatpak -y install "${FLATPAK_PACKAGES[@]}"
|
||||
|
||||
echo "Downloading flat-manager-client"
|
||||
mkdir -p "$FLAT_MANAGER_CLIENT_DIR"
|
||||
pushd "$FLAT_MANAGER_CLIENT_DIR"
|
||||
aria2c -Z "https://raw.githubusercontent.com/flatpak/flat-manager/master/flat-manager-client"
|
||||
chmod +x flat-manager-client
|
||||
echo "$FLAT_MANAGER_CLIENT_DIR" >> $GITHUB_PATH
|
||||
popd
|
||||
|
||||
@@ -52,7 +52,6 @@ declare -a PCSX2_PACKAGES=(
|
||||
"libpulse-dev"
|
||||
"librsvg2-dev"
|
||||
"libsamplerate0-dev"
|
||||
"libsoundtouch-dev"
|
||||
"libudev-dev"
|
||||
"libx11-xcb-dev"
|
||||
"libavcodec-dev"
|
||||
@@ -67,7 +66,13 @@ declare -a PCSX2_PACKAGES=(
|
||||
if [ "${COMPILER}" = "gcc" ]; then
|
||||
BUILD_PACKAGES+=("g++-10")
|
||||
else
|
||||
BUILD_PACKAGES+=("llvm-12" "lld-12" "clang-12")
|
||||
BUILD_PACKAGES+=("llvm-16" "lld-16" "clang-16")
|
||||
|
||||
# Ubuntu 20.04 doesn't ship with LLVM 16, so we need to pull it from the llvm.org repos.
|
||||
retry_command wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-add-repository -n 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-16 main'
|
||||
retry_command sudo apt-get update
|
||||
retry_command sudo apt-get install clang-16 lld-16
|
||||
fi
|
||||
|
||||
retry_command sudo apt-get -qq update && break
|
||||
|
||||
@@ -13,9 +13,20 @@
|
||||
</description>
|
||||
<url type="homepage">https://pcsx2.net/</url>
|
||||
<url type="bugtracker">https://github.com/PCSX2/pcsx2/issues</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://raw.githubusercontent.com/PCSX2/pcsx2/master/.github/workflows/scripts/linux/flatpak/screenshots/screenshot1.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image>https://raw.githubusercontent.com/PCSX2/pcsx2/master/.github/workflows/scripts/linux/flatpak/screenshots/screenshot2.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<content_rating type="oars-1.1"/>
|
||||
<update_contact>pcsx2_AT_pcsx2.net</update_contact>
|
||||
<update_contact>stenzek_AT_gmail.com</update_contact>
|
||||
<releases>
|
||||
<release version="@GIT_VERSION@" date="@GIT_DATE@" />
|
||||
</releases>
|
||||
<custom>
|
||||
<value key="flathub::manifest">https://raw.githubusercontent.com/PCSX2/pcsx2/@GIT_HASH@/.github/workflows/scripts/linux/flatpak/net.pcsx2.PCSX2.json</value>
|
||||
</custom>
|
||||
</component>
|
||||
|
||||
@@ -2,8 +2,8 @@ name: 🖥️ Windows Builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
branches-ignore:
|
||||
- "l10n_master"
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
@@ -12,6 +12,7 @@ jobs:
|
||||
# MSBUILD
|
||||
lint_vs_proj_files:
|
||||
name: Lint VS Project Files
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
@@ -22,6 +23,7 @@ jobs:
|
||||
build_qt_sse4:
|
||||
needs: lint_vs_proj_files
|
||||
name: "SSE4"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
@@ -32,6 +34,7 @@ jobs:
|
||||
build_qt_avx2:
|
||||
needs: lint_vs_proj_files
|
||||
name: "AVX2"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
@@ -40,6 +43,7 @@ jobs:
|
||||
|
||||
build_qt_cmake:
|
||||
name: "CMake"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
@@ -50,6 +54,7 @@ jobs:
|
||||
build_qt_clang_sse4:
|
||||
needs: lint_vs_proj_files
|
||||
name: "SSE4"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt Clang
|
||||
@@ -60,6 +65,7 @@ jobs:
|
||||
build_qt_clang_avx2:
|
||||
needs: lint_vs_proj_files
|
||||
name: "AVX2"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt Clang
|
||||
@@ -68,6 +74,7 @@ jobs:
|
||||
|
||||
build_qt_cmake_clang:
|
||||
name: "CMake"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt Clang
|
||||
|
||||
Vendored
+2
-1
@@ -9,9 +9,10 @@
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__WIN32__;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__WIN32__;WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_HAS_EXCEPTIONS=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
|
||||
Vendored
+3
-17
@@ -4764,23 +4764,9 @@ void cGram::demangleClassName(const std::string& input, cName* retvalue, cGram::
|
||||
std::string sLength = match[1];
|
||||
std::string name = match[2];
|
||||
|
||||
unsigned long length = 0;
|
||||
|
||||
bool ok = true;
|
||||
try {
|
||||
length = std::stoul(sLength);
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
ok = false;
|
||||
}
|
||||
catch (const std::out_of_range&) {
|
||||
ok = false;
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
if (name.length() == length) {
|
||||
className = name;
|
||||
}
|
||||
unsigned long length = std::stoul(sLength);
|
||||
if (name.length() == length) {
|
||||
className = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -989,11 +989,11 @@ void RA_Shutdown()
|
||||
// Call shutdown on toolchain
|
||||
if (_RA_Shutdown != nullptr)
|
||||
{
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus) && _HAS_EXCEPTIONS
|
||||
try {
|
||||
#endif
|
||||
_RA_Shutdown();
|
||||
#ifdef __cplusplus
|
||||
#if defined(__cplusplus) && _HAS_EXCEPTIONS
|
||||
}
|
||||
catch (std::runtime_error&) {
|
||||
}
|
||||
|
||||
Vendored
+17
-3
@@ -1,4 +1,4 @@
|
||||
add_library(soundtouch
|
||||
add_library(pcsx2-soundtouch
|
||||
source/SoundStretch/WavFile.cpp
|
||||
source/SoundTouch/AAFilter.cpp
|
||||
source/SoundTouch/BPMDetect.cpp
|
||||
@@ -30,5 +30,19 @@ add_library(soundtouch
|
||||
source/SoundTouch/RateTransposer.h
|
||||
source/SoundTouch/TDStretch.h
|
||||
)
|
||||
target_include_directories(soundtouch PUBLIC soundtouch)
|
||||
add_library(PkgConfig::SOUNDTOUCH ALIAS soundtouch)
|
||||
|
||||
target_include_directories(pcsx2-soundtouch PUBLIC soundtouch)
|
||||
target_compile_definitions(pcsx2-soundtouch PUBLIC SOUNDTOUCH_FLOAT_SAMPLES ST_NO_EXCEPTION_HANDLING)
|
||||
set_property(TARGET pcsx2-soundtouch PROPERTY CXX_STANDARD 17)
|
||||
set_property(TARGET pcsx2-soundtouch PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if(NOT "${CMAKE_BUILD_TYPE}" MATCHES "Debug")
|
||||
if(MSVC)
|
||||
target_compile_options(pcsx2-soundtouch PRIVATE /O2 /fp:fast)
|
||||
else()
|
||||
target_compile_options(pcsx2-soundtouch PRIVATE -Ofast)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(SoundTouch::SoundTouch ALIAS pcsx2-soundtouch)
|
||||
|
||||
|
||||
+1
@@ -31,6 +31,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>ST_NO_EXCEPTION_HANDLING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)soundtouch;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
+9
-9
@@ -91,7 +91,7 @@ public:
|
||||
);
|
||||
|
||||
/// destructor
|
||||
~FIFOSampleBuffer();
|
||||
~FIFOSampleBuffer() override;
|
||||
|
||||
/// Returns a pointer to the beginning of the output samples.
|
||||
/// This function is provided for accessing the output samples directly.
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
/// When using this function to output samples, also remember to 'remove' the
|
||||
/// output samples from the buffer by calling the
|
||||
/// 'receiveSamples(numSamples)' function
|
||||
virtual SAMPLETYPE *ptrBegin();
|
||||
virtual SAMPLETYPE *ptrBegin() override;
|
||||
|
||||
/// Returns a pointer to the end of the used part of the sample buffer (i.e.
|
||||
/// where the new samples are to be inserted). This function may be used for
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
/// the sample buffer.
|
||||
virtual void putSamples(const SAMPLETYPE *samples, ///< Pointer to samples.
|
||||
uint numSamples ///< Number of samples to insert.
|
||||
);
|
||||
) override;
|
||||
|
||||
/// Adjusts the book-keeping to increase number of samples in the buffer without
|
||||
/// copying any actual samples.
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
/// \return Number of samples returned.
|
||||
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
|
||||
uint maxSamples ///< How many samples to receive at max.
|
||||
);
|
||||
) override;
|
||||
|
||||
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
|
||||
/// sample buffer without copying them anywhere.
|
||||
@@ -147,10 +147,10 @@ public:
|
||||
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
|
||||
/// with 'ptrBegin' function.
|
||||
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
|
||||
);
|
||||
) override;
|
||||
|
||||
/// Returns number of samples currently available.
|
||||
virtual uint numSamples() const;
|
||||
virtual uint numSamples() const override;
|
||||
|
||||
/// Sets number of channels, 1 = mono, 2 = stereo.
|
||||
void setChannels(int numChannels);
|
||||
@@ -162,14 +162,14 @@ public:
|
||||
}
|
||||
|
||||
/// Returns nonzero if there aren't any samples available for outputting.
|
||||
virtual int isEmpty() const;
|
||||
virtual int isEmpty() const override;
|
||||
|
||||
/// Clears all the samples.
|
||||
virtual void clear();
|
||||
virtual void clear() override;
|
||||
|
||||
/// allow trimming (downwards) amount of samples in pipeline.
|
||||
/// Returns adjusted amount of samples
|
||||
uint adjustAmountOfSamples(uint numSamples);
|
||||
uint adjustAmountOfSamples(uint numSamples) override;
|
||||
|
||||
/// Add silence to end of buffer
|
||||
void addSilent(uint nSamples);
|
||||
|
||||
+7
-7
@@ -164,7 +164,7 @@ protected:
|
||||
}
|
||||
|
||||
/// Destructor.
|
||||
virtual ~FIFOProcessor()
|
||||
virtual ~FIFOProcessor() override
|
||||
{
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ protected:
|
||||
/// When using this function to output samples, also remember to 'remove' the
|
||||
/// output samples from the buffer by calling the
|
||||
/// 'receiveSamples(numSamples)' function
|
||||
virtual SAMPLETYPE *ptrBegin()
|
||||
virtual SAMPLETYPE *ptrBegin() override
|
||||
{
|
||||
return output->ptrBegin();
|
||||
}
|
||||
@@ -189,7 +189,7 @@ public:
|
||||
/// \return Number of samples returned.
|
||||
virtual uint receiveSamples(SAMPLETYPE *outBuffer, ///< Buffer where to copy output samples.
|
||||
uint maxSamples ///< How many samples to receive at max.
|
||||
)
|
||||
) override
|
||||
{
|
||||
return output->receiveSamples(outBuffer, maxSamples);
|
||||
}
|
||||
@@ -200,26 +200,26 @@ public:
|
||||
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
|
||||
/// with 'ptrBegin' function.
|
||||
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
|
||||
)
|
||||
) override
|
||||
{
|
||||
return output->receiveSamples(maxSamples);
|
||||
}
|
||||
|
||||
/// Returns number of samples currently available.
|
||||
virtual uint numSamples() const
|
||||
virtual uint numSamples() const override
|
||||
{
|
||||
return output->numSamples();
|
||||
}
|
||||
|
||||
/// Returns nonzero if there aren't any samples available for outputting.
|
||||
virtual int isEmpty() const
|
||||
virtual int isEmpty() const override
|
||||
{
|
||||
return output->isEmpty();
|
||||
}
|
||||
|
||||
/// allow trimming (downwards) amount of samples in pipeline.
|
||||
/// Returns adjusted amount of samples
|
||||
virtual uint adjustAmountOfSamples(uint numSamples)
|
||||
virtual uint adjustAmountOfSamples(uint numSamples) override
|
||||
{
|
||||
return output->adjustAmountOfSamples(numSamples);
|
||||
}
|
||||
|
||||
+5
-5
@@ -209,7 +209,7 @@ protected :
|
||||
|
||||
public:
|
||||
SoundTouch();
|
||||
virtual ~SoundTouch();
|
||||
virtual ~SoundTouch() override;
|
||||
|
||||
/// Get SoundTouch library version string
|
||||
static const char *getVersionString();
|
||||
@@ -287,7 +287,7 @@ public:
|
||||
uint numSamples ///< Number of samples in buffer. Notice
|
||||
///< that in case of stereo-sound a single sample
|
||||
///< contains data for both channels.
|
||||
);
|
||||
) override;
|
||||
|
||||
/// Output samples from beginning of the sample buffer. Copies requested samples to
|
||||
/// output buffer and removes them from the sample buffer. If there are less than
|
||||
@@ -296,7 +296,7 @@ public:
|
||||
/// \return Number of samples returned.
|
||||
virtual uint receiveSamples(SAMPLETYPE *output, ///< Buffer where to copy output samples.
|
||||
uint maxSamples ///< How many samples to receive at max.
|
||||
);
|
||||
) override;
|
||||
|
||||
/// Adjusts book-keeping so that given number of samples are removed from beginning of the
|
||||
/// sample buffer without copying them anywhere.
|
||||
@@ -304,11 +304,11 @@ public:
|
||||
/// Used to reduce the number of samples in the buffer when accessing the sample buffer directly
|
||||
/// with 'ptrBegin' function.
|
||||
virtual uint receiveSamples(uint maxSamples ///< Remove this many samples from the beginning of pipe.
|
||||
);
|
||||
) override;
|
||||
|
||||
/// Clears all the samples in the object's output and internal processing
|
||||
/// buffers.
|
||||
virtual void clear();
|
||||
virtual void clear() override;
|
||||
|
||||
/// Changes a setting controlling the processing system behaviour. See the
|
||||
/// 'SETTING_...' defines for available setting ID's.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// autotools configuration step replaces this file with a configured version.
|
||||
// this empty file stub is provided to avoid error about missing include file
|
||||
// when not using autotools build
|
||||
+4
-4
@@ -106,12 +106,12 @@ public:
|
||||
short *filterCoeffsUnalign;
|
||||
short *filterCoeffsAlign;
|
||||
|
||||
virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const;
|
||||
virtual uint evaluateFilterStereo(short *dest, const short *src, uint numSamples) const override;
|
||||
public:
|
||||
FIRFilterMMX();
|
||||
~FIRFilterMMX();
|
||||
|
||||
virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor);
|
||||
virtual void setCoefficients(const short *coeffs, uint newLength, uint uResultDivFactor) override;
|
||||
};
|
||||
|
||||
#endif // SOUNDTOUCH_ALLOW_MMX
|
||||
@@ -125,12 +125,12 @@ public:
|
||||
float *filterCoeffsUnalign;
|
||||
float *filterCoeffsAlign;
|
||||
|
||||
virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const;
|
||||
virtual uint evaluateFilterStereo(float *dest, const float *src, uint numSamples) const override;
|
||||
public:
|
||||
FIRFilterSSE();
|
||||
~FIRFilterSSE();
|
||||
|
||||
virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor);
|
||||
virtual void setCoefficients(const float *coeffs, uint newLength, uint uResultDivFactor) override;
|
||||
};
|
||||
|
||||
#endif // SOUNDTOUCH_ALLOW_SSE
|
||||
|
||||
@@ -43,20 +43,20 @@ class InterpolateCubic : public TransposerBase
|
||||
protected:
|
||||
virtual int transposeMono(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
int &srcSamples) override;
|
||||
virtual int transposeStereo(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
int &srcSamples) override;
|
||||
virtual int transposeMulti(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
int &srcSamples) override;
|
||||
|
||||
double fract;
|
||||
|
||||
public:
|
||||
InterpolateCubic();
|
||||
|
||||
virtual void resetRegisters();
|
||||
virtual void resetRegisters() override;
|
||||
|
||||
int getLatency() const
|
||||
{
|
||||
|
||||
@@ -47,21 +47,21 @@ protected:
|
||||
|
||||
virtual int transposeMono(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
int &srcSamples) override;
|
||||
virtual int transposeStereo(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples);
|
||||
int &srcSamples) override;
|
||||
virtual int transposeMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, int &srcSamples) override;
|
||||
public:
|
||||
InterpolateLinearInteger();
|
||||
|
||||
/// Sets new target rate. Normal rate = 1.0, smaller values represent slower
|
||||
/// rate, larger faster rates.
|
||||
virtual void setRate(double newRate);
|
||||
virtual void setRate(double newRate) override;
|
||||
|
||||
virtual void resetRegisters();
|
||||
virtual void resetRegisters() override;
|
||||
|
||||
int getLatency() const
|
||||
int getLatency() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -87,7 +87,7 @@ public:
|
||||
|
||||
virtual void resetRegisters();
|
||||
|
||||
int getLatency() const
|
||||
int getLatency() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -48,20 +48,20 @@ class InterpolateShannon : public TransposerBase
|
||||
protected:
|
||||
int transposeMono(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
int &srcSamples) override;
|
||||
int transposeStereo(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
int &srcSamples) override;
|
||||
int transposeMulti(SAMPLETYPE *dest,
|
||||
const SAMPLETYPE *src,
|
||||
int &srcSamples);
|
||||
int &srcSamples) override;
|
||||
|
||||
double fract;
|
||||
|
||||
public:
|
||||
InterpolateShannon();
|
||||
|
||||
void resetRegisters();
|
||||
void resetRegisters() override;
|
||||
|
||||
int getLatency() const
|
||||
{
|
||||
|
||||
+4
-4
@@ -124,7 +124,7 @@ protected:
|
||||
|
||||
public:
|
||||
RateTransposer();
|
||||
virtual ~RateTransposer();
|
||||
virtual ~RateTransposer() override;
|
||||
|
||||
/// Returns the output buffer object
|
||||
FIFOSamplePipe *getOutput() { return &outputBuffer; };
|
||||
@@ -147,13 +147,13 @@ public:
|
||||
|
||||
/// Adds 'numSamples' pcs of samples from the 'samples' memory position into
|
||||
/// the input of the object.
|
||||
void putSamples(const SAMPLETYPE *samples, uint numSamples);
|
||||
void putSamples(const SAMPLETYPE *samples, uint numSamples) override;
|
||||
|
||||
/// Clears all the samples in the object
|
||||
void clear();
|
||||
void clear() override;
|
||||
|
||||
/// Returns nonzero if there aren't any samples available for outputting.
|
||||
int isEmpty() const;
|
||||
int isEmpty() const override;
|
||||
|
||||
/// Return approximate initial input-output latency
|
||||
int getLatency() const;
|
||||
|
||||
+9
-9
@@ -165,7 +165,7 @@ protected:
|
||||
|
||||
public:
|
||||
TDStretch();
|
||||
virtual ~TDStretch();
|
||||
virtual ~TDStretch() override;
|
||||
|
||||
/// Operator 'new' is overloaded so that it automatically creates a suitable instance
|
||||
/// depending on if we've a MMX/SSE/etc-capable CPU available or not.
|
||||
@@ -187,7 +187,7 @@ public:
|
||||
void setTempo(double newTempo);
|
||||
|
||||
/// Returns nonzero if there aren't any samples available for outputting.
|
||||
virtual void clear();
|
||||
virtual void clear() override;
|
||||
|
||||
/// Clears the input buffer
|
||||
void clearInput();
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
const SAMPLETYPE *samples, ///< Input sample data
|
||||
uint numSamples ///< Number of samples in 'samples' so that one sample
|
||||
///< contains both channels if stereo
|
||||
);
|
||||
) override;
|
||||
|
||||
/// return nominal input sample requirement for triggering a processing batch
|
||||
int getInputSampleReq() const
|
||||
@@ -256,10 +256,10 @@ public:
|
||||
class TDStretchMMX : public TDStretch
|
||||
{
|
||||
protected:
|
||||
double calcCrossCorr(const short *mixingPos, const short *compare, double &norm);
|
||||
double calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm);
|
||||
virtual void overlapStereo(short *output, const short *input) const;
|
||||
virtual void clearCrossCorrState();
|
||||
double calcCrossCorr(const short *mixingPos, const short *compare, double &norm) override;
|
||||
double calcCrossCorrAccumulate(const short *mixingPos, const short *compare, double &norm) override;
|
||||
virtual void overlapStereo(short *output, const short *input) const override;
|
||||
virtual void clearCrossCorrState() override;
|
||||
};
|
||||
#endif /// SOUNDTOUCH_ALLOW_MMX
|
||||
|
||||
@@ -269,8 +269,8 @@ public:
|
||||
class TDStretchSSE : public TDStretch
|
||||
{
|
||||
protected:
|
||||
double calcCrossCorr(const float *mixingPos, const float *compare, double &norm);
|
||||
double calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm);
|
||||
double calcCrossCorr(const float *mixingPos, const float *compare, double &norm) override;
|
||||
double calcCrossCorrAccumulate(const float *mixingPos, const float *compare, double &norm) override;
|
||||
};
|
||||
|
||||
#endif /// SOUNDTOUCH_ALLOW_SSE
|
||||
|
||||
@@ -62,8 +62,6 @@ endif()
|
||||
|
||||
# tests
|
||||
if(ACTUALLY_ENABLE_TESTS)
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
add_subdirectory(3rdparty/gtest EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(tests/ctest)
|
||||
endif()
|
||||
|
||||
|
||||
+247
-148
File diff suppressed because it is too large
Load Diff
@@ -35,6 +35,7 @@
|
||||
03000000c82d00006528000000000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00000290000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows,
|
||||
03000000c82d00003038000000000000,8BitDo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows,
|
||||
03000000c82d00006928000000000000,8BitDo N64,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,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b11,platform:Windows,
|
||||
030000003512000012ab000000000000,8BitDo NES30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Windows,
|
||||
03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000022000000090000000000000,8BitDo NES30 Pro,a:b1,b:b0,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:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
|
||||
@@ -68,8 +69,11 @@
|
||||
03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
|
||||
03000000c82d00001230000000000000,8BitDo Ultimate,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,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001530000000000000,8BitDo Ultimate C,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:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001630000000000000,8BitDo Ultimate C,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:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001730000000000000,8BitDo Ultimate C,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:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001130000000000000,8BitDo Ultimate Wired,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,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001230000000000000,8BitDo Ultimate Wireless,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:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00001330000000000000,8BitDo Ultimate Wireless,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:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000c82d00000121000000000000,8BitDo Xbox One SN30 Pro,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:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
|
||||
@@ -386,6 +390,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,
|
||||
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,
|
||||
0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
|
||||
@@ -784,6 +789,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
|
||||
03000000c82d00001590000001000000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00006928000000010000,8BitDo N64,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,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
|
||||
030000003512000012ab000001000000,8BitDo NES30,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d000012ab000001000000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00002028000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
@@ -807,6 +813,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
|
||||
03000000c82d00001230000000010000,8BitDo Ultimate,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,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001530000001000000,8BitDo Ultimate C,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:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001630000001000000,8BitDo Ultimate C,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,
|
||||
03000000c82d00001730000001000000,8BitDo Ultimate C,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:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001130000000020000,8BitDo Ultimate Wired,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:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001330000001000000,8BitDo Ultimate Wireless,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:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000c82d00001330000000020000,8BitDo Ultimate 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,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
|
||||
@@ -1045,6 +1055,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux,
|
||||
03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
|
||||
05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
|
||||
05000000c82d00006928000000010000,8BitDo N64,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,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux,
|
||||
03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000c82d00000310000011010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000c82d00008010000000010000,8BitDo NES30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b9,righttrigger:b8,start:b11,x:b3,y:b4,platform:Linux,
|
||||
@@ -1082,6 +1093,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000c82d00000260000011010000,8BitDo SN30 Pro Plus,a:b1,b:b0,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:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,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:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00001230000000010000,8BitDo Ultimate,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,
|
||||
03000000c82d00001730000011010000,8BitDo Ultimate 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,
|
||||
03000000c82d00001530000011010000,8BitDo Ultimate C,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,
|
||||
03000000c82d00001630000011010000,8BitDo Ultimate C,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,
|
||||
03000000c82d00001130000011010000,8BitDo Ultimate Wired,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:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00001230000011010000,8BitDo Ultimate Wireless,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,
|
||||
@@ -1294,7 +1309,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005e040000ea02000008040000,Microsoft Xbox One,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,
|
||||
060000005e040000120b000009050000,Microsoft Xbox One,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,
|
||||
030000005e040000e302000003020000,Microsoft Xbox One Elite,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,
|
||||
030000005e040000000b000008040000,Microsoft Xbox One Elite 2,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,
|
||||
030000005e040000000b000007040000,Microsoft Xbox One Elite 2,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,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e040000000b000008040000,Microsoft Xbox One Elite 2,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,paddle1:b12,paddle2:b14,paddle3:b13,paddle4:b15,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,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,
|
||||
030000005e040000120b00000b050000,Microsoft 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,
|
||||
03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
|
||||
@@ -1368,6 +1384,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000006f0e0000a802000023020000,PDP Xbox One Controller,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:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
030000006f0e0000a702000023020000,PDP Xbox One Raven Black,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,
|
||||
030000006f0e0000d802000006640000,PDP 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,
|
||||
030000006f0e0000ef02000007640000,PDP Xbox Series Kinetic Wired 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,
|
||||
03000000666600006706000000010000,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:Linux,
|
||||
030000004c050000da0c000011010000,PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000d9040000160f000000010000,PlayStation Controller Adapter,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:Linux,
|
||||
@@ -1514,7 +1531,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,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:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux,
|
||||
03000000790000001c18000011010000,TGZ 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:Linux,
|
||||
03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,leftshoulder:b4,rightshoulder:b5,x:b3,y:b0,start:b7,platform:Linux,
|
||||
03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
|
||||
030000004f04000015b3000001010000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
|
||||
030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
|
||||
030000004f04000020b3000010010000,Thrustmaster Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
|
||||
@@ -1540,7 +1557,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000e00d00000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
|
||||
03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
|
||||
030000005f140000c501000010010000,Trust Gamepad,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:Linux,
|
||||
06000000f51000000870000003010000,Turtle Beach Recon,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
|
||||
06000000f51000000870000003010000,Turtle Beach Recon,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,
|
||||
03000000100800000100000010010000,Twin PS2 Adapter,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:Linux,
|
||||
03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
|
||||
03000000100800000300000010010000,USB Gamepad,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:Linux,
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 487 B |
@@ -134,8 +134,6 @@ add_compile_options("${ARCH_FLAG_LIST}")
|
||||
option(USE_PGO_GENERATE "Enable PGO optimization (generate profile)")
|
||||
option(USE_PGO_OPTIMIZE "Enable PGO optimization (use profile)")
|
||||
|
||||
# Note1: Builtin strcmp/memcmp was proved to be slower on Mesa than stdlib version.
|
||||
# Note2: float operation SSE is impacted by the PCSX2 SSE configuration. In particular, flush to zero denormal.
|
||||
if(MSVC AND NOT USE_CLANG_CL)
|
||||
add_compile_options(
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:/Zc:externConstexpr>"
|
||||
@@ -144,8 +142,20 @@ if(MSVC AND NOT USE_CLANG_CL)
|
||||
"/Zo"
|
||||
"/utf-8"
|
||||
)
|
||||
elseif(NOT MSVC)
|
||||
add_compile_options(-pipe -fvisibility=hidden -pthread -fno-builtin-strcmp -fno-builtin-memcmp -mfpmath=sse)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
# Disable RTTI
|
||||
string(REPLACE "/GR" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
|
||||
# Disable Exceptions
|
||||
string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
else()
|
||||
add_compile_options(-pipe -fvisibility=hidden -pthread)
|
||||
add_compile_options(
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>"
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(CONFIG_REL_NO_DEB $<OR:$<CONFIG:Release>,$<CONFIG:MinSizeRel>>)
|
||||
@@ -156,8 +166,9 @@ if(WIN32)
|
||||
$<$<CONFIG:Debug>:_ITERATOR_DEBUG_LEVEL=2>
|
||||
$<$<CONFIG:Devel>:_ITERATOR_DEBUG_LEVEL=1>
|
||||
$<${CONFIG_ANY_REL}:_ITERATOR_DEBUG_LEVEL=0>
|
||||
_HAS_EXCEPTIONS=0
|
||||
)
|
||||
list(APPEND PCSX2_DEFS TIXML_USE_STL _SCL_SECURE_NO_WARNINGS _UNICODE UNICODE)
|
||||
list(APPEND PCSX2_DEFS _SCL_SECURE_NO_WARNINGS _UNICODE UNICODE)
|
||||
endif()
|
||||
|
||||
# Enable debug information in release builds for Linux.
|
||||
|
||||
@@ -9,7 +9,6 @@ if (WIN32)
|
||||
add_subdirectory(3rdparty/zlib EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/libpng EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/libjpeg EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/soundtouch EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/wil EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/xz EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/D3D12MemAlloc EXCLUDE_FROM_ALL)
|
||||
@@ -74,8 +73,6 @@ else()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
check_lib(SOUNDTOUCH SoundTouch SoundTouch.h PATH_SUFFIXES soundtouch)
|
||||
|
||||
if(NOT QT_BUILD)
|
||||
find_optional_system_library(SDL2 3rdparty/sdl2 2.0.12)
|
||||
endif()
|
||||
@@ -165,6 +162,7 @@ endif()
|
||||
|
||||
add_subdirectory(3rdparty/lzma EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/libchdr EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/soundtouch EXCLUDE_FROM_ALL)
|
||||
|
||||
# rapidyaml includes fast_float as a submodule, saves us pulling it in directly.
|
||||
# Normally, we'd just pull in the cmake project, and link to it, but... it seems to enable
|
||||
|
||||
@@ -42,116 +42,3 @@ extern void _aligned_free(void* pmem);
|
||||
#define pcsx2_aligned_realloc(handle, new_size, align, old_size) \
|
||||
_aligned_realloc(handle, new_size, align)
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// AlignedBuffer
|
||||
// --------------------------------------------------------------------------------------
|
||||
// A simple container class for an aligned allocation. By default, no bounds checking is
|
||||
// performed, and there is no option for enabling bounds checking. If bounds checking and
|
||||
// other features are needed, use the more robust SafeArray<> instead.
|
||||
//
|
||||
template <typename T, uint align>
|
||||
class AlignedBuffer
|
||||
{
|
||||
static_assert(std::is_pod<T>::value, "Must use a POD type");
|
||||
|
||||
struct Deleter
|
||||
{
|
||||
void operator()(T* ptr)
|
||||
{
|
||||
_aligned_free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<T[], Deleter> m_buffer;
|
||||
std::size_t m_size;
|
||||
|
||||
public:
|
||||
AlignedBuffer(size_t size = 0)
|
||||
{
|
||||
Alloc(size);
|
||||
}
|
||||
|
||||
AlignedBuffer(const AlignedBuffer& copy)
|
||||
{
|
||||
Alloc(copy.m_size);
|
||||
if (copy.m_size > 0)
|
||||
std::memcpy(m_buffer.get(), copy.m_buffer.get(), copy.m_size);
|
||||
}
|
||||
|
||||
AlignedBuffer(AlignedBuffer&& move)
|
||||
: m_buffer(std::move(move.m_buffer))
|
||||
, m_size(move.m_size)
|
||||
{
|
||||
move.m_size = 0;
|
||||
}
|
||||
|
||||
size_t GetSize() const { return m_size; }
|
||||
size_t GetLength() const { return m_size; }
|
||||
|
||||
void Alloc(size_t newsize)
|
||||
{
|
||||
m_size = newsize;
|
||||
m_buffer.reset();
|
||||
if (!m_size)
|
||||
return;
|
||||
|
||||
m_buffer.reset(reinterpret_cast<T*>(_aligned_malloc(this->m_size * sizeof(T), align)));
|
||||
if (!m_buffer)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
void Resize(size_t newsize)
|
||||
{
|
||||
m_buffer.reset(reinterpret_cast<T*>(pcsx2_aligned_realloc(m_buffer.release(), newsize * sizeof(T), align, m_size * sizeof(T))));
|
||||
m_size = newsize;
|
||||
|
||||
if (!m_buffer)
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
void Free()
|
||||
{
|
||||
Alloc(0);
|
||||
}
|
||||
|
||||
// Makes enough room for the requested size. Existing data in the array is retained.
|
||||
void MakeRoomFor(uint size)
|
||||
{
|
||||
if (size <= m_size)
|
||||
return;
|
||||
Resize(size);
|
||||
}
|
||||
|
||||
AlignedBuffer& operator=(const AlignedBuffer& copy)
|
||||
{
|
||||
Alloc(copy.m_size);
|
||||
if (copy.m_size > 0)
|
||||
std::memcpy(m_buffer.get(), copy.m_buffer.get(), copy.m_size);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
AlignedBuffer& operator=(AlignedBuffer&& move)
|
||||
{
|
||||
m_buffer = std::move(move.m_buffer);
|
||||
m_size = move.m_size;
|
||||
move.m_size = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T* GetPtr(uint idx = 0) const
|
||||
{
|
||||
return &m_buffer[idx];
|
||||
}
|
||||
|
||||
T& operator[](uint idx)
|
||||
{
|
||||
return m_buffer[idx];
|
||||
}
|
||||
|
||||
const T& operator[](uint idx) const
|
||||
{
|
||||
return m_buffer[idx];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Threading.h"
|
||||
#include "General.h"
|
||||
#include "Assertions.h"
|
||||
#include "CrashHandler.h"
|
||||
|
||||
#include <mutex>
|
||||
#include "fmt/core.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "RedtapeWindows.h"
|
||||
#include <intrin.h>
|
||||
#include <tlhelp32.h>
|
||||
#endif
|
||||
|
||||
#ifdef __UNIX__
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
static std::mutex s_assertion_failed_mutex;
|
||||
|
||||
static inline void FreezeThreads(void** handle)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||
if (snapshot != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
THREADENTRY32 threadEntry;
|
||||
if (Thread32First(snapshot, &threadEntry))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (threadEntry.th32ThreadID == GetCurrentThreadId())
|
||||
continue;
|
||||
|
||||
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, threadEntry.th32ThreadID);
|
||||
if (hThread != nullptr)
|
||||
{
|
||||
SuspendThread(hThread);
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
} while (Thread32Next(snapshot, &threadEntry));
|
||||
}
|
||||
}
|
||||
|
||||
*handle = static_cast<void*>(snapshot);
|
||||
#else
|
||||
* handle = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void ResumeThreads(void* handle)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
THREADENTRY32 threadEntry;
|
||||
if (Thread32First(reinterpret_cast<HANDLE>(handle), &threadEntry))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (threadEntry.th32ThreadID == GetCurrentThreadId())
|
||||
continue;
|
||||
|
||||
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, threadEntry.th32ThreadID);
|
||||
if (hThread != nullptr)
|
||||
{
|
||||
ResumeThread(hThread);
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
} while (Thread32Next(reinterpret_cast<HANDLE>(handle), &threadEntry));
|
||||
}
|
||||
CloseHandle(reinterpret_cast<HANDLE>(handle));
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void pxOnAssertFail(const char* file, int line, const char* func, const char* msg)
|
||||
{
|
||||
std::unique_lock guard(s_assertion_failed_mutex);
|
||||
|
||||
void* handle;
|
||||
FreezeThreads(&handle);
|
||||
|
||||
char full_msg[512];
|
||||
std::snprintf(full_msg, sizeof(full_msg), "%s:%d: assertion failed in function %s: %s\n", file, line, func, msg);
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE error_handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
if (error_handle != INVALID_HANDLE_VALUE)
|
||||
WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), full_msg, static_cast<DWORD>(std::strlen(full_msg)), NULL, NULL);
|
||||
OutputDebugStringA(full_msg);
|
||||
|
||||
std::snprintf(
|
||||
full_msg, sizeof(full_msg),
|
||||
"Assertion failed in function %s (%s:%d):\n\n%s\n\nPress Abort to exit, Retry to break to debugger, or Ignore to attempt to continue.",
|
||||
func, file, line, msg);
|
||||
|
||||
int result = MessageBoxA(NULL, full_msg, NULL, MB_ABORTRETRYIGNORE | MB_ICONERROR);
|
||||
if (result == IDRETRY)
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
else if (result != IDIGNORE)
|
||||
{
|
||||
// try to save a crash dump before exiting
|
||||
CrashHandler::WriteDumpForCaller();
|
||||
TerminateProcess(GetCurrentProcess(), 0xBAADC0DE);
|
||||
}
|
||||
#else
|
||||
fputs(full_msg, stderr);
|
||||
fputs("\nAborting application.\n", stderr);
|
||||
fflush(stderr);
|
||||
AbortWithMessage(full_msg);
|
||||
#endif
|
||||
|
||||
ResumeThreads(handle);
|
||||
}
|
||||
@@ -10,11 +10,11 @@ add_library(common)
|
||||
# x86emitter sources
|
||||
target_sources(common PRIVATE
|
||||
AlignedMalloc.cpp
|
||||
SafeArray.inl
|
||||
Assertions.cpp
|
||||
Console.cpp
|
||||
CrashHandler.cpp
|
||||
DynamicLibrary.cpp
|
||||
Exceptions.cpp
|
||||
Error.cpp
|
||||
FastJmp.cpp
|
||||
FileSystem.cpp
|
||||
General.cpp
|
||||
@@ -70,7 +70,7 @@ target_sources(common PRIVATE
|
||||
DynamicLibrary.h
|
||||
Easing.h
|
||||
EnumOps.h
|
||||
Exceptions.h
|
||||
Error.h
|
||||
FastJmp.h
|
||||
FileSystem.h
|
||||
General.h
|
||||
@@ -81,7 +81,6 @@ target_sources(common PRIVATE
|
||||
HeapArray.h
|
||||
HTTPDownloader.h
|
||||
MemorySettingsInterface.h
|
||||
MemsetFast.inl
|
||||
MD5Digest.h
|
||||
MRCHelpers.h
|
||||
Path.h
|
||||
@@ -90,7 +89,6 @@ target_sources(common PRIVATE
|
||||
ReadbackSpinManager.h
|
||||
RedtapeWilCom.h
|
||||
RedtapeWindows.h
|
||||
SafeArray.h
|
||||
ScopedGuard.h
|
||||
SettingsInterface.h
|
||||
SettingsWrapper.h
|
||||
@@ -101,6 +99,7 @@ target_sources(common PRIVATE
|
||||
TraceLog.h
|
||||
WAVWriter.h
|
||||
WindowInfo.h
|
||||
WrappedMemCopy.h
|
||||
emitter/implement/dwshift.h
|
||||
emitter/implement/group1.h
|
||||
emitter/implement/group2.h
|
||||
|
||||
+2
-2
@@ -33,8 +33,8 @@ namespace CocoaTools
|
||||
std::optional<std::string> GetNonTranslocatedBundlePath();
|
||||
/// Move the given file to the trash, and return the path to its new location
|
||||
std::optional<std::string> MoveToTrash(std::string_view file);
|
||||
/// Launch the given application
|
||||
bool LaunchApplication(std::string_view file);
|
||||
/// Launch the given application once this one quits
|
||||
bool DelayedLaunch(std::string_view file);
|
||||
}
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
+9
-20
@@ -175,27 +175,16 @@ std::optional<std::string> CocoaTools::MoveToTrash(std::string_view file)
|
||||
return std::string([new_url fileSystemRepresentation]);
|
||||
}
|
||||
|
||||
bool CocoaTools::LaunchApplication(std::string_view file)
|
||||
bool CocoaTools::DelayedLaunch(std::string_view file)
|
||||
{
|
||||
NSURL* url = [NSURL fileURLWithPath:[[NSString alloc] initWithBytes:file.data() length:file.size() encoding:NSUTF8StringEncoding]];
|
||||
if (@available(macOS 10.15, *))
|
||||
{
|
||||
// replacement api is async which isn't great for us
|
||||
std::mutex done;
|
||||
bool output;
|
||||
done.lock();
|
||||
NSWorkspaceOpenConfiguration* config = [NSWorkspaceOpenConfiguration new];
|
||||
[config setCreatesNewApplicationInstance:YES];
|
||||
[[NSWorkspace sharedWorkspace] openApplicationAtURL:url configuration:config completionHandler:[&](NSRunningApplication*_Nullable app, NSError*_Nullable error) {
|
||||
output = app != nullptr;
|
||||
done.unlock();
|
||||
@autoreleasepool {
|
||||
NSTask* task = [NSTask new];
|
||||
[task setExecutableURL:[NSURL fileURLWithPath:@"/bin/sh"]];
|
||||
[task setEnvironment:@{
|
||||
@"WAITPID": [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]],
|
||||
@"LAUNCHAPP": [[NSString alloc] initWithBytes:file.data() length:file.size() encoding:NSUTF8StringEncoding],
|
||||
}];
|
||||
done.lock();
|
||||
done.unlock();
|
||||
return output;
|
||||
}
|
||||
else
|
||||
{
|
||||
return [[NSWorkspace sharedWorkspace] launchApplicationAtURL:url options:NSWorkspaceLaunchNewInstance configuration:@{} error:nil];
|
||||
[task setArguments:@[@"-c", @"while /bin/ps -p $WAITPID > /dev/null; do /bin/sleep 0.1; done; exec /usr/bin/open \"$LAUNCHAPP\";"]];
|
||||
return [task launchAndReturnError:nil];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "Error.h"
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
// Platform-specific includes
|
||||
#if defined(_WIN32)
|
||||
#include "RedtapeWindows.h"
|
||||
static_assert(std::is_same<DWORD, unsigned long>::value, "DWORD is unsigned long");
|
||||
static_assert(std::is_same<HRESULT, long>::value, "HRESULT is long");
|
||||
#endif
|
||||
|
||||
Error::Error() = default;
|
||||
|
||||
Error::Error(const Error& c) = default;
|
||||
|
||||
Error::Error(Error&& e) = default;
|
||||
|
||||
Error::~Error() = default;
|
||||
|
||||
void Error::Clear()
|
||||
{
|
||||
m_description = {};
|
||||
}
|
||||
|
||||
void Error::SetErrno(int err)
|
||||
{
|
||||
m_type = Type::Errno;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
char buf[128];
|
||||
if (strerror_s(buf, sizeof(buf), err) != 0)
|
||||
m_description = fmt::format("errno {}: {}", err, buf);
|
||||
else
|
||||
m_description = fmt::format("errno {}: <Could not get error message>", err);
|
||||
#else
|
||||
const char* buf = std::strerror(err);
|
||||
if (buf)
|
||||
m_description = fmt::format("errno {}: {}", err, buf);
|
||||
else
|
||||
m_description = fmt::format("errno {}: <Could not get error message>", err);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Error::SetErrno(Error* errptr, int err)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetErrno(err);
|
||||
}
|
||||
|
||||
void Error::SetString(std::string description)
|
||||
{
|
||||
m_type = Type::User;
|
||||
m_description = std::move(description);
|
||||
}
|
||||
|
||||
void Error::SetString(Error* errptr, std::string description)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetString(std::move(description));
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void Error::SetWin32(unsigned long err)
|
||||
{
|
||||
m_type = Type::Win32;
|
||||
|
||||
char buf[128];
|
||||
const DWORD r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, 0, buf, sizeof(buf), nullptr);
|
||||
if (r > 0)
|
||||
m_description = fmt::format("Win32 Error {}: {}", err, std::string_view(buf, r));
|
||||
else
|
||||
m_description = fmt::format("Win32 Error {}: <Could not resolve system error ID>");
|
||||
}
|
||||
|
||||
void Error::SetWin32(Error* errptr, unsigned long err)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetWin32(err);
|
||||
}
|
||||
|
||||
void Error::SetHResult(long err)
|
||||
{
|
||||
m_type = Type::HResult;
|
||||
|
||||
char buf[128];
|
||||
const DWORD r = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, err, 0, buf, sizeof(buf), nullptr);
|
||||
if (r > 0)
|
||||
m_description = fmt::format("HRESULT {:08X}: {}", err, std::string_view(buf, r));
|
||||
else
|
||||
m_description = fmt::format("HRESULT {:08X}: <Could not resolve system error ID>");
|
||||
}
|
||||
|
||||
void Error::SetHResult(Error* errptr, long err)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetHResult(err);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void Error::SetSocket(int err)
|
||||
{
|
||||
// Socket errors are win32 errors on windows
|
||||
#ifdef _WIN32
|
||||
SetWin32(err);
|
||||
#else
|
||||
SetErrno(err);
|
||||
#endif
|
||||
m_type = Type::Socket;
|
||||
}
|
||||
|
||||
void Error::SetSocket(Error* errptr, int err)
|
||||
{
|
||||
if (errptr)
|
||||
errptr->SetSocket(err);
|
||||
}
|
||||
|
||||
Error Error::CreateNone()
|
||||
{
|
||||
return Error();
|
||||
}
|
||||
|
||||
Error Error::CreateErrno(int err)
|
||||
{
|
||||
Error ret;
|
||||
ret.SetErrno(err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Error Error::CreateSocket(int err)
|
||||
{
|
||||
Error ret;
|
||||
ret.SetSocket(err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Error Error::CreateString(std::string description)
|
||||
{
|
||||
Error ret;
|
||||
ret.SetString(std::move(description));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
Error Error::CreateWin32(unsigned long err)
|
||||
{
|
||||
Error ret;
|
||||
ret.SetWin32(err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Error Error::CreateHResult(long err)
|
||||
{
|
||||
Error ret;
|
||||
ret.SetHResult(err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Error& Error::operator=(const Error& e) = default;
|
||||
|
||||
Error& Error::operator=(Error&& e) = default;
|
||||
|
||||
bool Error::operator==(const Error& e) const
|
||||
{
|
||||
return (m_type == e.m_type && m_description == e.m_description);
|
||||
}
|
||||
|
||||
bool Error::operator!=(const Error& e) const
|
||||
{
|
||||
return (m_type != e.m_type || m_description != e.m_description);
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2022 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "Pcsx2Defs.h"
|
||||
#include <string>
|
||||
|
||||
class Error
|
||||
{
|
||||
public:
|
||||
Error();
|
||||
Error(const Error& e);
|
||||
Error(Error&& e);
|
||||
~Error();
|
||||
|
||||
enum class Type
|
||||
{
|
||||
None = 0,
|
||||
Errno = 1,
|
||||
Socket = 2,
|
||||
User = 3,
|
||||
Win32 = 4,
|
||||
HResult = 5,
|
||||
};
|
||||
|
||||
__fi Type GetType() const { return m_type; }
|
||||
__fi const std::string& GetDescription() const { return m_description; }
|
||||
|
||||
void Clear();
|
||||
|
||||
/// Error that is set by system functions, such as open().
|
||||
void SetErrno(int err);
|
||||
|
||||
/// Error that is set by socket functions, such as socket(). On Unix this is the same as errno.
|
||||
void SetSocket(int err);
|
||||
|
||||
/// Set both description and message.
|
||||
void SetString(std::string description);
|
||||
|
||||
#ifdef _WIN32
|
||||
/// Error that is returned by some Win32 functions, such as RegOpenKeyEx. Also used by other APIs through GetLastError().
|
||||
void SetWin32(unsigned long err);
|
||||
|
||||
/// Error that is returned by Win32 COM methods, e.g. S_OK.
|
||||
void SetHResult(long err);
|
||||
#endif
|
||||
|
||||
static Error CreateNone();
|
||||
static Error CreateErrno(int err);
|
||||
static Error CreateSocket(int err);
|
||||
static Error CreateString(std::string description);
|
||||
#ifdef _WIN32
|
||||
static Error CreateWin32(unsigned long err);
|
||||
static Error CreateHResult(long err);
|
||||
#endif
|
||||
|
||||
// helpers for setting
|
||||
static void SetErrno(Error* errptr, int err);
|
||||
static void SetSocket(Error* errptr, int err);
|
||||
static void SetString(Error* errptr, std::string description);
|
||||
static void SetWin32(Error* errptr, unsigned long err);
|
||||
static void SetHResult(Error* errptr, long err);
|
||||
|
||||
Error& operator=(const Error& e);
|
||||
Error& operator=(Error&& e);
|
||||
bool operator==(const Error& e) const;
|
||||
bool operator!=(const Error& e) const;
|
||||
|
||||
private:
|
||||
Type m_type = Type::None;
|
||||
std::string m_description;
|
||||
};
|
||||
@@ -1,346 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Threading.h"
|
||||
#include "General.h"
|
||||
#include "Exceptions.h"
|
||||
#include "CrashHandler.h"
|
||||
|
||||
#include <mutex>
|
||||
#include "fmt/core.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "RedtapeWindows.h"
|
||||
#include <intrin.h>
|
||||
#include <tlhelp32.h>
|
||||
#endif
|
||||
|
||||
#ifdef __UNIX__
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
static std::mutex s_assertion_failed_mutex;
|
||||
|
||||
static inline void FreezeThreads(void** handle)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||
if (snapshot != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
THREADENTRY32 threadEntry;
|
||||
if (Thread32First(snapshot, &threadEntry))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (threadEntry.th32ThreadID == GetCurrentThreadId())
|
||||
continue;
|
||||
|
||||
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, threadEntry.th32ThreadID);
|
||||
if (hThread != nullptr)
|
||||
{
|
||||
SuspendThread(hThread);
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
} while (Thread32Next(snapshot, &threadEntry));
|
||||
}
|
||||
}
|
||||
|
||||
*handle = static_cast<void*>(snapshot);
|
||||
#else
|
||||
* handle = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void ResumeThreads(void* handle)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
if (handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
THREADENTRY32 threadEntry;
|
||||
if (Thread32First(reinterpret_cast<HANDLE>(handle), &threadEntry))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (threadEntry.th32ThreadID == GetCurrentThreadId())
|
||||
continue;
|
||||
|
||||
HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, threadEntry.th32ThreadID);
|
||||
if (hThread != nullptr)
|
||||
{
|
||||
ResumeThread(hThread);
|
||||
CloseHandle(hThread);
|
||||
}
|
||||
} while (Thread32Next(reinterpret_cast<HANDLE>(handle), &threadEntry));
|
||||
}
|
||||
CloseHandle(reinterpret_cast<HANDLE>(handle));
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void pxOnAssertFail(const char* file, int line, const char* func, const char* msg)
|
||||
{
|
||||
std::unique_lock guard(s_assertion_failed_mutex);
|
||||
|
||||
void* handle;
|
||||
FreezeThreads(&handle);
|
||||
|
||||
char full_msg[512];
|
||||
std::snprintf(full_msg, sizeof(full_msg), "%s:%d: assertion failed in function %s: %s\n", file, line, func, msg);
|
||||
|
||||
#if defined(_WIN32)
|
||||
HANDLE error_handle = GetStdHandle(STD_ERROR_HANDLE);
|
||||
if (error_handle != INVALID_HANDLE_VALUE)
|
||||
WriteConsoleA(GetStdHandle(STD_ERROR_HANDLE), full_msg, static_cast<DWORD>(std::strlen(full_msg)), NULL, NULL);
|
||||
OutputDebugStringA(full_msg);
|
||||
|
||||
std::snprintf(
|
||||
full_msg, sizeof(full_msg),
|
||||
"Assertion failed in function %s (%s:%d):\n\n%s\n\nPress Abort to exit, Retry to break to debugger, or Ignore to attempt to continue.",
|
||||
func, file, line, msg);
|
||||
|
||||
int result = MessageBoxA(NULL, full_msg, NULL, MB_ABORTRETRYIGNORE | MB_ICONERROR);
|
||||
if (result == IDRETRY)
|
||||
{
|
||||
__debugbreak();
|
||||
}
|
||||
else if (result != IDIGNORE)
|
||||
{
|
||||
// try to save a crash dump before exiting
|
||||
CrashHandler::WriteDumpForCaller();
|
||||
TerminateProcess(GetCurrentProcess(), 0xBAADC0DE);
|
||||
}
|
||||
#else
|
||||
fputs(full_msg, stderr);
|
||||
fputs("\nAborting application.\n", stderr);
|
||||
fflush(stderr);
|
||||
AbortWithMessage(full_msg);
|
||||
#endif
|
||||
|
||||
ResumeThreads(handle);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// BaseException (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
BaseException& BaseException::SetBothMsgs(const char* msg_diag)
|
||||
{
|
||||
m_message_user = msg_diag ? std::string(msg_diag) : std::string();
|
||||
return SetDiagMsg(msg_diag);
|
||||
}
|
||||
|
||||
BaseException& BaseException::SetDiagMsg(std::string msg_diag)
|
||||
{
|
||||
m_message_diag = std::move(msg_diag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BaseException& BaseException::SetUserMsg(std::string msg_user)
|
||||
{
|
||||
m_message_user = std::move(msg_user);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string BaseException::FormatDiagnosticMessage() const
|
||||
{
|
||||
return m_message_diag;
|
||||
}
|
||||
|
||||
std::string BaseException::FormatDisplayMessage() const
|
||||
{
|
||||
return m_message_user.empty() ? m_message_diag : m_message_user;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Exception::RuntimeError (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
Exception::RuntimeError::RuntimeError(const std::runtime_error& ex, const char* prefix /* = nullptr */)
|
||||
{
|
||||
IsSilent = false;
|
||||
|
||||
const bool has_prefix = prefix && prefix[0] != 0;
|
||||
|
||||
SetDiagMsg(fmt::format("STL Runtime Error{}{}{}: {}",
|
||||
has_prefix ? " (" : "", prefix ? prefix : "", has_prefix ? ")" : "",
|
||||
ex.what()));
|
||||
}
|
||||
|
||||
Exception::RuntimeError::RuntimeError(const std::exception& ex, const char* prefix /* = nullptr */)
|
||||
{
|
||||
IsSilent = false;
|
||||
|
||||
const bool has_prefix = prefix && prefix[0] != 0;
|
||||
|
||||
SetDiagMsg(fmt::format("STL Exception{}{}{}: {}",
|
||||
has_prefix ? " (" : "", prefix ? prefix : "", has_prefix ? ")" : "",
|
||||
ex.what()));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Exception::BadStream (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
std::string Exception::BadStream::FormatDiagnosticMessage() const
|
||||
{
|
||||
std::string retval;
|
||||
_formatDiagMsg(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string Exception::BadStream::FormatDisplayMessage() const
|
||||
{
|
||||
std::string retval;
|
||||
_formatUserMsg(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Exception::BadStream::_formatDiagMsg(std::string& dest) const
|
||||
{
|
||||
fmt::format_to(std::back_inserter(dest), "Path: ");
|
||||
if (!StreamName.empty())
|
||||
fmt::format_to(std::back_inserter(dest), "{}", StreamName);
|
||||
else
|
||||
dest += "[Unnamed or unknown]";
|
||||
|
||||
if (!m_message_diag.empty())
|
||||
fmt::format_to(std::back_inserter(dest), "\n{}", m_message_diag);
|
||||
}
|
||||
|
||||
void Exception::BadStream::_formatUserMsg(std::string& dest) const
|
||||
{
|
||||
fmt::format_to(std::back_inserter(dest), "Path: ");
|
||||
if (!StreamName.empty())
|
||||
fmt::format_to(std::back_inserter(dest), "{}", StreamName);
|
||||
else
|
||||
dest += "[Unnamed or unknown]";
|
||||
|
||||
if (!m_message_user.empty())
|
||||
fmt::format_to(std::back_inserter(dest), "\n{}", m_message_user);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Exception::CannotCreateStream (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
std::string Exception::CannotCreateStream::FormatDiagnosticMessage() const
|
||||
{
|
||||
std::string retval;
|
||||
retval = "File could not be created.";
|
||||
_formatDiagMsg(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string Exception::CannotCreateStream::FormatDisplayMessage() const
|
||||
{
|
||||
std::string retval;
|
||||
retval = "A file could not be created.\n";
|
||||
_formatUserMsg(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Exception::FileNotFound (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
std::string Exception::FileNotFound::FormatDiagnosticMessage() const
|
||||
{
|
||||
std::string retval;
|
||||
retval = "File not found.\n";
|
||||
_formatDiagMsg(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string Exception::FileNotFound::FormatDisplayMessage() const
|
||||
{
|
||||
std::string retval;
|
||||
retval = "File not found.\n";
|
||||
_formatUserMsg(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Exception::AccessDenied (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
std::string Exception::AccessDenied::FormatDiagnosticMessage() const
|
||||
{
|
||||
std::string retval;
|
||||
retval = "Permission denied to file.\n";
|
||||
_formatDiagMsg(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string Exception::AccessDenied::FormatDisplayMessage() const
|
||||
{
|
||||
std::string retval;
|
||||
retval = "Permission denied while trying to open file, likely due to insufficient user account rights.\n";
|
||||
_formatUserMsg(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Exception::EndOfStream (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
std::string Exception::EndOfStream::FormatDiagnosticMessage() const
|
||||
{
|
||||
std::string retval;
|
||||
retval = "Unexpected end of file or stream.\n";
|
||||
_formatDiagMsg(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string Exception::EndOfStream::FormatDisplayMessage() const
|
||||
{
|
||||
std::string retval;
|
||||
retval = "Unexpected end of file or stream encountered. File is probably truncated or corrupted.\n";
|
||||
_formatUserMsg(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Exceptions from Errno (POSIX)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
// Translates an Errno code into an exception.
|
||||
// Throws an exception based on the given error code (usually taken from ANSI C's errno)
|
||||
std::unique_ptr<BaseException> Exception::FromErrno(std::string streamname, int errcode)
|
||||
{
|
||||
pxAssumeDev(errcode != 0, "Invalid NULL error code? (errno)");
|
||||
|
||||
switch (errcode)
|
||||
{
|
||||
case EINVAL:
|
||||
pxFailDev("Invalid argument");
|
||||
return std::unique_ptr<BaseException>(&(new Exception::BadStream(streamname))->SetDiagMsg("Invalid argument? (likely caused by an unforgivable programmer error!)"));
|
||||
|
||||
case EACCES: // Access denied!
|
||||
return std::unique_ptr<BaseException>(new Exception::AccessDenied(streamname));
|
||||
|
||||
case EMFILE: // Too many open files!
|
||||
return std::unique_ptr<BaseException>(&(new Exception::CannotCreateStream(streamname))->SetDiagMsg("Too many open files")); // File handle allocation failure
|
||||
|
||||
case EEXIST:
|
||||
return std::unique_ptr<BaseException>(&(new Exception::CannotCreateStream(streamname))->SetDiagMsg("File already exists"));
|
||||
|
||||
case ENOENT: // File not found!
|
||||
return std::unique_ptr<BaseException>(new Exception::FileNotFound(streamname));
|
||||
|
||||
case EPIPE:
|
||||
return std::unique_ptr<BaseException>(&(new Exception::BadStream(streamname))->SetDiagMsg("Broken pipe"));
|
||||
|
||||
case EBADF:
|
||||
return std::unique_ptr<BaseException>(&(new Exception::BadStream(streamname))->SetDiagMsg("Bad file number"));
|
||||
|
||||
default:
|
||||
return std::unique_ptr<BaseException>(&(new Exception::BadStream(streamname))->SetDiagMsg(fmt::format("General file/stream error [errno: {}]", errcode)));
|
||||
}
|
||||
}
|
||||
@@ -1,255 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
namespace Exception
|
||||
{
|
||||
class BaseException;
|
||||
|
||||
std::unique_ptr<BaseException> FromErrno(std::string streamname, int errcode);
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// BaseException
|
||||
// --------------------------------------------------------------------------------------
|
||||
// std::exception sucks, and isn't entirely cross-platform reliable in its implementation,
|
||||
// so I made a replacement. The internal messages are non-const, which means that a
|
||||
// catch clause can optionally modify them and then re-throw to a top-level handler.
|
||||
//
|
||||
// Note, this class is "abstract" which means you shouldn't use it directly like, ever.
|
||||
// Use Exception::RuntimeError instead for generic exceptions.
|
||||
//
|
||||
// Because exceptions are the (only!) really useful example of multiple inheritance,
|
||||
// this class has only a trivial constructor, and must be manually initialized using
|
||||
// InitBaseEx() or by individual member assignments. This is because C++ multiple inheritence
|
||||
// is, by design, a lot of fail, especially when class initializers are mixed in.
|
||||
//
|
||||
// [TODO] : Add an InnerException component, and Clone() facility.
|
||||
//
|
||||
class BaseException
|
||||
{
|
||||
protected:
|
||||
std::string m_message_diag; // (untranslated) a "detailed" message of what disastrous thing has occurred!
|
||||
std::string m_message_user; // (translated) a "detailed" message of what disastrous thing has occurred!
|
||||
|
||||
public:
|
||||
virtual ~BaseException() = default;
|
||||
|
||||
const std::string& DiagMsg() const { return m_message_diag; }
|
||||
const std::string& UserMsg() const { return m_message_user; }
|
||||
|
||||
std::string& DiagMsg() { return m_message_diag; }
|
||||
std::string& UserMsg() { return m_message_user; }
|
||||
|
||||
BaseException& SetBothMsgs(const char* msg_diag);
|
||||
BaseException& SetDiagMsg(std::string msg_diag);
|
||||
BaseException& SetUserMsg(std::string msg_user);
|
||||
|
||||
// Returns a message suitable for diagnostic / logging purposes.
|
||||
// This message is always in English, and includes a full stack trace.
|
||||
virtual std::string FormatDiagnosticMessage() const;
|
||||
|
||||
// Returns a message suitable for end-user display.
|
||||
// This message is usually meant for display in a user popup or such.
|
||||
virtual std::string FormatDisplayMessage() const;
|
||||
|
||||
virtual void Rethrow() const = 0;
|
||||
virtual BaseException* Clone() const = 0;
|
||||
};
|
||||
|
||||
// Some helper macros for defining the standard constructors of internationalized constructors
|
||||
// Parameters:
|
||||
// classname - Yeah, the name of this class being defined. :)
|
||||
//
|
||||
// defmsg - default message (in english), which will be used for both english and i18n messages.
|
||||
// The text string will be passed through the translator, so if it's int he gettext database
|
||||
// it will be optionally translated.
|
||||
//
|
||||
// BUGZ?? I'd rather use 'classname' on the Clone() prototype, but for some reason it generates
|
||||
// ambiguity errors on virtual inheritance (it really shouldn't!). So I have to force it to the
|
||||
// BaseException base class. Not sure if this is Stupid Standard Tricks or Stupid MSVC Tricks. --air
|
||||
//
|
||||
// (update: web searches indicate it's MSVC specific -- happens in 2008, not sure about 2010).
|
||||
//
|
||||
#define DEFINE_EXCEPTION_COPYTORS(classname, parent) \
|
||||
private: \
|
||||
typedef parent _parent; \
|
||||
\
|
||||
public: \
|
||||
virtual ~classname() = default; \
|
||||
\
|
||||
virtual void Rethrow() const override \
|
||||
{ \
|
||||
throw *this; \
|
||||
} \
|
||||
\
|
||||
virtual classname* Clone() const override \
|
||||
{ \
|
||||
return new classname(*this); \
|
||||
}
|
||||
|
||||
#define DEFINE_EXCEPTION_MESSAGES(classname) \
|
||||
public: \
|
||||
classname& SetBothMsgs(const char* msg_diag) \
|
||||
{ \
|
||||
BaseException::SetBothMsgs(msg_diag); \
|
||||
return *this; \
|
||||
} \
|
||||
\
|
||||
classname& SetDiagMsg(std::string msg_diag) \
|
||||
{ \
|
||||
m_message_diag = msg_diag; \
|
||||
return *this; \
|
||||
} \
|
||||
\
|
||||
classname& SetUserMsg(std::string msg_user) \
|
||||
{ \
|
||||
m_message_user = std::move(msg_user); \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
#define DEFINE_RUNTIME_EXCEPTION(classname, parent, message) \
|
||||
DEFINE_EXCEPTION_COPYTORS(classname, parent) \
|
||||
classname() \
|
||||
{ \
|
||||
SetDiagMsg(message); \
|
||||
} \
|
||||
DEFINE_EXCEPTION_MESSAGES(classname)
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// RuntimeError - Generalized Exceptions with Recoverable Traits!
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
class RuntimeError : public BaseException
|
||||
{
|
||||
DEFINE_EXCEPTION_COPYTORS(RuntimeError, BaseException)
|
||||
DEFINE_EXCEPTION_MESSAGES(RuntimeError)
|
||||
|
||||
public:
|
||||
bool IsSilent;
|
||||
|
||||
RuntimeError() { IsSilent = false; }
|
||||
RuntimeError(const std::runtime_error& ex, const char* prefix = nullptr);
|
||||
RuntimeError(const std::exception& ex, const char* prefix = nullptr);
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// Streaming (file) Exceptions:
|
||||
// Stream / BadStream / CannotCreateStream / FileNotFound / AccessDenied / EndOfStream
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
#define DEFINE_STREAM_EXCEPTION(classname, parent) \
|
||||
DEFINE_RUNTIME_EXCEPTION(classname, parent, "") \
|
||||
classname(std::string filename) \
|
||||
{ \
|
||||
StreamName = filename; \
|
||||
} \
|
||||
virtual classname& SetStreamName(std::string name) override \
|
||||
{ \
|
||||
StreamName = std::move(name); \
|
||||
return *this; \
|
||||
} \
|
||||
\
|
||||
virtual classname& SetStreamName(const char* name) override \
|
||||
{ \
|
||||
StreamName = name; \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
// A generic base error class for bad streams -- corrupted data, sudden closures, loss of
|
||||
// connection, or anything else that would indicate a failure to open a stream or read the
|
||||
// data after the stream was successfully opened.
|
||||
//
|
||||
class BadStream : public RuntimeError
|
||||
{
|
||||
DEFINE_RUNTIME_EXCEPTION(BadStream, RuntimeError, "")
|
||||
|
||||
public:
|
||||
BadStream(std::string filename)
|
||||
: StreamName(std::move(filename))
|
||||
{
|
||||
}
|
||||
virtual BadStream& SetStreamName(std::string name)
|
||||
{
|
||||
StreamName = std::move(name);
|
||||
return *this;
|
||||
}
|
||||
virtual BadStream& SetStreamName(const char* name)
|
||||
{
|
||||
StreamName = name;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string StreamName; // name of the stream (if applicable)
|
||||
|
||||
virtual std::string FormatDiagnosticMessage() const override;
|
||||
virtual std::string FormatDisplayMessage() const override;
|
||||
|
||||
protected:
|
||||
void _formatDiagMsg(std::string& dest) const;
|
||||
void _formatUserMsg(std::string& dest) const;
|
||||
};
|
||||
|
||||
// A generic exception for odd-ball stream creation errors.
|
||||
//
|
||||
class CannotCreateStream : public BadStream
|
||||
{
|
||||
DEFINE_STREAM_EXCEPTION(CannotCreateStream, BadStream)
|
||||
|
||||
virtual std::string FormatDiagnosticMessage() const override;
|
||||
virtual std::string FormatDisplayMessage() const override;
|
||||
};
|
||||
|
||||
// Exception thrown when an attempt to open a non-existent file is made.
|
||||
// (this exception can also mean file permissions are invalid)
|
||||
//
|
||||
class FileNotFound : public CannotCreateStream
|
||||
{
|
||||
public:
|
||||
DEFINE_STREAM_EXCEPTION(FileNotFound, CannotCreateStream)
|
||||
|
||||
virtual std::string FormatDiagnosticMessage() const override;
|
||||
virtual std::string FormatDisplayMessage() const override;
|
||||
};
|
||||
|
||||
class AccessDenied : public CannotCreateStream
|
||||
{
|
||||
public:
|
||||
DEFINE_STREAM_EXCEPTION(AccessDenied, CannotCreateStream)
|
||||
|
||||
virtual std::string FormatDiagnosticMessage() const override;
|
||||
virtual std::string FormatDisplayMessage() const override;
|
||||
};
|
||||
|
||||
// EndOfStream can be used either as an error, or used just as a shortcut for manual
|
||||
// feof checks.
|
||||
//
|
||||
class EndOfStream : public BadStream
|
||||
{
|
||||
public:
|
||||
DEFINE_STREAM_EXCEPTION(EndOfStream, BadStream)
|
||||
|
||||
virtual std::string FormatDiagnosticMessage() const override;
|
||||
virtual std::string FormatDisplayMessage() const override;
|
||||
};
|
||||
} // namespace Exception
|
||||
|
||||
using Exception::BaseException;
|
||||
+32
-12
@@ -14,12 +14,14 @@
|
||||
*/
|
||||
|
||||
#include "FileSystem.h"
|
||||
#include "Error.h"
|
||||
#include "Path.h"
|
||||
#include "Assertions.h"
|
||||
#include "Console.h"
|
||||
#include "StringUtil.h"
|
||||
#include "Path.h"
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits>
|
||||
@@ -596,7 +598,7 @@ std::string Path::Combine(const std::string_view& base, const std::string_view&
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode)
|
||||
std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode, Error* error)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename));
|
||||
@@ -604,23 +606,34 @@ std::FILE* FileSystem::OpenCFile(const char* filename, const char* mode)
|
||||
if (!wfilename.empty() && !wmode.empty())
|
||||
{
|
||||
std::FILE* fp;
|
||||
if (_wfopen_s(&fp, wfilename.c_str(), wmode.c_str()) != 0)
|
||||
const errno_t err = _wfopen_s(&fp, wfilename.c_str(), wmode.c_str());
|
||||
if (err != 0)
|
||||
{
|
||||
Error::SetErrno(error, err);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return fp;
|
||||
}
|
||||
|
||||
std::FILE* fp;
|
||||
if (fopen_s(&fp, filename, mode) != 0)
|
||||
const errno_t err = fopen_s(&fp, filename, mode);
|
||||
if (err != 0)
|
||||
{
|
||||
Error::SetErrno(error, err);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return fp;
|
||||
#else
|
||||
return std::fopen(filename, mode);
|
||||
std::FILE* fp = std::fopen(filename, mode);
|
||||
if (!fp)
|
||||
Error::SetErrno(error, errno);
|
||||
return fp;
|
||||
#endif
|
||||
}
|
||||
|
||||
int FileSystem::OpenFDFile(const char* filename, int flags, int mode)
|
||||
int FileSystem::OpenFDFile(const char* filename, int flags, int mode, Error* error)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename));
|
||||
@@ -629,16 +642,19 @@ int FileSystem::OpenFDFile(const char* filename, int flags, int mode)
|
||||
|
||||
return -1;
|
||||
#else
|
||||
return open(filename, flags, mode);
|
||||
const int fd = open(filename, flags, mode);
|
||||
if (fd < 0)
|
||||
Error::SetErrno(error, errno);
|
||||
return fd;
|
||||
#endif
|
||||
}
|
||||
|
||||
FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, const char* mode)
|
||||
FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, const char* mode, Error* error)
|
||||
{
|
||||
return ManagedCFilePtr(OpenCFile(filename, mode), [](std::FILE* fp) { std::fclose(fp); });
|
||||
return ManagedCFilePtr(OpenCFile(filename, mode, error), [](std::FILE* fp) { std::fclose(fp); });
|
||||
}
|
||||
|
||||
std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode)
|
||||
std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const std::wstring wfilename(StringUtil::UTF8StringToWideString(filename));
|
||||
@@ -668,15 +684,19 @@ std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, F
|
||||
if (fp)
|
||||
return fp;
|
||||
|
||||
Error::SetErrno(error, errno);
|
||||
return nullptr;
|
||||
#else
|
||||
return std::fopen(filename, mode);
|
||||
std::FILE* fp = std::fopen(filename, mode);
|
||||
if (!fp)
|
||||
Error::SetErrno(error, errno);
|
||||
return fp;
|
||||
#endif
|
||||
}
|
||||
|
||||
FileSystem::ManagedCFilePtr FileSystem::OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode)
|
||||
FileSystem::ManagedCFilePtr FileSystem::OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error)
|
||||
{
|
||||
return ManagedCFilePtr(OpenSharedCFile(filename, mode, share_mode), [](std::FILE* fp) { std::fclose(fp); });
|
||||
return ManagedCFilePtr(OpenSharedCFile(filename, mode, share_mode, error), [](std::FILE* fp) { std::fclose(fp); });
|
||||
}
|
||||
|
||||
int FileSystem::FSeek64(std::FILE* fp, s64 offset, int whence)
|
||||
|
||||
+7
-5
@@ -23,6 +23,8 @@
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
|
||||
class Error;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define FS_OSPATH_SEPARATOR_CHARACTER '\\'
|
||||
#define FS_OSPATH_SEPARATOR_STR "\\"
|
||||
@@ -102,13 +104,13 @@ namespace FileSystem
|
||||
|
||||
/// open files
|
||||
using ManagedCFilePtr = std::unique_ptr<std::FILE, void (*)(std::FILE*)>;
|
||||
ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode);
|
||||
std::FILE* OpenCFile(const char* filename, const char* mode);
|
||||
ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode, Error* error = nullptr);
|
||||
std::FILE* OpenCFile(const char* filename, const char* mode, Error* error = nullptr);
|
||||
int FSeek64(std::FILE* fp, s64 offset, int whence);
|
||||
s64 FTell64(std::FILE* fp);
|
||||
s64 FSize64(std::FILE* fp);
|
||||
|
||||
int OpenFDFile(const char* filename, int flags, int mode);
|
||||
int OpenFDFile(const char* filename, int flags, int mode, Error* error = nullptr);
|
||||
|
||||
/// Sharing modes for OpenSharedCFile().
|
||||
enum class FileShareMode
|
||||
@@ -121,8 +123,8 @@ namespace FileSystem
|
||||
|
||||
/// Opens a file in shareable mode (where other processes can access it concurrently).
|
||||
/// Only has an effect on Windows systems.
|
||||
ManagedCFilePtr OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode);
|
||||
std::FILE* OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode);
|
||||
ManagedCFilePtr OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error = nullptr);
|
||||
std::FILE* OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error = nullptr);
|
||||
|
||||
std::optional<std::vector<u8>> ReadBinaryFile(const char* filename);
|
||||
std::optional<std::vector<u8>> ReadBinaryFile(std::FILE* fp);
|
||||
|
||||
@@ -198,24 +198,6 @@ private:
|
||||
#define SafeSysMunmap(ptr, size) \
|
||||
((void)(HostSys::Munmap(ptr, size), (ptr) = 0))
|
||||
|
||||
// This method can clear any object-like entity -- which is anything that is not a pointer.
|
||||
// Structures, static arrays, etc. No need to include sizeof() crap, this does it automatically
|
||||
// for you!
|
||||
template <typename T>
|
||||
static __fi void memzero(T& object)
|
||||
{
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
std::memset(&object, 0, sizeof(T));
|
||||
}
|
||||
|
||||
// This method clears an object with the given 8 bit value.
|
||||
template <u8 data, typename T>
|
||||
static __fi void memset8(T& object)
|
||||
{
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
std::memset(&object, data, sizeof(T));
|
||||
}
|
||||
|
||||
extern u64 GetTickFrequency();
|
||||
extern u64 GetCPUTicks();
|
||||
extern u64 GetPhysicalMemory();
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "common/Align.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/Exceptions.h"
|
||||
#include "common/General.h"
|
||||
|
||||
// Apple uses the MAP_ANON define instead of MAP_ANONYMOUS, but they mean
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
template <u8 data>
|
||||
__noinline void memset_sse_a(void* dest, const size_t size)
|
||||
{
|
||||
const uint MZFqwc = size / 16;
|
||||
|
||||
pxAssert((size & 0xf) == 0);
|
||||
|
||||
__m128 srcreg;
|
||||
|
||||
if (data != 0)
|
||||
{
|
||||
alignas(16) static const u8 loadval[8] = {data, data, data, data, data, data, data, data};
|
||||
srcreg = _mm_loadh_pi(_mm_load_ps((float*)loadval), (__m64*)loadval);
|
||||
}
|
||||
else
|
||||
srcreg = _mm_setzero_ps();
|
||||
|
||||
float(*destxmm)[4] = (float(*)[4])dest;
|
||||
|
||||
switch (MZFqwc & 0x07)
|
||||
{
|
||||
case 0x07:
|
||||
_mm_store_ps(&destxmm[0x07 - 1][0], srcreg);
|
||||
// Fall through
|
||||
case 0x06:
|
||||
_mm_store_ps(&destxmm[0x06 - 1][0], srcreg);
|
||||
// Fall through
|
||||
case 0x05:
|
||||
_mm_store_ps(&destxmm[0x05 - 1][0], srcreg);
|
||||
// Fall through
|
||||
case 0x04:
|
||||
_mm_store_ps(&destxmm[0x04 - 1][0], srcreg);
|
||||
// Fall through
|
||||
case 0x03:
|
||||
_mm_store_ps(&destxmm[0x03 - 1][0], srcreg);
|
||||
// Fall through
|
||||
case 0x02:
|
||||
_mm_store_ps(&destxmm[0x02 - 1][0], srcreg);
|
||||
// Fall through
|
||||
case 0x01:
|
||||
_mm_store_ps(&destxmm[0x01 - 1][0], srcreg);
|
||||
// Fall through
|
||||
}
|
||||
|
||||
destxmm += (MZFqwc & 0x07);
|
||||
for (uint i = 0; i < MZFqwc / 8; ++i, destxmm += 8)
|
||||
{
|
||||
_mm_store_ps(&destxmm[0][0], srcreg);
|
||||
_mm_store_ps(&destxmm[1][0], srcreg);
|
||||
_mm_store_ps(&destxmm[2][0], srcreg);
|
||||
_mm_store_ps(&destxmm[3][0], srcreg);
|
||||
_mm_store_ps(&destxmm[4][0], srcreg);
|
||||
_mm_store_ps(&destxmm[5][0], srcreg);
|
||||
_mm_store_ps(&destxmm[6][0], srcreg);
|
||||
_mm_store_ps(&destxmm[7][0], srcreg);
|
||||
}
|
||||
};
|
||||
|
||||
static __fi void memzero_sse_a(void* dest, const size_t size)
|
||||
{
|
||||
memset_sse_a<0>(dest, size);
|
||||
}
|
||||
|
||||
template <u8 data, typename T>
|
||||
__noinline void memset_sse_a(T& dest)
|
||||
{
|
||||
static_assert((sizeof(dest) & 0xf) == 0, "Bad size for SSE memset");
|
||||
memset_sse_a<data>(&dest, sizeof(dest));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void memzero_sse_a(T& dest)
|
||||
{
|
||||
static_assert((sizeof(dest) & 0xf) == 0, "Bad size for SSE memset");
|
||||
memset_sse_a<0>(&dest, sizeof(dest));
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
// Microsoft Windows only macro, useful for freeing out COM objects:
|
||||
#define safe_release(ptr) \
|
||||
((void)((((ptr) != NULL) && ((ptr)->Release(), !!0)), (ptr) = NULL))
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// SafeArray
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Handy little class for allocating a resizable memory block, complete with exception
|
||||
// error handling and automatic cleanup. A lightweight alternative to std::vector.
|
||||
//
|
||||
template <typename T>
|
||||
class SafeArray
|
||||
{
|
||||
DeclareNoncopyableObject(SafeArray);
|
||||
|
||||
public:
|
||||
static const int DefaultChunkSize = 0x1000 * sizeof(T);
|
||||
|
||||
public:
|
||||
std::string Name; // user-assigned block name
|
||||
int ChunkSize;
|
||||
|
||||
protected:
|
||||
T* m_ptr;
|
||||
int m_size; // size of the allocation of memory
|
||||
|
||||
protected:
|
||||
SafeArray(std::string name, T* allocated_mem, int initSize);
|
||||
virtual T* _virtual_realloc(int newsize);
|
||||
|
||||
// A safe array index fetcher. Asserts if the index is out of bounds (dev and debug
|
||||
// builds only -- no bounds checking is done in release builds).
|
||||
T* _getPtr(uint i) const;
|
||||
|
||||
public:
|
||||
virtual ~SafeArray();
|
||||
|
||||
explicit SafeArray(std::string name = "Unnamed");
|
||||
explicit SafeArray(int initialSize, std::string name = "Unnamed");
|
||||
|
||||
void Dispose();
|
||||
void ExactAlloc(int newsize);
|
||||
void MakeRoomFor(int newsize)
|
||||
{
|
||||
if (newsize > m_size)
|
||||
ExactAlloc(newsize);
|
||||
}
|
||||
|
||||
bool IsDisposed() const { return (m_ptr == NULL); }
|
||||
|
||||
// Returns the size of the memory allocation, as according to the array type.
|
||||
int GetLength() const { return m_size; }
|
||||
// Returns the size of the memory allocation in bytes.
|
||||
int GetSizeInBytes() const { return m_size * sizeof(T); }
|
||||
|
||||
// Extends the containment area of the array. Extensions are performed
|
||||
// in chunks.
|
||||
void GrowBy(int items)
|
||||
{
|
||||
MakeRoomFor(m_size + ChunkSize + items + 1);
|
||||
}
|
||||
|
||||
// Gets a pointer to the requested allocation index.
|
||||
// DevBuilds : Generates assertion if the index is invalid.
|
||||
T* GetPtr(uint idx = 0) { return _getPtr(idx); }
|
||||
const T* GetPtr(uint idx = 0) const { return _getPtr(idx); }
|
||||
|
||||
// Gets a pointer to the element directly after the last element in the array.
|
||||
// This is equivalent to doing GetPtr(GetLength()), except that this call *avoids*
|
||||
// the out-of-bounds assertion check that typically occurs when you do that. :)
|
||||
T* GetPtrEnd() { return &m_ptr[m_size]; }
|
||||
const T* GetPtrEnd() const { return &m_ptr[m_size]; }
|
||||
|
||||
// Gets an element of this memory allocation much as if it were an array.
|
||||
// DevBuilds : Generates assertion if the index is invalid.
|
||||
T& operator[](int idx) { return *_getPtr((uint)idx); }
|
||||
const T& operator[](int idx) const { return *_getPtr((uint)idx); }
|
||||
|
||||
virtual SafeArray<T>* Clone() const;
|
||||
};
|
||||
@@ -1,121 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/SafeArray.h"
|
||||
|
||||
// Internal constructor for use by derived classes. This allows a derived class to
|
||||
// use its own memory allocation (with an aligned memory, for example).
|
||||
// Throws:
|
||||
// Exception::OutOfMemory if the allocated_mem pointer is NULL.
|
||||
template <typename T>
|
||||
SafeArray<T>::SafeArray(std::string name, T* allocated_mem, int initSize)
|
||||
: Name(std::move(name))
|
||||
{
|
||||
ChunkSize = DefaultChunkSize;
|
||||
m_ptr = allocated_mem;
|
||||
m_size = initSize;
|
||||
|
||||
if (m_ptr == NULL)
|
||||
pxFailRel("SafeArray memory assignment failed");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* SafeArray<T>::_virtual_realloc(int newsize)
|
||||
{
|
||||
T* retval = (T*)((m_ptr == NULL) ?
|
||||
malloc(newsize * sizeof(T)) :
|
||||
realloc(m_ptr, newsize * sizeof(T)));
|
||||
|
||||
if (IsDebugBuild && (retval != NULL))
|
||||
{
|
||||
// Zero everything out to 0xbaadf00d, so that its obviously uncleared
|
||||
// to a debuggee
|
||||
|
||||
u32* fill = (u32*)&retval[m_size];
|
||||
const u32* end = (u32*)((((uptr)&retval[newsize - 1]) - 3) & ~0x3);
|
||||
for (; fill < end; ++fill)
|
||||
*fill = 0xbaadf00d;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SafeArray<T>::~SafeArray()
|
||||
{
|
||||
safe_free(m_ptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SafeArray<T>::SafeArray(std::string name)
|
||||
: Name(std::move(name))
|
||||
{
|
||||
ChunkSize = DefaultChunkSize;
|
||||
m_ptr = NULL;
|
||||
m_size = 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SafeArray<T>::SafeArray(int initialSize, std::string name)
|
||||
: Name(std::move(name))
|
||||
{
|
||||
ChunkSize = DefaultChunkSize;
|
||||
m_ptr = (initialSize == 0) ? NULL : (T*)malloc(initialSize * sizeof(T));
|
||||
m_size = initialSize;
|
||||
|
||||
if ((initialSize != 0) && (m_ptr == NULL))
|
||||
pxFailRel("SafeArray memory allocation failed");
|
||||
}
|
||||
|
||||
// Clears the contents of the array to zero, and frees all memory allocations.
|
||||
template <typename T>
|
||||
void SafeArray<T>::Dispose()
|
||||
{
|
||||
m_size = 0;
|
||||
safe_free(m_ptr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* SafeArray<T>::_getPtr(uint i) const
|
||||
{
|
||||
pxAssumeDev(i < static_cast<uint>(m_size), "Array index in bounds");
|
||||
return &m_ptr[i];
|
||||
}
|
||||
|
||||
// reallocates the array to the explicit size. Can be used to shrink or grow an
|
||||
// array, and bypasses the internal threshold growth indicators.
|
||||
template <typename T>
|
||||
void SafeArray<T>::ExactAlloc(int newsize)
|
||||
{
|
||||
if (newsize == m_size)
|
||||
return;
|
||||
|
||||
m_ptr = _virtual_realloc(newsize);
|
||||
if (m_ptr == NULL)
|
||||
pxFailRel("SafeArray exact alloc failed");
|
||||
|
||||
m_size = newsize;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
SafeArray<T>* SafeArray<T>::Clone() const
|
||||
{
|
||||
SafeArray<T>* retval = new SafeArray<T>(m_size);
|
||||
memcpy(retval->GetPtr(), m_ptr, sizeof(T) * m_size);
|
||||
return retval;
|
||||
}
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/General.h"
|
||||
#include "common/Exceptions.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "common/AlignedMalloc.h"
|
||||
#include "common/Assertions.h"
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/Exceptions.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "common/Threading.h"
|
||||
#include "common/General.h"
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
__ri static void MemCopy_WrappedDest(const u128* src, u128* destBase, uint& destStart, uint destSize, uint len)
|
||||
{
|
||||
uint endpos = destStart + len;
|
||||
if (endpos < destSize)
|
||||
{
|
||||
memcpy(&destBase[destStart], src, len * 16);
|
||||
destStart += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint firstcopylen = destSize - destStart;
|
||||
memcpy(&destBase[destStart], src, firstcopylen * 16);
|
||||
destStart = endpos % destSize;
|
||||
memcpy(destBase, src + firstcopylen, destStart * 16);
|
||||
}
|
||||
}
|
||||
|
||||
__ri static void MemCopy_WrappedSrc(const u128* srcBase, uint& srcStart, uint srcSize, u128* dest, uint len)
|
||||
{
|
||||
uint endpos = srcStart + len;
|
||||
if (endpos < srcSize)
|
||||
{
|
||||
memcpy(dest, &srcBase[srcStart], len * 16);
|
||||
srcStart += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint firstcopylen = srcSize - srcStart;
|
||||
memcpy(dest, &srcBase[srcStart], firstcopylen * 16);
|
||||
srcStart = endpos % srcSize;
|
||||
memcpy(dest + firstcopylen, srcBase, srcStart * 16);
|
||||
}
|
||||
}
|
||||
@@ -46,10 +46,11 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AlignedMalloc.cpp" />
|
||||
<ClCompile Include="Assertions.cpp" />
|
||||
<ClCompile Include="Console.cpp" />
|
||||
<ClCompile Include="CrashHandler.cpp" />
|
||||
<ClCompile Include="DynamicLibrary.cpp" />
|
||||
<ClCompile Include="Exceptions.cpp" />
|
||||
<ClCompile Include="Error.cpp" />
|
||||
<ClCompile Include="FastJmp.cpp">
|
||||
<ExcludedFromBuild>true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@@ -109,6 +110,7 @@
|
||||
<ClInclude Include="DynamicLibrary.h" />
|
||||
<ClInclude Include="Easing.h" />
|
||||
<ClInclude Include="boost_spsc_queue.hpp" />
|
||||
<ClInclude Include="Error.h" />
|
||||
<ClInclude Include="FastJmp.h" />
|
||||
<ClInclude Include="FileSystem.h" />
|
||||
<ClInclude Include="HashCombine.h" />
|
||||
@@ -131,7 +133,6 @@
|
||||
<ClInclude Include="SettingsWrapper.h" />
|
||||
<ClInclude Include="Assertions.h" />
|
||||
<ClInclude Include="Console.h" />
|
||||
<ClInclude Include="Exceptions.h" />
|
||||
<ClInclude Include="General.h" />
|
||||
<ClInclude Include="MathUtils.h" />
|
||||
<ClInclude Include="Path.h" />
|
||||
@@ -169,6 +170,7 @@
|
||||
<ClInclude Include="emitter\implement\simd_helpers.h" />
|
||||
<ClInclude Include="emitter\implement\simd_moremovs.h" />
|
||||
<ClInclude Include="emitter\implement\simd_shufflepack.h" />
|
||||
<ClInclude Include="WrappedMemCopy.h" />
|
||||
<ClInclude Include="ZipHelpers.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -180,4 +182,4 @@
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -13,9 +13,6 @@
|
||||
<ClCompile Include="emitter\cpudetect.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Exceptions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="emitter\fpu.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -139,6 +136,12 @@
|
||||
<ClCompile Include="General.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Error.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Assertions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AlignedMalloc.h">
|
||||
@@ -159,9 +162,6 @@
|
||||
<ClInclude Include="emitter\implement\dwshift.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Exceptions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="General.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -348,6 +348,12 @@
|
||||
<ClInclude Include="ByteSwap.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WrappedMemCopy.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Error.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
@@ -362,4 +368,4 @@
|
||||
<Filter>Source Files</Filter>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -66,8 +66,6 @@ x86capabilities::x86capabilities()
|
||||
, PhysicalCores(0)
|
||||
, LogicalCores(0)
|
||||
{
|
||||
memzero(VendorName);
|
||||
memzero(FamilyName);
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
#pragma optimize("", on)
|
||||
@@ -148,7 +146,6 @@ void x86capabilities::Identify()
|
||||
s32 regs[4];
|
||||
u32 cmds;
|
||||
|
||||
memzero(VendorName);
|
||||
cpuid(regs, 0);
|
||||
|
||||
cmds = regs[0];
|
||||
@@ -201,7 +198,6 @@ void x86capabilities::Identify()
|
||||
EFlags = regs[3];
|
||||
}
|
||||
|
||||
memzero(FamilyName);
|
||||
cpuid((int*)FamilyName, 0x80000002);
|
||||
cpuid((int*)(FamilyName + 16), 0x80000003);
|
||||
cpuid((int*)(FamilyName + 32), 0x80000004);
|
||||
|
||||
@@ -46,8 +46,8 @@ public:
|
||||
u32 EFlags2; // Extended Feature Flags pg2
|
||||
u32 SEFlag; // Structured Extended Feature Flags Enumeration
|
||||
|
||||
char VendorName[16]; // Vendor/Creator ID
|
||||
char FamilyName[50]; // the original cpu name
|
||||
char VendorName[16] = {}; // Vendor/Creator ID
|
||||
char FamilyName[50] = {}; // the original cpu name
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// x86 CPU Capabilities Section (all boolean flags!)
|
||||
@@ -55,6 +55,8 @@ public:
|
||||
|
||||
union
|
||||
{
|
||||
u64 AllCapabilities = 0;
|
||||
|
||||
struct
|
||||
{
|
||||
u32 hasFloatingPointUnit : 1;
|
||||
@@ -101,13 +103,11 @@ public:
|
||||
u32 hasAMD64BitArchitecture : 1;
|
||||
u32 hasStreamingSIMD4ExtensionsA : 1;
|
||||
};
|
||||
|
||||
u64 AllCapabilities;
|
||||
};
|
||||
|
||||
// Core Counts!
|
||||
u32 PhysicalCores;
|
||||
u32 LogicalCores;
|
||||
u32 PhysicalCores = 0;
|
||||
u32 LogicalCores = 0;
|
||||
|
||||
public:
|
||||
x86capabilities();
|
||||
|
||||
@@ -167,20 +167,25 @@
|
||||
/>
|
||||
</Target>
|
||||
|
||||
<!--Copies base translation files-->
|
||||
<!--Copies base translation files, need to rename them from qtbase_ to qt_ -->
|
||||
<ItemGroup>
|
||||
<BaseTsFiles Include="$(QtTranslationsDir)\*.qm" />
|
||||
</ItemGroup>
|
||||
<Target Name="QtCopyBaseTranslations"
|
||||
AfterTargets="Build"
|
||||
Inputs="@(BaseTsFiles)"
|
||||
Outputs="@(BaseTsFiles -> '$(QtTsOutDir)%(RecursiveDir)%(Filename)%(Extension)')">
|
||||
Outputs="@(BaseTsFiles -> '$(QtTsOutDir)%(RecursiveDir)%(Filename.Replace('qtbase_', 'qt_'))%(Extension)')">
|
||||
<!-- https://stackoverflow.com/a/15379344 -->
|
||||
<ItemGroup>
|
||||
<TempItems Include="@(BaseTsFiles->'%(Filename)%(Extension)'->Replace('qtbase_', 'qt_'))">
|
||||
<OriginalPath>%(Identity)</OriginalPath>
|
||||
<SavedRecursiveDir>%(RecursiveDir)</SavedRecursiveDir>
|
||||
</TempItems>
|
||||
</ItemGroup>
|
||||
<Message Text="Copying base translation files" Importance="High" />
|
||||
<Copy
|
||||
SourceFiles="@(BaseTsFiles)"
|
||||
DestinationFolder="$(QtTsOutDir)"
|
||||
SkipUnchangedFiles="true"
|
||||
/>
|
||||
<Copy SourceFiles="@(TempItems->'%(OriginalPath)')"
|
||||
DestinationFiles="@(TempItems->'$(QtTsOutDir)%(SavedRecursiveDir)%(Identity)')"
|
||||
SkipUnchangedFiles="true" />
|
||||
</Target>
|
||||
|
||||
<!--Compiles all translation files-->
|
||||
|
||||
@@ -19,19 +19,19 @@
|
||||
<ClCompile>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir);$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>__WIN32__;WIN32;_WINDOWS;WIN32_LEAN_AND_MEAN;NOMINMAX;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;WINVER=0x0A00;_WIN32_WINNT=0x0A00;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>__WIN32__;WIN32;_WINDOWS;WIN32_LEAN_AND_MEAN;NOMINMAX;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;_HAS_EXCEPTIONS=0;WINVER=0x0A00;_WIN32_WINNT=0x0A00;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="$(Configuration.Contains(Debug))">PCSX2_DEBUG;PCSX2_DEVBUILD;_SECURE_SCL_=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="$(Configuration.Contains(Devel))">PCSX2_DEVEL;PCSX2_DEVBUILD;NDEBUG;_SECURE_SCL_=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="$(Configuration.Contains(Release))">NDEBUG;_SECURE_SCL_=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<RuntimeTypeInfo>false</RuntimeTypeInfo>
|
||||
<ExceptionHandling>false</ExceptionHandling>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
<DisableSpecificWarnings>4063;4100;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
|
||||
|
||||
+3
-1
@@ -1,3 +1,5 @@
|
||||
pull_request_title: "[ci skip] Syncing Crowdin translations"
|
||||
commit_message: "[ci skip]"
|
||||
files:
|
||||
- source: pcsx2-qt/Translations/pcsx2-qt_en.ts
|
||||
translation: '/pcsx2-qt/Translations/pcsx2-qt_%two_letters_code%.ts'
|
||||
translation: '/pcsx2-qt/Translations/pcsx2-qt_%locale%.ts'
|
||||
|
||||
+15
-14
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/Exceptions.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/MemorySettingsInterface.h"
|
||||
#include "common/Path.h"
|
||||
@@ -40,13 +39,13 @@
|
||||
#include "pcsx2/Achievements.h"
|
||||
#include "pcsx2/CDVD/CDVD.h"
|
||||
#include "pcsx2/GS.h"
|
||||
#include "pcsx2/GS/GS.h"
|
||||
#include "pcsx2/GSDumpReplayer.h"
|
||||
#include "pcsx2/Host.h"
|
||||
#include "pcsx2/INISettingsInterface.h"
|
||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||
#include "pcsx2/Input/InputManager.h"
|
||||
#include "pcsx2/LogSink.h"
|
||||
#include "pcsx2/MTGS.h"
|
||||
#include "pcsx2/PAD/Host/PAD.h"
|
||||
#include "pcsx2/PerformanceMetrics.h"
|
||||
#include "pcsx2/VMManager.h"
|
||||
@@ -69,7 +68,6 @@ static constexpr u32 WINDOW_WIDTH = 640;
|
||||
static constexpr u32 WINDOW_HEIGHT = 480;
|
||||
|
||||
static MemorySettingsInterface s_settings_interface;
|
||||
alignas(16) static SysMtgsThread s_mtgs_thread;
|
||||
|
||||
static std::string s_output_prefix;
|
||||
static s32 s_loop_count = 1;
|
||||
@@ -362,15 +360,6 @@ std::optional<std::string> InputManager::ConvertHostKeyboardCodeToString(u32 cod
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
SysMtgsThread& GetMTGS()
|
||||
{
|
||||
return s_mtgs_thread;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Interface Stuff
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BEGIN_HOTKEY_LIST(g_host_hotkeys)
|
||||
END_HOTKEY_LIST()
|
||||
|
||||
@@ -651,13 +640,25 @@ int main(int argc, char* argv[])
|
||||
void Host::VSyncOnCPUThread()
|
||||
{
|
||||
// update GS thread copy of frame number
|
||||
GetMTGS().RunOnGSThread([frame_number = GSDumpReplayer::GetFrameNumber()]() { s_dump_frame_number = frame_number; });
|
||||
GetMTGS().RunOnGSThread([loop_number = GSDumpReplayer::GetLoopCount()]() { s_loop_number = loop_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(
|
||||
const std::string_view& context, const std::string_view& msg, char* tbuf, size_t tbuf_space)
|
||||
{
|
||||
if (msg.size() > tbuf_space)
|
||||
return -1;
|
||||
else if (msg.empty())
|
||||
return 0;
|
||||
|
||||
std::memcpy(tbuf, msg.data(), msg.size());
|
||||
return static_cast<s32>(msg.size());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Platform specific code
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -804,7 +804,8 @@ bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDi
|
||||
}
|
||||
QDir(QString::fromStdString(*trashed_path)).removeRecursively();
|
||||
}
|
||||
if (!CocoaTools::LaunchApplication(open_path.toStdString()))
|
||||
// For some reason if I use QProcess the shell gets killed immediately with SIGKILL, but NSTask is fine...
|
||||
if (!CocoaTools::DelayedLaunch(open_path.toStdString()))
|
||||
{
|
||||
reportError("Failed to start new application");
|
||||
return false;
|
||||
|
||||
@@ -25,7 +25,11 @@ target_sources(pcsx2-qt PRIVATE
|
||||
PrecompiledHeader.cpp
|
||||
PrecompiledHeader.h
|
||||
SettingWidgetBinder.h
|
||||
SetupWizardDialog.cpp
|
||||
SetupWizardDialog.h
|
||||
SetupWizardDialog.ui
|
||||
Themes.cpp
|
||||
Translations.cpp
|
||||
QtHost.cpp
|
||||
QtHost.h
|
||||
QtKeyCodes.cpp
|
||||
@@ -173,6 +177,8 @@ if(USE_ACHIEVEMENTS)
|
||||
)
|
||||
endif()
|
||||
|
||||
file(GLOB TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/Translations/*.ts)
|
||||
|
||||
target_precompile_headers(pcsx2-qt PRIVATE PrecompiledHeader.h)
|
||||
|
||||
target_include_directories(pcsx2-qt PRIVATE
|
||||
@@ -191,6 +197,27 @@ target_link_libraries(pcsx2-qt PRIVATE
|
||||
Qt6::Network
|
||||
)
|
||||
|
||||
# Our Qt builds may have exceptions on, so force them off.
|
||||
target_compile_definitions(pcsx2-qt PRIVATE QT_NO_EXCEPTIONS)
|
||||
|
||||
if(WIN32)
|
||||
set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION "${CMAKE_SOURCE_DIR}/bin/translations")
|
||||
qt_add_lrelease(pcsx2-qt TS_FILES ${TS_FILES})
|
||||
elseif(APPLE)
|
||||
# Hopefully macdeployqt will pick these up.
|
||||
qt_add_lrelease(pcsx2-qt TS_FILES ${TS_FILES})
|
||||
else()
|
||||
# TODO: Copy base translations.
|
||||
qt_add_lrelease(pcsx2-qt TS_FILES ${TS_FILES} QM_FILES_OUTPUT_VARIABLE QM_FILES)
|
||||
set(QM_OUTPUT_DIR "$<TARGET_FILE_DIR:pcsx2-qt>/translations")
|
||||
add_custom_command(TARGET pcsx2-qt POST_BUILD COMMAND "${CMAKE_COMMAND}" -E make_directory "${QM_OUTPUT_DIR}")
|
||||
foreach (QM_FILE IN LISTS QM_FILES)
|
||||
get_filename_component(QM_FILE_NAME ${QM_FILE} NAME)
|
||||
add_custom_command(TARGET pcsx2-qt POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${QM_FILE}" "${QM_OUTPUT_DIR}/${QM_FILE_NAME}")
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
|
||||
# Currently, 7z is only needed for the Windows updater.
|
||||
if(WIN32)
|
||||
target_link_libraries(pcsx2-qt PRIVATE
|
||||
|
||||
+72
-31
@@ -41,6 +41,7 @@
|
||||
#include "pcsx2/GameList.h"
|
||||
#include "pcsx2/Host.h"
|
||||
#include "pcsx2/LogSink.h"
|
||||
#include "pcsx2/MTGS.h"
|
||||
#include "pcsx2/PerformanceMetrics.h"
|
||||
#include "pcsx2/Recording/InputRecording.h"
|
||||
#include "pcsx2/Recording/InputRecordingControls.h"
|
||||
@@ -182,7 +183,6 @@ void MainWindow::setupAdditionalUi()
|
||||
{
|
||||
const bool show_advanced_settings = QtHost::ShouldShowAdvancedSettings();
|
||||
|
||||
setWindowIcon(QIcon(QStringLiteral("%1/icons/AppIconLarge.png").arg(QtHost::GetResourcesBasePath())));
|
||||
makeIconsMasks(menuBar());
|
||||
|
||||
m_ui.menuDebug->menuAction()->setVisible(show_advanced_settings);
|
||||
@@ -293,7 +293,6 @@ void MainWindow::connectSignals()
|
||||
connect(m_ui.actionStartFile, &QAction::triggered, this, &MainWindow::onStartFileActionTriggered);
|
||||
connect(m_ui.actionStartDisc, &QAction::triggered, this, &MainWindow::onStartDiscActionTriggered);
|
||||
connect(m_ui.actionStartBios, &QAction::triggered, this, &MainWindow::onStartBIOSActionTriggered);
|
||||
connect(m_ui.actionChangeDisc, &QAction::triggered, [this] { m_ui.menuChangeDisc->exec(QCursor::pos()); });
|
||||
connect(m_ui.actionChangeDiscFromFile, &QAction::triggered, this, &MainWindow::onChangeDiscFromFileActionTriggered);
|
||||
connect(m_ui.actionChangeDiscFromDevice, &QAction::triggered, this, &MainWindow::onChangeDiscFromDeviceActionTriggered);
|
||||
connect(m_ui.actionChangeDiscFromGameList, &QAction::triggered, this, &MainWindow::onChangeDiscFromGameListActionTriggered);
|
||||
@@ -302,14 +301,22 @@ void MainWindow::connectSignals()
|
||||
connect(m_ui.menuChangeDisc, &QMenu::aboutToHide, this, &MainWindow::onChangeDiscMenuAboutToHide);
|
||||
connect(m_ui.actionPowerOff, &QAction::triggered, this, [this]() { requestShutdown(true, true, EmuConfig.SaveStateOnShutdown); });
|
||||
connect(m_ui.actionPowerOffWithoutSaving, &QAction::triggered, this, [this]() { requestShutdown(false, false, false); });
|
||||
connect(m_ui.actionLoadState, &QAction::triggered, this, [this]() { m_ui.menuLoadState->exec(QCursor::pos()); });
|
||||
connect(m_ui.actionSaveState, &QAction::triggered, this, [this]() { m_ui.menuSaveState->exec(QCursor::pos()); });
|
||||
connect(m_ui.actionToolbarStartFile, &QAction::triggered, this, &MainWindow::onStartFileActionTriggered);
|
||||
connect(m_ui.actionToolbarStartDisc, &QAction::triggered, this, &MainWindow::onStartDiscActionTriggered);
|
||||
connect(m_ui.actionToolbarStartBios, &QAction::triggered, this, &MainWindow::onStartBIOSActionTriggered);
|
||||
connect(m_ui.actionToolbarChangeDisc, &QAction::triggered, [this] { m_ui.menuChangeDisc->exec(QCursor::pos()); });
|
||||
connect(m_ui.actionToolbarPowerOff, &QAction::triggered, this, [this]() { requestShutdown(true, true, EmuConfig.SaveStateOnShutdown); });
|
||||
connect(m_ui.actionToolbarLoadState, &QAction::triggered, this, [this]() { m_ui.menuLoadState->exec(QCursor::pos()); });
|
||||
connect(m_ui.actionToolbarSaveState, &QAction::triggered, this, [this]() { m_ui.menuSaveState->exec(QCursor::pos()); });
|
||||
connect(m_ui.actionToolbarSettings, &QAction::triggered, this, &MainWindow::onSettingsTriggeredFromToolbar);
|
||||
connect(m_ui.actionToolbarControllerSettings, &QAction::triggered,
|
||||
[this]() { doControllerSettings(ControllerSettingsDialog::Category::GlobalSettings); });
|
||||
connect(m_ui.actionToolbarScreenshot, &QAction::triggered, this, &MainWindow::onScreenshotActionTriggered);
|
||||
connect(m_ui.actionExit, &QAction::triggered, this, &MainWindow::close);
|
||||
connect(m_ui.actionScreenshot, &QAction::triggered, this, &MainWindow::onScreenshotActionTriggered);
|
||||
connect(m_ui.menuLoadState, &QMenu::aboutToShow, this, &MainWindow::onLoadStateMenuAboutToShow);
|
||||
connect(m_ui.menuSaveState, &QMenu::aboutToShow, this, &MainWindow::onSaveStateMenuAboutToShow);
|
||||
connect(m_ui.actionSettings, &QAction::triggered, [this]() { doSettings(); });
|
||||
connect(m_ui.actionSettings2, &QAction::triggered, this, &MainWindow::onSettingsTriggeredFromToolbar);
|
||||
connect(m_ui.actionInterfaceSettings, &QAction::triggered, [this]() { doSettings("Interface"); });
|
||||
connect(m_ui.actionGameListSettings, &QAction::triggered, [this]() { doSettings("Game List"); });
|
||||
connect(m_ui.actionEmulationSettings, &QAction::triggered, [this]() { doSettings("Emulation"); });
|
||||
@@ -402,7 +409,7 @@ void MainWindow::connectSignals()
|
||||
void MainWindow::connectVMThreadSignals(EmuThread* thread)
|
||||
{
|
||||
connect(m_ui.actionStartFullscreenUI, &QAction::triggered, thread, &EmuThread::startFullscreenUI);
|
||||
connect(m_ui.actionStartFullscreenUI2, &QAction::triggered, thread, &EmuThread::startFullscreenUI);
|
||||
connect(m_ui.actionToolbarStartFullscreenUI, &QAction::triggered, thread, &EmuThread::startFullscreenUI);
|
||||
connect(thread, &EmuThread::messageConfirmed, this, &MainWindow::confirmMessage, Qt::BlockingQueuedConnection);
|
||||
connect(thread, &EmuThread::onAcquireRenderWindowRequested, this, &MainWindow::acquireRenderWindow, Qt::BlockingQueuedConnection);
|
||||
connect(thread, &EmuThread::onReleaseRenderWindowRequested, this, &MainWindow::releaseRenderWindow, Qt::BlockingQueuedConnection);
|
||||
@@ -418,6 +425,9 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
|
||||
connect(m_ui.actionReset, &QAction::triggered, thread, &EmuThread::resetVM);
|
||||
connect(m_ui.actionPause, &QAction::toggled, thread, &EmuThread::setVMPaused);
|
||||
connect(m_ui.actionFullscreen, &QAction::triggered, thread, &EmuThread::toggleFullscreen);
|
||||
connect(m_ui.actionToolbarReset, &QAction::triggered, thread, &EmuThread::resetVM);
|
||||
connect(m_ui.actionToolbarPause, &QAction::toggled, thread, &EmuThread::setVMPaused);
|
||||
connect(m_ui.actionToolbarFullscreen, &QAction::triggered, thread, &EmuThread::toggleFullscreen);
|
||||
connect(m_ui.actionToggleSoftwareRendering, &QAction::triggered, thread, &EmuThread::toggleSoftwareRendering);
|
||||
connect(m_ui.actionDebugger, &QAction::triggered, this, &MainWindow::openDebugger);
|
||||
connect(m_ui.actionReloadPatches, &QAction::triggered, thread, &EmuThread::reloadPatches);
|
||||
@@ -672,18 +682,25 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool stoppi
|
||||
m_ui.actionStartFile->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionStartDisc->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionStartBios->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionToolbarStartFile->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionToolbarStartDisc->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionToolbarStartBios->setDisabled(starting_or_running || stopping);
|
||||
|
||||
m_ui.actionPowerOff->setEnabled(running);
|
||||
m_ui.actionPowerOffWithoutSaving->setEnabled(running);
|
||||
m_ui.actionReset->setEnabled(running);
|
||||
m_ui.actionPause->setEnabled(running);
|
||||
m_ui.actionChangeDisc->setEnabled(running);
|
||||
m_ui.actionScreenshot->setEnabled(running);
|
||||
m_ui.menuChangeDisc->setEnabled(running);
|
||||
|
||||
m_ui.actionSaveState->setEnabled(running);
|
||||
m_ui.menuSaveState->setEnabled(running);
|
||||
|
||||
m_ui.actionToolbarPowerOff->setEnabled(running);
|
||||
m_ui.actionToolbarReset->setEnabled(running);
|
||||
m_ui.actionToolbarPause->setEnabled(running);
|
||||
m_ui.actionToolbarScreenshot->setEnabled(running);
|
||||
m_ui.actionToolbarChangeDisc->setEnabled(running);
|
||||
m_ui.actionToolbarSaveState->setEnabled(running);
|
||||
|
||||
m_ui.actionViewGameProperties->setEnabled(running);
|
||||
|
||||
m_ui.actionToolsVideoCapture->setEnabled(running);
|
||||
@@ -697,8 +714,15 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool stoppi
|
||||
|
||||
if (!starting && !running)
|
||||
{
|
||||
QSignalBlocker sb(m_ui.actionPause);
|
||||
m_ui.actionPause->setChecked(false);
|
||||
{
|
||||
QSignalBlocker sb(m_ui.actionPause);
|
||||
m_ui.actionPause->setChecked(false);
|
||||
}
|
||||
|
||||
{
|
||||
QSignalBlocker sb(m_ui.actionToolbarPause);
|
||||
m_ui.actionToolbarPause->setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
// scanning needs to be disabled while running
|
||||
@@ -709,14 +733,20 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool stoppi
|
||||
void MainWindow::updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen)
|
||||
{
|
||||
// rendering to main, or switched to gamelist/grid
|
||||
m_ui.actionViewSystemDisplay->setEnabled((has_surface && render_to_main) || (!has_surface && GetMTGS().IsOpen()));
|
||||
m_ui.actionViewSystemDisplay->setEnabled((has_surface && render_to_main) || (!has_surface && MTGS::IsOpen()));
|
||||
m_ui.menuWindowSize->setEnabled(has_surface && !fullscreen);
|
||||
m_ui.actionFullscreen->setEnabled(has_surface);
|
||||
m_ui.actionToolbarFullscreen->setEnabled(has_surface);
|
||||
|
||||
{
|
||||
QSignalBlocker blocker(m_ui.actionFullscreen);
|
||||
m_ui.actionFullscreen->setChecked(fullscreen);
|
||||
}
|
||||
|
||||
{
|
||||
QSignalBlocker blocker(m_ui.actionToolbarFullscreen);
|
||||
m_ui.actionToolbarFullscreen->setChecked(fullscreen);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateStatusBarWidgetVisibility()
|
||||
@@ -821,7 +851,7 @@ bool MainWindow::isShowingGameList() const
|
||||
|
||||
bool MainWindow::isRenderingFullscreen() const
|
||||
{
|
||||
if (!GetMTGS().IsOpen() || !m_display_widget)
|
||||
if (!MTGS::IsOpen() || !m_display_widget)
|
||||
return false;
|
||||
|
||||
return getDisplayContainer()->isFullScreen();
|
||||
@@ -1394,6 +1424,12 @@ void MainWindow::updateTheme()
|
||||
m_game_list_widget->refreshImages();
|
||||
}
|
||||
|
||||
void MainWindow::updateLanguage()
|
||||
{
|
||||
QtHost::InstallTranslator();
|
||||
recreate();
|
||||
}
|
||||
|
||||
void MainWindow::onInputRecNewActionTriggered()
|
||||
{
|
||||
const bool wasPaused = s_vm_paused;
|
||||
@@ -1417,6 +1453,7 @@ void MainWindow::onInputRecNewActionTriggered()
|
||||
m_ui.actionInputRecNew->setEnabled(false);
|
||||
m_ui.actionInputRecStop->setEnabled(true);
|
||||
m_ui.actionReset->setEnabled(!g_InputRecording.isTypeSavestate());
|
||||
m_ui.actionToolbarReset->setEnabled(!g_InputRecording.isTypeSavestate());
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1469,6 +1506,7 @@ void MainWindow::onInputRecPlayActionTriggered()
|
||||
m_ui.actionInputRecNew->setEnabled(false);
|
||||
m_ui.actionInputRecStop->setEnabled(true);
|
||||
m_ui.actionReset->setEnabled(!g_InputRecording.isTypeSavestate());
|
||||
m_ui.actionToolbarReset->setEnabled(!g_InputRecording.isTypeSavestate());
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -1485,6 +1523,7 @@ void MainWindow::onInputRecStopActionTriggered()
|
||||
m_ui.actionInputRecNew->setEnabled(true);
|
||||
m_ui.actionInputRecStop->setEnabled(false);
|
||||
m_ui.actionReset->setEnabled(true);
|
||||
m_ui.actionToolbarReset->setEnabled(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1548,6 +1587,10 @@ void MainWindow::onVMPaused()
|
||||
QSignalBlocker sb(m_ui.actionPause);
|
||||
m_ui.actionPause->setChecked(true);
|
||||
}
|
||||
{
|
||||
QSignalBlocker sb(m_ui.actionToolbarPause);
|
||||
m_ui.actionToolbarPause->setChecked(true);
|
||||
}
|
||||
|
||||
s_vm_paused = true;
|
||||
updateWindowTitle();
|
||||
@@ -1565,6 +1608,10 @@ void MainWindow::onVMResumed()
|
||||
QSignalBlocker sb(m_ui.actionPause);
|
||||
m_ui.actionPause->setChecked(false);
|
||||
}
|
||||
{
|
||||
QSignalBlocker sb(m_ui.actionToolbarPause);
|
||||
m_ui.actionToolbarPause->setChecked(false);
|
||||
}
|
||||
|
||||
s_vm_paused = false;
|
||||
m_was_disc_change_request = false;
|
||||
@@ -1826,7 +1873,7 @@ std::optional<WindowInfo> MainWindow::acquireRenderWindow(bool recreate_window,
|
||||
updateWindowState();
|
||||
|
||||
m_ui.actionStartFullscreenUI->setEnabled(false);
|
||||
m_ui.actionStartFullscreenUI2->setEnabled(false);
|
||||
m_ui.actionToolbarStartFullscreenUI->setEnabled(false);
|
||||
|
||||
updateDisplayWidgetCursor();
|
||||
m_display_widget->setFocus();
|
||||
@@ -1933,7 +1980,7 @@ void MainWindow::relativeMouseModeRequested(bool enabled)
|
||||
return;
|
||||
|
||||
m_relative_mouse_mode = enabled;
|
||||
if (s_vm_valid && !s_vm_paused)
|
||||
if (m_display_widget && !s_vm_paused)
|
||||
updateDisplayWidgetCursor();
|
||||
}
|
||||
|
||||
@@ -1946,7 +1993,7 @@ void MainWindow::releaseRenderWindow()
|
||||
m_ui.actionViewSystemDisplay->setEnabled(false);
|
||||
m_ui.actionFullscreen->setEnabled(false);
|
||||
m_ui.actionStartFullscreenUI->setEnabled(true);
|
||||
m_ui.actionStartFullscreenUI2->setEnabled(true);
|
||||
m_ui.actionToolbarStartFullscreenUI->setEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::destroyDisplayWidget(bool show_game_list)
|
||||
@@ -2002,6 +2049,7 @@ void MainWindow::destroyDisplayWidget(bool show_game_list)
|
||||
|
||||
void MainWindow::updateDisplayWidgetCursor()
|
||||
{
|
||||
pxAssertRel(m_display_widget, "Should have a display widget");
|
||||
m_display_widget->updateRelativeMode(s_vm_valid && !s_vm_paused && m_relative_mouse_mode);
|
||||
m_display_widget->updateCursor(s_vm_valid && !s_vm_paused && shouldHideMouseCursor());
|
||||
}
|
||||
@@ -2063,6 +2111,11 @@ SettingsDialog* MainWindow::getSettingsDialog()
|
||||
{
|
||||
m_settings_dialog = new SettingsDialog(this);
|
||||
connect(m_settings_dialog->getInterfaceSettingsWidget(), &InterfaceSettingsWidget::themeChanged, this, &MainWindow::updateTheme);
|
||||
connect(m_settings_dialog->getInterfaceSettingsWidget(), &InterfaceSettingsWidget::languageChanged, this, [this]() {
|
||||
// reopen settings dialog after it applies
|
||||
updateLanguage();
|
||||
g_main_window->doSettings("Interface");
|
||||
});
|
||||
}
|
||||
|
||||
return m_settings_dialog;
|
||||
@@ -2420,9 +2473,9 @@ void MainWindow::updateSaveStateMenusEnableState(bool enable)
|
||||
const bool load_enabled = enable;
|
||||
const bool save_enabled = enable && s_vm_valid;
|
||||
m_ui.menuLoadState->setEnabled(load_enabled);
|
||||
m_ui.actionLoadState->setEnabled(load_enabled);
|
||||
m_ui.actionToolbarLoadState->setEnabled(load_enabled);
|
||||
m_ui.menuSaveState->setEnabled(save_enabled);
|
||||
m_ui.actionSaveState->setEnabled(save_enabled);
|
||||
m_ui.actionToolbarSaveState->setEnabled(save_enabled);
|
||||
}
|
||||
|
||||
void MainWindow::doStartFile(std::optional<CDVD_SourceType> source, const QString& path)
|
||||
@@ -2452,20 +2505,8 @@ void MainWindow::doStartFile(std::optional<CDVD_SourceType> source, const QStrin
|
||||
|
||||
void MainWindow::doDiscChange(CDVD_SourceType source, const QString& path)
|
||||
{
|
||||
const bool is_gs_dump = VMManager::IsGSDumpFileName(path.toStdString());
|
||||
if (is_gs_dump != GSDumpReplayer::IsReplayingDump())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Cannot switch from game to GS dump or vice versa."));
|
||||
return;
|
||||
}
|
||||
else if (is_gs_dump)
|
||||
{
|
||||
Host::RunOnCPUThread([path = path.toStdString()]() { GSDumpReplayer::ChangeDump(path.c_str()); });
|
||||
return;
|
||||
}
|
||||
|
||||
bool reset_system = false;
|
||||
if (!m_was_disc_change_request)
|
||||
if (!m_was_disc_change_request && !GSDumpReplayer::IsReplayingDump())
|
||||
{
|
||||
QMessageBox message(QMessageBox::Question, tr("Confirm Disc Change"),
|
||||
tr("Do you want to swap discs or boot the new image (via system reset)?"), QMessageBox::NoButton, this);
|
||||
|
||||
@@ -159,6 +159,7 @@ private Q_SLOTS:
|
||||
void onToolsOpenDataDirectoryTriggered();
|
||||
void onToolsCoverDownloaderTriggered();
|
||||
void updateTheme();
|
||||
void updateLanguage();
|
||||
void onScreenshotActionTriggered();
|
||||
void onSaveGSDumpActionTriggered();
|
||||
void onBlockDumpActionToggled(bool checked);
|
||||
|
||||
+153
-64
@@ -16,6 +16,11 @@
|
||||
<property name="windowTitle">
|
||||
<string>PCSX2</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normalon>:/icons/AppIcon64.png</normalon>
|
||||
</iconset>
|
||||
</property>
|
||||
<widget class="QStackedWidget" name="mainContainer"/>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
@@ -126,10 +131,10 @@
|
||||
<property name="title">
|
||||
<string>Switch Renderer</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="brush-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="brush-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
<addaction name="menuDebugSwitchRenderer"/>
|
||||
<addaction name="separator"/>
|
||||
@@ -234,24 +239,24 @@
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionStartFile"/>
|
||||
<addaction name="actionStartDisc"/>
|
||||
<addaction name="actionStartBios"/>
|
||||
<addaction name="actionStartFullscreenUI2"/>
|
||||
<addaction name="actionToolbarStartFile"/>
|
||||
<addaction name="actionToolbarStartDisc"/>
|
||||
<addaction name="actionToolbarStartBios"/>
|
||||
<addaction name="actionToolbarStartFullscreenUI"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionPowerOff"/>
|
||||
<addaction name="actionReset"/>
|
||||
<addaction name="actionPause"/>
|
||||
<addaction name="actionChangeDisc"/>
|
||||
<addaction name="actionScreenshot"/>
|
||||
<addaction name="actionToolbarPowerOff"/>
|
||||
<addaction name="actionToolbarReset"/>
|
||||
<addaction name="actionToolbarPause"/>
|
||||
<addaction name="actionToolbarChangeDisc"/>
|
||||
<addaction name="actionToolbarScreenshot"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionLoadState"/>
|
||||
<addaction name="actionSaveState"/>
|
||||
<addaction name="actionToolbarLoadState"/>
|
||||
<addaction name="actionToolbarSaveState"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionFullscreen"/>
|
||||
<addaction name="actionToolbarFullscreen"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSettings2"/>
|
||||
<addaction name="actionControllerSettings"/>
|
||||
<addaction name="actionToolbarSettings"/>
|
||||
<addaction name="actionToolbarControllerSettings"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
<action name="actionStartFile">
|
||||
@@ -263,6 +268,15 @@
|
||||
<string>Start &File...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbarStartFile">
|
||||
<property name="icon">
|
||||
<iconset theme="file-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string comment="In Toolbar">Start &File...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStartDisc">
|
||||
<property name="icon">
|
||||
<iconset theme="disc-2-line">
|
||||
@@ -272,6 +286,15 @@
|
||||
<string>Start &Disc...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbarStartDisc">
|
||||
<property name="icon">
|
||||
<iconset theme="disc-2-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string comment="In Toolbar">Start &Disc...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStartBios">
|
||||
<property name="icon">
|
||||
<iconset theme="chip-line">
|
||||
@@ -281,6 +304,15 @@
|
||||
<string>Start &BIOS</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbarStartBios">
|
||||
<property name="icon">
|
||||
<iconset theme="chip-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string comment="In Toolbar">Start &BIOS</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionScanForNewGames">
|
||||
<property name="icon">
|
||||
<iconset theme="file-search-line">
|
||||
@@ -308,6 +340,15 @@
|
||||
<string>Shut &Down</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbarPowerOff">
|
||||
<property name="icon">
|
||||
<iconset theme="shut-down-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string comment="In Toolbar">Shut &Down</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPowerOffWithoutSaving">
|
||||
<property name="icon">
|
||||
<iconset theme="close-line">
|
||||
@@ -326,6 +367,15 @@
|
||||
<string>&Reset</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbarReset">
|
||||
<property name="icon">
|
||||
<iconset theme="restart-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string comment="In Toolbar">&Reset</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPause">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
@@ -338,22 +388,34 @@
|
||||
<string>&Pause</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionLoadState">
|
||||
<action name="actionToolbarPause">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="pause-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string comment="In Toolbar">&Pause</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbarLoadState">
|
||||
<property name="icon">
|
||||
<iconset theme="floppy-out-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Load State</string>
|
||||
<string comment="In Toolbar">&Load State</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSaveState">
|
||||
<action name="actionToolbarSaveState">
|
||||
<property name="icon">
|
||||
<iconset theme="floppy-in-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Save State</string>
|
||||
<string comment="In Toolbar">&Save State</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit">
|
||||
@@ -392,6 +454,15 @@
|
||||
<string>&Controllers</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbarControllerSettings">
|
||||
<property name="icon">
|
||||
<iconset theme="controller-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string comment="In Toolbar">&Controllers</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHotkeySettings">
|
||||
<property name="icon">
|
||||
<iconset theme="keyboard-line">
|
||||
@@ -433,37 +504,46 @@
|
||||
<string>Fullscreen</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbarFullscreen">
|
||||
<property name="icon">
|
||||
<iconset theme="fullscreen-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string comment="In Toolbar">Fullscreen</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionResolution_Scale">
|
||||
<property name="text">
|
||||
<string>Resolution Scale</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGitHubRepository">
|
||||
<property name="text">
|
||||
<string>&GitHub Repository...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="github">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&GitHub Repository...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSupportForums">
|
||||
<property name="text">
|
||||
<string>Support &Forums...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="at">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Support &Forums...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDiscordServer">
|
||||
<property name="text">
|
||||
<string>&Discord Server...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="discord">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Discord Server...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCheckForUpdates">
|
||||
<property name="icon">
|
||||
@@ -484,21 +564,21 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout">
|
||||
<property name="icon">
|
||||
<iconset resource="resources/resources.qrc">
|
||||
<normaloff>:/icons/AppIcon64.png</normaloff>:/icons/AppIcon64.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&About PCSX2...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources/resources.qrc">
|
||||
<normaloff>:/icons/AppIcon.png</normaloff>:/icons/AppIcon.png</iconset>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionChangeDisc">
|
||||
<action name="actionToolbarChangeDisc">
|
||||
<property name="icon">
|
||||
<iconset theme="disc-eject-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Change Disc...</string>
|
||||
<string comment="In Toolbar">Change Disc...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAudioSettings">
|
||||
@@ -549,13 +629,13 @@
|
||||
<enum>QAction::PreferencesRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSettings2">
|
||||
<action name="actionToolbarSettings">
|
||||
<property name="icon">
|
||||
<iconset theme="settings-3-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Settings</string>
|
||||
<string comment="In Toolbar">&Settings</string>
|
||||
</property>
|
||||
<property name="menuRole">
|
||||
<enum>QAction::PreferencesRole</enum>
|
||||
@@ -595,6 +675,15 @@
|
||||
<string>&Screenshot</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbarScreenshot">
|
||||
<property name="icon">
|
||||
<iconset theme="screenshot-2-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string comment="In Toolbar">&Screenshot</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMemoryCardSettings">
|
||||
<property name="icon">
|
||||
<iconset theme="memcard-line">
|
||||
@@ -720,55 +809,55 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGridViewZoomIn">
|
||||
<property name="icon">
|
||||
<iconset theme="zoom-in-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom &In (Grid View)</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl++</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="zoom-in-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGridViewZoomOut">
|
||||
<property name="icon">
|
||||
<iconset theme="zoom-out-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom &Out (Grid View)</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+-</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="zoom-out-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGridViewRefreshCovers">
|
||||
<property name="text">
|
||||
<string>Refresh &Covers (Grid View)</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="refresh-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Refresh &Covers (Grid View)</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen_Memory_Card_Directory">
|
||||
<property name="text">
|
||||
<string>Open Memory Card Directory...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="memcard-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open Memory Card Directory...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpenDataDirectory">
|
||||
<property name="text">
|
||||
<string>Open Data Directory...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="folder-open-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open Data Directory...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToggleSoftwareRendering">
|
||||
<property name="text">
|
||||
@@ -776,13 +865,13 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDebugger">
|
||||
<property name="text">
|
||||
<string>Open Debugger</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="heart-circle-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open Debugger</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionReloadPatches">
|
||||
<property name="text">
|
||||
@@ -920,23 +1009,23 @@
|
||||
<string>Start Big Picture Mode</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStartFullscreenUI2">
|
||||
<action name="actionToolbarStartFullscreenUI">
|
||||
<property name="icon">
|
||||
<iconset theme="tv-2-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Big Picture</string>
|
||||
<string comment="In Toolbar">Big Picture</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCoverDownloader">
|
||||
<property name="text">
|
||||
<string>Cover Downloader...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="artboard-2-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cover Downloader...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShowAdvancedSettings">
|
||||
<property name="checkable">
|
||||
|
||||
+85
-45
@@ -21,6 +21,7 @@
|
||||
#include "MainWindow.h"
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
#include "SetupWizardDialog.h"
|
||||
#include "svnrev.h"
|
||||
|
||||
#include "pcsx2/CDVD/CDVDcommon.h"
|
||||
@@ -38,14 +39,15 @@
|
||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||
#include "pcsx2/Input/InputManager.h"
|
||||
#include "pcsx2/LogSink.h"
|
||||
#include "pcsx2/MTGS.h"
|
||||
#include "pcsx2/PAD/Host/PAD.h"
|
||||
#include "pcsx2/PerformanceMetrics.h"
|
||||
#include "pcsx2/SysForwardDefs.h"
|
||||
#include "pcsx2/VMManager.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/CrashHandler.h"
|
||||
#include "common/Exceptions.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Path.h"
|
||||
#include "common/SettingsWrapper.h"
|
||||
@@ -79,6 +81,8 @@ namespace QtHost
|
||||
static bool InitializeConfig();
|
||||
static void SaveSettings();
|
||||
static void HookSignals();
|
||||
static void RegisterTypes();
|
||||
static bool RunSetupWizard();
|
||||
} // namespace QtHost
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -91,6 +95,7 @@ static bool s_nogui_mode = false;
|
||||
static bool s_start_fullscreen_ui = false;
|
||||
static bool s_start_fullscreen_ui_fullscreen = false;
|
||||
static bool s_test_config_and_exit = false;
|
||||
static bool s_run_setup_wizard = false;
|
||||
static bool s_boot_and_debug = false;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -186,7 +191,7 @@ void EmuThread::startFullscreenUI(bool fullscreen)
|
||||
return;
|
||||
}
|
||||
|
||||
if (VMManager::HasValidVM() || GetMTGS().IsOpen())
|
||||
if (VMManager::HasValidVM() || MTGS::IsOpen())
|
||||
return;
|
||||
|
||||
// this should just set the flag so it gets automatically started
|
||||
@@ -195,7 +200,7 @@ void EmuThread::startFullscreenUI(bool fullscreen)
|
||||
m_is_rendering_to_main = shouldRenderToMain();
|
||||
m_is_fullscreen = fullscreen;
|
||||
|
||||
if (!GetMTGS().WaitForOpen())
|
||||
if (!MTGS::WaitForOpen())
|
||||
{
|
||||
m_run_fullscreen_ui = false;
|
||||
return;
|
||||
@@ -213,18 +218,18 @@ void EmuThread::stopFullscreenUI()
|
||||
QMetaObject::invokeMethod(this, &EmuThread::stopFullscreenUI, Qt::QueuedConnection);
|
||||
|
||||
// wait until the host display is gone
|
||||
while (GetMTGS().IsOpen())
|
||||
while (MTGS::IsOpen())
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetMTGS().IsOpen())
|
||||
if (!MTGS::IsOpen())
|
||||
return;
|
||||
|
||||
pxAssertRel(!VMManager::HasValidVM(), "VM is not valid at FSUI shutdown time");
|
||||
m_run_fullscreen_ui = false;
|
||||
GetMTGS().WaitForClose();
|
||||
MTGS::WaitForClose();
|
||||
}
|
||||
|
||||
void EmuThread::startVM(std::shared_ptr<VMBootParameters> boot_params)
|
||||
@@ -505,14 +510,14 @@ void EmuThread::setFullscreen(bool fullscreen, bool allow_render_to_main)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetMTGS().IsOpen() || m_is_fullscreen == fullscreen)
|
||||
if (!MTGS::IsOpen() || m_is_fullscreen == fullscreen)
|
||||
return;
|
||||
|
||||
// This will call back to us on the MTGS thread.
|
||||
m_is_fullscreen = fullscreen;
|
||||
m_is_rendering_to_main = allow_render_to_main && shouldRenderToMain();
|
||||
GetMTGS().UpdateDisplayWindow();
|
||||
GetMTGS().WaitGS();
|
||||
MTGS::UpdateDisplayWindow();
|
||||
MTGS::WaitGS();
|
||||
|
||||
// If we're using exclusive fullscreen, the refresh rate may have changed.
|
||||
UpdateVSyncRate(true);
|
||||
@@ -526,17 +531,17 @@ void EmuThread::setSurfaceless(bool surfaceless)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetMTGS().IsOpen() || m_is_surfaceless == surfaceless)
|
||||
if (!MTGS::IsOpen() || m_is_surfaceless == surfaceless)
|
||||
return;
|
||||
|
||||
// If we went surfaceless and were running the fullscreen UI, stop MTGS running idle.
|
||||
// Otherwise, we'll keep trying to present to nothing.
|
||||
GetMTGS().SetRunIdle(!surfaceless && m_run_fullscreen_ui);
|
||||
MTGS::SetRunIdle(!surfaceless && m_run_fullscreen_ui);
|
||||
|
||||
// This will call back to us on the MTGS thread.
|
||||
m_is_surfaceless = surfaceless;
|
||||
GetMTGS().UpdateDisplayWindow();
|
||||
GetMTGS().WaitGS();
|
||||
MTGS::UpdateDisplayWindow();
|
||||
MTGS::WaitGS();
|
||||
}
|
||||
|
||||
void EmuThread::applySettings()
|
||||
@@ -591,20 +596,22 @@ void Host::LoadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& loc
|
||||
|
||||
void EmuThread::checkForSettingChanges(const Pcsx2Config& old_config)
|
||||
{
|
||||
QMetaObject::invokeMethod(g_main_window, &MainWindow::checkForSettingChanges, Qt::QueuedConnection);
|
||||
if (g_main_window)
|
||||
{
|
||||
QMetaObject::invokeMethod(g_main_window, &MainWindow::checkForSettingChanges, Qt::QueuedConnection);
|
||||
updatePerformanceMetrics(true);
|
||||
}
|
||||
|
||||
if (GetMTGS().IsOpen())
|
||||
if (MTGS::IsOpen())
|
||||
{
|
||||
const bool render_to_main = shouldRenderToMain();
|
||||
if (!m_is_fullscreen && m_is_rendering_to_main != render_to_main)
|
||||
{
|
||||
m_is_rendering_to_main = render_to_main;
|
||||
GetMTGS().UpdateDisplayWindow();
|
||||
GetMTGS().WaitGS();
|
||||
MTGS::UpdateDisplayWindow();
|
||||
MTGS::WaitGS();
|
||||
}
|
||||
}
|
||||
|
||||
updatePerformanceMetrics(true);
|
||||
}
|
||||
|
||||
void Host::CheckForSettingsChanges(const Pcsx2Config& old_config)
|
||||
@@ -628,7 +635,7 @@ void EmuThread::toggleSoftwareRendering()
|
||||
if (!VMManager::HasValidVM())
|
||||
return;
|
||||
|
||||
GetMTGS().ToggleSoftwareRendering();
|
||||
MTGS::ToggleSoftwareRendering();
|
||||
}
|
||||
|
||||
void EmuThread::switchRenderer(GSRendererType renderer)
|
||||
@@ -642,7 +649,7 @@ void EmuThread::switchRenderer(GSRendererType renderer)
|
||||
if (!VMManager::HasValidVM())
|
||||
return;
|
||||
|
||||
GetMTGS().SwitchRenderer(renderer);
|
||||
MTGS::SwitchRenderer(renderer);
|
||||
}
|
||||
|
||||
void EmuThread::changeDisc(CDVD_SourceType source, const QString& path)
|
||||
@@ -786,10 +793,10 @@ void EmuThread::connectDisplaySignals(DisplayWidget* widget)
|
||||
|
||||
void EmuThread::onDisplayWindowResized(int width, int height, float scale)
|
||||
{
|
||||
if (!GetMTGS().IsOpen())
|
||||
if (!MTGS::IsOpen())
|
||||
return;
|
||||
|
||||
GetMTGS().ResizeDisplayWindow(width, height, scale);
|
||||
MTGS::ResizeDisplayWindow(width, height, scale);
|
||||
}
|
||||
|
||||
void EmuThread::onApplicationStateChanged(Qt::ApplicationState state)
|
||||
@@ -835,7 +842,7 @@ void EmuThread::redrawDisplayWindow()
|
||||
if (!VMManager::HasValidVM() || VMManager::GetState() == VMState::Running)
|
||||
return;
|
||||
|
||||
GetMTGS().PresentCurrentFrame();
|
||||
MTGS::PresentCurrentFrame();
|
||||
}
|
||||
|
||||
void EmuThread::runOnCPUThread(const std::function<void()>& func)
|
||||
@@ -854,7 +861,7 @@ void EmuThread::queueSnapshot(quint32 gsdump_frames)
|
||||
if (!VMManager::HasValidVM())
|
||||
return;
|
||||
|
||||
GetMTGS().RunOnGSThread([gsdump_frames]() { GSQueueSnapshot(std::string(), gsdump_frames); });
|
||||
MTGS::RunOnGSThread([gsdump_frames]() { GSQueueSnapshot(std::string(), gsdump_frames); });
|
||||
}
|
||||
|
||||
void EmuThread::beginCapture(const QString& path)
|
||||
@@ -868,13 +875,13 @@ void EmuThread::beginCapture(const QString& path)
|
||||
if (!VMManager::HasValidVM())
|
||||
return;
|
||||
|
||||
GetMTGS().RunOnGSThread([path = path.toStdString()]() {
|
||||
MTGS::RunOnGSThread([path = path.toStdString()]() {
|
||||
GSBeginCapture(std::move(path));
|
||||
});
|
||||
|
||||
// Sync GS thread. We want to start adding audio at the same time as video.
|
||||
// TODO: This could be up to 64 frames behind... use the pts to adjust it.
|
||||
GetMTGS().WaitGS(false, false, false);
|
||||
MTGS::WaitGS(false, false, false);
|
||||
}
|
||||
|
||||
void EmuThread::endCapture()
|
||||
@@ -888,7 +895,7 @@ void EmuThread::endCapture()
|
||||
if (!VMManager::HasValidVM())
|
||||
return;
|
||||
|
||||
GetMTGS().RunOnGSThread(&GSEndCapture);
|
||||
MTGS::RunOnGSThread(&GSEndCapture);
|
||||
}
|
||||
|
||||
std::optional<WindowInfo> EmuThread::acquireRenderWindow(bool recreate_window)
|
||||
@@ -1179,13 +1186,6 @@ void Host::SetFullscreen(bool enabled)
|
||||
g_emu_thread->setFullscreen(enabled, true);
|
||||
}
|
||||
|
||||
alignas(16) static SysMtgsThread s_mtgs_thread;
|
||||
|
||||
SysMtgsThread& GetMTGS()
|
||||
{
|
||||
return s_mtgs_thread;
|
||||
}
|
||||
|
||||
bool QtHost::InitializeConfig()
|
||||
{
|
||||
if (!EmuFolders::InitializeCriticalFolders())
|
||||
@@ -1199,6 +1199,7 @@ bool QtHost::InitializeConfig()
|
||||
CrashHandler::SetWriteDirectory(EmuFolders::DataRoot);
|
||||
|
||||
const std::string path(Path::Combine(EmuFolders::Settings, "PCSX2.ini"));
|
||||
s_run_setup_wizard = s_run_setup_wizard || !FileSystem::FileExists(path.c_str());
|
||||
Console.WriteLn("Loading config from %s.", path.c_str());
|
||||
|
||||
s_base_settings_interface = std::make_unique<INISettingsInterface>(std::move(path));
|
||||
@@ -1215,11 +1216,19 @@ bool QtHost::InitializeConfig()
|
||||
}
|
||||
|
||||
VMManager::SetDefaultSettings(*s_base_settings_interface, true, true, true, true, true);
|
||||
SaveSettings();
|
||||
|
||||
// Don't save if we're running the setup wizard. We want to run it next time if they don't finish it.
|
||||
if (!s_run_setup_wizard)
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
// Setup wizard was incomplete last time?
|
||||
s_run_setup_wizard =
|
||||
s_run_setup_wizard || s_base_settings_interface->GetBoolValue("UI", "SetupWizardIncomplete", false);
|
||||
|
||||
LogSink::SetBlockSystemConsole(QtHost::InNoGUIMode());
|
||||
VMManager::Internal::LoadStartupSettings();
|
||||
InstallTranslator();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1535,6 +1544,7 @@ void QtHost::PrintCommandLineHelp(const std::string_view& progname)
|
||||
std::fprintf(stderr, " -bigpicture: Forces PCSX2 to use the Big Picture mode (useful for controller-only and couch play).\n");
|
||||
std::fprintf(stderr, " -earlyconsolelog: Forces logging of early console messages to console.\n");
|
||||
std::fprintf(stderr, " -testconfig: Initializes configuration and checks version, then exits.\n");
|
||||
std::fprintf(stderr, " -setupwizard: Forces initial setup wizard to run.\n");
|
||||
std::fprintf(stderr, " -debugger: Open debugger and break on entry point.\n");
|
||||
#ifdef ENABLE_RAINTEGRATION
|
||||
std::fprintf(stderr, " -raintegration: Use RAIntegration instead of built-in achievement support.\n");
|
||||
@@ -1658,6 +1668,11 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
|
||||
s_test_config_and_exit = true;
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG(QStringLiteral("-setupwizard")))
|
||||
{
|
||||
s_run_setup_wizard = true;
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG(QStringLiteral("-debugger")))
|
||||
{
|
||||
s_boot_and_debug = true;
|
||||
@@ -1737,7 +1752,7 @@ static bool PerformEarlyHardwareChecks()
|
||||
|
||||
#endif
|
||||
|
||||
static void RegisterTypes()
|
||||
void QtHost::RegisterTypes()
|
||||
{
|
||||
qRegisterMetaType<std::optional<bool>>();
|
||||
qRegisterMetaType<std::optional<WindowInfo>>("std::optional<WindowInfo>()");
|
||||
@@ -1756,12 +1771,28 @@ static void RegisterTypes()
|
||||
qRegisterMetaType<const GameList::Entry*>();
|
||||
}
|
||||
|
||||
bool QtHost::RunSetupWizard()
|
||||
{
|
||||
// Set a flag in the config so that even though we created the ini, we'll run the wizard next time.
|
||||
Host::SetBaseBoolSettingValue("UI", "SetupWizardIncomplete", true);
|
||||
Host::CommitBaseSettingChanges();
|
||||
|
||||
SetupWizardDialog dialog;
|
||||
if (dialog.exec() == QDialog::Rejected)
|
||||
return false;
|
||||
|
||||
// Remove the flag.
|
||||
Host::SetBaseBoolSettingValue("UI", "SetupWizardIncomplete", false);
|
||||
Host::CommitBaseSettingChanges();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
CrashHandler::Install();
|
||||
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
RegisterTypes();
|
||||
QtHost::RegisterTypes();
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
@@ -1784,24 +1815,32 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Set theme before creating any windows.
|
||||
QtHost::UpdateApplicationTheme();
|
||||
MainWindow* main_window = new MainWindow();
|
||||
|
||||
// Start up the CPU thread.
|
||||
QtHost::HookSignals();
|
||||
EmuThread::start();
|
||||
|
||||
// Optionally run setup wizard.
|
||||
int result;
|
||||
if (s_run_setup_wizard && !QtHost::RunSetupWizard())
|
||||
{
|
||||
result = EXIT_FAILURE;
|
||||
goto shutdown_and_exit;
|
||||
}
|
||||
|
||||
// Create all window objects, the emuthread might still be starting up at this point.
|
||||
main_window->initialize();
|
||||
g_main_window = new MainWindow();
|
||||
g_main_window->initialize();
|
||||
|
||||
// When running in batch mode, ensure game list is loaded, but don't scan for any new files.
|
||||
if (!s_batch_mode)
|
||||
main_window->refreshGameList(false);
|
||||
g_main_window->refreshGameList(false);
|
||||
else
|
||||
GameList::Refresh(false, true);
|
||||
|
||||
// Don't bother showing the window in no-gui mode.
|
||||
if (!s_nogui_mode)
|
||||
main_window->show();
|
||||
g_main_window->show();
|
||||
|
||||
// Initialize big picture mode if requested.
|
||||
if (s_start_fullscreen_ui)
|
||||
@@ -1810,18 +1849,19 @@ int main(int argc, char* argv[])
|
||||
if (s_boot_and_debug)
|
||||
{
|
||||
DebugInterface::setPauseOnEntry(true);
|
||||
main_window->openDebugger();
|
||||
g_main_window->openDebugger();
|
||||
}
|
||||
|
||||
// Skip the update check if we're booting a game directly.
|
||||
if (autoboot)
|
||||
g_emu_thread->startVM(std::move(autoboot));
|
||||
else if (!s_nogui_mode)
|
||||
main_window->startupUpdateCheck();
|
||||
g_main_window->startupUpdateCheck();
|
||||
|
||||
// This doesn't return until we exit.
|
||||
const int result = app.exec();
|
||||
result = app.exec();
|
||||
|
||||
shutdown_and_exit:
|
||||
// Shutting down.
|
||||
EmuThread::stop();
|
||||
if (g_main_window)
|
||||
|
||||
@@ -216,6 +216,9 @@ namespace QtHost
|
||||
/// Default theme name for the platform.
|
||||
const char* GetDefaultThemeName();
|
||||
|
||||
/// Default language for the platform.
|
||||
const char* GetDefaultLanguage();
|
||||
|
||||
/// Sets application theme according to settings.
|
||||
void UpdateApplicationTheme();
|
||||
|
||||
@@ -234,6 +237,12 @@ namespace QtHost
|
||||
/// Executes a function on the UI thread.
|
||||
void RunOnUIThread(const std::function<void()>& func, bool block = false);
|
||||
|
||||
/// Returns a list of supported languages and codes (suffixes for translation files).
|
||||
std::vector<std::pair<QString, QString>> GetAvailableLanguageList();
|
||||
|
||||
/// Call when the language changes.
|
||||
void InstallTranslator();
|
||||
|
||||
/// Returns the application name and version, optionally including debug/devel config indicator.
|
||||
QString GetAppNameAndVersion();
|
||||
|
||||
|
||||
@@ -931,14 +931,18 @@ namespace SettingWidgetBinder
|
||||
|
||||
template <typename WidgetType>
|
||||
static inline void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key,
|
||||
const char** enum_names, const char** enum_values, const char* default_value)
|
||||
const char** enum_names, const char** enum_values, const char* default_value, const char* translation_ctx = nullptr)
|
||||
{
|
||||
using Accessor = SettingAccessor<WidgetType>;
|
||||
|
||||
const std::string value = Host::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value);
|
||||
|
||||
for (int i = 0; enum_names[i] != nullptr; i++)
|
||||
widget->addItem(QString::fromUtf8(enum_names[i]));
|
||||
{
|
||||
widget->addItem(translation_ctx ?
|
||||
qApp->translate(translation_ctx, enum_names[i]) :
|
||||
QString::fromUtf8(enum_names[i]));
|
||||
}
|
||||
|
||||
int enum_index = -1;
|
||||
for (int i = 0; enum_values[i] != nullptr; i++)
|
||||
|
||||
@@ -9,22 +9,10 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>410</width>
|
||||
<height>190</height>
|
||||
<width>447</width>
|
||||
<height>196</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>410</width>
|
||||
<height>190</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>410</width>
|
||||
<height>190</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string comment="Window title">RetroAchievements Login</string>
|
||||
</property>
|
||||
|
||||
@@ -157,7 +157,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p align="justify">PCSX2 uses RetroAchievements as an achievement database and for tracking progress. To use achievements, please sign up for an account at <a href="https://retroachievements.org/"><span style=" text-decoration: underline; color:#4169e1;">retroachievements.org</span></a>.</p><p align="justify">To view the achievement list in-game, press the hotkey for <span style=" font-weight:600;">Open Pause Menu</span> and select <span style=" font-weight:600;">Achievements</span> from the menu.</p></body></html></string>
|
||||
<string><html><head/><body><p align="justify">PCSX2 uses RetroAchievements as an achievement database and for tracking progress. To use achievements, please sign up for an account at <a href="https://retroachievements.org/">retroachievements.org</a>.</p><p align="justify">To view the achievement list in-game, press the hotkey for <span style=" font-weight:600;">Open Pause Menu</span> and select <span style=" font-weight:600;">Achievements</span> from the menu.</p></body></html></string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
|
||||
@@ -39,20 +39,6 @@ static constexpr s32 DEFAULT_SOUNDTOUCH_SEQUENCE_LENGTH = 30;
|
||||
static constexpr s32 DEFAULT_SOUNDTOUCH_SEEK_WINDOW = 20;
|
||||
static constexpr s32 DEFAULT_SOUNDTOUCH_OVERLAP = 10;
|
||||
|
||||
static const char* s_output_module_entries[] = {QT_TRANSLATE_NOOP("AudioSettingsWidget", "No Sound (Emulate SPU2 only)"),
|
||||
//: Cubeb is an audio engine name. Leave as-is.
|
||||
QT_TRANSLATE_NOOP("AudioSettingsWidget", "Cubeb (Cross-platform)"),
|
||||
#ifdef _WIN32
|
||||
//: XAudio2 is an audio engine name. Leave as-is.
|
||||
QT_TRANSLATE_NOOP("AudioSettingsWidget", "XAudio2"),
|
||||
#endif
|
||||
nullptr};
|
||||
static const char* s_output_module_values[] = {"nullout", "cubeb",
|
||||
#ifdef _WIN32
|
||||
"xaudio2",
|
||||
#endif
|
||||
nullptr};
|
||||
|
||||
AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, m_dialog(dialog)
|
||||
@@ -60,6 +46,7 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent
|
||||
SettingsInterface* sif = dialog->getSettingsInterface();
|
||||
|
||||
m_ui.setupUi(this);
|
||||
populateOutputModules();
|
||||
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.syncMode, "SPU2/Output", "SynchMode", DEFAULT_SYNCHRONIZATION_MODE);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.expansionMode, "SPU2/Output", "SpeakerConfiguration", DEFAULT_EXPANSION_MODE);
|
||||
@@ -69,8 +56,7 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent
|
||||
updateTargetLatencyRange();
|
||||
expansionModeChanged();
|
||||
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(
|
||||
sif, m_ui.outputModule, "SPU2/Output", "OutputModule", s_output_module_entries, s_output_module_values, DEFAULT_OUTPUT_MODULE);
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.outputModule, "SPU2/Output", "OutputModule", DEFAULT_OUTPUT_MODULE);
|
||||
SettingWidgetBinder::BindSliderToIntSetting(
|
||||
//: Measuring unit that will appear after the number selected in its option. Adapt the space depending on your language's rules.
|
||||
sif, m_ui.targetLatency, m_ui.targetLatencyLabel, tr(" ms"), "SPU2/Output", "Latency", DEFAULT_TARGET_LATENCY);
|
||||
@@ -86,15 +72,18 @@ AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent
|
||||
outputModuleChanged();
|
||||
|
||||
m_ui.volume->setValue(m_dialog->getEffectiveIntValue("SPU2/Mixing", "FinalVolume", DEFAULT_VOLUME));
|
||||
m_ui.volume->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(m_ui.volume, &QSlider::valueChanged, this, &AudioSettingsWidget::volumeChanged);
|
||||
connect(m_ui.volume, &QSlider::customContextMenuRequested, this, &AudioSettingsWidget::volumeContextMenuRequested);
|
||||
updateVolumeLabel();
|
||||
if (sif && sif->ContainsValue("SPU2/Mixing", "FinalVolume"))
|
||||
if (dialog->isPerGameSettings())
|
||||
{
|
||||
QFont bold_font(m_ui.volume->font());
|
||||
bold_font.setBold(true);
|
||||
m_ui.volumeLabel->setFont(bold_font);
|
||||
connect(m_ui.volume, &QSlider::customContextMenuRequested, this, &AudioSettingsWidget::volumeContextMenuRequested);
|
||||
m_ui.volume->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
if (sif->ContainsValue("SPU2/Mixing", "FinalVolume"))
|
||||
{
|
||||
QFont bold_font(m_ui.volume->font());
|
||||
bold_font.setBold(true);
|
||||
m_ui.volumeLabel->setFont(bold_font);
|
||||
}
|
||||
}
|
||||
|
||||
SettingWidgetBinder::BindSliderToIntSetting(sif, m_ui.sequenceLength, m_ui.sequenceLengthLabel, tr(" ms"), "Soundtouch",
|
||||
@@ -153,6 +142,12 @@ void AudioSettingsWidget::expansionModeChanged()
|
||||
m_ui.dplLevel->setDisabled(!expansion51);
|
||||
}
|
||||
|
||||
void AudioSettingsWidget::populateOutputModules()
|
||||
{
|
||||
for (const SndOutModule* mod : GetSndOutModules())
|
||||
m_ui.outputModule->addItem(qApp->translate("SPU2", mod->GetDisplayName()), QString::fromUtf8(mod->GetIdent()));
|
||||
}
|
||||
|
||||
void AudioSettingsWidget::outputModuleChanged()
|
||||
{
|
||||
const std::string module_name(m_dialog->getEffectiveStringValue("SPU2/Output", "OutputModule", DEFAULT_OUTPUT_MODULE));
|
||||
@@ -284,7 +279,7 @@ void AudioSettingsWidget::volumeContextMenuRequested(const QPoint& pt)
|
||||
m_ui.volume->connect(menu.addAction(qApp->translate("SettingWidgetBinder", "Reset")), &QAction::triggered, this, [this]() {
|
||||
const s32 global_value = Host::GetBaseIntSettingValue("SPU2/Mixing", "FinalVolume", DEFAULT_VOLUME);
|
||||
{
|
||||
QSignalBlocker sb(m_ui.volumeLabel);
|
||||
QSignalBlocker sb(m_ui.volume);
|
||||
m_ui.volume->setValue(global_value);
|
||||
updateVolumeLabel();
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ private Q_SLOTS:
|
||||
void resetTimestretchDefaults();
|
||||
|
||||
private:
|
||||
void populateOutputModules();
|
||||
void updateVolumeLabel();
|
||||
|
||||
SettingsDialog* m_dialog;
|
||||
|
||||
@@ -78,11 +78,17 @@ void BIOSSettingsWidget::refreshList()
|
||||
}
|
||||
|
||||
void BIOSSettingsWidget::listRefreshed(const QVector<BIOSInfo>& items)
|
||||
{
|
||||
QSignalBlocker sb(m_ui.fileList);
|
||||
populateList(m_ui.fileList, items);
|
||||
m_ui.fileList->setEnabled(true);
|
||||
}
|
||||
|
||||
void BIOSSettingsWidget::populateList(QTreeWidget* list, const QVector<BIOSInfo>& items)
|
||||
{
|
||||
const std::string selected_bios(Host::GetBaseStringSettingValue("Filenames", "BIOS"));
|
||||
const QString res_path(QtHost::GetResourcesBasePath());
|
||||
|
||||
QSignalBlocker sb(m_ui.fileList);
|
||||
for (const BIOSInfo& bi : items)
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
@@ -129,12 +135,14 @@ void BIOSSettingsWidget::listRefreshed(const QVector<BIOSInfo>& items)
|
||||
break;
|
||||
}
|
||||
|
||||
m_ui.fileList->addTopLevelItem(item);
|
||||
list->addTopLevelItem(item);
|
||||
|
||||
if (bi.filename == selected_bios)
|
||||
{
|
||||
list->selectionModel()->setCurrentIndex(list->indexFromItem(item), QItemSelectionModel::Select);
|
||||
item->setSelected(true);
|
||||
}
|
||||
}
|
||||
m_ui.fileList->setEnabled(true);
|
||||
}
|
||||
|
||||
void BIOSSettingsWidget::listItemChanged(const QTreeWidgetItem* current, const QTreeWidgetItem* previous)
|
||||
@@ -151,9 +159,8 @@ void BIOSSettingsWidget::fastBootChanged()
|
||||
m_ui.fastBootFastForward->setEnabled(enabled);
|
||||
}
|
||||
|
||||
BIOSSettingsWidget::RefreshThread::RefreshThread(BIOSSettingsWidget* parent, const QString& directory)
|
||||
BIOSSettingsWidget::RefreshThread::RefreshThread(QWidget* parent, const QString& directory)
|
||||
: QThread(parent)
|
||||
, m_parent(parent)
|
||||
, m_directory(directory)
|
||||
{
|
||||
}
|
||||
@@ -179,5 +186,5 @@ void BIOSSettingsWidget::RefreshThread::run()
|
||||
}
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(m_parent, "listRefreshed", Qt::QueuedConnection, Q_ARG(const QVector<BIOSInfo>&, items));
|
||||
QMetaObject::invokeMethod(parent(), "listRefreshed", Qt::QueuedConnection, Q_ARG(const QVector<BIOSInfo>&, items));
|
||||
}
|
||||
|
||||
@@ -46,6 +46,21 @@ public:
|
||||
BIOSSettingsWidget(SettingsDialog* dialog, QWidget* parent);
|
||||
~BIOSSettingsWidget();
|
||||
|
||||
class RefreshThread final : public QThread
|
||||
{
|
||||
public:
|
||||
RefreshThread(QWidget* parent, const QString& directory);
|
||||
~RefreshThread();
|
||||
|
||||
protected:
|
||||
void run() override;
|
||||
|
||||
private:
|
||||
QString m_directory;
|
||||
};
|
||||
|
||||
static void populateList(QTreeWidget* list, const QVector<BIOSInfo>& items);
|
||||
|
||||
private Q_SLOTS:
|
||||
void refreshList();
|
||||
|
||||
@@ -58,19 +73,5 @@ private:
|
||||
Ui::BIOSSettingsWidget m_ui;
|
||||
SettingsDialog* m_dialog;
|
||||
|
||||
class RefreshThread final : public QThread
|
||||
{
|
||||
public:
|
||||
RefreshThread(BIOSSettingsWidget* parent, const QString& directory);
|
||||
~RefreshThread();
|
||||
|
||||
protected:
|
||||
void run() override;
|
||||
|
||||
private:
|
||||
BIOSSettingsWidget* m_parent;
|
||||
QString m_directory;
|
||||
};
|
||||
|
||||
RefreshThread* m_refresh_thread = nullptr;
|
||||
};
|
||||
|
||||
@@ -72,7 +72,7 @@ QIcon ControllerBindingWidget::getIcon() const
|
||||
void ControllerBindingWidget::populateControllerTypes()
|
||||
{
|
||||
for (const auto& [name, display_name] : PAD::GetControllerTypeNames())
|
||||
m_ui.controllerType->addItem(QString::fromStdString(display_name), QString::fromStdString(name));
|
||||
m_ui.controllerType->addItem(qApp->translate("Pad", display_name), QString::fromStdString(name));
|
||||
}
|
||||
|
||||
void ControllerBindingWidget::onTypeChanged()
|
||||
@@ -116,8 +116,8 @@ void ControllerBindingWidget::onTypeChanged()
|
||||
if (has_settings)
|
||||
{
|
||||
const gsl::span<const SettingInfo> settings(cinfo->settings, cinfo->num_settings);
|
||||
m_settings_widget =
|
||||
new ControllerCustomSettingsWidget(settings, m_config_section, std::string(), cinfo->name, getDialog(), m_ui.stackedWidget);
|
||||
m_settings_widget = new ControllerCustomSettingsWidget(
|
||||
settings, m_config_section, std::string(), "Pad", getDialog(), m_ui.stackedWidget);
|
||||
m_ui.stackedWidget->addWidget(m_settings_widget);
|
||||
}
|
||||
|
||||
@@ -343,7 +343,7 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare
|
||||
continue;
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
item->setText(QString::fromUtf8(bi.display_name));
|
||||
item->setText(qApp->translate("Pad", bi.display_name));
|
||||
item->setCheckState((std::find(m_binds.begin(), m_binds.end(), &bi) != m_binds.end()) ? Qt::Checked : Qt::Unchecked);
|
||||
m_ui.bindList->addItem(item);
|
||||
}
|
||||
@@ -374,7 +374,7 @@ QString ControllerMacroEditWidget::getSummary() const
|
||||
{
|
||||
if (!str.isEmpty())
|
||||
str += static_cast<QChar>('/');
|
||||
str += QString::fromUtf8(bi->name);
|
||||
str += qApp->translate("Pad", bi->display_name);
|
||||
}
|
||||
return str.isEmpty() ? tr("Not Configured") : str;
|
||||
}
|
||||
@@ -902,7 +902,7 @@ QIcon USBDeviceWidget::getIcon() const
|
||||
void USBDeviceWidget::populateDeviceTypes()
|
||||
{
|
||||
for (const auto& [name, display_name] : USB::GetDeviceTypes())
|
||||
m_ui.deviceType->addItem(QString::fromStdString(display_name), QString::fromStdString(name));
|
||||
m_ui.deviceType->addItem(qApp->translate("USB", display_name), QString::fromUtf8(name));
|
||||
}
|
||||
|
||||
void USBDeviceWidget::populatePages()
|
||||
@@ -950,7 +950,7 @@ void USBDeviceWidget::populatePages()
|
||||
if (!settings.empty())
|
||||
{
|
||||
m_settings_widget = new ControllerCustomSettingsWidget(
|
||||
settings, m_config_section, m_device_type + "_", m_device_type.c_str(), m_dialog, m_ui.stackedWidget);
|
||||
settings, m_config_section, m_device_type + "_", "USB", m_dialog, m_ui.stackedWidget);
|
||||
m_ui.stackedWidget->addWidget(m_settings_widget);
|
||||
}
|
||||
|
||||
@@ -1027,7 +1027,7 @@ void USBDeviceWidget::onAutomaticBindingClicked()
|
||||
void USBDeviceWidget::onClearBindingsClicked()
|
||||
{
|
||||
if (QMessageBox::question(QtUtils::GetRootWidget(this), tr("Clear Bindings"),
|
||||
tr("Are you sure you want to clear all bindings for this controller? This action cannot be undone.")) != QMessageBox::Yes)
|
||||
tr("Are you sure you want to clear all bindings for this device? This action cannot be undone.")) != QMessageBox::Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ void ControllerSettingsDialog::onNewProfileClicked()
|
||||
// from global
|
||||
auto lock = Host::GetSettingsLock();
|
||||
PAD::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true, false);
|
||||
USB::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -135,6 +136,7 @@ void ControllerSettingsDialog::onNewProfileClicked()
|
||||
const bool copy_hotkey_bindings = m_profile_interface->GetBoolValue("Pad", "UseProfileHotkeyBindings", false);
|
||||
temp_si.SetBoolValue("Pad", "UseProfileHotkeyBindings", copy_hotkey_bindings);
|
||||
PAD::CopyConfiguration(&temp_si, *m_profile_interface, true, true, copy_hotkey_bindings);
|
||||
USB::CopyConfiguration(&temp_si, *m_profile_interface, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +165,7 @@ void ControllerSettingsDialog::onLoadProfileClicked()
|
||||
{
|
||||
auto lock = Host::GetSettingsLock();
|
||||
PAD::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false);
|
||||
USB::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true);
|
||||
}
|
||||
Host::CommitBaseSettingChanges();
|
||||
|
||||
@@ -398,7 +401,7 @@ void ControllerSettingsDialog::createWidgets()
|
||||
m_ui.settingsContainer->addWidget(m_port_bindings[global_slot]);
|
||||
|
||||
const PAD::ControllerInfo* ci = PAD::GetControllerInfo(m_port_bindings[global_slot]->getControllerType());
|
||||
const QString display_name(ci ? QString::fromUtf8(ci->display_name) : QStringLiteral("Unknown"));
|
||||
const QString display_name(ci ? qApp->translate("Pad", ci->display_name) : QStringLiteral("Unknown"));
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
|
||||
@@ -454,7 +457,7 @@ void ControllerSettingsDialog::updateListDescription(u32 global_slot, Controller
|
||||
const bool mtap_enabled = getBoolValue("Pad", (port == 0) ? "MultitapPort1" : "MultitapPort2", false);
|
||||
|
||||
const PAD::ControllerInfo* ci = PAD::GetControllerInfo(widget->getControllerType());
|
||||
const QString display_name(ci ? QString::fromUtf8(ci->display_name) : QStringLiteral("Unknown"));
|
||||
const QString display_name(ci ? qApp->translate("Pad", ci->display_name) : QStringLiteral("Unknown"));
|
||||
|
||||
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
|
||||
item->setText(mtap_enabled ? (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name)) :
|
||||
|
||||
@@ -73,7 +73,20 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="currentProfile"/>
|
||||
<widget class="QComboBox" name="currentProfile">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>220</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="newProfile">
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Low compatiblity warning: yes, it's very big, but may not work with many games.</string>
|
||||
<string>Low compatibility warning: yes, it's very big, but may not work with many games.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
|
||||
@@ -136,10 +136,10 @@ DEV9SettingsWidget::DEV9SettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
if (m_dialog->isPerGameSettings())
|
||||
m_ui.ethDevType->addItem(tr("Use Global Setting [%1]").arg(QString::fromUtf8(Pcsx2Config::DEV9Options::NetApiNames[static_cast<u32>(m_global_api)])));
|
||||
else
|
||||
m_ui.ethDevType->addItem(QString::fromUtf8(m_api_namelist[0]));
|
||||
m_ui.ethDevType->addItem(qApp->translate("DEV9SettingsWidget", m_api_namelist[0]));
|
||||
|
||||
for (int i = 1; m_api_namelist[i] != nullptr; i++)
|
||||
m_ui.ethDevType->addItem(QString::fromUtf8(m_api_namelist[i]));
|
||||
m_ui.ethDevType->addItem(qApp->translate("DEV9SettingsWidget", m_api_namelist[i]));
|
||||
|
||||
const std::string value = m_dialog->getStringValue("DEV9/Eth", "EthApi", Pcsx2Config::DEV9Options::NetApiNames[static_cast<int>(Pcsx2Config::DEV9Options::NetApi::Unset)]).value();
|
||||
|
||||
@@ -212,12 +212,12 @@ DEV9SettingsWidget::DEV9SettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
connect(m_ui.ethGatewayAuto, QOverload<int>::of(&QCheckBox::stateChanged), this, [&](int state) { onEthAutoChanged(m_ui.ethGatewayAuto, state, m_ui.ethGatewayAddr, "DEV9/Eth", "AutoGateway"); });
|
||||
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.ethDNS1Mode, "DEV9/Eth", "ModeDNS1",
|
||||
s_dns_name, Pcsx2Config::DEV9Options::DnsModeNames, Pcsx2Config::DEV9Options::DnsModeNames[static_cast<int>(Pcsx2Config::DEV9Options::DnsMode::Auto)]);
|
||||
s_dns_name, Pcsx2Config::DEV9Options::DnsModeNames, Pcsx2Config::DEV9Options::DnsModeNames[static_cast<int>(Pcsx2Config::DEV9Options::DnsMode::Auto)], "DEV9SettingsWidget");
|
||||
onEthDNSModeChanged(m_ui.ethDNS1Mode, m_ui.ethDNS1Mode->currentIndex(), m_ui.ethDNS1Addr, "DEV9/Eth", "ModeDNS1");
|
||||
connect(m_ui.ethDNS1Mode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](int index) { onEthDNSModeChanged(m_ui.ethDNS1Mode, index, m_ui.ethDNS1Addr, "DEV9/Eth", "ModeDNS1"); });
|
||||
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.ethDNS2Mode, "DEV9/Eth", "ModeDNS2",
|
||||
s_dns_name, Pcsx2Config::DEV9Options::DnsModeNames, Pcsx2Config::DEV9Options::DnsModeNames[static_cast<int>(Pcsx2Config::DEV9Options::DnsMode::Auto)]);
|
||||
s_dns_name, Pcsx2Config::DEV9Options::DnsModeNames, Pcsx2Config::DEV9Options::DnsModeNames[static_cast<int>(Pcsx2Config::DEV9Options::DnsMode::Auto)], "DEV9SettingsWidget");
|
||||
onEthDNSModeChanged(m_ui.ethDNS2Mode, m_ui.ethDNS2Mode->currentIndex(), m_ui.ethDNS2Addr, "DEV9/Eth", "ModeDNS2");
|
||||
connect(m_ui.ethDNS2Mode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [&](int index) { onEthDNSModeChanged(m_ui.ethDNS2Mode, index, m_ui.ethDNS2Addr, "DEV9/Eth", "ModeDNS2"); });
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
<item row="0" column="0" colspan="4">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Used for storing shaders, gzip indices, and game list data.</string>
|
||||
<string>Used for storing shaders, game list, and achievement data.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
<height>361</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
|
||||
@@ -16,9 +16,6 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
<height>392</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
|
||||
@@ -268,6 +268,11 @@
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-P (Portugal)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-PL (Poland)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string extracomment="Leave the code as-is, translate the country's name.">PAL-R (Russia)</string>
|
||||
|
||||
@@ -554,8 +554,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
||||
"Helps Harry Potter and Stuntman games. It has a big impact on performance."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.preloadFrameData, tr("Preload Frame Data"), tr("Unchecked"),
|
||||
tr("Uploads GS data when rendering a new frame to reproduce some effects accurately. "
|
||||
"Fixes black screen issues in games like Armored Core: Last Raven."));
|
||||
tr("Uploads GS data when rendering a new frame to reproduce some effects accurately. "));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.textureInsideRt, tr("Texture Inside RT"), tr("Disabled"),
|
||||
tr("Allows the texture cache to reuse as an input texture the inner portion of a previous framebuffer."));
|
||||
@@ -678,7 +677,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
|
||||
tr("Displays various settings and the current values of those settings, useful for debugging."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowInputs, tr("Show Inputs"), tr("Unchecked"),
|
||||
tr("Shows the current controler state of the system in the bottom left corner of the display."));
|
||||
tr("Shows the current controller state of the system in the bottom left corner of the display."));
|
||||
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.osdShowFrameTimes, tr("Show Frame Times"), tr("Unchecked"), tr("Displays a graph showing the average frametimes."));
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>720</width>
|
||||
<height>492</height>
|
||||
<height>463</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -29,7 +29,7 @@
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Renderer</string>
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
@@ -237,7 +237,7 @@
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="stretchY">
|
||||
<property name="suffix">
|
||||
<string extracomment="Percentage sign that shows next to a value. You might want to add a space before if you language requires it.">%</string>
|
||||
<string extracomment="Percentage sign that shows next to a value. You might want to add a space before if your language requires it.">%</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "SettingsDialog.h"
|
||||
#include "QtHost.h"
|
||||
|
||||
static const char* THEME_NAMES[] = {
|
||||
const char* InterfaceSettingsWidget::THEME_NAMES[] = {
|
||||
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Native"),
|
||||
//: Ignore what Crowdin says in this string about "[Light]/[Dark]" being untouchable here, these are not variables in this case and must be translated.
|
||||
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Fusion [Light/Dark]"),
|
||||
@@ -52,7 +52,7 @@ static const char* THEME_NAMES[] = {
|
||||
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Custom.qss [Drop in PCSX2 Folder]"),
|
||||
nullptr};
|
||||
|
||||
static const char* THEME_VALUES[] = {
|
||||
const char* InterfaceSettingsWidget::THEME_VALUES[] = {
|
||||
"",
|
||||
"fusion",
|
||||
"darkfusion",
|
||||
@@ -92,9 +92,13 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsDialog* dialog, QWidget
|
||||
connect(m_ui.renderToSeparateWindow, &QCheckBox::stateChanged, this, &InterfaceSettingsWidget::onRenderToSeparateWindowChanged);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.theme, "UI", "Theme", THEME_NAMES, THEME_VALUES,
|
||||
QtHost::GetDefaultThemeName());
|
||||
QtHost::GetDefaultThemeName(), "InterfaceSettingsWidget");
|
||||
connect(m_ui.theme, QOverload<int>::of(&QComboBox::currentIndexChanged), [this]() { emit themeChanged(); });
|
||||
|
||||
populateLanguages();
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.language, "UI", "Language", QtHost::GetDefaultLanguage());
|
||||
connect(m_ui.language, QOverload<int>::of(&QComboBox::currentIndexChanged), [this]() { emit languageChanged(); });
|
||||
|
||||
// Per-game settings is special, we don't want to bind it if we're editing per-game settings.
|
||||
m_ui.perGameSettings->setEnabled(!dialog->isPerGameSettings());
|
||||
if (!dialog->isPerGameSettings())
|
||||
@@ -181,9 +185,6 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsDialog* dialog, QWidget
|
||||
m_ui.disableWindowResizing, tr("Disable Window Resizing"), tr("Unchecked"),
|
||||
tr("Prevents the main window from being resized."));
|
||||
|
||||
// Not yet used, disable the options
|
||||
m_ui.language->setDisabled(true);
|
||||
|
||||
onRenderToSeparateWindowChanged();
|
||||
}
|
||||
|
||||
@@ -193,3 +194,9 @@ void InterfaceSettingsWidget::onRenderToSeparateWindowChanged()
|
||||
{
|
||||
m_ui.hideMainWindow->setEnabled(m_ui.renderToSeparateWindow->isChecked());
|
||||
}
|
||||
|
||||
void InterfaceSettingsWidget::populateLanguages()
|
||||
{
|
||||
for (const std::pair<QString, QString>& it : QtHost::GetAvailableLanguageList())
|
||||
m_ui.language->addItem(it.first, it.second);
|
||||
}
|
||||
|
||||
@@ -31,10 +31,17 @@ public:
|
||||
|
||||
Q_SIGNALS:
|
||||
void themeChanged();
|
||||
void languageChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void onRenderToSeparateWindowChanged();
|
||||
|
||||
private:
|
||||
void populateLanguages();
|
||||
|
||||
Ui::InterfaceSettingsWidget m_ui;
|
||||
|
||||
public:
|
||||
static const char* THEME_NAMES[];
|
||||
static const char* THEME_VALUES[];
|
||||
};
|
||||
|
||||
@@ -30,6 +30,13 @@ MemoryCardConvertDialog::MemoryCardConvertDialog(QWidget* parent, QString select
|
||||
: QDialog(parent)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
// For some reason, setting these in the .ui doesn't work..
|
||||
m_ui.conversionTypeDescription->setFrameStyle(QFrame::Sunken);
|
||||
m_ui.conversionTypeDescription->setFrameShape(QFrame::WinPanel);
|
||||
m_ui.note->setFrameStyle(QFrame::Sunken);
|
||||
m_ui.note->setFrameShape(QFrame::WinPanel);
|
||||
|
||||
m_selectedCard = selectedCard;
|
||||
std::optional<AvailableMcdInfo> srcCardInfo = FileMcd_GetCardInfo(m_selectedCard.toStdString());
|
||||
|
||||
@@ -49,22 +56,22 @@ MemoryCardConvertDialog::MemoryCardConvertDialog(QWidget* parent, QString select
|
||||
switch (m_srcCardInfo.type)
|
||||
{
|
||||
case MemoryCardType::File:
|
||||
SetType(MemoryCardType::Folder, MemoryCardFileType::Unknown, "Uses a folder on your PC filesystem, instead of a file. Infinite capacity, while keeping the same compatibility as an 8 MB Memory Card.");
|
||||
SetType(MemoryCardType::Folder, MemoryCardFileType::Unknown, tr("Uses a folder on your PC filesystem, instead of a file. Infinite capacity, while keeping the same compatibility as an 8 MB Memory Card."));
|
||||
break;
|
||||
case MemoryCardType::Folder:
|
||||
switch (m_ui.conversionTypeSelect->currentData().toInt())
|
||||
{
|
||||
case 8:
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_8MB, "A standard, 8 MB Memory Card. Most compatible, but smallest capacity.");
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_8MB, tr("A standard, 8 MB Memory Card. Most compatible, but smallest capacity."));
|
||||
break;
|
||||
case 16:
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_16MB, "2x larger than a standard Memory Card. May have some compatibility issues.");
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_16MB, tr("2x larger than a standard Memory Card. May have some compatibility issues."));
|
||||
break;
|
||||
case 32:
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_32MB, "4x larger than a standard Memory Card. Likely to have compatibility issues.");
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_32MB, tr("4x larger than a standard Memory Card. Likely to have compatibility issues."));
|
||||
break;
|
||||
case 64:
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_64MB, "8x larger than a standard Memory Card. Likely to have compatibility issues.");
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_64MB, tr("8x larger than a standard Memory Card. Likely to have compatibility issues."));
|
||||
break;
|
||||
default:
|
||||
//: MemoryCardType should be left as-is.
|
||||
@@ -153,7 +160,7 @@ bool MemoryCardConvertDialog::SetupPicklist()
|
||||
{
|
||||
case MemoryCardType::File:
|
||||
m_ui.conversionTypeSelect->addItems({"Folder"});
|
||||
SetType(MemoryCardType::Folder, MemoryCardFileType::Unknown, "Uses a folder on your PC filesystem, instead of a file. Infinite capacity, while keeping the same compatibility as an 8 MB Memory Card.");
|
||||
SetType(MemoryCardType::Folder, MemoryCardFileType::Unknown, tr("Uses a folder on your PC filesystem, instead of a file. Infinite capacity, while keeping the same compatibility as an 8 MB Memory Card."));
|
||||
break;
|
||||
case MemoryCardType::Folder:
|
||||
// Compute which file types should be allowed.
|
||||
@@ -183,7 +190,7 @@ bool MemoryCardConvertDialog::SetupPicklist()
|
||||
|
||||
if (sizeBytes < CardCapacity::_8_MB)
|
||||
{
|
||||
m_ui.conversionTypeSelect->addItem("8 MB File", 8);
|
||||
m_ui.conversionTypeSelect->addItem(tr("8 MB File"), 8);
|
||||
|
||||
if (!typeSet)
|
||||
{
|
||||
@@ -194,7 +201,7 @@ bool MemoryCardConvertDialog::SetupPicklist()
|
||||
|
||||
if (sizeBytes < CardCapacity::_16_MB)
|
||||
{
|
||||
m_ui.conversionTypeSelect->addItem("16 MB File", 16);
|
||||
m_ui.conversionTypeSelect->addItem(tr("16 MB File"), 16);
|
||||
|
||||
if (!typeSet)
|
||||
{
|
||||
@@ -205,7 +212,7 @@ bool MemoryCardConvertDialog::SetupPicklist()
|
||||
|
||||
if (sizeBytes < CardCapacity::_32_MB)
|
||||
{
|
||||
m_ui.conversionTypeSelect->addItem("32 MB File", 32);
|
||||
m_ui.conversionTypeSelect->addItem(tr("32 MB File"), 32);
|
||||
|
||||
if (!typeSet)
|
||||
{
|
||||
@@ -216,7 +223,7 @@ bool MemoryCardConvertDialog::SetupPicklist()
|
||||
|
||||
if (sizeBytes < CardCapacity::_64_MB)
|
||||
{
|
||||
m_ui.conversionTypeSelect->addItem("64 MB File", 64);
|
||||
m_ui.conversionTypeSelect->addItem(tr("64 MB File"), 64);
|
||||
|
||||
if (!typeSet)
|
||||
{
|
||||
@@ -284,30 +291,30 @@ void MemoryCardConvertDialog::SetType(MemoryCardType type, MemoryCardFileType fi
|
||||
{
|
||||
m_type = type;
|
||||
m_fileType = fileType;
|
||||
m_ui.conversionTypeDescription->setPlainText(description);
|
||||
m_ui.conversionTypeDescription->setText(QStringLiteral("<center>%1</center>").arg(description));
|
||||
}
|
||||
|
||||
void MemoryCardConvertDialog::SetType_8()
|
||||
{
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_8MB, "A standard, 8 MB Memory Card. Most compatible, but smallest capacity.");
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_8MB, tr("A standard, 8 MB Memory Card. Most compatible, but smallest capacity."));
|
||||
}
|
||||
|
||||
void MemoryCardConvertDialog::SetType_16()
|
||||
{
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_16MB, "2x larger as a standard Memory Card. May have some compatibility issues.");
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_16MB, tr("2x larger as a standard Memory Card. May have some compatibility issues."));
|
||||
}
|
||||
|
||||
void MemoryCardConvertDialog::SetType_32()
|
||||
{
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_32MB, "4x larger than a standard Memory Card. Likely to have compatibility issues.");
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_32MB, tr("4x larger than a standard Memory Card. Likely to have compatibility issues."));
|
||||
}
|
||||
|
||||
void MemoryCardConvertDialog::SetType_64()
|
||||
{
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_64MB, "8x larger than a standard Memory Card. Likely to have compatibility issues.");
|
||||
SetType(MemoryCardType::File, MemoryCardFileType::PS2_64MB, tr("8x larger than a standard Memory Card. Likely to have compatibility issues."));
|
||||
}
|
||||
|
||||
void MemoryCardConvertDialog::SetType_Folder()
|
||||
{
|
||||
SetType(MemoryCardType::Folder, MemoryCardFileType::Unknown, "Uses a folder on your PC filesystem, instead of a file. Infinite capacity, while keeping the same compatibility as an 8 MB Memory Card.");
|
||||
SetType(MemoryCardType::Folder, MemoryCardFileType::Unknown, tr("Uses a folder on your PC filesystem, instead of a file. Infinite capacity, while keeping the same compatibility as an 8 MB Memory Card."));
|
||||
}
|
||||
|
||||
@@ -10,27 +10,9 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>440</width>
|
||||
<height>320</height>
|
||||
<height>282</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>440</width>
|
||||
<height>320</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>440</width>
|
||||
<height>320</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Convert Memory Card</string>
|
||||
</property>
|
||||
@@ -40,141 +22,117 @@
|
||||
<property name="modal">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="conversionTypeGroup">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>421</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Conversion Type</string>
|
||||
</property>
|
||||
<widget class="QComboBox" name="conversionTypeSelect">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>30</y>
|
||||
<width>401</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>8 MB File</string>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="conversionTypeGroup">
|
||||
<property name="title">
|
||||
<string>Conversion Type</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>16 MB File</string>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="conversionTypeSelect">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>8 MB File</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>16 MB File</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>32 MB File</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>64 MB File</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Folder</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="conversionTypeDescription">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>32 MB File</string>
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="note">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>64 MB File</string>
|
||||
<string><center><strong>Note:</strong> Converting a Memory Card creates a <strong>COPY</strong> of your existing Memory Card. It does <strong">NOT delete, modify, or replace</strong> your existing Memory Card.</center></string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Folder</string>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QTextBrowser" name="note">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>150</y>
|
||||
<width>421</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
hr { height: 1px; border-width: 0; }
|
||||
</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note: Converting a Memory Card creates a COPY of your existing Memory Card. It does NOT delete, modify, or replace your existing Memory Card.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTextBrowser" name="conversionTypeDescription">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>80</y>
|
||||
<width>421</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
hr { height: 1px; border-width: 0; }
|
||||
</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>270</x>
|
||||
<y>290</y>
|
||||
<width>156</width>
|
||||
<height>24</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="progressGroup">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>220</y>
|
||||
<width>421</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Progress</string>
|
||||
</property>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>30</y>
|
||||
<width>401</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="progressGroup">
|
||||
<property name="title">
|
||||
<string>Progress</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
<height>112</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,1">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
|
||||
@@ -0,0 +1,506 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "PAD/Host/PAD.h"
|
||||
#include "QtHost.h"
|
||||
#include "QtUtils.h"
|
||||
#include "SettingWidgetBinder.h"
|
||||
#include "Settings/ControllerSettingWidgetBinder.h"
|
||||
#include "Settings/InterfaceSettingsWidget.h"
|
||||
#include "SetupWizardDialog.h"
|
||||
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
SetupWizardDialog::SetupWizardDialog()
|
||||
{
|
||||
setupUi();
|
||||
updatePageLabels(-1);
|
||||
updatePageButtons();
|
||||
}
|
||||
|
||||
SetupWizardDialog::~SetupWizardDialog()
|
||||
{
|
||||
if (m_bios_refresh_thread)
|
||||
{
|
||||
m_bios_refresh_thread->wait();
|
||||
delete m_bios_refresh_thread;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupWizardDialog::resizeEvent(QResizeEvent* event)
|
||||
{
|
||||
QDialog::resizeEvent(event);
|
||||
resizeDirectoryListColumns();
|
||||
}
|
||||
|
||||
bool SetupWizardDialog::canShowNextPage()
|
||||
{
|
||||
const int current_page = m_ui.pages->currentIndex();
|
||||
|
||||
switch (current_page)
|
||||
{
|
||||
case Page_BIOS:
|
||||
{
|
||||
if (!m_ui.biosList->currentItem())
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Warning"),
|
||||
tr("A BIOS image has not been selected. PCSX2 <strong>will not</strong> be able to run games "
|
||||
"without a BIOS image.<br><br>Are you sure you wish to continue without selecting a BIOS "
|
||||
"image?")) != QMessageBox::Yes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Page_GameList:
|
||||
{
|
||||
if (m_ui.searchDirectoryList->rowCount() == 0)
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Warning"),
|
||||
tr("No game directories have been selected. You will have to manually open any game dumps you "
|
||||
"want to play, PCSX2's list will be empty.\n\nAre you sure you want to continue?")) !=
|
||||
QMessageBox::Yes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetupWizardDialog::previousPage()
|
||||
{
|
||||
const int current_page = m_ui.pages->currentIndex();
|
||||
if (current_page == 0)
|
||||
return;
|
||||
|
||||
m_ui.pages->setCurrentIndex(current_page - 1);
|
||||
updatePageLabels(current_page);
|
||||
updatePageButtons();
|
||||
}
|
||||
|
||||
void SetupWizardDialog::nextPage()
|
||||
{
|
||||
const int current_page = m_ui.pages->currentIndex();
|
||||
if (current_page == Page_Complete)
|
||||
{
|
||||
accept();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!canShowNextPage())
|
||||
return;
|
||||
|
||||
const int new_page = current_page + 1;
|
||||
m_ui.pages->setCurrentIndex(new_page);
|
||||
updatePageLabels(current_page);
|
||||
updatePageButtons();
|
||||
pageChangedTo(new_page);
|
||||
}
|
||||
|
||||
void SetupWizardDialog::pageChangedTo(int page)
|
||||
{
|
||||
switch (page)
|
||||
{
|
||||
case Page_GameList:
|
||||
resizeDirectoryListColumns();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupWizardDialog::updatePageLabels(int prev_page)
|
||||
{
|
||||
if (prev_page >= 0)
|
||||
{
|
||||
QFont prev_font = m_page_labels[prev_page]->font();
|
||||
prev_font.setBold(false);
|
||||
m_page_labels[prev_page]->setFont(prev_font);
|
||||
}
|
||||
|
||||
const int page = m_ui.pages->currentIndex();
|
||||
QFont font = m_page_labels[page]->font();
|
||||
font.setBold(true);
|
||||
m_page_labels[page]->setFont(font);
|
||||
}
|
||||
|
||||
void SetupWizardDialog::updatePageButtons()
|
||||
{
|
||||
const int page = m_ui.pages->currentIndex();
|
||||
m_ui.next->setText((page == Page_Complete) ? "&Finish" : "&Next");
|
||||
m_ui.back->setEnabled(page > 0);
|
||||
}
|
||||
|
||||
void SetupWizardDialog::confirmCancel()
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Cancel Setup"),
|
||||
tr("Are you sure you want to cancel PCSX2 setup?\n\nAny changes have been saved, and the wizard will run "
|
||||
"again next time you start PCSX2.")) != QMessageBox::Yes)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
reject();
|
||||
}
|
||||
|
||||
void SetupWizardDialog::setupUi()
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
m_ui.logo->setPixmap(QPixmap(QStringLiteral("%1/icons/AppIconLarge.png").arg(QtHost::GetResourcesBasePath())));
|
||||
|
||||
m_ui.pages->setCurrentIndex(0);
|
||||
|
||||
m_page_labels[Page_Language] = m_ui.labelLanguage;
|
||||
m_page_labels[Page_BIOS] = m_ui.labelBIOS;
|
||||
m_page_labels[Page_GameList] = m_ui.labelGameList;
|
||||
m_page_labels[Page_Controller] = m_ui.labelController;
|
||||
m_page_labels[Page_Complete] = m_ui.labelComplete;
|
||||
|
||||
connect(m_ui.back, &QPushButton::clicked, this, &SetupWizardDialog::previousPage);
|
||||
connect(m_ui.next, &QPushButton::clicked, this, &SetupWizardDialog::nextPage);
|
||||
connect(m_ui.cancel, &QPushButton::clicked, this, &SetupWizardDialog::confirmCancel);
|
||||
|
||||
setupLanguagePage();
|
||||
setupBIOSPage();
|
||||
setupGameListPage();
|
||||
setupControllerPage();
|
||||
}
|
||||
|
||||
void SetupWizardDialog::setupLanguagePage()
|
||||
{
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(nullptr, m_ui.theme, "UI", "Theme",
|
||||
InterfaceSettingsWidget::THEME_NAMES, InterfaceSettingsWidget::THEME_VALUES, QtHost::GetDefaultThemeName(), "InterfaceSettingsWidget");
|
||||
connect(m_ui.theme, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SetupWizardDialog::themeChanged);
|
||||
|
||||
for (const std::pair<QString, QString>& it : QtHost::GetAvailableLanguageList())
|
||||
m_ui.language->addItem(it.first, it.second);
|
||||
SettingWidgetBinder::BindWidgetToStringSetting(
|
||||
nullptr, m_ui.language, "UI", "Language", QtHost::GetDefaultLanguage());
|
||||
connect(
|
||||
m_ui.language, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &SetupWizardDialog::languageChanged);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(
|
||||
nullptr, m_ui.autoUpdateEnabled, "AutoUpdater", "CheckAtStartup", true);
|
||||
}
|
||||
|
||||
void SetupWizardDialog::themeChanged()
|
||||
{
|
||||
// Main window gets recreated at the end here anyway, so it's fine to just yolo it.
|
||||
QtHost::UpdateApplicationTheme();
|
||||
}
|
||||
|
||||
void SetupWizardDialog::languageChanged()
|
||||
{
|
||||
// Skip the recreation, since we don't have many dynamic UI elements.
|
||||
QtHost::InstallTranslator();
|
||||
m_ui.retranslateUi(this);
|
||||
}
|
||||
|
||||
void SetupWizardDialog::setupBIOSPage()
|
||||
{
|
||||
SettingWidgetBinder::BindWidgetToFolderSetting(nullptr, m_ui.biosSearchDirectory, m_ui.browseBiosSearchDirectory,
|
||||
m_ui.openBiosSearchDirectory, m_ui.resetBiosSearchDirectory, "Folders", "Bios",
|
||||
Path::Combine(EmuFolders::DataRoot, "bios"));
|
||||
|
||||
refreshBiosList();
|
||||
|
||||
connect(m_ui.biosSearchDirectory, &QLineEdit::textChanged, this, &SetupWizardDialog::refreshBiosList);
|
||||
connect(m_ui.refreshBiosList, &QPushButton::clicked, this, &SetupWizardDialog::refreshBiosList);
|
||||
connect(m_ui.biosList, &QTreeWidget::currentItemChanged, this, &SetupWizardDialog::biosListItemChanged);
|
||||
}
|
||||
|
||||
void SetupWizardDialog::refreshBiosList()
|
||||
{
|
||||
if (m_bios_refresh_thread)
|
||||
{
|
||||
m_bios_refresh_thread->wait();
|
||||
delete m_bios_refresh_thread;
|
||||
}
|
||||
|
||||
QSignalBlocker blocker(m_ui.biosList);
|
||||
m_ui.biosList->clear();
|
||||
m_ui.biosList->setEnabled(false);
|
||||
|
||||
m_bios_refresh_thread = new BIOSSettingsWidget::RefreshThread(this, m_ui.biosSearchDirectory->text());
|
||||
m_bios_refresh_thread->start();
|
||||
}
|
||||
|
||||
void SetupWizardDialog::biosListItemChanged(const QTreeWidgetItem* current, const QTreeWidgetItem* previous)
|
||||
{
|
||||
Host::SetBaseStringSettingValue("Filenames", "BIOS", current->text(0).toUtf8().constData());
|
||||
Host::CommitBaseSettingChanges();
|
||||
g_emu_thread->applySettings();
|
||||
}
|
||||
|
||||
void SetupWizardDialog::listRefreshed(const QVector<BIOSInfo>& items)
|
||||
{
|
||||
QSignalBlocker sb(m_ui.biosList);
|
||||
BIOSSettingsWidget::populateList(m_ui.biosList, items);
|
||||
m_ui.biosList->setEnabled(true);
|
||||
}
|
||||
|
||||
void SetupWizardDialog::setupGameListPage()
|
||||
{
|
||||
m_ui.searchDirectoryList->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_ui.searchDirectoryList->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_ui.searchDirectoryList->setAlternatingRowColors(true);
|
||||
m_ui.searchDirectoryList->setShowGrid(false);
|
||||
m_ui.searchDirectoryList->horizontalHeader()->setHighlightSections(false);
|
||||
m_ui.searchDirectoryList->verticalHeader()->hide();
|
||||
m_ui.searchDirectoryList->setCurrentIndex({});
|
||||
m_ui.searchDirectoryList->setContextMenuPolicy(Qt::ContextMenuPolicy::CustomContextMenu);
|
||||
|
||||
connect(m_ui.searchDirectoryList, &QTableWidget::customContextMenuRequested, this,
|
||||
&SetupWizardDialog::onDirectoryListContextMenuRequested);
|
||||
connect(m_ui.addSearchDirectoryButton, &QPushButton::clicked, this,
|
||||
&SetupWizardDialog::onAddSearchDirectoryButtonClicked);
|
||||
connect(m_ui.removeSearchDirectoryButton, &QPushButton::clicked, this,
|
||||
&SetupWizardDialog::onRemoveSearchDirectoryButtonClicked);
|
||||
|
||||
refreshDirectoryList();
|
||||
}
|
||||
|
||||
void SetupWizardDialog::onDirectoryListContextMenuRequested(const QPoint& point)
|
||||
{
|
||||
QModelIndexList selection = m_ui.searchDirectoryList->selectionModel()->selectedIndexes();
|
||||
if (selection.size() < 1)
|
||||
return;
|
||||
|
||||
const int row = selection[0].row();
|
||||
|
||||
QMenu menu;
|
||||
menu.addAction(tr("Remove"), [this]() { onRemoveSearchDirectoryButtonClicked(); });
|
||||
menu.addSeparator();
|
||||
menu.addAction(tr("Open Directory..."),
|
||||
[this, row]() { QtUtils::OpenURL(this, QUrl::fromLocalFile(m_ui.searchDirectoryList->item(row, 0)->text())); });
|
||||
menu.exec(m_ui.searchDirectoryList->mapToGlobal(point));
|
||||
}
|
||||
|
||||
void SetupWizardDialog::onAddSearchDirectoryButtonClicked()
|
||||
{
|
||||
QString dir = QDir::toNativeSeparators(QFileDialog::getExistingDirectory(this, tr("Select Search Directory")));
|
||||
|
||||
if (dir.isEmpty())
|
||||
return;
|
||||
|
||||
QMessageBox::StandardButton selection = QMessageBox::question(this, tr("Scan Recursively?"),
|
||||
tr("Would you like to scan the directory \"%1\" recursively?\n\nScanning recursively takes "
|
||||
"more time, but will identify files in subdirectories.")
|
||||
.arg(dir),
|
||||
QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
|
||||
if (selection == QMessageBox::Cancel)
|
||||
return;
|
||||
|
||||
const bool recursive = (selection == QMessageBox::Yes);
|
||||
const std::string spath = dir.toStdString();
|
||||
Host::RemoveBaseValueFromStringList("GameList", recursive ? "Paths" : "RecursivePaths", spath.c_str());
|
||||
Host::AddBaseValueToStringList("GameList", recursive ? "RecursivePaths" : "Paths", spath.c_str());
|
||||
Host::CommitBaseSettingChanges();
|
||||
refreshDirectoryList();
|
||||
}
|
||||
|
||||
void SetupWizardDialog::onRemoveSearchDirectoryButtonClicked()
|
||||
{
|
||||
const int row = m_ui.searchDirectoryList->currentRow();
|
||||
std::unique_ptr<QTableWidgetItem> item((row >= 0) ? m_ui.searchDirectoryList->takeItem(row, 0) : nullptr);
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
const std::string spath = item->text().toStdString();
|
||||
if (!Host::RemoveBaseValueFromStringList("GameList", "Paths", spath.c_str()) &&
|
||||
!Host::RemoveBaseValueFromStringList("GameList", "RecursivePaths", spath.c_str()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Host::CommitBaseSettingChanges();
|
||||
refreshDirectoryList();
|
||||
}
|
||||
|
||||
void SetupWizardDialog::addPathToTable(const std::string& path, bool recursive)
|
||||
{
|
||||
const int row = m_ui.searchDirectoryList->rowCount();
|
||||
m_ui.searchDirectoryList->insertRow(row);
|
||||
|
||||
QTableWidgetItem* item = new QTableWidgetItem();
|
||||
item->setText(QString::fromStdString(path));
|
||||
item->setFlags(item->flags() & ~(Qt::ItemIsEditable));
|
||||
m_ui.searchDirectoryList->setItem(row, 0, item);
|
||||
|
||||
QCheckBox* cb = new QCheckBox(m_ui.searchDirectoryList);
|
||||
m_ui.searchDirectoryList->setCellWidget(row, 1, cb);
|
||||
cb->setChecked(recursive);
|
||||
|
||||
connect(cb, &QCheckBox::stateChanged, [item](int state) {
|
||||
const std::string path(item->text().toStdString());
|
||||
if (state == Qt::Checked)
|
||||
{
|
||||
Host::RemoveBaseValueFromStringList("GameList", "Paths", path.c_str());
|
||||
Host::AddBaseValueToStringList("GameList", "RecursivePaths", path.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Host::RemoveBaseValueFromStringList("GameList", "RecursivePaths", path.c_str());
|
||||
Host::AddBaseValueToStringList("GameList", "Paths", path.c_str());
|
||||
}
|
||||
Host::CommitBaseSettingChanges();
|
||||
});
|
||||
}
|
||||
|
||||
void SetupWizardDialog::refreshDirectoryList()
|
||||
{
|
||||
QSignalBlocker sb(m_ui.searchDirectoryList);
|
||||
while (m_ui.searchDirectoryList->rowCount() > 0)
|
||||
m_ui.searchDirectoryList->removeRow(0);
|
||||
|
||||
std::vector<std::string> path_list = Host::GetBaseStringListSetting("GameList", "Paths");
|
||||
for (const std::string& entry : path_list)
|
||||
addPathToTable(entry, false);
|
||||
|
||||
path_list = Host::GetBaseStringListSetting("GameList", "RecursivePaths");
|
||||
for (const std::string& entry : path_list)
|
||||
addPathToTable(entry, true);
|
||||
|
||||
m_ui.searchDirectoryList->sortByColumn(0, Qt::AscendingOrder);
|
||||
}
|
||||
|
||||
void SetupWizardDialog::resizeDirectoryListColumns()
|
||||
{
|
||||
QtUtils::ResizeColumnsForTableView(m_ui.searchDirectoryList, {-1, 100});
|
||||
}
|
||||
|
||||
void SetupWizardDialog::setupControllerPage()
|
||||
{
|
||||
static constexpr u32 NUM_PADS = 2;
|
||||
|
||||
struct PadWidgets
|
||||
{
|
||||
QComboBox* type_combo;
|
||||
QLabel* mapping_result;
|
||||
QToolButton* mapping_button;
|
||||
};
|
||||
const PadWidgets pad_widgets[NUM_PADS] = {
|
||||
{m_ui.controller1Type, m_ui.controller1Mapping, m_ui.controller1AutomaticMapping},
|
||||
{m_ui.controller2Type, m_ui.controller2Mapping, m_ui.controller2AutomaticMapping},
|
||||
};
|
||||
|
||||
for (u32 port = 0; port < NUM_PADS; port++)
|
||||
{
|
||||
const std::string section = fmt::format("Pad{}", port + 1);
|
||||
const PadWidgets& w = pad_widgets[port];
|
||||
|
||||
for (const auto& [name, display_name] : PAD::GetControllerTypeNames())
|
||||
w.type_combo->addItem(qApp->translate("Pad", display_name), QString::fromStdString(name));
|
||||
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(
|
||||
nullptr, w.type_combo, section, "Type", PAD::GetDefaultPadType(port));
|
||||
|
||||
w.mapping_result->setText((port == 0) ? tr("Default (Keyboard)") : tr("Default (None)"));
|
||||
|
||||
connect(w.mapping_button, &QAbstractButton::clicked, this,
|
||||
[this, port, label = w.mapping_result]() { openAutomaticMappingMenu(port, label); });
|
||||
}
|
||||
|
||||
// Trigger enumeration to populate the device list.
|
||||
connect(g_emu_thread, &EmuThread::onInputDevicesEnumerated, this, &SetupWizardDialog::onInputDevicesEnumerated);
|
||||
connect(g_emu_thread, &EmuThread::onInputDeviceConnected, this, &SetupWizardDialog::onInputDeviceConnected);
|
||||
connect(g_emu_thread, &EmuThread::onInputDeviceDisconnected, this, &SetupWizardDialog::onInputDeviceDisconnected);
|
||||
g_emu_thread->enumerateInputDevices();
|
||||
}
|
||||
|
||||
void SetupWizardDialog::openAutomaticMappingMenu(u32 port, QLabel* update_label)
|
||||
{
|
||||
QMenu menu(this);
|
||||
bool added = false;
|
||||
|
||||
for (const QPair<QString, QString>& dev : m_device_list)
|
||||
{
|
||||
// we set it as data, because the device list could get invalidated while the menu is up
|
||||
QAction* action = menu.addAction(QStringLiteral("%1 (%2)").arg(dev.first).arg(dev.second));
|
||||
action->setData(dev.first);
|
||||
connect(action, &QAction::triggered, this, [this, port, update_label, action]() {
|
||||
doDeviceAutomaticBinding(port, update_label, action->data().toString());
|
||||
});
|
||||
added = true;
|
||||
}
|
||||
|
||||
if (!added)
|
||||
{
|
||||
QAction* action = menu.addAction(tr("No devices available"));
|
||||
action->setEnabled(false);
|
||||
}
|
||||
|
||||
menu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void SetupWizardDialog::doDeviceAutomaticBinding(u32 port, QLabel* update_label, const QString& device)
|
||||
{
|
||||
std::vector<std::pair<GenericInputBinding, std::string>> mapping =
|
||||
InputManager::GetGenericBindingMapping(device.toStdString());
|
||||
if (mapping.empty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Automatic Binding"),
|
||||
tr("No generic bindings were generated for device '%1'. The controller/source may not support automatic "
|
||||
"mapping.")
|
||||
.arg(device));
|
||||
return;
|
||||
}
|
||||
|
||||
bool result;
|
||||
{
|
||||
auto lock = Host::GetSettingsLock();
|
||||
result = PAD::MapController(*Host::Internal::GetBaseSettingsLayer(), port, mapping);
|
||||
}
|
||||
if (!result)
|
||||
return;
|
||||
|
||||
Host::CommitBaseSettingChanges();
|
||||
|
||||
update_label->setText(device);
|
||||
}
|
||||
|
||||
void SetupWizardDialog::onInputDevicesEnumerated(const QList<QPair<QString, QString>>& devices)
|
||||
{
|
||||
m_device_list = devices;
|
||||
}
|
||||
|
||||
void SetupWizardDialog::onInputDeviceConnected(const QString& identifier, const QString& device_name)
|
||||
{
|
||||
m_device_list.emplace_back(identifier, device_name);
|
||||
}
|
||||
|
||||
void SetupWizardDialog::onInputDeviceDisconnected(const QString& identifier)
|
||||
{
|
||||
for (auto iter = m_device_list.begin(); iter != m_device_list.end(); ++iter)
|
||||
{
|
||||
if (iter->first == identifier)
|
||||
{
|
||||
m_device_list.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Settings/BIOSSettingsWidget.h"
|
||||
|
||||
#include "ui_SetupWizardDialog.h"
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtWidgets/QDialog>
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
class SetupWizardDialog final : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SetupWizardDialog();
|
||||
~SetupWizardDialog();
|
||||
|
||||
private Q_SLOTS:
|
||||
bool canShowNextPage();
|
||||
void previousPage();
|
||||
void nextPage();
|
||||
void confirmCancel();
|
||||
|
||||
void themeChanged();
|
||||
void languageChanged();
|
||||
|
||||
void refreshBiosList();
|
||||
void biosListItemChanged(const QTreeWidgetItem* current, const QTreeWidgetItem* previous);
|
||||
void listRefreshed(const QVector<BIOSInfo>& items);
|
||||
|
||||
void onDirectoryListContextMenuRequested(const QPoint& point);
|
||||
void onAddSearchDirectoryButtonClicked();
|
||||
void onRemoveSearchDirectoryButtonClicked();
|
||||
void refreshDirectoryList();
|
||||
void resizeDirectoryListColumns();
|
||||
|
||||
void onInputDevicesEnumerated(const QList<QPair<QString, QString>>& devices);
|
||||
void onInputDeviceConnected(const QString& identifier, const QString& device_name);
|
||||
void onInputDeviceDisconnected(const QString& identifier);
|
||||
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
|
||||
private:
|
||||
enum Page : u32
|
||||
{
|
||||
Page_Language,
|
||||
Page_BIOS,
|
||||
Page_GameList,
|
||||
Page_Controller,
|
||||
Page_Complete,
|
||||
Page_Count,
|
||||
};
|
||||
|
||||
void setupUi();
|
||||
void setupLanguagePage();
|
||||
void setupBIOSPage();
|
||||
void setupGameListPage();
|
||||
void setupControllerPage();
|
||||
|
||||
void pageChangedTo(int page);
|
||||
void updatePageLabels(int prev_page);
|
||||
void updatePageButtons();
|
||||
|
||||
void addPathToTable(const std::string& path, bool recursive);
|
||||
|
||||
void openAutomaticMappingMenu(u32 port, QLabel* update_label);
|
||||
void doDeviceAutomaticBinding(u32 port, QLabel* update_label, const QString& device);
|
||||
|
||||
Ui::SetupWizardDialog m_ui;
|
||||
|
||||
std::array<QLabel*, Page_Count> m_page_labels;
|
||||
|
||||
BIOSSettingsWidget::RefreshThread* m_bios_refresh_thread = nullptr;
|
||||
|
||||
QList<QPair<QString, QString>> m_device_list;
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user