Compare commits

...

48 Commits

Author SHA1 Message Date
TheLastRar
ded55635c1 input-rec: Directly use recorded values for pressure sensitive buttons 2024-07-26 08:57:14 +02:00
PCSX2 Bot
c9b8874eb6 Qt: Update Base Translation 2024-07-25 20:17:06 -04:00
KamFretoZ
9172a1a6f8 Qt: Add prompt to missing ffmpeg warning 2024-07-25 09:26:58 -04:00
KamFretoZ
b2ac7afbcb Qt: Add Video Capture button to toolbar 2024-07-25 09:26:58 -04:00
TheTechnician27
dcfd663c19 Qt: Simplify compat line in GameSummaryWidget 2024-07-24 13:14:05 -04:00
TheLastRar
225f057a5c gitignore: Ignore bin* 2024-07-23 18:56:17 -04:00
TheLastRar
0017e33023 Deps: Remove hardcoded version for zstd 2024-07-23 18:56:17 -04:00
TheLastRar
76ced16f9e Deps: Update Windows ARM64 dependencies 2024-07-23 18:56:17 -04:00
TheLastRar
245937eb85 3rdparty/cpuinfo: Fix ARM64 project 2024-07-23 18:56:17 -04:00
TheTechnician27
3a72328d55 Qt: Add per-game link to PCSX2 Wiki pages on right-click 2024-07-23 18:51:44 -04:00
PCSX2 Bot
06bc0300c0 Qt: Update Base Translation 2024-07-22 22:17:10 +02:00
PCSX2 Bot
98dcf40967 PAD: Update to latest controller database. 2024-07-22 21:39:29 +02:00
Ty Lamontagne
6b61ffbb63 GS Capture: Allow selecting the pixel format based on the current codec 2024-07-22 10:56:30 -04:00
Ty Lamontagne
dd7eef723a GS Capture: Set ffmpeg channel layout 2024-07-22 10:56:30 -04:00
TellowKrinkle
328275cd45 GS:Capture: VAAPI support 2024-07-21 14:31:22 -04:00
PCSX2 Bot
a4f1431bcc Qt: Update Base Translation 2024-07-20 23:10:29 +02:00
lightningterror
473df8dad4 Debugger: Cleanup warnings and casts.
MemoryViewWidget.cpp
BreakpointModel.cpp
2024-07-20 23:09:51 +02:00
lightningterror
042959958e GS/HW: Use enum for blend_hw shader bit everywhere.
Leftover places I forgot to replace.
2024-07-20 15:20:07 +02:00
KamFretoZ
cd4de28b9e OSD: Add PCSX2 Version toggle 2024-07-19 12:46:35 -04:00
TheTechnician27
24a87c3fee Qt: Disable Single Frame GS Dump tool when not playing a game 2024-07-19 09:14:43 -04:00
GovanifY
17567b960f qt/MainWindow: for disable hide window if render to main is enabled
This fixes a crash on wayland (and possibly others)
2024-07-19 07:49:50 -04:00
JordanTheToaster
7a3d22ecdf GameDB: TC SOLA fixes 2024-07-18 19:55:28 -04:00
Ty Lamontagne
7e5016fdab linux/cmake: Allow libbacktrace to be disabled 2024-07-18 16:46:24 -04:00
PCSX2 Bot
47606400fa Qt: Update Base Translation 2024-07-18 19:11:09 +02:00
TheLastRar
d6076a6107 DEV9: Use const in ICMP session 2024-07-18 19:10:40 +02:00
TheLastRar
95c57462cc DEV9: FreeBSD/Mac Fixes for ICMP session 2024-07-18 19:10:40 +02:00
TheLastRar
48a1ec3531 DEV9: Use std::unique_ptr for tracking active pings 2024-07-18 19:10:40 +02:00
TheLastRar
9da3bccca2 DEV9: Use vector for ICMP temp buffer 2024-07-18 19:10:40 +02:00
TheLastRar
a1a92920b2 DEV9: Fix handling of ICMP timeout 2024-07-18 19:10:40 +02:00
TheLastRar
b6b775e44e DEV9: Fix IP_PayloadPtr::WriteBytes() 2024-07-18 19:10:40 +02:00
TheLastRar
5ea46ac076 DEV9: Use non-blocking sockets for ICMP Sessions on Unix 2024-07-18 19:10:40 +02:00
TheLastRar
ab008bf5d0 DEV9: Correct ICMP log messages 2024-07-18 19:10:40 +02:00
TheLastRar
54782cbf70 DEV9: Amend ICMP_Session comments 2024-07-18 19:10:40 +02:00
TheLastRar
3c7cff99f4 DEV9: Eliminate c-style casts from ICMP_Session 2024-07-18 19:10:40 +02:00
TheLastRar
f326e8775f DEV9: Correct spelling in ICMP session 2024-07-18 19:10:40 +02:00
AKuHAK
a2a711b1b3 Bios: add support for Rom2 up to 4Mb 2024-07-18 11:50:57 -04:00
PCSX2 Bot
dfb857b68f Qt: Update Base Translation 2024-07-17 22:20:21 +02:00
TheLastRar
ad64d88e7b Common: Fix FreeBSD build 2024-07-17 22:15:09 +02:00
TheTechnician27
cbd207d3f4 Qt: Add Emerald theme and fix palette var names 2024-07-17 21:56:46 +02:00
gooosedev
4bf8b23204 Debugger: change how the nullbyte (0x00) are displayed in the memoryview widget. 2024-07-17 21:55:04 +02:00
Ty Lamontagne
951780b43d Debugger: Implement little endian memory view support 2024-07-17 21:55:04 +02:00
TheTechnician27
84fe413635 GameDB: Ensure NativeScaling doesn't nag users at native res 2024-07-17 15:01:07 -04:00
Mrlinkwii
17aaa31362 github: mention to verify games if making an issue
[ci skip]
2024-07-17 14:58:37 -04:00
TheTechnician27
f943bdad98 Covers: Use serial for cover image names when selected individually 2024-07-17 14:58:04 -04:00
JordanTheToaster
09b2b6f949 GameDB: Fix up ATV ORF 3 fixes 2024-07-17 20:57:56 +02:00
L1Q
c46902c0f5 ReadMe: Fix BIOS dump link. (#11552) 2024-07-17 20:57:07 +02:00
PCSX2 Bot
c0dce9f64b PAD: Update to latest controller database. 2024-07-17 20:55:31 +02:00
Silent
cd3e11bff7 InputManager: Release settings lock before shutting down the input source 2024-07-13 07:29:26 -04:00
58 changed files with 2960 additions and 2492 deletions

View File

@@ -18,6 +18,8 @@ body:
Please make an effort to make sure your issue isn't already reported.
Please make sure your game is verified using the built-in game verifier.
Do not create issues involving software piracy of BIOS or ISO files, our rules specifically prohibit this and your issue will be closed.
### Please Avoid Issues Pertaining to the Following:

View File

@@ -47,13 +47,13 @@ set HARFBUZZ=8.3.1
set LIBJPEG=9f
set LIBPNG=1643
set LZ4=b8fd2d15309dd4e605070bd4486e26b6ef814e29
set QT=6.7.0
set QT=6.7.2
set QTMINOR=6.7
set SDL=SDL2-2.30.2
set WEBP=1.3.2
set SDL=SDL2-2.30.5
set WEBP=1.4.0
set ZLIB=1.3.1
set ZLIBSHORT=131
set ZSTD=1.5.5
set ZSTD=1.5.6
set SHADERC=2024.1
set SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
@@ -64,16 +64,17 @@ call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip b2bc56184ae37324bc4829fde7d3f9e6916866ad711ee85792e457547c9fd127 || goto error
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1643.zip fc466a1e638e635d6c66363bdf3f38555b81b0141d0b06ba45b49ccca327436d || goto error
call :downloadfile "jpegsr%LIBJPEG%.zip" https://ijg.org/files/jpegsr%LIBJPEG%.zip 6255da8c89e09d694e6800688c76145eb6870a76ac0d36c74fccd61b3940aafa || goto error
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 2a499607df669e40258e53d0ade8035ba4ec0175244869d1025d460562aa09b4 || goto error
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 61f873ec69e3be1b99535634340d5bde750b2e4447caa1db9f61be3fd49ab1e5 || goto error
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/%LZ4%.zip" 0c33119688d6b180c7e760b0acd70059222389cfd581632623784bee27e51a31 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" c5d78a9e0346c6695f03df8ba25e5e111a1e23c8aefa8372a1c5a0dd79acaf10 || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 3027fb990cb66436b5476b9dd17cd58f23b55a42eb1c1bcf9c7d78bca3ad7d63 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" f30065289517847d721467827ee446a5f606f6d1c750e166cbfb0ed5bf066c5e || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 882d1db58d35155bd92e4ed92b485d7d713b6aff0d7cf78655de0b414a980689 || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 93a31892ca8a4f38464e923328788ce3da881d82016fe18fa1ed12dd43ce486c || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 102ca62fa682c0d3e700ba89069fd3b6663b9f0c2890b058e97998b6e8971fb3 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 688d3da2bf7e887d0ba8e0f81c926119f85029544f4f6da8dea96db70f9d28e3 || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 488119aad60719a085a1e45c31641ac2406ef86fc088a3c99885c18e9d6b4bb9 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 8e736b02db7dd67dbe834d56503b242344ce85d3532da692f1812b30ccf80997 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 85a22142270a92be0dd0ab5d27cc53617b2a2f1a45fc0a3890024164032f8475 || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 9e15f1fdbd83e4123e733bff20aff1b45921c09056c3790fa42eb71d0a5cd01f || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" d1f25e0f68a1282feffdd5fe795a027ee5f16ad19e3b1fa2e04a51cea19110ec || goto error
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" c5c8daa1d40dabc51790c62a5b86af2b36dfc4e1a738ff10dc4a46ea4e68ee51 || goto error
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 3b1c3b46e416d36931efd34663122d7f51b550c87f74de2d38249516fe7d8be5 || goto error
call :downloadfile "zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" https://github.com/facebook/zstd/commit/fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch 675f144b11f8ab2424b64bed8ccdca5d3f35b9326046fa7a883925dd180f0651 || goto error
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 6c9f42ed6bf42750f5369b089909abfdcf0101488b4a1f41116d5159d00af8e7 || goto error
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 03ad8a6fa987af4653d0cfe6bdaed41bcf617f1366a151fb1574da75950cd3e8 || goto error
@@ -108,6 +109,7 @@ ninja -C build install || goto error
cd .. || goto error
echo Building libjpeg...
rmdir /S /Q "jpeg-%LIBJPEG%"
%SEVENZIP% x "jpegsr%LIBJPEG%.zip" || goto error
cd "jpeg-%LIBJPEG%" || goto error
%PATCH% -p1 < "%SCRIPTDIR%\libjpeg-cmake.patch" || goto error
@@ -155,8 +157,9 @@ cd .. || goto error
echo Building Zstandard...
rmdir /S /Q "zstd-%ZSTD%"
%SEVENZIP% x "-x^!zstd-1.5.5\tests\cli-tests\bin" "zstd-%ZSTD%.zip" || goto error
%SEVENZIP% x "-x^!zstd-%ZSTD%\tests\cli-tests\bin" "zstd-%ZSTD%.zip" || goto error
cd "zstd-%ZSTD%"
%PATCH% -p1 < "..\zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" || goto error
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DZSTD_BUILD_SHARED=ON -DZSTD_BUILD_STATIC=OFF -DZSTD_BUILD_PROGRAMS=OFF -B build -G Ninja build/cmake
cmake --build build --parallel || goto error
ninja -C build install || goto error

View File

@@ -154,7 +154,7 @@ cd .. || goto error
echo Building Zstandard...
rmdir /S /Q "zstd-%ZSTD%"
%SEVENZIP% x "-x^!zstd-1.5.6\tests\cli-tests\bin" "zstd-%ZSTD%.zip" || goto error
%SEVENZIP% x "-x^!zstd-%ZSTD%\tests\cli-tests\bin" "zstd-%ZSTD%.zip" || goto error
cd "zstd-%ZSTD%"
%PATCH% -p1 < "..\zstd-fd5f8106a58601a963ee816e6a57aa7c61fafc53.patch" || goto error
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DZSTD_BUILD_SHARED=ON -DZSTD_BUILD_STATIC=OFF -DZSTD_BUILD_PROGRAMS=OFF -B build -G Ninja build/cmake

58
.gitignore vendored
View File

@@ -63,35 +63,35 @@ oprofile_data/
*.kdev4
/.kdev4*
/bin/**/*.dll
/bin/**/*.dmp
/bin/**/*.exp
/bin/**/*.ilk
/bin/**/*.lib
/bin/**/*.pdb
/bin/pcsx2*
/bin/qt.conf
/bin/bios
/bin/cache
/bin/cheats
/bin/patches
/bin/covers
/bin/dumps
/bin/gamesettings
/bin/help
/bin/inis
/bin/inis/debuggersettings
/bin/logs
/bin/memcards
/bin/plugins
/bin/snaps
/bin/sstates
/bin/textures
/bin/translations
/bin/inputprofiles
/bin/videos
/bin/portable.ini
/bin/portable.txt
/bin*/**/*.dll
/bin*/**/*.dmp
/bin*/**/*.exp
/bin*/**/*.ilk
/bin*/**/*.lib
/bin*/**/*.pdb
/bin*/pcsx2*
/bin*/qt.conf
/bin*/bios
/bin*/cache
/bin*/cheats
/bin*/patches
/bin*/covers
/bin*/dumps
/bin*/gamesettings
/bin*/help
/bin*/inis
/bin*/inis/debuggersettings
/bin*/logs
/bin*/memcards
/bin*/plugins
/bin*/snaps
/bin*/sstates
/bin*/textures
/bin*/translations
/bin*/inputprofiles
/bin*/videos
/bin*/portable.ini
/bin*/portable.txt
# Manually added by user.
/bin/resources/patches.zip

View File

@@ -30,13 +30,16 @@
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\cache.c">
<ClCompile Include="src\arm\cache.c">
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\uarch.c">
<ClCompile Include="src\arm\uarch.c">
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\windows\init.c">
<ClCompile Include="src\arm\windows\init-by-logical-sys-info.c">
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="src\arm\windows\init.c">
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="deps\clog\src\clog.c" />
@@ -78,13 +81,13 @@
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\api.h">
<ClInclude Include="src\arm\api.h">
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\midr.h">
<ClInclude Include="src\arm\midr.h">
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\windows\api.h">
<ClInclude Include="src\arm\windows\windows-arm-init.h">
<ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild>
</ClInclude>
<ClInclude Include="deps\clog\include\clog.h" />

View File

@@ -63,13 +63,16 @@
<ClCompile Include="deps\clog\src\clog.c">
<Filter>clog</Filter>
</ClCompile>
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\cache.c">
<ClCompile Include="src\arm\cache.c">
<Filter>arm</Filter>
</ClCompile>
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\uarch.c">
<ClCompile Include="src\arm\uarch.c">
<Filter>arm</Filter>
</ClCompile>
<ClCompile Include="..\..\..\duckstation\dep\cpuinfo\src\arm\windows\init.c">
<ClCompile Include="src\arm\windows\init.c">
<Filter>arm\windows</Filter>
</ClCompile>
<ClCompile Include="src\arm\windows\init-by-logical-sys-info.c">
<Filter>arm\windows</Filter>
</ClCompile>
</ItemGroup>
@@ -99,13 +102,13 @@
<ClInclude Include="deps\clog\include\clog.h">
<Filter>clog</Filter>
</ClInclude>
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\api.h">
<ClInclude Include="src\arm\api.h">
<Filter>arm</Filter>
</ClInclude>
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\midr.h">
<ClInclude Include="src\arm\midr.h">
<Filter>arm</Filter>
</ClInclude>
<ClInclude Include="..\..\..\duckstation\dep\cpuinfo\src\arm\windows\api.h">
<ClInclude Include="src\arm\windows\windows-arm-init.h">
<Filter>arm\windows</Filter>
</ClInclude>
</ItemGroup>

View File

@@ -18,7 +18,7 @@ Installers and binaries for both stable and nightly builds are available from [o
PCSX2 supports Windows, Linux, and Mac platforms. Our [setup documentation page](https://pcsx2.net/docs/setup/requirements) contains additional details on software and hardware requirements.
Please note that a BIOS dump from a legitimately-owned PS2 console is required to use the emulator. For more information, visit [this page](https://pcsx2.net/docs/setup/gather/#how-to-dump-your-ps2-bios).
Please note that a BIOS dump from a legitimately-owned PS2 console is required to use the emulator. For more information, visit [this page](https://pcsx2.net/docs/setup/bios/).
## Contributing / Building

View File

@@ -11186,8 +11186,6 @@ SCUS-97436:
SCUS-97437:
name: "ATV Offroad Fury 3 [Demo]"
region: "NTSC-U"
speedHacks:
mtvu: 0 # Increases FPS drastically.
SCUS-97438:
name: "EyeToy - Antigrav [Demo]"
region: "NTSC-U"
@@ -11583,8 +11581,6 @@ SCUS-97513:
SCUS-97514:
name: "ATV Offroad Fury 3 [Greatest Hits]"
region: "NTSC-U"
speedHacks:
mtvu: 0 # Increases FPS drastically.
SCUS-97515:
name: "Hot Shots Golf FORE! [Greatest Hits]"
region: "NTSC-U"
@@ -12497,7 +12493,7 @@ SLED-51211:
gsHWFixes:
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
halfPixelOffset: 4 # Aligns bloom effect.
halfPixelOffset: 2 # Aligns bloom effect.
bilinearUpscale: 2 # Reduces color banding of the sun glare.
nativeScaling: 2 # Fixes post lighting.
roundModes:
@@ -12585,6 +12581,7 @@ SLED-51902:
halfPixelOffset: 3 # Fixes double image.
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
autoFlush: 1 # Fixes sun occlusion.
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
SLED-51921:
name: "Final Fantasy X-2 [Demo]"
region: "PAL-Unk"
@@ -15583,7 +15580,7 @@ SLES-51044:
gsHWFixes:
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
halfPixelOffset: 4 # Aligns bloom effect.
halfPixelOffset: 2 # Aligns bloom effect.
bilinearUpscale: 2 # Reduces color banding of the sun glare.
nativeScaling: 2 # Fixes post lighting.
roundModes:
@@ -17217,6 +17214,7 @@ SLES-51753:
halfPixelOffset: 3 # Fixes double image.
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
autoFlush: 1 # Fixes sun occlusion.
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
SLES-51754:
name: "True Crime - Streets of L.A."
region: "PAL-M5"
@@ -17226,6 +17224,7 @@ SLES-51754:
halfPixelOffset: 3 # Fixes double image.
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
autoFlush: 1 # Fixes sun occlusion.
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
SLES-51755:
name: "Disney/Pixar Finding Nemo"
region: "PAL-E"
@@ -20435,7 +20434,7 @@ SLES-52968:
gsHWFixes:
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
halfPixelOffset: 4 # Aligns bloom effect.
halfPixelOffset: 2 # Aligns bloom effect.
bilinearUpscale: 2 # Reduces color banding of the sun glare.
nativeScaling: 2 # Fixes post lighting.
roundModes:
@@ -22926,8 +22925,6 @@ SLES-53753:
SLES-53754:
name: "ATV Offroad Fury 3"
region: "PAL-M6"
speedHacks:
mtvu: 0 # Increases FPS drastically.
SLES-53755:
name: "Castlevania - Curse of Darkness"
region: "PAL-M5"
@@ -28951,7 +28948,7 @@ SLKA-25039:
gsHWFixes:
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
halfPixelOffset: 4 # Aligns bloom effect.
halfPixelOffset: 2 # Aligns bloom effect.
bilinearUpscale: 2 # Reduces color banding of the sun glare.
nativeScaling: 2 # Fixes post lighting.
roundModes:
@@ -40829,6 +40826,7 @@ SLPM-65729:
halfPixelOffset: 3 # Fixes double image.
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
autoFlush: 1 # Fixes sun occlusion.
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
SLPM-65730:
name: "ロックマンX8"
name-sort: "ろっくまんえっくす8"
@@ -42962,6 +42960,7 @@ SLPM-66098:
halfPixelOffset: 3 # Fixes double image.
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
autoFlush: 1 # Fixes sun occlusion.
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
SLPM-66099:
name: "Harukanaru Toki no Naka de 3 - Izayoiki [Premium Box-Triple Pack]"
region: "NTSC-J"
@@ -53682,7 +53681,7 @@ SLPS-25351:
gsHWFixes:
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
halfPixelOffset: 4 # Aligns bloom effect.
halfPixelOffset: 2 # Aligns bloom effect.
bilinearUpscale: 2 # Reduces color banding of the sun glare.
nativeScaling: 2 # Fixes post lighting.
roundModes:
@@ -60443,7 +60442,7 @@ SLUS-20497:
gsHWFixes:
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
halfPixelOffset: 4 # Aligns bloom effect.
halfPixelOffset: 2 # Aligns bloom effect.
bilinearUpscale: 2 # Reduces color banding of the sun glare.
nativeScaling: 2 # Fixes post lighting.
roundModes:
@@ -60712,6 +60711,7 @@ SLUS-20550:
halfPixelOffset: 3 # Fixes double image.
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
autoFlush: 1 # Fixes sun occlusion.
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
SLUS-20552:
name: "Grand Theft Auto - Vice City"
region: "NTSC-U"
@@ -69617,8 +69617,6 @@ SLUS-90009:
SLUS-97405:
name: "ATV Offroad Fury 3"
region: "NTSC-U"
speedHacks:
mtvu: 0 # Increases FPS drastically.
SRPM-70201:
name: "Space Venus Starring Morning Musume."
region: "NTSC-J"

View File

@@ -484,7 +484,7 @@
03000000f0250000c183000000000000,PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d9040000160f000000000000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000d620000011a7000000000000,PowerA Core Plus GameCube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000d620000011a7000000000000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -1468,7 +1468,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000c62400000053000000010000,PowerA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c62400003a54000001010000,PowerA 1428124-01,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000d620000011a7000011010000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000d620000011a7000011010000,PowerA Core Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -1690,6 +1690,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000005e040000ea02000011050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
050082795e040000e002000003090000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000ea0200000b050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000ea0200000d050000,Xbox One S Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000120b000001050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,

View File

@@ -23,6 +23,7 @@ if(UNIX AND NOT APPLE)
option(ENABLE_SETCAP "Enable networking capability for DEV9" OFF)
option(X11_API "Enable X11 support" ON)
option(WAYLAND_API "Enable Wayland support" ON)
option(USE_BACKTRACE "Enable libbacktrace support" ON)
endif()
if(UNIX)

View File

@@ -65,7 +65,10 @@ else()
find_package(Wayland REQUIRED Egl)
endif()
find_package(Libbacktrace REQUIRED)
if(USE_BACKTRACE)
find_package(Libbacktrace REQUIRED)
endif()
find_package(PkgConfig REQUIRED)
pkg_check_modules(DBUS REQUIRED dbus-1)
endif()

View File

@@ -167,10 +167,16 @@ else()
)
target_link_libraries(common PRIVATE
${DBUS_LINK_LIBRARIES}
libbacktrace::libbacktrace
X11::X11
X11::Xrandr
)
if(USE_BACKTRACE)
target_compile_definitions(common PRIVATE "HAS_LIBBACKTRACE=1")
target_link_libraries(common PRIVATE libbacktrace::libbacktrace)
endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
target_link_libraries(common PRIVATE cpuinfo)
endif()
endif()
set_source_files_properties(PrecompiledHeader.cpp PROPERTIES HEADER_FILE_ONLY TRUE)

View File

@@ -176,7 +176,7 @@ void CrashHandler::WriteDumpForCaller()
WriteMinidumpAndCallstack(nullptr);
}
#elif !defined(__APPLE__)
#elif !defined(__APPLE__) && defined(HAS_LIBBACKTRACE)
#include "FileSystem.h"
@@ -377,4 +377,4 @@ void CrashHandler::CrashSignalHandler(int signal, siginfo_t* siginfo, void* ctx)
std::abort();
}
#endif
#endif

View File

@@ -19,6 +19,10 @@
#include "fmt/core.h"
#if defined(__FreeBSD__)
#include "cpuinfo.h"
#endif
// FreeBSD does not have MAP_FIXED_NOREPLACE, but does have MAP_EXCL.
// MAP_FIXED combined with MAP_EXCL behaves like MAP_FIXED_NOREPLACE.
#if defined(__FreeBSD__) && !defined(MAP_FIXED_NOREPLACE)
@@ -142,6 +146,22 @@ size_t HostSys::GetRuntimePageSize()
size_t HostSys::GetRuntimeCacheLineSize()
{
#if defined(__FreeBSD__)
if (!cpuinfo_initialize())
return 0;
u32 max_line_size = 0;
for (u32 i = 0; i < cpuinfo_get_processors_count(); i++)
{
const u32 l1i = cpuinfo_get_processor(i)->cache.l1i->line_size;
const u32 l1d = cpuinfo_get_processor(i)->cache.l1d->line_size;
const u32 res = std::max<u32>(l1i, l1d);
max_line_size = std::max<u32>(max_line_size, res);
}
return static_cast<size_t>(max_line_size);
#else
int l1i = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
int l1d = sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
int res = (l1i > l1d) ? l1i : l1d;
@@ -160,6 +180,7 @@ size_t HostSys::GetRuntimeCacheLineSize()
}
return (res > 0) ? static_cast<size_t>(res) : 0;
#endif
}
SharedMemoryMappingArea::SharedMemoryMappingArea(u8* base_ptr, size_t size, size_t num_pages)

View File

@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0+
#include "MemoryViewWidget.h"
#include "common/Console.h"
#include "QtHost.h"
#include "QtUtils.h"
@@ -10,7 +11,6 @@
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
#include <QtGui/QClipboard>
#include <QtCore/QtEndian>
using namespace QtUtils;
@@ -66,48 +66,78 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
const u32 currentRowAddress = startAddress + (i * 0x10);
s32 valX = valuexAxis;
segmentXAxis[0] = valX;
u32 currentSegmentAddress = currentRowAddress;
for (int j = 0; j < 16; j++)
for (int j = 0; j < 16 / static_cast<s32>(displayType); j++)
{
const u32 currentByteAddress = currentRowAddress + j;
valX += charWidth;
const u32 thisSegmentsStart = currentRowAddress + (j * static_cast<s32>(displayType));
if (!(j % (s32)displayType))
{
valX += charWidth;
currentSegmentAddress = currentByteAddress;
}
segmentXAxis[j] = valX;
bool penDefault = false;
if ((selectedAddress & ~0xF) == currentRowAddress)
{
if (selectedAddress == currentByteAddress)
if (selectedAddress >= thisSegmentsStart && selectedAddress < (thisSegmentsStart + static_cast<s32>(displayType)))
{ // If the current byte and row we are drawing is selected
if (!selectedText)
{
s32 charsIntoSegment = ((selectedAddress - thisSegmentsStart) * 2) + ((selectedNibbleHI ? 0 : 1) ^ littleEndian);
if (littleEndian)
charsIntoSegment = (static_cast<s32>(displayType) * 2) - charsIntoSegment - 1;
painter.setPen(QColor::fromRgb(205, 165, 0)); // SELECTED NIBBLE LINE COLOUR
const QPoint lineStart(valX + (selectedNibbleHI ? 0 : charWidth) + 1, y + (rowHeight * i));
const QPoint lineStart(valX + (charsIntoSegment * charWidth) + 1, y + (rowHeight * i));
painter.drawLine(lineStart, lineStart + QPoint(charWidth - 3, 0));
}
painter.setPen(QColor::fromRgb(0xaa, 0x22, 0x22)); // SELECTED BYTE COLOUR
}
// If the current selected byte is in our current segment, highlight the entire segment
else if (displayType != MemoryViewType::BYTE &&
currentSegmentAddress <= selectedAddress && (selectedAddress <= (currentSegmentAddress + (s32)displayType - 1)))
{
painter.setPen(palette.highlight().color()); // SELECTED SEGMENT COLOUR
}
else
{
penDefault = true;
painter.setPen(palette.text().color()); // Default colour
}
}
else
{
penDefault = true;
painter.setPen(palette.text().color()); // Default colour
}
bool valid;
const u8 val = static_cast<u8>(m_cpu->read8(currentByteAddress, valid));
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "??");
valX += charWidth * 2;
switch (displayType)
{
case MemoryViewType::BYTE:
{
const u8 val = static_cast<u8>(m_cpu->read8(thisSegmentsStart, valid));
if (penDefault && val == 0)
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "??");
break;
}
case MemoryViewType::BYTEHW:
{
const u16 val = convertEndian<u16>(static_cast<u16>(m_cpu->read16(thisSegmentsStart, valid)));
if (penDefault && val == 0)
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "????");
break;
}
case MemoryViewType::WORD:
{
const u32 val = convertEndian<u32>(m_cpu->read32(thisSegmentsStart, valid));
if (penDefault && val == 0)
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "????????");
break;
}
case MemoryViewType::DWORD:
{
const u64 val = convertEndian<u64>(m_cpu->read64(thisSegmentsStart, valid));
if (penDefault && val == 0)
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "????????????????");
break;
}
}
valX += charWidth * 2 * static_cast<s32>(displayType);
}
// valX is our new X position after the hex values
@@ -146,12 +176,15 @@ void MemoryViewTable::SelectAt(QPoint pos)
const u32 selectedRow = (pos.y() - 2) / (rowHeight);
const s32 x = pos.x();
const s32 avgSegmentWidth = segmentXAxis[1] - segmentXAxis[0];
const u32 nibbleWidth = (avgSegmentWidth / (2 * (s32)displayType));
selectedAddress = (selectedRow * 0x10) + startAddress;
if (x <= segmentXAxis[0])
{
selectedText = false;
// The user clicked before the first segment
selectedText = false;
if (littleEndian)
selectedAddress += static_cast<s32>(displayType) - 1;
selectedNibbleHI = true;
}
else if (x > valuexAxis && x < textXAxis)
@@ -160,10 +193,13 @@ void MemoryViewTable::SelectAt(QPoint pos)
// The user clicked inside of the hexadecimal area
for (s32 i = 0; i < 16; i++)
{
if (i == 15 || (x >= segmentXAxis[i] && x < (segmentXAxis[i + 1])))
if (i == ((16 / static_cast<s32>(displayType)) - 1) || (x >= segmentXAxis[i] && x < (segmentXAxis[i + 1])))
{
selectedAddress = selectedAddress + i;
selectedNibbleHI = ((x - segmentXAxis[i]) < ((avgSegmentWidth / 2) - 2)); // Subtract 2 units, makes selecting nibbles feel more natural
u32 indexInSegment = (x - segmentXAxis[i]) / nibbleWidth;
if (littleEndian)
indexInSegment = (static_cast<s32>(displayType) * 2) - indexInSegment - 1;
selectedAddress = selectedAddress + i * static_cast<s32>(displayType) + (indexInSegment / 2);
selectedNibbleHI = littleEndian ? indexInSegment & 1 : !(indexInSegment & 1);
break;
}
}
@@ -185,13 +221,13 @@ u128 MemoryViewTable::GetSelectedSegment()
val.lo = m_cpu->read8(selectedAddress);
break;
case MemoryViewType::BYTEHW:
val.lo = qToBigEndian((u16)m_cpu->read16(selectedAddress & ~1));
val.lo = convertEndian(static_cast<u16>(m_cpu->read16(selectedAddress & ~1)));
break;
case MemoryViewType::WORD:
val.lo = qToBigEndian(m_cpu->read32(selectedAddress & ~3));
val.lo = convertEndian(m_cpu->read32(selectedAddress & ~3));
break;
case MemoryViewType::DWORD:
val._u64[0] = qToBigEndian(m_cpu->read64(selectedAddress & ~7));
val._u64[0] = convertEndian(m_cpu->read64(selectedAddress & ~7));
break;
}
return val;
@@ -210,7 +246,8 @@ void MemoryViewTable::InsertIntoSelectedHexView(u8 value)
});
}
void MemoryViewTable::InsertAtCurrentSelection(const QString& text) {
void MemoryViewTable::InsertAtCurrentSelection(const QString& text)
{
if (!m_cpu->isValidAddress(selectedAddress))
return;
@@ -218,16 +255,89 @@ void MemoryViewTable::InsertAtCurrentSelection(const QString& text) {
// This approach prevents one from pasting on a nibble boundary, but that is almost always
// user error, and we don't have an undo function in this view, so best to stay conservative.
QByteArray input = selectedText ? text.toUtf8() : QByteArray::fromHex(text.toUtf8());
Host::RunOnCPUThread([this, address = selectedAddress, cpu = m_cpu, inBytes = input] {
u32 currAddr = address;
for (int i = 0; i < inBytes.size(); i++)
{
cpu->write8(address + i, inBytes[i]);
cpu->write8(currAddr, inBytes[i]);
currAddr = nextAddress(currAddr);
QtHost::RunOnUIThread([this] { parent->update(); });
}
QtHost::RunOnUIThread([this, inBytes] { UpdateSelectedAddress(selectedAddress + inBytes.size()); parent->update(); });
});
}
u32 MemoryViewTable::nextAddress(u32 addr)
{
if (!littleEndian)
{
return addr + 1;
}
else
{
if (selectedAddress % static_cast<s32>(displayType) == 0)
return addr + (static_cast<s32>(displayType) * 2 - 1);
else
return addr - 1;
}
}
u32 MemoryViewTable::prevAddress(u32 addr)
{
if (!littleEndian)
{
return addr - 1;
}
else
{
// It works
if ((addr & (static_cast<u32>(displayType) - 1)) == (static_cast<u32>(displayType) - 1))
return addr - (static_cast<s32>(displayType) * 2 - 1);
else
return selectedAddress + 1;
}
}
void MemoryViewTable::ForwardSelection()
{
if (!littleEndian)
{
if ((selectedNibbleHI = !selectedNibbleHI))
UpdateSelectedAddress(selectedAddress + 1);
}
else
{
if ((selectedNibbleHI = !selectedNibbleHI))
{
if (selectedAddress % static_cast<s32>(displayType) == 0)
UpdateSelectedAddress(selectedAddress + (static_cast<s32>(displayType) * 2 - 1));
else
UpdateSelectedAddress(selectedAddress - 1);
}
}
}
void MemoryViewTable::BackwardSelection()
{
if (!littleEndian)
{
if (!(selectedNibbleHI = !selectedNibbleHI))
UpdateSelectedAddress(selectedAddress - 1);
}
else
{
if (!(selectedNibbleHI = !selectedNibbleHI))
{
// It works
if ((selectedAddress & (static_cast<u32>(displayType) - 1)) == (static_cast<u32>(displayType) - 1))
UpdateSelectedAddress(selectedAddress - (static_cast<s32>(displayType) * 2 - 1));
else
UpdateSelectedAddress(selectedAddress + 1);
}
}
}
// We need both key and keychar because `key` is easy to use, but is case insensitive
bool MemoryViewTable::KeyPress(int key, QChar keychar)
{
@@ -255,16 +365,16 @@ bool MemoryViewTable::KeyPress(int key, QChar keychar)
case Qt::Key::Key_Escape:
Host::RunOnCPUThread([this, address = selectedAddress, cpu = m_cpu] {
cpu->write8(address, 0);
QtHost::RunOnUIThread([this] { UpdateSelectedAddress(selectedAddress - 1); parent->update(); });
QtHost::RunOnUIThread([this] {BackwardSelection(); parent->update(); });
});
pressHandled = true;
break;
case Qt::Key::Key_Right:
UpdateSelectedAddress(selectedAddress + 1);
ForwardSelection();
pressHandled = true;
break;
case Qt::Key::Key_Left:
UpdateSelectedAddress(selectedAddress - 1);
BackwardSelection();
pressHandled = true;
break;
default:
@@ -278,13 +388,11 @@ bool MemoryViewTable::KeyPress(int key, QChar keychar)
if (keyCharIsText)
{
// Check if key pressed is hex before insertion (QString conversion fails otherwise)
const u8 keyPressed = (u8)QString(QChar(key)).toInt(&pressHandled, 16);
const u8 keyPressed = static_cast<u8>(QString(QChar(key)).toInt(&pressHandled, 16));
if (pressHandled)
{
InsertIntoSelectedHexView(keyPressed);
// Increment to the next nibble or byte
if ((selectedNibbleHI = !selectedNibbleHI))
UpdateSelectedAddress(selectedAddress + 1);
ForwardSelection();
}
}
@@ -293,19 +401,15 @@ bool MemoryViewTable::KeyPress(int key, QChar keychar)
case Qt::Key::Key_Backspace:
case Qt::Key::Key_Escape:
InsertIntoSelectedHexView(0);
// Move back a byte or nibble if it's backspace being pressed
if (!(selectedNibbleHI = !selectedNibbleHI))
UpdateSelectedAddress(selectedAddress - 1);
BackwardSelection();
pressHandled = true;
break;
case Qt::Key::Key_Right:
if ((selectedNibbleHI = !selectedNibbleHI))
UpdateSelectedAddress(selectedAddress + 1);
ForwardSelection();
pressHandled = true;
break;
case Qt::Key::Key_Left:
if (!(selectedNibbleHI = !selectedNibbleHI))
UpdateSelectedAddress(selectedAddress - 1);
BackwardSelection();
pressHandled = true;
break;
default:
@@ -403,6 +507,11 @@ void MemoryViewWidget::customMenuRequested(QPoint pos)
m_contextMenu->addSeparator();
m_actionLittleEndian = new QAction(tr("Show as Little Endian"));
m_actionLittleEndian->setCheckable(true);
m_contextMenu->addAction(m_actionLittleEndian);
connect(m_actionLittleEndian, &QAction::triggered, this, [this]() { m_table.SetLittleEndian(m_actionLittleEndian->isChecked()); });
// View Types
m_actionBYTE = new QAction(tr("Show as 1 byte"));
m_actionBYTE->setCheckable(true);
@@ -446,6 +555,8 @@ void MemoryViewWidget::customMenuRequested(QPoint pos)
m_contextMenu->addAction(action);
connect(action, &QAction::triggered, this, [this]() { contextPaste(); });
}
m_actionLittleEndian->setChecked(m_table.GetLittleEndian());
const MemoryViewType currentViewType = m_table.GetViewType();
m_actionBYTE->setChecked(currentViewType == MemoryViewType::BYTE);

View File

@@ -12,6 +12,7 @@
#include <QtWidgets/QMenu>
#include <QtWidgets/QTabBar>
#include <QtGui/QPainter>
#include <QtCore/QtEndian>
#include <vector>
@@ -28,22 +29,39 @@ class MemoryViewTable
QWidget* parent;
DebugInterface* m_cpu;
MemoryViewType displayType = MemoryViewType::BYTE;
bool littleEndian = true;
u32 rowCount;
u32 rowVisible;
s32 rowHeight;
// Stuff used for selection handling
// This gets set every paint and depends on the window size / current display mode (1byte,2byte,etc)
s32 valuexAxis; // Where the hexadecimal view begins
s32 textXAxis; // Where the text view begins
s32 row1YAxis; // Where the first row starts
s32 segmentXAxis[16]; // Where the segments begin
s32 valuexAxis; // Where the hexadecimal view begins
s32 textXAxis; // Where the text view begins
s32 row1YAxis; // Where the first row starts
s32 segmentXAxis[16]; // Where the segments begin
bool selectedText = false; // Whether the user has clicked on text or hex
bool selectedNibbleHI = false;
void InsertIntoSelectedHexView(u8 value);
template <class T>
T convertEndian(T in)
{
if (littleEndian)
{
return in;
}
else
{
return qToBigEndian(in);
}
}
u32 nextAddress(u32 addr);
u32 prevAddress(u32 addr);
public:
MemoryViewTable(QWidget* parent)
: parent(parent){};
@@ -60,6 +78,8 @@ public:
void SelectAt(QPoint pos);
u128 GetSelectedSegment();
void InsertAtCurrentSelection(const QString& text);
void ForwardSelection();
void BackwardSelection();
// Returns true if the keypress was handled
bool KeyPress(int key, QChar keychar);
@@ -72,6 +92,16 @@ public:
{
displayType = viewType;
}
bool GetLittleEndian()
{
return littleEndian;
}
void SetLittleEndian(bool le)
{
littleEndian = le;
}
};
@@ -111,6 +141,7 @@ private:
Ui::RegisterWidget ui;
QMenu* m_contextMenu = 0x0;
QAction* m_actionLittleEndian;
QAction* m_actionBYTE;
QAction* m_actionBYTEHW;
QAction* m_actionWORD;

View File

@@ -256,8 +256,6 @@ Qt::ItemFlags BreakpointModel::flags(const QModelIndex& index) const
{
volatile const int row = index.row();
const bool is_breakpoint = std::holds_alternative<BreakPoint>(m_breakpoints.at(row));
switch (index.column())
{
case BreakpointColumns::CONDITION:

View File

@@ -396,7 +396,7 @@ void MainWindow::connectSignals()
connect(m_ui.actionSaveBlockDump, &QAction::toggled, this, &MainWindow::onBlockDumpActionToggled);
connect(m_ui.actionShowAdvancedSettings, &QAction::toggled, this, &MainWindow::onShowAdvancedSettingsToggled);
connect(m_ui.actionSaveGSDump, &QAction::triggered, this, &MainWindow::onSaveGSDumpActionTriggered);
connect(m_ui.actionToolsVideoCapture, &QAction::toggled, this, &MainWindow::onToolsVideoCaptureToggled);
connect(m_ui.actionVideoCapture, &QAction::toggled, this, &MainWindow::onVideoCaptureToggled);
connect(m_ui.actionEditPatches, &QAction::triggered, this, [this]() { onToolsEditCheatsPatchesTriggered(false); });
connect(m_ui.actionEditCheats, &QAction::triggered, this, [this]() { onToolsEditCheatsPatchesTriggered(true); });
@@ -712,14 +712,14 @@ void MainWindow::updateAdvancedSettingsVisibility()
m_ui.actionEnableVerboseLogging->setVisible(enabled);
}
void MainWindow::onToolsVideoCaptureToggled(bool checked)
void MainWindow::onVideoCaptureToggled(bool checked)
{
if (!s_vm_valid)
return;
// Reset the checked state, we'll get updated by the GS thread.
QSignalBlocker sb(m_ui.actionToolsVideoCapture);
m_ui.actionToolsVideoCapture->setChecked(!checked);
QSignalBlocker sb(m_ui.actionVideoCapture);
m_ui.actionVideoCapture->setChecked(!checked);
if (!checked)
{
@@ -744,8 +744,8 @@ void MainWindow::onCaptureStarted(const QString& filename)
if (!s_vm_valid)
return;
QSignalBlocker sb(m_ui.actionToolsVideoCapture);
m_ui.actionToolsVideoCapture->setChecked(true);
QSignalBlocker sb(m_ui.actionVideoCapture);
m_ui.actionVideoCapture->setChecked(true);
}
void MainWindow::onCaptureStopped()
@@ -753,8 +753,8 @@ void MainWindow::onCaptureStopped()
if (!s_vm_valid)
return;
QSignalBlocker sb(m_ui.actionToolsVideoCapture);
m_ui.actionToolsVideoCapture->setChecked(false);
QSignalBlocker sb(m_ui.actionVideoCapture);
m_ui.actionVideoCapture->setChecked(false);
}
void MainWindow::onAchievementsLoginRequested(Achievements::LoginRequestReason reason)
@@ -851,16 +851,16 @@ void MainWindow::restoreStateFromConfig()
void MainWindow::updateEmulationActions(bool starting, bool running, bool stopping)
{
const bool starting_or_running = starting || running;
const bool starting_or_running_or_stopping = starting || running || stopping;
m_ui.actionStartFile->setDisabled(starting_or_running || stopping);
m_ui.actionStartDisc->setDisabled(starting_or_running || stopping);
m_ui.actionStartBios->setDisabled(starting_or_running || stopping);
m_ui.actionToolbarStartFile->setDisabled(starting_or_running || stopping);
m_ui.actionToolbarStartDisc->setDisabled(starting_or_running || stopping);
m_ui.actionToolbarStartBios->setDisabled(starting_or_running || stopping);
m_ui.actionStartFullscreenUI->setDisabled(starting_or_running || stopping);
m_ui.actionToolbarStartFullscreenUI->setDisabled(starting_or_running || stopping);
m_ui.actionStartFile->setDisabled(starting_or_running_or_stopping);
m_ui.actionStartDisc->setDisabled(starting_or_running_or_stopping);
m_ui.actionStartBios->setDisabled(starting_or_running_or_stopping);
m_ui.actionToolbarStartFile->setDisabled(starting_or_running_or_stopping);
m_ui.actionToolbarStartDisc->setDisabled(starting_or_running_or_stopping);
m_ui.actionToolbarStartBios->setDisabled(starting_or_running_or_stopping);
m_ui.actionStartFullscreenUI->setDisabled(starting_or_running_or_stopping);
m_ui.actionToolbarStartFullscreenUI->setDisabled(starting_or_running_or_stopping);
m_ui.actionPowerOff->setEnabled(running);
m_ui.actionPowerOffWithoutSaving->setEnabled(running);
@@ -869,6 +869,7 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool stoppi
m_ui.actionScreenshot->setEnabled(running);
m_ui.menuChangeDisc->setEnabled(running);
m_ui.menuSaveState->setEnabled(running);
m_ui.actionSaveGSDump->setEnabled(running);
m_ui.actionToolbarPowerOff->setEnabled(running);
m_ui.actionToolbarReset->setEnabled(running);
@@ -879,11 +880,11 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool stoppi
m_ui.actionViewGameProperties->setEnabled(running);
m_ui.actionToolsVideoCapture->setEnabled(running);
if (!running && m_ui.actionToolsVideoCapture->isChecked())
m_ui.actionVideoCapture->setEnabled(running);
if (!running && m_ui.actionVideoCapture->isChecked())
{
QSignalBlocker sb(m_ui.actionToolsVideoCapture);
m_ui.actionToolsVideoCapture->setChecked(false);
QSignalBlocker sb(m_ui.actionVideoCapture);
m_ui.actionVideoCapture->setChecked(false);
}
m_game_list_widget->setDisabled(starting && !running);
@@ -902,8 +903,8 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool stoppi
}
// scanning needs to be disabled while running
m_ui.actionScanForNewGames->setDisabled(starting_or_running || stopping);
m_ui.actionRescanAllGames->setDisabled(starting_or_running || stopping);
m_ui.actionScanForNewGames->setDisabled(starting_or_running_or_stopping);
m_ui.actionRescanAllGames->setDisabled(starting_or_running_or_stopping);
}
void MainWindow::updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen)
@@ -1053,7 +1054,7 @@ bool MainWindow::shouldHideMouseCursor() const
bool MainWindow::shouldHideMainWindow() const
{
// NOTE: We can't use isRenderingToMain() here, because this happens post-fullscreen-switch.
return Host::GetBoolSettingValue("UI", "HideMainWindowWhenRunning", false) ||
return (Host::GetBoolSettingValue("UI", "HideMainWindowWhenRunning", false) && !g_emu_thread->shouldRenderToMain()) ||
(g_emu_thread->shouldRenderToMain() && (isRenderingFullscreen() || m_is_temporarily_windowed)) ||
QtHost::InNoGUIMode();
}
@@ -1355,6 +1356,11 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
connect(menu.addAction(tr("Reset Play Time")), &QAction::triggered, [this, entry]() { clearGameListEntryPlayTime(entry); });
if (!entry->serial.empty())
{
connect(menu.addAction(tr("Check Wiki Page")), &QAction::triggered, [this, entry]() { goToWikiPage(entry); });
}
menu.addSeparator();
if (!s_vm_valid)
@@ -2664,7 +2670,7 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
return;
const QString old_filename = QString::fromStdString(GameList::GetCoverImagePathForEntry(entry));
const QString new_filename = QString::fromStdString(GameList::GetNewCoverImagePathForEntry(entry, filename.toUtf8().constData()));
const QString new_filename = QString::fromStdString(GameList::GetNewCoverImagePathForEntry(entry, filename.toUtf8().constData(), true));
if (new_filename.isEmpty())
return;
@@ -2718,6 +2724,11 @@ void MainWindow::clearGameListEntryPlayTime(const GameList::Entry* entry)
m_game_list_widget->refresh(false);
}
void MainWindow::goToWikiPage(const GameList::Entry* entry)
{
QtUtils::OpenURL(this, fmt::format("https://wiki.pcsx2.net/{}", entry->serial).c_str());
}
std::optional<bool> MainWindow::promptForResumeState(const QString& save_state_path)
{
if (save_state_path.isEmpty())

View File

@@ -171,7 +171,7 @@ private Q_SLOTS:
void onSaveGSDumpActionTriggered();
void onBlockDumpActionToggled(bool checked);
void onShowAdvancedSettingsToggled(bool checked);
void onToolsVideoCaptureToggled(bool checked);
void onVideoCaptureToggled(bool checked);
void onSettingsTriggeredFromToolbar();
// Input Recording
@@ -267,6 +267,7 @@ private:
const GameList::Entry* entry, std::optional<s32> save_slot = std::nullopt, std::optional<bool> fast_boot = std::nullopt);
void setGameListEntryCoverImage(const GameList::Entry* entry);
void clearGameListEntryPlayTime(const GameList::Entry* entry);
void goToWikiPage(const GameList::Entry* entry);
std::optional<bool> promptForResumeState(const QString& save_state_path);
void loadSaveStateSlot(s32 slot);

