mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-31 11:18:41 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -2,8 +2,8 @@ name: 📝 Validate GameDB
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
branches-ignore:
|
||||
- "l10n_master"
|
||||
paths:
|
||||
- '**/GameIndex.yaml'
|
||||
pull_request:
|
||||
|
||||
@@ -83,8 +83,20 @@ jobs:
|
||||
arch: x86_64
|
||||
build-bundle: true
|
||||
verbose: true
|
||||
mirror-screenshots-url: https://dl.flathub.org/repo/screenshots
|
||||
branch: beta
|
||||
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 .github/workflows/scripts/linux/flatpak/screenshots
|
||||
|
||||
- name: Push to Flathub
|
||||
if: inputs.publish == true
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@v6.1
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: beta
|
||||
token: ${{ secrets.FLATHUB_BETA_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,6 +21,7 @@ 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"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -287,7 +287,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"
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
@@ -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.
|
||||
@@ -36,3 +45,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
|
||||
|
||||
@@ -67,7 +67,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,6 +13,14 @@
|
||||
</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>
|
||||
<releases>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2025,6 +2025,13 @@ SCED-51262:
|
||||
SCED-51279:
|
||||
name: "Official PlayStation 2 Magazine Demo 25"
|
||||
region: "PAL-M5"
|
||||
SCED-51305:
|
||||
name: "WRC II Extreme [Press Kit]"
|
||||
region: "PAL-E"
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes SPS.
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 1 # Fixes texture misalignment.
|
||||
SCED-51319:
|
||||
name: "Official PlayStation 2 Magazine Demo 27" # German
|
||||
region: "PAL-E-G"
|
||||
@@ -2160,6 +2167,13 @@ SCED-51573:
|
||||
SCED-51575:
|
||||
name: "Official PlayStation 2 Magazine Demo 40" # German
|
||||
region: "PAL-E-G"
|
||||
SCED-51632:
|
||||
name: "WRC II Extreme [Special Demo]"
|
||||
region: "PAL-E"
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes SPS.
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 1 # Fixes texture misalignment.
|
||||
SCED-51657:
|
||||
name: "Official PlayStation Magazine Demo 33"
|
||||
region: "PAL-Unk"
|
||||
@@ -2275,9 +2289,17 @@ SCED-52092:
|
||||
SCED-52120:
|
||||
name: "Official PlayStation 2 Magazine Demo 55" # German
|
||||
region: "PAL-E-G"
|
||||
SCED-52137:
|
||||
name: "WRC 3 [Demo]"
|
||||
region: "PAL-E"
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes SPS.
|
||||
gsHWFixes:
|
||||
roundSprite: 2 # Correct misaligned font, better aligns car shadow.
|
||||
autoFlush: 2 # Fixes sun luminosity.
|
||||
SCED-52141:
|
||||
name: "WRC 3 [Demo]"
|
||||
region: "NTSC-J"
|
||||
region: "PAL-E"
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes SPS.
|
||||
@@ -4984,6 +5006,8 @@ SCES-55571:
|
||||
SCES-55573:
|
||||
name: "MotorStorm - Arctic Edge"
|
||||
region: "PAL-M14"
|
||||
clampModes:
|
||||
vu1ClampMode: 3 # Fixes bad polys in menu.
|
||||
SCES-55591:
|
||||
name: "Street Cricket Champions"
|
||||
region: "PAL-IN"
|
||||
@@ -9330,9 +9354,11 @@ SCUS-97653:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SCUS-97654:
|
||||
name: "MotorStorm Arctic Edge"
|
||||
name: "MotorStorm - Arctic Edge"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
clampModes:
|
||||
vu1ClampMode: 3 # Fixes bad polys in menu.
|
||||
SCUS-97657:
|
||||
name: "MLB 11 - The Show"
|
||||
region: "NTSC-U"
|
||||
@@ -9527,6 +9553,7 @@ SLAJ-25072:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
halfPixelOffset: 2 # Fix effects upscaling.
|
||||
autoFlush: 1 # Fixes broken post processing.
|
||||
SLAJ-25073:
|
||||
name: "Resident Evil 4"
|
||||
region: "NTSC-J"
|
||||
@@ -9981,6 +10008,7 @@ SLED-53845:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
halfPixelOffset: 2 # Fix effects upscaling.
|
||||
autoFlush: 1 # Fixes broken post processing.
|
||||
SLED-53937:
|
||||
name: "Black [Demo]"
|
||||
region: "PAL-M5"
|
||||
@@ -17943,11 +17971,17 @@ SLES-53393:
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes garbage textures flashing on the character model.
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes missing post processing.
|
||||
halfPixelOffset: 1 # Aligns post processing.
|
||||
SLES-53396:
|
||||
name: "Spartan - Total Warrior"
|
||||
region: "PAL-M3"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes garbage textures flashing on the character model.
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes missing post processing.
|
||||
halfPixelOffset: 1 # Aligns post processing.
|
||||
SLES-53398:
|
||||
name: "Zombie Zone"
|
||||
region: "PAL-E"
|
||||
@@ -18135,6 +18169,7 @@ SLES-53462:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
halfPixelOffset: 2 # Fix effects upscaling.
|
||||
autoFlush: 1 # Fixes broken post processing.
|
||||
SLES-53463:
|
||||
name: "NHL '06"
|
||||
region: "PAL-E"
|
||||
@@ -19191,6 +19226,7 @@ SLES-53759:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
halfPixelOffset: 2 # Fix effects upscaling.
|
||||
autoFlush: 1 # Fixes broken post processing.
|
||||
SLES-53760:
|
||||
name: "Rugby Challenge 2006"
|
||||
region: "PAL-M5"
|
||||
@@ -19280,6 +19316,7 @@ SLES-53799:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
halfPixelOffset: 2 # Fix effects upscaling.
|
||||
autoFlush: 1 # Fixes broken post processing.
|
||||
SLES-53800:
|
||||
name: "Rampage - Total Destruction"
|
||||
region: "PAL-M5"
|
||||
@@ -23757,8 +23794,10 @@ SLES-55572:
|
||||
gameFixes:
|
||||
- EETimingHack # Broken textures.
|
||||
SLES-55573:
|
||||
name: "MotorStorm Arctic Edge"
|
||||
name: "MotorStorm - Arctic Edge"
|
||||
region: "PAL-M14"
|
||||
clampModes:
|
||||
vu1ClampMode: 3 # Fixes bad polys in menu.
|
||||
SLES-55574:
|
||||
name: "Lord of the Rings, The - Aragorn's Quest"
|
||||
region: "PAL-M6"
|
||||
@@ -24381,6 +24420,8 @@ SLKA-15032:
|
||||
SLKA-15033:
|
||||
name: "Princess Maker 2"
|
||||
region: "NTSC-K"
|
||||
gsHWFixes:
|
||||
partialTargetInvalidation: 1 # Fixes full screen C32->C16 frame invalidation.
|
||||
SLKA-15043:
|
||||
name: "Super Puzzle Bobble Collection Vol 1"
|
||||
region: "NTSC-K"
|
||||
@@ -25291,6 +25332,7 @@ SLKA-25303:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
halfPixelOffset: 2 # Fix effects upscaling.
|
||||
autoFlush: 1 # Fixes broken post processing.
|
||||
SLKA-25304:
|
||||
name: "Burnout Revenge"
|
||||
region: "NTSC-K"
|
||||
@@ -26219,6 +26261,9 @@ SLPM-60109:
|
||||
roundSprite: 1 # Fixes ui and hud alignment.
|
||||
gpuPaletteConversion: 2 # Lots of CLUTs in large textures.
|
||||
cpuCLUTRender: 1 # Fixes car textures.
|
||||
SLPM-60114:
|
||||
name: "Magical Sports - 2000 Koushien [Trial]"
|
||||
region: "NTSC-J"
|
||||
SLPM-60122:
|
||||
name: "Ring of Red [Taikenban trial]"
|
||||
region: "NTSC-J"
|
||||
@@ -28593,6 +28638,8 @@ SLPM-62700:
|
||||
SLPM-62701:
|
||||
name: "Princess Maker 2 [Best Hit Selection]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
partialTargetInvalidation: 1 # Fixes full screen C32->C16 frame invalidation.
|
||||
SLPM-62702:
|
||||
name: "Momotaro Densetsu 15"
|
||||
region: "NTSC-J"
|
||||
@@ -29923,6 +29970,8 @@ SLPM-65284:
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes SPS.
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 1 # Fixes texture misalignment.
|
||||
SLPM-65285:
|
||||
name: "Love Hina Gorgeous [First Limited Edition]"
|
||||
region: "NTSC-J"
|
||||
@@ -30864,6 +30913,8 @@ SLPM-65573:
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- XGKickHack # Fixes SPS.
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 1 # Fixes texture misalignment.
|
||||
SLPM-65574:
|
||||
name: "Silent Hill 4 - The Room"
|
||||
region: "NTSC-J"
|
||||
@@ -31997,7 +32048,7 @@ SLPM-65889:
|
||||
name: "Kazoku Keikaku - Kokoro no Kizuna"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
beforeDraw: "OI_PointListPalette"
|
||||
gpuTargetCLUT: 1 # Fixes broken colors.
|
||||
SLPM-65890:
|
||||
name: "Shin Sangoku Musou 4"
|
||||
region: "NTSC-J"
|
||||
@@ -32932,8 +32983,10 @@ SLPM-66136:
|
||||
name: "SuperLite 2000 Vol. 34 - Akai Ito"
|
||||
region: "NTSC-J"
|
||||
SLPM-66137:
|
||||
name: "Clover Heart's Looking for Happiness [The Best]"
|
||||
name: "Clover Heart's - Looking for Happiness [The Best]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
minimumBlendingLevel: 4 # Fixes transparancy.
|
||||
SLPM-66138:
|
||||
name: "Desire [Best Version]"
|
||||
region: "NTSC-J"
|
||||
@@ -33093,6 +33146,7 @@ SLPM-66177:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
halfPixelOffset: 2 # Fix effects upscaling.
|
||||
autoFlush: 1 # Fixes broken post processing.
|
||||
SLPM-66178:
|
||||
name: "pop'n music 7 [Konami The Best]"
|
||||
region: "NTSC-J"
|
||||
@@ -33624,7 +33678,8 @@ SLPM-66302:
|
||||
name: "Clannad"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
cpuCLUTRender: 1 # Fixes colours.
|
||||
gpuTargetCLUT: 1 # Fixes colours.
|
||||
minimumBlendingLevel: 4 # Fixes transparancy.
|
||||
SLPM-66307:
|
||||
name: "Sengoku Musou 2"
|
||||
region: "NTSC-J"
|
||||
@@ -34150,10 +34205,13 @@ SLPM-66443:
|
||||
gameFixes:
|
||||
- GIFFIFOHack # Fixes flag corruptions.
|
||||
SLPM-66444:
|
||||
name: "Spartan - Total Warrior"
|
||||
name: "Spartan - Kodai Greece Eiyuuden"
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes garbage textures flashing on the character model.
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes missing post processing.
|
||||
halfPixelOffset: 1 # Aligns post processing.
|
||||
SLPM-66445:
|
||||
name: "Persona 3"
|
||||
region: "NTSC-J"
|
||||
@@ -37577,6 +37635,9 @@ SLPS-20240:
|
||||
SLPS-20243:
|
||||
name: "New Price Go Go Golf"
|
||||
region: "NTSC-J"
|
||||
SLPS-20244:
|
||||
name: "Magical Sports - 2000 Koushien [NewPrice]"
|
||||
region: "NTSC-J"
|
||||
SLPS-20245:
|
||||
name: "Low Rider"
|
||||
region: "NTSC-J"
|
||||
@@ -37930,6 +37991,8 @@ SLPS-20392:
|
||||
SLPS-20393:
|
||||
name: "Princess Maker 2"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
partialTargetInvalidation: 1 # Fixes full screen C32->C16 frame invalidation.
|
||||
SLPS-20394:
|
||||
name: "Suki na Mono wa Sukida Rashouganai + White Flower + Sukisyo!"
|
||||
region: "NTSC-J"
|
||||
@@ -39514,6 +39577,8 @@ SLPS-25330:
|
||||
SLPS-25332:
|
||||
name: "Snow [First Limited Edition]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
minimumBlendingLevel: 4 # Fixes transparancy.
|
||||
SLPS-25333:
|
||||
name: "Gallop Racer Lucky 7"
|
||||
region: "NTSC-J"
|
||||
@@ -39578,6 +39643,8 @@ SLPS-25341:
|
||||
SLPS-25342:
|
||||
name: "Snow"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
minimumBlendingLevel: 4 # Fixes transparancy.
|
||||
SLPS-25343:
|
||||
name: "Gunslinger Girl Vol.1"
|
||||
region: "NTSC-J"
|
||||
@@ -39778,11 +39845,15 @@ SLPS-25389:
|
||||
name: "Gundam Seed - Never Ending Tomorrow"
|
||||
region: "NTSC-J"
|
||||
SLPS-25390:
|
||||
name: "Clover's Heart - Looking for Happiness [Limited Edition]"
|
||||
name: "Clover Heart's - Looking for Happiness [Limited Edition]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
minimumBlendingLevel: 4 # Fixes transparancy.
|
||||
SLPS-25391:
|
||||
name: "Clover's Heart - Looking for Happiness"
|
||||
name: "Clover Heart's - Looking for Happiness"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
minimumBlendingLevel: 4 # Fixes transparancy.
|
||||
SLPS-25392:
|
||||
name: "Desire"
|
||||
region: "NTSC-J"
|
||||
@@ -48355,6 +48426,9 @@ SLUS-21212:
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- EETimingHack # Fixes garbage textures flashing on the character model.
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes missing post processing.
|
||||
halfPixelOffset: 1 # Aligns post processing.
|
||||
SLUS-21213:
|
||||
name: "Madden NFL '06"
|
||||
region: "NTSC-U"
|
||||
@@ -48773,6 +48847,7 @@ SLUS-21273:
|
||||
mipmap: 2 # Mipmap + trilinear, improves ground textures to match sw renderer.
|
||||
trilinearFiltering: 1
|
||||
halfPixelOffset: 2 # Fix effects upscaling.
|
||||
autoFlush: 1 # Fixes broken post processing.
|
||||
SLUS-21274:
|
||||
name: "OutRun 2006 - Coast 2 Coast"
|
||||
region: "NTSC-U"
|
||||
|
||||
@@ -81,7 +81,6 @@ target_sources(common PRIVATE
|
||||
HeapArray.h
|
||||
HTTPDownloader.h
|
||||
MemorySettingsInterface.h
|
||||
MemsetFast.inl
|
||||
MD5Digest.h
|
||||
MRCHelpers.h
|
||||
Path.h
|
||||
@@ -101,6 +100,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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -169,6 +169,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 +181,4 @@
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -348,6 +348,9 @@
|
||||
<ClInclude Include="ByteSwap.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WrappedMemCopy.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
|
||||
@@ -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-->
|
||||
|
||||
+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
-13
@@ -40,13 +40,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 +69,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 +361,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 +641,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,24 @@ target_link_libraries(pcsx2-qt PRIVATE
|
||||
Qt6::Network
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
+14
-3
@@ -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);
|
||||
@@ -709,7 +709,7 @@ 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);
|
||||
|
||||
@@ -821,7 +821,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 +1394,12 @@ void MainWindow::updateTheme()
|
||||
m_game_list_widget->refreshImages();
|
||||
}
|
||||
|
||||
void MainWindow::updateLanguage()
|
||||
{
|
||||
QtHost::InstallTranslator();
|
||||
recreate();
|
||||
}
|
||||
|
||||
void MainWindow::onInputRecNewActionTriggered()
|
||||
{
|
||||
const bool wasPaused = s_vm_paused;
|
||||
@@ -2064,6 +2070,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;
|
||||
|
||||
@@ -159,6 +159,7 @@ private Q_SLOTS:
|
||||
void onToolsOpenDataDirectoryTriggered();
|
||||
void onToolsCoverDownloaderTriggered();
|
||||
void updateTheme();
|
||||
void updateLanguage();
|
||||
void onScreenshotActionTriggered();
|
||||
void onSaveGSDumpActionTriggered();
|
||||
void onBlockDumpActionToggled(bool checked);
|
||||
|
||||
+13
-8
@@ -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"/>
|
||||
@@ -484,12 +489,12 @@
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout">
|
||||
<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>
|
||||
<normaloff>:/icons/AppIcon64.png</normaloff>:/icons/AppIcon64.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&About PCSX2...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionChangeDisc">
|
||||
|
||||
+84
-44
@@ -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,6 +39,7 @@
|
||||
#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"
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -10,19 +10,19 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>410</width>
|
||||
<height>190</height>
|
||||
<height>215</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>410</width>
|
||||
<height>190</height>
|
||||
<height>215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>410</width>
|
||||
<height>190</height>
|
||||
<height>215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -86,15 +86,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",
|
||||
@@ -284,7 +287,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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -401,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.
|
||||
@@ -457,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)) :
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -678,7 +678,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",
|
||||
@@ -95,6 +95,10 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsDialog* dialog, QWidget
|
||||
QtHost::GetDefaultThemeName());
|
||||
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[];
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
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;
|
||||
};
|
||||
@@ -0,0 +1,669 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SetupWizardDialog</class>
|
||||
<widget class="QDialog" name="SetupWizardDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>760</width>
|
||||
<height>389</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>PCSX2 Setup Wizard</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normalon>:/icons/AppIcon64.png</normalon>
|
||||
</iconset>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="horizontalSpacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="logo">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>20</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelLanguage">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Language</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelBIOS">
|
||||
<property name="text">
|
||||
<string>BIOS Image</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelGameList">
|
||||
<property name="text">
|
||||
<string>Game Directories</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelController">
|
||||
<property name="text">
|
||||
<string>Controller Setup</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelComplete">
|
||||
<property name="text">
|
||||
<string>Complete</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</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>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QStackedWidget" name="pages">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string><html><head/><body><h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:700;">Welcome to PCSX2!</span></h1><p>This wizard will help guide you through the configuration steps required to use the application. It is recommended if this is your first time installing PCSX2 that you view the setup guide at <a href="https://pcsx2.net/docs/usage/setup/">https://pcsx2.net/docs/usage/setup/</a>.</p><p>By default, PCSX2 will connect to the server at <a href="https://pcsx2.net/">pcsx2.net</a> to check for updates, and if available and confirmed, download update packages from <a href="https://github.com/">github.com</a>. If you do not wish for PCSX2 to make any network connections on startup, you should uncheck the Automatic Updates option now. The Automatic Update setting can be changed later at any time in Interface Settings.</p><p>Please choose a language and theme to begin.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Language:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="language">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Theme:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="theme"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<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 row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="autoUpdateEnabled">
|
||||
<property name="text">
|
||||
<string>Enable Automatic Updates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>PCSX2 requires a PS2 BIOS in order to run.</p><p>For legal reasons, you must obtain a BIOS <strong>from an actual PS2 unit that you own</strong> (borrowing doesn't count).</p><p>Once dumped, this BIOS image should be placed in the bios folder within the data directory shown below, or you can instruct PCSX2 to scan an alternative directory.</p><p>A guide for dumping your BIOS can be found at <a href="https://pcsx2.net/docs/usage/setup/#how-to-dump-your-ps2-bios">pcsx2.net</a>.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_10">
|
||||
<property name="text">
|
||||
<string>BIOS Directory:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="biosSearchDirectory"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="browseBiosSearchDirectory">
|
||||
<property name="text">
|
||||
<string>Browse...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="resetBiosSearchDirectory">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="biosList">
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerMinimumSectionSize">
|
||||
<number>250</number>
|
||||
</attribute>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>250</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Filename</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Version</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="openBiosSearchDirectory">
|
||||
<property name="text">
|
||||
<string>Open in Explorer...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="refreshBiosList">
|
||||
<property name="text">
|
||||
<string>Refresh List</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>PCSX2 will automatically scan and identify games from the selected directories below, and populate the game list.<br>These games should be dumped from discs you own. Guides for dumping discs can be found at <a href="https://pcsx2.net/docs/usage/setup/#dumping-ps2-discs-via-imgburn">pcsx2.net</a>.</p><p>Supported formats for dumps include:</p><p><ul><li>.bin/.iso (ISO Disc Images)</li><li>.mdf (Media Descriptor File)</li><li>.chd (Compressed Hunks of Data)</li><li>.cso (Compressed ISO)</li><li>.gz (Gzip Compressed ISO)</li></ul></p></p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>Search Directories (will be scanned for games)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="addSearchDirectoryButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="folder-add-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="removeSearchDirectoryButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="folder-reduce-line">
|
||||
<normaloff>.</normaloff>.</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="searchDirectoryList">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Search Directory</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Scan Recursively</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_4">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>By default, PCSX2 will map your keyboard to the virtual PS2 controller.</p><p><span style=" font-weight:700;">To use an external controller, you must map it first. </span>On this screen, you can automatically map any controller which is currently connected. If your controller is not currently connected, you can plug it in now.</p><p>To change controller bindings in more detail, or use multi-tap, open the Settings menu and choose Controllers once you have completed the Setup Wizard.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Controller Port 1</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="controller1Type"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_12">
|
||||
<property name="text">
|
||||
<string>Controller Mapped To:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_11">
|
||||
<property name="text">
|
||||
<string>Controller Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="controller1Mapping">
|
||||
<property name="text">
|
||||
<string>Default (Keyboard)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="controller1AutomaticMapping">
|
||||
<property name="text">
|
||||
<string>Automatic Mapping</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="controller-line">
|
||||
<normaloff>Settings</normaloff>Settings</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Controller Port 2</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_13">
|
||||
<property name="text">
|
||||
<string>Controller Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="controller2Type"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Controller Mapped To:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<item>
|
||||
<widget class="QLabel" name="controller2Mapping">
|
||||
<property name="text">
|
||||
<string>Default (Keyboard)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="controller2AutomaticMapping">
|
||||
<property name="text">
|
||||
<string>Automatic Mapping</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="controller-line">
|
||||
<normaloff>Settings</normaloff>Settings</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_5">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string><html><head/><body><h1 style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:700;">Setup Complete!</span></h1><p>You are now ready to run games.</p><p>Further options are available under the settings menu. You can also use the Big Picture UI for navigation entirely with a gamepad.</p><p>We hope you enjoy using PCSX2.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="back">
|
||||
<property name="text">
|
||||
<string>&Back</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="next">
|
||||
<property name="text">
|
||||
<string>&Next</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancel">
|
||||
<property name="text">
|
||||
<string>&Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources/resources.qrc"/>
|
||||
<include location="resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,320 @@
|
||||
/* 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 "QtHost.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/StringUtil.h"
|
||||
|
||||
#include "pcsx2/ImGui/ImGuiManager.h"
|
||||
|
||||
#include "fmt/format.h"
|
||||
#include "imgui.h"
|
||||
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QTranslator>
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include <KnownFolders.h>
|
||||
#include <ShlObj.h>
|
||||
#endif
|
||||
|
||||
namespace QtHost
|
||||
{
|
||||
struct GlyphInfo
|
||||
{
|
||||
const char* language;
|
||||
const char* windows_font_name;
|
||||
const char* linux_font_name;
|
||||
const char* mac_font_name;
|
||||
const char16_t* used_glyphs;
|
||||
};
|
||||
|
||||
static std::string GetFontPath(const GlyphInfo* gi);
|
||||
static void UpdateGlyphRanges(const std::string_view& language);
|
||||
static const GlyphInfo* GetGlyphInfo(const std::string_view& language);
|
||||
|
||||
static std::vector<ImWchar> s_glyph_ranges;
|
||||
} // namespace QtHost
|
||||
|
||||
static std::vector<QTranslator*> s_translators;
|
||||
|
||||
void QtHost::InstallTranslator()
|
||||
{
|
||||
for (QTranslator* translator : s_translators)
|
||||
{
|
||||
qApp->removeTranslator(translator);
|
||||
translator->deleteLater();
|
||||
}
|
||||
s_translators.clear();
|
||||
|
||||
const QString language =
|
||||
QString::fromStdString(Host::GetBaseStringSettingValue("UI", "Language", GetDefaultLanguage()));
|
||||
|
||||
// Install the base qt translation first.
|
||||
const QString base_dir = QStringLiteral("%1/translations").arg(qApp->applicationDirPath());
|
||||
QString base_path = QStringLiteral("%1/qt_%2.qm").arg(base_dir).arg(language);
|
||||
bool has_base_ts = QFile::exists(base_path);
|
||||
if (!has_base_ts)
|
||||
{
|
||||
// Try without the country suffix.
|
||||
const int index = language.indexOf('-');
|
||||
if (index > 0)
|
||||
{
|
||||
base_path = QStringLiteral("%1/qt_%2.qm").arg(base_dir).arg(language.left(index));
|
||||
has_base_ts = QFile::exists(base_path);
|
||||
}
|
||||
}
|
||||
if (has_base_ts)
|
||||
{
|
||||
QTranslator* base_translator = new QTranslator(qApp);
|
||||
if (!base_translator->load(base_path))
|
||||
{
|
||||
QMessageBox::warning(nullptr, QStringLiteral("Translation Error"),
|
||||
QStringLiteral("Failed to find load base translation file for '%1':\n%2").arg(language).arg(base_path));
|
||||
delete base_translator;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_translators.push_back(base_translator);
|
||||
qApp->installTranslator(base_translator);
|
||||
}
|
||||
}
|
||||
|
||||
const QString path = QStringLiteral("%1/pcsx2-qt_%3.qm").arg(base_dir).arg(language);
|
||||
QTranslator* translator = nullptr;
|
||||
if (QFile::exists(path))
|
||||
{
|
||||
translator = new QTranslator(qApp);
|
||||
if (translator->load(path))
|
||||
{
|
||||
Console.WriteLn(
|
||||
Color_StrongYellow, "Loaded translation file for language %s", language.toUtf8().constData());
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(nullptr, QStringLiteral("Translation Error"),
|
||||
QStringLiteral("Failed to load translation file for language '%1':\n%2").arg(language).arg(path));
|
||||
delete translator;
|
||||
translator = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
// For now, until we're sure this works on all platforms, we won't block users from starting if they're missing.
|
||||
QMessageBox::warning(nullptr, QStringLiteral("Translation Error"),
|
||||
QStringLiteral("Failed to find translation file for language '%1':\n%2").arg(language).arg(path));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (translator)
|
||||
{
|
||||
qApp->installTranslator(translator);
|
||||
s_translators.push_back(translator);
|
||||
}
|
||||
|
||||
UpdateGlyphRanges(language.toStdString());
|
||||
|
||||
// Clear translation cache after installing translators, to prevent races.
|
||||
Host::ClearTranslationCache();
|
||||
}
|
||||
|
||||
static std::string QtHost::GetFontPath(const GlyphInfo* gi)
|
||||
{
|
||||
std::string font_path;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (gi->windows_font_name)
|
||||
{
|
||||
PWSTR folder_path;
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Fonts, 0, nullptr, &folder_path)))
|
||||
{
|
||||
font_path = StringUtil::WideStringToUTF8String(folder_path);
|
||||
CoTaskMemFree(folder_path);
|
||||
font_path += "\\";
|
||||
font_path += gi->windows_font_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
font_path = fmt::format("C:\\Windows\\Fonts\\%s", gi->windows_font_name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return font_path;
|
||||
}
|
||||
|
||||
const char* QtHost::GetDefaultLanguage()
|
||||
{
|
||||
return "en";
|
||||
}
|
||||
|
||||
s32 Host::Internal::GetTranslatedStringImpl(
|
||||
const std::string_view& context, const std::string_view& msg, char* tbuf, size_t tbuf_space)
|
||||
{
|
||||
// This is really awful. Thankfully we're caching the results...
|
||||
const std::string temp_context(context);
|
||||
const std::string temp_msg(msg);
|
||||
const QString translated_msg = qApp->translate(temp_context.c_str(), temp_msg.c_str());
|
||||
const QByteArray translated_utf8 = translated_msg.toUtf8();
|
||||
const size_t translated_size = translated_utf8.size();
|
||||
if (translated_size > tbuf_space)
|
||||
return -1;
|
||||
else if (translated_size > 0)
|
||||
std::memcpy(tbuf, translated_utf8.constData(), translated_size);
|
||||
|
||||
return static_cast<s32>(translated_size);
|
||||
}
|
||||
|
||||
std::vector<std::pair<QString, QString>> QtHost::GetAvailableLanguageList()
|
||||
{
|
||||
return {
|
||||
{QStringLiteral("Afrikaans (af-ZA)"), QStringLiteral("af-ZA")},
|
||||
{QStringLiteral("عربي (ar-SA)"), QStringLiteral("ar-SA")},
|
||||
{QStringLiteral("Català (ca-ES)"), QStringLiteral("ca-ES")},
|
||||
{QStringLiteral("Čeština (cs-CZ)"), QStringLiteral("cs-CZ")},
|
||||
{QStringLiteral("Dansk (da-DK)"), QStringLiteral("da-DK")},
|
||||
{QStringLiteral("Deutsch (de-DE)"), QStringLiteral("de-DE")},
|
||||
{QStringLiteral("Ελληνικά (el-GR)"), QStringLiteral("el-GR")},
|
||||
{QStringLiteral("English (en)"), QStringLiteral("en")},
|
||||
{QStringLiteral("Español (Hispanoamérica) (es-419)"), QStringLiteral("es-419")},
|
||||
{QStringLiteral("Español (España) (es-ES)"), QStringLiteral("es-ES")},
|
||||
{QStringLiteral("فارسی (fa-IR)"), QStringLiteral("fa-IR")},
|
||||
{QStringLiteral("Suomi (fi-FI)"), QStringLiteral("fi-FI")},
|
||||
{QStringLiteral("Français (fr-FR)"), QStringLiteral("fr-FR")},
|
||||
{QStringLiteral("עִבְרִית (he-IL)"), QStringLiteral("he-IL")},
|
||||
{QStringLiteral("Magyar (hu-HU)"), QStringLiteral("hu-HU")},
|
||||
{QStringLiteral("Bahasa Indonesia (in-ID)"), QStringLiteral("id-ID")},
|
||||
{QStringLiteral("Italiano (it-IT)"), QStringLiteral("it-IT")},
|
||||
{QStringLiteral("日本語 (ja-JP)"), QStringLiteral("ja-JP")},
|
||||
{QStringLiteral("한국어 (ko-KR)"), QStringLiteral("ko-KR")},
|
||||
{QStringLiteral("Nederlands (nl-NL)"), QStringLiteral("nl-NL")},
|
||||
{QStringLiteral("Norsk (nl-NL)"), QStringLiteral("no-NO")},
|
||||
{QStringLiteral("Polski (pl-PL)"), QStringLiteral("pl-PL")},
|
||||
{QStringLiteral("Português (Brasil) (pt-BR)"), QStringLiteral("pt-BR")},
|
||||
{QStringLiteral("Português (Portugal) (pt-PT)"), QStringLiteral("pt-PT")},
|
||||
{QStringLiteral("Limba română (ro-RO)"), QStringLiteral("ro-RO")},
|
||||
{QStringLiteral("Русский (ru-RU)"), QStringLiteral("ru-RU")},
|
||||
{QStringLiteral("Српски језик (sr-SP)"), QStringLiteral("sr-SP")},
|
||||
{QStringLiteral("Svenska (sv-SE)"), QStringLiteral("sv-SE")},
|
||||
{QStringLiteral("Türkçe (tr-TR)"), QStringLiteral("tr-TR")},
|
||||
{QStringLiteral("Українська мова (uk-UA)"), QStringLiteral("uk-UA")},
|
||||
{QStringLiteral("Tiếng Việt (vi-VN)"), QStringLiteral("vi-VN")},
|
||||
{QStringLiteral("简体中文 (zh-CN)"), QStringLiteral("zh-CN")},
|
||||
{QStringLiteral("繁體中文 (zh-TW)"), QStringLiteral("zh-TW")},
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr const ImWchar s_base_latin_range[] = {
|
||||
0x0020, 0x00FF, // Basic Latin + Latin Supplement
|
||||
};
|
||||
static constexpr const ImWchar s_central_european_ranges[] = {
|
||||
0x0100, 0x017F, // Central European diacritics
|
||||
};
|
||||
|
||||
void QtHost::UpdateGlyphRanges(const std::string_view& language)
|
||||
{
|
||||
const GlyphInfo* gi = GetGlyphInfo(language);
|
||||
|
||||
std::string font_path;
|
||||
s_glyph_ranges.clear();
|
||||
|
||||
// Base Latin range is always included.
|
||||
s_glyph_ranges.insert(s_glyph_ranges.begin(), std::begin(s_base_latin_range), std::end(s_base_latin_range));
|
||||
|
||||
if (gi)
|
||||
{
|
||||
if (gi->used_glyphs)
|
||||
{
|
||||
const char16_t* ptr = gi->used_glyphs;
|
||||
while (*ptr != 0)
|
||||
{
|
||||
// Always should be in pairs.
|
||||
pxAssert(ptr[0] != 0 && ptr[1] != 0);
|
||||
s_glyph_ranges.push_back(*(ptr++));
|
||||
s_glyph_ranges.push_back(*(ptr++));
|
||||
}
|
||||
}
|
||||
|
||||
font_path = GetFontPath(gi);
|
||||
}
|
||||
|
||||
// If we don't have any specific glyph range, assume Central European, except if English, then keep the size down.
|
||||
if ((!gi || !gi->used_glyphs) && language != "en")
|
||||
{
|
||||
s_glyph_ranges.insert(
|
||||
s_glyph_ranges.begin(), std::begin(s_central_european_ranges), std::end(s_central_european_ranges));
|
||||
}
|
||||
|
||||
// List terminator.
|
||||
s_glyph_ranges.push_back(0);
|
||||
s_glyph_ranges.push_back(0);
|
||||
|
||||
ImGuiManager::SetFontPath(std::move(font_path));
|
||||
ImGuiManager::SetFontRange(s_glyph_ranges.data());
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
static constexpr const char16_t s_cyrillic_ranges[] = {
|
||||
/* Cyrillic + Cyrillic Supplement */ 0x0400, 0x052F, /* Extended-A */ 0x2DE0, 0x2DFF, /* Extended-B */ 0xA640, 0xA69F, 0, 0
|
||||
};
|
||||
static constexpr const QtHost::GlyphInfo s_glyph_info[] = {
|
||||
// Cyrillic languages
|
||||
{ "ru-RU", nullptr, nullptr, nullptr, s_cyrillic_ranges },
|
||||
{ "sr-SP", nullptr, nullptr, nullptr, s_cyrillic_ranges },
|
||||
{ "uk-UA", nullptr, nullptr, nullptr, s_cyrillic_ranges },
|
||||
|
||||
{
|
||||
"ja-JP", "msgothic.ttc", nullptr, nullptr,
|
||||
// auto update by update_glyph_ranges.py with pcsx2-qt_ja-JP.ts
|
||||
u"□□△△◯◯✕✕、。〜〜ああいいううええおきくぐここささしすせせそそただっつてにのはびびへべほほまみめもややよれわわをんァイウコサソタチッツテニネパビロワワンンーー一一上下不不中中丸丸了了互互今今他他代代仮仮作作使使保保信信修修倍倍値値停停備備像像入入全全公公内内再再出出切切別別利利制制削削副副割割力力加加効効動動勧勧化化十十南南参参反収取取古古可台右右合合同名向向回回固固国国在在報報場場境境壊壊変変外外大大失失奨奨始始字存完完定定実実左左帰帰常常幅幅度度式式張張形形待待後後御御性性情情想想意意感感態態成成投投択択拡拡推推提提換換敗敗数数整整新新方方既既日日明明時時更更書書替最有有期期本本果果検検標標橙橙機機止正毎毎比比況況注注消消港港湾湾準準無無照照状状率率現現璧璧環環生生用用画画異異的的直直知知確確示示種種稿稿空空索索終終緑緑編編績績能能自自般般行行表表製製複複視視覧覧解解言言設設認認語語読読赤赤起起跡跡転転軸軸込込近近追追送送通通速速進進遅遅遊遊適適選選部部長長閉閉開開関関防防限限除除隅隅集集青青非非面面韓韓音音類類香香高高黄黄++??"
|
||||
},
|
||||
{
|
||||
"ko-KR", "malgun.ttf", nullptr, nullptr,
|
||||
// auto update by update_glyph_ranges.py with pcsx2-qt_ko-KR.ts
|
||||
u""
|
||||
},
|
||||
{
|
||||
"zh-CN", "msyh.ttc", nullptr, nullptr,
|
||||
// auto update by update_glyph_ranges.py with pcsx2-qt_zh-CN.ts
|
||||
u"‘’□□△△○○、。一丁三下不与且且世世丢丢两两个个中中丰丰串串为主么义之之乎乎乐乐乘乘也也了了事二于于互互亚些交交产产享享亮亮亲亲人人什什仅仅介介仍从他他代以们们件价任任份份伍伍休休优优会会传传估估伸伸似似但但位住佑佑体体何何余余作作佣佣佳佳使使例例供供侧侧便便俄俄保保信信修修倍倍值值倾倾假假偏偏做做停停储储像像儿儿允允元元充充先光克克免免入入全全六六兰共关关兵典兼兼内内册再写写冲决况况净净准准减减几几出击函函刀刀刃刃分切列列则则创创删删利利别别到到制刷刹刹前前剪剪副副力力功务动助势势勿勿包包化化匹区十十升升半半协协单单南南占卡卫卫印印即即压压原原去去参参及及双反发发取变叠叠口古另另只只可台右右号号各各合吉同后向向吗吗否否含含启启呈呈告告员员味味命命和和哈哈响响哪哪唤唤商商善善器器四四回回因因团团围围国图圈圈在在地地场场址址均均坏坐块块坛坛垂垂型型域域基基堆堆堪堪塔塔填填增增士士声声处处备备复复外外多多够够大大天太失失头头夹夹奇奇奏奏套套奥奥奶奶好好如如始始威威娱娱婴婴媒媒子子字存它它安安完完宏宏官官定定宝实害害家家容容宽宽宿宿寄寄密密富富寸对导导封封射射将将小小少少尔尔尚尚尝尝就就尺尺尼尾局局层层屏屏展展属属崩崩工左巨巨差差己已巴巴希希带帧帮帮常常幅幅幕幕平平并并幸幸序序库底度度延延建建开开异弃弊弊式式引引张张弹强归当录录形形彩彩影影径待很很得得循循微微德德心心必忆志志忙忙快快忽忽态态性性怪怪恢恢息息您您悬悬情情惑惑惯惯意意感感慢慢戏我或或战战截截戳戳户户所扁手手打打托托执执扩扩扫扬扳扳找找技技抑抑抖抗护护拆拆拉拉拍拍拒拒拟拟拦拦择择括括拳拳持持指指按按挑挑挡挡挪挪振振捕捕损损换换据据掌掌排排接接控掩描提插插握握搜搜摇摇撕撕撤撤播播操擎支支收收改改放放故故效效敏敏散散数数整整文文断断斯新方方旋旋无无日日旧旧时时明明易易星映是是显显晕晕普普晰晰暂暂暗暗曲曲更更替最有有服服期期未未本本机机权权杆杆束束条条来来板板极极果果柄柄某某染染查查栅栅标栈栏栏校校样根格格框框案案档档桥桥检检棕棕榜榜模模橙橙次次欧欧止步死死殊殊段段每每比比毫毫水水求求汇汇没没油油法法波波注注泻泻洲洲活活流流浅浅测测浏浏浪浪浮浮海海消消深深混混添添清清港港渲渲游游湖湖湾湾溃溃源源溢溢滑滑满满滤滤演演澳澳激激灰灰灵灵点点烈烈热热焦焦然然煞煞照照片版牌牌牙牙特特状状狂狂独独狼狼猎猎猩猩率率王王玩玩环现班班理理瑞瑞甚甚生生用用由甲电电画画畅畅界界留留略略疤疤登登白百的的皇皇盖盘目目直直相相省省看看真眠着着知知短短石石码码破破础础硬硬确确碌碌磁磁示示神神禁禁离离种种秒秒积称移移程程稍稍稳稳空空突突窗窗立立站站端端符符第第等等筛筛签签简简算算管管类类粉粉粘粘精精糊糊系系素素索索紫紫纠纠红红级级纯纯纳纳纹纹线线组组细终经经绑绑结结绕绕绘给络绝统统继继绪绪续续维维绿缀缓缓编编缩缩网网罗罗置置美美翻翻考考者者而而耗耗耳耳联联肩肩胖胖能能腊腊自自至致舍舍良良色色节节芬芬英英范范荐荐荷荷莱莱获获菜菜萄萄著著葡葡蓝蓝藏藏虑虑虚虚融融行行衡衡补补表表被被裁裂装装西西要要覆覆观观规规视视览觉角角解解触触言言警警计计认认让让议议记记许许论论设访证证诊诊译译试试询询该详语语误误说说请诸读读调调谍谍豹豹负负败账质质贴贴费费赛赛起起超超越越足足跟跟跨跨路路跳跳踏踏踪踪身身车车轨轨转转轮软轴轴轻轻载载较较辅辅辑辑输输辨辨边边达达过过运近还这进进连迟述述追追退适选选逐逐递递通通速造遇遇道道避避那那部部都都配配醒醒采采释释里重量量针针钮钮铁铁铺铺链链销锁锐锐错错键锯镜镜长长门门闭问闲闲间间队队防防阴阴附附陆陆降降限限除除险险随隐隔隔隙隙障障雄雄集集零零雾雾需需震震静静非非靠靠面面韩韩音音顶顶项须顿顿预预频频题题颜额风风饱饱馈馈首首香香马马驱驱验验高高鬼鬼魂魂魔魔麦麦黄黄黑黑默默鼓鼓鼠鼠齐齐齿齿,,??"
|
||||
},
|
||||
{
|
||||
"zh-TW", "msyh.ttc", nullptr, nullptr,
|
||||
// auto update by update_glyph_ranges.py with pcsx2-qt_zh-TW.ts
|
||||
u""
|
||||
},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
const QtHost::GlyphInfo* QtHost::GetGlyphInfo(const std::string_view& language)
|
||||
{
|
||||
for (const GlyphInfo& it : s_glyph_info)
|
||||
{
|
||||
if (language == it.language)
|
||||
return ⁢
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+4689
-2101
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,19 @@
|
||||
@echo off
|
||||
|
||||
set QTBIN=..\..\3rdparty\qt\6.5.0\msvc2022_64\bin
|
||||
set SRCDIRS=../ ../../pcsx2/
|
||||
|
||||
set OPTS=-tr-function-alias QT_TRANSLATE_NOOP+=TRANSLATE,QT_TRANSLATE_NOOP+=TRANSLATE_SV,QT_TRANSLATE_NOOP+=TRANSLATE_STR,QT_TRANSLATE_N_NOOP3+=TRANSLATE_FMT,QT_TRANSLATE_NOOP+=TRANSLATE_NOOP
|
||||
|
||||
"%QTBIN%\lupdate.exe" %SRCDIRS% %OPTS% -no-obsolete -source-language en -ts pcsx2-qt_en.ts
|
||||
|
||||
echo.
|
||||
echo ******************************************************************************************************************
|
||||
echo * PLEASE READ *
|
||||
echo ******************************************************************************************************************
|
||||
echo.
|
||||
echo Make sure you have deleted the build (x64) directory from pcsx2-qt, otherwise you will have polluted the .ts file.
|
||||
echo If you did not, then you should reset/checkout the ts file, delete the build directory, and run this script again.
|
||||
echo.
|
||||
echo.
|
||||
pause
|
||||
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import re
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
languages_to_update = [
|
||||
"ja-JP",
|
||||
"ko-KR",
|
||||
"zh-CN",
|
||||
"zh-TW"
|
||||
]
|
||||
|
||||
src_path = os.path.join(os.path.dirname(__file__), "..", "Translations.cpp")
|
||||
ts_dir = os.path.join(os.path.dirname(__file__))
|
||||
|
||||
def parse_xml(path):
|
||||
tree = ET.parse(path)
|
||||
root = tree.getroot()
|
||||
translations = ""
|
||||
for node in root.findall("context/message/translation"):
|
||||
if node.text:
|
||||
translations += node.text
|
||||
|
||||
ords = list(set([ord(ch) for ch in translations if ord(ch) >= 0x2000]))
|
||||
if len(ords) == 0:
|
||||
return ""
|
||||
|
||||
# Try to organize it into ranges
|
||||
ords.sort()
|
||||
ord_pairs = []
|
||||
start_ord = None
|
||||
last_ord = None
|
||||
for nord in ords:
|
||||
if start_ord is not None and nord == (last_ord + 1):
|
||||
last_ord = nord
|
||||
continue
|
||||
if start_ord is not None:
|
||||
ord_pairs.append(start_ord)
|
||||
ord_pairs.append(last_ord)
|
||||
start_ord = nord
|
||||
last_ord = nord
|
||||
|
||||
if start_ord is not None:
|
||||
ord_pairs.append(start_ord)
|
||||
ord_pairs.append(last_ord)
|
||||
|
||||
chars = "".join([chr(ch) for ch in ord_pairs])
|
||||
return chars
|
||||
|
||||
def update_src_file(ts_file, chars):
|
||||
ts_name = os.path.basename(ts_file)
|
||||
pattern = re.compile('(// auto update.*' + ts_name + '.*\n[^"]+")[^"]*(".*)')
|
||||
with open(src_path, "r", encoding="utf-8") as f:
|
||||
original = f.read()
|
||||
update = pattern.sub("\\1" + chars + "\\2", original)
|
||||
if original != update:
|
||||
with open(src_path, "w", encoding="utf-8") as f:
|
||||
f.write(update)
|
||||
print(f"Updated character list for {ts_file}.")
|
||||
else:
|
||||
print(f"Character list is unchanged for {ts_file}.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
for language in languages_to_update:
|
||||
ts_file = os.path.join(ts_dir, f"pcsx2-qt_{language}.ts")
|
||||
chars = parse_xml(ts_file)
|
||||
print(f"{language}: {len(chars)} character(s) detected.")
|
||||
update_src_file(ts_file, chars)
|
||||
@@ -39,6 +39,7 @@
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\lzma\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\simpleini\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\imgui\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\demangler\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\rapidyaml\rapidyaml\ext\c4core\src\c4\ext\fast_float\include;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\sdl2\include;$(SolutionDir)3rdparty\sdl2\SDL\include</AdditionalIncludeDirectories>
|
||||
@@ -87,6 +88,7 @@
|
||||
<ClCompile Include="Settings\GameCheatSettingsWidget.cpp" />
|
||||
<ClCompile Include="Settings\GamePatchSettingsWidget.cpp" />
|
||||
<ClCompile Include="Settings\MemoryCardConvertWorker.cpp" />
|
||||
<ClCompile Include="SetupWizardDialog.cpp" />
|
||||
<ClCompile Include="Themes.cpp" />
|
||||
<ClCompile Include="Tools\InputRecording\InputRecordingViewer.cpp" />
|
||||
<ClCompile Include="Tools\InputRecording\NewInputRecordingDlg.cpp" />
|
||||
@@ -138,8 +140,10 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="QtKeyCodes.cpp" />
|
||||
<ClCompile Include="QtUtils.cpp" />
|
||||
<ClCompile Include="Translations.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="SetupWizardDialog.h" />
|
||||
<QtMoc Include="Settings\InterfaceSettingsWidget.h" />
|
||||
<QtMoc Include="Settings\GameListSettingsWidget.h" />
|
||||
<QtMoc Include="Settings\BIOSSettingsWidget.h" />
|
||||
@@ -251,6 +255,7 @@
|
||||
<ClCompile Include="$(IntDir)moc_MainWindow.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_QtHost.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_QtProgressCallback.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_SetupWizardDialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)Tools\InputRecording\moc_NewInputRecordingDlg.cpp" />
|
||||
<ClCompile Include="$(IntDir)Tools\InputRecording\moc_InputRecordingViewer.cpp" />
|
||||
<ClCompile Include="$(IntDir)qrc_resources.cpp">
|
||||
@@ -365,6 +370,12 @@
|
||||
</QtUi>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUi Include="SetupWizardDialog.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtTs Include="Translations\pcsx2-qt_en.ts">
|
||||
<FileType>Document</FileType>
|
||||
</QtTs>
|
||||
<QtUi Include="Settings\DebugSettingsWidget.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
<Filter Include="Debugger\Models">
|
||||
<UniqueIdentifier>{f4084ca0-d9d5-4584-b9d2-063db9f67de2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Translations">
|
||||
<UniqueIdentifier>{ad04f939-64a0-4039-97aa-a38b8aa46855}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\pcsx2\windows\PCSX2.rc" />
|
||||
@@ -328,6 +331,11 @@
|
||||
<ClCompile Include="$(IntDir)Settings\moc_GameCheatSettingsWidget.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Translations.cpp" />
|
||||
<ClCompile Include="SetupWizardDialog.cpp" />
|
||||
<ClCompile Include="$(IntDir)moc_SetupWizardDialog.cpp">
|
||||
<Filter>moc</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="..\pcsx2\windows\PCSX2.manifest">
|
||||
@@ -475,8 +483,13 @@
|
||||
<Filter>Debugger\Models</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="ColorPickerButton.h" />
|
||||
<QtMoc Include="Settings\GameCheatSettingsWidget.h" />
|
||||
<QtMoc Include="Settings\GamePatchSettingsWidget.h" />
|
||||
<QtMoc Include="SetupWizardDialog.h" />
|
||||
<QtMoc Include="Settings\GameCheatSettingsWidget.h">
|
||||
<Filter>Settings</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="Settings\GamePatchSettingsWidget.h">
|
||||
<Filter>Settings</Filter>
|
||||
</QtMoc>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtResource Include="resources\resources.qrc">
|
||||
@@ -607,6 +620,7 @@
|
||||
<QtUi Include="Settings\GamePatchSettingsWidget.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="SetupWizardDialog.ui" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Settings\FolderSettingsWidget.ui">
|
||||
@@ -619,4 +633,9 @@
|
||||
<Filter>Settings</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtTs Include="Translations\pcsx2-qt_en.ts">
|
||||
<Filter>Translations</Filter>
|
||||
</QtTs>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
@@ -1,6 +1,6 @@
|
||||
<RCC>
|
||||
<qresource>
|
||||
<file>icons/AppIcon.png</file>
|
||||
<file>icons/AppIcon64.png</file>
|
||||
<file>icons/applications-system-24.png</file>
|
||||
<file>icons/black/index.theme</file>
|
||||
<file>icons/black/svg/arrow-left-right-line.svg</file>
|
||||
|
||||
+14
-13
@@ -21,13 +21,13 @@
|
||||
#include "CDVD/IsoFS/IsoFS.h"
|
||||
#include "CDVD/IsoFS/IsoFSCDVD.h"
|
||||
#include "Elfheader.h"
|
||||
#include "GS.h"
|
||||
#include "Host.h"
|
||||
#include "ImGui/FullscreenUI.h"
|
||||
#include "ImGui/ImGuiFullscreen.h"
|
||||
#include "ImGui/ImGuiManager.h"
|
||||
#include "IopMem.h"
|
||||
#include "Memory.h"
|
||||
#include "MTGS.h"
|
||||
#include "VMManager.h"
|
||||
#include "svnrev.h"
|
||||
#include "vtlb.h"
|
||||
@@ -426,7 +426,7 @@ std::string Achievements::GetUserAgent()
|
||||
|
||||
void Achievements::BeginLoadingScreen(const char* text, bool* was_running_idle)
|
||||
{
|
||||
GetMTGS().RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
|
||||
MTGS::RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
|
||||
ImGuiFullscreen::OpenBackgroundProgressDialog("achievements_loading", text, 0, 0, 0);
|
||||
}
|
||||
|
||||
@@ -1041,7 +1041,7 @@ void Achievements::DownloadImage(std::string url, std::string cache_filename)
|
||||
return;
|
||||
}
|
||||
|
||||
GetMTGS().RunOnGSThread([cache_filename]() { ImGuiFullscreen::InvalidateCachedTexture(cache_filename); });
|
||||
MTGS::RunOnGSThread([cache_filename]() { ImGuiFullscreen::InvalidateCachedTexture(cache_filename); });
|
||||
};
|
||||
|
||||
s_http_downloader->CreateRequest(std::move(url), std::move(callback));
|
||||
@@ -1053,26 +1053,26 @@ void Achievements::DisplayAchievementSummary()
|
||||
{
|
||||
std::string title = s_game_title;
|
||||
if (ChallengeModeActive())
|
||||
title += " (Hardcore Mode)";
|
||||
title += TRANSLATE_SV("Achievements", " (Hardcore Mode)");
|
||||
|
||||
std::string summary;
|
||||
if (GetAchievementCount() > 0)
|
||||
{
|
||||
summary = StringUtil::StdStringFromFormat("You have earned %u of %u achievements, and %u of %u points.",
|
||||
summary = fmt::format(TRANSLATE_SV("Achievements", "You have earned {0} of {1} achievements, and {2} of {3} points."),
|
||||
GetUnlockedAchiementCount(), GetAchievementCount(), GetCurrentPointsForGame(), GetMaximumPointsForGame());
|
||||
}
|
||||
else
|
||||
{
|
||||
summary = "This game has no achievements.";
|
||||
summary = TRANSLATE_SV("Achievements", "This game has no achievements.");
|
||||
}
|
||||
if (GetLeaderboardCount() > 0)
|
||||
{
|
||||
summary.push_back('\n');
|
||||
if (LeaderboardsActive())
|
||||
summary.append("Leaderboard submission is enabled.");
|
||||
summary.append(TRANSLATE_SV("Achievements", "Leaderboard submission is enabled."));
|
||||
}
|
||||
|
||||
GetMTGS().RunOnGSThread([title = std::move(title), summary = std::move(summary), icon = s_game_icon]() {
|
||||
MTGS::RunOnGSThread([title = std::move(title), summary = std::move(summary), icon = s_game_icon]() {
|
||||
if (FullscreenUI::IsInitialized())
|
||||
ImGuiFullscreen::AddNotification(10.0f, std::move(title), std::move(summary), std::move(icon));
|
||||
});
|
||||
@@ -1092,7 +1092,7 @@ void Achievements::DisplayMasteredNotification()
|
||||
std::string message(fmt::format(
|
||||
"{} achievements, {} points{}", GetAchievementCount(), GetCurrentPointsForGame(), s_challenge_mode ? " (Hardcore Mode)" : ""));
|
||||
|
||||
GetMTGS().RunOnGSThread([title = std::move(title), message = std::move(message), icon = s_game_icon]() {
|
||||
MTGS::RunOnGSThread([title = std::move(title), message = std::move(message), icon = s_game_icon]() {
|
||||
if (FullscreenUI::IsInitialized())
|
||||
ImGuiFullscreen::AddNotification(20.0f, std::move(title), std::move(message), std::move(icon));
|
||||
});
|
||||
@@ -1157,7 +1157,7 @@ void Achievements::GetPatchesCallback(s32 status_code, const std::string& conten
|
||||
return;
|
||||
|
||||
// ensure fullscreen UI is ready
|
||||
GetMTGS().RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
|
||||
MTGS::RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
|
||||
|
||||
s_game_id = response.id;
|
||||
s_game_title = response.title;
|
||||
@@ -1505,7 +1505,8 @@ void Achievements::GameChanged(u32 disc_crc, u32 crc)
|
||||
// when we're booting the bios, or shutting down, this will fail
|
||||
if (disc_crc != 0)
|
||||
{
|
||||
Host::AddKeyedOSDMessage("retroachievements_disc_read_failed", "Failed to read executable from disc. Achievements disabled.",
|
||||
Host::AddKeyedOSDMessage("retroachievements_disc_read_failed",
|
||||
TRANSLATE_STR("Achievements", "Failed to read executable from disc. Achievements disabled."),
|
||||
Host::OSD_CRITICAL_ERROR_DURATION);
|
||||
}
|
||||
|
||||
@@ -1846,7 +1847,7 @@ void Achievements::SubmitLeaderboardCallback(s32 status_code, const std::string&
|
||||
std::string summary = fmt::format(
|
||||
"Your Score: {} (Best: {})\nLeaderboard Position: {} of {}", submitted_score, best_score, response.new_rank, response.num_entries);
|
||||
|
||||
GetMTGS().RunOnGSThread([title = lb->title, summary = std::move(summary), icon = s_game_icon]() {
|
||||
MTGS::RunOnGSThread([title = lb->title, summary = std::move(summary), icon = s_game_icon]() {
|
||||
if (FullscreenUI::IsInitialized())
|
||||
ImGuiFullscreen::AddNotification(10.0f, std::move(title), std::move(summary), std::move(icon));
|
||||
});
|
||||
@@ -1889,7 +1890,7 @@ void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification /
|
||||
break;
|
||||
}
|
||||
|
||||
GetMTGS().RunOnGSThread(
|
||||
MTGS::RunOnGSThread(
|
||||
[title = std::move(title), description = achievement->description, icon = GetAchievementBadgePath(*achievement)]() {
|
||||
ImGuiFullscreen::AddNotification(15.0f, std::move(title), std::move(description), std::move(icon));
|
||||
});
|
||||
|
||||
+5
-3
@@ -19,6 +19,7 @@
|
||||
#include "IopHw.h"
|
||||
#include "IopDma.h"
|
||||
#include "VMManager.h"
|
||||
#include "Sio.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <ctime>
|
||||
@@ -913,7 +914,7 @@ static uint cdvdBlockReadTime(CDVD_MODE_TYPE mode)
|
||||
|
||||
void cdvdReset()
|
||||
{
|
||||
memzero(cdvd);
|
||||
std::memset(&cdvd, 0, sizeof(cdvd));
|
||||
|
||||
cdvd.Type = CDVD_TYPE_NODISC;
|
||||
cdvd.Spinning = false;
|
||||
@@ -1528,6 +1529,7 @@ void cdvdVsync()
|
||||
cdvd.RTCcount = 0;
|
||||
|
||||
cdvdUpdateTrayState();
|
||||
AutoEject::CountDownTicks();
|
||||
|
||||
cdvd.RTC.second++;
|
||||
if (cdvd.RTC.second < 60)
|
||||
@@ -1824,7 +1826,7 @@ static void cdvdWrite04(u8 rt)
|
||||
cdvd.SCMDParamC = 0;
|
||||
cdvdUpdateStatus(CDVD_STATUS_STOP);
|
||||
cdvd.Spinning = false;
|
||||
memzero(cdvd.SCMDResult);
|
||||
std::memset(cdvd.SCMDResult, 0, sizeof(cdvd.SCMDResult));
|
||||
cdvdSetIrq();
|
||||
break;
|
||||
|
||||
@@ -2337,7 +2339,7 @@ static void cdvdWrite16(u8 rt) // SCOMMAND
|
||||
CDVD_LOG("cdvdWrite16: SCMD %s (%x) (ParamP = %x)", sCmdName[rt], rt, cdvd.SCMDParamP);
|
||||
|
||||
cdvd.sCommand = rt;
|
||||
memzero(cdvd.SCMDResult);
|
||||
std::memset(cdvd.SCMDResult, 0, sizeof(cdvd.SCMDResult));
|
||||
|
||||
switch (rt)
|
||||
{
|
||||
|
||||
@@ -314,7 +314,10 @@ void CDVDsys_SetFile(CDVD_SourceType srctype, std::string newfile)
|
||||
const auto driveType = GetDriveType(StringUtil::UTF8StringToWideString(root).c_str());
|
||||
if (driveType == DRIVE_REMOVABLE)
|
||||
{
|
||||
Host::AddIconOSDMessage("RemovableDriveWarning", ICON_FA_EXCLAMATION_TRIANGLE, "Game disc location is on a removable drive, performance issues such as jittering and freezing may occur.", Host::OSD_WARNING_DURATION);
|
||||
Host::AddIconOSDMessage("RemovableDriveWarning", ICON_FA_EXCLAMATION_TRIANGLE,
|
||||
TRANSLATE_SV("CDVD", "Game disc location is on a removable drive, performance issues such as jittering "
|
||||
"and freezing may occur."),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -421,7 +424,8 @@ bool DoCDVDopen()
|
||||
cdvdTD td;
|
||||
CDVD->getTD(0, &td);
|
||||
|
||||
Host::AddKeyedOSDMessage("BlockDumpCreate", fmt::format("Saving CDVD block dump to '{}'.", temp), Host::OSD_INFO_DURATION);
|
||||
Host::AddKeyedOSDMessage("BlockDumpCreate",
|
||||
fmt::format(TRANSLATE_SV("CDVD", "Saving CDVD block dump to '{}'."), temp), Host::OSD_INFO_DURATION);
|
||||
|
||||
if (blockDumpFile.Create(std::move(temp), 2))
|
||||
{
|
||||
|
||||
@@ -591,7 +591,7 @@ void cdrReadInterrupt()
|
||||
if (cdr.RErr == -1)
|
||||
{
|
||||
DevCon.Warning("CD err");
|
||||
memzero(cdr.Transfer);
|
||||
std::memset(cdr.Transfer, 0, sizeof(cdr.Transfer));
|
||||
cdr.Stat = DiskError;
|
||||
cdr.StatP |= STATUS_ERROR;
|
||||
cdr.Result[0] = cdr.StatP;
|
||||
@@ -1107,7 +1107,7 @@ void psxDma3(u32 madr, u32 bcr, u32 chcr)
|
||||
|
||||
void cdrReset()
|
||||
{
|
||||
memzero(cdr);
|
||||
std::memset(&cdr, 0, sizeof(cdr));
|
||||
cdr.CurTrack = 1;
|
||||
cdr.File = 1;
|
||||
cdr.Channel = 1;
|
||||
|
||||
@@ -202,6 +202,7 @@ set(pcsx2Headers
|
||||
LogSink.h
|
||||
PINE.h
|
||||
Mdec.h
|
||||
MTGS.h
|
||||
MTVU.h
|
||||
Memory.h
|
||||
MemoryCardFile.h
|
||||
|
||||
+1
-1
@@ -165,7 +165,7 @@ namespace
|
||||
|
||||
void resetCache()
|
||||
{
|
||||
memzero(cache);
|
||||
std::memset(&cache, 0, sizeof(cache));
|
||||
}
|
||||
|
||||
static bool findInCache(const CacheSet& set, uptr ppf, int* way)
|
||||
|
||||
+5
-5
@@ -1,5 +1,5 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
* 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-
|
||||
@@ -26,16 +26,16 @@
|
||||
|
||||
#include "GS.h"
|
||||
#include "GS/GS.h"
|
||||
#include "VUmicro.h"
|
||||
#include "MTGS.h"
|
||||
#include "PerformanceMetrics.h"
|
||||
#include "Patch.h"
|
||||
|
||||
#include "ps2/HwInternal.h"
|
||||
#include "Sio.h"
|
||||
#include "SPU2/spu2.h"
|
||||
#include "PAD/Host/PAD.h"
|
||||
#include "Recording/InputRecording.h"
|
||||
#include "VMManager.h"
|
||||
#include "VUmicro.h"
|
||||
|
||||
using namespace Threading;
|
||||
|
||||
@@ -164,7 +164,7 @@ void rcntInit()
|
||||
|
||||
g_FrameCount = 0;
|
||||
|
||||
memzero(counters);
|
||||
std::memset(counters, 0, sizeof(counters));
|
||||
|
||||
for (i=0; i<4; i++) {
|
||||
counters[i].rate = 2;
|
||||
@@ -538,7 +538,7 @@ static __fi void DoFMVSwitch()
|
||||
RendererSwitched = GSConfig.UseHardwareRenderer();
|
||||
|
||||
// we don't use the sw toggle here, because it'll change back to auto if set to sw
|
||||
GetMTGS().SwitchRenderer(new_fmv_state ? GSRendererType::SW : EmuConfig.GS.Renderer, false);
|
||||
MTGS::SwitchRenderer(new_fmv_state ? GSRendererType::SW : EmuConfig.GS.Renderer, false);
|
||||
}
|
||||
else
|
||||
RendererSwitched = false;
|
||||
|
||||
@@ -222,6 +222,9 @@ private:
|
||||
bool IO_SparseZero(u64 byteOffset, u64 byteSize);
|
||||
void IO_SparseCacheUpdateLocation(u64 Offset);
|
||||
void IO_SparseCacheLoad();
|
||||
#if defined(PCSX2_DEBUG) || defined(PCSX2_DEVBUILD)
|
||||
void IO_SparseCacheAssertFileZeros(u64 hddSparseBlockSizeReadable);
|
||||
#endif
|
||||
bool IsAllZero(const void* data, size_t len);
|
||||
void HDD_ReadAsync(void (ATA::*drqCMD)());
|
||||
void HDD_ReadSync(void (ATA::*drqCMD)());
|
||||
|
||||
+23
-23
@@ -1,5 +1,5 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
* 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-
|
||||
@@ -46,15 +46,15 @@ void ATA::WritePaddedString(u8* data, int* index, std::string value, u32 len)
|
||||
|
||||
void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
{
|
||||
const u16 sectorSize = 512;
|
||||
constexpr u16 sectorSize = 512;
|
||||
DevCon.WriteLn("DEV9: HddSize : %i", sizeSectors * sectorSize / (1024 * 1024));
|
||||
const u64 nbSectors = sizeSectors;
|
||||
DevCon.WriteLn("DEV9: nbSectors : %i", nbSectors);
|
||||
|
||||
memset(&identifyData, 0, sizeof(identifyData));
|
||||
//Defualt CHS translation
|
||||
const u16 defHeads = 16;
|
||||
const u16 defSectors = 63;
|
||||
constexpr u16 defHeads = 16;
|
||||
constexpr u16 defSectors = 63;
|
||||
u64 cylinderslong = std::min<u64>(nbSectors, 16514064) / defHeads / defSectors;
|
||||
const u16 defCylinders = (u16)std::min<u64>(cylinderslong, UINT16_MAX);
|
||||
|
||||
@@ -94,7 +94,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
//Default Num of heads (Retired)
|
||||
WriteUInt16(identifyData, &index, defHeads); //word 3
|
||||
//Number of unformatted bytes per track (Retired)
|
||||
WriteUInt16(identifyData, &index, (u16)(sectorSize * defSectors)); //word 4
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(sectorSize * defSectors)); //word 4
|
||||
//Number of unformatted bytes per sector (Retired)
|
||||
WriteUInt16(identifyData, &index, sectorSize); //word 5
|
||||
//Default Number of sectors per track (Retired)
|
||||
@@ -133,7 +133,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
//Capabilities (0-Shall be set to one to indicate a device specific Standby timer value minimum)
|
||||
index += 1 * 2; //word 50
|
||||
//PIO data transfer cycle timing mode (Obsolete)
|
||||
WriteUInt16(identifyData, &index, (u8)((pioMode > 2 ? pioMode : 2) << 8)); //word 51
|
||||
WriteUInt16(identifyData, &index, static_cast<u8>((pioMode > 2 ? pioMode : 2) << 8)); //word 51
|
||||
//DMA data transfer cycle timing mode (Obsolete)
|
||||
WriteUInt16(identifyData, &index, 0); //word 52
|
||||
//
|
||||
@@ -150,23 +150,23 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
//Number of current sectors per track
|
||||
WriteUInt16(identifyData, &index, curSectors); //word 56
|
||||
//Current capacity in sectors
|
||||
WriteUInt32(identifyData, &index, (u32)curOldsize); //word 57-58
|
||||
WriteUInt32(identifyData, &index, static_cast<u32>(curOldsize)); //word 57-58
|
||||
//PIO READ/WRITE Multiple setting
|
||||
/*
|
||||
* bit 7-0: Current setting for number of logical sectors that shall be transferred per DRQ
|
||||
* data block on READ/WRITE Multiple commands
|
||||
* bit 8: Multiple sector setting is valid
|
||||
*/
|
||||
WriteUInt16(identifyData, &index, (u16)(curMultipleSectorsSetting | (1 << 8))); //word 59
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(curMultipleSectorsSetting | (1 << 8))); //word 59
|
||||
//Total number of user addressable logical sectors
|
||||
WriteUInt32(identifyData, &index, (u32)(nbSectors < 268435456 ? nbSectors : 268435456)); //word 60-61
|
||||
WriteUInt32(identifyData, &index, static_cast<u32>(nbSectors < 268435456 ? nbSectors : 268435456)); //word 60-61
|
||||
//DMA modes
|
||||
/*
|
||||
* bits 0-7: Singleword modes supported (0,1,2)
|
||||
* bits 8-15: Transfer mode active
|
||||
*/
|
||||
if (sdmaMode > 0)
|
||||
WriteUInt16(identifyData, &index, (u16)(0x07 | (1 << (sdmaMode + 8)))); //word 62
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(0x07 | (1 << (sdmaMode + 8)))); //word 62
|
||||
else
|
||||
WriteUInt16(identifyData, &index, 0x07); //word 62
|
||||
//DMA Modes
|
||||
@@ -175,7 +175,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bits 8-15: Transfer mode active
|
||||
*/
|
||||
if (mdmaMode > 0)
|
||||
WriteUInt16(identifyData, &index, (u16)(0x07 | (1 << (mdmaMode + 8)))); //word 63
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(0x07 | (1 << (mdmaMode + 8)))); //word 63
|
||||
else
|
||||
WriteUInt16(identifyData, &index, 0x07); //word 63
|
||||
//Bit 0-7-PIO modes supported (0,1,2,3,4)
|
||||
@@ -220,7 +220,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bit 14: NOP
|
||||
* bit 15: (Obsolete)
|
||||
*/
|
||||
WriteUInt16(identifyData, &index, (u16)((1 << 14) | (1 << 5) | /*(1 << 1) | (1 << 10) |*/ 1)); //word 82
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((1 << 14) | (1 << 5) | /*(1 << 1) | (1 << 10) |*/ 1)); //word 82
|
||||
//Supported Feature Sets (83)
|
||||
/*
|
||||
* bit 0: DOWNLOAD MICROCODE
|
||||
@@ -239,7 +239,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bit 13: FLUSH CACHE EXT
|
||||
* bit 14: 1
|
||||
*/
|
||||
WriteUInt16(identifyData, &index, (u16)((1 << 14) | (1 << 13) | (1 << 12) /*| (1 << 8)*/ | ((lba48Supported ? 1 : 0) << 10))); //word 83
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((1 << 14) | (1 << 13) | (1 << 12) /*| (1 << 8)*/ | ((lba48Supported ? 1 : 0) << 10))); //word 83
|
||||
//Supported Feature Sets (84)
|
||||
/*
|
||||
* bit 0: Smart error logging
|
||||
@@ -256,19 +256,19 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bit 13: IDLE IMMEDIATE with UNLOAD FEATURE
|
||||
* bit 14: 1
|
||||
*/
|
||||
WriteUInt16(identifyData, &index, (u16)((1 << 14) | (1 << 1) | 1)); //word 84
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((1 << 14) | (1 << 1) | 1)); //word 84
|
||||
//Command set/feature enabled/supported (See word 82)
|
||||
WriteUInt16(identifyData, &index, (u16)((fetSmartEnabled << 0) | (fetSecurityEnabled << 1) | (fetWriteCacheEnabled << 5) | (fetHostProtectedAreaEnabled << 10) | (1 << 14))); //Fixed //word 85
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((fetSmartEnabled << 0) | (fetSecurityEnabled << 1) | (fetWriteCacheEnabled << 5) | (fetHostProtectedAreaEnabled << 10) | (1 << 14))); //Fixed //word 85
|
||||
//Command set/feature enabled/supported (See word 83)
|
||||
// clang-format off
|
||||
WriteUInt16(identifyData, &index, (u16)(
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(
|
||||
/*(1 << 8) | //SET MAX */
|
||||
((lba48Supported ? 1 : 0) << 10) | //Fixed
|
||||
(1 << 12) | //Fixed
|
||||
(1 << 13))); //Fixed //word 86
|
||||
//Command set/feature enabled/supported (See word 84)
|
||||
WriteUInt16(identifyData, &index, (u16)((1 << 14) | (1 << 1) | 1));
|
||||
WriteUInt16(identifyData, &index, (u16)(
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((1 << 14) | (1 << 1) | 1));
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(
|
||||
(1) | //Fixed
|
||||
((1) << 1))); //Fixed //word 87
|
||||
// clang-format on
|
||||
@@ -278,7 +278,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bits 8-15: Transfer mode active
|
||||
*/
|
||||
if (udmaMode > 0)
|
||||
WriteUInt16(identifyData, &index, (u16)(0x7f | (1 << (udmaMode + 8)))); //word 88
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(0x7f | (1 << (udmaMode + 8)))); //word 88
|
||||
else
|
||||
WriteUInt16(identifyData, &index, 0x7f); //word 88
|
||||
//Time required for security erase unit completion
|
||||
@@ -306,7 +306,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bit 14: 1
|
||||
*/
|
||||
index = 93 * 2;
|
||||
WriteUInt16(identifyData, &index, (u16)(1 | (1 << 14) | 0x2000)); //word 93
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>(1 | (1 << 14) | 0x2000)); //word 93
|
||||
//Vendor’s recommended acoustic management value.
|
||||
//94
|
||||
//Stream Minimum Request Size
|
||||
@@ -319,7 +319,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
//98-99
|
||||
//Total Number of User Addressable Sectors for the 48-bit Address feature set.
|
||||
index = 100 * 2;
|
||||
WriteUInt64(identifyData, &index, (u16)nbSectors);
|
||||
WriteUInt64(identifyData, &index, static_cast<u16>(nbSectors));
|
||||
index -= 2;
|
||||
WriteUInt16(identifyData, &index, 0); //truncate to 48bits
|
||||
//Streaming Transfer Time - PIO
|
||||
@@ -334,7 +334,7 @@ void ATA::CreateHDDinfo(u64 sizeSectors)
|
||||
* bit 14: 1
|
||||
*/
|
||||
index = 106 * 2;
|
||||
WriteUInt16(identifyData, &index, (u16)((1 << 14) | 0));
|
||||
WriteUInt16(identifyData, &index, static_cast<u16>((1 << 14) | 0));
|
||||
//Inter-seek delay for ISO-7779acoustic testing in microseconds
|
||||
//107
|
||||
//WNN
|
||||
@@ -384,7 +384,7 @@ void ATA::CreateHDDinfoCsum() //Is this correct?
|
||||
counter += 0xA5;
|
||||
|
||||
identifyData[510] = 0xA5;
|
||||
identifyData[511] = (u8)(255 - counter + 1);
|
||||
identifyData[511] = static_cast<u8>(255 - counter + 1);
|
||||
counter = 0;
|
||||
|
||||
for (int i = 0; i < (512); i++)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
* 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-
|
||||
@@ -381,35 +381,35 @@ void ATA::Write16(u32 addr, u16 value)
|
||||
//DevCon.WriteLn("DEV9: *ATA_R_FEATURE 16bit write at address %x, value %x", addr, value);
|
||||
ClearHOB();
|
||||
regFeatureHOB = regFeature;
|
||||
regFeature = (u8)value;
|
||||
regFeature = static_cast<u8>(value);
|
||||
break;
|
||||
case ATA_R_NSECTOR:
|
||||
//DevCon.WriteLn("DEV9: *ATA_R_NSECTOR 16bit write at address %x, value %x", addr, value);
|
||||
ClearHOB();
|
||||
regNsectorHOB = regNsector;
|
||||
regNsector = (u8)value;
|
||||
regNsector = static_cast<u8>(value);
|
||||
break;
|
||||
case ATA_R_SECTOR:
|
||||
//DevCon.WriteLn("DEV9: *ATA_R_SECTOR 16bit write at address %x, value %x", addr, value);
|
||||
ClearHOB();
|
||||
regSectorHOB = regSector;
|
||||
regSector = (u8)value;
|
||||
regSector = static_cast<u8>(value);
|
||||
break;
|
||||
case ATA_R_LCYL:
|
||||
//DevCon.WriteLn("DEV9: *ATA_R_LCYL 16bit write at address %x, value %x", addr, value);
|
||||
ClearHOB();
|
||||
regLcylHOB = regLcyl;
|
||||
regLcyl = (u8)value;
|
||||
regLcyl = static_cast<u8>(value);
|
||||
break;
|
||||
case ATA_R_HCYL:
|
||||
//DevCon.WriteLn("DEV9: *ATA_R_HCYL 16bit write at address %x, value %x", addr, value);
|
||||
ClearHOB();
|
||||
regHcylHOB = regHcyl;
|
||||
regHcyl = (u8)value;
|
||||
regHcyl = static_cast<u8>(value);
|
||||
break;
|
||||
case ATA_R_SELECT:
|
||||
//DevCon.WriteLn("DEV9: *ATA_R_SELECT 16bit write at address %x, value %x", addr, value);
|
||||
regSelect = (u8)value;
|
||||
regSelect = static_cast<u8>(value);
|
||||
//bus->ifs[0].select = (val & ~0x10) | 0xa0;
|
||||
//bus->ifs[1].select = (val | 0x10) | 0xa0;
|
||||
break;
|
||||
@@ -502,18 +502,18 @@ s64 ATA::HDD_GetLBA()
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((s64)regHcylHOB << 40) |
|
||||
((s64)regLcylHOB << 32) |
|
||||
((s64)regSectorHOB << 24) |
|
||||
((s64)regHcyl << 16) |
|
||||
((s64)regLcyl << 8) |
|
||||
return (static_cast<s64>(regHcylHOB) << 40) |
|
||||
(static_cast<s64>(regLcylHOB) << 32) |
|
||||
(static_cast<s64>(regSectorHOB) << 24) |
|
||||
(static_cast<s64>(regHcyl) << 16) |
|
||||
(static_cast<s64>(regLcyl) << 8) |
|
||||
regSector;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
regStatus |= (u8)ATA_STAT_ERR;
|
||||
regError |= (u8)ATA_ERR_ABORT;
|
||||
regStatus |= static_cast<u8>(ATA_STAT_ERR);
|
||||
regError |= static_cast<u8>(ATA_ERR_ABORT);
|
||||
|
||||
Console.Error("DEV9: ATA: Tried to get LBA address while LBA mode disabled");
|
||||
//(c.Nh + h).Ns+(s-1)
|
||||
@@ -528,19 +528,19 @@ void ATA::HDD_SetLBA(s64 sectorNum)
|
||||
{
|
||||
if (!lba48)
|
||||
{
|
||||
regSelect = (u8)((regSelect & 0xf0) | (int)((sectorNum >> 24) & 0x0f));
|
||||
regHcyl = (u8)(sectorNum >> 16);
|
||||
regLcyl = (u8)(sectorNum >> 8);
|
||||
regSector = (u8)(sectorNum);
|
||||
regSelect = static_cast<u8>((regSelect & 0xf0) | static_cast<int>((sectorNum >> 24) & 0x0f));
|
||||
regHcyl = static_cast<u8>(sectorNum >> 16);
|
||||
regLcyl = static_cast<u8>(sectorNum >> 8);
|
||||
regSector = static_cast<u8>(sectorNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
regSector = (u8)sectorNum;
|
||||
regLcyl = (u8)(sectorNum >> 8);
|
||||
regHcyl = (u8)(sectorNum >> 16);
|
||||
regSectorHOB = (u8)(sectorNum >> 24);
|
||||
regLcylHOB = (u8)(sectorNum >> 32);
|
||||
regHcylHOB = (u8)(sectorNum >> 40);
|
||||
regSector = static_cast<u8>(sectorNum);
|
||||
regLcyl = static_cast<u8>(sectorNum >> 8);
|
||||
regHcyl = static_cast<u8>(sectorNum >> 16);
|
||||
regSectorHOB = static_cast<u8>(sectorNum >> 24);
|
||||
regLcylHOB = static_cast<u8>(sectorNum >> 32);
|
||||
regHcylHOB = static_cast<u8>(sectorNum >> 40);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -560,35 +560,27 @@ bool ATA::HDD_CanSeek()
|
||||
|
||||
bool ATA::HDD_CanAccess(int* sectors)
|
||||
{
|
||||
s64 lba;
|
||||
s64 posStart;
|
||||
s64 posEnd;
|
||||
s64 maxLBA;
|
||||
|
||||
maxLBA = std::min<s64>(EmuConfig.DEV9.HddSizeSectors, hddImageSize / 512) - 1;
|
||||
s64 maxLBA = std::min<s64>(EmuConfig.DEV9.HddSizeSectors, hddImageSize / 512) - 1;
|
||||
if ((regSelect & 0x40) == 0) //CHS mode
|
||||
maxLBA = std::min<s64>(maxLBA, curCylinders * curHeads * curSectors);
|
||||
|
||||
lba = HDD_GetLBA();
|
||||
if (lba == -1)
|
||||
const s64 posStart = HDD_GetLBA();
|
||||
if (posStart == -1)
|
||||
return false;
|
||||
|
||||
//DevCon.WriteLn("DEV9: LBA :%i", lba);
|
||||
posStart = lba;
|
||||
|
||||
if (posStart > maxLBA)
|
||||
{
|
||||
*sectors = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
posEnd = posStart + *sectors;
|
||||
|
||||
const s64 posEnd = posStart + *sectors;
|
||||
if (posEnd > maxLBA)
|
||||
{
|
||||
const s64 overshoot = posEnd - maxLBA;
|
||||
s64 space = *sectors - overshoot;
|
||||
*sectors = (int)space;
|
||||
*sectors = static_cast<int>(space);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user