mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
26 Commits
misc_auto_
...
v2.5.162
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2bc80a96f | ||
|
|
704e531c1f | ||
|
|
203981182d | ||
|
|
14b67e3ac3 | ||
|
|
f83e11892b | ||
|
|
a8c549baee | ||
|
|
13142dd31d | ||
|
|
ed5c364603 | ||
|
|
0ccf7d2e10 | ||
|
|
ebb0dc7cc5 | ||
|
|
52ebebc739 | ||
|
|
c8141261f2 | ||
|
|
9c7750b85d | ||
|
|
bf10b55aa1 | ||
|
|
43d9ea99b0 | ||
|
|
37f28e95b6 | ||
|
|
1870193615 | ||
|
|
189374d19c | ||
|
|
ac04695edd | ||
|
|
93bf9db0b4 | ||
|
|
9219a1a38b | ||
|
|
1a28d6f0d1 | ||
|
|
aca1b4478e | ||
|
|
9a794f7aaa | ||
|
|
6e65558d42 | ||
|
|
74936f49e0 |
6
.github/workflows/release_cut_new.yml
vendored
6
.github/workflows/release_cut_new.yml
vendored
@@ -68,7 +68,7 @@ jobs:
|
||||
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
|
||||
|
||||
- name: Create a GitHub Release (Manual)
|
||||
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
- name: Create a GitHub Release (Push)
|
||||
uses: softprops/action-gh-release@72f2c25fcb47643c292f7107632f7a47c1df5cd8
|
||||
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name != 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
@@ -203,7 +203,7 @@ jobs:
|
||||
echo "TAG_VAL=${TAG_VAL}"
|
||||
gh release edit ${TAG_VAL} --draft=false --repo PCSX2/pcsx2
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.1
|
||||
LIBPNG=1.6.50
|
||||
LIBWEBP=1.6.0
|
||||
SDL=SDL3-3.2.20
|
||||
SDL=SDL3-3.2.22
|
||||
QT=6.9.2
|
||||
LZ4=1.10.0
|
||||
ZSTD=1.5.7
|
||||
@@ -43,7 +43,7 @@ fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.
|
||||
aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67 $SDL.tar.gz
|
||||
f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc $SDL.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
44be9c9ecfe04129c4dea0a7e1b36ad476c9cc07c292016ac98e7b41514f2440 qtbase-everywhere-src-$QT.tar.xz
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.20.tar.gz",
|
||||
"sha256": "467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67"
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.22.tar.gz",
|
||||
"sha256": "f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -40,7 +40,7 @@ fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
SDL=SDL3-3.2.20
|
||||
SDL=SDL3-3.2.22
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.50
|
||||
@@ -79,7 +79,7 @@ CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67 $SDL.tar.gz
|
||||
f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
|
||||
@@ -22,7 +22,7 @@ fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
SDL=SDL3-3.2.20
|
||||
SDL=SDL3-3.2.22
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.50
|
||||
@@ -59,7 +59,7 @@ CMAKE_COMMON=(
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67 $SDL.tar.gz
|
||||
f29d00cbcee273c0a54f3f32f86bf5c595e8823a96b1d92a145aac40571ebfcc $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
|
||||
@@ -46,7 +46,7 @@ set FREETYPE=2.13.3
|
||||
set HARFBUZZ=11.2.0
|
||||
set LIBJPEGTURBO=3.1.1
|
||||
set LIBPNG=1650
|
||||
set SDL=SDL3-3.2.20
|
||||
set SDL=SDL3-3.2.22
|
||||
set QT=6.9.2
|
||||
set QTMINOR=6.9
|
||||
set LZ4=1.10.0
|
||||
@@ -68,7 +68,7 @@ call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuz
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1650.zip 4be6938313b08d5921f9dede13f2789b653c96f4f8595d92ff3f09c9320e51c7 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" d76454913ea6f5f38856fbf00578d8e39daf842887f3396c95608414680250f7 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 3d60068b1e5c83c66bb14c325dfef46f8fcc380735b4591de6f5e7b9738929d1 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 97d59c78e40b4ddd018738d285a12afc320b57f8265a3f760353739a3619ccdb || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" f2fc6ff382c6f3af79493d0709dbd64847d0356313518f094f9096315f2fdb30 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" af80bb671ea0f66c0036ce7041a56b0e550fc94fb88d2c77b5b6a3e33e42139b || goto error
|
||||
|
||||
@@ -44,7 +44,7 @@ set FREETYPE=2.13.3
|
||||
set HARFBUZZ=11.2.0
|
||||
set LIBJPEGTURBO=3.1.1
|
||||
set LIBPNG=1650
|
||||
set SDL=SDL3-3.2.20
|
||||
set SDL=SDL3-3.2.22
|
||||
set QT=6.9.2
|
||||
set QTMINOR=6.9
|
||||
set LZ4=1.10.0
|
||||
@@ -66,7 +66,7 @@ call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuz
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1650.zip 4be6938313b08d5921f9dede13f2789b653c96f4f8595d92ff3f09c9320e51c7 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" d76454913ea6f5f38856fbf00578d8e39daf842887f3396c95608414680250f7 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 3d60068b1e5c83c66bb14c325dfef46f8fcc380735b4591de6f5e7b9738929d1 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 97d59c78e40b4ddd018738d285a12afc320b57f8265a3f760353739a3619ccdb || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" f2fc6ff382c6f3af79493d0709dbd64847d0356313518f094f9096315f2fdb30 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" af80bb671ea0f66c0036ce7041a56b0e550fc94fb88d2c77b5b6a3e33e42139b || goto error
|
||||
|
||||
2
.github/workflows/triage_pr.yml
vendored
2
.github/workflows/triage_pr.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v5
|
||||
- uses: actions/labeler@v6
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
18
3rdparty/include/IconsPromptFont.h
vendored
18
3rdparty/include/IconsPromptFont.h
vendored
@@ -185,7 +185,24 @@
|
||||
#define ICON_PF_KEYBOARD "\xE2\x90\xBD"
|
||||
#define ICON_PF_MOUSE "\xE2\x90\xBE"
|
||||
#define ICON_PF_MOUSE_AND_KEYBOARD "\xE2\x90\xBF"
|
||||
#define ICON_PF_DUALSHOCK2 "\xE2\x91\x81"
|
||||
#define ICON_PF_DUALSHOCK2_SLASH "\xE2\x91\x82"
|
||||
#define ICON_PF_GUITAR "\xE2\x91\x83"
|
||||
#define ICON_PF_STEERING_WHEEL_ALT "\xE2\x91\x84"
|
||||
#define ICON_PF_SEGA_SEAMIC "\xE2\x91\x85"
|
||||
#define ICON_PF_JOGCON "\xE2\x91\x86"
|
||||
#define ICON_PF_BUZZ_CONTROLLER "\xE2\x91\x87"
|
||||
#define ICON_PF_GAMETRAK_DEVICE "\xE2\x91\x88"
|
||||
#define ICON_PF_DJ_HERO_TURNTABLE "\xE2\x91\x89"
|
||||
#define ICON_PF_REALPLAY_BOWLING "\xE2\x91\x8A"
|
||||
#define ICON_PF_NEGCON "\xE2\x91\x8B"
|
||||
#define ICON_PF_REZ_VIBRATOR "\xE2\x91\x8C"
|
||||
#define ICON_PF_EYETOY_WEBCAM "\xE2\x91\x8D"
|
||||
#define ICON_PF_SINGSTAR_MIC "\xE2\x91\x8E"
|
||||
#define ICON_PF_GUNCON2 "\xE2\x91\x8F"
|
||||
#define ICON_PF_HEADSET "\xE2\x91\x90"
|
||||
#define ICON_PF_KEYBOARDMANIA "\xE2\x91\x91"
|
||||
#define ICON_PF_PRINTER "\xE2\x91\x92"
|
||||
#define ICON_PF_F1 "\xE2\x91\xA0"
|
||||
#define ICON_PF_F2 "\xE2\x91\xA1"
|
||||
#define ICON_PF_F3 "\xE2\x91\xA2"
|
||||
@@ -362,6 +379,7 @@
|
||||
#define ICON_PF_HEARTBEAT_MAG "\xE2\x8D\xBE"
|
||||
#define ICON_PF_MONITOR_CODE "\xE2\x8D\xBF"
|
||||
#define ICON_PF_SIXTY_CIRCLE "\xE2\x8E\x80"
|
||||
#define ICON_PF_VIDEO_CAMERA "\xE2\x8E\x81"
|
||||
#define ICON_PF_SPEAKER_ALT "\xE2\x8D\xA7"
|
||||
#define ICON_PF_THUNDERBOLT "\xE2\x8D\x9C"
|
||||
#define ICON_PF_BACKWARD "\xE2\x8F\x8C"
|
||||
|
||||
1214
3rdparty/promptfont/promptfont.sfd
vendored
1214
3rdparty/promptfont/promptfont.sfd
vendored
File diff suppressed because it is too large
Load Diff
@@ -21758,6 +21758,8 @@ SLES-52954:
|
||||
SLES-52955:
|
||||
name: "Deadly Strike"
|
||||
region: "PAL-E"
|
||||
roundModes:
|
||||
eeDivRoundMode: 3 # Fixes grid like pattern.
|
||||
SLES-52956:
|
||||
name: "Action Girlz Racing"
|
||||
region: "PAL-E"
|
||||
@@ -38928,6 +38930,8 @@ SLPM-62459:
|
||||
name-en: "Simple 2000 Series Vol. 16 - Sengoku vs. Gendai"
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
roundModes:
|
||||
eeDivRoundMode: 3 # Fixes grid like pattern.
|
||||
SLPM-62460:
|
||||
name: "SuperLite2000 シミュレーション 箱庭鉄道 ~ブルートレイン・特急編~"
|
||||
name-sort: "すーぱーらいと 2000 しみゅれーしょん はこにわてつどう ぶるーとれいんとっきゅうへん"
|
||||
|
||||
Binary file not shown.
@@ -191,6 +191,7 @@
|
||||
0300004112000000e500000000000000,Elecom JC-U909Z,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows,
|
||||
03000041120000001050000000000000,Elecom JC-U911,a:b1,b:b2,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b0,x:b4,y:b5,platform:Windows,
|
||||
030000006e0500000520000000000000,Elecom P301U PlayStation Controller Adapter,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
|
||||
03000000250900000218000000000000,Elecom PlayStation Adapter,a:b2,b:b1,back:b9,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:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
|
||||
030000006e0500000320000000000000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
|
||||
030000006e0500000e20000000000000,Elecom U3912T,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
|
||||
@@ -252,6 +253,7 @@
|
||||
03000000300f00000b01000000000000,GGE909 Recoil,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f0250000c283000000000000,Gioteck PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f025000021c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f025000021c1000010010000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
|
||||
@@ -478,6 +480,7 @@
|
||||
030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows,
|
||||
03000000152000000182000000000000,NGDS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
|
||||
03000000ec110000e1a7000000000000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
030000007e0500006920000000000000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Windows,
|
||||
030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows,
|
||||
@@ -535,7 +538,6 @@
|
||||
03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000120c0000f90e000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000250900000118000000000000,PS3 Controller,a:b2,b:b1,back:b9,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:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000250900000218000000000000,PS3 Controller,a:b2,b:b1,back:b9,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:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,
|
||||
030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows,
|
||||
030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -681,6 +683,7 @@
|
||||
03000000c01100004150000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
|
||||
03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows,
|
||||
03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
|
||||
030000009d0d00001130000000000000,Sanwa PlayStation Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
|
||||
03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows,
|
||||
03000000c01100000051000000000000,Satechi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
|
||||
030000004f04000028b3000000000000,Score A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
@@ -841,6 +844,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000007d0400000340000000000000,Xterminator Digital Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:-a4,lefttrigger:+a4,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b9,righttrigger:b2,rightx:a3,righty:a5,start:b8,x:b3,y:b4,platform:Windows,
|
||||
030000002c3600000100000000000000,Yawman Arrow,+rightx:h0.2,+righty:h0.4,-rightx:h0.8,-righty:h0.1,a:b4,b:b5,back:b6,dpdown:b15,dpleft:b14,dpright:b16,dpup:b13,leftshoulder:b10,leftstick:b0,lefttrigger:-a4,leftx:a0,lefty:a1,paddle1:b11,paddle2:b12,rightshoulder:b8,rightstick:b9,righttrigger:+a4,start:b3,x:b1,y:b2,platform:Windows,
|
||||
03000000790000004f18000000000000,ZDT Android 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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000073500000400000000000000,Zenaim Arcade 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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000120c00000500000000000000,Zeroplus Adapter,a:b2,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
|
||||
03000000120c0000101e000000000000,Zeroplus P4 Gamepad,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
|
||||
|
||||
@@ -1018,6 +1022,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000632500007505000000020000,NeoGeo mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X,
|
||||
030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X,
|
||||
03000000ec110000e1a7000001010000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
030000007e0500006920000001010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Mac OS X,
|
||||
030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1290,6 +1295,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000af1e00002400000010010000,Clockwork Pi DevTerm,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b9,x:b3,y:b0,platform:Linux,
|
||||
030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux,
|
||||
03000000632500007a05000001020000,Cosmic Byte Ares Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000a306000022f6000011010000,Cyborg V3 Rumble,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:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000005e0400008e02000002010000,Data Frog S80,a:b1,b:b0,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:b3,y:b2,platform:Linux,
|
||||
@@ -1311,6 +1317,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
|
||||
19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000373500000b10000019010000,GameSir Cyclone 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000ac0500005b05000010010000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000bc2000000055000011010000,GameSir G3w,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
@@ -1503,8 +1510,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
|
||||
030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux,
|
||||
060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
|
||||
030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,platform:Linux,
|
||||
03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000ec110000e1a7000010010000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
030000007e0500006920000011010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Linux,
|
||||
060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
|
||||
060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
|
||||
@@ -1656,7 +1663,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000321500000b10000011010000,Razer Wolverine PS5 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
0300000032150000140a000001010000,Razer Wolverine Ultimate Xbox,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,
|
||||
030000000d0f0000c100000010010000,Retro Bit Legacy16,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b12,leftshoulder:b4,lefttrigger:b6,misc1:b13,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f0000c100000072056800,Retro Bit Legacy16,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:+a4,misc1:b11,rightshoulder:b10,righttrigger:+a5,start:b6,x:b3,y:b2,platform:Linux,
|
||||
03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
0300000003040000c197000011010000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,
|
||||
190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
@@ -1692,11 +1698,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000790000002201000011010000,Sega Saturn,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
|
||||
03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
|
||||
03000000632500002305000010010000,Shanwan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000632500002605000010010000,Shanwan Gamepad,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,
|
||||
03000000632500007505000010010000,Shanwan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000bc2000000055000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000f025000021c1000010010000,Shanwan Gioteck PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000632500002605000010010000,ShanWan Gamepad,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,
|
||||
03000000632500007505000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
03000000bc2000000055000010010000,ShanWan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000341a00000908000010010000,SL6566,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
030000004b2900000430000011000000,Snakebyte 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,
|
||||
050000004c050000cc09000001000000,Sony DualShock 4,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
|
||||
@@ -305,64 +305,64 @@ PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
|
||||
uint2 pos = uint2(input.p.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uint2 column = (pos & ~uint2(0u, 3u)) / uint2(1,2);
|
||||
uint2 column = (pos & ~uint2(0u, 3u)) / uint2(1u, 2u);
|
||||
uint2 subcolumn = (pos & uint2(0u, 1u));
|
||||
column.x -= (column.x / 128) * 64;
|
||||
column.y += (column.y / 32) * 32;
|
||||
column.x -= (column.x / 128u) * 64u;
|
||||
column.y += (column.y / 32u) * 32u;
|
||||
|
||||
uint PSM = uint(DOFFSET);
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((PSM & 0x8) != 0) // PSMCT16S
|
||||
if ((PSM & 0x8u) != 0u) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32) != 0)
|
||||
if ((pos.x & 32u) != 0u)
|
||||
{
|
||||
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32;
|
||||
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 64) != 0)
|
||||
if ((pos.x & 64u) != 0u)
|
||||
{
|
||||
column.x -= 32;
|
||||
column.x -= 32u;
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 16;
|
||||
column.x ^= 32u;
|
||||
column.y ^= 16u;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32) != 0)
|
||||
if ((pos.y & 32u) != 0u)
|
||||
{
|
||||
column.y -= 16;
|
||||
column.x += 32;
|
||||
column.y -= 16u;
|
||||
column.x += 32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 96) != 0)
|
||||
if ((pos.x & 96u) != 0u)
|
||||
{
|
||||
uint multi = (pos.x & 96) / 32;
|
||||
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96);
|
||||
uint multi = (pos.x & 96u) / 32u;
|
||||
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96u);
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16) != 0))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 32;
|
||||
column.x ^= 32u;
|
||||
column.y ^= 32u;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,10 +371,10 @@ PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
|
||||
// Compensate for potentially differing page pitch.
|
||||
uint SBW = uint(EMODA);
|
||||
uint DBW = uint(EMODC);
|
||||
uint2 block_xy = coord / uint2(64,64);
|
||||
uint block_num = (block_xy.y * (DBW / 128)) + block_xy.x;
|
||||
uint2 block_offset = uint2((block_num % (SBW / 64)) * 64, (block_num / (SBW / 64)) * 64);
|
||||
coord = (coord % uint2(64, 64)) + block_offset;
|
||||
uint2 block_xy = coord / uint2(64u, 64u);
|
||||
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
|
||||
uint2 block_offset = uint2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 64u);
|
||||
coord = (coord % uint2(64u, 64u)) + block_offset;
|
||||
|
||||
// Apply offset to cols 1 and 2
|
||||
uint is_col23 = pos.y & 4u;
|
||||
@@ -394,18 +394,16 @@ PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
float sel0 = (float)(((green << 5) | red) & 0xFF) / 255.0f;
|
||||
|
||||
output.c = (float4)(sel0);
|
||||
output.c = (float4)(((float)(((green << 5) | red) & 0xFFu)) / 255.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
float sel0 = (float)((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
|
||||
|
||||
output.c = (float4)(sel0);
|
||||
output.c = (float4)(((float)((alpha | (blue << 2) | (green >> 3)) & 0xFFu)) / 255.0f);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ float4 ContrastSaturationBrightness(float4 color) // Ported to HLSL
|
||||
float3 conColor = lerp(AvgLumin, satColor, con);
|
||||
|
||||
float3 csb = conColor;
|
||||
csb = pow(csb, 1.0 / gam);
|
||||
csb = exp2(log2(csb) * (1.0 / gam));
|
||||
color.rgb = csb;
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -258,62 +258,62 @@ void ps_convert_rgb5a1_8i()
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1,2);
|
||||
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1u, 2u);
|
||||
uvec2 subcolumn = (pos & uvec2(0u, 1u));
|
||||
column.x -= (column.x / 128) * 64;
|
||||
column.y += (column.y / 32) * 32;
|
||||
column.x -= (column.x / 128u) * 64u;
|
||||
column.y += (column.y / 32u) * 32u;
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((PSM & 0x8) != 0) // PSMCT16S
|
||||
if ((PSM & 0x8u) != 0u) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32) != 0)
|
||||
if ((pos.x & 32u) != 0u)
|
||||
{
|
||||
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32;
|
||||
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 64) != 0)
|
||||
if ((pos.x & 64u) != 0u)
|
||||
{
|
||||
column.x -= 32;
|
||||
column.x -= 32u;
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 16;
|
||||
column.x ^= 32u;
|
||||
column.y ^= 16u;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32) != 0)
|
||||
if ((pos.y & 32u) != 0u)
|
||||
{
|
||||
column.y -= 16;
|
||||
column.x += 32;
|
||||
column.y -= 16u;
|
||||
column.x += 32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 96) != 0)
|
||||
if ((pos.x & 96u) != 0u)
|
||||
{
|
||||
uint multi = (pos.x & 96) / 32;
|
||||
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96);
|
||||
uint multi = (pos.x & 96u) / 32u;
|
||||
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96u);
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 32;
|
||||
column.x ^= 32u;
|
||||
column.y ^= 32u;
|
||||
}
|
||||
}
|
||||
uvec2 coord = column | subcolumn;
|
||||
@@ -342,18 +342,16 @@ void ps_convert_rgb5a1_8i()
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
float sel0 = float(((green << 5) | red) & 0xFF) / 255.0f;
|
||||
|
||||
SV_Target0 = vec4(sel0);
|
||||
SV_Target0 = vec4(float(((green << 5) | red) & 0xFFu) / 255.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
float sel0 = float((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
|
||||
|
||||
SV_Target0 = vec4(sel0);
|
||||
SV_Target0 = vec4(float((alpha | (blue << 2) | (green >> 3)) & 0xFFu) / 255.0f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -332,62 +332,62 @@ void ps_convert_rgb5a1_8i()
|
||||
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||
|
||||
// Collapse separate R G B A areas into their base pixel
|
||||
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1,2);
|
||||
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1u, 2u);
|
||||
uvec2 subcolumn = (pos & uvec2(0u, 1u));
|
||||
column.x -= (column.x / 128) * 64;
|
||||
column.y += (column.y / 32) * 32;
|
||||
column.x -= (column.x / 128u) * 64u;
|
||||
column.y += (column.y / 32u) * 32u;
|
||||
|
||||
// Deal with swizzling differences
|
||||
if ((PSM & 0x8) != 0) // PSMCT16S
|
||||
if ((PSM & 0x8u) != 0u) // PSMCT16S
|
||||
{
|
||||
if ((pos.x & 32) != 0)
|
||||
if ((pos.x & 32u) != 0u)
|
||||
{
|
||||
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32;
|
||||
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x &= ~32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 64) != 0)
|
||||
if ((pos.x & 64u) != 0u)
|
||||
{
|
||||
column.x -= 32;
|
||||
column.x -= 32u;
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 16;
|
||||
column.x ^= 32u;
|
||||
column.y ^= 16u;
|
||||
}
|
||||
}
|
||||
else // PSMCT16
|
||||
{
|
||||
if ((pos.y & 32) != 0)
|
||||
if ((pos.y & 32u) != 0u)
|
||||
{
|
||||
column.y -= 16;
|
||||
column.x += 32;
|
||||
column.y -= 16u;
|
||||
column.x += 32u;
|
||||
}
|
||||
|
||||
if ((pos.x & 96) != 0)
|
||||
if ((pos.x & 96u) != 0u)
|
||||
{
|
||||
uint multi = (pos.x & 96) / 32;
|
||||
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96);
|
||||
uint multi = (pos.x & 96u) / 32u;
|
||||
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
|
||||
column.x -= (pos.x & 96u);
|
||||
}
|
||||
|
||||
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
|
||||
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
|
||||
{
|
||||
column.x ^= 16;
|
||||
column.y ^= 8;
|
||||
column.x ^= 16u;
|
||||
column.y ^= 8u;
|
||||
}
|
||||
|
||||
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
|
||||
{
|
||||
column.x ^= 32;
|
||||
column.y ^= 32;
|
||||
column.x ^= 32u;
|
||||
column.y ^= 32u;
|
||||
}
|
||||
}
|
||||
uvec2 coord = column | subcolumn;
|
||||
@@ -410,23 +410,22 @@ void ps_convert_rgb5a1_8i()
|
||||
coord *= uvec2(ScaleFactor);
|
||||
|
||||
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
|
||||
|
||||
uvec4 denorm_c = uvec4(pixel * 255.5f);
|
||||
if ((pos.y & 2u) == 0u)
|
||||
{
|
||||
uint red = (denorm_c.r >> 3) & 0x1Fu;
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
float sel0 = float(((green << 5) | red) & 0xFF) / 255.0f;
|
||||
|
||||
o_col0 = vec4(sel0);
|
||||
o_col0 = vec4(float(((green << 5) | red) & 0xFFu) / 255.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint green = (denorm_c.g >> 3) & 0x1Fu;
|
||||
uint blue = (denorm_c.b >> 3) & 0x1Fu;
|
||||
uint alpha = denorm_c.a & 0x80u;
|
||||
float sel0 = float((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
|
||||
|
||||
o_col0 = vec4(sel0);
|
||||
o_col0 = vec4(float((alpha | (blue << 2) | (green >> 3)) & 0xFFu) / 255.0f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -473,8 +473,8 @@ static void PrintCommandLineHelp(const char* progname)
|
||||
std::fprintf(stderr, " -help: Displays this information and exits.\n");
|
||||
std::fprintf(stderr, " -version: Displays version information and exits.\n");
|
||||
std::fprintf(stderr, " -dumpdir <dir>: Frame dump directory (will be dumped as filename_frameN.png).\n");
|
||||
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i]: Enabling dumping of render target, texture, z buffer, frame, "
|
||||
"alphas, and info (context, vertices), respectively, per draw. Generates lots of data.\n");
|
||||
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i|tr]: Enabling dumping of render target, texture, z buffer, frame, "
|
||||
"alphas, and info (context, vertices, transfers (list)), transfers (images), respectively, per draw. Generates lots of data.\n");
|
||||
std::fprintf(stderr, " -dumprange N[,L,B]: Start dumping from draw N (base 0), stops after L draws, and only "
|
||||
"those draws that are multiples of B (intersection of -dumprange and -dumprangef used)."
|
||||
"Defaults to 0,-1,1 (all draws). Only used if -dump used.\n");
|
||||
@@ -558,6 +558,8 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveAlpha", true);
|
||||
if (str.find("i") != std::string::npos)
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveInfo", true);
|
||||
if (str.find("tr") != std::string::npos)
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveTransferImages", true);
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG_PARAM("-dumprange"))
|
||||
|
||||
@@ -339,6 +339,8 @@ void MainWindow::connectSignals()
|
||||
connect(m_ui.actionToolbarSettings, &QAction::triggered, this, &MainWindow::onSettingsTriggeredFromToolbar);
|
||||
connect(m_ui.actionToolbarControllerSettings, &QAction::triggered,
|
||||
[this]() { doControllerSettings(ControllerSettingsWindow::Category::GlobalSettings); });
|
||||
connect(m_ui.actionToolbarHotkeySettings, &QAction::triggered,
|
||||
[this]() { doControllerSettings(ControllerSettingsWindow::Category::HotkeySettings); });
|
||||
connect(m_ui.actionToolbarScreenshot, &QAction::triggered, this, &MainWindow::onScreenshotActionTriggered);
|
||||
connect(m_ui.actionExit, &QAction::triggered, this, &MainWindow::close);
|
||||
connect(m_ui.actionScreenshot, &QAction::triggered, this, &MainWindow::onScreenshotActionTriggered);
|
||||
|
||||
@@ -266,6 +266,7 @@
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionToolbarSettings"/>
|
||||
<addaction name="actionToolbarControllerSettings"/>
|
||||
<addaction name="actionToolbarHotkeySettings"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
<action name="actionStartFile">
|
||||
@@ -458,6 +459,14 @@
|
||||
<string>&Hotkeys</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolbarHotkeySettings">
|
||||
<property name="icon">
|
||||
<iconset theme="keyboard-line"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string comment="In Toolbar">Hotkeys</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionGraphicsSettings">
|
||||
<property name="icon">
|
||||
<iconset theme="image-fill"/>
|
||||
|
||||
@@ -71,6 +71,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="saveTransferImages">
|
||||
<property name="text">
|
||||
<string>Save Transfer Image Data</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
|
||||
@@ -109,6 +109,7 @@ DebugSettingsWidget::DebugSettingsWidget(SettingsWindow* settings_dialog, QWidge
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveDepth, "EmuCore/GS", "SaveDepth", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveAlpha, "EmuCore/GS", "SaveAlpha", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveInfo, "EmuCore/GS", "SaveInfo", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveTransferImages, "EmuCore/GS", "SaveTransferImages", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveDrawStart, "EmuCore/GS", "SaveDrawStart", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveDrawCount, "EmuCore/GS", "SaveDrawCount", 5000);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveFrameStart, "EmuCore/GS", "SaveFrameStart", 0);
|
||||
@@ -213,6 +214,7 @@ void DebugSettingsWidget::onDrawDumpingChanged()
|
||||
m_gs.saveDepth->setEnabled(enabled);
|
||||
m_gs.saveAlpha->setEnabled(enabled);
|
||||
m_gs.saveInfo->setEnabled(enabled);
|
||||
m_gs.saveTransferImages->setEnabled(enabled);
|
||||
m_gs.saveDrawStart->setEnabled(enabled);
|
||||
m_gs.saveDrawCount->setEnabled(enabled);
|
||||
m_gs.saveFrameStart->setEnabled(enabled);
|
||||
|
||||
@@ -53,16 +53,24 @@ void HotkeySettingsWidget::createButtons()
|
||||
auto iter = m_categories.find(category);
|
||||
if (iter == m_categories.end())
|
||||
{
|
||||
// Top line
|
||||
QLabel* top_line = new QLabel(m_container);
|
||||
top_line->setFrameShape(QFrame::HLine);
|
||||
top_line->setFixedHeight(12);
|
||||
m_layout->addWidget(top_line);
|
||||
|
||||
// Category label
|
||||
QLabel* label = new QLabel(category, m_container);
|
||||
QFont label_font(label->font());
|
||||
label_font.setPointSizeF(14.0f);
|
||||
label->setFont(label_font);
|
||||
m_layout->addWidget(label);
|
||||
|
||||
QLabel* line = new QLabel(m_container);
|
||||
line->setFrameShape(QFrame::HLine);
|
||||
line->setFixedHeight(4);
|
||||
m_layout->addWidget(line);
|
||||
// Bottom line
|
||||
QLabel* bottom_line = new QLabel(m_container);
|
||||
bottom_line->setFrameShape(QFrame::HLine);
|
||||
bottom_line->setFixedHeight(12);
|
||||
m_layout->addWidget(bottom_line);
|
||||
|
||||
QGridLayout* layout = new QGridLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -774,6 +774,7 @@ struct Pcsx2Config
|
||||
SaveDepth : 1,
|
||||
SaveAlpha : 1,
|
||||
SaveInfo : 1,
|
||||
SaveTransferImages : 1,
|
||||
DumpReplaceableTextures : 1,
|
||||
DumpReplaceableMipmaps : 1,
|
||||
DumpTexturesWithFMVActive : 1,
|
||||
|
||||
@@ -169,121 +169,123 @@ void GSDrawingContext::Dump(const std::string& filename)
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
// Warning: The indentation must be consistent with GSDrawingEnvironment::Dump().
|
||||
|
||||
fprintf(fp,
|
||||
"XYOFFSET\n"
|
||||
"\tOFX:%.4f\n"
|
||||
"\tOFY:%.4f\n\n",
|
||||
"XYOFFSET:\n"
|
||||
" OFX: %.4f\n"
|
||||
" OFY: %.4f\n\n",
|
||||
XYOFFSET.OFX / 16.0f, XYOFFSET.OFY / 16.0f);
|
||||
|
||||
fprintf(fp,
|
||||
"MIPTBP1\n"
|
||||
"\tTBP1:0x%x\n"
|
||||
"\tTBW1:%u\n"
|
||||
"\tTBP2:0x%x\n"
|
||||
"\tTBW2:%u\n"
|
||||
"\tTBP3:0x%x\n"
|
||||
"\tTBW3:%u\n\n",
|
||||
"MIPTBP1:\n"
|
||||
" TBP1: 0x%x\n"
|
||||
" TBW1: %u\n"
|
||||
" TBP2: 0x%x\n"
|
||||
" TBW2: %u\n"
|
||||
" TBP3: 0x%x\n"
|
||||
" TBW3: %u\n\n",
|
||||
static_cast<uint32_t>(MIPTBP1.TBP1), static_cast<uint32_t>(MIPTBP1.TBW1), static_cast<uint32_t>(MIPTBP1.TBP2),
|
||||
static_cast<uint32_t>(MIPTBP1.TBW2), static_cast<uint32_t>(MIPTBP1.TBP3), static_cast<uint32_t>(MIPTBP1.TBW3));
|
||||
|
||||
fprintf(fp,
|
||||
"MIPTBP2\n"
|
||||
"\tTBP4:0x%x\n"
|
||||
"\tTBW4:%u\n"
|
||||
"\tTBP5:0x%x\n"
|
||||
"\tTBW5:%u\n"
|
||||
"\tTBP6:0x%x\n"
|
||||
"\tTBW6:%u\n\n",
|
||||
"MIPTBP2:\n"
|
||||
" TBP4: 0x%x\n"
|
||||
" TBW4: %u\n"
|
||||
" TBP5: 0x%x\n"
|
||||
" TBW5: %u\n"
|
||||
" TBP6: 0x%x\n"
|
||||
" TBW6: %u\n\n",
|
||||
static_cast<uint32_t>(MIPTBP2.TBP4), static_cast<uint32_t>(MIPTBP2.TBW4), static_cast<uint32_t>(MIPTBP2.TBP5),
|
||||
static_cast<uint32_t>(MIPTBP2.TBW5), static_cast<uint32_t>(MIPTBP2.TBP6), static_cast<uint32_t>(MIPTBP2.TBW6));
|
||||
|
||||
fprintf(fp,
|
||||
"TEX0\n"
|
||||
"\tTBP0:0x%x\n"
|
||||
"\tTBW:%u\n"
|
||||
"\tPSM:0x%x (%s)\n"
|
||||
"\tTW:%u\n"
|
||||
"\tTH:%u\n"
|
||||
"\tTCC:%u\n"
|
||||
"\tTFX:%u\n"
|
||||
"\tCBP:0x%x\n"
|
||||
"\tCPSM:0x%x (%s)\n"
|
||||
"\tCSM:%u\n"
|
||||
"\tCSA:%u\n"
|
||||
"\tCLD:%u\n\n",
|
||||
TEX0.TBP0, TEX0.TBW, TEX0.PSM, GSUtil::GetPSMName(TEX0.PSM), TEX0.TW, static_cast<uint32_t>(TEX0.TH), TEX0.TCC, TEX0.TFX, TEX0.CBP, TEX0.CPSM, GSUtil::GetPSMName(TEX0.CPSM), TEX0.CSM,TEX0.CSA, TEX0.CLD);
|
||||
"TEX0:\n"
|
||||
" TBP0: 0x%x\n"
|
||||
" TBW: %u\n"
|
||||
" PSM: 0x%x # %s\n"
|
||||
" TW: %u\n"
|
||||
" TH: %u\n"
|
||||
" TCC: %u # %s\n"
|
||||
" TFX: %u # %s\n"
|
||||
" CBP: 0x%x\n"
|
||||
" CPSM: 0x%x # %s\n"
|
||||
" CSM: %u\n"
|
||||
" CSA: %u\n"
|
||||
" CLD: %u\n\n",
|
||||
TEX0.TBP0, TEX0.TBW, TEX0.PSM, GSUtil::GetPSMName(TEX0.PSM), TEX0.TW, static_cast<uint32_t>(TEX0.TH), TEX0.TCC, GSUtil::GetTCCName(TEX0.TCC), TEX0.TFX, GSUtil::GetTFXName(TEX0.TFX), TEX0.CBP, TEX0.CPSM, GSUtil::GetPSMName(TEX0.CPSM), TEX0.CSM, TEX0.CSA, TEX0.CLD);
|
||||
|
||||
fprintf(fp,
|
||||
"TEX1\n"
|
||||
"\tLCM:%u\n"
|
||||
"\tMXL:%u\n"
|
||||
"\tMMAG:%u\n"
|
||||
"\tMMIN:%u\n"
|
||||
"\tMTBA:%u\n"
|
||||
"\tL:%u\n"
|
||||
"\tK:%d\n\n",
|
||||
TEX1.LCM, TEX1.MXL, TEX1.MMAG, TEX1.MMIN, TEX1.MTBA, TEX1.L, TEX1.K);
|
||||
"TEX1:\n"
|
||||
" LCM: %u # %s\n"
|
||||
" MXL: %u\n"
|
||||
" MMAG: %u # %s\n"
|
||||
" MMIN: %u # %s\n"
|
||||
" MTBA: %u\n"
|
||||
" L: %u\n"
|
||||
" K: %.4f\n\n",
|
||||
TEX1.LCM, GSUtil::GetLCMName(TEX1.LCM), TEX1.MXL, TEX1.MMAG, GSUtil::GetMMAGName(TEX1.MMAG), TEX1.MMIN, GSUtil::GetMMINName(TEX1.MMIN), TEX1.MTBA, TEX1.L, static_cast<float>((static_cast<int>(TEX1.K) ^ 0x800) - 0x800) / 16.0f);
|
||||
|
||||
fprintf(fp,
|
||||
"CLAMP\n"
|
||||
"\tWMS:%u (%s)\n"
|
||||
"\tWMT:%u (%s)\n"
|
||||
"\tMINU:%u\n"
|
||||
"\tMAXU:%u\n"
|
||||
"\tMAXV:%u\n"
|
||||
"\tMINV:%u\n\n",
|
||||
CLAMP.WMS, GSUtil::GetWMName(CLAMP.WMS), CLAMP.WMT,GSUtil::GetWMName(CLAMP.WMT), CLAMP.MINU, CLAMP.MAXU, CLAMP.MAXV, static_cast<uint32_t>(CLAMP.MINV));
|
||||
"CLAMP:\n"
|
||||
" WMS: %u # %s\n"
|
||||
" WMT: %u # %s\n"
|
||||
" MINU: %u\n"
|
||||
" MAXU: %u\n"
|
||||
" MINV: %u\n"
|
||||
" MAXV: %u\n\n",
|
||||
CLAMP.WMS, GSUtil::GetWMName(CLAMP.WMS), CLAMP.WMT,GSUtil::GetWMName(CLAMP.WMT), CLAMP.MINU, CLAMP.MAXU, static_cast<uint32_t>(CLAMP.MINV), CLAMP.MAXV);
|
||||
|
||||
fprintf(fp,
|
||||
"SCISSOR\n"
|
||||
"\tSCAX0:%u\n"
|
||||
"\tSCAX1:%u\n"
|
||||
"\tSCAY0:%u\n"
|
||||
"\tSCAY1:%u\n\n",
|
||||
"SCISSOR:\n"
|
||||
" SCAX0: %u\n"
|
||||
" SCAX1: %u\n"
|
||||
" SCAY0: %u\n"
|
||||
" SCAY1: %u\n\n",
|
||||
SCISSOR.SCAX0, SCISSOR.SCAX1, SCISSOR.SCAY0, SCISSOR.SCAY1);
|
||||
|
||||
fprintf(fp,
|
||||
"ALPHA\n"
|
||||
"\tA:%u\n"
|
||||
"\tB:%u\n"
|
||||
"\tC:%u\n"
|
||||
"\tD:%u\n"
|
||||
"\tFIX:%u\n",
|
||||
"ALPHA:\n"
|
||||
" A: %u\n"
|
||||
" B: %u\n"
|
||||
" C: %u\n"
|
||||
" D: %u\n"
|
||||
" FIX: %u\n",
|
||||
ALPHA.A, ALPHA.B, ALPHA.C, ALPHA.D, ALPHA.FIX);
|
||||
const char* col[3] = {"Cs", "Cd", "0"};
|
||||
const char* alpha[3] = {"As", "Ad", "Af"};
|
||||
fprintf(fp, "\t=> (%s - %s) * %s + %s\n\n", col[ALPHA.A], col[ALPHA.B], alpha[ALPHA.C], col[ALPHA.D]);
|
||||
constexpr const char* col[3] = {"Cs", "Cd", "0"};
|
||||
constexpr const char* alpha[3] = {"As", "Ad", "Af"};
|
||||
fprintf(fp, " # => (%s - %s) * %s + %s\n\n", col[ALPHA.A], col[ALPHA.B], alpha[ALPHA.C], col[ALPHA.D]);
|
||||
|
||||
fprintf(fp,
|
||||
"TEST\n"
|
||||
"\tATE:%u\n"
|
||||
"\tATST:%u (%s)\n"
|
||||
"\tAREF:%u\n"
|
||||
"\tAFAIL:%u (%s)\n"
|
||||
"\tDATE:%u\n"
|
||||
"\tDATM:%u\n"
|
||||
"\tZTE:%u\n"
|
||||
"\tZTST:%u (%s)\n\n",
|
||||
TEST.ATE, TEST.ATST, GSUtil::GetATSTName(TEST.ATST), TEST.AREF, TEST.AFAIL, GSUtil::GetAFAILName(TEST.AFAIL), TEST.DATE, TEST.DATM, TEST.ZTE, TEST.ZTST, GSUtil::GetZTSTName(TEST.ZTST));
|
||||
"TEST:\n"
|
||||
" ATE: %u\n"
|
||||
" ATST: %u # %s\n"
|
||||
" AREF: %u\n"
|
||||
" AFAIL: %u # %s\n"
|
||||
" DATE: %u\n"
|
||||
" DATM: %u # %s\n"
|
||||
" ZTE: %u\n"
|
||||
" ZTST: %u # %s\n\n",
|
||||
TEST.ATE, TEST.ATST, GSUtil::GetATSTName(TEST.ATST), TEST.AREF, TEST.AFAIL, GSUtil::GetAFAILName(TEST.AFAIL), TEST.DATE, TEST.DATM, GSUtil::GetDATMName(TEST.DATM), TEST.ZTE, TEST.ZTST, GSUtil::GetZTSTName(TEST.ZTST));
|
||||
|
||||
fprintf(fp,
|
||||
"FBA\n"
|
||||
"\tFBA:%u\n\n",
|
||||
"FBA:\n"
|
||||
" FBA: %u\n\n",
|
||||
FBA.FBA);
|
||||
|
||||
fprintf(fp,
|
||||
"FRAME\n"
|
||||
"\tFBP (*32):0x%x\n"
|
||||
"\tFBW:%u\n"
|
||||
"\tPSM:0x%x (%s)\n"
|
||||
"\tFBMSK:0x%x\n\n",
|
||||
"FRAME:\n"
|
||||
" FBP: 0x%x # (*32)\n"
|
||||
" FBW: %u\n"
|
||||
" PSM: 0x%x # %s\n"
|
||||
" FBMSK: 0x%x\n\n",
|
||||
FRAME.FBP * 32, FRAME.FBW, FRAME.PSM, GSUtil::GetPSMName(FRAME.PSM), FRAME.FBMSK);
|
||||
|
||||
fprintf(fp,
|
||||
"ZBUF\n"
|
||||
"\tZBP (*32):0x%x\n"
|
||||
"\tPSM:0x%x (%s)\n"
|
||||
"\tZMSK:%u\n\n",
|
||||
"ZBUF:\n"
|
||||
" ZBP: 0x%x # (*32)\n"
|
||||
" PSM: 0x%x # %s\n"
|
||||
" ZMSK: %u\n\n",
|
||||
ZBUF.ZBP * 32, ZBUF.PSM, GSUtil::GetPSMName(ZBUF.PSM), ZBUF.ZMSK);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
@@ -35,112 +35,114 @@ void GSDrawingEnvironment::Dump(const std::string& filename) const
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
fprintf(fp, "PRIM\n"
|
||||
"\tPRIM:%u (%s)\n"
|
||||
"\tIIP:%u\n"
|
||||
"\tTME:%u\n"
|
||||
"\tFGE:%u\n"
|
||||
"\tABE:%u\n"
|
||||
"\tAA1:%u\n"
|
||||
"\tFST:%u\n"
|
||||
"\tCTXT:%u\n"
|
||||
"\tFIX:%u\n\n",
|
||||
// Warning: The indentation must be consistent with GSDrawingContext::Dump().
|
||||
|
||||
fprintf(fp, "PRIM:\n"
|
||||
" PRIM: %u # %s\n"
|
||||
" IIP: %u\n"
|
||||
" TME: %u\n"
|
||||
" FGE: %u\n"
|
||||
" ABE: %u\n"
|
||||
" AA1: %u\n"
|
||||
" FST: %u\n"
|
||||
" CTXT: %u\n"
|
||||
" FIX: %u\n\n",
|
||||
PRIM.PRIM, GSUtil::GetPrimName(PRIM.PRIM), PRIM.IIP, PRIM.TME, PRIM.FGE, PRIM.ABE, PRIM.AA1, PRIM.FST, PRIM.CTXT, PRIM.FIX);
|
||||
|
||||
fprintf(fp, "PRMODE (when AC=0)\n"
|
||||
"\t_PRIM:%u (%s)\n"
|
||||
"\tIIP:%u\n"
|
||||
"\tTME:%u\n"
|
||||
"\tFGE:%u\n"
|
||||
"\tABE:%u\n"
|
||||
"\tAA1:%u\n"
|
||||
"\tFST:%u\n"
|
||||
"\tCTXT:%u\n"
|
||||
"\tFIX:%u\n\n",
|
||||
fprintf(fp, "PRMODE: # when AC=0\n"
|
||||
" _PRIM: %u # %s\n"
|
||||
" IIP: %u\n"
|
||||
" TME: %u\n"
|
||||
" FGE: %u\n"
|
||||
" ABE: %u\n"
|
||||
" AA1: %u\n"
|
||||
" FST: %u\n"
|
||||
" CTXT: %u\n"
|
||||
" FIX: %u\n\n",
|
||||
PRMODE._PRIM, GSUtil::GetPrimName(PRMODE._PRIM), PRMODE.IIP, PRMODE.TME, PRMODE.FGE, PRMODE.ABE, PRMODE.AA1, PRMODE.FST, PRMODE.CTXT, PRMODE.FIX);
|
||||
|
||||
fprintf(fp, "PRMODECONT\n"
|
||||
"\tAC:%u\n\n",
|
||||
PRMODECONT.AC);
|
||||
fprintf(fp, "PRMODECONT:\n"
|
||||
" AC: %u # %s\n\n",
|
||||
PRMODECONT.AC, GSUtil::GetACName(PRMODECONT.AC));
|
||||
|
||||
fprintf(fp, "TEXCLUT\n"
|
||||
"\tCOU:%u\n"
|
||||
"\tCBW:%u\n"
|
||||
"\tCOV:%u\n\n",
|
||||
TEXCLUT.COU, TEXCLUT.CBW, TEXCLUT.COV);
|
||||
fprintf(fp, "TEXCLUT:\n"
|
||||
" CBW: %u\n"
|
||||
" COU: %u\n"
|
||||
" COV: %u\n\n",
|
||||
TEXCLUT.CBW, TEXCLUT.COU, TEXCLUT.COV);
|
||||
|
||||
fprintf(fp, "SCANMSK\n"
|
||||
"\tMSK:%u\n\n",
|
||||
SCANMSK.MSK);
|
||||
fprintf(fp, "SCANMSK:\n"
|
||||
" MSK: %u # %s\n\n",
|
||||
SCANMSK.MSK, GSUtil::GetSCANMSKName(SCANMSK.MSK));
|
||||
|
||||
fprintf(fp, "TEXA\n"
|
||||
"\tAEM:%u\n"
|
||||
"\tTA0:%u\n"
|
||||
"\tTA1:%u\n\n",
|
||||
fprintf(fp, "TEXA:\n"
|
||||
" AEM: %u\n"
|
||||
" TA0: %u\n"
|
||||
" TA1: %u\n\n",
|
||||
TEXA.AEM, TEXA.TA0, TEXA.TA1);
|
||||
|
||||
fprintf(fp, "FOGCOL\n"
|
||||
"\tFCG:%u\n"
|
||||
"\tFCB:%u\n"
|
||||
"\tFCR:%u\n\n",
|
||||
fprintf(fp, "FOGCOL:\n"
|
||||
" FCG: %u\n"
|
||||
" FCB: %u\n"
|
||||
" FCR: %u\n\n",
|
||||
FOGCOL.FCG, FOGCOL.FCB, FOGCOL.FCR);
|
||||
|
||||
fprintf(fp, "DIMX\n"
|
||||
"\tDM22:%d\n"
|
||||
"\tDM23:%d\n"
|
||||
"\tDM31:%d\n"
|
||||
"\tDM02:%d\n"
|
||||
"\tDM21:%d\n"
|
||||
"\tDM12:%d\n"
|
||||
"\tDM03:%d\n"
|
||||
"\tDM01:%d\n"
|
||||
"\tDM33:%d\n"
|
||||
"\tDM30:%d\n"
|
||||
"\tDM11:%d\n"
|
||||
"\tDM10:%d\n"
|
||||
"\tDM20:%d\n"
|
||||
"\tDM32:%d\n"
|
||||
"\tDM00:%d\n"
|
||||
"\tDM13:%d\n\n",
|
||||
fprintf(fp, "DIMX:\n"
|
||||
" DM22: %d\n"
|
||||
" DM23: %d\n"
|
||||
" DM31: %d\n"
|
||||
" DM02: %d\n"
|
||||
" DM21: %d\n"
|
||||
" DM12: %d\n"
|
||||
" DM03: %d\n"
|
||||
" DM01: %d\n"
|
||||
" DM33: %d\n"
|
||||
" DM30: %d\n"
|
||||
" DM11: %d\n"
|
||||
" DM10: %d\n"
|
||||
" DM20: %d\n"
|
||||
" DM32: %d\n"
|
||||
" DM00: %d\n"
|
||||
" DM13: %d\n\n",
|
||||
DIMX.DM22, DIMX.DM23, DIMX.DM31, DIMX.DM02, DIMX.DM21, DIMX.DM12, DIMX.DM03, DIMX.DM01, DIMX.DM33, DIMX.DM30, DIMX.DM11, DIMX.DM10, DIMX.DM20, DIMX.DM32, DIMX.DM00, DIMX.DM13);
|
||||
|
||||
fprintf(fp, "DTHE\n"
|
||||
"\tDTHE:%u\n\n",
|
||||
fprintf(fp, "DTHE:\n"
|
||||
" DTHE: %u\n\n",
|
||||
DTHE.DTHE);
|
||||
|
||||
fprintf(fp, "COLCLAMP\n"
|
||||
"\tCLAMP:%u\n\n",
|
||||
fprintf(fp, "COLCLAMP:\n"
|
||||
" CLAMP: %u\n\n",
|
||||
COLCLAMP.CLAMP);
|
||||
|
||||
fprintf(fp, "PABE\n"
|
||||
"\tPABE:%u\n\n",
|
||||
fprintf(fp, "PABE:\n"
|
||||
" PABE: %u\n\n",
|
||||
PABE.PABE);
|
||||
|
||||
fprintf(fp, "BITBLTBUF\n"
|
||||
"\tSBW:%u\n"
|
||||
"\tSBP:0x%x\n"
|
||||
"\tSPSM:%u (%s)\n"
|
||||
"\tDBW:%u\n"
|
||||
"\tDPSM:%u (%s)\n"
|
||||
"\tDBP:0x%x\n\n",
|
||||
fprintf(fp, "BITBLTBUF:\n"
|
||||
" SBW: %u\n"
|
||||
" SBP: 0x%x\n"
|
||||
" SPSM: %u # %s\n"
|
||||
" DBW: %u\n"
|
||||
" DPSM: %u # %s\n"
|
||||
" DBP: 0x%x\n\n",
|
||||
BITBLTBUF.SBW, BITBLTBUF.SBP, BITBLTBUF.SPSM, GSUtil::GetPSMName(BITBLTBUF.SPSM), BITBLTBUF.DBW, BITBLTBUF.DPSM, GSUtil::GetPSMName(BITBLTBUF.DPSM), BITBLTBUF.DBP);
|
||||
|
||||
fprintf(fp, "TRXDIR\n"
|
||||
"\tXDIR:%u\n\n",
|
||||
fprintf(fp, "TRXDIR:\n"
|
||||
" XDIR: %u\n\n",
|
||||
TRXDIR.XDIR);
|
||||
|
||||
fprintf(fp, "TRXPOS\n"
|
||||
"\tDIRY:%u\n"
|
||||
"\tSSAY:%u\n"
|
||||
"\tSSAX:%u\n"
|
||||
"\tDIRX:%u\n"
|
||||
"\tDSAX:%u\n"
|
||||
"\tDSAY:%u\n\n",
|
||||
fprintf(fp, "TRXPOS:\n"
|
||||
" DIRY: %u\n"
|
||||
" SSAY: %u\n"
|
||||
" SSAX: %u\n"
|
||||
" DIRX: %u\n"
|
||||
" DSAX: %u\n"
|
||||
" DSAY: %u\n\n",
|
||||
TRXPOS.DIRY, TRXPOS.SSAY, TRXPOS.SSAX, TRXPOS.DIRX, TRXPOS.DSAX, TRXPOS.DSAY);
|
||||
|
||||
fprintf(fp, "TRXREG\n"
|
||||
"\tRRH:%u\n"
|
||||
"\tRRW:%u\n\n",
|
||||
fprintf(fp, "TRXREG:\n"
|
||||
" RRH: %u\n"
|
||||
" RRW: %u\n\n",
|
||||
TRXREG.RRH, TRXREG.RRW);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
@@ -651,7 +651,7 @@ void GSLocalMemory::ReadTexture(const GSOffset& off, const GSVector4i& r, u8* ds
|
||||
|
||||
//
|
||||
|
||||
void GSLocalMemory::SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int w, int h)
|
||||
void GSLocalMemory::SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int w, int h, int x, int y)
|
||||
{
|
||||
int pitch = w * 4;
|
||||
int size = pitch * h;
|
||||
@@ -671,7 +671,7 @@ void GSLocalMemory::SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
((u32*)p)[i] = (this->*rp)(i, j, TEX0.TBP0, TEX0.TBW);
|
||||
((u32*)p)[i] = (this->*rp)(x + i, y + j, TEX0.TBP0, TEX0.TBW);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1121,7 +1121,7 @@ public:
|
||||
|
||||
//
|
||||
|
||||
void SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int w, int h);
|
||||
void SaveBMP(const std::string& fn, u32 bp, u32 bw, u32 psm, int w, int h, int x = 0, int y = 0);
|
||||
};
|
||||
|
||||
constexpr inline GSOffset GSOffset::fromKnownPSM(u32 bp, u32 bw, GS_PSM psm)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <algorithm>
|
||||
#include <cfloat>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <bit>
|
||||
|
||||
@@ -433,6 +434,34 @@ const char* GSState::GetFlushReasonString(GSFlushReason reason)
|
||||
}
|
||||
}
|
||||
|
||||
void GSState::DumpDrawInfo(bool dump_regs, bool dump_verts, bool dump_transfers)
|
||||
{
|
||||
std::string s;
|
||||
|
||||
// Dump Register state
|
||||
if (dump_regs)
|
||||
{
|
||||
s = GetDrawDumpPath("%05d_context.txt", s_n);
|
||||
|
||||
m_draw_env->Dump(s);
|
||||
m_context->Dump(s);
|
||||
}
|
||||
|
||||
// Dump vertices
|
||||
if (dump_verts)
|
||||
{
|
||||
s = GetDrawDumpPath("%05d_vertex.txt", s_n);
|
||||
DumpVertices(s);
|
||||
}
|
||||
|
||||
// Dump transfers
|
||||
if (dump_transfers)
|
||||
{
|
||||
s = GetDrawDumpPath("%05d_transfers.txt", s_n);
|
||||
DumpTransferList(s);
|
||||
}
|
||||
}
|
||||
|
||||
void GSState::DumpVertices(const std::string& filename)
|
||||
{
|
||||
std::ofstream file(filename);
|
||||
@@ -440,108 +469,370 @@ void GSState::DumpVertices(const std::string& filename)
|
||||
if (!file.is_open())
|
||||
return;
|
||||
|
||||
file << "FLUSH REASON: " << GetFlushReasonString(m_state_flush_reason);
|
||||
file.imbue(std::locale::classic()); // Disable integer separators.
|
||||
|
||||
if (m_state_flush_reason != GSFlushReason::CONTEXTCHANGE && m_dirty_gs_regs)
|
||||
file << " AND POSSIBLE CONTEXT CHANGE";
|
||||
constexpr const char* DEL = ", ";
|
||||
constexpr const char* INDENT = " ";
|
||||
constexpr const char* LIST_ITEM = "- ";
|
||||
constexpr const char* OPEN_MAP = "{";
|
||||
constexpr const char* CLOSE_MAP = "}";
|
||||
|
||||
constexpr int TRACE_INDEX_WIDTH = 10;
|
||||
constexpr int XYUV_WIDTH = 9;
|
||||
constexpr int Z_WIDTH = 10;
|
||||
constexpr int RGBA_WIDTH = 3;
|
||||
constexpr int SCI_FLOAT_WIDTH = 15;
|
||||
constexpr int STQ_BITS_WIDTH = 10;
|
||||
|
||||
file << std::endl << std::endl;
|
||||
auto WriteVertexIndex = [&file](int index) {
|
||||
file << std::left << std::dec << " # " << index;
|
||||
};
|
||||
|
||||
const u32 count = m_index.tail;
|
||||
GSVertex* buffer = &m_vertex.buff[0];
|
||||
auto WriteTraceIndex = [&file](const char* index) {
|
||||
file << std::left << std::dec << std::setw(TRACE_INDEX_WIDTH) << std::setfill(' ') << index;
|
||||
};
|
||||
|
||||
const char* DEL = ", ";
|
||||
auto WriteXYZ_vec = [&file](const GSVector4& v) {
|
||||
file << std::dec << std::right << std::fixed;
|
||||
file << "X: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << v.x << DEL;
|
||||
file << "Y: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << v.y << DEL;
|
||||
file << "Z: " << std::setw(Z_WIDTH) << std::setfill(' ') << static_cast<u32>(v.z);
|
||||
};
|
||||
|
||||
file << "VERTEX COORDS (XYZ)" << std::endl;
|
||||
file << std::fixed << std::setprecision(4);
|
||||
for (u32 i = 0; i < count; ++i)
|
||||
{
|
||||
file << "\t" << std::dec << "v" << i << ": ";
|
||||
GSVertex v = buffer[m_index.buff[i]];
|
||||
// Different handler because we have full precision on Z
|
||||
auto WriteXYZ_vert = [this, &file](const GSVertex& v) {
|
||||
const float x = (static_cast<int>(v.XYZ.X) - static_cast<int>(m_context->XYOFFSET.OFX)) / 16.0f;
|
||||
const float y = (static_cast<int>(v.XYZ.Y) - static_cast<int>(m_context->XYOFFSET.OFY)) / 16.0f;
|
||||
file << std::dec << std::right << std::fixed;
|
||||
file << "X: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << x << DEL;
|
||||
file << "Y: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << y << DEL;
|
||||
file << "Z: " << std::setw(Z_WIDTH) << std::setfill(' ') << v.XYZ.Z;
|
||||
};
|
||||
|
||||
const float x = (v.XYZ.X - (int)m_context->XYOFFSET.OFX) / 16.0f;
|
||||
const float y = (v.XYZ.Y - (int)m_context->XYOFFSET.OFY) / 16.0f;
|
||||
|
||||
file << x << DEL;
|
||||
file << y << DEL;
|
||||
file << v.XYZ.Z;
|
||||
file << std::endl;
|
||||
}
|
||||
|
||||
file << std::endl;
|
||||
|
||||
file << "VERTEX COLOR (RGBA)" << std::endl;
|
||||
file << std::fixed << std::setprecision(6);
|
||||
for (u32 i = 0; i < count; ++i)
|
||||
{
|
||||
file << "\t" << std::dec << "v" << i << ": ";
|
||||
GSVertex v = buffer[m_index.buff[i]];
|
||||
|
||||
file << std::setfill('0') << std::setw(3) << unsigned(v.RGBAQ.R) << DEL;
|
||||
file << std::setfill('0') << std::setw(3) << unsigned(v.RGBAQ.G) << DEL;
|
||||
file << std::setfill('0') << std::setw(3) << unsigned(v.RGBAQ.B) << DEL;
|
||||
file << std::setfill('0') << std::setw(3) << unsigned(v.RGBAQ.A) << DEL;
|
||||
file << "FOG: " << std::setfill('0') << std::setw(3) << unsigned(v.FOG);
|
||||
file << std::endl;
|
||||
}
|
||||
|
||||
file << std::endl;
|
||||
|
||||
const bool use_uv = PRIM->FST;
|
||||
const std::string qualifier = use_uv ? "UV" : "STQ";
|
||||
|
||||
file << "TEXTURE COORDS (" << qualifier << ")" << std::endl;;
|
||||
for (u32 i = 0; i < count; ++i)
|
||||
{
|
||||
file << "\t" << "v" << std::dec << i << ": ";
|
||||
const GSVertex v = buffer[m_index.buff[i]];
|
||||
|
||||
// note
|
||||
// Yes, technically as far as the GS is concerned Q belongs
|
||||
// to RGBAQ. However, the purpose of this dump is to print
|
||||
// our data in a more human readable format and typically Q
|
||||
// is associated with STQ.
|
||||
if (use_uv)
|
||||
auto WriteUV_vec = [this, &file](const GSVector4& v) {
|
||||
file << std::right;
|
||||
if (PRIM->FST)
|
||||
{
|
||||
const float uv_U = v.U / 16.0f;
|
||||
const float uv_V = v.V / 16.0f;
|
||||
|
||||
file << uv_U << DEL << uv_V;
|
||||
file << std::fixed;
|
||||
file << "U: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << v.x << DEL;
|
||||
file << "V: " << std::setprecision(4) << std::setw(XYUV_WIDTH) << std::setfill(' ') << v.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
float x = (v.ST.S / v.RGBAQ.Q) * (1 << m_context->TEX0.TW);
|
||||
float y = (v.ST.T / v.RGBAQ.Q) * (1 << m_context->TEX0.TH);
|
||||
file << v.ST.S << "(" << std::hex << std::bit_cast<u32>(v.ST.S) << ")" << DEL << v.ST.T << "(" << std::hex << std::bit_cast<u32>(v.ST.T) << ")" << DEL << v.RGBAQ.Q << "(" << std::hex << std::bit_cast<u32>(v.RGBAQ.Q) << ") - " << x << "," << y;
|
||||
file << std::defaultfloat;
|
||||
file << "U: " << std::setw(SCI_FLOAT_WIDTH) << std::setfill(' ') << v.x << DEL;
|
||||
file << "V: " << std::setw(SCI_FLOAT_WIDTH) << std::setfill(' ') << v.y;
|
||||
}
|
||||
};
|
||||
|
||||
auto WriteUV_vert = [this, WriteUV_vec](const GSVertex& v) {
|
||||
GSVector4 vec;
|
||||
if (PRIM->FST)
|
||||
vec = GSVector4(v.U / 16.0f, v.V / 16.0f);
|
||||
else
|
||||
vec = GSVector4(
|
||||
(v.ST.S / v.RGBAQ.Q) * (1 << m_context->TEX0.TW),
|
||||
(v.ST.T / v.RGBAQ.Q) * (1 << m_context->TEX0.TH)
|
||||
);
|
||||
WriteUV_vec(vec);
|
||||
};
|
||||
|
||||
auto WriteRGBA_vec = [&file](const GSVector4i& v) {
|
||||
file << std::dec << std::right;
|
||||
file << "R: " << std::setw(RGBA_WIDTH) << std::setfill(' ') << v.r << DEL;
|
||||
file << "G: " << std::setw(RGBA_WIDTH) << std::setfill(' ') << v.g << DEL;
|
||||
file << "B: " << std::setw(RGBA_WIDTH) << std::setfill(' ') << v.b << DEL;
|
||||
file << "A: " << std::setw(RGBA_WIDTH) << std::setfill(' ') << v.a;
|
||||
};
|
||||
|
||||
auto WriteRGBA_vert = [WriteRGBA_vec](const GSVertex& v) {
|
||||
GSVector4i vec = GSVector4i(v.RGBAQ.R, v.RGBAQ.G, v.RGBAQ.B, v.RGBAQ.A);
|
||||
WriteRGBA_vec(vec);
|
||||
};
|
||||
|
||||
auto WriteSTQ_vec = [&file](const GSVector4& v) {
|
||||
file << std::defaultfloat << std::right;
|
||||
file << "S: " << std::setw(SCI_FLOAT_WIDTH) << std::setfill(' ') << v.x << DEL;
|
||||
file << "T: " << std::setw(SCI_FLOAT_WIDTH) << std::setfill(' ') << v.y << DEL;
|
||||
file << "Q: " << std::setw(SCI_FLOAT_WIDTH) << std::setfill(' ') << v.z;
|
||||
};
|
||||
|
||||
auto WriteSTQ_bits = [&file](const GSVector4& v) {
|
||||
file << std::hex << std::showbase << std::right;
|
||||
file << "Si: " << std::setw(STQ_BITS_WIDTH) << std::setfill('0') << std::bit_cast<u32>(v.x) << DEL;
|
||||
file << "Ti: " << std::setw(STQ_BITS_WIDTH) << std::setfill('0') << std::bit_cast<u32>(v.y) << DEL;
|
||||
file << "Qi: " << std::setw(STQ_BITS_WIDTH) << std::setfill('0') << std::bit_cast<u32>(v.z);
|
||||
};
|
||||
|
||||
auto WriteSTQ_vert = [&file, WriteSTQ_vec, WriteSTQ_bits](const GSVertex& v) {
|
||||
GSVector4 vec = GSVector4(v.ST.S, v.ST.T, v.RGBAQ.Q, v.RGBAQ.Q);
|
||||
WriteSTQ_vec(vec);
|
||||
file << DEL;
|
||||
WriteSTQ_bits(vec);
|
||||
};
|
||||
|
||||
auto WriteBools = [&file](std::vector<const char*> names, std::vector<u32> values) {
|
||||
for (int i = 0; i < static_cast<int>(names.size()); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
file << DEL;
|
||||
file << names[i] << ": " << static_cast<bool>(values[i]);
|
||||
}
|
||||
};
|
||||
|
||||
// Dump flush reason
|
||||
file << "flush_reason: \"" << GetFlushReasonString(m_state_flush_reason);
|
||||
if (m_state_flush_reason != GSFlushReason::CONTEXTCHANGE && m_dirty_gs_regs)
|
||||
file << " AND POSSIBLE CONTEXT CHANGE";
|
||||
file << "\"" << std::endl;
|
||||
|
||||
file << std::endl;
|
||||
|
||||
// Dump vertices
|
||||
file << "vertex:" << std::endl;
|
||||
const u32 count = m_index.tail;
|
||||
GSVertex* buffer = &m_vertex.buff[0];
|
||||
for (u32 i = 0; i < count; ++i)
|
||||
{
|
||||
GSVertex v = buffer[m_index.buff[i]];
|
||||
|
||||
file << INDENT << LIST_ITEM << OPEN_MAP;
|
||||
WriteXYZ_vert(v);
|
||||
if (PRIM->TME)
|
||||
{
|
||||
file << DEL;
|
||||
WriteUV_vert(v);
|
||||
}
|
||||
file << DEL;
|
||||
WriteRGBA_vert(v);
|
||||
file << CLOSE_MAP;
|
||||
|
||||
WriteVertexIndex(i);
|
||||
|
||||
file << std::endl;
|
||||
}
|
||||
|
||||
file << std::endl;
|
||||
|
||||
file << "TRACER" << std::dec << std::endl;
|
||||
// Dump extra info for STQ
|
||||
if (PRIM->TME && !PRIM->FST)
|
||||
{
|
||||
file << "vertex_stq:" << std::endl;
|
||||
for (u32 i = 0; i < count; ++i)
|
||||
{
|
||||
file << INDENT << LIST_ITEM << OPEN_MAP;
|
||||
WriteSTQ_vert(buffer[m_index.buff[i]]);
|
||||
file << CLOSE_MAP;
|
||||
|
||||
GSVector4i v = m_vt.m_min.c;
|
||||
file << "\tmin c (r,g,b,a): " << v.x << DEL << v.y << DEL << v.z << DEL << v.w << std::endl;
|
||||
v = m_vt.m_max.c;
|
||||
file << "\tmax c (r,g,b,a): " << v.x << DEL << v.y << DEL << v.z << DEL << v.w << std::endl;
|
||||
WriteVertexIndex(i);
|
||||
|
||||
GSVector4 v2 = m_vt.m_min.p;
|
||||
file << "\tmin p (x,y,z,f): " << v2.x << DEL << v2.y << DEL << v2.z << DEL << (u32)v2.w << std::endl;
|
||||
v2 = m_vt.m_max.p;
|
||||
file << "\tmax p (x,y,z,f): " << v2.x << DEL << v2.y << DEL << v2.z << DEL << (u32)v2.w << std::endl;
|
||||
|
||||
v2 = m_vt.m_min.t;
|
||||
file << "\tmin t (u,v,q): " << v2.x << DEL << v2.y << DEL << v2.z << std::endl;
|
||||
v2 = m_vt.m_max.t;
|
||||
file << "\tmax t (u,v,q): " << v2.x << DEL << v2.y << DEL << v2.z << std::endl;
|
||||
file << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
file << std::endl;
|
||||
file << "\teq c (r,g,b,a): " << (m_vt.m_eq.r & 1) << DEL << (m_vt.m_eq.g & 1) << DEL << (m_vt.m_eq.b & 1) << DEL << (m_vt.m_eq.a & 1) << std::endl;
|
||||
file << "\teq p (x,y,z,f): " << (m_vt.m_eq.x & 1) << DEL << (m_vt.m_eq.y & 1) << DEL << (m_vt.m_eq.z & 1) << DEL << (m_vt.m_eq.f & 1) << std::endl;
|
||||
file << "\teq t (u,v,q) : " << (m_vt.m_eq.s & 1) << DEL << (m_vt.m_eq.t & 1) << DEL << (m_vt.m_eq.q & 1) << std::endl;
|
||||
file.close();
|
||||
|
||||
// Dump vertex trace
|
||||
file << "vertex_trace:" << std::endl;
|
||||
|
||||
file << INDENT;
|
||||
WriteTraceIndex("min_xyz: ");
|
||||
file << OPEN_MAP;
|
||||
WriteXYZ_vec(m_vt.m_min.p);
|
||||
file << CLOSE_MAP << std::endl;
|
||||
|
||||
file << INDENT;
|
||||
WriteTraceIndex("max_xyz: ");
|
||||
file << OPEN_MAP;
|
||||
WriteXYZ_vec(m_vt.m_max.p);
|
||||
file << CLOSE_MAP << std::endl;
|
||||
|
||||
if (PRIM->TME)
|
||||
{
|
||||
if (PRIM->FST)
|
||||
{
|
||||
file << INDENT;
|
||||
WriteTraceIndex("min_uv: ");
|
||||
file << OPEN_MAP;
|
||||
WriteUV_vec(m_vt.m_min.t);
|
||||
file << CLOSE_MAP << std::endl;
|
||||
|
||||
file << INDENT;
|
||||
WriteTraceIndex("max_uv: ");
|
||||
file << OPEN_MAP;
|
||||
WriteUV_vec(m_vt.m_max.t);
|
||||
file << CLOSE_MAP << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: The vertex trace does not actually track the min/max of raw ST values
|
||||
// hence the labels "min_uvq" and "max_uvq" are used instead of "min_stq" and "max_stq".
|
||||
file << INDENT;
|
||||
WriteTraceIndex("min_uvq: ");
|
||||
file << OPEN_MAP;
|
||||
WriteSTQ_vec(m_vt.m_min.t);
|
||||
file << CLOSE_MAP << std::endl;
|
||||
|
||||
file << INDENT;
|
||||
WriteTraceIndex("max_uvq: ");
|
||||
file << OPEN_MAP;
|
||||
WriteSTQ_vec(m_vt.m_max.t);
|
||||
file << CLOSE_MAP << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
file << INDENT;
|
||||
WriteTraceIndex("min_rgba: ");
|
||||
file << OPEN_MAP;
|
||||
WriteRGBA_vec(m_vt.m_min.c);
|
||||
file << CLOSE_MAP << std::endl;
|
||||
|
||||
file << INDENT;
|
||||
WriteTraceIndex("max_rgba: ");
|
||||
file << OPEN_MAP;
|
||||
WriteRGBA_vec(m_vt.m_max.c);
|
||||
file << CLOSE_MAP << std::endl;
|
||||
|
||||
file << std::endl;
|
||||
|
||||
file << INDENT;
|
||||
WriteTraceIndex("eq_xyz: ");
|
||||
file << OPEN_MAP;
|
||||
WriteBools({"X", "Y", "Z"}, {m_vt.m_eq.x, m_vt.m_eq.y, m_vt.m_eq.z});
|
||||
file << CLOSE_MAP << std::endl;
|
||||
|
||||
if (PRIM->TME)
|
||||
{
|
||||
if (PRIM->FST)
|
||||
{
|
||||
file << INDENT;
|
||||
WriteTraceIndex("eq_uv: ");
|
||||
file << OPEN_MAP;
|
||||
WriteBools({"U", "V"}, {m_vt.m_eq.s, m_vt.m_eq.t});
|
||||
file << CLOSE_MAP << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: The vertex trace does not actually track the min/max of raw ST values
|
||||
// hence the labels "eq_uvq" is used instead of "eq_stq".
|
||||
file << INDENT;
|
||||
WriteTraceIndex("eq_uvq: ");
|
||||
file << OPEN_MAP;
|
||||
WriteBools({"U", "V", "Q"}, {m_vt.m_eq.s, m_vt.m_eq.t, m_vt.m_eq.q});
|
||||
file << CLOSE_MAP << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
file << INDENT;
|
||||
WriteTraceIndex("eq_rgba: ");
|
||||
file << OPEN_MAP;
|
||||
WriteBools({"R", "G", "B", "A"}, {m_vt.m_eq.r, m_vt.m_eq.g, m_vt.m_eq.b, m_vt.m_eq.a});
|
||||
file << CLOSE_MAP << std::endl;
|
||||
}
|
||||
|
||||
void GSState::DumpTransferList(const std::string& filename)
|
||||
{
|
||||
// Only create the file if there are transfers to dump
|
||||
std::optional<std::ofstream> file;
|
||||
|
||||
constexpr const char* LIST_ITEM = "- ";
|
||||
constexpr const char* DEL = ", ";
|
||||
constexpr const char* INDENT = " ";
|
||||
constexpr const char* OPEN_MAP = "{";
|
||||
constexpr const char* CLOSE_MAP = "}";
|
||||
constexpr const char* COMMENT = " # ";
|
||||
|
||||
int n_dumped = 0; // Number of transfers dumped for this draw.
|
||||
for (int i = 0; i < static_cast<int>(m_draw_transfers.size()); ++i)
|
||||
{
|
||||
if (m_draw_transfers[i].draw != s_n - 1)
|
||||
continue; // skip transfers that did not start in the previous draw
|
||||
|
||||
if (!file.has_value())
|
||||
{
|
||||
file.emplace(filename);
|
||||
if (!file->is_open())
|
||||
return; // failed to open file
|
||||
file->imbue(std::locale::classic()); // Disable integer separators.
|
||||
}
|
||||
|
||||
const GSUploadQueue& transfer = m_draw_transfers[i];
|
||||
|
||||
if (n_dumped > 0)
|
||||
(*file) << std::endl;
|
||||
|
||||
// EE->GS or GS->GS
|
||||
(*file) << LIST_ITEM << "type: " << (transfer.ee_to_gs ? "EE_to_GS" : "GS_to_GS") << std::endl;
|
||||
|
||||
// Dump BITBLTBUF
|
||||
(*file) << INDENT << "BITBLTBUF: " << OPEN_MAP;
|
||||
|
||||
if (!transfer.ee_to_gs)
|
||||
{
|
||||
// Transferring GS->GS so the source info is relevant
|
||||
(*file) << "SBP: " << std::hex << std::showbase << transfer.blit.SBP << DEL <<
|
||||
"SBW: " << std::dec << transfer.blit.SBW << DEL <<
|
||||
"SPSM: " << std::hex << std::showbase << transfer.blit.SPSM << DEL;
|
||||
}
|
||||
|
||||
(*file) << "DBP: " << std::hex << std::showbase << transfer.blit.DBP << DEL <<
|
||||
"DBW: " << std::dec << transfer.blit.DBW << DEL <<
|
||||
"DPSM: " << std::hex << std::showbase << transfer.blit.DPSM << CLOSE_MAP;
|
||||
|
||||
(*file) << COMMENT; // Write the human-readable PSM in comments
|
||||
|
||||
if (!transfer.ee_to_gs)
|
||||
{
|
||||
// Transferring GS->GS so the source info is relevant
|
||||
(*file) << GSUtil::GetPSMName(transfer.blit.SPSM) << " -> ";
|
||||
}
|
||||
|
||||
(*file) << GSUtil::GetPSMName(transfer.blit.DPSM) << std::endl;
|
||||
|
||||
// Dump rectangle
|
||||
(*file) << INDENT << "rect: [" << std::dec << transfer.rect.x << DEL << transfer.rect.y << DEL <<
|
||||
transfer.rect.z << DEL << transfer.rect.w << "]" << std::endl;
|
||||
|
||||
// Dump zero_clear
|
||||
(*file) << INDENT << "zero_clear: " << (transfer.zero_clear ? "true" : "false") << std::endl;
|
||||
|
||||
n_dumped++;
|
||||
}
|
||||
}
|
||||
|
||||
void GSState::DumpTransferImages()
|
||||
{
|
||||
// Only create the file if there are transfers to dump
|
||||
std::optional<std::ofstream> file;
|
||||
|
||||
int transfer_n = 0;
|
||||
for (int i = 0; i < static_cast<int>(m_draw_transfers.size()); ++i)
|
||||
{
|
||||
if (m_draw_transfers[i].draw != s_n - 1)
|
||||
continue; // skip transfers that did not start in the previous draw
|
||||
|
||||
const GSUploadQueue& transfer = m_draw_transfers[i];
|
||||
|
||||
std::string filename;
|
||||
if (transfer.ee_to_gs)
|
||||
{
|
||||
// Transferring EE->GS then only the destination info is relevant.
|
||||
filename = GetDrawDumpPath("%05d_transfer%02d_EE_to_GS_%03x_%d_%s_%d_%d_%d_%d.png",
|
||||
s_n, transfer_n++, transfer.blit.DBP, transfer.blit.DBW, GSUtil::GetPSMName(transfer.blit.DPSM),
|
||||
transfer.rect.x, transfer.rect.y, transfer.rect.z, transfer.rect.w);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Transferring GS->GS then the source info is relevant.
|
||||
filename = GetDrawDumpPath("%05d_transfer%02d_GS_to_GS_%03x_%d_%s_%03x_%d_%s_%d_%d_%d_%d.bmp",
|
||||
s_n, transfer_n++, transfer.blit.SBP, transfer.blit.SBW, GSUtil::GetPSMName(transfer.blit.SPSM),
|
||||
transfer.blit.DBP, transfer.blit.DBW, GSUtil::GetPSMName(transfer.blit.DPSM),
|
||||
transfer.rect.x, transfer.rect.y, transfer.rect.z, transfer.rect.w);
|
||||
}
|
||||
|
||||
m_mem.SaveBMP(filename, transfer.blit.DBP, transfer.blit.DBW, transfer.blit.DPSM,
|
||||
transfer.rect.width(), transfer.rect.height(), transfer.rect.x, transfer.rect.y);
|
||||
}
|
||||
}
|
||||
|
||||
__inline void GSState::CheckFlushes()
|
||||
@@ -1771,6 +2062,20 @@ void GSState::FlushPrim()
|
||||
const bool skip_draw = (m_context->TEST.ZTE && m_context->TEST.ZTST == ZTST_NEVER);
|
||||
m_quad_check_valid = false;
|
||||
|
||||
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
|
||||
{
|
||||
if (GSConfig.SaveInfo)
|
||||
{
|
||||
// Only dump registers/vertices if we are drawing.
|
||||
// Always dump the transfers since these are relevant for debugging regardless of
|
||||
// whether the draw is skipped or not.
|
||||
DumpDrawInfo(!skip_draw, !skip_draw, true);
|
||||
}
|
||||
|
||||
if (GSConfig.SaveTransferImages)
|
||||
DumpTransferImages();
|
||||
}
|
||||
|
||||
if (!skip_draw)
|
||||
Draw();
|
||||
|
||||
@@ -2016,7 +2321,7 @@ void GSState::Write(const u8* mem, int len)
|
||||
}
|
||||
else
|
||||
{
|
||||
GSUploadQueue new_transfer = { blit, r, s_n, false };
|
||||
const GSUploadQueue new_transfer = { blit, r, s_n, false, true };
|
||||
m_draw_transfers.push_back(new_transfer);
|
||||
}
|
||||
|
||||
@@ -2207,7 +2512,7 @@ void GSState::Move()
|
||||
}
|
||||
else
|
||||
{
|
||||
GSUploadQueue new_transfer = { m_env.BITBLTBUF, r, s_n, false };
|
||||
const GSUploadQueue new_transfer = { m_env.BITBLTBUF, r, s_n, false, false };
|
||||
m_draw_transfers.push_back(new_transfer);
|
||||
}
|
||||
|
||||
|
||||
@@ -215,6 +215,7 @@ public:
|
||||
GSVector4i rect;
|
||||
int draw;
|
||||
bool zero_clear;
|
||||
bool ee_to_gs;
|
||||
};
|
||||
|
||||
enum NoGapsType
|
||||
@@ -441,7 +442,10 @@ public:
|
||||
u8* GetRegsMem() const { return reinterpret_cast<u8*>(m_regs); }
|
||||
void SetRegsMem(u8* basemem) { m_regs = reinterpret_cast<GSPrivRegSet*>(basemem); }
|
||||
|
||||
void DumpDrawInfo(bool dump_regs, bool dump_verts, bool dump_transfers);
|
||||
void DumpVertices(const std::string& filename);
|
||||
void DumpTransferList(const std::string& filename);
|
||||
void DumpTransferImages();
|
||||
|
||||
bool TrianglesAreQuads(bool shuffle_check = false);
|
||||
PRIM_OVERLAP PrimitiveOverlap();
|
||||
|
||||
@@ -114,6 +114,61 @@ const char* GSUtil::GetPrimName(u32 prim)
|
||||
return (prim < std::size(names)) ? names[prim] : "";
|
||||
}
|
||||
|
||||
const char* GSUtil::GetMMAGName(u32 mmag)
|
||||
{
|
||||
static constexpr const char* names[] = {"NEAREST", "LINEAR"};
|
||||
return (mmag < std::size(names)) ? names[mmag] : "";
|
||||
}
|
||||
|
||||
const char* GSUtil::GetMMINName(u32 mmin)
|
||||
{
|
||||
static constexpr const char* names[8] = {"NEAREST", "LINEAR", "NEAREST_MIPMAP_NEAREST", "NEAREST_MIPMAP_LINEAR",
|
||||
"LINEAR_MIPMAP_NEAREST", "LINEAR_MIPMAP_LINEAR"};
|
||||
return (mmin < std::size(names)) ? names[mmin] : "";
|
||||
}
|
||||
|
||||
const char* GSUtil::GetMTBAName(u32 mtba)
|
||||
{
|
||||
static constexpr const char* names[] = {"MIPTBP1", "AUTO"};
|
||||
return (mtba < std::size(names)) ? names[mtba] : "";
|
||||
}
|
||||
|
||||
const char* GSUtil::GetLCMName(u32 lcm)
|
||||
{
|
||||
static constexpr const char* names[] = {"Formula", "K"};
|
||||
return (lcm < std::size(names)) ? names[lcm] : "";
|
||||
}
|
||||
|
||||
const char* GSUtil::GetSCANMSKName(u32 scanmsk)
|
||||
{
|
||||
static constexpr const char* names[] = {"Normal", "Reserved", "Even prohibited", "Odd prohibited"};
|
||||
return (scanmsk < std::size(names)) ? names[scanmsk] : "";
|
||||
}
|
||||
|
||||
const char* GSUtil::GetDATMName(u32 datm)
|
||||
{
|
||||
static constexpr const char* names[] = {"0 pass", "1 pass"};
|
||||
return (datm < std::size(names)) ? names[datm] : "";
|
||||
}
|
||||
|
||||
const char* GSUtil::GetTFXName(u32 tfx)
|
||||
{
|
||||
static constexpr const char* names[] = {"MODULATE", "DECAL", "HIGHLIGHT", "HIGHLIGHT2"};
|
||||
return (tfx < std::size(names)) ? names[tfx] : "";
|
||||
}
|
||||
|
||||
const char* GSUtil::GetTCCName(u32 tcc)
|
||||
{
|
||||
static constexpr const char* names[] = {"RGB", "RGBA"};
|
||||
return (tcc < std::size(names)) ? names[tcc] : "";
|
||||
}
|
||||
|
||||
const char* GSUtil::GetACName(u32 ac)
|
||||
{
|
||||
static constexpr const char* names[] = {"PRMODE", "PRIM"};
|
||||
return (ac < std::size(names)) ? names[ac] : "";
|
||||
}
|
||||
|
||||
const u32* GSUtil::HasSharedBitsPtr(u32 dpsm)
|
||||
{
|
||||
return s_maps.SharedBitsField[dpsm];
|
||||
|
||||
@@ -15,6 +15,15 @@ public:
|
||||
static const char* GetWMName(u32 wm);
|
||||
static const char* GetZTSTName(u32 ztst);
|
||||
static const char* GetPrimName(u32 prim);
|
||||
static const char* GetMMAGName(u32 mmag);
|
||||
static const char* GetMMINName(u32 mmin);
|
||||
static const char* GetMTBAName(u32 mtba);
|
||||
static const char* GetLCMName(u32 lcm);
|
||||
static const char* GetSCANMSKName(u32 scanmsk);
|
||||
static const char* GetDATMName(u32 datm);
|
||||
static const char* GetTFXName(u32 tfx);
|
||||
static const char* GetTCCName(u32 tcc);
|
||||
static const char* GetACName(u32 ac);
|
||||
|
||||
static const u32* HasSharedBitsPtr(u32 dpsm);
|
||||
static bool HasSharedBits(u32 spsm, const u32* ptr);
|
||||
|
||||
@@ -569,9 +569,17 @@ void GSRenderer::EndPresentFrame()
|
||||
|
||||
void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
|
||||
{
|
||||
if (GSConfig.SaveInfo && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
|
||||
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
|
||||
{
|
||||
DumpGSPrivRegs(*m_regs, GetDrawDumpPath("%05d_f%05lld_vsync_gs_reg.txt", s_n, g_perfmon.GetFrame()));
|
||||
if (GSConfig.SaveInfo)
|
||||
{
|
||||
DumpGSPrivRegs(*m_regs, GetDrawDumpPath("%05d_f%05lld_vsync_gs_reg.txt", s_n, g_perfmon.GetFrame()));
|
||||
|
||||
DumpDrawInfo(false, false, true);
|
||||
}
|
||||
|
||||
if (GSConfig.SaveTransferImages)
|
||||
DumpTransferImages();
|
||||
}
|
||||
|
||||
const int fb_sprite_blits = g_perfmon.GetDisplayFramebufferSpriteBlits();
|
||||
@@ -1088,7 +1096,7 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
|
||||
if (i == 1 && !r.PMODE.EN2)
|
||||
continue;
|
||||
|
||||
std::fprintf(fp.get(), "DISPFB[%d] BP=%05x BW=%u PSM=%u DBX=%u DBY=%u\n",
|
||||
std::fprintf(fp.get(), "DISPFB%d: { BP: 0x%05x, BW: %u, PSM: %u, DBX: %u, DBY: %u }\n",
|
||||
i,
|
||||
r.DISP[i].DISPFB.Block(),
|
||||
r.DISP[i].DISPFB.FBW,
|
||||
@@ -1096,7 +1104,7 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
|
||||
r.DISP[i].DISPFB.DBX,
|
||||
r.DISP[i].DISPFB.DBY);
|
||||
|
||||
std::fprintf(fp.get(), "DISPLAY[%d] DX=%u DY=%u DW=%u DH=%u MAGH=%u MAGV=%u\n",
|
||||
std::fprintf(fp.get(), "DISPLAY%d: { DX: %u, DY: %u, DW: %u, DH: %u, MAGH: %u, MAGV: %u }\n",
|
||||
i,
|
||||
r.DISP[i].DISPLAY.DX,
|
||||
r.DISP[i].DISPLAY.DY,
|
||||
@@ -1106,7 +1114,7 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
|
||||
r.DISP[i].DISPLAY.MAGV);
|
||||
}
|
||||
|
||||
std::fprintf(fp.get(), "PMODE EN1=%u EN2=%u CRTMD=%u MMOD=%u AMOD=%u SLBG=%u ALP=%u\n",
|
||||
std::fprintf(fp.get(), "PMODE: { EN1: %u, EN2: %u, CRTMD: %u, MMOD: %u, AMOD: %u, SLBG: %u, ALP: %u }\n",
|
||||
r.PMODE.EN1,
|
||||
r.PMODE.EN2,
|
||||
r.PMODE.CRTMD,
|
||||
@@ -1115,7 +1123,8 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
|
||||
r.PMODE.SLBG,
|
||||
r.PMODE.ALP);
|
||||
|
||||
std::fprintf(fp.get(), "SMODE1 CLKSEL=%u CMOD=%u EX=%u GCONT=%u LC=%u NVCK=%u PCK2=%u PEHS=%u PEVS=%u PHS=%u PRST=%u PVS=%u RC=%u SINT=%u SLCK=%u SLCK2=%u SPML=%u T1248=%u VCKSEL=%u VHP=%u XPCK=%u\n",
|
||||
std::fprintf(fp.get(),
|
||||
"SMODE1: { CLKSEL: %u, CMOD: %u, EX: %u, GCONT: %u, LC: %u, NVCK: %u, PCK2: %u, PEHS: %u, PEVS: %u, PHS: %u, PRST: %u, PVS: %u, RC: %u, SINT: %u, SLCK: %u, SLCK2: %u, SPML: %u, T1248: %u, VCKSEL: %u, VHP: %u, XPCK: %u }\n",
|
||||
r.SMODE1.CLKSEL,
|
||||
r.SMODE1.CMOD,
|
||||
r.SMODE1.EX,
|
||||
@@ -1138,24 +1147,24 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
|
||||
r.SMODE1.VHP,
|
||||
r.SMODE1.XPCK);
|
||||
|
||||
std::fprintf(fp.get(), "SMODE2 INT=%u FFMD=%u DPMS=%u\n",
|
||||
std::fprintf(fp.get(), "SMODE2: { INT: %u, FFMD: %u, DPMS: %u }\n",
|
||||
r.SMODE2.INT,
|
||||
r.SMODE2.FFMD,
|
||||
r.SMODE2.DPMS);
|
||||
|
||||
std::fprintf(fp.get(), "SRFSH %08x_%08x\n",
|
||||
std::fprintf(fp.get(), "SRFSH: { U32_0: 0x%08x, U32_1: 0x%08x }\n",
|
||||
r.SRFSH.U32[0],
|
||||
r.SRFSH.U32[1]);
|
||||
|
||||
std::fprintf(fp.get(), "SYNCH1 %08x_%08x\n",
|
||||
std::fprintf(fp.get(), "SYNCH1: { U32_0: 0x%08x, U32_1: 0x%08x }\n",
|
||||
r.SYNCH1.U32[0],
|
||||
r.SYNCH1.U32[1]);
|
||||
|
||||
std::fprintf(fp.get(), "SYNCH2 %08x_%08x\n",
|
||||
std::fprintf(fp.get(), "SYNCH2: { U32_0: 0x%08x, U32_1: 0x%08x }\n",
|
||||
r.SYNCH2.U32[0],
|
||||
r.SYNCH2.U32[1]);
|
||||
|
||||
std::fprintf(fp.get(), "SYNCV VBP=%u VBPE=%u VDP=%u VFP=%u VFPE=%u VS=%u\n",
|
||||
std::fprintf(fp.get(), "SYNCV: { VBP: %u, VBPE: %u, VDP: %u, VFP: %u, VFPE: %u, VS: %u }\n",
|
||||
r.SYNCV.VBP,
|
||||
r.SYNCV.VBPE,
|
||||
r.SYNCV.VDP,
|
||||
@@ -1163,21 +1172,21 @@ void DumpGSPrivRegs(const GSPrivRegSet& r, const std::string& filename)
|
||||
r.SYNCV.VFPE,
|
||||
r.SYNCV.VS);
|
||||
|
||||
std::fprintf(fp.get(), "CSR %08x_%08x\n",
|
||||
std::fprintf(fp.get(), "CSR: { U32_0: 0x%08x, U32_1: 0x%08x }\n",
|
||||
r.CSR.U32[0],
|
||||
r.CSR.U32[1]);
|
||||
|
||||
std::fprintf(fp.get(), "BGCOLOR B=%u G=%u R=%u\n",
|
||||
std::fprintf(fp.get(), "BGCOLOR: { B: %u, G: %u, R: %u }\n",
|
||||
r.BGCOLOR.B,
|
||||
r.BGCOLOR.G,
|
||||
r.BGCOLOR.R);
|
||||
|
||||
std::fprintf(fp.get(), "EXTBUF BP=0x%x BW=%u FBIN=%u WFFMD=%u EMODA=%u EMODC=%u WDX=%u WDY=%u\n",
|
||||
std::fprintf(fp.get(), "EXTBUF: { BP: 0x%05x, BW: %u, FBIN: %u, WFFMD: %u, EMODA: %u, EMODC: %u, WDX: %u, WDY: %u }\n",
|
||||
r.EXTBUF.EXBP, r.EXTBUF.EXBW, r.EXTBUF.FBIN, r.EXTBUF.WFFMD,
|
||||
r.EXTBUF.EMODA, r.EXTBUF.EMODC, r.EXTBUF.WDX, r.EXTBUF.WDY);
|
||||
|
||||
std::fprintf(fp.get(), "EXTDATA SX=%u SY=%u SMPH=%u SMPV=%u WW=%u WH=%u\n",
|
||||
std::fprintf(fp.get(), "EXTDATA: { SX: %u, SY: %u, SMPH: %u, SMPV: %u, WW: %u, WH: %u }\n",
|
||||
r.EXTDATA.SX, r.EXTDATA.SY, r.EXTDATA.SMPH, r.EXTDATA.SMPV, r.EXTDATA.WW, r.EXTDATA.WH);
|
||||
|
||||
std::fprintf(fp.get(), "EXTWRITE EN=%u\n", r.EXTWRITE.WRITE);
|
||||
std::fprintf(fp.get(), "EXTWRITE: { EN: %u }\n", r.EXTWRITE.WRITE);
|
||||
}
|
||||
|
||||
@@ -2317,21 +2317,6 @@ void GSRendererHW::RoundSpriteOffset()
|
||||
|
||||
void GSRendererHW::Draw()
|
||||
{
|
||||
if (GSConfig.SaveInfo && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
|
||||
{
|
||||
std::string s;
|
||||
|
||||
// Dump Register state
|
||||
s = GetDrawDumpPath("%05d_context.txt", s_n);
|
||||
|
||||
m_draw_env->Dump(s);
|
||||
m_context->Dump(s);
|
||||
|
||||
// Dump vertices
|
||||
s = GetDrawDumpPath("%05d_vertex.txt", s_n);
|
||||
DumpVertices(s);
|
||||
}
|
||||
|
||||
static u32 num_skipped_channel_shuffle_draws = 0;
|
||||
|
||||
// We mess with this state as an optimization, so take a copy and use that instead.
|
||||
|
||||
@@ -309,21 +309,6 @@ void GSRendererSW::Draw()
|
||||
{
|
||||
const GSDrawingContext* context = m_context;
|
||||
|
||||
if (GSConfig.SaveInfo && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
|
||||
{
|
||||
std::string s;
|
||||
|
||||
// Dump Register state
|
||||
s = GetDrawDumpPath("%05d_context.txt", s_n);
|
||||
|
||||
m_draw_env->Dump(s);
|
||||
m_context->Dump(s);
|
||||
|
||||
// Dump vertices
|
||||
s = GetDrawDumpPath("%05d_vertex.txt", s_n);
|
||||
DumpVertices(s);
|
||||
}
|
||||
|
||||
auto data = m_vertex_heap.make_shared<SharedData>().cast<GSRasterizerData>();
|
||||
SharedData* sd = static_cast<SharedData*>(data.get());
|
||||
|
||||
|
||||
@@ -113,32 +113,37 @@ static bool UseSavestateSelector()
|
||||
}
|
||||
|
||||
BEGIN_HOTKEY_LIST(g_common_hotkeys)
|
||||
DEFINE_HOTKEY("OpenPauseMenu", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Open Pause Menu"),
|
||||
DEFINE_HOTKEY("ToggleFullscreen", TRANSLATE_NOOP("Hotkeys", "Navigation"), TRANSLATE_NOOP("Hotkeys", "Toggle Fullscreen"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed)
|
||||
Host::SetFullscreen(!Host::IsFullscreen());
|
||||
})
|
||||
DEFINE_HOTKEY("OpenPauseMenu", TRANSLATE_NOOP("Hotkeys", "Navigation"), TRANSLATE_NOOP("Hotkeys", "Open Pause Menu"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM() && CanPause())
|
||||
FullscreenUI::OpenPauseMenu();
|
||||
})
|
||||
DEFINE_HOTKEY("OpenAchievementsList", TRANSLATE_NOOP("Hotkeys", "System"),
|
||||
DEFINE_HOTKEY("OpenAchievementsList", TRANSLATE_NOOP("Hotkeys", "Navigation"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Open Achievements List"), [](s32 pressed) {
|
||||
if (!pressed && CanPause())
|
||||
FullscreenUI::OpenAchievementsWindow();
|
||||
})
|
||||
DEFINE_HOTKEY("OpenLeaderboardsList", TRANSLATE_NOOP("Hotkeys", "System"),
|
||||
DEFINE_HOTKEY("OpenLeaderboardsList", TRANSLATE_NOOP("Hotkeys", "Navigation"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Open Leaderboards List"), [](s32 pressed) {
|
||||
if (!pressed && CanPause())
|
||||
FullscreenUI::OpenLeaderboardsWindow();
|
||||
})
|
||||
DEFINE_HOTKEY(
|
||||
"TogglePause", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Toggle Pause"), [](s32 pressed) {
|
||||
"TogglePause", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Toggle Pause"), [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM() && CanPause())
|
||||
VMManager::SetPaused(VMManager::GetState() != VMState::Paused);
|
||||
})
|
||||
DEFINE_HOTKEY("ToggleFullscreen", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Toggle Fullscreen"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed)
|
||||
Host::SetFullscreen(!Host::IsFullscreen());
|
||||
DEFINE_HOTKEY(
|
||||
"FrameAdvance", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Frame Advance"), [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
VMManager::FrameAdvance(1);
|
||||
})
|
||||
DEFINE_HOTKEY("ToggleFrameLimit", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Toggle Frame Limit"),
|
||||
DEFINE_HOTKEY("ToggleFrameLimit", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Toggle Frame Limit"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
{
|
||||
@@ -147,7 +152,7 @@ DEFINE_HOTKEY("ToggleFrameLimit", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE
|
||||
LimiterModeType::Nominal);
|
||||
}
|
||||
})
|
||||
DEFINE_HOTKEY("ToggleTurbo", TRANSLATE_NOOP("Hotkeys", "System"),
|
||||
DEFINE_HOTKEY("ToggleTurbo", TRANSLATE_NOOP("Hotkeys", "Speed"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Toggle Turbo / Fast Forward"), [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
{
|
||||
@@ -155,15 +160,7 @@ DEFINE_HOTKEY("ToggleTurbo", TRANSLATE_NOOP("Hotkeys", "System"),
|
||||
(VMManager::GetLimiterMode() != LimiterModeType::Turbo) ? LimiterModeType::Turbo : LimiterModeType::Nominal);
|
||||
}
|
||||
})
|
||||
DEFINE_HOTKEY("ToggleSlowMotion", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Toggle Slow Motion"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
{
|
||||
VMManager::SetLimiterMode(
|
||||
(VMManager::GetLimiterMode() != LimiterModeType::Slomo) ? LimiterModeType::Slomo : LimiterModeType::Nominal);
|
||||
}
|
||||
})
|
||||
DEFINE_HOTKEY("HoldTurbo", TRANSLATE_NOOP("Hotkeys", "System"),
|
||||
DEFINE_HOTKEY("HoldTurbo", TRANSLATE_NOOP("Hotkeys", "Speed"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Turbo / Fast Forward (Hold)"), [](s32 pressed) {
|
||||
if (!VMManager::HasValidVM())
|
||||
return;
|
||||
@@ -180,35 +177,24 @@ DEFINE_HOTKEY("HoldTurbo", TRANSLATE_NOOP("Hotkeys", "System"),
|
||||
s_limiter_mode_prior_to_hold_interaction.reset();
|
||||
}
|
||||
})
|
||||
DEFINE_HOTKEY("IncreaseSpeed", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Increase Target Speed"),
|
||||
DEFINE_HOTKEY("ToggleSlowMotion", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Toggle Slow Motion"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
{
|
||||
VMManager::SetLimiterMode(
|
||||
(VMManager::GetLimiterMode() != LimiterModeType::Slomo) ? LimiterModeType::Slomo : LimiterModeType::Nominal);
|
||||
}
|
||||
})
|
||||
DEFINE_HOTKEY("IncreaseSpeed", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Increase Target Speed"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
HotkeyAdjustTargetSpeed(0.1);
|
||||
})
|
||||
DEFINE_HOTKEY("DecreaseSpeed", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Decrease Target Speed"),
|
||||
DEFINE_HOTKEY("DecreaseSpeed", TRANSLATE_NOOP("Hotkeys", "Speed"), TRANSLATE_NOOP("Hotkeys", "Decrease Target Speed"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
HotkeyAdjustTargetSpeed(-0.1);
|
||||
})
|
||||
DEFINE_HOTKEY("IncreaseVolume", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Increase Volume"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
HotkeyAdjustVolume(-1, 5);
|
||||
})
|
||||
DEFINE_HOTKEY("DecreaseVolume", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Decrease Volume"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
HotkeyAdjustVolume(-1, -5);
|
||||
})
|
||||
DEFINE_HOTKEY("Mute", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Toggle Mute"), [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
HotkeyAdjustVolume((SPU2::GetOutputVolume() == 0) ? SPU2::GetResetVolume() : 0, 0);
|
||||
})
|
||||
DEFINE_HOTKEY(
|
||||
"FrameAdvance", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Frame Advance"), [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
VMManager::FrameAdvance(1);
|
||||
})
|
||||
DEFINE_HOTKEY("ShutdownVM", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Hotkeys", "Shut Down Virtual Machine"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
@@ -219,11 +205,6 @@ DEFINE_HOTKEY("ResetVM", TRANSLATE_NOOP("Hotkeys", "System"), TRANSLATE_NOOP("Ho
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
VMManager::Reset();
|
||||
})
|
||||
DEFINE_HOTKEY("InputRecToggleMode", TRANSLATE_NOOP("Hotkeys", "System"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Toggle Input Recording Mode"), [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
g_InputRecording.getControls().toggleRecordMode();
|
||||
})
|
||||
DEFINE_HOTKEY("SwapMemCards", TRANSLATE_NOOP("Hotkeys", "System"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Swap Memory Cards"), [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
@@ -231,6 +212,11 @@ DEFINE_HOTKEY("SwapMemCards", TRANSLATE_NOOP("Hotkeys", "System"),
|
||||
FileMcd_Swap();
|
||||
});
|
||||
})
|
||||
DEFINE_HOTKEY("InputRecToggleMode", TRANSLATE_NOOP("Hotkeys", "System"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Toggle Input Recording Mode"), [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
g_InputRecording.getControls().toggleRecordMode();
|
||||
})
|
||||
DEFINE_HOTKEY("PreviousSaveStateSlot", TRANSLATE_NOOP("Hotkeys", "Save States"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Select Previous Save Slot"), [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
@@ -305,4 +291,18 @@ DEFINE_HOTKEY_SAVESTATE_X(10, TRANSLATE_NOOP("Hotkeys", "Save State To Slot 10")
|
||||
DEFINE_HOTKEY_LOADSTATE_X(10, TRANSLATE_NOOP("Hotkeys", "Load State From Slot 10"))
|
||||
#undef DEFINE_HOTKEY_SAVESTATE_X
|
||||
#undef DEFINE_HOTKEY_LOADSTATE_X
|
||||
DEFINE_HOTKEY("Mute", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_NOOP("Hotkeys", "Toggle Mute"), [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
HotkeyAdjustVolume((SPU2::GetOutputVolume() == 0) ? SPU2::GetResetVolume() : 0, 0);
|
||||
})
|
||||
DEFINE_HOTKEY("IncreaseVolume", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_NOOP("Hotkeys", "Increase Volume"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
HotkeyAdjustVolume(-1, 5);
|
||||
})
|
||||
DEFINE_HOTKEY("DecreaseVolume", TRANSLATE_NOOP("Hotkeys", "Audio"), TRANSLATE_NOOP("Hotkeys", "Decrease Volume"),
|
||||
[](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
HotkeyAdjustVolume(-1, -5);
|
||||
})
|
||||
END_HOTKEY_LIST()
|
||||
|
||||
@@ -6443,6 +6443,44 @@ void FullscreenUI::DrawResumeStateSelector()
|
||||
|
||||
void FullscreenUI::DoLoadState(std::string path)
|
||||
{
|
||||
// Check for hardcore mode before loading state
|
||||
if (Achievements::IsHardcoreModeActive())
|
||||
{
|
||||
Achievements::ConfirmHardcoreModeDisableAsync(TRANSLATE("VMManager", "Loading state"),
|
||||
[path = std::move(path)](bool approved) {
|
||||
if (approved)
|
||||
DoLoadState(std::move(path));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string filename = std::string(Path::GetFileName(path));
|
||||
s32 slot = -1;
|
||||
bool is_backup = false;
|
||||
|
||||
std::string base_filename = filename;
|
||||
if (filename.length() > 7 && filename.substr(filename.length() - 7) == ".backup")
|
||||
{
|
||||
is_backup = true;
|
||||
base_filename = filename.substr(0, filename.length() - 7);
|
||||
}
|
||||
|
||||
// Get slot number from filename (format: serial.crc.slot.p2s)
|
||||
const size_t last_dot = base_filename.rfind('.');
|
||||
const size_t second_last_dot = base_filename.rfind('.', last_dot - 1);
|
||||
if (last_dot != std::string::npos && second_last_dot != std::string::npos)
|
||||
{
|
||||
const std::string slot_str = base_filename.substr(second_last_dot + 1, last_dot - second_last_dot - 1);
|
||||
if (!slot_str.empty())
|
||||
slot = std::atoi(slot_str.c_str());
|
||||
}
|
||||
|
||||
const std::string message = (slot >= 0) ?
|
||||
fmt::format(TRANSLATE_FS("VMManager", "Loading {} from slot {}..."), is_backup ? TRANSLATE("VMManager", "backup state") : TRANSLATE("VMManager", "state"), slot) :
|
||||
TRANSLATE_STR("VMManager", "Loading save state...");
|
||||
|
||||
Host::AddIconOSDMessage("LoadStateFromSlot", ICON_FA_FOLDER_OPEN, message, Host::OSD_QUICK_DURATION);
|
||||
|
||||
Host::RunOnCPUThread([path = std::move(path)]()
|
||||
{
|
||||
const std::string boot_path = s_save_state_selector_game_path;
|
||||
|
||||
@@ -467,7 +467,7 @@ ImFont* ImGuiManager::AddTextFont()
|
||||
{
|
||||
// Exclude FA and PF ranges
|
||||
// clang-format off
|
||||
static constexpr ImWchar range_exclude_icons[] = { 0x2198,0x2199,0x219e,0x21a7,0x21b0,0x21b3,0x21ba,0x21c3,0x21ce,0x21d4,0x21dc,0x21dd,0x21e0,0x21e3,0x21e6,0x21e8,0x21f3,0x21f3,0x21f7,0x21fb,0x2206,0x2208,0x221a,0x221a,0x227a,0x227d,0x22bf,0x22c8,0x2349,0x2349,0x235a,0x2361,0x2364,0x2367,0x237a,0x237f,0x23b2,0x23b5,0x23cc,0x23cc,0x23f4,0x23f7,0x2427,0x243a,0x243d,0x243d,0x2443,0x2443,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24ff,0x2605,0x2605,0x2699,0x2699,0x278a,0x278e,0xff21,0xff3a,0x0,0x0 };
|
||||
static constexpr ImWchar range_exclude_icons[] = { 0x2198,0x2199,0x219e,0x21a7,0x21b0,0x21b3,0x21ba,0x21c3,0x21ce,0x21d4,0x21dc,0x21dd,0x21e0,0x21e3,0x21e6,0x21e8,0x21f3,0x21f3,0x21f7,0x21fb,0x2206,0x2208,0x221a,0x221a,0x227a,0x227d,0x22bf,0x22c8,0x2349,0x2349,0x235a,0x2361,0x2364,0x2367,0x237a,0x237f,0x23b2,0x23b5,0x23cc,0x23cc,0x23f4,0x23f7,0x2427,0x243a,0x243d,0x243e,0x2441,0x2452,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24ff,0x2605,0x2605,0x2699,0x2699,0x278a,0x278e,0xff21,0xff3a,0x0,0x0 };
|
||||
// clang-format on
|
||||
|
||||
ImFontConfig cfg;
|
||||
|
||||
@@ -670,7 +670,7 @@ __ri void ImGuiManager::DrawInputsOverlay(float scale, float margin, float spaci
|
||||
|
||||
for (u32 port = 0; port < USB::NUM_PORTS; port++)
|
||||
{
|
||||
if (EmuConfig.USB.Ports[port].DeviceType >= 0 && !USB::GetDeviceBindings(port).empty())
|
||||
if (EmuConfig.USB.Ports[port].DeviceType >= 0)
|
||||
num_ports++;
|
||||
}
|
||||
|
||||
@@ -688,10 +688,7 @@ __ri void ImGuiManager::DrawInputsOverlay(float scale, float margin, float spaci
|
||||
continue;
|
||||
|
||||
const Pad::ControllerInfo& cinfo = pad->GetInfo();
|
||||
if (cinfo.icon_name)
|
||||
text.format("{} {}", cinfo.icon_name, slot + 1u);
|
||||
else
|
||||
text.format("{} |", slot + 1u);
|
||||
text.format("{} {} • {} |", ICON_FA_GAMEPAD, slot + 1u, cinfo.icon_name ? cinfo.icon_name : ICON_FA_TRIANGLE_EXCLAMATION);
|
||||
|
||||
for (u32 bind = 0; bind < static_cast<u32>(cinfo.bindings.size()); bind++)
|
||||
{
|
||||
@@ -744,10 +741,9 @@ __ri void ImGuiManager::DrawInputsOverlay(float scale, float margin, float spaci
|
||||
continue;
|
||||
|
||||
const std::span<const InputBindingInfo> bindings(USB::GetDeviceBindings(port));
|
||||
if (bindings.empty())
|
||||
continue;
|
||||
|
||||
text.format("{} {} ", ICON_PF_USB, port + 1u);
|
||||
const char* icon = USB::GetDeviceIconName(port);
|
||||
text.format("{} {} • {} | ", ICON_PF_USB, port + 1u, icon ? icon : ICON_FA_TRIANGLE_EXCLAMATION);
|
||||
|
||||
for (const InputBindingInfo& bi : bindings)
|
||||
{
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "vtlb.h"
|
||||
#include "MemoryTypes.h"
|
||||
#include "common/BitUtils.h"
|
||||
|
||||
// This is a table of default virtual map addresses for ps2vm components. These locations
|
||||
// are provided and used to assist in debugging and possibly hacking; as it makes it possible
|
||||
@@ -22,13 +24,15 @@ namespace HostMemoryMap
|
||||
// Main
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// PS2 main memory, SPR, and ROMs (approximately 138.5MB, but we round up to 139MB for simplicity).
|
||||
// PS2 main memory, SPR, and ROMs (approximately 143MB).
|
||||
// Needs to be big enough to fit the EEVM_MemoryAllocMess struct
|
||||
static constexpr u32 EEmemOffset = 0x00000000;
|
||||
static constexpr u32 EEmemSize = 0x8B00000;
|
||||
static constexpr u32 EEmemSize = Common::AlignUp(sizeof(EEVM_MemoryAllocMess), _1mb);
|
||||
|
||||
// IOP main memory (2MB + 64K + 256b, rounded up to 3MB for simplicity).
|
||||
// IOP main memory (approximately 3MB).
|
||||
// Needs to be big enough to fit the IopVM_MemoryAllocMess struct
|
||||
static constexpr u32 IOPmemOffset = EEmemOffset + EEmemSize;
|
||||
static constexpr u32 IOPmemSize = 0x300000;
|
||||
static constexpr u32 IOPmemSize = Common::AlignUp(sizeof(IopVM_MemoryAllocMess), _1mb);
|
||||
|
||||
// VU0 and VU1 memory (40KB, rounded up to 1MB for simplicity).
|
||||
static constexpr u32 VUmemOffset = IOPmemOffset + IOPmemSize;
|
||||
|
||||
@@ -29,6 +29,7 @@ typedef u32 mem32_t;
|
||||
typedef u64 mem64_t;
|
||||
typedef u128 mem128_t;
|
||||
|
||||
// Needs to fit within EEmemSize of Memory.h
|
||||
struct EEVM_MemoryAllocMess
|
||||
{
|
||||
u8 Main[Ps2MemSize::MainRam]; // Main memory (hard-wired to 32MB)
|
||||
@@ -47,6 +48,7 @@ struct EEVM_MemoryAllocMess
|
||||
u8 ZeroWrite[_1mb];
|
||||
};
|
||||
|
||||
// Needs to fit within IOPmemSize of Memory.h
|
||||
struct IopVM_MemoryAllocMess
|
||||
{
|
||||
u8 Main[Ps2MemSize::IopRam]; // Main memory (hard-wired to 2MB)
|
||||
|
||||
131
pcsx2/PINE.cpp
131
pcsx2/PINE.cpp
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#if _WIN32
|
||||
#if defined(_WIN32)
|
||||
#define read_portable(a, b, c) (recv(a, (char*)b, c, 0))
|
||||
#define write_portable(a, b, c) (send(a, (const char*)b, c, 0))
|
||||
#define safe_close_portable(a) \
|
||||
@@ -31,9 +31,23 @@
|
||||
(a) = INVALID_SOCKET; \
|
||||
} \
|
||||
} while (0)
|
||||
#define bzero(b, len) (memset((b), '\0', (len)), (void)0)
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include <WinSock2.h>
|
||||
#elif defined(__linux__) || defined(__FreeBSD__)
|
||||
#define read_portable(a, b, c) (read(a, b, c))
|
||||
#define write_portable(a, b, c) (send(a, b, c, MSG_NOSIGNAL))
|
||||
#define safe_close_portable(a) \
|
||||
do \
|
||||
{ \
|
||||
if ((a) >= 0) \
|
||||
{ \
|
||||
close((a)); \
|
||||
(a) = -1; \
|
||||
} \
|
||||
} while (0)
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#define read_portable(a, b, c) (read(a, b, c))
|
||||
#define write_portable(a, b, c) (write(a, b, c))
|
||||
@@ -74,25 +88,25 @@ static bool InitializeWinsock()
|
||||
|
||||
namespace PINEServer
|
||||
{
|
||||
std::thread m_thread;
|
||||
int m_slot;
|
||||
static std::thread s_thread;
|
||||
static int s_slot;
|
||||
|
||||
#ifdef _WIN32
|
||||
// windows claim to have support for AF_UNIX sockets but that is a blatant lie,
|
||||
// their SDK won't even run their own examples, so we go on TCP sockets.
|
||||
static SOCKET m_sock = INVALID_SOCKET;
|
||||
static SOCKET s_sock = INVALID_SOCKET;
|
||||
// the message socket used in thread's accept().
|
||||
static SOCKET m_msgsock = INVALID_SOCKET;
|
||||
static SOCKET s_msgsock = INVALID_SOCKET;
|
||||
#else
|
||||
// absolute path of the socket. Stored in XDG_RUNTIME_DIR, if unset /tmp
|
||||
static std::string m_socket_name;
|
||||
static int m_sock = -1;
|
||||
static std::string s_socket_name;
|
||||
static int s_sock = -1;
|
||||
// the message socket used in thread's accept().
|
||||
static int m_msgsock = -1;
|
||||
static int s_msgsock = -1;
|
||||
#endif
|
||||
|
||||
// Whether the socket processing thread should stop executing/is stopped.
|
||||
static std::atomic_bool m_end{true};
|
||||
static std::atomic_bool s_end{true};
|
||||
|
||||
/**
|
||||
* Maximum memory used by an IPC message request.
|
||||
@@ -111,13 +125,13 @@ namespace PINEServer
|
||||
* A preallocated buffer used to store all IPC replies.
|
||||
* to the size of 50.000 MsgWrite64 IPC calls.
|
||||
*/
|
||||
static std::vector<u8> m_ret_buffer;
|
||||
static std::vector<u8> s_ret_buffer;
|
||||
|
||||
/**
|
||||
* IPC messages buffer.
|
||||
* A preallocated buffer used to store all IPC messages.
|
||||
*/
|
||||
static std::vector<u8> m_ipc_buffer;
|
||||
static std::vector<u8> s_ipc_buffer;
|
||||
|
||||
/**
|
||||
* IPC Command messages opcodes.
|
||||
@@ -246,8 +260,8 @@ namespace PINEServer
|
||||
|
||||
bool PINEServer::Initialize(int slot)
|
||||
{
|
||||
m_end.store(false, std::memory_order_release);
|
||||
m_slot = slot;
|
||||
s_end.store(false, std::memory_order_release);
|
||||
s_slot = slot;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!InitializeWinsock())
|
||||
@@ -257,8 +271,8 @@ bool PINEServer::Initialize(int slot)
|
||||
return false;
|
||||
}
|
||||
|
||||
m_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if ((m_sock == INVALID_SOCKET) || slot > 65536)
|
||||
s_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if ((s_sock == INVALID_SOCKET) || slot > 65536)
|
||||
{
|
||||
Console.WriteLn(Color_Red, "PINE: Cannot open socket! Shutting down...");
|
||||
Deinitialize();
|
||||
@@ -270,7 +284,7 @@ bool PINEServer::Initialize(int slot)
|
||||
server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // localhost only
|
||||
server.sin_port = htons(slot);
|
||||
|
||||
if (bind(m_sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
|
||||
if (bind(s_sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR)
|
||||
{
|
||||
Console.WriteLn(Color_Red, "PINE: Error while binding to socket! Shutting down...");
|
||||
Deinitialize();
|
||||
@@ -287,32 +301,32 @@ bool PINEServer::Initialize(int slot)
|
||||
// fallback in case macOS or other OSes don't implement the XDG base
|
||||
// spec
|
||||
if (runtime_dir == nullptr)
|
||||
m_socket_name = "/tmp/" PINE_EMULATOR_NAME ".sock";
|
||||
s_socket_name = "/tmp/" PINE_EMULATOR_NAME ".sock";
|
||||
else
|
||||
{
|
||||
m_socket_name = runtime_dir;
|
||||
m_socket_name += "/" PINE_EMULATOR_NAME ".sock";
|
||||
s_socket_name = runtime_dir;
|
||||
s_socket_name += "/" PINE_EMULATOR_NAME ".sock";
|
||||
}
|
||||
|
||||
if (slot != PINE_DEFAULT_SLOT)
|
||||
m_socket_name += "." + std::to_string(slot);
|
||||
s_socket_name += "." + std::to_string(slot);
|
||||
|
||||
struct sockaddr_un server;
|
||||
|
||||
m_sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (m_sock < 0)
|
||||
s_sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (s_sock < 0)
|
||||
{
|
||||
Console.WriteLn(Color_Red, "PINE: Cannot open socket! Shutting down...");
|
||||
Deinitialize();
|
||||
return false;
|
||||
}
|
||||
server.sun_family = AF_UNIX;
|
||||
StringUtil::Strlcpy(server.sun_path, m_socket_name, sizeof(server.sun_path));
|
||||
StringUtil::Strlcpy(server.sun_path, s_socket_name, sizeof(server.sun_path));
|
||||
|
||||
// we unlink the socket so that when releasing this thread the socket gets
|
||||
// freed even if we didn't close correctly the loop
|
||||
unlink(m_socket_name.c_str());
|
||||
if (bind(m_sock, (struct sockaddr*)&server, sizeof(struct sockaddr_un)))
|
||||
unlink(s_socket_name.c_str());
|
||||
if (bind(s_sock, (struct sockaddr*)&server, sizeof(struct sockaddr_un)))
|
||||
{
|
||||
Console.WriteLn(Color_Red, "PINE: Error while binding to socket! Shutting down...");
|
||||
Deinitialize();
|
||||
@@ -323,7 +337,7 @@ bool PINEServer::Initialize(int slot)
|
||||
// maximum queue of 4096 commands before refusing, approximated to the
|
||||
// nearest legal value. We do not use SOMAXCONN as windows have this idea
|
||||
// that a "reasonable" value is 5, which is not.
|
||||
if (listen(m_sock, 4096))
|
||||
if (listen(s_sock, 4096))
|
||||
{
|
||||
Console.WriteLn(Color_Red, "PINE: Cannot listen for connections! Shutting down...");
|
||||
Deinitialize();
|
||||
@@ -332,23 +346,23 @@ bool PINEServer::Initialize(int slot)
|
||||
|
||||
// we allocate once buffers to not have to do mallocs for each IPC
|
||||
// request, as malloc is expansive when we optimize for µs.
|
||||
m_ret_buffer.resize(MAX_IPC_RETURN_SIZE);
|
||||
m_ipc_buffer.resize(MAX_IPC_SIZE);
|
||||
s_ret_buffer.resize(MAX_IPC_RETURN_SIZE);
|
||||
s_ipc_buffer.resize(MAX_IPC_SIZE);
|
||||
|
||||
// we start the thread
|
||||
m_thread = std::thread(&PINEServer::MainLoop);
|
||||
s_thread = std::thread(&PINEServer::MainLoop);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PINEServer::IsInitialized()
|
||||
{
|
||||
return !m_end.load(std::memory_order_acquire);
|
||||
return !s_end.load(std::memory_order_acquire);
|
||||
}
|
||||
|
||||
int PINEServer::GetSlot()
|
||||
{
|
||||
return m_slot;
|
||||
return s_slot;
|
||||
}
|
||||
|
||||
std::vector<u8>& PINEServer::MakeOkIPC(std::vector<u8>& ret_buffer, uint32_t size = 5)
|
||||
@@ -367,24 +381,29 @@ std::vector<u8>& PINEServer::MakeFailIPC(std::vector<u8>& ret_buffer, uint32_t s
|
||||
|
||||
bool PINEServer::AcceptClient()
|
||||
{
|
||||
m_msgsock = accept(m_sock, 0, 0);
|
||||
if (m_msgsock >= 0)
|
||||
s_msgsock = accept(s_sock, 0, 0);
|
||||
if (s_msgsock >= 0)
|
||||
{
|
||||
// Gross C-style cast, but SOCKET is a handle on Windows.
|
||||
Console.WriteLn("PINE: New client with FD %d connected.", (int)m_msgsock);
|
||||
Console.WriteLn("PINE: New client with FD %d connected.", (int)s_msgsock);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
int nosigpipe = 1;
|
||||
setsockopt(s_msgsock, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
|
||||
#endif
|
||||
|
||||
// everything else is non recoverable in our scope
|
||||
// we also mark as recoverable socket errors where it would block a
|
||||
// non blocking socket, even though our socket is blocking, in case
|
||||
// we ever have to implement a non blocking socket.
|
||||
#ifdef _WIN32
|
||||
const int errno_w = WSAGetLastError();
|
||||
if (!(errno_w == WSAECONNRESET || errno_w == WSAEINTR || errno_w == WSAEINPROGRESS || errno_w == WSAEMFILE || errno_w == WSAEWOULDBLOCK) && m_sock != INVALID_SOCKET)
|
||||
if (!(errno_w == WSAECONNRESET || errno_w == WSAEINTR || errno_w == WSAEINPROGRESS || errno_w == WSAEMFILE || errno_w == WSAEWOULDBLOCK) && s_sock != INVALID_SOCKET)
|
||||
Console.Error("PINE: accept() returned error %d", errno_w);
|
||||
#else
|
||||
if (!(errno == ECONNABORTED || errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) && m_sock >= 0)
|
||||
if (!(errno == ECONNABORTED || errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) && s_sock >= 0)
|
||||
Console.Error("PINE: accept() returned error %d", errno);
|
||||
#endif
|
||||
|
||||
@@ -395,7 +414,7 @@ void PINEServer::MainLoop()
|
||||
{
|
||||
Threading::SetNameOfCurrentThread("PINE Server");
|
||||
|
||||
while (!m_end.load(std::memory_order_acquire))
|
||||
while (!s_end.load(std::memory_order_acquire))
|
||||
{
|
||||
if (!AcceptClient())
|
||||
continue;
|
||||
@@ -403,25 +422,25 @@ void PINEServer::MainLoop()
|
||||
ClientLoop();
|
||||
|
||||
Console.WriteLn("PINE: Client disconnected.");
|
||||
safe_close_portable(m_msgsock);
|
||||
safe_close_portable(s_msgsock);
|
||||
}
|
||||
}
|
||||
|
||||
void PINEServer::ClientLoop()
|
||||
{
|
||||
while (!m_end.load(std::memory_order_acquire))
|
||||
while (!s_end.load(std::memory_order_acquire))
|
||||
{
|
||||
// either int or ssize_t depending on the platform, so we have to
|
||||
// use a bunch of auto
|
||||
auto receive_length = 0;
|
||||
auto end_length = 4;
|
||||
const std::span<u8> ipc_buffer_span(m_ipc_buffer);
|
||||
const std::span<u8> ipc_buffer_span(s_ipc_buffer);
|
||||
|
||||
// while we haven't received the entire packet, maybe due to
|
||||
// socket datagram splittage, we continue to read
|
||||
while (receive_length < end_length)
|
||||
{
|
||||
const auto tmp_length = read_portable(m_msgsock, &ipc_buffer_span[receive_length], MAX_IPC_SIZE - receive_length);
|
||||
const auto tmp_length = read_portable(s_msgsock, &ipc_buffer_span[receive_length], MAX_IPC_SIZE - receive_length);
|
||||
|
||||
// we recreate the socket if an error happens
|
||||
if (tmp_length <= 0)
|
||||
@@ -450,10 +469,10 @@ void PINEServer::ClientLoop()
|
||||
// disconnects
|
||||
if (receive_length != 0)
|
||||
{
|
||||
res = ParseCommand(ipc_buffer_span.subspan(4), m_ret_buffer, (u32)end_length - 4);
|
||||
res = ParseCommand(ipc_buffer_span.subspan(4), s_ret_buffer, (u32)end_length - 4);
|
||||
|
||||
// if we cannot send back our answer restart the socket
|
||||
if (write_portable(m_msgsock, res.buffer.data(), res.size) < 0)
|
||||
if (write_portable(s_msgsock, res.buffer.data(), res.size) < 0)
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -461,30 +480,30 @@ void PINEServer::ClientLoop()
|
||||
|
||||
void PINEServer::Deinitialize()
|
||||
{
|
||||
m_end.store(true, std::memory_order_release);
|
||||
s_end.store(true, std::memory_order_release);
|
||||
|
||||
#ifndef _WIN32
|
||||
if (!m_socket_name.empty())
|
||||
if (!s_socket_name.empty())
|
||||
{
|
||||
unlink(m_socket_name.c_str());
|
||||
m_socket_name = {};
|
||||
unlink(s_socket_name.c_str());
|
||||
s_socket_name = {};
|
||||
}
|
||||
#endif
|
||||
|
||||
// shutdown() is needed, otherwise accept() will still block.
|
||||
#ifdef _WIN32
|
||||
if (m_sock != INVALID_SOCKET)
|
||||
shutdown(m_sock, SD_BOTH);
|
||||
if (s_sock != INVALID_SOCKET)
|
||||
shutdown(s_sock, SD_BOTH);
|
||||
#else
|
||||
if (m_sock >= 0)
|
||||
shutdown(m_sock, SHUT_RDWR);
|
||||
if (s_sock >= 0)
|
||||
shutdown(s_sock, SHUT_RDWR);
|
||||
#endif
|
||||
|
||||
safe_close_portable(m_sock);
|
||||
safe_close_portable(m_msgsock);
|
||||
safe_close_portable(s_sock);
|
||||
safe_close_portable(s_msgsock);
|
||||
|
||||
if (m_thread.joinable())
|
||||
m_thread.join();
|
||||
if (s_thread.joinable())
|
||||
s_thread.join();
|
||||
}
|
||||
|
||||
PINEServer::IPCBuffer PINEServer::ParseCommand(std::span<u8> buf, std::vector<u8>& ret_buffer, u32 buf_size)
|
||||
|
||||
@@ -987,6 +987,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapBitBoolEx(SaveDepth, "SaveDepth");
|
||||
SettingsWrapBitBoolEx(SaveAlpha, "SaveAlpha");
|
||||
SettingsWrapBitBoolEx(SaveInfo, "SaveInfo");
|
||||
SettingsWrapBitBoolEx(SaveTransferImages, "SaveTransferImages");
|
||||
SettingsWrapBitBool(DumpReplaceableTextures);
|
||||
SettingsWrapBitBool(DumpReplaceableMipmaps);
|
||||
SettingsWrapBitBool(DumpTexturesWithFMVActive);
|
||||
|
||||
@@ -81,7 +81,7 @@ static const SettingInfo s_settings[] = {
|
||||
};
|
||||
|
||||
const Pad::ControllerInfo PadDualshock2::ControllerInfo = {Pad::ControllerType::DualShock2, "DualShock2",
|
||||
TRANSLATE_NOOP("Pad", "DualShock 2"), ICON_PF_GAMEPAD_ALT, s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors};
|
||||
TRANSLATE_NOOP("Pad", "DualShock 2"), ICON_PF_DUALSHOCK2, s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors};
|
||||
|
||||
void PadDualshock2::ConfigLog()
|
||||
{
|
||||
|
||||
@@ -45,7 +45,7 @@ static const SettingInfo s_settings[] = {
|
||||
};
|
||||
|
||||
const Pad::ControllerInfo PadJogcon::ControllerInfo = {Pad::ControllerType::Jogcon, "Jogcon",
|
||||
TRANSLATE_NOOP("Pad", "Jogcon"), ICON_PF_GAMEPAD_ALT, s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors};
|
||||
TRANSLATE_NOOP("Pad", "Jogcon"), ICON_PF_JOGCON, s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors};
|
||||
|
||||
void PadJogcon::ConfigLog()
|
||||
{
|
||||
|
||||
@@ -42,7 +42,7 @@ static const SettingInfo s_settings[] = {
|
||||
};
|
||||
|
||||
const Pad::ControllerInfo PadNegcon::ControllerInfo = {Pad::ControllerType::Negcon, "NeGcon",
|
||||
TRANSLATE_NOOP("Pad", "NeGcon"), ICON_PF_GAMEPAD_ALT, s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors};
|
||||
TRANSLATE_NOOP("Pad", "NeGcon"), ICON_PF_NEGCON, s_bindings, s_settings, Pad::VibrationCapabilities::LargeSmallMotors};
|
||||
|
||||
void PadNegcon::ConfigLog()
|
||||
{
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
||||
/// shaders change, to invalidate the cache.
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 72;
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 73;
|
||||
|
||||
@@ -561,6 +561,15 @@ const char* USB::GetDeviceName(const std::string_view device)
|
||||
return dev ? dev->Name() : TRANSLATE_NOOP("USB", "Not Connected");
|
||||
}
|
||||
|
||||
const char* USB::GetDeviceIconName(u32 port)
|
||||
{
|
||||
pxAssert(port < NUM_PORTS);
|
||||
if (s_usb_device_proxy[port])
|
||||
return s_usb_device_proxy[port]->IconName();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* USB::GetDeviceSubtypeName(const std::string_view device, u32 subtype)
|
||||
{
|
||||
const DeviceProxy* dev = RegisterDevice::instance().Device(device);
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace USB
|
||||
|
||||
std::vector<std::pair<const char*, const char*>> GetDeviceTypes();
|
||||
const char* GetDeviceName(const std::string_view device);
|
||||
const char* GetDeviceIconName(u32 port);
|
||||
const char* GetDeviceSubtypeName(const std::string_view device, u32 subtype);
|
||||
std::span<const char*> GetDeviceSubtypes(const std::string_view device);
|
||||
std::span<const InputBindingInfo> GetDeviceBindings(const std::string_view device, u32 subtype);
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
|
||||
virtual const char* Name() const = 0;
|
||||
virtual const char* TypeName() const = 0;
|
||||
virtual const char* IconName() const = 0;
|
||||
virtual std::span<const char*> SubTypes() const;
|
||||
virtual std::span<const InputBindingInfo> Bindings(u32 subtype) const;
|
||||
virtual std::span<const SettingInfo> Settings(u32 subtype) const;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "Host.h"
|
||||
#include "IconsPromptFont.h"
|
||||
#include "videodev.h"
|
||||
#include "usb-eyetoy-webcam.h"
|
||||
#include "ov519.h"
|
||||
@@ -491,6 +492,11 @@ namespace usb_eyetoy
|
||||
return "webcam";
|
||||
}
|
||||
|
||||
const char* EyeToyWebCamDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_EYETOY_WEBCAM;
|
||||
}
|
||||
|
||||
bool EyeToyWebCamDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
EYETOYState* s = USB_CONTAINER_OF(dev, EYETOYState, dev);
|
||||
|
||||
@@ -461,6 +461,7 @@ namespace usb_eyetoy
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() 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;
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "USB/qemu-usb/desc.h"
|
||||
#include "USB/usb-hid/usb-hid.h"
|
||||
|
||||
#include "IconsPromptFont.h"
|
||||
#include "common/Console.h"
|
||||
|
||||
namespace usb_hid
|
||||
@@ -826,6 +827,11 @@ namespace usb_hid
|
||||
return "hidkbd";
|
||||
}
|
||||
|
||||
const char* HIDKbdDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_KEYBOARD_ALT;
|
||||
}
|
||||
|
||||
std::span<const InputBindingInfo> HIDKbdDevice::Bindings(u32 subtype) const
|
||||
{
|
||||
static constexpr const InputBindingInfo info[] = {
|
||||
@@ -899,6 +905,11 @@ namespace usb_hid
|
||||
return "hidmouse";
|
||||
}
|
||||
|
||||
const char* HIDMouseDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_MOUSE;
|
||||
}
|
||||
|
||||
bool HIDMouseDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
UsbHIDState* s = USB_CONTAINER_OF(dev, UsbHIDState, dev);
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace usb_hid
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() const override;
|
||||
std::span<const InputBindingInfo> Bindings(u32 subtype) const override;
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
void SetBindingValue(USBDevice* dev, u32 bind, float value) const override;
|
||||
@@ -25,6 +26,7 @@ namespace usb_hid
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() const override;
|
||||
std::span<const InputBindingInfo> Bindings(u32 subtype) const override;
|
||||
float GetBindingValue(const USBDevice* dev, u32 bind) const override;
|
||||
void SetBindingValue(USBDevice* dev, u32 bind, float value) const override;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "GS/GS.h"
|
||||
#include "Host.h"
|
||||
#include "IconsPromptFont.h"
|
||||
#include "ImGui/ImGuiManager.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "StateWrapper.h"
|
||||
@@ -444,6 +445,11 @@ namespace usb_lightgun
|
||||
return "guncon2";
|
||||
}
|
||||
|
||||
const char* GunCon2Device::IconName() const
|
||||
{
|
||||
return ICON_PF_GUNCON2;
|
||||
}
|
||||
|
||||
USBDevice* GunCon2Device::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const
|
||||
{
|
||||
GunCon2State* s = new GunCon2State(port);
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace usb_lightgun
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() const override;
|
||||
bool Freeze(USBDevice* dev, StateWrapper& sw) const override;
|
||||
void UpdateSettings(USBDevice* dev, SettingsInterface& si) const override;
|
||||
float GetBindingValue(const USBDevice* dev, u32 bind_index) const override;
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "USB/USB.h"
|
||||
#include "StateWrapper.h"
|
||||
|
||||
#include "IconsPromptFont.h"
|
||||
#include "common/Console.h"
|
||||
|
||||
#define BUFFER_FRAMES 200
|
||||
@@ -962,6 +963,11 @@ namespace usb_mic
|
||||
return TRANSLATE_NOOP("USB", "Logitech USB Headset");
|
||||
}
|
||||
|
||||
const char* HeadsetDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_HEADSET;
|
||||
}
|
||||
|
||||
bool HeadsetDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
HeadsetState* s = USB_CONTAINER_OF(dev, HeadsetState, dev);
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace usb_mic
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
const char* TypeName() const override;
|
||||
const char* Name() const override;
|
||||
const char* IconName() const override;
|
||||
|
||||
bool Freeze(USBDevice* dev, StateWrapper& sw) const override;
|
||||
void UpdateSettings(USBDevice* dev, SettingsInterface& si) const override;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
// Most stuff is based on Qemu 1.7 USB soundcard passthrough code.
|
||||
|
||||
#include "IconsPromptFont.h"
|
||||
#include "USB/qemu-usb/qusb.h"
|
||||
#include "USB/qemu-usb/desc.h"
|
||||
#include "USB/qemu-usb/USBinternal.h"
|
||||
@@ -1204,6 +1205,11 @@ namespace usb_mic
|
||||
return "singstar";
|
||||
}
|
||||
|
||||
const char* MicrophoneDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_SINGSTAR_MIC;
|
||||
}
|
||||
|
||||
bool MicrophoneDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
SINGSTARMICState* s = USB_CONTAINER_OF(dev, SINGSTARMICState, dev);
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace usb_mic
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() 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;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "IconsFontAwesome6.h"
|
||||
#include "USB/qemu-usb/qusb.h"
|
||||
#include "USB/qemu-usb/desc.h"
|
||||
#include "USB/qemu-usb/USBinternal.h"
|
||||
@@ -1189,6 +1190,11 @@ namespace usb_msd
|
||||
return TRANSLATE_NOOP("USB", "Mass Storage Device");
|
||||
}
|
||||
|
||||
const char* MsdDevice::IconName() const
|
||||
{
|
||||
return ICON_FA_HARD_DRIVE;
|
||||
}
|
||||
|
||||
bool MsdDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
MSDState* s = USB_CONTAINER_OF(dev, MSDState, dev);
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace usb_msd
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
const char* TypeName() const override;
|
||||
const char* Name() const override;
|
||||
const char* IconName() 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;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "Host.h"
|
||||
#include "IconsPromptFont.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "StateWrapper.h"
|
||||
#include "USB/USB.h"
|
||||
@@ -205,6 +206,11 @@ namespace usb_pad
|
||||
return "BuzzDevice";
|
||||
}
|
||||
|
||||
const char* BuzzDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_BUZZ_CONTROLLER;
|
||||
}
|
||||
|
||||
bool BuzzDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace usb_pad
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() const override;
|
||||
bool Freeze(USBDevice* dev, StateWrapper& sw) const override;
|
||||
float GetBindingValue(const USBDevice* dev, u32 bind_index) const override;
|
||||
void SetBindingValue(USBDevice* dev, u32 bind_index, float value) const override;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "Host.h"
|
||||
#include "IconsPromptFont.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "StateWrapper.h"
|
||||
#include "USB/USB.h"
|
||||
@@ -282,6 +283,11 @@ namespace usb_pad
|
||||
return "Gametrak";
|
||||
}
|
||||
|
||||
const char* GametrakDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_GAMETRAK_DEVICE;
|
||||
}
|
||||
|
||||
USBDevice* GametrakDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const
|
||||
{
|
||||
GametrakState* s = new GametrakState(port);
|
||||
|
||||
@@ -74,6 +74,7 @@ namespace usb_pad
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() 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;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "usb-pad.h"
|
||||
#include "IconsFontAwesome6.h"
|
||||
#include "IconsPromptFont.h"
|
||||
#include "USB/qemu-usb/USBinternal.h"
|
||||
#include "USB/usb-pad/usb-pad-sdl-ff.h"
|
||||
#include "USB/USB.h"
|
||||
@@ -814,6 +816,11 @@ namespace usb_pad
|
||||
return "Pad";
|
||||
}
|
||||
|
||||
const char* PadDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_STEERING_WHEEL_ALT;
|
||||
}
|
||||
|
||||
bool PadDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
PadState* s = USB_CONTAINER_OF(dev, PadState, dev);
|
||||
@@ -887,6 +894,11 @@ namespace usb_pad
|
||||
return "RBDrumKit";
|
||||
}
|
||||
|
||||
const char* RBDrumKitDevice::IconName() const
|
||||
{
|
||||
return ICON_FA_DRUM;
|
||||
}
|
||||
|
||||
USBDevice* RBDrumKitDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const
|
||||
{
|
||||
PadState* s = new PadState(port, WT_ROCKBAND1_DRUMKIT);
|
||||
@@ -949,6 +961,11 @@ namespace usb_pad
|
||||
return "Keyboardmania";
|
||||
}
|
||||
|
||||
const char* KeyboardmaniaDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_KEYBOARDMANIA;
|
||||
}
|
||||
|
||||
std::span<const char*> KeyboardmaniaDevice::SubTypes() const
|
||||
{
|
||||
return {};
|
||||
|
||||
@@ -72,6 +72,7 @@ namespace usb_pad
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() const override;
|
||||
bool Freeze(USBDevice* dev, StateWrapper& sw) const override;
|
||||
void UpdateSettings(USBDevice* dev, SettingsInterface& si) const override;
|
||||
float GetBindingValue(const USBDevice* dev, u32 bind_index) const override;
|
||||
@@ -88,6 +89,7 @@ namespace usb_pad
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() 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;
|
||||
@@ -99,6 +101,7 @@ namespace usb_pad
|
||||
public:
|
||||
const char* Name() const;
|
||||
const char* TypeName() const;
|
||||
const char* IconName() const;
|
||||
std::span<const char*> SubTypes() const;
|
||||
std::span<const InputBindingInfo> Bindings(u32 subtype) const;
|
||||
std::span<const SettingInfo> Settings(u32 subtype) const;
|
||||
@@ -111,6 +114,7 @@ namespace usb_pad
|
||||
public:
|
||||
const char* Name() const;
|
||||
const char* TypeName() const;
|
||||
const char* IconName() const;
|
||||
std::span<const char*> SubTypes() const;
|
||||
std::span<const InputBindingInfo> Bindings(u32 subtype) const;
|
||||
std::span<const SettingInfo> Settings(u32 subtype) const;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "Host.h"
|
||||
#include "IconsPromptFont.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "StateWrapper.h"
|
||||
#include "USB/USB.h"
|
||||
@@ -285,6 +286,11 @@ namespace usb_pad
|
||||
return "RealPlay";
|
||||
}
|
||||
|
||||
const char* RealPlayDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_REALPLAY_BOWLING;
|
||||
}
|
||||
|
||||
USBDevice* RealPlayDevice::CreateDevice(SettingsInterface& si, u32 port, u32 type) const
|
||||
{
|
||||
RealPlayState* s = new RealPlayState(port, type);
|
||||
|
||||
@@ -80,6 +80,7 @@ namespace usb_pad
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() 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;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "Host.h"
|
||||
#include "IconsPromptFont.h"
|
||||
#include "USB/usb-pad/usb-pad.h"
|
||||
#include "USB/qemu-usb/desc.h"
|
||||
#include "USB/usb-mic/usb-mic.h"
|
||||
@@ -341,6 +342,11 @@ namespace usb_pad
|
||||
return "seamic";
|
||||
}
|
||||
|
||||
const char* SeamicDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_SEGA_SEAMIC;
|
||||
}
|
||||
|
||||
std::span<const char*> SeamicDevice::SubTypes() const
|
||||
{
|
||||
return {};
|
||||
|
||||
@@ -26,6 +26,11 @@ namespace usb_pad
|
||||
return "TrainController";
|
||||
}
|
||||
|
||||
const char* TrainDevice::IconName() const
|
||||
{
|
||||
return ICON_FA_TRAIN;
|
||||
}
|
||||
|
||||
std::span<const char*> TrainDevice::SubTypes() const
|
||||
{
|
||||
static const char* subtypes[] = {
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace usb_pad
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() const override;
|
||||
std::span<const char*> SubTypes() const override;
|
||||
void UpdateSettings(USBDevice* dev, SettingsInterface& si) const override;
|
||||
std::span<const SettingInfo> Settings(u32 subtype) const override;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "Host.h"
|
||||
#include "IconsPromptFont.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "StateWrapper.h"
|
||||
#include "USB/USB.h"
|
||||
@@ -129,6 +130,11 @@ namespace usb_pad
|
||||
return "TranceVibrator";
|
||||
}
|
||||
|
||||
const char* TranceVibratorDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_REZ_VIBRATOR;
|
||||
}
|
||||
|
||||
bool TranceVibratorDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace usb_pad
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() const override;
|
||||
bool Freeze(USBDevice* dev, StateWrapper& sw) const override;
|
||||
float GetBindingValue(const USBDevice* dev, u32 bind_index) const override;
|
||||
void SetBindingValue(USBDevice* dev, u32 bind_index, float value) const override;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "Host.h"
|
||||
#include "IconsFontAwesome6.h"
|
||||
#include "IconsPromptFont.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "StateWrapper.h"
|
||||
#include "USB/USB.h"
|
||||
@@ -235,6 +237,11 @@ namespace usb_pad
|
||||
return "DJTurntable";
|
||||
}
|
||||
|
||||
const char* DJTurntableDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_DJ_HERO_TURNTABLE;
|
||||
}
|
||||
|
||||
USBDevice* DJTurntableDevice::CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const
|
||||
{
|
||||
TurntableState* s = new TurntableState(port);
|
||||
|
||||
@@ -86,6 +86,7 @@ namespace usb_pad
|
||||
public:
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() 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;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-FileCopyrightText: 2002-2025 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "IconsPromptFont.h"
|
||||
#include "USB/qemu-usb/qusb.h"
|
||||
#include "USB/qemu-usb/USBinternal.h"
|
||||
#include "USB/usb-printer/usb-printer.h"
|
||||
@@ -331,6 +332,11 @@ namespace usb_printer
|
||||
return "printer";
|
||||
}
|
||||
|
||||
const char* PrinterDevice::IconName() const
|
||||
{
|
||||
return ICON_PF_PRINTER;
|
||||
}
|
||||
|
||||
bool PrinterDevice::Freeze(USBDevice* dev, StateWrapper& sw) const
|
||||
{
|
||||
PrinterState* s = USB_CONTAINER_OF(dev, PrinterState, dev);
|
||||
|
||||
@@ -114,6 +114,7 @@ namespace usb_printer
|
||||
USBDevice* CreateDevice(SettingsInterface& si, u32 port, u32 subtype) const override;
|
||||
const char* Name() const override;
|
||||
const char* TypeName() const override;
|
||||
const char* IconName() const override;
|
||||
|
||||
bool Freeze(USBDevice* dev, StateWrapper& sw) const override;
|
||||
std::span<const char*> SubTypes() const override;
|
||||
|
||||
@@ -2251,8 +2251,15 @@ bool VMManager::ChangeDisc(CDVD_SourceType source, std::string path)
|
||||
{
|
||||
if (source == CDVD_SourceType::NoDisc)
|
||||
{
|
||||
Host::AddIconOSDMessage("ChangeDisc", ICON_FA_COMPACT_DISC, TRANSLATE_SV("VMManager", "Disc removed."),
|
||||
Host::OSD_INFO_DURATION);
|
||||
if (old_path.empty())
|
||||
Host::AddIconOSDMessage("ChangeDisc", ICON_FA_COMPACT_DISC, TRANSLATE_SV("VMManager", "No disc to remove."),
|
||||
Host::OSD_INFO_DURATION);
|
||||
else
|
||||
{
|
||||
Host::AddIconOSDMessage("ChangeDisc", ICON_FA_COMPACT_DISC, TRANSLATE_SV("VMManager", "Disc removed."),
|
||||
Host::OSD_INFO_DURATION);
|
||||
Console.WriteLnFmt("Removed disc: '{}'", old_path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user