View File

@@ -210,7 +210,7 @@
<addaction name="separator"/>
<addaction name="actionToggleSoftwareRendering"/>
<addaction name="menuInputRecording"/>
<addaction name="actionToolsVideoCapture"/>
<addaction name="actionVideoCapture"/>
<addaction name="separator"/>
<addaction name="actionEnableSystemConsole"/>
<addaction name="actionEnableDebugConsole"/>
@@ -260,7 +260,9 @@
<addaction name="actionToolbarReset"/>
<addaction name="actionToolbarPause"/>
<addaction name="actionToolbarChangeDisc"/>
<addaction name="separator"/>
<addaction name="actionToolbarScreenshot"/>
<addaction name="actionVideoCapture"/>
<addaction name="separator"/>
<addaction name="actionToolbarLoadState"/>
<addaction name="actionToolbarSaveState"/>
@@ -1080,13 +1082,17 @@
<string>Recording Viewer</string>
</property>
</action>
<action name="actionToolsVideoCapture">
<action name="actionVideoCapture">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Video Capture</string>
</property>
<property name="icon">
<iconset theme="camera-video">
<normaloff>.</normaloff>.</iconset>
</property>
</action>
<action name="actionEditCheats">
<property name="text">

View File

@@ -35,10 +35,6 @@ GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsWindo
m_ui.region->setItemIcon(i,
QIcon(QStringLiteral("%1/icons/flags/%2.png").arg(base_path).arg(GameList::RegionToString(static_cast<GameList::Region>(i)))));
}
for (int i = 1; i < m_ui.compatibility->count(); i++)
{
m_ui.compatibility->setItemIcon(i, QIcon(QStringLiteral("%1/icons/star-%2.png").arg(base_path).arg(i)));
}
m_entry_path = entry->path;
populateInputProfiles();
@@ -49,11 +45,13 @@ GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsWindo
connect(m_ui.inputProfile, &QComboBox::currentIndexChanged, this, &GameSummaryWidget::onInputProfileChanged);
connect(m_ui.verify, &QAbstractButton::clicked, this, &GameSummaryWidget::onVerifyClicked);
connect(m_ui.searchHash, &QAbstractButton::clicked, this, &GameSummaryWidget::onSearchHashClicked);
connect(m_ui.checkWiki, &QAbstractButton::clicked, this, [this, entry]() { onCheckWikiClicked(entry); });
bool has_custom_title = false, has_custom_region = false;
GameList::CheckCustomAttributesForPath(m_entry_path, has_custom_title, has_custom_region);
m_ui.restoreTitle->setEnabled(has_custom_title);
m_ui.restoreRegion->setEnabled(has_custom_region);
m_ui.checkWiki->setEnabled(!entry->serial.empty());
}
GameSummaryWidget::~GameSummaryWidget() = default;
@@ -74,7 +72,15 @@ void GameSummaryWidget::populateDetails(const GameList::Entry* entry)
m_ui.crc->setText(QString::fromStdString(fmt::format("{:08X}", entry->crc)));
m_ui.type->setCurrentIndex(static_cast<int>(entry->type));
m_ui.region->setCurrentIndex(static_cast<int>(entry->region));
m_ui.compatibility->setCurrentIndex(static_cast<int>(entry->compatibility_rating));
m_ui.compatibility->setText(QString("%0%1")
.arg(GameList::EntryCompatibilityRatingToString(entry->compatibility_rating))
.arg([entry]() {
if (entry->compatibility_rating == GameList::CompatibilityRating::Unknown)
return QString();
const qsizetype compatibility_value = static_cast<qsizetype>(entry->compatibility_rating);
return QString(" ") + QString("").repeated(compatibility_value - 1) + QString("").repeated(6 - compatibility_value);
}()));
int row = 0;
m_ui.detailsFormLayout->getWidgetPosition(m_ui.titleSort, &row, nullptr);
@@ -348,6 +354,11 @@ void GameSummaryWidget::onSearchHashClicked()
QtUtils::OpenURL(this, fmt::format("http://redump.org/discs/quicksearch/{}", m_redump_search_keyword).c_str());
}
void GameSummaryWidget::onCheckWikiClicked(const GameList::Entry* entry)
{
QtUtils::OpenURL(this, fmt::format("https://wiki.pcsx2.net/{}", entry->serial).c_str());
}
void GameSummaryWidget::setVerifyResult(QString error)
{
m_ui.verify->setVisible(false);

View File

@@ -28,6 +28,7 @@ private Q_SLOTS:
void onDiscPathBrowseClicked();
void onVerifyClicked();
void onSearchHashClicked();
void onCheckWikiClicked(const GameList::Entry* entry);
private:
void populateInputProfiles();

View File

@@ -104,11 +104,25 @@
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="serial">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLineEdit" name="serial">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="checkWiki">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Check Wiki</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_36">
@@ -363,54 +377,10 @@
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="compatibility">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<widget class="QLineEdit" name="compatibility">
<property name="readOnly">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>Unknown</string>
</property>
</item>
<item>
<property name="text">
<string>Not Bootable</string>
</property>
</item>
<item>
<property name="text">
<string>Reaches Intro</string>
</property>
</item>
<item>
<property name="text">
<string>Reaches Menu</string>
</property>
</item>
<item>
<property name="text">
<string>In-Game</string>
</property>
</item>
<item>
<property name="text">
<string>Playable</string>
</property>
</item>
<item>
<property name="text">
<string>Perfect</string>
</property>
</item>
</widget>
</item>
<item row="9" column="0">

View File

@@ -124,6 +124,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowSettings, "EmuCore/GS", "OsdShowSettings", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowInputs, "EmuCore/GS", "OsdShowInputs", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowFrameTimes, "EmuCore/GS", "OsdShowFrameTimes", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowVersion, "EmuCore/GS", "OsdShowVersion", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.warnAboutUnsafeSettings, "EmuCore", "WarnAboutUnsafeSettings", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fxaa, "EmuCore/GS", "fxaa", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.shadeBoost, "EmuCore/GS", "ShadeBoost", false);
@@ -396,6 +397,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
&GraphicsSettingsWidget::onEnableAudioCaptureArgumentsChanged);
onCaptureContainerChanged();
onCaptureCodecChanged();
onEnableVideoCaptureChanged();
onEnableVideoCaptureArgumentsChanged();
onVideoCaptureAutoResolutionChanged();
@@ -718,8 +720,11 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
dialog->registerWidgetHelp(m_ui.osdShowInputs, tr("Show Inputs"), tr("Unchecked"),
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."));
dialog->registerWidgetHelp(m_ui.osdShowFrameTimes, tr("Show Frame Times"), tr("Unchecked"),
tr("Displays a graph showing the average frametimes."));
dialog->registerWidgetHelp(m_ui.osdShowVersion, tr("Show PCSX2 Version"), tr("Unchecked"),
tr("Shows the current PCSX2 version on the top-right corner of the display"));
dialog->registerWidgetHelp(m_ui.warnAboutUnsafeSettings, tr("Warn About Unsafe Settings"), tr("Checked"),
tr("Displays warnings when settings are enabled which may break games."));
@@ -731,6 +736,10 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
"<b>If unsure, leave it on default.<b>"));
dialog->registerWidgetHelp(m_ui.videoCaptureFormat, tr("Video Format"), tr("Default"), tr("Selects which Video Format to be used for Video Capture. If by chance the codec does not support the format, the first format available will be used. "
"<b>If unsure, leave it on default.<b>"));
dialog->registerWidgetHelp(m_ui.videoCaptureBitrate, tr("Video Bitrate"), tr("6000 kbps"), tr("Sets the video bitrate to be used. "
"Larger bitrate generally yields better video quality at the cost of larger resulting file size."));
@@ -779,7 +788,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
dialog->registerWidgetHelp(m_ui.skipPresentingDuplicateFrames, tr("Skip Presenting Duplicate Frames"), tr("Unchecked"),
tr("Detects when idle frames are being presented in 25/30fps games, and skips presenting those frames. The frame is still "
"rendered, it just means the GPU has more time to complete it (this is NOT frame skipping). Can smooth our frame time "
"rendered, it just means the GPU has more time to complete it (this is NOT frame skipping). Can smooth out frame time "
"fluctuations when the CPU/GPU are near maximum utilization, but makes frame pacing more inconsistent and can increase "
"input lag."));
@@ -910,6 +919,7 @@ void GraphicsSettingsWidget::onCaptureContainerChanged()
SettingWidgetBinder::BindWidgetToStringSetting(
m_dialog->getSettingsInterface(), m_ui.videoCaptureCodec, "EmuCore/GS", "VideoCaptureCodec");
connect(m_ui.videoCaptureCodec, &QComboBox::currentIndexChanged, this, &GraphicsSettingsWidget::onCaptureCodecChanged);
m_ui.audioCaptureCodec->disconnect();
m_ui.audioCaptureCodec->clear();
@@ -925,6 +935,30 @@ void GraphicsSettingsWidget::onCaptureContainerChanged()
m_dialog->getSettingsInterface(), m_ui.audioCaptureCodec, "EmuCore/GS", "AudioCaptureCodec");
}
void GraphicsSettingsWidget::GraphicsSettingsWidget::onCaptureCodecChanged()
{
m_ui.videoCaptureFormat->disconnect();
m_ui.videoCaptureFormat->clear();
//: This string refers to a default pixel format
m_ui.videoCaptureFormat->addItem(tr("Default"), "");
const std::string codec(
m_dialog->getEffectiveStringValue("EmuCore/GS", "VideoCaptureCodec", ""));
if (!codec.empty())
{
for (const auto& [id, name] : GSCapture::GetVideoFormatList(codec.c_str()))
{
const QString qid(QString::number(id));
const QString qname(QString::fromStdString(name));
m_ui.videoCaptureFormat->addItem(qname, qid);
}
}
SettingWidgetBinder::BindWidgetToStringSetting(
m_dialog->getSettingsInterface(), m_ui.videoCaptureFormat, "EmuCore/GS", "VideoCaptureFormat");
}
void GraphicsSettingsWidget::onEnableVideoCaptureChanged()
{
const bool enabled = m_dialog->getEffectiveBoolValue("EmuCore/GS", "EnableVideoCapture", true);

View File

@@ -38,6 +38,7 @@ private Q_SLOTS:
void onTextureReplacementChanged();
void onShadeBoostChanged();
void onCaptureContainerChanged();
void onCaptureCodecChanged();
void onEnableVideoCaptureChanged();
void onEnableVideoCaptureArgumentsChanged();
void onVideoCaptureAutoResolutionChanged();

View File

@@ -1610,59 +1610,17 @@
</item>
<item row="1" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_6">
<item row="3" column="1">
<widget class="QCheckBox" name="osdShowIndicators">
<property name="text">
<string>Show Indicators</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="osdShowResolution">
<property name="text">
<string>Show Resolution</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="osdShowInputs">
<property name="text">
<string>Show Inputs</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="osdShowGPU">
<property name="text">
<string>Show GPU Usage</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="osdShowSettings">
<property name="text">
<string>Show Settings</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="osdShowFPS">
<property name="text">
<string>Show FPS</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="osdShowMessages">
<item row="1" column="0">
<widget class="QCheckBox" name="osdShowVersion">
<property name="text">
<string>Show OSD Messages</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="osdShowGSStats">
<property name="text">
<string>Show Statistics</string>
<string>Show PCSX2 Version</string>
</property>
</widget>
</item>
@@ -1673,27 +1631,76 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="osdShowSpeed">
<item row="3" column="1">
<widget class="QCheckBox" name="osdShowIndicators">
<property name="text">
<string>Show Speed Percentages</string>
<string>Show Indicators</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="0" column="0">
<widget class="QCheckBox" name="osdShowMessages">
<property name="text">
<string>Show OSD Messages</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QCheckBox" name="warnAboutUnsafeSettings">
<property name="text">
<string>Warn About Unsafe Settings</string>
</property>
</widget>
</item>
<item row="5" column="0">
<item row="2" column="1">
<widget class="QCheckBox" name="osdShowGPU">
<property name="text">
<string>Show GPU Usage</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="osdShowResolution">
<property name="text">
<string>Show Resolution</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="osdShowFrameTimes">
<property name="text">
<string>Show Frame Times</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="osdShowGSStats">
<property name="text">
<string>Show Statistics</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="osdShowSpeed">
<property name="text">
<string>Show Speed Percentages</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="osdShowInputs">
<property name="text">
<string>Show Inputs</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="osdShowSettings">
<property name="text">
<string>Show Settings</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@@ -1840,13 +1847,23 @@
<widget class="QComboBox" name="videoCaptureCodec"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="videoCaptureFomatLabel">
<property name="text">
<string>Format:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="videoCaptureFormat"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="videoCaptureBitrateLabel">
<property name="text">
<string>Bitrate:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="QSpinBox" name="videoCaptureBitrate">
<property name="suffix">
<string extracomment="Unit that will appear next to a number. Alter the space or whatever is needed before the text depending on your language."> kbps</string>
@@ -1862,14 +1879,14 @@
</property>
</widget>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="videoCaptureResolutionLabel">
<property name="text">
<string>Resolution:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_10" stretch="1,0,1,0">
<item>
<widget class="QSpinBox" name="videoCaptureWidth">
@@ -1919,14 +1936,14 @@
</item>
</layout>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="enableVideoCaptureArguments">
<property name="text">
<string>Extra Arguments</string>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<item row="5" column="0" colspan="2">
<widget class="QLineEdit" name="videoCaptureArguments"/>
</item>
</layout>

View File

@@ -39,6 +39,8 @@ const char* InterfaceSettingsWidget::THEME_NAMES[] = {
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Ruby (Black/Red) [Dark]"),
//: 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", "Sapphire (Black/Blue) [Dark]"),
//: 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", "Emerald (Black/Green) [Dark]"),
//: "Custom.qss" must be kept as-is.
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Custom.qss [Drop in PCSX2 Folder]"),
nullptr};
@@ -61,6 +63,7 @@ const char* InterfaceSettingsWidget::THEME_VALUES[] = {
"CobaltSky",
"Ruby",
"Sapphire",
"Emerald",
"Custom",
nullptr};

View File

@@ -108,28 +108,28 @@ void QtHost::SetStyleFromSettings()
const QColor blue(198, 238, 255);
const QColor blue2(0, 88, 208);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, darkGray);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, black);
darkPalette.setColor(QPalette::AlternateBase, darkGray);
darkPalette.setColor(QPalette::ToolTipBase, blue2);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, darkGray);
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, blue);
darkPalette.setColor(QPalette::Highlight, blue2);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::PlaceholderText, QColor(Qt::white).darker());
QPalette darkBluePalette;
darkBluePalette.setColor(QPalette::Window, darkGray);
darkBluePalette.setColor(QPalette::WindowText, Qt::white);
darkBluePalette.setColor(QPalette::Base, black);
darkBluePalette.setColor(QPalette::AlternateBase, darkGray);
darkBluePalette.setColor(QPalette::ToolTipBase, blue2);
darkBluePalette.setColor(QPalette::ToolTipText, Qt::white);
darkBluePalette.setColor(QPalette::Text, Qt::white);
darkBluePalette.setColor(QPalette::Button, darkGray);
darkBluePalette.setColor(QPalette::ButtonText, Qt::white);
darkBluePalette.setColor(QPalette::Link, blue);
darkBluePalette.setColor(QPalette::Highlight, blue2);
darkBluePalette.setColor(QPalette::HighlightedText, Qt::white);
darkBluePalette.setColor(QPalette::PlaceholderText, QColor(Qt::white).darker());
darkPalette.setColor(QPalette::Active, QPalette::Button, darkGray);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, darkGray);
darkBluePalette.setColor(QPalette::Active, QPalette::Button, darkGray);
darkBluePalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
darkBluePalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
darkBluePalette.setColor(QPalette::Disabled, QPalette::Text, gray);
darkBluePalette.setColor(QPalette::Disabled, QPalette::Light, darkGray);
qApp->setPalette(darkPalette);
qApp->setPalette(darkBluePalette);
}
else if (theme == "GreyMatter")
{
@@ -143,28 +143,28 @@ void QtHost::SetStyleFromSettings()
const QColor gray(111, 111, 111);
const QColor blue(198, 238, 255);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, darkGray);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, lighterGray);
darkPalette.setColor(QPalette::AlternateBase, darkGray);
darkPalette.setColor(QPalette::ToolTipBase, darkGray);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, lighterGray);
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, blue);
darkPalette.setColor(QPalette::Highlight, lighterGray.lighter());
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::PlaceholderText, QColor(Qt::white).darker());
QPalette greyMatterPalette;
greyMatterPalette.setColor(QPalette::Window, darkGray);
greyMatterPalette.setColor(QPalette::WindowText, Qt::white);
greyMatterPalette.setColor(QPalette::Base, lighterGray);
greyMatterPalette.setColor(QPalette::AlternateBase, darkGray);
greyMatterPalette.setColor(QPalette::ToolTipBase, darkGray);
greyMatterPalette.setColor(QPalette::ToolTipText, Qt::white);
greyMatterPalette.setColor(QPalette::Text, Qt::white);
greyMatterPalette.setColor(QPalette::Button, lighterGray);
greyMatterPalette.setColor(QPalette::ButtonText, Qt::white);
greyMatterPalette.setColor(QPalette::Link, blue);
greyMatterPalette.setColor(QPalette::Highlight, lighterGray.lighter());
greyMatterPalette.setColor(QPalette::HighlightedText, Qt::white);
greyMatterPalette.setColor(QPalette::PlaceholderText, QColor(Qt::white).darker());
darkPalette.setColor(QPalette::Active, QPalette::Button, lighterGray);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray.lighter());
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray.lighter());
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray.lighter());
darkPalette.setColor(QPalette::Disabled, QPalette::Light, darkGray);
greyMatterPalette.setColor(QPalette::Active, QPalette::Button, lighterGray);
greyMatterPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray.lighter());
greyMatterPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray.lighter());
greyMatterPalette.setColor(QPalette::Disabled, QPalette::Text, gray.lighter());
greyMatterPalette.setColor(QPalette::Disabled, QPalette::Light, darkGray);
qApp->setPalette(darkPalette);
qApp->setPalette(greyMatterPalette);
}
else if (theme == "UntouchedLagoon")
{
@@ -178,27 +178,27 @@ void QtHost::SetStyleFromSettings()
const QColor tameTeal(160, 190, 185);
const QColor grayBlue(160, 180, 190);
QPalette standardPalette;
standardPalette.setColor(QPalette::Window, tameTeal);
standardPalette.setColor(QPalette::WindowText, black.lighter());
standardPalette.setColor(QPalette::Base, grayBlue);
standardPalette.setColor(QPalette::AlternateBase, tameTeal);
standardPalette.setColor(QPalette::ToolTipBase, tameTeal);
standardPalette.setColor(QPalette::ToolTipText, grayBlue);
standardPalette.setColor(QPalette::Text, black);
standardPalette.setColor(QPalette::Button, tameTeal);
standardPalette.setColor(QPalette::ButtonText, black);
standardPalette.setColor(QPalette::Link, black.lighter());
standardPalette.setColor(QPalette::Highlight, teal);
standardPalette.setColor(QPalette::HighlightedText, grayBlue.lighter());
QPalette untouchedLagoonPalette;
untouchedLagoonPalette.setColor(QPalette::Window, tameTeal);
untouchedLagoonPalette.setColor(QPalette::WindowText, black.lighter());
untouchedLagoonPalette.setColor(QPalette::Base, grayBlue);
untouchedLagoonPalette.setColor(QPalette::AlternateBase, tameTeal);
untouchedLagoonPalette.setColor(QPalette::ToolTipBase, tameTeal);
untouchedLagoonPalette.setColor(QPalette::ToolTipText, grayBlue);
untouchedLagoonPalette.setColor(QPalette::Text, black);
untouchedLagoonPalette.setColor(QPalette::Button, tameTeal);
untouchedLagoonPalette.setColor(QPalette::ButtonText, black);
untouchedLagoonPalette.setColor(QPalette::Link, black.lighter());
untouchedLagoonPalette.setColor(QPalette::Highlight, teal);
untouchedLagoonPalette.setColor(QPalette::HighlightedText, grayBlue.lighter());
standardPalette.setColor(QPalette::Active, QPalette::Button, tameTeal);
standardPalette.setColor(QPalette::Disabled, QPalette::ButtonText, darkteal);
standardPalette.setColor(QPalette::Disabled, QPalette::WindowText, darkteal.lighter());
standardPalette.setColor(QPalette::Disabled, QPalette::Text, darkteal.lighter());
standardPalette.setColor(QPalette::Disabled, QPalette::Light, tameTeal);
untouchedLagoonPalette.setColor(QPalette::Active, QPalette::Button, tameTeal);
untouchedLagoonPalette.setColor(QPalette::Disabled, QPalette::ButtonText, darkteal);
untouchedLagoonPalette.setColor(QPalette::Disabled, QPalette::WindowText, darkteal.lighter());
untouchedLagoonPalette.setColor(QPalette::Disabled, QPalette::Text, darkteal.lighter());
untouchedLagoonPalette.setColor(QPalette::Disabled, QPalette::Light, tameTeal);
qApp->setPalette(standardPalette);
qApp->setPalette(untouchedLagoonPalette);
}
else if (theme == "BabyPastel")
{
@@ -214,27 +214,27 @@ void QtHost::SetStyleFromSettings()
const QColor congoPink(255, 127, 121);
const QColor blue(221, 225, 239);
QPalette standardPalette;
standardPalette.setColor(QPalette::Window, pink);
standardPalette.setColor(QPalette::WindowText, black);
standardPalette.setColor(QPalette::Base, brightPink);
standardPalette.setColor(QPalette::AlternateBase, blue);
standardPalette.setColor(QPalette::ToolTipBase, pink);
standardPalette.setColor(QPalette::ToolTipText, brightPink);
standardPalette.setColor(QPalette::Text, black);
standardPalette.setColor(QPalette::Button, pink);
standardPalette.setColor(QPalette::ButtonText, black);
standardPalette.setColor(QPalette::Link, black);
standardPalette.setColor(QPalette::Highlight, congoPink);
standardPalette.setColor(QPalette::HighlightedText, black);
QPalette babyPastelPalette;
babyPastelPalette.setColor(QPalette::Window, pink);
babyPastelPalette.setColor(QPalette::WindowText, black);
babyPastelPalette.setColor(QPalette::Base, brightPink);
babyPastelPalette.setColor(QPalette::AlternateBase, blue);
babyPastelPalette.setColor(QPalette::ToolTipBase, pink);
babyPastelPalette.setColor(QPalette::ToolTipText, brightPink);
babyPastelPalette.setColor(QPalette::Text, black);
babyPastelPalette.setColor(QPalette::Button, pink);
babyPastelPalette.setColor(QPalette::ButtonText, black);
babyPastelPalette.setColor(QPalette::Link, black);
babyPastelPalette.setColor(QPalette::Highlight, congoPink);
babyPastelPalette.setColor(QPalette::HighlightedText, black);
standardPalette.setColor(QPalette::Active, QPalette::Button, pink);
standardPalette.setColor(QPalette::Disabled, QPalette::ButtonText, redpinkish);
standardPalette.setColor(QPalette::Disabled, QPalette::WindowText, redpinkish);
standardPalette.setColor(QPalette::Disabled, QPalette::Text, redpinkish);
standardPalette.setColor(QPalette::Disabled, QPalette::Light, gray);
babyPastelPalette.setColor(QPalette::Active, QPalette::Button, pink);
babyPastelPalette.setColor(QPalette::Disabled, QPalette::ButtonText, redpinkish);
babyPastelPalette.setColor(QPalette::Disabled, QPalette::WindowText, redpinkish);
babyPastelPalette.setColor(QPalette::Disabled, QPalette::Text, redpinkish);
babyPastelPalette.setColor(QPalette::Disabled, QPalette::Light, gray);
qApp->setPalette(standardPalette);
qApp->setPalette(babyPastelPalette);
}
else if (theme == "PizzaBrown")
{
@@ -250,26 +250,27 @@ void QtHost::SetStyleFromSettings()
const QColor comp(248, 230, 213);
const QColor highlight(188, 100, 60);
QPalette standardPalette;
standardPalette.setColor(QPalette::Window, main);
standardPalette.setColor(QPalette::WindowText, Qt::black);
standardPalette.setColor(QPalette::Base, comp);
standardPalette.setColor(QPalette::AlternateBase, extr);
standardPalette.setColor(QPalette::ToolTipBase, comp);
standardPalette.setColor(QPalette::ToolTipText, Qt::black);
standardPalette.setColor(QPalette::Text, Qt::black);
standardPalette.setColor(QPalette::Button, extr);
standardPalette.setColor(QPalette::ButtonText, Qt::black);
standardPalette.setColor(QPalette::Link, highlight.darker());
standardPalette.setColor(QPalette::Highlight, highlight);
standardPalette.setColor(QPalette::HighlightedText, Qt::white);
standardPalette.setColor(QPalette::Active, QPalette::Button, extr);
standardPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray.darker());
standardPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray.darker());
standardPalette.setColor(QPalette::Disabled, QPalette::Text, Qt::gray);
standardPalette.setColor(QPalette::Disabled, QPalette::Light, gray.lighter());
QPalette pizzaPalette;
pizzaPalette.setColor(QPalette::Window, main);
pizzaPalette.setColor(QPalette::WindowText, Qt::black);
pizzaPalette.setColor(QPalette::Base, comp);
pizzaPalette.setColor(QPalette::AlternateBase, extr);
pizzaPalette.setColor(QPalette::ToolTipBase, comp);
pizzaPalette.setColor(QPalette::ToolTipText, Qt::black);
pizzaPalette.setColor(QPalette::Text, Qt::black);
pizzaPalette.setColor(QPalette::Button, extr);
pizzaPalette.setColor(QPalette::ButtonText, Qt::black);
pizzaPalette.setColor(QPalette::Link, highlight.darker());
pizzaPalette.setColor(QPalette::Highlight, highlight);
pizzaPalette.setColor(QPalette::HighlightedText, Qt::white);
pizzaPalette.setColor(QPalette::Active, QPalette::Button, extr);
pizzaPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray.darker());
pizzaPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray.darker());
pizzaPalette.setColor(QPalette::Disabled, QPalette::Text, Qt::gray);
pizzaPalette.setColor(QPalette::Disabled, QPalette::Light, gray.lighter());
qApp->setPalette(standardPalette);
qApp->setPalette(pizzaPalette);
}
else if (theme == "PCSX2Blue")
{
@@ -283,27 +284,27 @@ void QtHost::SetStyleFromSettings()
const QColor blue(106, 156, 255);
const QColor lightBlue(130, 155, 241);
QPalette standardPalette;
standardPalette.setColor(QPalette::Window, blue2.lighter());
standardPalette.setColor(QPalette::WindowText, blackish);
standardPalette.setColor(QPalette::Base, lightBlue);
standardPalette.setColor(QPalette::AlternateBase, blue2.lighter());
standardPalette.setColor(QPalette::ToolTipBase, blue2);
standardPalette.setColor(QPalette::ToolTipText, Qt::white);
standardPalette.setColor(QPalette::Text, blackish);
standardPalette.setColor(QPalette::Button, blue);
standardPalette.setColor(QPalette::ButtonText, blackish);
standardPalette.setColor(QPalette::Link, darkBlue);
standardPalette.setColor(QPalette::Highlight, Qt::white);
standardPalette.setColor(QPalette::HighlightedText, blackish);
QPalette pcsx2BluePalette;
pcsx2BluePalette.setColor(QPalette::Window, blue2.lighter());
pcsx2BluePalette.setColor(QPalette::WindowText, blackish);
pcsx2BluePalette.setColor(QPalette::Base, lightBlue);
pcsx2BluePalette.setColor(QPalette::AlternateBase, blue2.lighter());
pcsx2BluePalette.setColor(QPalette::ToolTipBase, blue2);
pcsx2BluePalette.setColor(QPalette::ToolTipText, Qt::white);
pcsx2BluePalette.setColor(QPalette::Text, blackish);
pcsx2BluePalette.setColor(QPalette::Button, blue);
pcsx2BluePalette.setColor(QPalette::ButtonText, blackish);
pcsx2BluePalette.setColor(QPalette::Link, darkBlue);
pcsx2BluePalette.setColor(QPalette::Highlight, Qt::white);
pcsx2BluePalette.setColor(QPalette::HighlightedText, blackish);
standardPalette.setColor(QPalette::Active, QPalette::Button, blue);
standardPalette.setColor(QPalette::Disabled, QPalette::ButtonText, darkBlue);
standardPalette.setColor(QPalette::Disabled, QPalette::WindowText, darkBlue);
standardPalette.setColor(QPalette::Disabled, QPalette::Text, darkBlue);
standardPalette.setColor(QPalette::Disabled, QPalette::Light, darkBlue);
pcsx2BluePalette.setColor(QPalette::Active, QPalette::Button, blue);
pcsx2BluePalette.setColor(QPalette::Disabled, QPalette::ButtonText, darkBlue);
pcsx2BluePalette.setColor(QPalette::Disabled, QPalette::WindowText, darkBlue);
pcsx2BluePalette.setColor(QPalette::Disabled, QPalette::Text, darkBlue);
pcsx2BluePalette.setColor(QPalette::Disabled, QPalette::Light, darkBlue);
qApp->setPalette(standardPalette);
qApp->setPalette(pcsx2BluePalette);
}
else if (theme == "ScarletDevilRed")
{
@@ -315,27 +316,27 @@ void QtHost::SetStyleFromSettings()
const QColor purplishRed(120, 45, 69);
const QColor brightRed(200, 45, 69);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, darkRed);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, purplishRed);
darkPalette.setColor(QPalette::AlternateBase, darkRed);
darkPalette.setColor(QPalette::ToolTipBase, darkRed);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, purplishRed.darker());
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, brightRed);
darkPalette.setColor(QPalette::Highlight, brightRed);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
QPalette scarletDevilPalette;
scarletDevilPalette.setColor(QPalette::Window, darkRed);
scarletDevilPalette.setColor(QPalette::WindowText, Qt::white);
scarletDevilPalette.setColor(QPalette::Base, purplishRed);
scarletDevilPalette.setColor(QPalette::AlternateBase, darkRed);
scarletDevilPalette.setColor(QPalette::ToolTipBase, darkRed);
scarletDevilPalette.setColor(QPalette::ToolTipText, Qt::white);
scarletDevilPalette.setColor(QPalette::Text, Qt::white);
scarletDevilPalette.setColor(QPalette::Button, purplishRed.darker());
scarletDevilPalette.setColor(QPalette::ButtonText, Qt::white);
scarletDevilPalette.setColor(QPalette::Link, brightRed);
scarletDevilPalette.setColor(QPalette::Highlight, brightRed);
scarletDevilPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, purplishRed.darker());
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, brightRed);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, brightRed);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, brightRed);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, darkRed);
scarletDevilPalette.setColor(QPalette::Active, QPalette::Button, purplishRed.darker());
scarletDevilPalette.setColor(QPalette::Disabled, QPalette::ButtonText, brightRed);
scarletDevilPalette.setColor(QPalette::Disabled, QPalette::WindowText, brightRed);
scarletDevilPalette.setColor(QPalette::Disabled, QPalette::Text, brightRed);
scarletDevilPalette.setColor(QPalette::Disabled, QPalette::Light, darkRed);
qApp->setPalette(darkPalette);
qApp->setPalette(scarletDevilPalette);
}
else if (theme == "VioletAngelPurple")
{
@@ -347,27 +348,27 @@ void QtHost::SetStyleFromSettings()
const QColor darkerPurple(90, 30, 105);
const QColor nauticalPurple(110, 30, 125);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, blackishblue);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, nauticalPurple);
darkPalette.setColor(QPalette::AlternateBase, blackishblue);
darkPalette.setColor(QPalette::ToolTipBase, nauticalPurple);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, nauticalPurple.darker());
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, darkerPurple.lighter());
darkPalette.setColor(QPalette::Highlight, darkerPurple.lighter());
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
QPalette violetAngelPalette;
violetAngelPalette.setColor(QPalette::Window, blackishblue);
violetAngelPalette.setColor(QPalette::WindowText, Qt::white);
violetAngelPalette.setColor(QPalette::Base, nauticalPurple);
violetAngelPalette.setColor(QPalette::AlternateBase, blackishblue);
violetAngelPalette.setColor(QPalette::ToolTipBase, nauticalPurple);
violetAngelPalette.setColor(QPalette::ToolTipText, Qt::white);
violetAngelPalette.setColor(QPalette::Text, Qt::white);
violetAngelPalette.setColor(QPalette::Button, nauticalPurple.darker());
violetAngelPalette.setColor(QPalette::ButtonText, Qt::white);
violetAngelPalette.setColor(QPalette::Link, darkerPurple.lighter());
violetAngelPalette.setColor(QPalette::Highlight, darkerPurple.lighter());
violetAngelPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, nauticalPurple.darker());
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, darkerPurple.lighter());
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, darkerPurple.lighter());
darkPalette.setColor(QPalette::Disabled, QPalette::Text, darkerPurple.darker());
darkPalette.setColor(QPalette::Disabled, QPalette::Light, nauticalPurple);
violetAngelPalette.setColor(QPalette::Active, QPalette::Button, nauticalPurple.darker());
violetAngelPalette.setColor(QPalette::Disabled, QPalette::ButtonText, darkerPurple.lighter());
violetAngelPalette.setColor(QPalette::Disabled, QPalette::WindowText, darkerPurple.lighter());
violetAngelPalette.setColor(QPalette::Disabled, QPalette::Text, darkerPurple.darker());
violetAngelPalette.setColor(QPalette::Disabled, QPalette::Light, nauticalPurple);
qApp->setPalette(darkPalette);
qApp->setPalette(violetAngelPalette);
}
else if (theme == "CobaltSky")
{
@@ -383,27 +384,27 @@ void QtHost::SetStyleFromSettings()
const QColor highlight(36, 93, 218);
const QColor link(0, 202, 255);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, royalBlue);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, royalBlue.lighter());
darkPalette.setColor(QPalette::AlternateBase, darkishBlue);
darkPalette.setColor(QPalette::ToolTipBase, darkishBlue);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, lighterBlue);
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, link);
darkPalette.setColor(QPalette::Highlight, highlight);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
QPalette cobaltSkyPalette;
cobaltSkyPalette.setColor(QPalette::Window, royalBlue);
cobaltSkyPalette.setColor(QPalette::WindowText, Qt::white);
cobaltSkyPalette.setColor(QPalette::Base, royalBlue.lighter());
cobaltSkyPalette.setColor(QPalette::AlternateBase, darkishBlue);
cobaltSkyPalette.setColor(QPalette::ToolTipBase, darkishBlue);
cobaltSkyPalette.setColor(QPalette::ToolTipText, Qt::white);
cobaltSkyPalette.setColor(QPalette::Text, Qt::white);
cobaltSkyPalette.setColor(QPalette::Button, lighterBlue);
cobaltSkyPalette.setColor(QPalette::ButtonText, Qt::white);
cobaltSkyPalette.setColor(QPalette::Link, link);
cobaltSkyPalette.setColor(QPalette::Highlight, highlight);
cobaltSkyPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, lighterBlue);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, gray);
cobaltSkyPalette.setColor(QPalette::Active, QPalette::Button, lighterBlue);
cobaltSkyPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
cobaltSkyPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
cobaltSkyPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
cobaltSkyPalette.setColor(QPalette::Disabled, QPalette::Light, gray);
qApp->setPalette(darkPalette);
qApp->setPalette(cobaltSkyPalette);
}
else if (theme == "Ruby")
{
@@ -415,27 +416,27 @@ void QtHost::SetStyleFromSettings()
const QColor slate(18, 18, 18);
const QColor rubyish(172, 21, 31);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, slate);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, slate.lighter());
darkPalette.setColor(QPalette::AlternateBase, slate.lighter());
darkPalette.setColor(QPalette::ToolTipBase, slate);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, slate);
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, Qt::white);
darkPalette.setColor(QPalette::Highlight, rubyish);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
QPalette rubyPalette;
rubyPalette.setColor(QPalette::Window, slate);
rubyPalette.setColor(QPalette::WindowText, Qt::white);
rubyPalette.setColor(QPalette::Base, slate.lighter());
rubyPalette.setColor(QPalette::AlternateBase, slate.lighter());
rubyPalette.setColor(QPalette::ToolTipBase, slate);
rubyPalette.setColor(QPalette::ToolTipText, Qt::white);
rubyPalette.setColor(QPalette::Text, Qt::white);
rubyPalette.setColor(QPalette::Button, slate);
rubyPalette.setColor(QPalette::ButtonText, Qt::white);
rubyPalette.setColor(QPalette::Link, Qt::white);
rubyPalette.setColor(QPalette::Highlight, rubyish);
rubyPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, slate);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, slate.lighter());
rubyPalette.setColor(QPalette::Active, QPalette::Button, slate);
rubyPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
rubyPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
rubyPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
rubyPalette.setColor(QPalette::Disabled, QPalette::Light, slate.lighter());
qApp->setPalette(darkPalette);
qApp->setPalette(rubyPalette);
}
else if (theme == "Sapphire")
{
@@ -447,27 +448,59 @@ void QtHost::SetStyleFromSettings()
const QColor slate(18, 18, 18);
const QColor persianBlue(32, 35, 204);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, slate);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, slate.lighter());
darkPalette.setColor(QPalette::AlternateBase, slate.lighter());
darkPalette.setColor(QPalette::ToolTipBase, slate);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, slate);
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, Qt::white);
darkPalette.setColor(QPalette::Highlight, persianBlue);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
QPalette sapphirePalette;
sapphirePalette.setColor(QPalette::Window, slate);
sapphirePalette.setColor(QPalette::WindowText, Qt::white);
sapphirePalette.setColor(QPalette::Base, slate.lighter());
sapphirePalette.setColor(QPalette::AlternateBase, slate.lighter());
sapphirePalette.setColor(QPalette::ToolTipBase, slate);
sapphirePalette.setColor(QPalette::ToolTipText, Qt::white);
sapphirePalette.setColor(QPalette::Text, Qt::white);
sapphirePalette.setColor(QPalette::Button, slate);
sapphirePalette.setColor(QPalette::ButtonText, Qt::white);
sapphirePalette.setColor(QPalette::Link, Qt::white);
sapphirePalette.setColor(QPalette::Highlight, persianBlue);
sapphirePalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, slate);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, slate.lighter());
sapphirePalette.setColor(QPalette::Active, QPalette::Button, slate);
sapphirePalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
sapphirePalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
sapphirePalette.setColor(QPalette::Disabled, QPalette::Text, gray);
sapphirePalette.setColor(QPalette::Disabled, QPalette::Light, slate.lighter());
qApp->setPalette(darkPalette);
qApp->setPalette(sapphirePalette);
}
else if (theme == "Emerald")
{
// Custom palette by RedDevilus, Black as main color and Blue as complimentary.
// Alternative dark (black) theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor gray(128, 128, 128);
const QColor slate(18, 18, 18);
const QColor evergreenEmerald(15, 81, 59);
QPalette emeraldPalette;
emeraldPalette.setColor(QPalette::Window, slate);
emeraldPalette.setColor(QPalette::WindowText, Qt::white);
emeraldPalette.setColor(QPalette::Base, slate.lighter());
emeraldPalette.setColor(QPalette::AlternateBase, slate.lighter());
emeraldPalette.setColor(QPalette::ToolTipBase, slate);
emeraldPalette.setColor(QPalette::ToolTipText, Qt::white);
emeraldPalette.setColor(QPalette::Text, Qt::white);
emeraldPalette.setColor(QPalette::Button, slate);
emeraldPalette.setColor(QPalette::ButtonText, Qt::white);
emeraldPalette.setColor(QPalette::Link, Qt::white);
emeraldPalette.setColor(QPalette::Highlight, evergreenEmerald);
emeraldPalette.setColor(QPalette::HighlightedText, Qt::white);
emeraldPalette.setColor(QPalette::Active, QPalette::Button, slate);
emeraldPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
emeraldPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
emeraldPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
emeraldPalette.setColor(QPalette::Disabled, QPalette::Light, slate.lighter());
qApp->setPalette(emeraldPalette);
}
else if (theme == "Custom")
{

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg width="256px" height="256px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#000000" class="bi bi-camera-video">
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>

After

Width:  |  Height:  |  Size: 782 B

View File

@@ -0,0 +1,7 @@
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
<svg width="256px" height="256px" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="#ffffff" class="bi bi-camera-video">
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>

After

Width:  |  Height:  |  Size: 782 B

View File

@@ -9,16 +9,17 @@
<file>icons/black/svg/band-aid-line.svg</file>
<file>icons/black/svg/brush-line.svg</file>
<file>icons/black/svg/buzz-controller-line.svg</file>
<file>icons/black/svg/camera-video.svg</file>
<file>icons/black/svg/cheats-line.svg</file>
<file>icons/black/svg/checkbox-multiple-blank-line.svg</file>
<file>icons/black/svg/chip-line.svg</file>
<file>icons/black/svg/close-line.svg</file>
<file>icons/black/svg/controller-line.svg</file>
<file>icons/black/svg/controller-strike-line.svg</file>
<file>icons/black/svg/debugger-line.svg</file>
<file>icons/black/svg/debug-step-into-line.svg</file>
<file>icons/black/svg/debug-step-out-line.svg</file>
<file>icons/black/svg/debug-step-over-line.svg</file>
<file>icons/black/svg/debugger-line.svg</file>
<file>icons/black/svg/delete-back-2-line.svg</file>
<file>icons/black/svg/disc-2-line.svg</file>
<file>icons/black/svg/disc-eject-line.svg</file>
@@ -105,16 +106,17 @@
<file>icons/white/svg/band-aid-line.svg</file>
<file>icons/white/svg/brush-line.svg</file>
<file>icons/white/svg/buzz-controller-line.svg</file>
<file>icons/white/svg/camera-video.svg</file>
<file>icons/white/svg/cheats-line.svg</file>
<file>icons/white/svg/checkbox-multiple-blank-line.svg</file>
<file>icons/white/svg/chip-line.svg</file>
<file>icons/white/svg/close-line.svg</file>
<file>icons/white/svg/controller-line.svg</file>
<file>icons/white/svg/controller-strike-line.svg</file>
<file>icons/white/svg/debugger-line.svg</file>
<file>icons/white/svg/debug-step-into-line.svg</file>
<file>icons/white/svg/debug-step-out-line.svg</file>
<file>icons/white/svg/debug-step-over-line.svg</file>
<file>icons/white/svg/debugger-line.svg</file>
<file>icons/white/svg/delete-back-2-line.svg</file>
<file>icons/white/svg/disc-2-line.svg</file>
<file>icons/white/svg/disc-eject-line.svg</file>

View File

@@ -621,6 +621,7 @@ struct Pcsx2Config
OsdShowSettings : 1,
OsdShowInputs : 1,
OsdShowFrameTimes : 1,
OsdShowVersion : 1,
HWSpinGPUForReadbacks : 1,
HWSpinCPUForReadbacks : 1,
GPUPaletteConversion : 1,
@@ -730,6 +731,7 @@ struct Pcsx2Config
std::string CaptureContainer = DEFAULT_CAPTURE_CONTAINER;
std::string VideoCaptureCodec;
std::string VideoCaptureFormat;
std::string VideoCaptureParameters;
std::string AudioCaptureCodec;
std::string AudioCaptureParameters;

View File

@@ -96,10 +96,10 @@ namespace PacketReader::IP
{
//If buffer & data point to the same location
//Then no copy is needed
if (data == buffer)
if (data == &buffer[*offset])
return;
memcpy(buffer, data, length);
memcpy(&buffer[*offset], data, length);
*offset += length;
}
virtual IP_Payload* Clone() const

View File

@@ -15,8 +15,11 @@
#endif
#include <algorithm>
#include <bit>
#include <thread>
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
@@ -35,36 +38,38 @@ using namespace PacketReader::IP::ICMP;
using namespace std::chrono_literals;
/* Ping is kindof annoying to do crossplatform
All platforms restrict raw sockets
Windows provides an api for ICMP
ICMP_ECHO_REPLY should always be used, ignore ICMP_ECHO_REPLY32
IP_OPTION_INFORMATION should always be used, ignore IP_OPTION_INFORMATION32
Linux
We have access to raw sockets via CAP_NET_RAW (for pcap)
However we may be missing that cap on some builds
Linux has socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP), used similar to raw sockets but for ICMP only
Auto filters responses
Requires net.ipv4.ping_group_range sysctl, default off on alot of distros
Timeouts reported via sock_extended_err control messages (with IP_RECVERR socket option set)
Mac
Raw sockets restricted
Mac has socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)
No restriction to using it
Implementation differs, is more versatile than linux
Does not auto filter responses
Timeouts reported as a normal packet
FreeBSD
Raw sockets restricted
No unprivilaged ICMP sockets
Timeouts reported as a normal packet??
Ping cli
Present for all platforms, but command args differ
/*
* Ping is kindof annoying to do crossplatform
* All platforms restrict raw sockets
*
* Windows provides an api for ICMP
* ICMP_ECHO_REPLY should always be used, ignore ICMP_ECHO_REPLY32
* IP_OPTION_INFORMATION should always be used, ignore IP_OPTION_INFORMATION32
*
* Linux
* We have access to raw sockets via CAP_NET_RAW (for pcap)
* However we may be missing that cap on some builds
* Also hava socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP), used similarly to raw sockets, but for ICMP only
* Auto filters responses
* Requires net.ipv4.ping_group_range sysctl, default off on a lot of distros
* Timeouts reported via sock_extended_err control messages (with IP_RECVERR socket option set)
*
* Mac
* Raw sockets restricted
* Mac has socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)
* No restriction to using it with ICMP_ECHO
* Implementation differs, is more versatile than linux
* Does not auto filter responses
* Timeouts reported as a normal packet
*
* FreeBSD
* Raw sockets restricted
* No unprivilaged ICMP sockets
* Timeouts reported as a normal packet??
*
* Ping cli
* Present for all platforms, but command args differ
* Not used here
*/
namespace Sessions
@@ -95,29 +100,36 @@ namespace Sessions
return;
}
//Allocate return buffer
//Documentation says + 8 to allow for an ICMP error message
//In testing, ICMP_ECHO_REPLY structure itself was returned with data set to null
/*
* Allocate response buffer
* Documentation says + 8 to allow for an ICMP error message
* In testing, ICMP_ECHO_REPLY structure itself was returned with data set to null
*/
icmpResponseBufferLen = sizeof(ICMP_ECHO_REPLY) + requestSize + 8;
icmpResponseBuffer = std::make_unique<u8[]>(icmpResponseBufferLen);
icmpResponseBuffer = std::make_unique<std::byte[]>(icmpResponseBufferLen);
#elif defined(__POSIX__)
{
/*
* Allocate response buffer
* Size needed depends on which socket protocol (ICMP or raw) we use aswell as os
*/
switch (icmpConnectionKind)
{
//Two different methods for raw/icmp sockets bettween the unix OSes
//Play it safe and only enable when we know which of the two methods we use
// Two different methods for raw/icmp sockets between the Unix OSes
// Play it safe and only enable when we know which of the two methods we use
#if defined(ICMP_SOCKETS_LINUX) || defined(ICMP_SOCKETS_BSD)
case (PingType::ICMP):
icmpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
if (icmpSocket != -1)
{
#if defined(ICMP_SOCKETS_LINUX)
//Space for ICMP header, as MSG_ERRQUEUE returns what we sent
//An extra +8 required sometimes, for some reason?
// Only need space for ICMP header, as MSG_ERRQUEUE returns data we sent
// Testing found an extra + 8 was required sometimes, for some reason?
icmpResponseBufferLen = 8 + requestSize + 8;
#elif defined(ICMP_SOCKETS_BSD)
//Returned IP Header, ICMP Header & either data or failed ICMP packet
icmpResponseBufferLen = 20 + 8 + std::max(20 + 8, requestSize);
// Returned IP Header, ICMP Header & either data or failed ICMP packet
// Sometimes get full packet in ICMP error response
icmpResponseBufferLen = 20 + 8 + (20 + 8 + requestSize);
#endif
break;
}
@@ -132,16 +144,17 @@ namespace Sessions
if (icmpSocket != -1)
{
#if defined(ICMP_SOCKETS_LINUX)
//We get packet + header
// We get IP packet + ICMP header
icmpResponseBufferLen = 20 + 8 + requestSize;
#elif defined(ICMP_SOCKETS_BSD)
//As above, but we will also directly recive error ICMP messages
// As above, but we will also directly receive error ICMP messages
icmpResponseBufferLen = 20 + 8 + std::max(20 + 8, requestSize);
#endif
break;
}
DevCon.WriteLn("DEV9: ICMP: Failed To Open RAW Socket");
[[fallthrough]];
#endif
default:
@@ -149,11 +162,11 @@ namespace Sessions
return;
}
icmpResponseBuffer = std::make_unique<u8[]>(icmpResponseBufferLen);
icmpResponseBuffer = std::make_unique<std::byte[]>(icmpResponseBufferLen);
#endif
}
bool ICMP_Session::Ping::IsInitialised()
bool ICMP_Session::Ping::IsInitialised() const
{
#ifdef _WIN32
return icmpFile != INVALID_HANDLE_VALUE;
@@ -169,19 +182,29 @@ namespace Sessions
#endif
}
//Note, we can finish reading but have no data
// Returned PingResult.data is only valid when PingResult.type is 0
ICMP_Session::PingResult* ICMP_Session::Ping::Recv()
{
#ifdef _WIN32
if (WaitForSingleObject(icmpEvent, 0) == WAIT_OBJECT_0)
{
ResetEvent(icmpEvent);
//Prep buffer for reasing
[[maybe_unused]] int count = IcmpParseReplies(icmpResponseBuffer.get(), icmpResponseBufferLen);
pxAssert(count == 1);
ICMP_ECHO_REPLY* pingRet = (ICMP_ECHO_REPLY*)icmpResponseBuffer.get();
//Map status to ICMP type/code
const int count = IcmpParseReplies(icmpResponseBuffer.get(), icmpResponseBufferLen);
pxAssert(count <= 1);
// Timeout
if (count == 0)
{
result.type = -2;
result.code = 0;
return &result;
}
// Rely on implicit object creation
const ICMP_ECHO_REPLY* pingRet = reinterpret_cast<ICMP_ECHO_REPLY*>(icmpResponseBuffer.get());
// Map status to ICMP type/code
switch (pingRet->Status)
{
case (IP_SUCCESS):
@@ -208,21 +231,23 @@ namespace Sessions
result.type = 3;
result.code = 4;
break;
case (IP_BAD_ROUTE): //Bad source route
case (IP_BAD_ROUTE): // Bad source route
result.type = 3;
result.code = 5;
break;
case (IP_BAD_DESTINATION):
//I think this could be either
//Destination network unknown
//or
//Destination host unknown
//Use host unkown
/*
* I think this could be mapped to either
* Destination network unknown
* or
* Destination host unknown
* Lets map to host unknown
*/
result.type = 3;
result.code = 7;
break;
case (IP_REQ_TIMED_OUT):
//Return nothing
// Return nothing
result.type = -2;
result.code = 0;
break;
@@ -239,7 +264,7 @@ namespace Sessions
result.code = 0;
break;
//Unexpected Errors
// Unexpected errors
case (IP_BUF_TOO_SMALL):
case (IP_NO_RESOURCES):
case (IP_BAD_OPTION):
@@ -255,7 +280,7 @@ namespace Sessions
}
result.dataLength = pingRet->DataSize;
result.data = (u8*)pingRet->Data;
result.data = static_cast<u8*>(pingRet->Data);
result.address.integer = pingRet->Address;
return &result;
@@ -268,82 +293,30 @@ namespace Sessions
case (PingType::ICMP):
case (PingType::RAW):
{
int ret;
#if defined(ICMP_SOCKETS_BSD)
fd_set sReady;
fd_set sExcept;
timeval nowait{0};
FD_ZERO(&sReady);
FD_ZERO(&sExcept);
FD_SET(icmpSocket, &sReady);
FD_SET(icmpSocket, &sExcept);
ret = select(icmpSocket + 1, &sReady, nullptr, &sExcept, &nowait);
bool hasData;
if (ret == -1)
{
hasData = false;
Console.WriteLn("DEV9: ICMP: select failed. Error Code: %d", errno);
}
else if (FD_ISSET(icmpSocket, &sExcept))
{
hasData = false;
int error = 0;
socklen_t len = sizeof(error);
if (getsockopt(icmpSocket, SOL_SOCKET, SO_ERROR, (char*)&error, &len) < 0)
Console.Error("DEV9: ICMP: Unkown ICMP Connection Error (getsockopt Error: %d)", errno);
else
Console.Error("DEV9: ICMP: Recv Error: %d", error);
}
else
hasData = FD_ISSET(icmpSocket, &sReady);
if (hasData == false)
{
if (std::chrono::steady_clock::now() - icmpDeathClockStart > ICMP_TIMEOUT)
{
result.type = -2;
result.code = 0;
return &result;
}
else
return nullptr;
}
#endif
sockaddr endpoint{0};
sockaddr_in endpoint{};
iovec iov;
iov.iov_base = icmpResponseBuffer.get();
iov.iov_len = icmpResponseBufferLen;
#if defined(ICMP_SOCKETS_LINUX)
//Needs to hold cmsghdr + sock_extended_err + sockaddr_in
//for ICMP error responses (total 44 bytes)
//Unkown for other types of error
u8 cbuff[64];
// Needs to hold cmsghdr + sock_extended_err + sockaddr_in
// for ICMP error responses, this is a total of 44 bytes
// Unknown size needed for other error types
std::byte cbuff[64]{};
#endif
msghdr msg{0};
msghdr msg{};
msg.msg_name = &endpoint;
msg.msg_namelen = sizeof(endpoint);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
#if defined(ICMP_SOCKETS_LINUX)
ret = recvmsg(icmpSocket, &msg, MSG_DONTWAIT);
#elif defined(ICMP_SOCKETS_BSD)
ret = recvmsg(icmpSocket, &msg, 0);
#endif
int ret = recvmsg(icmpSocket, &msg, 0);
if (ret == -1)
{
int err = errno;
#if defined(ICMP_SOCKETS_LINUX)
if (err == EAGAIN || err == EWOULDBLOCK)
{
if (std::chrono::steady_clock::now() - icmpDeathClockStart > ICMP_TIMEOUT)
@@ -355,14 +328,16 @@ namespace Sessions
else
return nullptr;
}
#if defined(ICMP_SOCKETS_LINUX)
else
{
msg.msg_control = &cbuff;
msg.msg_controllen = sizeof(cbuff);
ret = recvmsg(icmpSocket, &msg, MSG_ERRQUEUE | MSG_DONTWAIT);
ret = recvmsg(icmpSocket, &msg, MSG_ERRQUEUE);
}
#endif
if (ret == -1)
#endif
{
Console.Error("DEV9: ICMP: RecvMsg Error: %d", err);
result.type = -1;
@@ -373,40 +348,59 @@ namespace Sessions
if (msg.msg_flags & MSG_TRUNC)
Console.Error("DEV9: ICMP: RecvMsg Truncated");
#if defined(ICMP_SOCKETS_LINUX)
if (msg.msg_flags & MSG_CTRUNC)
Console.Error("DEV9: ICMP: RecvMsg Control Truncated");
sock_extended_err* ex_err = nullptr;
// On Linux, ICMP errors are stored in control messages retrieved using MSG_ERRQUEUE
sock_extended_err* exErrorPtr = nullptr;
cmsghdr* cmsg;
/* Receive auxiliary data in msgh */
// Search though control messages, taking the latest mesage
// We should only have at most 1 message
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
{
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
{
ex_err = (sock_extended_err*)CMSG_DATA(cmsg);
pxAssert(!exErrorPtr);
exErrorPtr = reinterpret_cast<sock_extended_err*>(CMSG_DATA(cmsg));
continue;
}
pxAssert(false);
}
if (ex_err != nullptr)
if (exErrorPtr != nullptr)
{
if (ex_err->ee_origin == SO_EE_ORIGIN_ICMP)
{
result.type = ex_err->ee_type;
result.code = ex_err->ee_code;
/*
* The pointer returned cannot be assumed to be suitably aligned for accessing arbitrary payload data types
* So we would need to memcpy sock_extended_err
*/
sock_extended_err exError;
std::memcpy(&exError, exErrorPtr, sizeof(exError));
sockaddr_in* sockaddr = (sockaddr_in*)SO_EE_OFFENDER(ex_err);
result.address = *(IP_Address*)&sockaddr->sin_addr;
// Process the error
if (exError.ee_origin == SO_EE_ORIGIN_ICMP)
{
result.type = exError.ee_type;
result.code = exError.ee_code;
/*
* SO_EE_OFFENDER reads data relative to, but not necessarily included in struct sock_extended_err
* So we need to pass the original pointer provided to us from CMSG_DATA()
* However, the input pointer needs to be of type sock_extended_err*, hence the reinterpret_cast
* The pointer returned may not be suitably aligned (see CMSG_DATA), so we need to memcpy
*/
sockaddr_in errorEndpoint;
std::memcpy(&errorEndpoint, SO_EE_OFFENDER(exErrorPtr), sizeof(errorEndpoint));
result.address = std::bit_cast<IP_Address>(errorEndpoint.sin_addr);
return &result;
}
else
{
Console.Error("DEV9: ICMP: Recv Error %d", ex_err->ee_errno);
Console.Error("DEV9: ICMP: Recv error %d", exError.ee_errno);
result.type = -1;
result.code = ex_err->ee_errno;
result.code = exError.ee_errno;
return &result;
}
}
@@ -424,60 +418,66 @@ namespace Sessions
else
#endif
{
ip* ipHeader = (ip*)icmpResponseBuffer.get();
int headerLength = ipHeader->ip_hl << 2;
// Rely on implicit object creation
const ip* ipHeader = reinterpret_cast<ip*>(icmpResponseBuffer.get());
const int headerLength = ipHeader->ip_hl << 2;
pxAssert(headerLength == 20);
offset = headerLength;
#ifdef __APPLE__
//Apple (old BSD)'s raw IP sockets implementation converts the ip_len field to host byte order
//and additionally subtracts the header length.
//https://www.unix.com/man-page/mojave/4/ip/
// Apple (old BSD)'s raw IP sockets implementation converts the ip_len field to host byte order
// and additionally subtracts the header length.
// https://www.unix.com/man-page/mojave/4/ip/
length = ipHeader->ip_len;
#else
length = ntohs(ipHeader->ip_len) - headerLength;
#endif
}
ICMP_Packet icmp(&icmpResponseBuffer[offset], length);
// Rely on implicit object creation for u8
ICMP_Packet icmp(reinterpret_cast<u8*>(&icmpResponseBuffer[offset]), length);
PayloadPtr* icmpPayload = static_cast<PayloadPtr*>(icmp.GetPayload());
result.type = icmp.type;
result.code = icmp.code;
sockaddr_in* sockaddr = (sockaddr_in*)&endpoint;
result.address = *(IP_Address*)&sockaddr->sin_addr;
result.address = std::bit_cast<IP_Address>(endpoint.sin_addr);
if (icmp.type == 0)
{
//Check if response is to us
// Check if response is for us
if (icmpConnectionKind == PingType::RAW)
{
ICMP_HeaderDataIdentifier headerData(icmp.headerData);
const ICMP_HeaderDataIdentifier headerData(icmp.headerData);
if (headerData.identifier != icmpId)
return nullptr;
}
//While icmp (and its PayloadPtr) will be destroyed when leaving this function
//the data pointed to it persist in icmpResponseBuffer
// While icmp (and its PayloadPtr) will be destroyed when leaving this function
// the data it points to persists in icmpResponseBuffer
result.dataLength = icmpPayload->GetLength();
result.data = icmpPayload->data;
return &result;
}
#if defined(ICMP_SOCKETS_BSD)
// On BSD/Mac, ICMP errors are returned as normal packets
else if (icmp.type == 3 || icmp.type == 4 || icmp.type == 5 || icmp.type == 11)
{
//Check if response is to us
//We need to extract the sent header
// Extract the packet the ICMP message is responding to
IP_Packet ipPacket(icmpPayload->data, icmpPayload->GetLength(), true);
IP_PayloadPtr* ipPayload = static_cast<IP_PayloadPtr*>(ipPacket.GetPayload());
ICMP_Packet retIcmp(ipPayload->data, ipPayload->GetLength());
ICMP_HeaderDataIdentifier headerData(icmp.headerData);
if (ipPacket.protocol != static_cast<u8>(IP_Type::ICMP))
return nullptr;
IP_PayloadPtr* ipPayload = static_cast<IP_PayloadPtr*>(ipPacket.GetPayload());
ICMP_Packet icmpInner(ipPayload->data, ipPayload->GetLength());
// Check if response is for us
const ICMP_HeaderDataIdentifier headerData(icmpInner.headerData);
if (headerData.identifier != icmpId)
return nullptr;
//This response is for us
// This response is for us
return &result;
}
#endif
@@ -487,7 +487,7 @@ namespace Sessions
Console.Error("DEV9: ICMP: Unexpected packet");
pxAssert(false);
#endif
//Assume not for us
// Assume not for us
return nullptr;
}
}
@@ -503,25 +503,25 @@ namespace Sessions
bool ICMP_Session::Ping::Send(IP_Address parAdapterIP, IP_Address parDestIP, int parTimeToLive, PayloadPtr* parPayload)
{
#ifdef _WIN32
//Documentation is incorrect, IP_OPTION_INFORMATION is to be used regardless of platform
IP_OPTION_INFORMATION ipInfo{0};
// Documentation is incorrect, IP_OPTION_INFORMATION is to be used regardless of platform
IP_OPTION_INFORMATION ipInfo{};
ipInfo.Ttl = parTimeToLive;
DWORD ret;
if (parAdapterIP.integer != 0)
ret = IcmpSendEcho2Ex(icmpFile, icmpEvent, nullptr, nullptr, parAdapterIP.integer, parDestIP.integer, parPayload->data, parPayload->GetLength(), &ipInfo, icmpResponseBuffer.get(), icmpResponseBufferLen,
(DWORD)std::chrono::duration_cast<std::chrono::milliseconds>(ICMP_TIMEOUT).count());
static_cast<DWORD>(std::chrono::duration_cast<std::chrono::milliseconds>(ICMP_TIMEOUT).count()));
else
ret = IcmpSendEcho2(icmpFile, icmpEvent, nullptr, nullptr, parDestIP.integer, parPayload->data, parPayload->GetLength(), &ipInfo, icmpResponseBuffer.get(), icmpResponseBufferLen,
(DWORD)std::chrono::duration_cast<std::chrono::milliseconds>(ICMP_TIMEOUT).count());
static_cast<DWORD>(std::chrono::duration_cast<std::chrono::milliseconds>(ICMP_TIMEOUT).count()));
//Documentation states that IcmpSendEcho2 returns ERROR_IO_PENDING
//However, it actully returns zero, with the error set to ERROR_IO_PENDING
// Documentation states that IcmpSendEcho2 returns ERROR_IO_PENDING
// However, it actually returns zero, with the error set to ERROR_IO_PENDING
if (ret == 0)
ret = GetLastError();
if (ret != ERROR_IO_PENDING)
{
Console.Error("DEV9: ICMP: Failed to Send Echo, %d", GetLastError());
Console.Error("DEV9: ICMP: Failed to send echo, %d", GetLastError());
return false;
}
@@ -534,16 +534,16 @@ namespace Sessions
{
icmpDeathClockStart = std::chrono::steady_clock::now();
//broadcast and multicast mignt need extra setsockopts
//I don't think any game will broadcast/multicast ping
// Broadcast and multicast might need extra setsockopts calls
// I don't think any game will do a broadcast/multicast ping
if (parAdapterIP.integer != 0)
{
sockaddr_in endpoint{0};
sockaddr_in endpoint{};
endpoint.sin_family = AF_INET;
*(IP_Address*)&endpoint.sin_addr = parAdapterIP;
endpoint.sin_addr = std::bit_cast<in_addr>(parAdapterIP);
if (bind(icmpSocket, (const sockaddr*)&endpoint, sizeof(endpoint)) == -1)
if (bind(icmpSocket, reinterpret_cast<const sockaddr*>(&endpoint), sizeof(endpoint)) == -1)
{
Console.Error("DEV9: ICMP: Failed to bind socket. Error: %d", errno);
::close(icmpSocket);
@@ -553,8 +553,8 @@ namespace Sessions
}
#if defined(ICMP_SOCKETS_LINUX)
int value = 1;
if (setsockopt(icmpSocket, SOL_IP, IP_RECVERR, (char*)&value, sizeof(value)))
const int value = 1;
if (setsockopt(icmpSocket, SOL_IP, IP_RECVERR, reinterpret_cast<const char*>(&value), sizeof(value)))
{
Console.Error("DEV9: ICMP: Failed to setsockopt IP_RECVERR. Error: %d", errno);
::close(icmpSocket);
@@ -563,8 +563,8 @@ namespace Sessions
}
#endif
// TTL (Note multicast & regular ttl are seperate)
if (setsockopt(icmpSocket, IPPROTO_IP, IP_TTL, (const char*)&parTimeToLive, sizeof(parTimeToLive)) == -1)
// TTL (Note multicast & regular ttl are separate)
if (setsockopt(icmpSocket, IPPROTO_IP, IP_TTL, reinterpret_cast<const char*>(&parTimeToLive), sizeof(parTimeToLive)) == -1)
{
Console.Error("DEV9: ICMP: Failed to set TTL. Error: %d", errno);
::close(icmpSocket);
@@ -572,13 +572,23 @@ namespace Sessions
return false;
}
// Non-blocking
int blocking = 1;
if (ioctl(icmpSocket, FIONBIO, &blocking) == -1)
{
Console.Error("DEV9: ICMP: Failed to set non-blocking. Error: %d", errno);
::close(icmpSocket);
icmpSocket = -1;
return false;
}
#if defined(ICMP_SOCKETS_LINUX)
if (icmpConnectionKind == PingType::ICMP)
{
//We get assigned a port
sockaddr_in endpoint{0};
// We get assigned a port/Id
sockaddr_in endpoint{};
socklen_t endpointsize = sizeof(endpoint);
if (getsockname(icmpSocket, (sockaddr*)&endpoint, &endpointsize) == -1)
if (getsockname(icmpSocket, reinterpret_cast<sockaddr*>(&endpoint), &endpointsize) == -1)
{
Console.Error("DEV9: ICMP: Failed to get id. Error: %d", errno);
::close(icmpSocket);
@@ -591,15 +601,15 @@ namespace Sessions
else
#endif
{
//Use time, in ms, as id
icmpId = (u16)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
// Use time, in ms, as id
icmpId = static_cast<u16>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
}
ICMP_Packet icmp(parPayload->Clone());
icmp.type = 8;
icmp.code = 0;
//We only send one icmp packet per identifier
// We only send one icmp packet per identifier
ICMP_HeaderDataIdentifier headerData(icmpId, 1);
headerData.WriteHeaderData(icmp.headerData);
@@ -609,17 +619,27 @@ namespace Sessions
int offset = 0;
icmp.WriteBytes(buffer.get(), &offset);
sockaddr_in endpoint{0};
sockaddr_in endpoint{};
endpoint.sin_family = AF_INET;
*(IP_Address*)&endpoint.sin_addr.s_addr = parDestIP;
endpoint.sin_addr = std::bit_cast<in_addr>(parDestIP);
const int ret = sendto(icmpSocket, buffer.get(), icmp.GetLength(), 0, (const sockaddr*)&endpoint, sizeof(endpoint));
if (ret == -1)
int ret = -1;
while (ret == -1)
{
Console.Error("DEV9: ICMP: Send Error %d", errno);
::close(icmpSocket);
icmpSocket = -1;
return false;
ret = sendto(icmpSocket, buffer.get(), icmp.GetLength(), 0, reinterpret_cast<const sockaddr*>(&endpoint), sizeof(endpoint));
if (ret == -1)
{
const int err = errno;
if (err == EAGAIN || err == EWOULDBLOCK)
std::this_thread::yield();
else
{
Console.Error("DEV9: ICMP: Send error %d", errno);
::close(icmpSocket);
icmpSocket = -1;
return false;
}
}
}
return true;
@@ -665,16 +685,15 @@ namespace Sessions
for (size_t i = 0; i < pings.size(); i++)
{
ICMP_Session::PingResult* pingRet = nullptr;
pingRet = pings[i]->Recv();
const ICMP_Session::PingResult* pingRet = pings[i]->Recv();
if (pingRet != nullptr)
{
Ping* ping = pings[i];
//Remove ping from list and unlock
std::unique_ptr<Ping> ping = std::move(pings[i]);
// Remove ping from list and unlock mutex
pings.erase(pings.begin() + i);
lock.unlock();
//Create return ICMP packet
// Create return ICMP packet
std::optional<ReceivedPayload> ret;
if (pingRet->type >= 0)
{
@@ -686,22 +705,19 @@ namespace Sessions
}
else
{
//We will copy the original packet back here
//Allocate fullsize buffer
u8* temp = new u8[ping->originalPacket->GetLength()];
//Allocate data
int responseSize = ping->originalPacket->GetHeaderLength() + 8;
// Copy the original packet into the returned ICMP packet
// Allocate fullsize buffer
std::vector<u8> temp = std::vector<u8>(ping->originalPacket->GetLength());
// Allocate returned ICMP payload
const int responseSize = ping->originalPacket->GetHeaderLength() + 8;
data = new PayloadData(responseSize);
//Write packet back into bytes
// Write packet into buffer
int offset = 0;
ping->originalPacket->WriteBytes(temp, &offset);
ping->originalPacket->WriteBytes(temp.data(), &offset);
//Copy only needed bytes
memcpy(data->data.get(), temp, responseSize);
//cleanup
delete[] temp;
// Copy only needed bytes
memcpy(data->data.get(), temp.data(), responseSize);
}
std::unique_ptr<ICMP_Packet> pRet = std::make_unique<ICMP_Packet>(data);
@@ -716,16 +732,13 @@ namespace Sessions
else
DevCon.WriteLn("DEV9: ICMP: ICMP timeout");
//free ping
delete ping;
if (ret.has_value())
DevCon.WriteLn("DEV9: ICMP: Return Ping");
if (--open == 0)
RaiseEventConnectionClosed();
if (ret.has_value())
DevCon.WriteLn("DEV9: ICMP: Return Ping");
//Return packet
// Return packet
return ret;
}
}
@@ -741,7 +754,7 @@ namespace Sessions
return false;
}
//Note, expects caller to set ipTimeToLive before calling
// Expects caller to set ipTimeToLive before calling
bool ICMP_Session::Send(PacketReader::IP::IP_Payload* payload, IP_Packet* packet)
{
IP_PayloadPtr* ipPayload = static_cast<IP_PayloadPtr*>(payload);
@@ -751,16 +764,19 @@ namespace Sessions
switch (icmp.type)
{
case 3: //Port Closed
case 3: // Port Closed
switch (icmp.code)
{
case 3:
{
Console.Error("DEV9: ICMP: Recived Packet Rejected, Port Closed");
//RE:Outbreak Hackfix
//TODO, check if still needed
Console.Error("DEV9: ICMP: Received Packet Rejected, Port Closed");
/*
* RE:Outbreak Hackfix
* ICMP port closed messages has an extra 4 bytes of padding before the packet copy
* this can be tested by trying to connect without using the resurrection server DNS
* turbo mode may be needed to trigger the bug, depending on the DNS server's latency
*/
std::unique_ptr<IP_Packet> retPkt;
if ((icmpPayload->data[0] & 0xF0) == (4 << 4))
retPkt = std::make_unique<IP_Packet>(icmpPayload->data, icmpPayload->GetLength(), true);
@@ -776,20 +792,20 @@ namespace Sessions
retPkt = std::make_unique<IP_Packet>(&icmpPayload->data[off], icmpPayload->GetLength(), true);
}
IP_Address srvIP = retPkt->sourceIP;
u8 prot = retPkt->protocol;
const IP_Address srvIP = retPkt->sourceIP;
const u8 prot = retPkt->protocol;
u16 srvPort = 0;
u16 ps2Port = 0;
switch (prot)
{
case (u8)IP_Type::TCP:
case (u8)IP_Type::UDP:
//Read ports directly from the payload
//both UDP and TCP have the same locations for ports
case static_cast<u8>(IP_Type::TCP):
case static_cast<u8>(IP_Type::UDP):
// Read ports directly from the payload
// both UDP and TCP have the same locations for ports
IP_PayloadPtr* payload = static_cast<IP_PayloadPtr*>(retPkt->GetPayload());
int offset = 0;
NetLib::ReadUInt16(payload->data, &offset, &srvPort); //src
NetLib::ReadUInt16(payload->data, &offset, &ps2Port); //dst
NetLib::ReadUInt16(payload->data, &offset, &srvPort); // src
NetLib::ReadUInt16(payload->data, &offset, &ps2Port); // dst
}
ConnectionKey Key{};
@@ -798,7 +814,7 @@ namespace Sessions
Key.ps2Port = ps2Port;
Key.srvPort = srvPort;
//is from Normal Port?
// Is from Normal Port?
BaseSession* s = nullptr;
connections->TryGetValue(Key, &s);
@@ -809,7 +825,7 @@ namespace Sessions
break;
}
//Is from Fixed Port?
// Is from Fixed Port?
Key.ip = {};
Key.srvPort = 0;
connections->TryGetValue(Key, &s);
@@ -827,18 +843,17 @@ namespace Sessions
Console.Error("DEV9: ICMP: Unsupported ICMP Code For Destination Unreachable %d", icmp.code);
}
break;
case 8: //Echo
case 8: // Echo
{
DevCon.WriteLn("DEV9: ICMP: Send Ping");
open++;
Ping* ping = new Ping(icmpPayload->GetLength());
std::unique_ptr<Ping> ping = std::make_unique<Ping>(icmpPayload->GetLength());
if (!ping->IsInitialised())
{
if (--open == 0)
RaiseEventConnectionClosed();
delete ping;
return false;
}
@@ -846,18 +861,17 @@ namespace Sessions
{
if (--open == 0)
RaiseEventConnectionClosed();
delete ping;
return false;
}
memcpy(ping->headerData, icmp.headerData, 4);
//Need to copy IP_Packet, original is stack allocated
// Need to copy IP_Packet, original is stack allocated
ping->originalPacket = std::make_unique<IP_Packet>(*packet);
{
std::scoped_lock lock(ping_mutex);
pings.push_back(ping);
pings.push_back(std::move(ping));
}
break;
@@ -876,10 +890,8 @@ namespace Sessions
ICMP_Session::~ICMP_Session()
{
// Cleanup
std::scoped_lock lock(ping_mutex);
//Cleanup
for (size_t i = 0; i < pings.size(); i++)
delete pings[i];
pings.clear();
}
} // namespace Sessions

View File

@@ -47,30 +47,29 @@ namespace Sessions
static PingType icmpConnectionKind;
//Sockets
// Sockets
int icmpSocket{-1};
std::chrono::steady_clock::time_point icmpDeathClockStart;
u16 icmpId;
#endif
//Return buffers
// Return buffers
PingResult result{};
int icmpResponseBufferLen{0};
std::unique_ptr<u8[]> icmpResponseBuffer;
std::unique_ptr<std::byte[]> icmpResponseBuffer;
public:
Ping(int requestSize);
bool IsInitialised();
bool IsInitialised() const;
PingResult* Recv();
bool Send(PacketReader::IP::IP_Address parAdapterIP, PacketReader::IP::IP_Address parDestIP, int parTimeToLive, PacketReader::PayloadPtr* parPayload);
~Ping();
};
SimpleQueue<PacketReader::IP::ICMP::ICMP_Packet*> _recvBuff;
std::mutex ping_mutex;
std::vector<Ping*> pings;
std::vector<std::unique_ptr<Ping>> pings;
ThreadSafeMap<Sessions::ConnectionKey, Sessions::BaseSession*>* connections;
std::atomic<int> open{0};

View File

@@ -1054,6 +1054,7 @@ static void HotkeyToggleOSD()
GSConfig.OsdShowSettings ^= EmuConfig.GS.OsdShowSettings;
GSConfig.OsdShowInputs ^= EmuConfig.GS.OsdShowInputs;
GSConfig.OsdShowFrameTimes ^= EmuConfig.GS.OsdShowFrameTimes;
GSConfig.OsdShowVersion ^= EmuConfig.GS.OsdShowVersion;
}
BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphics"),

View File

@@ -42,6 +42,8 @@ extern "C" {
#include "libavutil/dict.h"
#include "libavutil/opt.h"
#include "libavutil/version.h"
#include "libavutil/channel_layout.h"
#include "libavutil/pixdesc.h"
#include "libswscale/swscale.h"
#include "libswscale/version.h"
#include "libswresample/swresample.h"
@@ -88,7 +90,8 @@ extern "C" {
#else
#define AVUTIL_57_IMPORTS(X) \
X(av_channel_layout_default) \
X(av_channel_layout_copy)
X(av_channel_layout_copy) \
X(av_opt_set_chlayout)
#endif
#define VISIT_AVUTIL_IMPORTS(X) \
@@ -115,7 +118,8 @@ extern "C" {
X(av_hwframe_transfer_data) \
X(av_hwframe_get_buffer) \
X(av_buffer_ref) \
X(av_buffer_unref)
X(av_buffer_unref) \
X(av_get_pix_fmt_name)
#define VISIT_SWSCALE_IMPORTS(X) \
X(sws_getCachedContext) \
@@ -291,11 +295,13 @@ bool GSCapture::LoadFFmpeg(bool report_errors)
{
Host::ReportErrorAsync(TRANSLATE_SV("GSCapture","Failed to load FFmpeg"),
fmt::format(TRANSLATE_FS("GSCapture","You may be missing one or more files, or are using the incorrect version. This build of PCSX2 requires:\n"
" libavcodec: {}\n"
" libavformat: {}\n"
" libavutil: {}\n"
" libswscale: {}\n"
" libswresample: {}\n"), LIBAVCODEC_VERSION_MAJOR, LIBAVFORMAT_VERSION_MAJOR, LIBAVUTIL_VERSION_MAJOR,
" libavcodec: {}\n"
" libavformat: {}\n"
" libavutil: {}\n"
" libswscale: {}\n"
" libswresample: {}\n\n"
"Please see our official documentation for more information."),
LIBAVCODEC_VERSION_MAJOR, LIBAVFORMAT_VERSION_MAJOR, LIBAVUTIL_VERSION_MAJOR,
LIBSWSCALE_VERSION_MAJOR, LIBSWRESAMPLE_VERSION_MAJOR));
}
@@ -445,23 +451,30 @@ bool GSCapture::BeginCapture(float fps, GSVector2i recommendedResolution, float
wrap_av_reduce(&s_video_codec_context->time_base.num, &s_video_codec_context->time_base.den, 10000,
static_cast<s64>(static_cast<double>(fps) * 10000.0), std::numeric_limits<s32>::max());
// Default to YUV 4:2:0 if the codec doesn't specify a pixel format.
AVPixelFormat sw_pix_fmt = AV_PIX_FMT_YUV420P;
// Default to NV12 if not overridden by the user
const AVPixelFormat preferred_sw_pix_fmt = GSConfig.VideoCaptureFormat.empty() ? AV_PIX_FMT_NV12 : static_cast<AVPixelFormat>(std::stoi(GSConfig.VideoCaptureFormat));
AVPixelFormat sw_pix_fmt = preferred_sw_pix_fmt;
if (vcodec->pix_fmts)
{
// Prefer YUV420 given the choice, but otherwise fall back to whatever it supports.
sw_pix_fmt = vcodec->pix_fmts[0];
for (u32 i = 0; vcodec->pix_fmts[i] != AV_PIX_FMT_NONE; i++)
{
if (vcodec->pix_fmts[i] == AV_PIX_FMT_YUV420P)
if (vcodec->pix_fmts[i] == preferred_sw_pix_fmt)
{
sw_pix_fmt = vcodec->pix_fmts[i];
break;
}
}
}
if (sw_pix_fmt == AV_PIX_FMT_VAAPI)
sw_pix_fmt = AV_PIX_FMT_NV12;
s_video_codec_context->pix_fmt = sw_pix_fmt;
if (preferred_sw_pix_fmt != sw_pix_fmt)
Console.Warning("GSCapture: preferred pixel format (%d) was unsupported by the codec. Using (%d) instead.", preferred_sw_pix_fmt, sw_pix_fmt);
// Can we use hardware encoding?
const AVCodecHWConfig* hwconfig = wrap_avcodec_get_hw_config(vcodec, 0);
if (hwconfig && hwconfig->pix_fmt != AV_PIX_FMT_NONE && hwconfig->pix_fmt != sw_pix_fmt)
@@ -688,9 +701,16 @@ bool GSCapture::BeginCapture(float fps, GSVector2i recommendedResolution, float
return false;
}
#if LIBAVUTIL_VERSION_MAJOR >= 57
const AVChannelLayout layout = AV_CHANNEL_LAYOUT_STEREO;
wrap_av_opt_set_chlayout(s_swr_context, "in_chlayout", &layout, 0);
wrap_av_opt_set_chlayout(s_swr_context, "out_chlayout", &layout, 0);
#endif
wrap_av_opt_set_int(s_swr_context, "in_channel_count", AUDIO_CHANNELS, 0);
wrap_av_opt_set_int(s_swr_context, "in_sample_rate", sample_rate, 0);
wrap_av_opt_set_sample_fmt(s_swr_context, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
wrap_av_opt_set_int(s_swr_context, "out_channel_count", AUDIO_CHANNELS, 0);
wrap_av_opt_set_int(s_swr_context, "out_sample_rate", sample_rate, 0);
wrap_av_opt_set_sample_fmt(s_swr_context, "out_sample_fmt", s_audio_codec_context->sample_fmt, 0);
@@ -1491,3 +1511,33 @@ GSCapture::CodecList GSCapture::GetAudioCodecList(const char* container)
{
return GetCodecListForContainer(container, AVMEDIA_TYPE_AUDIO);
}
GSCapture::FormatList GSCapture::GetVideoFormatList(const char* codec)
{
FormatList ret;
if (!LoadFFmpeg(false))
return ret;
const AVCodec* v_codec = wrap_avcodec_find_encoder_by_name(codec);
if (!v_codec)
{
Console.Error("(GetVideoFormatList) avcodec_find_encoder_by_name() failed");
return ret;
}
// rawvideo doesn't have a list of formats.
if(v_codec->pix_fmts == nullptr)
{
Console.Error("(GetVideoFormatList) v_codec->pix_fmts is null.");
return ret;
}
for (int i = 0; v_codec->pix_fmts[i] != AVPixelFormat::AV_PIX_FMT_NONE; i++)
{
ret.emplace_back(v_codec->pix_fmts[i], wrap_av_get_pix_fmt_name(v_codec->pix_fmts[i]));
}
return ret;
}

View File

@@ -37,4 +37,8 @@ namespace GSCapture
using CodecList = std::vector<CodecName>;
CodecList GetVideoCodecList(const char* container);
CodecList GetAudioCodecList(const char* container);
using FormatName = std::pair<int , std::string>; // id,name
using FormatList = std::vector<FormatName>;
FormatList GetVideoFormatList(const char* codec);
}; // namespace GSCapture

View File

@@ -4668,7 +4668,6 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
blend.op = GSDevice::OP_ADD;
// Render pass 2: Add or subtract result of render pass 1(Cd) from Cs.
m_conf.blend_second_pass.enable = true;
m_conf.blend_second_pass.blend_hw = 0;
m_conf.blend_second_pass.dither = dither * GSConfig.Dithering;
m_conf.blend_second_pass.blend = {true, blend_second_pass.src, GSDevice::CONST_ONE, blend_second_pass.op, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0};
}
@@ -4743,8 +4742,12 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::SRC_DOUBLE);
}
if (m_conf.ps.blend_c == 2 && (m_conf.ps.blend_hw == 2 || m_conf.ps.blend_hw == 4 || m_conf.blend_second_pass.blend_hw == 2))
if (m_conf.ps.blend_c == 2 && (m_conf.ps.blend_hw == static_cast<u8>(HWBlendType::SRC_ALPHA_DST_FACTOR)
|| m_conf.ps.blend_hw == static_cast<u8>(HWBlendType::SRC_HALF_ONE_DST_FACTOR)
|| m_conf.blend_second_pass.blend_hw == static_cast<u8>(HWBlendType::SRC_ALPHA_DST_FACTOR)))
{
m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast<float>(AFIX) / 128.0f;
}
const GSDevice::BlendFactor src_factor_alpha = m_conf.blend_second_pass.enable ? GSDevice::CONST_ZERO : GSDevice::CONST_ONE;
const GSDevice::BlendFactor dst_factor_alpha = m_conf.blend_second_pass.enable ? GSDevice::CONST_ONE : GSDevice::CONST_ZERO;

View File

@@ -640,7 +640,7 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
return (config.UpscaleMultiplier <= 1.0f || config.UserHacks_RoundSprite == value);
case GSHWFixId::NativeScaling:
return (static_cast<int>(config.UserHacks_NativeScaling) == value);
return (config.UpscaleMultiplier <= 1.0f || static_cast<int>(config.UserHacks_NativeScaling) == value);
case GSHWFixId::TexturePreloading:
return (static_cast<int>(config.TexturePreloading) <= value);

View File

@@ -3123,6 +3123,9 @@ void FullscreenUI::DrawInterfaceSettingsPage()
FSUI_CSTR(
"Shows on-screen-display messages when events occur such as save states being created/loaded, screenshots being taken, etc."),
"EmuCore/GS", "OsdShowMessages", true);
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_INFO, "Show PCSX2 Version"),
FSUI_CSTR("Shows the current PCSX2 version on the top-right corner of the display."), "EmuCore/GS",
"OsdShowVersion", false);
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_TACHOMETER_ALT, "Show Speed"),
FSUI_CSTR("Shows the current emulation speed of the system in the top-right corner of the display as a percentage."), "EmuCore/GS",
"OsdShowSpeed", false);
@@ -3287,11 +3290,11 @@ void FullscreenUI::DrawEmulationSettingsPage()
MenuHeading(FSUI_CSTR("Speed Control"));
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_FA_PLAY,"Normal Speed"), FSUI_CSTR("Sets the speed when running without fast forwarding."), "Framerate",
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_FA_PLAY, "Normal Speed"), FSUI_CSTR("Sets the speed when running without fast forwarding."), "Framerate",
"NominalScalar", 1.00f, speed_entries, speed_values, std::size(speed_entries), true);
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_FA_FAST_FORWARD,"Fast Forward Speed"), FSUI_CSTR("Sets the speed when using the fast forward hotkey."), "Framerate",
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_FA_FAST_FORWARD, "Fast Forward Speed"), FSUI_CSTR("Sets the speed when using the fast forward hotkey."), "Framerate",
"TurboScalar", 2.00f, speed_entries, speed_values, std::size(speed_entries), true);
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_PF_SLOW_MOTION,"Slow Motion Speed"), FSUI_CSTR("Sets the speed when using the slow motion hotkey."), "Framerate",
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_PF_SLOW_MOTION, "Slow Motion Speed"), FSUI_CSTR("Sets the speed when using the slow motion hotkey."), "Framerate",
"SlomoScalar", 0.50f, speed_entries, speed_values, std::size(speed_entries), true);
MenuHeading(FSUI_CSTR("System Settings"));
@@ -3597,7 +3600,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
BeginMenuButtons();
MenuHeading(FSUI_CSTR("Renderer"));
DrawStringListSetting(bsi, FSUI_ICONSTR(ICON_FA_PAINT_BRUSH,"Renderer"), FSUI_CSTR("Selects the API used to render the emulated GS."), "EmuCore/GS",
DrawStringListSetting(bsi, FSUI_ICONSTR(ICON_FA_PAINT_BRUSH, "Renderer"), FSUI_CSTR("Selects the API used to render the emulated GS."), "EmuCore/GS",
"Renderer", "-1", s_renderer_names, s_renderer_values, std::size(s_renderer_names), true);
MenuHeading(FSUI_CSTR("Display"));
@@ -3950,7 +3953,7 @@ void FullscreenUI::DrawAudioSettingsPage()
DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_VOLUME_UP, "Output Volume"),
FSUI_CSTR("Controls the volume of the audio played on the host."), "SPU2/Output", "OutputVolume", 100,
0, 100, "%d%%");
DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_FAST_FORWARD,"Fast Forward Volume"),
DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_FAST_FORWARD, "Fast Forward Volume"),
FSUI_CSTR("Controls the volume of the audio played on the host when fast forwarding."), "SPU2/Output",
"FastForwardVolume", 100, 0, 100, "%d%%");
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_VOLUME_MUTE, "Mute All Sound"),

