Compare commits

...
66 Commits
Author SHA1 Message Date
Stenzek 19cf29e5cf CI/Linux: Push to Flathub beta 2023-06-27 01:50:15 +10:00
refractionpcsx2 d51d51b3cc Memcard: Stop Folder memcards double reindexing 2023-06-26 14:45:50 +01:00
refractionpcsx2 c40e132284 SIO/MCD: hugely improved memcard swapping + reinsertion 2023-06-26 14:45:50 +01:00
Connor McLaughlin f8f54bd892 Qt: Adjust cache folder help text 2023-06-26 20:40:18 +10:00
Stenzek 5302cdcf2b Qt: Remove renderer title from top group box
Save a little vertical space.
2023-06-26 17:52:39 +10:00
Stenzek 8fe9282bd9 Qt: De-duplicate AppIcon 2023-06-26 17:52:39 +10:00
refractionpcsx2 07ed213b1f GameDB: Add blending for Clannad and Clover Heart's VNs 2023-06-25 17:08:22 +01:00
JordanTheToasterandrefractionpcsx2 8a1b8d2091 GameDB: Add missing WRC 3 serial
God help me.
2023-06-25 15:30:36 +01:00
IlDucciandConnor McLaughlin 034ef5692c Qt: Updating language names
Correcting or expanding language names for both variants of Spanish and Portuguese.
2023-06-25 21:14:46 +10:00
Stenzek b9b9405c35 Qt: Hook up current translations 2023-06-25 16:45:37 +10:00
JordanTheToasterandrefractionpcsx2 ca8d4f9ff0 GameDB: Add missing WRC II Fixes
Adds missing demos and fixes to fix SPS on demos.
2023-06-25 04:09:43 +01:00
Stenzek 0dc39a66d7 GS: Use ResetGS() for CSR resets 2023-06-25 12:54:14 +10:00
Stenzek 55e73bb4b9 MTGS: Convert to namespace 2023-06-25 12:54:14 +10:00
refractionpcsx2 6f9164b986 IPU: Slow down BDEC and IDEC so they don't outstrip DMA data writes 2023-06-25 01:05:42 +01:00
TellowKrinkleandrefractionpcsx2 8d27c32418 Updater:Mac: Delay launch of new application until the old one exits
Prevents duplicate dock icons
2023-06-24 22:28:56 +01:00
refractionpcsx2 a17a7ad1ec UI: Expand Achievement login box height slightly 2023-06-24 20:06:53 +01:00
refractionpcsx2 585868f930 GS/Cleanup: Remove some remaining eewrite references 2023-06-24 18:29:28 +01:00
refractionpcsx2 795d0a6682 GS: Double buffer the EE transfer queue 2023-06-24 18:29:28 +01:00
refractionpcsx2 3c0b7f7724 IPU: Redo FIFO transfers, plus small IPU_TO DMA tweak 2023-06-24 18:11:46 +01:00
Stenzek ff23f87010 FullscreenUI: Add patches/cheats to game settings 2023-06-25 01:52:56 +10:00
Stenzek 989fca99c6 FullscreenUI: Add Disable VS expand option 2023-06-25 01:52:56 +10:00
KamFretoZandConnor McLaughlin b44e10df3c Qt: Removes hyperlink color override from Rcheevos 2023-06-24 22:10:33 +10:00
Stenzek c9e9f92c93 Qt: Add Setup Wizard 2023-06-24 15:18:24 +10:00
refractionpcsx2 bb1a366989 GS/HW: Update drawn area and full valid bits on hardware move 2023-06-24 04:50:21 +01:00
refractionpcsx2 1458511756 Config: Don't apply upscaling fixes from GameDB in native
Also removed some stuff we no longer need
2023-06-24 04:49:44 +01:00
JordanTheToasterandrefractionpcsx2 3ebfc81727 GameDB: Spartan Total Warrior Fixes
Fixes for missing post processing.
2023-06-24 01:48:20 +01:00
refractionpcsx2 8d0d59175d DEV9: Fix typo preventing linux debug builds 2023-06-24 01:42:02 +01:00
Tyler WildingandGitHub a46b3f2ed9 New Crowdin updates (#9030) 2023-06-23 15:08:16 -04:00
TheLastRarandrefractionpcsx2 cb224789e2 DEV9: Deduplicate sparse file assert code 2023-06-23 20:05:50 +01:00
Stenzek cd4d829f9f CI/Linux: Use clang 16 for AppImage 2023-06-24 02:10:35 +10:00
refractionpcsx2 faa25f2a96 GameDB: Add minimum blending level for Snow (SLPS 25342 & 25332) 2023-06-23 14:46:35 +01:00
refractionpcsx2 36e8f49b63 GameDB: Add Partial Target Invalidation to Princess Maker 2 2023-06-23 13:42:04 +01:00
refractionpcsx2 e2a4657777 GS/HW: Improve full dirty rect clears. Remember new EE draws.
Rocky Legends transfers the new frame sometimes just before vsync, and it was getting lost.
2023-06-23 13:42:04 +01:00
refractionpcsx2 261b3f7e5c GS/HW: Remove eewrite from invalidatevideomem, allow age on frame 2023-06-23 13:42:04 +01:00
Stenzekandrefractionpcsx2 d6ba2aa76a CI: Prevent double builds on pushes to pcsx2 repo 2023-06-23 13:20:18 +01:00
refractionpcsx2 fb135a87ab GameDB: Fix CLUT colors for Kazuku Keikaku (SLPM-65889) 2023-06-23 13:17:14 +01:00
Stenzekandrefractionpcsx2 286fabaddc MemoryCardFolder: Fix saved message displaying junk 2023-06-23 11:50:39 +01:00
Stenzekandrefractionpcsx2 a79ad44370 Qt: Fix crash when right clicking volume slider 2023-06-23 11:42:23 +01:00
Stenzek 2046a9b414 GS: Use 32-bit vertex positions for culling
More accurate, stops it passing through vertices which are off-screen
and coordinates overflowed.

Differences versus current have been manually verified to be correct.
2023-06-23 19:54:46 +10:00
lightningterror c77d8b3709 DEV9: Cleanup ATA. 2023-06-23 00:52:15 +02:00
lightningterror 7b428bb6b0 DEV9: Cleanup dev9 base tree. 2023-06-23 00:52:15 +02:00
Tyler WildingandGitHub 6986030cd9 ci: don't build the localization branch on push (#9031) 2023-06-22 17:33:10 -04:00
refractionpcsx2 cc9b9a1935 UI: Fix some typo's and casing in UI 2023-06-22 18:42:03 +01:00
JordanTheToasterandrefractionpcsx2 2b7eeba55c GameDB: Matrix Path Of Neo Fixes
Fixes broken post processing by using autoflush.
2023-06-22 10:13:50 +01:00
Stenzek c87dd99824 GS/HW: Remove targets which lie completely within the invalidate range
Fixes part of Burnout 3's car reflections.
2023-06-22 19:12:22 +10:00
Stenzek fbd837eadb GS/HW: Improve draw rect accuracy 2023-06-22 19:12:22 +10:00
Stenzek 7c9c8e197c Common: Replace MemsetFast routines with C memset
And associated cleanup.

On most compilers these days, it'll either inline the memset with vector
fills or rep stosq, or outline with a call to memset.

I trust the compiler is probably going to make a better decision here,
than manual SSE intrinsics.

Ends up a couple of percent faster in FMV decoding.
2023-06-22 19:11:57 +10:00
Stenzek 0366929231 Flatpak: Add screenshots 2023-06-22 18:32:51 +10:00
KamFretoZandrefractionpcsx2 10d5261153 Updater: Clarify the error message when the program being runs directly 2023-06-21 17:32:24 +01:00
refractionpcsx2 3278856764 GS/HW: Adjust BurnoutGames CRC to allow preloading of undercarriage 2023-06-21 15:11:09 +01:00
refractionpcsx2 ff5a9e0ea1 GS/HW: Add target check safety to FFX and Sonic Unleashed CRC hacks 2023-06-21 15:11:09 +01:00
lightningterror 59b0c09443 GS-hw: Fix Wunused-variable warning. 2023-06-21 00:19:26 +02:00
lightningterror ae772e6a74 Elfheader: Fix Wsign-compare warnings. 2023-06-21 00:19:26 +02:00
RedPanda4552andrefractionpcsx2 0a58783a86 Translations: Fix missing context marker on Manual Hardware Fixes string
Fixes CTD when OSD messages print
2023-06-20 21:19:07 +01:00
refractionpcsx2 6f6de13fd4 GameDB: Add VU Clamping to Motorstorm 2023-06-20 20:30:23 +01:00
refractionpcsx2 89dcb78efa GS/CRC: Fix Ar Tonelico 2 CRC hack to check DS exists 2023-06-20 20:14:13 +01:00
Stenzek 703c02c32c Qt: Update base (en) translation 2023-06-20 22:46:00 +10:00
Stenzek adcfca4db3 Qt: Localization support 2023-06-20 22:46:00 +10:00
Stenzek c359223fd4 ImGuiManager: Localization support 2023-06-20 22:46:00 +10:00
Stenzek c4c7d26bb3 Host: Remove now-unused Add[Keyed]FormattedOSDMessage 2023-06-20 22:46:00 +10:00
Stenzek c06bc16b22 Misc: Mark core strings for translation 2023-06-20 22:46:00 +10:00
Stenzek f7bc05c735 Host: Add message translation functions 2023-06-20 22:46:00 +10:00
Stenzek ff02d41992 USB: Make GetDeviceTypes() return C strings 2023-06-20 22:46:00 +10:00
Stenzek ec180e2771 Hotkeys: Fix adjust target speed 2023-06-20 20:36:47 +10:00
Stenzek dffa9e0b8c VMManager: Fix WS patch not applying auto aspect ratio 2023-06-20 20:36:47 +10:00
Stenzek 497e06bcd9 VMManager: Close memcards on boot failure
And get rid of some double shutdowns.
2023-06-20 20:36:47 +10:00
210 changed files with 365299 additions and 4388 deletions
+2 -2
View File
@@ -2,8 +2,8 @@ name: 📝 Validate GameDB
on:
push:
branches:
- master
branches-ignore:
- "l10n_master"
paths:
- '**/GameIndex.yaml'
pull_request:
+13 -1
View File
@@ -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 }}
+4 -2
View File
@@ -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"
+2 -2
View File
@@ -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
+3 -2
View File
@@ -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>
+9 -2
View File
@@ -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
+84 -9
View File
@@ -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"
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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];
}
}
-18
View File
@@ -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();
-95
View File
@@ -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));
}
+50
View File
@@ -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);
}
}
+2 -1
View File
@@ -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>
+3
View File
@@ -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">
-4
View File
@@ -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);
+6 -6
View File
@@ -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();
+12 -7
View File
@@ -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
View File
@@ -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
View File
@@ -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
//////////////////////////////////////////////////////////////////////////
+2 -1
View File
@@ -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;
+24
View File
@@ -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
View File
@@ -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;
+1
View File
@@ -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
View File
@@ -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>&amp;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>&amp;About PCSX2...</string>
</property>
</action>
<action name="actionChangeDisc">
+84 -44
View File
@@ -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)
+9
View File
@@ -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();
+3 -3
View File
@@ -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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;PCSX2 uses RetroAchievements as an achievement database and for tracking progress. To use achievements, please sign up for an account at &lt;a href=&quot;https://retroachievements.org/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#4169e1;&quot;&gt;retroachievements.org&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;To view the achievement list in-game, press the hotkey for &lt;span style=&quot; font-weight:600;&quot;&gt;Open Pause Menu&lt;/span&gt; and select &lt;span style=&quot; font-weight:600;&quot;&gt;Achievements&lt;/span&gt; from the menu.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;PCSX2 uses RetroAchievements as an achievement database and for tracking progress. To use achievements, please sign up for an account at &lt;a href=&quot;https://retroachievements.org/&quot;&gt;retroachievements.org&lt;/a&gt;.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;To view the achievement list in-game, press the hotkey for &lt;span style=&quot; font-weight:600;&quot;&gt;Open Pause Menu&lt;/span&gt; and select &lt;span style=&quot; font-weight:600;&quot;&gt;Achievements&lt;/span&gt; from the menu.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>
+10 -7
View File
@@ -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();
}
+13 -6
View File
@@ -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));
}
+15 -14
View File
@@ -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)) :
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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."));
+3 -3
View File
@@ -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>
+12 -5
View File
@@ -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[];
};
+506
View File
@@ -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;
}
}
}
+96
View File
@@ -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;
};
+669
View File
@@ -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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;h1 style=&quot; margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:xx-large; font-weight:700;&quot;&gt;Welcome to PCSX2!&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;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 &lt;a href=&quot;https://pcsx2.net/docs/usage/setup/&quot;&gt;https://pcsx2.net/docs/usage/setup/&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;By default, PCSX2 will connect to the server at &lt;a href=&quot;https://pcsx2.net/&quot;&gt;pcsx2.net&lt;/a&gt; to check for updates, and if available and confirmed, download update packages from &lt;a href=&quot;https://github.com/&quot;&gt;github.com&lt;/a&gt;. 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.&lt;/p&gt;&lt;p&gt;Please choose a language and theme to begin.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;PCSX2 requires a PS2 BIOS in order to run.&lt;/p&gt;&lt;p&gt;For legal reasons, you must obtain a BIOS &lt;strong&gt;from an actual PS2 unit that you own&lt;/strong&gt; (borrowing doesn't count).&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;p&gt;A guide for dumping your BIOS can be found at &lt;a href=&quot;https://pcsx2.net/docs/usage/setup/#how-to-dump-your-ps2-bios&quot;&gt;pcsx2.net&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;PCSX2 will automatically scan and identify games from the selected directories below, and populate the game list.&lt;br&gt;These games should be dumped from discs you own. Guides for dumping discs can be found at &lt;a href=&quot;https://pcsx2.net/docs/usage/setup/#dumping-ps2-discs-via-imgburn&quot;&gt;pcsx2.net&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Supported formats for dumps include:&lt;/p&gt;&lt;p&gt;&lt;ul&gt;&lt;li&gt;.bin/.iso (ISO Disc Images)&lt;/li&gt;&lt;li&gt;.mdf (Media Descriptor File)&lt;/li&gt;&lt;li&gt;.chd (Compressed Hunks of Data)&lt;/li&gt;&lt;li&gt;.cso (Compressed ISO)&lt;/li&gt;&lt;li&gt;.gz (Gzip Compressed ISO)&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;By default, PCSX2 will map your keyboard to the virtual PS2 controller.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:700;&quot;&gt;To use an external controller, you must map it first. &lt;/span&gt;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.&lt;/p&gt;&lt;p&gt;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.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;h1 style=&quot; margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:xx-large; font-weight:700;&quot;&gt;Setup Complete!&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;You are now ready to run games.&lt;/p&gt;&lt;p&gt;Further options are available under the settings menu. You can also use the Big Picture UI for navigation entirely with a gamepad.&lt;/p&gt;&lt;p&gt;We hope you enjoy using PCSX2.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&amp;Back</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="next">
<property name="text">
<string>&amp;Next</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancel">
<property name="text">
<string>&amp;Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="resources/resources.qrc"/>
<include location="resources/resources.qrc"/>
</resources>
<connections/>
</ui>
+320
View File
@@ -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 &it;
}
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
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)
+11
View File
@@ -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>
+21 -2
View File
@@ -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 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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)
{
+6 -2
View File
@@ -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))
{
+2 -2
View File
@@ -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;
+1
View File
@@ -202,6 +202,7 @@ set(pcsx2Headers
LogSink.h
PINE.h
Mdec.h
MTGS.h
MTVU.h
Memory.h
MemoryCardFile.h
+1 -1
View File
@@ -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
View File
@@ -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;
+3
View File
@@ -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
View File
@@ -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
//Vendors 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++)
+29 -37
View File
@@ -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