mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dc015c0a3 | ||
|
|
edd39dfe08 | ||
|
|
f5320e201e | ||
|
|
37569d1526 | ||
|
|
1efeab4078 | ||
|
|
2bff3579e5 | ||
|
|
2fa85c56c2 | ||
|
|
ded55635c1 | ||
|
|
c9b8874eb6 | ||
|
|
9172a1a6f8 | ||
|
|
b2ac7afbcb | ||
|
|
dcfd663c19 | ||
|
|
225f057a5c | ||
|
|
0017e33023 | ||
|
|
76ced16f9e | ||
|
|
245937eb85 | ||
|
|
3a72328d55 | ||
|
|
06bc0300c0 | ||
|
|
98dcf40967 | ||
|
|
6b61ffbb63 | ||
|
|
dd7eef723a | ||
|
|
328275cd45 | ||
|
|
a4f1431bcc | ||
|
|
473df8dad4 | ||
|
|
042959958e | ||
|
|
cd4de28b9e | ||
|
|
24a87c3fee | ||
|
|
17567b960f | ||
|
|
7a3d22ecdf | ||
|
|
7e5016fdab | ||
|
|
47606400fa | ||
|
|
d6076a6107 | ||
|
|
95c57462cc | ||
|
|
48a1ec3531 | ||
|
|
9da3bccca2 | ||
|
|
a1a92920b2 | ||
|
|
b6b775e44e | ||
|
|
5ea46ac076 | ||
|
|
ab008bf5d0 | ||
|
|
54782cbf70 | ||
|
|
3c7cff99f4 | ||
|
|
f326e8775f | ||
|
|
a2a711b1b3 | ||
|
|
dfb857b68f | ||
|
|
ad64d88e7b | ||
|
|
cbd207d3f4 | ||
|
|
4bf8b23204 | ||
|
|
951780b43d | ||
|
|
84fe413635 | ||
|
|
17aaa31362 | ||
|
|
f943bdad98 | ||
|
|
09b2b6f949 | ||
|
|
c46902c0f5 | ||
|
|
c0dce9f64b | ||
|
|
cd3e11bff7 |
2
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
2
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
58
.gitignore
vendored
@@ -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
|
||||
|
||||
15
3rdparty/cpuinfo/cpuinfo.vcxproj
vendored
15
3rdparty/cpuinfo/cpuinfo.vcxproj
vendored
@@ -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" />
|
||||
|
||||
15
3rdparty/cpuinfo/cpuinfo.vcxproj.filters
vendored
15
3rdparty/cpuinfo/cpuinfo.vcxproj.filters
vendored
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -24,8 +24,11 @@
|
||||
#include "SettingWidgetBinder.h"
|
||||
|
||||
#include "ui_USBBindingWidget_DrivingForce.h"
|
||||
#include "ui_USBBindingWidget_Gametrak.h"
|
||||
#include "ui_USBBindingWidget_GTForce.h"
|
||||
#include "ui_USBBindingWidget_GunCon2.h"
|
||||
#include "ui_USBBindingWidget_RealPlay.h"
|
||||
#include "ui_USBBindingWidget_TranceVibrator.h"
|
||||
|
||||
ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSettingsWindow* dialog, u32 port)
|
||||
: QWidget(parent)
|
||||
@@ -963,6 +966,7 @@ QIcon USBDeviceWidget::getIcon() const
|
||||
{"hidmouse", "mouse-line"}, // HID Mouse
|
||||
{"RBDrumKit", "drum-line"}, // Rock Band Drum Kit
|
||||
{"BuzzDevice", "buzz-controller-line"}, // Buzz Controller
|
||||
{"TranceVibrator", "trance-vibrator-line"}, // Trance Vibrator
|
||||
{"webcam", "eyetoy-line"}, // EyeToy
|
||||
{"beatmania", "keyboard-2-line"}, // BeatMania Da Da Da!! (Konami Keyboard)
|
||||
{"seamic", "seamic-line"}, // SEGA Seamic
|
||||
@@ -1300,6 +1304,13 @@ void USBBindingWidget::bindWidgets(std::span<const InputBindingInfo> bindings)
|
||||
|
||||
widget->initialize(sif, bi.bind_type, getConfigSection(), getBindingKey(bi.name));
|
||||
}
|
||||
|
||||
if (bi.bind_type == InputBindingInfo::Type::Motor)
|
||||
{
|
||||
InputVibrationBindingWidget* widget = findChild<InputVibrationBindingWidget*>(QString::fromUtf8(bi.name));
|
||||
if (widget)
|
||||
widget->setKey(getDialog(), getConfigSection(), getBindingKey(bi.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1322,11 +1333,26 @@ USBBindingWidget* USBBindingWidget::createInstance(
|
||||
has_template = true;
|
||||
}
|
||||
}
|
||||
else if (type == "Gametrak")
|
||||
{
|
||||
Ui::USBBindingWidget_Gametrak().setupUi(widget);
|
||||
has_template = true;
|
||||
}
|
||||
else if (type == "guncon2")
|
||||
{
|
||||
Ui::USBBindingWidget_GunCon2().setupUi(widget);
|
||||
has_template = true;
|
||||
}
|
||||
else if (type == "RealPlay")
|
||||
{
|
||||
Ui::USBBindingWidget_RealPlay().setupUi(widget);
|
||||
has_template = true;
|
||||
}
|
||||
else if (type == "TranceVibrator")
|
||||
{
|
||||
Ui::USBBindingWidget_TranceVibrator().setupUi(widget);
|
||||
has_template = true;
|
||||
}
|
||||
|
||||
if (has_template)
|
||||
widget->bindWidgets(bindings);
|
||||
|
||||
@@ -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,17 @@ 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));
|
||||
//: First arg is a GameList compat; second is a string with space followed by star rating OR empty if Unknown compat
|
||||
m_ui.compatibility->setText(tr("%0%1")
|
||||
.arg(GameList::EntryCompatibilityRatingToString(entry->compatibility_rating))
|
||||
.arg([entry]() {
|
||||
if (entry->compatibility_rating == GameList::CompatibilityRating::Unknown)
|
||||
return QStringLiteral("");
|
||||
|
||||
const qsizetype compatibility_value = static_cast<qsizetype>(entry->compatibility_rating);
|
||||
//: First arg is filled-in stars for game compatibility; second is empty stars; should be swapped for RTL languages
|
||||
return tr(" %0%1").arg(QStringLiteral("★").repeated(compatibility_value - 1)).arg(QStringLiteral("☆").repeated(6 - compatibility_value));
|
||||
}()));
|
||||
|
||||
int row = 0;
|
||||
m_ui.detailsFormLayout->getWidgetPosition(m_ui.titleSort, &row, nullptr);
|
||||
@@ -348,6 +356,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);
|
||||
|
||||
@@ -28,6 +28,7 @@ private Q_SLOTS:
|
||||
void onDiscPathBrowseClicked();
|
||||
void onVerifyClicked();
|
||||
void onSearchHashClicked();
|
||||
void onCheckWikiClicked(const GameList::Entry* entry);
|
||||
|
||||
private:
|
||||
void populateInputProfiles();
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -38,6 +38,7 @@ private Q_SLOTS:
|
||||
void onTextureReplacementChanged();
|
||||
void onShadeBoostChanged();
|
||||
void onCaptureContainerChanged();
|
||||
void onCaptureCodecChanged();
|
||||
void onEnableVideoCaptureChanged();
|
||||
void onEnableVideoCaptureArgumentsChanged();
|
||||
void onVideoCaptureAutoResolutionChanged();
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
436
pcsx2-qt/Settings/USBBindingWidget_Gametrak.ui
Normal file
436
pcsx2-qt/Settings/USBBindingWidget_Gametrak.ui
Normal file
@@ -0,0 +1,436 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>USBBindingWidget_Gametrak</class>
|
||||
<widget class="QWidget" name="USBBindingWidget_Gametrak">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1100</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<spacer name="horizontalSpacer0">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QVBoxLayout" name="verticalLayout1">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox1">
|
||||
<property name="title">
|
||||
<string>Left Hand</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox1_X">
|
||||
<property name="title">
|
||||
<string>X Axis</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout1_X">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="LeftX">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label1_X">
|
||||
<property name="text">
|
||||
<string>Left=0 / Right=0x3ff</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox1_Y">
|
||||
<property name="title">
|
||||
<string>Y Axis</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout1_Y">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="LeftY">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label1_Y">
|
||||
<property name="text">
|
||||
<string>Back=0 / Front=0x3ff</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="groupBox1_Z">
|
||||
<property name="title">
|
||||
<string>Z Axis</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout1_Z">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="LeftZ">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label1_Z">
|
||||
<property name="text">
|
||||
<string>Top=0 / Bottom=0xfff</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox2">
|
||||
<property name="title">
|
||||
<string>Foot Pedal</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="FootPedal">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox3">
|
||||
<property name="title">
|
||||
<string>Right Hand</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox3_X">
|
||||
<property name="title">
|
||||
<string>X Axis</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout3_X">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="RightX">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label3_X">
|
||||
<property name="text">
|
||||
<string>Left=0 / Right=0x3ff</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox3_Y">
|
||||
<property name="title">
|
||||
<string>Y Axis</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout3_Y">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="RightY">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label3_Y">
|
||||
<property name="text">
|
||||
<string>Back=0 / Front=0x3ff</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QGroupBox" name="groupBox3_Z">
|
||||
<property name="title">
|
||||
<string>Z Axis</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout3_Z">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="RightZ">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label3_Z">
|
||||
<property name="text">
|
||||
<string>Top=0 / Bottom=0xfff</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<spacer name="horizontalSpacer4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>InputBindingWidget</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
506
pcsx2-qt/Settings/USBBindingWidget_RealPlay.ui
Normal file
506
pcsx2-qt/Settings/USBBindingWidget_RealPlay.ui
Normal file
@@ -0,0 +1,506 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>USBBindingWidget_RealPlay</class>
|
||||
<widget class="QWidget" name="USBBindingWidget_RealPlay">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1100</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="2">
|
||||
<widget class="QGroupBox" name="groupBoxDPadUp">
|
||||
<property name="title">
|
||||
<string>D-Pad Up</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutDPadUp">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="DPadUp">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QGroupBox" name="groupBoxDPadDown">
|
||||
<property name="title">
|
||||
<string>D-Pad Down</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutDPadDown">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="DPadDown">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGroupBox" name="groupBoxDPadLeft">
|
||||
<property name="title">
|
||||
<string>D-Pad Left</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutDPadLeft">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="DPadLeft">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QGroupBox" name="groupBoxDPadRight">
|
||||
<property name="title">
|
||||
<string>D-Pad Right</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutDPadRight">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="DPadRight">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6">
|
||||
<widget class="QGroupBox" name="groupBoxBtnRed">
|
||||
<property name="title">
|
||||
<string>Red</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutBtnRed">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Red">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="6">
|
||||
<widget class="QGroupBox" name="groupBoxBtnGreen">
|
||||
<property name="title">
|
||||
<string>Green</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutBtnGreen">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Green">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<widget class="QGroupBox" name="groupBoxBtnYellow">
|
||||
<property name="title">
|
||||
<string>Yellow</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutBtnYellow">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Yellow">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="7">
|
||||
<widget class="QGroupBox" name="groupBoxBtnBlue">
|
||||
<property name="title">
|
||||
<string>Blue</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutBtnBlue">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="Blue">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QGroupBox" name="groupBoxAccelX">
|
||||
<property name="title">
|
||||
<string>Accel X</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutAccelX">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="AccelX">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QGroupBox" name="groupBoxAccelY">
|
||||
<property name="title">
|
||||
<string>Accel Y</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutAccelY">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="AccelY">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="5">
|
||||
<widget class="QGroupBox" name="groupBoxAccelZ">
|
||||
<property name="title">
|
||||
<string>Accel Z</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutAccelZ">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputBindingWidget" name="AccelZ">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>130</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" rowspan="4">
|
||||
<spacer name="horizontalSpacer0">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="8" rowspan="4">
|
||||
<spacer name="horizontalSpacer8">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="7">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>InputBindingWidget</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
116
pcsx2-qt/Settings/USBBindingWidget_TranceVibrator.ui
Normal file
116
pcsx2-qt/Settings/USBBindingWidget_TranceVibrator.ui
Normal file
@@ -0,0 +1,116 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>USBBindingWidget_TranceVibrator</class>
|
||||
<widget class="QWidget" name="USBBindingWidget_TranceVibrator">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1100</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>1100</width>
|
||||
<height>500</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_1">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<spacer name="horizontalSpacer0">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Motor</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="InputVibrationBindingWidget" name="Motor">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">PushButton</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer1">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>InputVibrationBindingWidget</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>Settings/InputBindingWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources/resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -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
@@ -395,9 +395,6 @@
|
||||
</QtUi>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUi Include="Settings\USBBindingWidget_GunCon2.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="SetupWizardDialog.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
@@ -422,9 +419,21 @@
|
||||
<QtUi Include="Settings\USBBindingWidget_DrivingForce.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBBindingWidget_Gametrak.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBBindingWidget_GTForce.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBBindingWidget_GunCon2.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBBindingWidget_RealPlay.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBBindingWidget_TranceVibrator.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBDeviceWidget.ui">
|
||||
<FileType>Document</FileType>
|
||||
</QtUi>
|
||||
|
||||
@@ -660,12 +660,21 @@
|
||||
<QtUi Include="Settings\USBBindingWidget_DrivingForce.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBBindingWidget_Gametrak.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBBindingWidget_GTForce.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBBindingWidget_GunCon2.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBBindingWidget_RealPlay.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\USBBindingWidget_TranceVibrator.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
<QtUi Include="Settings\AudioExpansionSettingsDialog.ui">
|
||||
<Filter>Settings</Filter>
|
||||
</QtUi>
|
||||
|
||||
7
pcsx2-qt/resources/icons/black/svg/camera-video.svg
Normal file
7
pcsx2-qt/resources/icons/black/svg/camera-video.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="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 |
19
pcsx2-qt/resources/icons/black/svg/trance-vibrator-line.svg
Normal file
19
pcsx2-qt/resources/icons/black/svg/trance-vibrator-line.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -10 100 110" >
|
||||
<g>
|
||||
<path
|
||||
fill="none"
|
||||
stroke="black"
|
||||
stroke-width="8"
|
||||
stroke-miterlimit="5"
|
||||
d="m 0 50
|
||||
l 20,0
|
||||
l 7.5,20
|
||||
l 15,-45
|
||||
l 15,55
|
||||
l 15,-65
|
||||
l 7.5,35
|
||||
l 20,0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 332 B |
7
pcsx2-qt/resources/icons/white/svg/camera-video.svg
Normal file
7
pcsx2-qt/resources/icons/white/svg/camera-video.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Transformed by: SVG Repo Mixer Tools -->
|
||||
<svg width="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 |
19
pcsx2-qt/resources/icons/white/svg/trance-vibrator-line.svg
Normal file
19
pcsx2-qt/resources/icons/white/svg/trance-vibrator-line.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -10 100 110" >
|
||||
<g>
|
||||
<path
|
||||
fill="none"
|
||||
stroke="white"
|
||||
stroke-width="8"
|
||||
stroke-miterlimit="5"
|
||||
d="m 0 50
|
||||
l 20,0
|
||||
l 7.5,20
|
||||
l 15,-45
|
||||
l 15,55
|
||||
l 15,-65
|
||||
l 7.5,35
|
||||
l 20,0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 332 B |
@@ -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>
|
||||
@@ -82,6 +83,7 @@
|
||||
<file>icons/black/svg/shut-down-line.svg</file>
|
||||
<file>icons/black/svg/singstar-line.svg</file>
|
||||
<file>icons/black/svg/tools-line.svg</file>
|
||||
<file>icons/black/svg/trance-vibrator-line.svg</file>
|
||||
<file>icons/black/svg/trash-fill.svg</file>
|
||||
<file>icons/black/svg/trophy-line.svg</file>
|
||||
<file>icons/black/svg/tv-2-line.svg</file>
|
||||
@@ -105,16 +107,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>
|
||||
@@ -178,6 +181,7 @@
|
||||
<file>icons/white/svg/shut-down-line.svg</file>
|
||||
<file>icons/white/svg/singstar-line.svg</file>
|
||||
<file>icons/white/svg/tools-line.svg</file>
|
||||
<file>icons/white/svg/trance-vibrator-line.svg</file>
|
||||
<file>icons/white/svg/trash-fill.svg</file>
|
||||
<file>icons/white/svg/trophy-line.svg</file>
|
||||
<file>icons/white/svg/tv-2-line.svg</file>
|
||||
|
||||
@@ -1052,8 +1052,8 @@ void Achievements::DisplayHardcoreDeferredMessage()
|
||||
if (VMManager::HasValidVM() && EmuConfig.Achievements.HardcoreMode && !s_hardcore_mode &&
|
||||
ImGuiManager::InitializeFullscreenUI())
|
||||
{
|
||||
ImGuiFullscreen::ShowToast(
|
||||
std::string(), TRANSLATE_STR("Achievements", "Hardcore mode will be enabled on system reset."),
|
||||
Host::AddIconOSDMessage(
|
||||
"hardcore_on_reset", ICON_PF_DUMBELL, TRANSLATE_STR("Achievements", "Hardcore mode will be enabled on system reset."),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
}
|
||||
});
|
||||
@@ -1343,9 +1343,8 @@ void Achievements::HandleServerDisconnectedEvent(const rc_client_event_t* event)
|
||||
MTGS::RunOnGSThread([]() {
|
||||
if (ImGuiManager::InitializeFullscreenUI())
|
||||
{
|
||||
ImGuiFullscreen::ShowToast(TRANSLATE_STR("Achievements", "Achievements Disconnected"),
|
||||
TRANSLATE_STR("Achievements", "An unlock request could not be completed. We will keep retrying to submit this request."),
|
||||
Host::OSD_ERROR_DURATION);
|
||||
ImGuiFullscreen::AddNotification("achievements_disconnect", Host::OSD_ERROR_DURATION, TRANSLATE_STR("Achievements", "Achievements Disconnected"),
|
||||
TRANSLATE_STR("Achievements", "An unlock request could not be completed. We will keep retrying to submit this request."), s_game_icon);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1357,8 +1356,8 @@ void Achievements::HandleServerReconnectedEvent(const rc_client_event_t* event)
|
||||
MTGS::RunOnGSThread([]() {
|
||||
if (ImGuiManager::InitializeFullscreenUI())
|
||||
{
|
||||
ImGuiFullscreen::ShowToast(TRANSLATE_STR("Achievements", "Achievements Reconnected"),
|
||||
TRANSLATE_STR("Achievements", "All pending unlock requests have completed."), Host::OSD_INFO_DURATION);
|
||||
ImGuiFullscreen::AddNotification("achievements_reconnect", Host::OSD_INFO_DURATION, TRANSLATE_STR("Achievements", "Achievements Reconnected"),
|
||||
TRANSLATE_STR("Achievements", "All pending unlock requests have completed."), s_game_icon);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -1445,7 +1444,7 @@ void Achievements::SetHardcoreMode(bool enabled, bool force_display_message)
|
||||
MTGS::RunOnGSThread([enabled]() {
|
||||
if (ImGuiManager::InitializeFullscreenUI())
|
||||
{
|
||||
ImGuiFullscreen::ShowToast(std::string(),
|
||||
Host::AddIconOSDMessage("hardcore_status", ICON_PF_DUMBELL,
|
||||
enabled ? TRANSLATE_STR("Achievements", "Hardcore mode is now enabled.") :
|
||||
TRANSLATE_STR("Achievements", "Hardcore mode is now disabled."),
|
||||
Host::OSD_INFO_DURATION);
|
||||
@@ -1858,7 +1857,7 @@ void Achievements::ConfirmHardcoreModeDisableAsync(const char* trigger, std::fun
|
||||
MTGS::RunOnGSThread([trigger = TinyString(trigger), callback = std::move(callback)]() {
|
||||
if (!FullscreenUI::Initialize())
|
||||
{
|
||||
Host::AddOSDMessage(fmt::format(TRANSLATE_FS("Cannot {} while hardcode mode is active.", trigger)),
|
||||
Host::AddOSDMessage(fmt::format(TRANSLATE_FS("Cannot {} while hardcore mode is active.", trigger)),
|
||||
Host::OSD_WARNING_DURATION);
|
||||
callback(false);
|
||||
return;
|
||||
@@ -2931,7 +2930,8 @@ void Achievements::LeaderboardFetchNearbyCallback(
|
||||
|
||||
if (result != RC_OK)
|
||||
{
|
||||
ImGuiFullscreen::ShowToast(TRANSLATE("Achievements", "Leaderboard download failed"), error_message);
|
||||
ImGuiFullscreen::AddNotification("leaderboard_dl_fail", Host::OSD_INFO_DURATION,
|
||||
TRANSLATE("Achievements", "Leaderboard Download Failed"), error_message, s_game_icon);
|
||||
CloseLeaderboard();
|
||||
return;
|
||||
}
|
||||
@@ -2950,7 +2950,8 @@ void Achievements::LeaderboardFetchAllCallback(
|
||||
|
||||
if (result != RC_OK)
|
||||
{
|
||||
ImGuiFullscreen::ShowToast(TRANSLATE("Achievements", "Leaderboard download failed"), error_message);
|
||||
ImGuiFullscreen::AddNotification("leaderboard_dl_fail", Host::OSD_INFO_DURATION,
|
||||
TRANSLATE("Achievements", "Leaderboard Download Failed"), error_message, s_game_icon);
|
||||
CloseLeaderboard();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -383,10 +383,13 @@ set(pcsx2USBSources
|
||||
USB/usb-mic/usb-mic-singstar.cpp
|
||||
USB/usb-msd/usb-msd.cpp
|
||||
USB/usb-pad/lg/lg_ff.cpp
|
||||
USB/usb-pad/usb-gametrak.cpp
|
||||
USB/usb-pad/usb-realplay.cpp
|
||||
USB/usb-pad/usb-pad-ff.cpp
|
||||
USB/usb-pad/usb-pad-sdl-ff.cpp
|
||||
USB/usb-pad/usb-pad.cpp
|
||||
USB/usb-pad/usb-seamic.cpp
|
||||
USB/usb-pad/usb-trance-vibrator.cpp
|
||||
USB/usb-pad/usb-turntable.cpp
|
||||
USB/usb-printer/usb-printer.cpp
|
||||
)
|
||||
@@ -417,8 +420,11 @@ set(pcsx2USBHeaders
|
||||
USB/usb-mic/usb-mic-singstar.h
|
||||
USB/usb-msd/usb-msd.h
|
||||
USB/usb-pad/lg/lg_ff.h
|
||||
USB/usb-pad/usb-gametrak.h
|
||||
USB/usb-pad/usb-realplay.h
|
||||
USB/usb-pad/usb-pad-sdl-ff.h
|
||||
USB/usb-pad/usb-pad.h
|
||||
USB/usb-pad/usb-trance-vibrator.h
|
||||
USB/usb-printer/usb-printer.h
|
||||
)
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -117,14 +117,14 @@ const char* GameList::EntryCompatibilityRatingToString(CompatibilityRating ratin
|
||||
// clang-format off
|
||||
switch (rating)
|
||||
{
|
||||
case CompatibilityRating::Unknown: return "Unknown";
|
||||
case CompatibilityRating::Nothing: return "Nothing";
|
||||
case CompatibilityRating::Intro: return "Intro";
|
||||
case CompatibilityRating::Menu: return "Menu";
|
||||
case CompatibilityRating::InGame: return "InGame";
|
||||
case CompatibilityRating::Playable: return "Playable";
|
||||
case CompatibilityRating::Perfect: return "Perfect";
|
||||
default: return "";
|
||||
case CompatibilityRating::Unknown: return TRANSLATE("GameList", "Unknown");
|
||||
case CompatibilityRating::Nothing: return TRANSLATE("GameList", "Nothing");
|
||||
case CompatibilityRating::Intro: return TRANSLATE("GameList", "Intro");
|
||||
case CompatibilityRating::Menu: return TRANSLATE("GameList", "Menu");
|
||||
case CompatibilityRating::InGame: return TRANSLATE("GameList", "In-Game");
|
||||
case CompatibilityRating::Playable: return TRANSLATE("GameList", "Playable");
|
||||
case CompatibilityRating::Perfect: return TRANSLATE("GameList", "Perfect");
|
||||
default: return "";
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
@@ -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"),
|
||||
@@ -6919,6 +6922,7 @@ TRANSLATE_NOOP("FullscreenUI", "On-Screen Display");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Determines how large the on-screen messages and monitor are.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "%d%%");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Shows on-screen-display messages when events occur such as save states being created/loaded, screenshots being taken, etc.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Shows the current PCSX2 version on the top-right corner of the display.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Shows the current emulation speed of the system in the top-right corner of the display as a percentage.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Shows the number of video frames (or v-syncs) displayed per second by the system in the top-right corner of the display.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Shows the CPU usage based on threads in the top-right corner of the display.");
|
||||
@@ -7062,6 +7066,8 @@ TRANSLATE_NOOP("FullscreenUI", "When enabled GPU converts colormap-textures, oth
|
||||
TRANSLATE_NOOP("FullscreenUI", "Upscaling Fixes");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Half Pixel Offset");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Adjusts vertices relative to upscaling.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Native Scaling");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Attempt to do rescaling at native resolution.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Round Sprite");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Adjusts sprite coordinates.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Bilinear Upscale");
|
||||
@@ -7407,20 +7413,22 @@ TRANSLATE_NOOP("FullscreenUI", "Blend (Bottom Field First, Half FPS)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Adaptive (Top Field First)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Adaptive (Bottom Field First)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Native (PS2)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "1.25x Native");
|
||||
TRANSLATE_NOOP("FullscreenUI", "1.5x Native");
|
||||
TRANSLATE_NOOP("FullscreenUI", "1.75x Native");
|
||||
TRANSLATE_NOOP("FullscreenUI", "2x Native (~720p)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "2.25x Native");
|
||||
TRANSLATE_NOOP("FullscreenUI", "2.5x Native");
|
||||
TRANSLATE_NOOP("FullscreenUI", "2.75x Native");
|
||||
TRANSLATE_NOOP("FullscreenUI", "3x Native (~1080p)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "3.5x Native");
|
||||
TRANSLATE_NOOP("FullscreenUI", "4x Native (~1440p/2K)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "5x Native (~1620p)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "6x Native (~2160p/4K)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "7x Native (~2520p)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "8x Native (~2880p)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "1.25x Native (~450px)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "1.5x Native (~540px)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "1.75x Native (~630px)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "2x Native (~720px/HD)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "2.5x Native (~900px/HD+)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "3x Native (~1080px/FHD)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "3.5x Native (~1260px)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "4x Native (~1440px/QHD)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "5x Native (~1800px/QHD+)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "6x Native (~2160px/4K UHD)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "7x Native (~2520px)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "8x Native (~2880px/5K UHD)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "9x Native (~3240px)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "10x Native (~3600px/6K UHD)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "11x Native (~3960px)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "12x Native (~4320px/8K UHD)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Nearest");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Bilinear (Forced)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Bilinear (PS2)");
|
||||
@@ -7478,6 +7486,7 @@ TRANSLATE_NOOP("FullscreenUI", "Normal (Vertex)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Special (Texture)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Special (Texture - Aggressive)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Align To Native");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Aggressive");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Half");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Force Bilinear");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Force Nearest");
|
||||
@@ -7559,6 +7568,7 @@ TRANSLATE_NOOP("FullscreenUI", "Double-Click Toggles Fullscreen");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Hide Cursor In Fullscreen");
|
||||
TRANSLATE_NOOP("FullscreenUI", "OSD Scale");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Show Messages");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Show PCSX2 Version");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Show Speed");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Show FPS");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Show CPU Usage");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -868,6 +868,19 @@ void InputManager::AddUSBBindings(SettingsInterface& si, u32 port)
|
||||
}
|
||||
break;
|
||||
|
||||
case InputBindingInfo::Type::Motor:
|
||||
{
|
||||
const std::vector<std::string> bindings(si.GetStringList(section.c_str(), bind_name.c_str()));
|
||||
for (const std::string& binding : bindings)
|
||||
{
|
||||
PadVibrationBinding vib;
|
||||
vib.pad_index = Pad::NUM_CONTROLLER_PORTS + port;
|
||||
ParseBindingAndGetSource(binding, &vib.motors[0].binding, &vib.motors[0].source);
|
||||
s_pad_vibration_array.push_back(std::move(vib));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1219,6 +1232,11 @@ void InputManager::OnInputDeviceDisconnected(const InputBindingKey key, const st
|
||||
// Vibration
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
void InputManager::SetUSBVibrationIntensity(u32 port, float large_or_single_motor_intensity, float small_motor_intensity)
|
||||
{
|
||||
SetPadVibrationIntensity(Pad::NUM_CONTROLLER_PORTS + port, large_or_single_motor_intensity, small_motor_intensity);
|
||||
}
|
||||
|
||||
void InputManager::SetPadVibrationIntensity(u32 pad_index, float large_or_single_motor_intensity, float small_motor_intensity)
|
||||
{
|
||||
for (PadVibrationBinding& pad : s_pad_vibration_array)
|
||||
@@ -1605,7 +1623,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,6 +270,7 @@ namespace InputManager
|
||||
|
||||
/// Internal method used by pads to dispatch vibration updates to input sources.
|
||||
/// Intensity is normalized from 0 to 1.
|
||||
void SetUSBVibrationIntensity(u32 port, float large_or_single_motor_intensity, float small_motor_intensity);
|
||||
void SetPadVibrationIntensity(u32 pad_index, float large_or_single_motor_intensity, float small_motor_intensity);
|
||||
|
||||
/// Zeros all vibration intensities. Call when pausing.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
|
||||
#include "deviceproxy.h"
|
||||
#include "usb-eyetoy/usb-eyetoy-webcam.h"
|
||||
#include "usb-pad/usb-gametrak.h"
|
||||
#include "usb-pad/usb-realplay.h"
|
||||
#include "usb-hid/usb-hid.h"
|
||||
#include "usb-mic/usb-headset.h"
|
||||
#include "usb-mic/usb-mic-singstar.h"
|
||||
#include "usb-msd/usb-msd.h"
|
||||
#include "usb-pad/usb-pad.h"
|
||||
#include "usb-pad/usb-trance-vibrator.h"
|
||||
#include "usb-pad/usb-turntable.h"
|
||||
#include "usb-printer/usb-printer.h"
|
||||
#include "usb-lightgun/guncon2.h"
|
||||
@@ -74,10 +77,13 @@ void RegisterDevice::Register()
|
||||
inst.Add(DEVTYPE_BUZZ, new usb_pad::BuzzDevice());
|
||||
inst.Add(DEVTYPE_EYETOY, new usb_eyetoy::EyeToyWebCamDevice());
|
||||
inst.Add(DEVTYPE_BEATMANIA_DADADA, new usb_hid::BeatManiaDevice());
|
||||
inst.Add(DEVTYPE_TRANCE_VIBRATOR, new usb_pad::TranceVibratorDevice());
|
||||
inst.Add(DEVTYPE_SEGA_SEAMIC, new usb_pad::SeamicDevice());
|
||||
inst.Add(DEVTYPE_PRINTER, new usb_printer::PrinterDevice());
|
||||
inst.Add(DEVTYPE_KEYBOARDMANIA, new usb_pad::KeyboardmaniaDevice());
|
||||
inst.Add(DEVTYPE_GUNCON2, new usb_lightgun::GunCon2Device());
|
||||
inst.Add(DEVTYPE_GAMETRAK, new usb_pad::GametrakDevice());
|
||||
inst.Add(DEVTYPE_REALPLAY, new usb_pad::RealPlayDevice());
|
||||
}
|
||||
|
||||
void RegisterDevice::Unregister()
|
||||
|
||||
@@ -35,11 +35,14 @@ enum DeviceType : s32
|
||||
DEVTYPE_BUZZ,
|
||||
DEVTYPE_EYETOY,
|
||||
DEVTYPE_BEATMANIA_DADADA,
|
||||
DEVTYPE_TRANCE_VIBRATOR,
|
||||
DEVTYPE_SEGA_SEAMIC,
|
||||
DEVTYPE_PRINTER,
|
||||
DEVTYPE_KEYBOARDMANIA,
|
||||
DEVTYPE_GUNCON2,
|
||||
DEVTYPE_DJ
|
||||
DEVTYPE_DJ,
|
||||
DEVTYPE_GAMETRAK,
|
||||
DEVTYPE_REALPLAY,
|
||||
};
|
||||
|
||||
class DeviceProxy
|
||||
|
||||
408
pcsx2/USB/usb-pad/usb-gametrak.cpp
Normal file
408
pcsx2/USB/usb-pad/usb-gametrak.cpp
Normal file
@@ -0,0 +1,408 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#include "Host.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "StateWrapper.h"
|
||||
#include "USB/USB.h"
|
||||
#include "USB/deviceproxy.h"
|
||||
#include "USB/qemu-usb/USBinternal.h"
|
||||
#include "USB/qemu-usb/desc.h"
|
||||
#include "USB/usb-pad/usb-gametrak.h"
|
||||
#include "USB/usb-pad/usb-pad.h"
|
||||
#include <common/Console.h>
|
||||
|
||||
namespace usb_pad
|
||||
{
|
||||
static const USBDescStrings desc_strings = {
|
||||
"",
|
||||
"In2Games Ltd.",
|
||||
"Game-Trak V1.3"};
|
||||
|
||||
static uint8_t dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x10, 0x01, // bcdUSB 1.10
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x08, // bMaxPacketSize0 8
|
||||
0xB7, 0x14, // idVendor 0x14B7
|
||||
0x82, 0x09, // idProduct 0x0982
|
||||
0x01, 0x00, // bcdDevice 0.01
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t config_descriptor[] = {
|
||||
0x09, // bLength
|
||||
0x02, // bDescriptorType (Configuration)
|
||||
0x22, 0x00, // wTotalLength 34
|
||||
0x01, // bNumInterfaces 1
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration (String Index)
|
||||
0x80, // bmAttributes
|
||||
0x0A, // bMaxPower 20mA
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x00, // bInterfaceNumber 0
|
||||
0x00, // bAlternateSetting
|
||||
0x01, // bNumEndpoints 1
|
||||
0x03, // bInterfaceClass
|
||||
0x00, // bInterfaceSubClass
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x09, // bLength
|
||||
0x21, // bDescriptorType (HID)
|
||||
0x01, 0x01, // bcdHID 1.01
|
||||
0x00, // bCountryCode
|
||||
0x01, // bNumDescriptors
|
||||
0x22, // bDescriptorType[0] (HID)
|
||||
0x7A, 0x00, // wDescriptorLength[0] 122
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x81, // bEndpointAddress (IN/D2H)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x10, 0x00, // wMaxPacketSize 16
|
||||
0x0A, // bInterval 10 (unit depends on device speed)
|
||||
};
|
||||
|
||||
static const uint8_t hid_report_descriptor[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x04, // Usage (Joystick)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x09, 0x01, // Usage (Pointer)
|
||||
0xA1, 0x00, // Collection (Physical)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x09, 0x33, // Usage (Rx)
|
||||
0x09, 0x34, // Usage (Ry)
|
||||
0x09, 0x35, // Usage (Rz)
|
||||
0x16, 0x00, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x0F, // Logical Maximum (4095)
|
||||
0x36, 0x00, 0x00, // Physical Minimum (0)
|
||||
0x46, 0xFF, 0x0F, // Physical Maximum (4095)
|
||||
0x66, 0x00, 0x00, // Unit (None)
|
||||
0x75, 0x10, // Report Size (16)
|
||||
0x95, 0x06, // Report Count (6)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, // End Collection
|
||||
0x09, 0x39, // Usage (Hat switch)
|
||||
0x15, 0x01, // Logical Minimum (1)
|
||||
0x25, 0x08, // Logical Maximum (8)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0x3B, 0x01, // Physical Maximum (315)
|
||||
0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter)
|
||||
0x75, 0x04, // Report Size (4)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (0x01)
|
||||
0x29, 0x0C, // Usage Maximum (0x0C)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x0C, // Report Count (12)
|
||||
0x55, 0x00, // Unit Exponent (0)
|
||||
0x65, 0x00, // Unit (None)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x02, // Report Count (2)
|
||||
0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x08, // Usage Page (LEDs)
|
||||
0x09, 0x43, // Usage (Slow Blink On Time)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||
0x09, 0x44, // Usage (Slow Blink Off Time)
|
||||
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||
0x09, 0x45, // Usage (Fast Blink On Time)
|
||||
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||
0x09, 0x46, // Usage (Fast Blink Off Time)
|
||||
0x91, 0x82, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Volatile)
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
GametrakState::GametrakState(u32 port_)
|
||||
: port(port_)
|
||||
{
|
||||
}
|
||||
|
||||
GametrakState::~GametrakState() = default;
|
||||
|
||||
static u32 gametrak_compute_key(u32* key)
|
||||
{
|
||||
u32 ret = 0;
|
||||
ret = *key << 2 & 0xFC0000;
|
||||
ret |= *key << 17 & 0x020000;
|
||||
ret ^= *key << 16 & 0xFE0000;
|
||||
ret |= *key & 0x010000;
|
||||
ret |= *key >> 9 & 0x007F7F;
|
||||
ret |= *key << 7 & 0x008080;
|
||||
*key = ret;
|
||||
return ret >> 16;
|
||||
};
|
||||
|
||||
static void gametrak_handle_control(USBDevice* dev, USBPacket* p,
|
||||
int request, int value, int index, int length, uint8_t* data)
|
||||
{
|
||||
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||
int ret = 0;
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
|
||||
switch (value >> 8)
|
||||
{
|
||||
case USB_DT_REPORT:
|
||||
ret = sizeof(hid_report_descriptor);
|
||||
memcpy(data, hid_report_descriptor, ret);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SET_REPORT:
|
||||
{
|
||||
constexpr u8 secret[] = "Gametrak";
|
||||
if (length == 8 && std::memcmp(data, secret, sizeof(secret)) == 0)
|
||||
{
|
||||
s->state = 0;
|
||||
s->key = 0;
|
||||
}
|
||||
else if (length == 2)
|
||||
{
|
||||
if (data[0] == 0x45)
|
||||
{
|
||||
s->key = data[1] << 16;
|
||||
}
|
||||
|
||||
if ((s->key >> 16) == data[1])
|
||||
{
|
||||
gametrak_compute_key(&s->key);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG("gametrak error : own key = {}, recv key = {}", s->key >> 16, data[1]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SET_IDLE:
|
||||
break;
|
||||
default:
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void gametrak_handle_data(USBDevice* dev, USBPacket* p)
|
||||
{
|
||||
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||
|
||||
switch (p->pid)
|
||||
{
|
||||
case USB_TOKEN_IN:
|
||||
if (p->ep->nr == 1)
|
||||
{
|
||||
pxAssert(p->buffer_size >= sizeof(s->data));
|
||||
|
||||
if (s->state == 0)
|
||||
{
|
||||
s->state = 1;
|
||||
constexpr u8 secret[] = "Gametrak\0\0\0\0\0\0\0\0";
|
||||
std::memcpy(p->buffer_ptr, secret, sizeof(secret));
|
||||
}
|
||||
else
|
||||
{
|
||||
s->data.k1 = s->key >> 16 & 1;
|
||||
s->data.k2 = s->key >> 17 & 1;
|
||||
s->data.k3 = s->key >> 18 & 1;
|
||||
s->data.k4 = s->key >> 19 & 1;
|
||||
s->data.k5 = s->key >> 20 & 1;
|
||||
s->data.k6 = s->key >> 21 & 1;
|
||||
|
||||
auto time = std::chrono::steady_clock::now();
|
||||
if (std::chrono::duration_cast<std::chrono::milliseconds>(time - s->last_log).count() > 500)
|
||||
{
|
||||
Log::Write(LOGLEVEL_INFO, Color_Green, "{} LX={} LY={} LZ={} RX={} RY={} RZ={} Btn={}",
|
||||
__FUNCTION__,
|
||||
(u16)s->data.left_x, (u16)s->data.left_y, (u16)s->data.left_z,
|
||||
(u16)s->data.right_x, (u16)s->data.right_y, (u16)s->data.right_z,
|
||||
(u8)s->data.button);
|
||||
s->last_log = time;
|
||||
}
|
||||
|
||||
std::memcpy(p->buffer_ptr, &s->data, sizeof(s->data));
|
||||
}
|
||||
|
||||
p->actual_length += sizeof(s->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case USB_TOKEN_OUT:
|
||||
break;
|
||||
default:
|
||||
fail:
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void gametrak_unrealize(USBDevice* dev)
|
||||
{
|
||||
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||
delete s;
|
||||
}
|
||||
|
||||
const char* GametrakDevice::Name() const
|
||||
{
|
||||
return TRANSLATE_NOOP("USB", "Gametrak Device");
|
||||
}
|
||||
|
||||
const char* GametrakDevice::TypeName() const
|
||||
{
|
||||
return "Gametrak";
|
||||
}
|
||||
|
||||
USBDevice* GametrakDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const
|
||||
{
|
||||
GametrakState* s = new GametrakState(port);
|
||||
|
||||
s->desc.full = &s->desc_dev;
|
||||
s->desc.str = desc_strings;
|
||||
|
||||
if (usb_desc_parse_dev(dev_descriptor, sizeof(dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(config_descriptor, sizeof(config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
|
||||
s->dev.speed = USB_SPEED_FULL;
|
||||
s->dev.klass.handle_attach = usb_desc_attach;
|
||||
s->dev.klass.handle_reset = nullptr;
|
||||
s->dev.klass.handle_control = gametrak_handle_control;
|
||||
s->dev.klass.handle_data = gametrak_handle_data;
|
||||
s->dev.klass.unrealize = gametrak_unrealize;
|
||||
s->dev.klass.usb_desc = &s->desc;
|
||||
s->dev.klass.product_desc = nullptr;
|
||||
|
||||
usb_desc_init(&s->dev);
|
||||
usb_ep_init(&s->dev);
|
||||
|
||||
return &s->dev;
|
||||
|
||||
fail:
|
||||
gametrak_unrealize(&s->dev);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool GametrakDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||
|
||||
if (!sw.DoMarker("GametrakDevice"))
|
||||
return false;
|
||||
|
||||
sw.Do(&s->state);
|
||||
sw.Do(&s->key);
|
||||
return !sw.HasError();
|
||||
}
|
||||
|
||||
float GametrakDevice::GetBindingValue(const USBDevice* dev, u32 bind_index) const
|
||||
{
|
||||
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||
if (bind_index == CID_GT_BUTTON)
|
||||
return s->data.button;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void GametrakDevice::SetBindingValue(USBDevice* dev, u32 bind_index, float value) const
|
||||
{
|
||||
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||
switch (bind_index)
|
||||
{
|
||||
case CID_GT_BUTTON:
|
||||
s->data.button = (value >= 0.5f);
|
||||
break;
|
||||
case CID_GT_LEFT_X:
|
||||
s->data.left_x = static_cast<u16>(std::clamp<long>(std::lroundf(value * 2047.f), 0, 2047));
|
||||
s->data.left_x = s->invert_x_axis ? 2047 - s->data.left_x : s->data.left_x;
|
||||
break;
|
||||
case CID_GT_LEFT_Y:
|
||||
s->data.left_y = static_cast<u16>(std::clamp<long>(std::lroundf(value * 2047.f), 0, 2047));
|
||||
s->data.left_y = s->invert_y_axis ? 2047 - s->data.left_y : s->data.left_y;
|
||||
break;
|
||||
case CID_GT_LEFT_Z:
|
||||
s->data.left_z = static_cast<u32>(std::clamp<long>(std::lroundf(value * s->limit_z_axis), 0, s->limit_z_axis));
|
||||
s->data.left_z = s->invert_z_axis ? s->limit_z_axis - s->data.left_z : s->data.left_z;
|
||||
break;
|
||||
case CID_GT_RIGHT_X:
|
||||
s->data.right_x = static_cast<u16>(std::clamp<long>(std::lroundf(value * 2047.f), 0, 2047));
|
||||
s->data.right_x = s->invert_x_axis ? 2047 - s->data.right_x : s->data.right_x;
|
||||
break;
|
||||
case CID_GT_RIGHT_Y:
|
||||
s->data.right_y = static_cast<u16>(std::clamp<long>(std::lroundf(value * 2047.f), 0, 2047));
|
||||
s->data.right_y = s->invert_y_axis ? 2047 - s->data.right_y : s->data.right_y;
|
||||
break;
|
||||
case CID_GT_RIGHT_Z:
|
||||
s->data.right_z = static_cast<u32>(std::clamp<long>(std::lroundf(value * s->limit_z_axis), 0, s->limit_z_axis));
|
||||
s->data.right_z = s->invert_z_axis ? s->limit_z_axis - s->data.right_z : s->data.right_z;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GametrakDevice::UpdateSettings(USBDevice* dev, SettingsInterface& si) const
|
||||
{
|
||||
GametrakState* s = USB_CONTAINER_OF(dev, GametrakState, dev);
|
||||
s->invert_x_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_x_axis", false);
|
||||
s->invert_y_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_y_axis", false);
|
||||
s->invert_z_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_z_axis", false);
|
||||
s->limit_z_axis = USB::GetConfigInt(si, s->port, TypeName(), "limit_z_axis", 4095);
|
||||
}
|
||||
|
||||
std::span<const InputBindingInfo> GametrakDevice::Bindings(u32 subtype) const
|
||||
{
|
||||
static constexpr const InputBindingInfo bindings[] = {
|
||||
{"FootPedal", TRANSLATE_NOOP("USB", "Foot Pedal"), nullptr, InputBindingInfo::Type::Button, CID_GT_BUTTON, GenericInputBinding::Cross},
|
||||
{"LeftX", TRANSLATE_NOOP("USB", "Left X"), nullptr, InputBindingInfo::Type::Axis, CID_GT_LEFT_X, GenericInputBinding::Unknown},
|
||||
{"LeftY", TRANSLATE_NOOP("USB", "Left Y"), nullptr, InputBindingInfo::Type::Axis, CID_GT_LEFT_Y, GenericInputBinding::Unknown},
|
||||
{"LeftZ", TRANSLATE_NOOP("USB", "Left Z"), nullptr, InputBindingInfo::Type::Axis, CID_GT_LEFT_Z, GenericInputBinding::Unknown},
|
||||
{"RightX", TRANSLATE_NOOP("USB", "Right X"), nullptr, InputBindingInfo::Type::Axis, CID_GT_RIGHT_X, GenericInputBinding::Unknown},
|
||||
{"RightY", TRANSLATE_NOOP("USB", "Right Y"), nullptr, InputBindingInfo::Type::Axis, CID_GT_RIGHT_Y, GenericInputBinding::Unknown},
|
||||
{"RightZ", TRANSLATE_NOOP("USB", "Right Z"), nullptr, InputBindingInfo::Type::Axis, CID_GT_RIGHT_Z, GenericInputBinding::Unknown},
|
||||
};
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
std::span<const SettingInfo> GametrakDevice::Settings(u32 subtype) const
|
||||
{
|
||||
static constexpr const SettingInfo info[] = {
|
||||
{SettingInfo::Type::Boolean, "invert_x_axis", TRANSLATE_NOOP("USB", "Invert X axis"), TRANSLATE_NOOP("USB", "Invert X axis"), "false"},
|
||||
{SettingInfo::Type::Boolean, "invert_y_axis", TRANSLATE_NOOP("USB", "Invert Y axis"), TRANSLATE_NOOP("USB", "Invert Y axis"), "false"},
|
||||
{SettingInfo::Type::Boolean, "invert_z_axis", TRANSLATE_NOOP("USB", "Invert Z axis"), TRANSLATE_NOOP("USB", "Invert Z axis"), "false"},
|
||||
{SettingInfo::Type::Integer, "limit_z_axis", TRANSLATE_NOOP("USB", "Limit Z axis [100-4095]"),
|
||||
TRANSLATE_NOOP("USB", "- 4095 for original Gametrak controllers\n- 1790 for standard gamepads"),
|
||||
"4095", "100", "4095", "1", TRANSLATE_NOOP("USB", "%d"), nullptr, nullptr, 1.0f},
|
||||
};
|
||||
return info;
|
||||
}
|
||||
} // namespace usb_pad
|
||||
86
pcsx2/USB/usb-pad/usb-gametrak.h
Normal file
86
pcsx2/USB/usb-pad/usb-gametrak.h
Normal file
@@ -0,0 +1,86 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#pragma once
|
||||
#include "SaveState.h"
|
||||
#include "USB/qemu-usb/desc.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
namespace usb_pad
|
||||
{
|
||||
enum GametrakControlID
|
||||
{
|
||||
CID_GT_BUTTON,
|
||||
CID_GT_LEFT_X,
|
||||
CID_GT_LEFT_Y,
|
||||
CID_GT_LEFT_Z,
|
||||
CID_GT_RIGHT_X,
|
||||
CID_GT_RIGHT_Y,
|
||||
CID_GT_RIGHT_Z,
|
||||
CID_GT_COUNT,
|
||||
};
|
||||
|
||||
struct GametrakState
|
||||
{
|
||||
GametrakState(u32 port_);
|
||||
~GametrakState();
|
||||
|
||||
USBDevice dev{};
|
||||
USBDesc desc{};
|
||||
USBDescDevice desc_dev{};
|
||||
|
||||
u32 port = 0;
|
||||
u8 state = 0;
|
||||
u32 key = 0;
|
||||
|
||||
// Settings
|
||||
bool invert_x_axis = false;
|
||||
bool invert_y_axis = false;
|
||||
bool invert_z_axis = false;
|
||||
u16 limit_z_axis = 0xfff;
|
||||
|
||||
std::chrono::steady_clock::time_point last_log;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct
|
||||
{
|
||||
u16 k1 : 1;
|
||||
u16 left_x : 15;
|
||||
u16 k2 : 1;
|
||||
u16 left_y : 15;
|
||||
u16 k3 : 1;
|
||||
u16 left_z : 15;
|
||||
u16 k4 : 1;
|
||||
u16 right_x : 15;
|
||||
u16 k5 : 1;
|
||||
u16 right_y : 15;
|
||||
u16 k6 : 1;
|
||||
u16 right_z : 15;
|
||||
|
||||
u8 : 4;
|
||||
u8 button : 1;
|
||||
u8 : 3;
|
||||
|
||||
u8 : 8;
|
||||
u8 : 8;
|
||||
u8 : 8;
|
||||
} data = {};
|
||||
#pragma pack(pop)
|
||||
};
|
||||
|
||||
class GametrakDevice final : public DeviceProxy
|
||||
{
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
float GetBindingValue(const USBDevice* dev, u32 bind_index) const override;
|
||||
void SetBindingValue(USBDevice* dev, u32 bind_index, float value) const override;
|
||||
bool Freeze(USBDevice* dev, StateWrapper& sw) const override;
|
||||
void UpdateSettings(USBDevice* dev, SettingsInterface& si) const override;
|
||||
std::span<const InputBindingInfo> Bindings(u32 subtype) const override;
|
||||
std::span<const SettingInfo> Settings(u32 subtype) const override;
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
};
|
||||
|
||||
} // namespace usb_pad
|
||||
466
pcsx2/USB/usb-pad/usb-realplay.cpp
Normal file
466
pcsx2/USB/usb-pad/usb-realplay.cpp
Normal file
@@ -0,0 +1,466 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#include "Host.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "StateWrapper.h"
|
||||
#include "USB/USB.h"
|
||||
#include "USB/deviceproxy.h"
|
||||
#include "USB/qemu-usb/USBinternal.h"
|
||||
#include "USB/qemu-usb/desc.h"
|
||||
#include "USB/usb-pad/usb-realplay.h"
|
||||
#include "USB/usb-pad/usb-pad.h"
|
||||
#include <common/Console.h>
|
||||
|
||||
namespace usb_pad
|
||||
{
|
||||
static const USBDescStrings desc_strings = {
|
||||
"",
|
||||
"In2Games",
|
||||
"Real Play"};
|
||||
|
||||
static const uint8_t realplay_racing_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x00, 0x02, // bcdUSB 2.00
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x40, // bMaxPacketSize0 64
|
||||
0xB7, 0x14, // idVendor 0x14B7
|
||||
0xB2, 0x09, // idProduct 0x09B2
|
||||
0x00, 0x01, // bcdDevice 2.00
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t realplay_sphere_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x00, 0x02, // bcdUSB 2.00
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x40, // bMaxPacketSize0 64
|
||||
0xB7, 0x14, // idVendor 0x14B7
|
||||
0xB3, 0x09, // idProduct 0x09B3
|
||||
0x00, 0x01, // bcdDevice 2.00
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t realplay_golf_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x00, 0x02, // bcdUSB 2.00
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x40, // bMaxPacketSize0 64
|
||||
0xB7, 0x14, // idVendor 0x14B7
|
||||
0xB5, 0x09, // idProduct 0x09B5
|
||||
0x00, 0x01, // bcdDevice 2.00
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t realplay_pool_dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x00, 0x02, // bcdUSB 2.00
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x40, // bMaxPacketSize0 64
|
||||
0xB7, 0x14, // idVendor 0x14B7
|
||||
0xB6, 0x09, // idProduct 0x09B6
|
||||
0x00, 0x01, // bcdDevice 2.00
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t config_descriptor[] = {
|
||||
0x09, // bLength
|
||||
0x02, // bDescriptorType (Configuration)
|
||||
0x29, 0x00, // wTotalLength 41
|
||||
0x01, // bNumInterfaces 1
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration (String Index)
|
||||
0x80, // bmAttributes
|
||||
0x32, // bMaxPower 100mA
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x00, // bInterfaceNumber 0
|
||||
0x00, // bAlternateSetting
|
||||
0x02, // bNumEndpoints 2
|
||||
0x03, // bInterfaceClass
|
||||
0x00, // bInterfaceSubClass
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x09, // bLength
|
||||
0x21, // bDescriptorType (HID)
|
||||
0x11, 0x01, // bcdHID 1.11
|
||||
0x00, // bCountryCode
|
||||
0x01, // bNumDescriptors
|
||||
0x22, // bDescriptorType[0] (HID)
|
||||
0x85, 0x00, // wDescriptorLength[0] 133
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x02, // bEndpointAddress (OUT/H2D)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x40, 0x00, // wMaxPacketSize 64
|
||||
0x0A, // bInterval 10 (unit depends on device speed)
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x81, // bEndpointAddress (IN/D2H)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x40, 0x00, // wMaxPacketSize 64
|
||||
0x0A, // bInterval 10 (unit depends on device speed)
|
||||
};
|
||||
|
||||
static const uint8_t hid_report_descriptor[] = {
|
||||
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x05, // Usage (Game Pad)
|
||||
0xA1, 0x01, // Collection (Application)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x26, 0xFF, 0x0F, // Logical Maximum (4095)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x46, 0xFF, 0x0F, // Physical Maximum (4095)
|
||||
0x09, 0x30, // Usage (X)
|
||||
0x75, 0x0C, // Report Size (12)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x09, 0x31, // Usage (Y)
|
||||
0x75, 0x0C, // Report Size (12)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x09, 0x32, // Usage (Z)
|
||||
0x75, 0x0C, // Report Size (12)
|
||||
0x95, 0x01, // Report Count (1)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x20, // Usage (0x20)
|
||||
0x09, 0x21, // Usage (0x21)
|
||||
0x09, 0x22, // Usage (0x22)
|
||||
0x09, 0x23, // Usage (0x23)
|
||||
0x09, 0x24, // Usage (0x24)
|
||||
0x09, 0x25, // Usage (0x25)
|
||||
0x09, 0x26, // Usage (0x26)
|
||||
0x09, 0x27, // Usage (0x27)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x08, // Report Count (8)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x15, 0x00, // Logical Minimum (0)
|
||||
0x25, 0x01, // Logical Maximum (1)
|
||||
0x35, 0x00, // Physical Minimum (0)
|
||||
0x45, 0x01, // Physical Maximum (1)
|
||||
0x75, 0x01, // Report Size (1)
|
||||
0x95, 0x08, // Report Count (8)
|
||||
0x05, 0x09, // Usage Page (Button)
|
||||
0x19, 0x01, // Usage Minimum (0x01)
|
||||
0x29, 0x08, // Usage Maximum (0x08)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00)
|
||||
0x09, 0x28, // Usage (0x28)
|
||||
0x09, 0x29, // Usage (0x29)
|
||||
0x09, 0x2A, // Usage (0x2A)
|
||||
0x09, 0x2B, // Usage (0x2B)
|
||||
0x26, 0xFF, 0x00, // Logical Maximum (255)
|
||||
0x46, 0xFF, 0x00, // Physical Maximum (255)
|
||||
0x75, 0x08, // Report Size (8)
|
||||
0x95, 0x04, // Report Count (4)
|
||||
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
RealPlayState::RealPlayState(u32 port_, u32 type_)
|
||||
: port(port_)
|
||||
, type(type_)
|
||||
{
|
||||
}
|
||||
|
||||
RealPlayState::~RealPlayState() = default;
|
||||
|
||||
static void realplay_handle_control(USBDevice* dev, USBPacket* p,
|
||||
int request, int value, int index, int length, uint8_t* data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
|
||||
switch (value >> 8)
|
||||
{
|
||||
case USB_DT_REPORT:
|
||||
ret = sizeof(hid_report_descriptor);
|
||||
memcpy(data, hid_report_descriptor, ret);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SET_REPORT:
|
||||
break;
|
||||
case SET_IDLE:
|
||||
break;
|
||||
default:
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void realplay_handle_data(USBDevice* dev, USBPacket* p)
|
||||
{
|
||||
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||
|
||||
switch (p->pid)
|
||||
{
|
||||
case USB_TOKEN_IN:
|
||||
if (p->ep->nr == 1)
|
||||
{
|
||||
pxAssert(p->buffer_size >= sizeof(s->data));
|
||||
|
||||
std::memcpy(p->buffer_ptr, &s->data, sizeof(s->data));
|
||||
|
||||
// simulate a slight move to avoid a game "protection" : controller disconnected
|
||||
p->buffer_ptr[0] ^= s->state;
|
||||
s->state ^= 1;
|
||||
|
||||
p->actual_length += sizeof(s->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case USB_TOKEN_OUT:
|
||||
break;
|
||||
default:
|
||||
fail:
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void realplay_unrealize(USBDevice* dev)
|
||||
{
|
||||
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||
delete s;
|
||||
}
|
||||
|
||||
const char* RealPlayDevice::Name() const
|
||||
{
|
||||
return TRANSLATE_NOOP("USB", "RealPlay Device");
|
||||
}
|
||||
|
||||
const char* RealPlayDevice::TypeName() const
|
||||
{
|
||||
return "RealPlay";
|
||||
}
|
||||
|
||||
USBDevice* RealPlayDevice::CreateDevice(SettingsInterface& si, u32 port, u32 type) const
|
||||
{
|
||||
RealPlayState* s = new RealPlayState(port, type);
|
||||
|
||||
s->desc.full = &s->desc_dev;
|
||||
s->desc.str = desc_strings;
|
||||
|
||||
const uint8_t* dev_desc = nullptr;
|
||||
int dev_desc_len = 0;
|
||||
|
||||
switch (s->type)
|
||||
{
|
||||
case REALPLAY_RACING:
|
||||
dev_desc = realplay_racing_dev_descriptor;
|
||||
dev_desc_len = sizeof(realplay_racing_dev_descriptor);
|
||||
break;
|
||||
case REALPLAY_SPHERE:
|
||||
dev_desc = realplay_sphere_dev_descriptor;
|
||||
dev_desc_len = sizeof(realplay_sphere_dev_descriptor);
|
||||
break;
|
||||
case REALPLAY_GOLF:
|
||||
dev_desc = realplay_golf_dev_descriptor;
|
||||
dev_desc_len = sizeof(realplay_golf_dev_descriptor);
|
||||
break;
|
||||
case REALPLAY_POOL:
|
||||
dev_desc = realplay_pool_dev_descriptor;
|
||||
dev_desc_len = sizeof(realplay_pool_dev_descriptor);
|
||||
break;
|
||||
default:
|
||||
pxAssertMsg(false, "Unhandled type");
|
||||
break;
|
||||
}
|
||||
|
||||
if (usb_desc_parse_dev(dev_desc, dev_desc_len, s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(config_descriptor, sizeof(config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
|
||||
s->dev.speed = USB_SPEED_FULL;
|
||||
s->dev.klass.handle_attach = usb_desc_attach;
|
||||
s->dev.klass.handle_reset = nullptr;
|
||||
s->dev.klass.handle_control = realplay_handle_control;
|
||||
s->dev.klass.handle_data = realplay_handle_data;
|
||||
s->dev.klass.unrealize = realplay_unrealize;
|
||||
s->dev.klass.usb_desc = &s->desc;
|
||||
s->dev.klass.product_desc = nullptr;
|
||||
|
||||
usb_desc_init(&s->dev);
|
||||
usb_ep_init(&s->dev);
|
||||
|
||||
return &s->dev;
|
||||
|
||||
fail:
|
||||
realplay_unrealize(&s->dev);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool RealPlayDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||
|
||||
if (!sw.DoMarker("RealPlayDevice"))
|
||||
return false;
|
||||
|
||||
sw.Do(&s->type);
|
||||
sw.Do(&s->state);
|
||||
return !sw.HasError();
|
||||
}
|
||||
|
||||
float RealPlayDevice::GetBindingValue(const USBDevice* dev, u32 bind_index) const
|
||||
{
|
||||
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||
switch (bind_index)
|
||||
{
|
||||
case CID_RP_DPAD_UP: return s->data.dpad_up;
|
||||
case CID_RP_DPAD_DOWN: return s->data.dpad_down;
|
||||
case CID_RP_DPAD_LEFT: return s->data.dpad_left;
|
||||
case CID_RP_DPAD_RIGHT: return s->data.dpad_right;
|
||||
case CID_RP_RED: return s->data.btn_red;
|
||||
case CID_RP_GREEN: return s->data.btn_green;
|
||||
case CID_RP_YELLOW: return s->data.btn_yellow;
|
||||
case CID_RP_BLUE: return s->data.btn_blue;
|
||||
default: return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void RealPlayDevice::SetBindingValue(USBDevice* dev, u32 bind_index, float value) const
|
||||
{
|
||||
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||
switch (bind_index)
|
||||
{
|
||||
case CID_RP_DPAD_UP:
|
||||
s->data.dpad_up = (value >= 0.5f);
|
||||
break;
|
||||
case CID_RP_DPAD_DOWN:
|
||||
s->data.dpad_down = (value >= 0.5f);
|
||||
break;
|
||||
case CID_RP_DPAD_LEFT:
|
||||
s->data.dpad_left = (value >= 0.5f);
|
||||
break;
|
||||
case CID_RP_DPAD_RIGHT:
|
||||
s->data.dpad_right = (value >= 0.5f);
|
||||
break;
|
||||
case CID_RP_RED:
|
||||
s->data.btn_red = (value >= 0.5f);
|
||||
break;
|
||||
case CID_RP_GREEN:
|
||||
s->data.btn_green = (value >= 0.5f);
|
||||
break;
|
||||
case CID_RP_YELLOW:
|
||||
s->data.btn_yellow = (value >= 0.5f);
|
||||
break;
|
||||
case CID_RP_BLUE:
|
||||
s->data.btn_blue = (value >= 0.5f);
|
||||
break;
|
||||
case CID_RP_ACC_X:
|
||||
s->data.acc_x = static_cast<u16>(std::clamp<long>(std::lroundf(value * 4095.f), 0, 4095));
|
||||
s->data.acc_x = s->invert_x_axis ? 4095 - s->data.acc_x : s->data.acc_x;
|
||||
break;
|
||||
case CID_RP_ACC_Y:
|
||||
s->data.acc_y = static_cast<u16>(std::clamp<long>(std::lroundf(value * 4095.f), 0, 4095));
|
||||
s->data.acc_y = s->invert_x_axis ? 4095 - s->data.acc_y : s->data.acc_y;
|
||||
break;
|
||||
case CID_RP_ACC_Z:
|
||||
s->data.acc_z = static_cast<u16>(std::clamp<long>(std::lroundf(value * 4095.f), 0, 4095));
|
||||
s->data.acc_z = s->invert_x_axis ? 4095 - s->data.acc_z : s->data.acc_z;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::span<const char*> RealPlayDevice::SubTypes() const
|
||||
{
|
||||
static const char* subtypes[] = {
|
||||
TRANSLATE_NOOP("USB", "RealPlay Racing"),
|
||||
TRANSLATE_NOOP("USB", "RealPlay Sphere"),
|
||||
TRANSLATE_NOOP("USB", "RealPlay Golf"),
|
||||
TRANSLATE_NOOP("USB", "RealPlay Pool"),
|
||||
};
|
||||
return subtypes;
|
||||
}
|
||||
|
||||
void RealPlayDevice::UpdateSettings(USBDevice* dev, SettingsInterface& si) const
|
||||
{
|
||||
RealPlayState* s = USB_CONTAINER_OF(dev, RealPlayState, dev);
|
||||
s->invert_x_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_x_axis", false);
|
||||
s->invert_y_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_y_axis", false);
|
||||
s->invert_z_axis = USB::GetConfigBool(si, s->port, TypeName(), "invert_z_axis", false);
|
||||
}
|
||||
|
||||
std::span<const InputBindingInfo> RealPlayDevice::Bindings(u32 subtype) const
|
||||
{
|
||||
static constexpr const InputBindingInfo bindings[] = {
|
||||
{"DPadUp", TRANSLATE_NOOP("USB", "D-Pad Up"), nullptr, InputBindingInfo::Type::Button, CID_RP_DPAD_UP, GenericInputBinding::DPadUp},
|
||||
{"DPadDown", TRANSLATE_NOOP("USB", "D-Pad Down"), nullptr, InputBindingInfo::Type::Button, CID_RP_DPAD_DOWN, GenericInputBinding::DPadDown},
|
||||
{"DPadLeft", TRANSLATE_NOOP("USB", "D-Pad Left"), nullptr, InputBindingInfo::Type::Button, CID_RP_DPAD_LEFT, GenericInputBinding::DPadLeft},
|
||||
{"DPadRight", TRANSLATE_NOOP("USB", "D-Pad Right"), nullptr, InputBindingInfo::Type::Button, CID_RP_DPAD_RIGHT, GenericInputBinding::DPadRight},
|
||||
{"Red", TRANSLATE_NOOP("USB", "Red"), nullptr, InputBindingInfo::Type::Button, CID_RP_RED, GenericInputBinding::Triangle},
|
||||
{"Green", TRANSLATE_NOOP("USB", "Green"), nullptr, InputBindingInfo::Type::Button, CID_RP_GREEN, GenericInputBinding::Cross},
|
||||
{"Yellow", TRANSLATE_NOOP("USB", "Yellow"), nullptr, InputBindingInfo::Type::Button, CID_RP_YELLOW, GenericInputBinding::Square},
|
||||
{"Blue", TRANSLATE_NOOP("USB", "Blue"), nullptr, InputBindingInfo::Type::Button, CID_RP_BLUE, GenericInputBinding::Circle},
|
||||
{"AccelX", TRANSLATE_NOOP("USB", "Accel X"), nullptr, InputBindingInfo::Type::Axis, CID_RP_ACC_X, GenericInputBinding::Unknown},
|
||||
{"AccelY", TRANSLATE_NOOP("USB", "Accel Y"), nullptr, InputBindingInfo::Type::Axis, CID_RP_ACC_Y, GenericInputBinding::Unknown},
|
||||
{"AccelZ", TRANSLATE_NOOP("USB", "Accel Z"), nullptr, InputBindingInfo::Type::Axis, CID_RP_ACC_Z, GenericInputBinding::Unknown},
|
||||
};
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
std::span<const SettingInfo> RealPlayDevice::Settings(u32 subtype) const
|
||||
{
|
||||
static constexpr const SettingInfo info[] = {
|
||||
{SettingInfo::Type::Boolean, "invert_x_axis", TRANSLATE_NOOP("USB", "Invert X axis"), TRANSLATE_NOOP("USB", "Invert X axis"), "false"},
|
||||
{SettingInfo::Type::Boolean, "invert_y_axis", TRANSLATE_NOOP("USB", "Invert Y axis"), TRANSLATE_NOOP("USB", "Invert Y axis"), "false"},
|
||||
{SettingInfo::Type::Boolean, "invert_z_axis", TRANSLATE_NOOP("USB", "Invert Z axis"), TRANSLATE_NOOP("USB", "Invert Z axis"), "false"},
|
||||
};
|
||||
return info;
|
||||
}
|
||||
} // namespace usb_pad
|
||||
92
pcsx2/USB/usb-pad/usb-realplay.h
Normal file
92
pcsx2/USB/usb-pad/usb-realplay.h
Normal file
@@ -0,0 +1,92 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#pragma once
|
||||
#include "SaveState.h"
|
||||
#include "USB/qemu-usb/desc.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
namespace usb_pad
|
||||
{
|
||||
enum RealPlayControlID
|
||||
{
|
||||
CID_RP_DPAD_UP,
|
||||
CID_RP_DPAD_DOWN,
|
||||
CID_RP_DPAD_LEFT,
|
||||
CID_RP_DPAD_RIGHT,
|
||||
CID_RP_RED,
|
||||
CID_RP_GREEN,
|
||||
CID_RP_YELLOW,
|
||||
CID_RP_BLUE,
|
||||
CID_RP_ACC_X,
|
||||
CID_RP_ACC_Y,
|
||||
CID_RP_ACC_Z,
|
||||
CID_RP_COUNT,
|
||||
};
|
||||
|
||||
enum RealPlayType
|
||||
{
|
||||
REALPLAY_RACING,
|
||||
REALPLAY_SPHERE,
|
||||
REALPLAY_GOLF,
|
||||
REALPLAY_POOL,
|
||||
};
|
||||
|
||||
struct RealPlayState
|
||||
{
|
||||
RealPlayState(u32 port_, u32 type_);
|
||||
~RealPlayState();
|
||||
|
||||
USBDevice dev{};
|
||||
USBDesc desc{};
|
||||
USBDescDevice desc_dev{};
|
||||
|
||||
u32 port = 0;
|
||||
u32 type = 0;
|
||||
u8 state = 0;
|
||||
|
||||
// Settings
|
||||
bool invert_x_axis = false;
|
||||
bool invert_y_axis = false;
|
||||
bool invert_z_axis = false;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct
|
||||
{
|
||||
u16 acc_x;
|
||||
u16 acc_y;
|
||||
u16 acc_z;
|
||||
|
||||
u32 : 32;
|
||||
u32 : 32;
|
||||
|
||||
u8 dpad_up : 1;
|
||||
u8 dpad_down : 1;
|
||||
u8 dpad_left : 1;
|
||||
u8 dpad_right : 1;
|
||||
u8 btn_red : 1;
|
||||
u8 btn_green: 1;
|
||||
u8 btn_yellow : 1;
|
||||
u8 btn_blue : 1;
|
||||
|
||||
u32 : 32;
|
||||
} data = {};
|
||||
#pragma pack(pop)
|
||||
};
|
||||
|
||||
class RealPlayDevice final : public DeviceProxy
|
||||
{
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
float GetBindingValue(const USBDevice* dev, u32 bind_index) const override;
|
||||
void SetBindingValue(USBDevice* dev, u32 bind_index, float value) const override;
|
||||
bool Freeze(USBDevice* dev, StateWrapper& sw) const override;
|
||||
void UpdateSettings(USBDevice* dev, SettingsInterface& si) const override;
|
||||
std::span<const char*> SubTypes() const override;
|
||||
std::span<const InputBindingInfo> Bindings(u32 subtype) const override;
|
||||
std::span<const SettingInfo> Settings(u32 subtype) const override;
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
};
|
||||
} // namespace usb_pad
|
||||
185
pcsx2/USB/usb-pad/usb-trance-vibrator.cpp
Normal file
185
pcsx2/USB/usb-pad/usb-trance-vibrator.cpp
Normal file
@@ -0,0 +1,185 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#include "Host.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "StateWrapper.h"
|
||||
#include "USB/USB.h"
|
||||
#include "USB/deviceproxy.h"
|
||||
#include "USB/qemu-usb/USBinternal.h"
|
||||
#include "USB/qemu-usb/desc.h"
|
||||
#include "USB/usb-pad/usb-trance-vibrator.h"
|
||||
#include "USB/usb-pad/usb-pad.h"
|
||||
#include <common/Console.h>
|
||||
|
||||
namespace usb_pad
|
||||
{
|
||||
static const USBDescStrings desc_strings = {
|
||||
"",
|
||||
"ASCII CORPORATION",
|
||||
"ASCII Vib"};
|
||||
|
||||
static uint8_t dev_descriptor[] = {
|
||||
0x12, // bLength
|
||||
0x01, // bDescriptorType (Device)
|
||||
0x00, 0x01, // bcdUSB 1.00
|
||||
0x00, // bDeviceClass (Use class information in the Interface Descriptors)
|
||||
0x00, // bDeviceSubClass
|
||||
0x00, // bDeviceProtocol
|
||||
0x08, // bMaxPacketSize0 8
|
||||
0x49, 0x0B, // idVendor 0x0B49
|
||||
0x4F, 0x06, // idProduct 0x064F
|
||||
0x00, 0x01, // bcdDevice 2.00
|
||||
0x01, // iManufacturer (String Index)
|
||||
0x02, // iProduct (String Index)
|
||||
0x00, // iSerialNumber (String Index)
|
||||
0x01, // bNumConfigurations 1
|
||||
};
|
||||
|
||||
static const uint8_t config_descriptor[] = {
|
||||
0x09, // bLength
|
||||
0x02, // bDescriptorType (Configuration)
|
||||
0x22, 0x00, // wTotalLength 34
|
||||
0x01, // bNumInterfaces 1
|
||||
0x01, // bConfigurationValue
|
||||
0x00, // iConfiguration (String Index)
|
||||
0x80, // bmAttributes
|
||||
0x31, // bMaxPower 98mA
|
||||
|
||||
0x09, // bLength
|
||||
0x04, // bDescriptorType (Interface)
|
||||
0x00, // bInterfaceNumber 0
|
||||
0x00, // bAlternateSetting
|
||||
0x01, // bNumEndpoints 1
|
||||
0x00, // bInterfaceClass
|
||||
0x00, // bInterfaceSubClass
|
||||
0x00, // bInterfaceProtocol
|
||||
0x00, // iInterface (String Index)
|
||||
|
||||
0x07, // bLength
|
||||
0x05, // bDescriptorType (Endpoint)
|
||||
0x81, // bEndpointAddress (IN/D2H)
|
||||
0x03, // bmAttributes (Interrupt)
|
||||
0x08, 0x00, // wMaxPacketSize 8
|
||||
0x0A, // bInterval 10 (unit depends on device speed)
|
||||
};
|
||||
|
||||
TranceVibratorState::TranceVibratorState(u32 port_)
|
||||
: port(port_)
|
||||
{
|
||||
}
|
||||
|
||||
TranceVibratorState::~TranceVibratorState() = default;
|
||||
|
||||
static void trancevibrator_handle_control(USBDevice* dev, USBPacket* p,
|
||||
int request, int value, int index, int length, uint8_t* data)
|
||||
{
|
||||
TranceVibratorState* s = USB_CONTAINER_OF(dev, TranceVibratorState, dev);
|
||||
int ret = 0;
|
||||
|
||||
switch (request)
|
||||
{
|
||||
case InterfaceRequest | USB_REQ_GET_DESCRIPTOR:
|
||||
break;
|
||||
case SET_IDLE:
|
||||
break;
|
||||
case VendorDeviceOutRequest:
|
||||
// Vibration = wValue
|
||||
// LED1 = wIndex&1, LED2 = wIndex&2, LED3 = wIndex&4
|
||||
InputManager::SetUSBVibrationIntensity(s->port, value & 0xff, 0);
|
||||
break;
|
||||
default:
|
||||
ret = usb_desc_handle_control(dev, p, request, value, index, length, data);
|
||||
if (ret >= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void trancevibrator_handle_data(USBDevice* dev, USBPacket* p)
|
||||
{
|
||||
switch (p->pid)
|
||||
{
|
||||
case USB_TOKEN_IN:
|
||||
break;
|
||||
case USB_TOKEN_OUT:
|
||||
break;
|
||||
default:
|
||||
p->status = USB_RET_STALL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void trancevibrator_unrealize(USBDevice* dev)
|
||||
{
|
||||
TranceVibratorState* s = USB_CONTAINER_OF(dev, TranceVibratorState, dev);
|
||||
delete s;
|
||||
}
|
||||
|
||||
const char* TranceVibratorDevice::Name() const
|
||||
{
|
||||
return TRANSLATE_NOOP("USB", "Trance Vibrator (Rez)");
|
||||
}
|
||||
|
||||
const char* TranceVibratorDevice::TypeName() const
|
||||
{
|
||||
return "TranceVibrator";
|
||||
}
|
||||
|
||||
USBDevice* TranceVibratorDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const
|
||||
{
|
||||
TranceVibratorState* s = new TranceVibratorState(port);
|
||||
|
||||
s->desc.full = &s->desc_dev;
|
||||
s->desc.str = desc_strings;
|
||||
|
||||
if (usb_desc_parse_dev(dev_descriptor, sizeof(dev_descriptor), s->desc, s->desc_dev) < 0)
|
||||
goto fail;
|
||||
if (usb_desc_parse_config(config_descriptor, sizeof(config_descriptor), s->desc_dev) < 0)
|
||||
goto fail;
|
||||
|
||||
s->dev.speed = USB_SPEED_FULL;
|
||||
s->dev.klass.handle_attach = usb_desc_attach;
|
||||
s->dev.klass.handle_reset = nullptr;
|
||||
s->dev.klass.handle_control = trancevibrator_handle_control;
|
||||
s->dev.klass.handle_data = trancevibrator_handle_data;
|
||||
s->dev.klass.unrealize = trancevibrator_unrealize;
|
||||
s->dev.klass.usb_desc = &s->desc;
|
||||
s->dev.klass.product_desc = nullptr;
|
||||
|
||||
usb_desc_init(&s->dev);
|
||||
usb_ep_init(&s->dev);
|
||||
|
||||
return &s->dev;
|
||||
|
||||
fail:
|
||||
trancevibrator_unrealize(&s->dev);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float TranceVibratorDevice::GetBindingValue(const USBDevice* dev, u32 bind_index) const
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void TranceVibratorDevice::SetBindingValue(USBDevice* dev, u32 bind_index, float value) const
|
||||
{
|
||||
}
|
||||
|
||||
std::span<const InputBindingInfo> TranceVibratorDevice::Bindings(u32 subtype) const
|
||||
{
|
||||
static constexpr const InputBindingInfo bindings[] = {
|
||||
{"Motor", TRANSLATE_NOOP("Pad", "Motor"), nullptr, InputBindingInfo::Type::Motor, 0, GenericInputBinding::LargeMotor},
|
||||
};
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
std::span<const SettingInfo> TranceVibratorDevice::Settings(u32 subtype) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
} // namespace usb_pad
|
||||
36
pcsx2/USB/usb-pad/usb-trance-vibrator.h
Normal file
36
pcsx2/USB/usb-pad/usb-trance-vibrator.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: LGPL-3.0+
|
||||
|
||||
#pragma once
|
||||
#include "SaveState.h"
|
||||
#include "USB/qemu-usb/desc.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
namespace usb_pad
|
||||
{
|
||||
struct TranceVibratorState
|
||||
{
|
||||
TranceVibratorState(u32 port_);
|
||||
~TranceVibratorState();
|
||||
|
||||
USBDevice dev{};
|
||||
USBDesc desc{};
|
||||
USBDescDevice desc_dev{};
|
||||
|
||||
u32 port = 0;
|
||||
};
|
||||
|
||||
class TranceVibratorDevice final : public DeviceProxy
|
||||
{
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
float GetBindingValue(const USBDevice* dev, u32 bind_index) const override;
|
||||
void SetBindingValue(USBDevice* dev, u32 bind_index, float value) const override;
|
||||
std::span<const InputBindingInfo> Bindings(u32 subtype) const override;
|
||||
std::span<const SettingInfo> Settings(u32 subtype) const override;
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
};
|
||||
|
||||
} // namespace usb_pad
|
||||
@@ -3612,7 +3612,7 @@ void VMManager::UpdateDiscordPresence(bool update_session_time)
|
||||
rp.largeImageKey = "4k-pcsx2";
|
||||
rp.largeImageText = "PCSX2 Emulator";
|
||||
rp.startTimestamp = s_discord_presence_time_epoch;
|
||||
rp.details = s_title.empty() ? "No Game Running" : s_title.c_str();
|
||||
rp.details = s_title.empty() ? TRANSLATE("VMManager","No Game Running") : s_title.c_str();
|
||||
|
||||
std::string state_string;
|
||||
if (Achievements::HasRichPresence())
|
||||
|
||||
@@ -392,10 +392,13 @@
|
||||
<ClCompile Include="USB\usb-mic\usb-mic-singstar.cpp" />
|
||||
<ClCompile Include="USB\usb-msd\usb-msd.cpp" />
|
||||
<ClCompile Include="USB\usb-pad\lg\lg_ff.cpp" />
|
||||
<ClCompile Include="USB\usb-pad\usb-gametrak.cpp" />
|
||||
<ClCompile Include="USB\usb-pad\usb-realplay.cpp" />
|
||||
<ClCompile Include="USB\usb-pad\usb-pad-ff.cpp" />
|
||||
<ClCompile Include="USB\usb-pad\usb-pad-sdl-ff.cpp" />
|
||||
<ClCompile Include="USB\usb-pad\usb-pad.cpp" />
|
||||
<ClCompile Include="USB\usb-pad\usb-seamic.cpp" />
|
||||
<ClCompile Include="USB\usb-pad\usb-trance-vibrator.cpp" />
|
||||
<ClCompile Include="USB\usb-pad\usb-turntable.cpp" />
|
||||
<ClCompile Include="USB\usb-printer\usb-printer.cpp" />
|
||||
<ClCompile Include="USB\USB.cpp" />
|
||||
@@ -839,8 +842,11 @@
|
||||
<ClInclude Include="USB\usb-mic\usb-mic-singstar.h" />
|
||||
<ClInclude Include="USB\usb-msd\usb-msd.h" />
|
||||
<ClInclude Include="USB\usb-pad\lg\lg_ff.h" />
|
||||
<ClInclude Include="USB\usb-pad\usb-gametrak.h" />
|
||||
<ClInclude Include="USB\usb-pad\usb-realplay.h" />
|
||||
<ClInclude Include="USB\usb-pad\usb-pad-sdl-ff.h" />
|
||||
<ClInclude Include="USB\usb-pad\usb-pad.h" />
|
||||
<ClInclude Include="USB\usb-pad\usb-trance-vibrator.h" />
|
||||
<ClInclude Include="USB\usb-pad\usb-turntable.h" />
|
||||
<ClInclude Include="USB\usb-printer\usb-printer.h" />
|
||||
<ClInclude Include="USB\USB.h" />
|
||||
|
||||
@@ -1187,12 +1187,21 @@
|
||||
<ClCompile Include="USB\usb-hid\usb-hid.cpp">
|
||||
<Filter>System\Ps2\USB\usb-hid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-pad\usb-gametrak.cpp">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-pad\usb-realplay.cpp">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-pad\usb-pad.cpp">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-pad\usb-seamic.cpp">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-pad\usb-trance-vibrator.cpp">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="USB\usb-pad\usb-turntable.cpp">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClCompile>
|
||||
@@ -2121,9 +2130,18 @@
|
||||
<ClInclude Include="USB\usb-hid\usb-hid.h">
|
||||
<Filter>System\Ps2\USB\usb-hid</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-pad\usb-gametrak.h">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-pad\usb-realplay.h">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-pad\usb-pad.h">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-pad\usb-trance-vibrator.h">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="USB\usb-pad\usb-turntable.h">
|
||||
<Filter>System\Ps2\USB\usb-pad</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -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();
|
||||
|
||||
0
tools/generate_fullscreen_ui_translation_strings.py
Normal file → Executable file
0
tools/generate_fullscreen_ui_translation_strings.py
Normal file → Executable file
Reference in New Issue
Block a user