View File

@@ -24,6 +24,7 @@
#include "SIO/Pad/PadBase.h"
#include "USB/USB.h"
#include "VMManager.h"
#include "svnrev.h"
#include "common/BitUtils.h"
#include "common/FileSystem.h"
@@ -121,6 +122,7 @@ __ri void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, f
{
bool first = true;
const float speed = PerformanceMetrics::GetSpeed();
if (GSConfig.OsdShowFPS)
{
switch (PerformanceMetrics::GetInternalFPSMethod())
@@ -152,6 +154,16 @@ __ri void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, f
else
text.append_format(" ({:.0f}%)", target_speed * 100.0f);
}
if (GSConfig.OsdShowVersion)
{
if (GSConfig.OsdShowFPS || GSConfig.OsdShowSpeed)
{
text.append_format(" | ");
}
text.append_format("PCSX2 {}", GIT_REV);
}
if (!text.empty())
{
ImU32 color;

View File

@@ -1605,7 +1605,10 @@ void InputManager::UpdateInputSourceState(SettingsInterface& si, std::unique_loc
{
if (s_input_sources[static_cast<u32>(type)])
{
settings_lock.unlock();
s_input_sources[static_cast<u32>(type)]->Shutdown();
settings_lock.lock();
s_input_sources[static_cast<u32>(type)].reset();
}
}

View File

@@ -39,18 +39,18 @@ void iopMemRelease()
// which is performed by MemInit and PsxMemInit()
void iopMemReset()
{
pxAssert( iopMem );
pxAssert(iopMem);
DbgCon.WriteLn("IOP resetting main memory...");
memset(psxMemWLUT, 0, 0x2000 * sizeof(uptr) * 2); // clears both allocations, RLUT and WLUT
memset(psxMemWLUT, 0, 0x2000 * sizeof(uptr) * 2); // clears both allocations, RLUT and WLUT
// Trick! We're accessing RLUT here through WLUT, since it's the non-const pointer.
// So the ones with a 0x2000 prefixed are RLUT tables.
// Map IOP main memory, which is Read/Write, and mirrored three times
// at 0x0, 0x8000, and 0xa000:
for (int i=0; i<0x0080; i++)
for (int i = 0; i < 0x0080; i++)
{
psxMemWLUT[i + 0x0000] = (uptr)&iopMem->Main[(i & 0x1f) << 16];
@@ -78,7 +78,7 @@ void iopMemReset()
psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&eeMem->ROM1[i << 16];
}
for (int i = 0; i < 0x0008; i++)
for (int i = 0; i < 0x0040; i++)
{
psxMemWLUT[i + 0x2000 + 0x1e40] = (uptr)&eeMem->ROM2[i << 16];
}
@@ -318,7 +318,7 @@ void iopMemWrite16(u32 mem, u16 value)
default:
psxHu16(mem) = value;
break;
break;
}
} else
{
@@ -443,7 +443,7 @@ void iopMemWrite32(u32 mem, u32 value)
case 0x60:
psHu32(SBUS_F260) = 0;
return;
return;
}
#if PSX_EXTRALOGS
@@ -529,11 +529,11 @@ bool iopMemSafeWriteBytes(u32 mem, const void* src, u32 size)
std::string iopMemReadString(u32 mem, int maxlen)
{
std::string ret;
char c;
std::string ret;
char c;
while ((c = iopMemRead8(mem++)) && maxlen--)
ret.push_back(c);
while ((c = iopMemRead8(mem++)) && maxlen--)
ret.push_back(c);
return ret;
return ret;
}

View File

@@ -11,7 +11,7 @@ namespace Ps2MemSize
static constexpr u32 TotalRam = _1mb * 128;// 128 MB total memory.
static constexpr u32 Rom = _1mb * 4; // 4 MB main rom
static constexpr u32 Rom1 = _1mb * 4; // DVD player
static constexpr u32 Rom2 = 0x00080000; // Chinese rom extension
static constexpr u32 Rom2 = _1mb * 4; // Chinese rom extension
static constexpr u32 Hardware = _64kb;
static constexpr u32 Scratch = _16kb;

View File

@@ -629,6 +629,7 @@ Pcsx2Config::GSOptions::GSOptions()
OsdShowSettings = false;
OsdShowInputs = false;
OsdShowFrameTimes = false;
OsdShowVersion = false;
HWDownloadMode = GSHardwareDownloadMode::Enabled;
HWSpinGPUForReadbacks = false;
@@ -749,6 +750,7 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
OpEqu(CaptureContainer) &&
OpEqu(VideoCaptureCodec) &&
OpEqu(VideoCaptureFormat) &&
OpEqu(VideoCaptureParameters) &&
OpEqu(AudioCaptureCodec) &&
OpEqu(AudioCaptureParameters) &&
@@ -833,6 +835,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapBitBool(OsdShowSettings);
SettingsWrapBitBool(OsdShowInputs);
SettingsWrapBitBool(OsdShowFrameTimes);
SettingsWrapBitBool(OsdShowVersion);
SettingsWrapBitBool(HWSpinGPUForReadbacks);
SettingsWrapBitBool(HWSpinCPUForReadbacks);
@@ -923,6 +926,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapEntryEx(CaptureContainer, "CaptureContainer");
SettingsWrapEntryEx(VideoCaptureCodec, "VideoCaptureCodec");
SettingsWrapEntryEx(VideoCaptureFormat, "VideoCaptureFormat");
SettingsWrapEntryEx(VideoCaptureParameters, "VideoCaptureParameters");
SettingsWrapEntryEx(AudioCaptureCodec, "AudioCaptureCodec");
SettingsWrapEntryEx(AudioCaptureParameters, "AudioCaptureParameters");

View File

@@ -97,24 +97,24 @@ void PadData::OverrideActualController() const
PadBase* pad = Pad::GetPad(m_ext_port);
pad->SetRawAnalogs(m_leftAnalog, m_rightAnalog);
pad->Set(PadDualshock2::Inputs::PAD_RIGHT, std::get<1>(m_right));
pad->Set(PadDualshock2::Inputs::PAD_LEFT, std::get<1>(m_left));
pad->Set(PadDualshock2::Inputs::PAD_UP, std::get<1>(m_up));
pad->Set(PadDualshock2::Inputs::PAD_DOWN, std::get<1>(m_down));
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_RIGHT, m_right);
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_LEFT, m_left);
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_UP, m_up);
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_DOWN, m_down);
pad->Set(PadDualshock2::Inputs::PAD_START, m_start);
pad->Set(PadDualshock2::Inputs::PAD_SELECT, m_select);
pad->Set(PadDualshock2::Inputs::PAD_R3, m_r3);
pad->Set(PadDualshock2::Inputs::PAD_L3, m_l3);
pad->Set(PadDualshock2::Inputs::PAD_SQUARE, std::get<1>(m_square));
pad->Set(PadDualshock2::Inputs::PAD_CROSS, std::get<1>(m_cross));
pad->Set(PadDualshock2::Inputs::PAD_CIRCLE, std::get<1>(m_circle));
pad->Set(PadDualshock2::Inputs::PAD_TRIANGLE, std::get<1>(m_triangle));
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_SQUARE, m_square);
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_CROSS, m_cross);
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_CIRCLE, m_circle);
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_TRIANGLE, m_triangle);
pad->Set(PadDualshock2::Inputs::PAD_R1, std::get<1>(m_r1));
pad->Set(PadDualshock2::Inputs::PAD_L1, std::get<1>(m_l1));
pad->Set(PadDualshock2::Inputs::PAD_R2, std::get<1>(m_r2));
pad->Set(PadDualshock2::Inputs::PAD_L2, std::get<1>(m_l2));
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_R1, m_r1);
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_L1, m_l1);
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_R2, m_r2);
pad->SetRawPressureButton(PadDualshock2::Inputs::PAD_L2, m_l2);
}
void addButtonInfoToString(std::string label, std::string& str, std::tuple<bool, u8> buttonInfo)

View File

@@ -39,6 +39,7 @@ public: // Public members
virtual void Set(u32 index, float value) = 0;
virtual void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) = 0;
virtual void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) = 0;
virtual void SetAxisScale(float deadzone, float scale) = 0;
virtual float GetVibrationScale(u32 motor) const = 0;
virtual void SetVibrationScale(u32 motor, float scale) = 0;

View File

@@ -560,29 +560,6 @@ void PadDualshock2::Set(u32 index, float value)
return;
}
// Since we reordered the buttons for better UI, we need to remap them here.
static constexpr std::array<u8, Inputs::LENGTH> bitmaskMapping = {{
12, // PAD_UP
13, // PAD_RIGHT
14, // PAD_DOWN
15, // PAD_LEFT
4, // PAD_TRIANGLE
5, // PAD_CIRCLE
6, // PAD_CROSS
7, // PAD_SQUARE
8, // PAD_SELECT
11, // PAD_START
2, // PAD_L1
0, // PAD_L2
3, // PAD_R1
1, // PAD_R2
9, // PAD_L3
10, // PAD_R3
16, // PAD_ANALOG
17, // PAD_PRESSURE
// remainder are analogs and not used here
}};
if (IsAnalogKey(index))
{
this->rawInputs[index] = static_cast<u8>(std::clamp(value * this->axisScale * 255.0f, 0.0f, 255.0f));
@@ -742,6 +719,20 @@ void PadDualshock2::SetRawAnalogs(const std::tuple<u8, u8> left, const std::tupl
this->analogs.ry = std::get<1>(right);
}
void PadDualshock2::SetRawPressureButton(u32 index, const std::tuple<bool, u8> value)
{
this->rawInputs[index] = std::get<1>(value);
if (std::get<0>(value))
{
this->buttons &= ~(1u << bitmaskMapping[index]);
}
else
{
this->buttons |= (1u << bitmaskMapping[index]);
}
}
void PadDualshock2::SetAxisScale(float deadzone, float scale)
{
this->axisDeadzone = deadzone;

View File

@@ -85,6 +85,29 @@ private:
// Used to store the last vibration mapping request the PS2 made for the large motor.
u8 largeMotorLastConfig = 0xff;
// Since we reordered the buttons for better UI, we need to remap them here.
static constexpr std::array<u8, Inputs::LENGTH> bitmaskMapping = {{
12, // PAD_UP
13, // PAD_RIGHT
14, // PAD_DOWN
15, // PAD_LEFT
4, // PAD_TRIANGLE
5, // PAD_CIRCLE
6, // PAD_CROSS
7, // PAD_SQUARE
8, // PAD_SELECT
11, // PAD_START
2, // PAD_L1
0, // PAD_L2
3, // PAD_R1
1, // PAD_R2
9, // PAD_L3
10, // PAD_R3
16, // PAD_ANALOG
17, // PAD_PRESSURE
// remainder are analogs and not used here
}};
void ConfigLog();
u8 Mystery(u8 commandByte);
@@ -117,6 +140,7 @@ public:
const Pad::ControllerInfo& GetInfo() const override;
void Set(u32 index, float value) override;
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
void SetAxisScale(float deadzone, float scale) override;
float GetVibrationScale(u32 motor) const override;
void SetVibrationScale(u32 motor, float scale) override;

View File

@@ -318,6 +318,20 @@ void PadGuitar::SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8
{
}
void PadGuitar::SetRawPressureButton(u32 index, const std::tuple<bool, u8> value)
{
this->rawInputs[index] = std::get<1>(value);
if (std::get<0>(value))
{
this->buttons &= ~(1u << bitmaskMapping[index]);
}
else
{
this->buttons |= (1u << bitmaskMapping[index]);
}
}
void PadGuitar::SetAxisScale(float deadzone, float scale)
{
this->whammyDeadzone = deadzone;

View File

@@ -37,6 +37,20 @@ private:
float whammyDeadzone = 0.0f;
float buttonDeadzone = 0.0f; // Button deadzone is still a good idea, in case a host analog stick is bound to a guitar button
// Since we reordered the buttons for better UI, we need to remap them here.
static constexpr std::array<u8, Inputs::LENGTH> bitmaskMapping = {{
12, // STRUM_UP
14, // STRUM_DOWN
8, // SELECT
11, // START
1, // GREEN
5, // RED
4, // YELLOW
6, // BLUE
7, // ORANGE
0 // TILT
}};
void ConfigLog();
u8 Mystery(u8 commandByte);
@@ -58,6 +72,7 @@ public:
const Pad::ControllerInfo& GetInfo() const override;
void Set(u32 index, float value) override;
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
void SetAxisScale(float deadzone, float scale) override;
float GetVibrationScale(u32 motor) const override;
void SetVibrationScale(u32 motor, float scale) override;

View File

@@ -36,6 +36,11 @@ void PadNotConnected::SetRawAnalogs(const std::tuple<u8, u8> left, const std::tu
}
void PadNotConnected::SetRawPressureButton(u32 index, const std::tuple<bool, u8> value)
{
}
void PadNotConnected::SetAxisScale(float deadzone, float scale)
{

View File

@@ -15,6 +15,7 @@ public:
const Pad::ControllerInfo& GetInfo() const override;
void Set(u32 index, float value) override;
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
void SetAxisScale(float deadzone, float scale) override;
float GetVibrationScale(u32 motor) const override;
void SetVibrationScale(u32 motor, float scale) override;

View File

@@ -376,21 +376,6 @@ void PadPopn::Set(u32 index, float value)
return;
}
// Since we reordered the buttons for better UI, we need to remap them here.
static constexpr std::array<u8, Inputs::LENGTH> bitmaskMapping = {{
5, // PAD_YELLOW_LEFT
12, // PAD_YELLOW_RIGHT
6, // PAD_BLUE_LEFT
7, // PAD_BLUE_RIGHT
4, // PAD_WHITE_LEFT
0, // PAD_WHITE_RIGHT
3, // PAD_GREEN_LEFT
1, // PAD_GREEN_RIGHT
2, // PAD_RED
11, // PAD_START
8, // PAD_SELECT
}};
this->rawInputs[index] = static_cast<u8>(std::clamp(value * 255.0f, 0.0f, 255.0f));
if (value)
@@ -407,6 +392,20 @@ void PadPopn::SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8,
{
}
void PadPopn::SetRawPressureButton(u32 index, const std::tuple<bool, u8> value)
{
this->rawInputs[index] = std::get<1>(value);
if (std::get<0>(value))
{
this->buttons &= ~(1u << bitmaskMapping[index]);
}
else
{
this->buttons |= (1u << bitmaskMapping[index]);
}
}
void PadPopn::SetAxisScale(float deadzone, float scale)
{
}

View File

@@ -59,6 +59,21 @@ private:
bool commandStage = false;
u32 responseBytes = 0;
// Since we reordered the buttons for better UI, we need to remap them here.
static constexpr std::array<u8, Inputs::LENGTH> bitmaskMapping = {{
5, // PAD_YELLOW_LEFT
12, // PAD_YELLOW_RIGHT
6, // PAD_BLUE_LEFT
7, // PAD_BLUE_RIGHT
4, // PAD_WHITE_LEFT
0, // PAD_WHITE_RIGHT
3, // PAD_GREEN_LEFT
1, // PAD_GREEN_RIGHT
2, // PAD_RED
11, // PAD_START
8, // PAD_SELECT
}};
void ConfigLog();
u8 Mystery(u8 commandByte);
@@ -81,6 +96,7 @@ public:
const Pad::ControllerInfo& GetInfo() const override;
void Set(u32 index, float value) override;
void SetRawAnalogs(const std::tuple<u8, u8> left, const std::tuple<u8, u8> right) override;
void SetRawPressureButton(u32 index, const std::tuple<bool, u8> value) override;
void SetAxisScale(float deadzone, float scale) override;
float GetVibrationScale(u32 motor) const override;
void SetVibrationScale(u32 motor, float scale) override;

View File

@@ -548,7 +548,7 @@ static void recReserveRAM()
recLUT_SetPage(recLUT, hwLUT, recROM1, 0xa000, i, i - 0x1e00);
}
for (int i = 0x1e40; i < 0x1e48; i++)
for (int i = 0x1e40; i < 0x1e80; i++)
{
recLUT_SetPage(recLUT, hwLUT, recROM2, 0x0000, i, i - 0x1e40);
recLUT_SetPage(recLUT, hwLUT, recROM2, 0x8000, i, i - 0x1e40);
@@ -691,7 +691,7 @@ static void recExecute()
if (!fastjmp_set(&m_SetJmp_StateCheck))
{
eeCpuExecuting = true;
((void(*)())EnterRecompiledCode)();
((void (*)())EnterRecompiledCode)();
// Generally unreachable code here ...
}
@@ -1544,7 +1544,7 @@ void dynarecMemcheck(size_t i)
auto mc = CBreakPoints::GetMemChecks(BREAKPOINT_EE)[i];
if(mc.hasCond)
if (mc.hasCond)
{
if (!mc.cond.Evaluate())
return;
@@ -1557,7 +1557,7 @@ void dynarecMemcheck(size_t i)
else
DevCon.WriteLn("Hit load breakpoint @0x%x", cpuRegs.pc);
}
CBreakPoints::SetBreakpointTriggered(true, BREAKPOINT_EE);
VMManager::SetPaused(true);
recExitExecution();