Compare commits

...

13 Commits

Author SHA1 Message Date
lightningterror
3b0a83c1ab Qt/Fullscreenui/GS: Add Automatic blending option.
Automatic blending option will behave like basic level with the exception of gamedb if it forces a blend level then it will take that in to consideration, any other option will override the gamedb.
2025-09-02 14:47:44 +02:00
PCSX2 Bot
9864cd97de [ci skip] PAD: Update to latest controller database. 2025-09-02 04:16:00 +02:00
TheTechnician27
6d7deb57a0 CDVD: Fix block index past EoF error message 2025-09-01 08:07:58 +02:00
PCSX2 Bot
21876ff590 [ci skip] Qt: Update Base Translation. 2025-09-01 02:04:57 +02:00
chaoticgd
c543c05968 Debugger: Save symbol tree display options to layout files 2025-08-31 17:31:37 -04:00
chaoticgd
a5537da4df Debugger: Add option to show leading zeroes in the symbol trees 2025-08-31 17:31:37 -04:00
chaoticgd
edaddeecc4 Debugger: Add option to change the base of integers in the symbol trees 2025-08-31 17:31:37 -04:00
chaoticgd
6b30a199da Qt: Use the correct case for the name of the custom.qss file 2025-08-31 17:29:43 -04:00
lightningterror
23c637e3e5 GS/DX11: Post dx11 multidraw fb copy cleanup.
Don't clear stencil for stencil date.
We don't want to do this unless we always sample with stencil date like vk/gl.
Only swap primid date with barrier date if there is overlap, stencil date might send the wrong alpha on a previous draw which could be wrong when we use the alpha to sample from.
2025-08-31 02:51:36 +02:00
lightningterror
313b0fe3b5 GS/DX: Fully implement tex is fb on dx11, extend partially on dx12.
Always use tex is fb for dx11.

Partial support for dx12 if prims don't overlap.

Previously it didn't work on dx because we used input.t which is interpolated, instead of absolute cords when fb sampling.
2025-08-31 02:16:13 +02:00
PCSX2 Bot
90818c3627 [ci skip] Qt: Update Base Translation. 2025-08-30 20:03:21 -04:00
JordanTheToaster
89877aba58 Deps: Update Windows and Linux to Qt 6.9.2 2025-08-30 20:02:37 -04:00
Ty
80cb381b35 EE Cache: Use GSVector instead of intrinsics 2025-08-30 20:02:19 -04:00
27 changed files with 549 additions and 291 deletions

View File

@@ -21,7 +21,7 @@ LIBJPEGTURBO=3.1.1
LIBPNG=1.6.50
LIBWEBP=1.6.0
SDL=SDL3-3.2.20
QT=6.9.1
QT=6.9.2
LZ4=1.10.0
ZSTD=1.5.7
KDDOCKWIDGETS=2.2.3
@@ -46,12 +46,12 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67 $SDL.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
40caedbf83cc9a1959610830563565889878bc95f115868bbf545d1914acf28e qtbase-everywhere-src-$QT.tar.xz
ebe9f238daaf9bb752c7233edadf4af33fc4fa30d914936812b6410d3af1577c qtimageformats-everywhere-src-$QT.tar.xz
2dfc5de5fd891ff2afd9861e519bf1a26e6deb729b3133f68a28ba763c9abbd5 qtsvg-everywhere-src-$QT.tar.xz
90c4a562f4ccfd043fd99f34c600853e0b5ba9babc6ec616c0f306f2ce3f4b4c qttools-everywhere-src-$QT.tar.xz
9761a1a555f447cdeba79fdec6a705dee8a7882ac10c12e85f49467ddd01a741 qttranslations-everywhere-src-$QT.tar.xz
7d21ea0e687180ebb19b9a1f86ae9cfa7a25b4f02d5db05ec834164409932e3e qtwayland-everywhere-src-$QT.tar.xz
44be9c9ecfe04129c4dea0a7e1b36ad476c9cc07c292016ac98e7b41514f2440 qtbase-everywhere-src-$QT.tar.xz
8a023f7e2f57dedc02e2ab10c975f7cb3cccac9b8f0823c12fd6824834549139 qtimageformats-everywhere-src-$QT.tar.xz
d984cab8f26334aa1c15e5b8f0cd9f1b7c0c1289fe0b68c1c84ab469b75605a5 qtsvg-everywhere-src-$QT.tar.xz
d8b7f7e8e970cc0b975205fd6d5832ea917ef3e751df69b97439c1cddd67a489 qttools-everywhere-src-$QT.tar.xz
c73bb6281ed365c0f954f4b1b6e1b13e1b3fefd94854f46fcd9a412f641f7ed6 qttranslations-everywhere-src-$QT.tar.xz
cad79806565568f12f9983fed69219416abcee9d5deef4abdfcf94aa2eef7781 qtwayland-everywhere-src-$QT.tar.xz
a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADERC.tar.gz
9427deccbdf4bde6a269938df38c6bd75247493786a310d8d733a2c82065ef47 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz

View File

@@ -47,7 +47,7 @@ set HARFBUZZ=11.2.0
set LIBJPEGTURBO=3.1.1
set LIBPNG=1650
set SDL=SDL3-3.2.20
set QT=6.9.1
set QT=6.9.2
set QTMINOR=6.9
set LZ4=1.10.0
set WEBP=1.6.0
@@ -69,11 +69,11 @@ call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lp
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 "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" efa6d8ef9f7ae0fd9f7d280fbff574d71882b60a357ae639e516dc173cf26986 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 8439d3394bc380fd17a920ee96df1d2272bf8d3490871d948ef750f95e0ded06 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" a8f90c768b54e28d61e02c1229b74a2b834e9852af523e5c70bcd2ae4c34a772 || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 38db91c4a8044c395eac89e325ecc25edbda12606fc28812491ef5e5b6b53dd6 || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" fd2e776164751fb486495efeee336d26d85fe1ca1f6a7b9eb6aafca2e3d333aa || 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
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" d2f4c7a4a12630e879702353f944f96a5d8e764771b5a5f04163334ad61b39db || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 3e168d1b081ee3a2175fe1bd97ad03bb40fe7ce38a37e99923a19f0e7ec4d81c || goto error
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error

View File

@@ -45,7 +45,7 @@ set HARFBUZZ=11.2.0
set LIBJPEGTURBO=3.1.1
set LIBPNG=1650
set SDL=SDL3-3.2.20
set QT=6.9.1
set QT=6.9.2
set QTMINOR=6.9
set LZ4=1.10.0
set WEBP=1.6.0
@@ -67,11 +67,11 @@ call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lp
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 "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" efa6d8ef9f7ae0fd9f7d280fbff574d71882b60a357ae639e516dc173cf26986 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 8439d3394bc380fd17a920ee96df1d2272bf8d3490871d948ef750f95e0ded06 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" a8f90c768b54e28d61e02c1229b74a2b834e9852af523e5c70bcd2ae4c34a772 || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 38db91c4a8044c395eac89e325ecc25edbda12606fc28812491ef5e5b6b53dd6 || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" fd2e776164751fb486495efeee336d26d85fe1ca1f6a7b9eb6aafca2e3d333aa || 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
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" d2f4c7a4a12630e879702353f944f96a5d8e764771b5a5f04163334ad61b39db || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 3e168d1b081ee3a2175fe1bd97ad03bb40fe7ce38a37e99923a19f0e7ec4d81c || goto error
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error

View File

@@ -76,6 +76,7 @@
03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001230000000000000,8BitDo Ultimate,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,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001260000000000000,8BitDo Ultimate 2,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,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001b30000000000000,8BitDo Ultimate 2C,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,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001d30000000000000,8BitDo Ultimate 2C,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,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001530000000000000,8BitDo Ultimate C,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,

View File

@@ -173,10 +173,10 @@ cbuffer cb1
float RcpScaleFactor;
};
float4 sample_c(float2 uv, float uv_w)
float4 sample_c(float2 uv, float uv_w, int2 xy)
{
#if PS_TEX_IS_FB == 1
return RtTexture.Load(int3(int2(uv * WH.zw), 0));
return RtTexture.Load(int3(int2(xy), 0));
#elif PS_REGION_RECT == 1
return Texture.Load(int3(int2(uv), 0));
#else
@@ -315,26 +315,26 @@ float4 clamp_wrap_uv(float4 uv)
return uv;
}
float4x4 sample_4c(float4 uv, float uv_w)
float4x4 sample_4c(float4 uv, float uv_w, int2 xy)
{
float4x4 c;
c[0] = sample_c(uv.xy, uv_w);
c[1] = sample_c(uv.zy, uv_w);
c[2] = sample_c(uv.xw, uv_w);
c[3] = sample_c(uv.zw, uv_w);
c[0] = sample_c(uv.xy, uv_w, xy);
c[1] = sample_c(uv.zy, uv_w, xy);
c[2] = sample_c(uv.xw, uv_w, xy);
c[3] = sample_c(uv.zw, uv_w, xy);
return c;
}
uint4 sample_4_index(float4 uv, float uv_w)
uint4 sample_4_index(float4 uv, float uv_w, int2 xy)
{
float4 c;
c.x = sample_c(uv.xy, uv_w).a;
c.y = sample_c(uv.zy, uv_w).a;
c.z = sample_c(uv.xw, uv_w).a;
c.w = sample_c(uv.zw, uv_w).a;
c.x = sample_c(uv.xy, uv_w, xy).a;
c.y = sample_c(uv.zy, uv_w, xy).a;
c.z = sample_c(uv.xw, uv_w, xy).a;
c.w = sample_c(uv.zw, uv_w, xy).a;
// Denormalize value
uint4 i;
@@ -606,7 +606,7 @@ float4 fetch_gXbY(int2 xy)
}
}
float4 sample_color(float2 st, float uv_w)
float4 sample_color(float2 st, float uv_w, int2 xy)
{
#if PS_TCOFFSETHACK
st += TC_OffsetHack.xy;
@@ -618,7 +618,7 @@ float4 sample_color(float2 st, float uv_w)
if (PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_REGION_RECT == 0 && PS_WMS < 2 && PS_WMT < 2)
{
c[0] = sample_c(st, uv_w);
c[0] = sample_c(st, uv_w, xy);
}
else
{
@@ -642,9 +642,9 @@ float4 sample_color(float2 st, float uv_w)
uv = clamp_wrap_uv(uv);
#if PS_PAL_FMT != 0
c = sample_4p(sample_4_index(uv, uv_w));
c = sample_4p(sample_4_index(uv, uv_w, xy));
#else
c = sample_4c(uv, uv_w);
c = sample_4c(uv, uv_w, xy);
#endif
}
@@ -769,7 +769,7 @@ float4 ps_color(PS_INPUT input)
#elif PS_DEPTH_FMT > 0
float4 T = sample_depth(st_int, input.p.xy);
#else
float4 T = sample_color(st, input.t.w);
float4 T = sample_color(st, input.t.w, int2(input.p.xy));
#endif
if (PS_SHUFFLE && !PS_SHUFFLE_SAME && !PS_READ16_SRC && !(PS_PROCESS_BA == SHUFFLE_READWRITE && PS_PROCESS_RG == SHUFFLE_READWRITE))

View File

@@ -3,13 +3,14 @@
#include "SymbolTreeDelegates.h"
#include "Debugger/SymbolTree/SymbolTreeModel.h"
#include "Debugger/SymbolTree/TypeString.h"
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QMessageBox>
#include "Debugger/SymbolTree/SymbolTreeModel.h"
#include "Debugger/SymbolTree/TypeString.h"
SymbolTreeValueDelegate::SymbolTreeValueDelegate(
DebugInterface& cpu,
@@ -28,6 +29,8 @@ QWidget* SymbolTreeValueDelegate::createEditor(QWidget* parent, const QStyleOpti
if (!tree_model)
return nullptr;
const SymbolTreeDisplayOptions& display_options = tree_model->displayOptions();
SymbolTreeNode* node = tree_model->nodeFromIndex(index);
if (!node || !node->type.valid())
return nullptr;
@@ -46,9 +49,9 @@ QWidget* SymbolTreeValueDelegate::createEditor(QWidget* parent, const QStyleOpti
{
case ccc::ast::BUILTIN:
{
const ccc::ast::BuiltIn& builtIn = type.as<ccc::ast::BuiltIn>();
const ccc::ast::BuiltIn& builtin = type.as<ccc::ast::BuiltIn>();
switch (builtIn.bclass)
switch (builtin.bclass)
{
case ccc::ast::BuiltInClass::UNSIGNED_8:
case ccc::ast::BuiltInClass::UNQUALIFIED_8:
@@ -56,8 +59,9 @@ QWidget* SymbolTreeValueDelegate::createEditor(QWidget* parent, const QStyleOpti
case ccc::ast::BuiltInClass::UNSIGNED_32:
case ccc::ast::BuiltInClass::UNSIGNED_64:
{
QLineEdit* editor = new QLineEdit(parent);
editor->setText(QString::number(value.toULongLong()));
SymbolTreeIntegerLineEdit* editor = new SymbolTreeIntegerLineEdit(
display_options, ccc::ast::builtin_class_size(builtin.bclass) * 8, parent);
editor->setUnsignedValue(value.toULongLong());
result = editor;
break;
@@ -67,8 +71,9 @@ QWidget* SymbolTreeValueDelegate::createEditor(QWidget* parent, const QStyleOpti
case ccc::ast::BuiltInClass::SIGNED_32:
case ccc::ast::BuiltInClass::SIGNED_64:
{
QLineEdit* editor = new QLineEdit(parent);
editor->setText(QString::number(value.toLongLong()));
SymbolTreeIntegerLineEdit* editor = new SymbolTreeIntegerLineEdit(
display_options, ccc::ast::builtin_class_size(builtin.bclass) * 8, parent);
editor->setSignedValue(value.toLongLong());
result = editor;
break;
@@ -168,9 +173,9 @@ void SymbolTreeValueDelegate::setModelData(QWidget* editor, QAbstractItemModel*
{
case ccc::ast::BUILTIN:
{
const ccc::ast::BuiltIn& builtIn = type.as<ccc::ast::BuiltIn>();
const ccc::ast::BuiltIn& builtin = type.as<ccc::ast::BuiltIn>();
switch (builtIn.bclass)
switch (builtin.bclass)
{
case ccc::ast::BuiltInClass::UNSIGNED_8:
case ccc::ast::BuiltInClass::UNQUALIFIED_8:
@@ -178,13 +183,12 @@ void SymbolTreeValueDelegate::setModelData(QWidget* editor, QAbstractItemModel*
case ccc::ast::BuiltInClass::UNSIGNED_32:
case ccc::ast::BuiltInClass::UNSIGNED_64:
{
QLineEdit* line_edit = qobject_cast<QLineEdit*>(editor);
auto line_edit = qobject_cast<SymbolTreeIntegerLineEdit*>(editor);
Q_ASSERT(line_edit);
bool ok;
qulonglong i = line_edit->text().toULongLong(&ok);
if (ok)
value = i;
std::optional<u64> i = line_edit->unsignedValue();
if (i.has_value())
value = static_cast<quint64>(*i);
break;
}
@@ -193,13 +197,12 @@ void SymbolTreeValueDelegate::setModelData(QWidget* editor, QAbstractItemModel*
case ccc::ast::BuiltInClass::SIGNED_32:
case ccc::ast::BuiltInClass::SIGNED_64:
{
QLineEdit* line_edit = qobject_cast<QLineEdit*>(editor);
auto line_edit = qobject_cast<SymbolTreeIntegerLineEdit*>(editor);
Q_ASSERT(line_edit);
bool ok;
qlonglong i = line_edit->text().toLongLong(&ok);
if (ok)
value = i;
std::optional<s64> i = line_edit->signedValue();
if (i.has_value())
value = static_cast<qint64>(*i);
break;
}
@@ -481,3 +484,33 @@ void SymbolTreeTypeDelegate::setModelData(QWidget* editor, QAbstractItemModel* m
else
QMessageBox::warning(editor, tr("Cannot Change Type"), error_message);
}
// *****************************************************************************
SymbolTreeIntegerLineEdit::SymbolTreeIntegerLineEdit(
SymbolTreeDisplayOptions display_options, s32 size_bits, QWidget* parent)
: QLineEdit(parent)
, m_display_options(display_options)
, m_size_bits(size_bits)
{
}
std::optional<u64> SymbolTreeIntegerLineEdit::unsignedValue()
{
return m_display_options.stringToUnsignedInteger(text());
}
void SymbolTreeIntegerLineEdit::setUnsignedValue(u64 value)
{
setText(m_display_options.unsignedIntegerToString(value, m_size_bits));
}
std::optional<s64> SymbolTreeIntegerLineEdit::signedValue()
{
return m_display_options.stringToSignedInteger(text());
}
void SymbolTreeIntegerLineEdit::setSignedValue(s64 value)
{
setText(m_display_options.signedIntegerToString(value, m_size_bits));
}

View File

@@ -3,10 +3,12 @@
#pragma once
#include <QtWidgets/QStyledItemDelegate>
#include "Debugger/SymbolTree/SymbolTreeNode.h"
#include "DebugTools/DebugInterface.h"
#include "DebugTools/SymbolGuardian.h"
#include <QtWidgets/QStyledItemDelegate>
#include <QtWidgets/QLineEdit>
class SymbolTreeValueDelegate : public QStyledItemDelegate
{
@@ -21,7 +23,7 @@ public:
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
protected:
private:
// These make it so the values inputted are written back to memory
// immediately when the widgets are interacted with rather than when they
// are deselected.
@@ -45,7 +47,7 @@ public:
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
protected:
private:
DebugInterface& m_cpu;
u32 m_alignment;
};
@@ -63,6 +65,24 @@ public:
void setEditorData(QWidget* editor, const QModelIndex& index) const override;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override;
protected:
private:
DebugInterface& m_cpu;
};
class SymbolTreeIntegerLineEdit : public QLineEdit
{
Q_OBJECT
public:
SymbolTreeIntegerLineEdit(SymbolTreeDisplayOptions display_options, s32 size_bits, QWidget* parent);
std::optional<u64> unsignedValue();
void setUnsignedValue(u64 value);
std::optional<s64> signedValue();
void setSignedValue(s64 value);
private:
SymbolTreeDisplayOptions m_display_options;
s32 m_size_bits;
};

View File

@@ -183,10 +183,10 @@ bool SymbolTreeModel::setData(const QModelIndex& index, const QVariant& value, i
switch (role)
{
case EDIT_ROLE:
data_changed = node->writeToVM(value, m_cpu, database);
data_changed = node->writeToVM(value, m_cpu, database, m_display_options);
break;
case UPDATE_FROM_MEMORY_ROLE:
data_changed = node->readFromVM(m_cpu, database);
data_changed = node->readFromVM(m_cpu, database, m_display_options);
break;
}
});
@@ -216,7 +216,13 @@ void SymbolTreeModel::fetchMore(const QModelIndex& parent)
return;
children = populateChildren(
parent_node->name, parent_node->location, *logical_parent_type, parent_node->type, m_cpu, database);
parent_node->name,
parent_node->location,
*logical_parent_type,
parent_node->type,
m_cpu,
database,
m_display_options);
});
bool insert_children = !children.empty();
@@ -403,7 +409,8 @@ std::vector<std::unique_ptr<SymbolTreeNode>> SymbolTreeModel::populateChildren(
const ccc::ast::Node& logical_type,
ccc::NodeHandle parent_handle,
DebugInterface& cpu,
const ccc::SymbolDatabase& database)
const ccc::SymbolDatabase& database,
const SymbolTreeDisplayOptions& display_options)
{
auto [physical_type, symbol] = logical_type.physical_type(database);
@@ -485,7 +492,7 @@ std::vector<std::unique_ptr<SymbolTreeNode>> SymbolTreeModel::populateChildren(
}
for (std::unique_ptr<SymbolTreeNode>& child : children)
child->readFromVM(cpu, database);
child->readFromVM(cpu, database, display_options);
return children;
}

View File

@@ -65,6 +65,9 @@ public:
std::optional<QString> changeTypeTemporarily(QModelIndex index, std::string_view type_string);
std::optional<QString> typeFromModelIndexToString(QModelIndex index);
const SymbolTreeDisplayOptions& displayOptions() const { return m_display_options; }
void setDisplayOptions(const SymbolTreeDisplayOptions& options) { m_display_options = options; }
protected:
static std::vector<std::unique_ptr<SymbolTreeNode>> populateChildren(
const QString& name,
@@ -72,11 +75,13 @@ protected:
const ccc::ast::Node& logical_type,
ccc::NodeHandle parent_handle,
DebugInterface& cpu,
const ccc::SymbolDatabase& database);
const ccc::SymbolDatabase& database,
const SymbolTreeDisplayOptions& display_options);
static bool nodeHasChildren(const ccc::ast::Node& logical_type, const ccc::SymbolDatabase& database);
std::unique_ptr<SymbolTreeNode> m_root;
QString m_filter;
DebugInterface& m_cpu;
SymbolTreeDisplayOptions m_display_options;
};

View File

@@ -20,7 +20,10 @@ std::optional<bool> SymbolTreeNode::liveness()
return m_liveness;
}
bool SymbolTreeNode::readFromVM(DebugInterface& cpu, const ccc::SymbolDatabase& database)
bool SymbolTreeNode::readFromVM(
DebugInterface& cpu,
const ccc::SymbolDatabase& database,
const SymbolTreeDisplayOptions& display_options)
{
QVariant new_value;
@@ -39,14 +42,18 @@ bool SymbolTreeNode::readFromVM(DebugInterface& cpu, const ccc::SymbolDatabase&
data_changed = true;
}
data_changed |= updateDisplayString(cpu, database);
data_changed |= updateDisplayString(cpu, database, display_options);
data_changed |= updateLiveness(cpu);
data_changed |= updateMatchesMemory(cpu, database);
return data_changed;
}
bool SymbolTreeNode::writeToVM(QVariant value, DebugInterface& cpu, const ccc::SymbolDatabase& database)
bool SymbolTreeNode::writeToVM(
QVariant value,
DebugInterface& cpu,
const ccc::SymbolDatabase& database,
const SymbolTreeDisplayOptions& display_options)
{
bool data_changed = false;
@@ -63,7 +70,7 @@ bool SymbolTreeNode::writeToVM(QVariant value, DebugInterface& cpu, const ccc::S
writeValueFromVariant(m_value, physical_type, cpu);
}
data_changed |= updateDisplayString(cpu, database);
data_changed |= updateDisplayString(cpu, database, display_options);
data_changed |= updateLiveness(cpu);
return data_changed;
@@ -202,7 +209,8 @@ bool SymbolTreeNode::writeValueFromVariant(QVariant value, const ccc::ast::Node&
return true;
}
bool SymbolTreeNode::updateDisplayString(DebugInterface& cpu, const ccc::SymbolDatabase& database)
bool SymbolTreeNode::updateDisplayString(
DebugInterface& cpu, const ccc::SymbolDatabase& database, const SymbolTreeDisplayOptions& display)
{
QString result;
@@ -210,7 +218,7 @@ bool SymbolTreeNode::updateDisplayString(DebugInterface& cpu, const ccc::SymbolD
if (logical_type)
{
const ccc::ast::Node& physical_type = *logical_type->physical_type(database).first;
result = generateDisplayString(physical_type, cpu, database, 0);
result = generateDisplayString(physical_type, cpu, database, display, 0);
}
if (result.isEmpty())
@@ -219,10 +227,10 @@ bool SymbolTreeNode::updateDisplayString(DebugInterface& cpu, const ccc::SymbolD
// first 4 bytes of it as a hex dump.
u32 value = location.read32(cpu);
result = QString("%1 %2 %3 %4")
.arg(value & 0xff, 2, 16, QChar('0'))
.arg((value >> 8) & 0xff, 2, 16, QChar('0'))
.arg((value >> 16) & 0xff, 2, 16, QChar('0'))
.arg((value >> 24) & 0xff, 2, 16, QChar('0'));
.arg(value & 0xff, 2, 16, QChar('0'))
.arg((value >> 8) & 0xff, 2, 16, QChar('0'))
.arg((value >> 16) & 0xff, 2, 16, QChar('0'))
.arg((value >> 24) & 0xff, 2, 16, QChar('0'));
}
if (result == m_display_value)
@@ -234,7 +242,11 @@ bool SymbolTreeNode::updateDisplayString(DebugInterface& cpu, const ccc::SymbolD
}
QString SymbolTreeNode::generateDisplayString(
const ccc::ast::Node& physical_type, DebugInterface& cpu, const ccc::SymbolDatabase& database, s32 depth) const
const ccc::ast::Node& physical_type,
DebugInterface& cpu,
const ccc::SymbolDatabase& database,
const SymbolTreeDisplayOptions& display_options,
s32 depth) const
{
s32 max_elements_to_display = 0;
switch (depth)
@@ -270,7 +282,7 @@ QString SymbolTreeNode::generateDisplayString(
SymbolTreeNode node;
node.location = location.addOffset(i * array.element_type->size_bytes);
QString element = node.generateDisplayString(element_type, cpu, database, depth + 1);
QString element = node.generateDisplayString(element_type, cpu, database, display_options, depth + 1);
if (element.isEmpty())
element = QString("(%1)").arg(ccc::ast::node_type_to_string(element_type));
result += element;
@@ -293,28 +305,28 @@ QString SymbolTreeNode::generateDisplayString(
switch (builtIn.bclass)
{
case ccc::ast::BuiltInClass::UNSIGNED_8:
result = QString::number(location.read8(cpu));
result = display_options.unsignedIntegerToString(location.read8(cpu), 8);
break;
case ccc::ast::BuiltInClass::SIGNED_8:
result = QString::number((s8)location.read8(cpu));
result = display_options.signedIntegerToString(static_cast<s8>(location.read8(cpu)), 8);
break;
case ccc::ast::BuiltInClass::UNQUALIFIED_8:
result = QString::number(location.read8(cpu));
result = display_options.unsignedIntegerToString(location.read8(cpu), 8);
break;
case ccc::ast::BuiltInClass::BOOL_8:
result = location.read8(cpu) ? "true" : "false";
break;
case ccc::ast::BuiltInClass::UNSIGNED_16:
result = QString::number(location.read16(cpu));
result = display_options.unsignedIntegerToString(location.read16(cpu), 16);
break;
case ccc::ast::BuiltInClass::SIGNED_16:
result = QString::number((s16)location.read16(cpu));
result = display_options.signedIntegerToString(static_cast<s16>(location.read16(cpu)), 16);
break;
case ccc::ast::BuiltInClass::UNSIGNED_32:
result = QString::number(location.read32(cpu));
result = display_options.unsignedIntegerToString(location.read32(cpu), 32);
break;
case ccc::ast::BuiltInClass::SIGNED_32:
result = QString::number((s32)location.read32(cpu));
result = display_options.signedIntegerToString(static_cast<s32>(location.read32(cpu)), 32);
break;
case ccc::ast::BuiltInClass::FLOAT_32:
{
@@ -323,10 +335,10 @@ QString SymbolTreeNode::generateDisplayString(
break;
}
case ccc::ast::BuiltInClass::UNSIGNED_64:
result = QString::number(location.read64(cpu));
result = display_options.unsignedIntegerToString(location.read64(cpu), 64);
break;
case ccc::ast::BuiltInClass::SIGNED_64:
result = QString::number((s64)location.read64(cpu));
result = display_options.signedIntegerToString(static_cast<s64>(location.read64(cpu)), 64);
break;
case ccc::ast::BuiltInClass::FLOAT_64:
{
@@ -408,7 +420,7 @@ QString SymbolTreeNode::generateDisplayString(
}
else if (depth == 0)
{
QString pointee = generateDisplayString(value_type, cpu, database, depth + 1);
QString pointee = generateDisplayString(value_type, cpu, database, display_options, depth + 1);
if (!pointee.isEmpty())
result += QString(" -> %1").arg(pointee);
}
@@ -437,7 +449,7 @@ QString SymbolTreeNode::generateDisplayString(
node.location = location.addOffset(field.base_offset + field.node->offset_bytes);
const ccc::ast::Node& field_type = *field.node->physical_type(database).first;
QString field_value = node.generateDisplayString(field_type, cpu, database, depth + 1);
QString field_value = node.generateDisplayString(field_type, cpu, database, display_options, depth + 1);
if (field_value.isEmpty())
field_value = QString("(%1)").arg(ccc::ast::node_type_to_string(field_type));
@@ -709,3 +721,99 @@ void SymbolTreeNode::sortChildrenRecursively(bool sort_by_if_type_is_known)
for (std::unique_ptr<SymbolTreeNode>& child : m_children)
child->sortChildrenRecursively(sort_by_if_type_is_known);
}
// *****************************************************************************
int SymbolTreeDisplayOptions::integerBase() const
{
return m_integer_base;
}
bool SymbolTreeDisplayOptions::setIntegerBase(int base)
{
if (base == m_integer_base || (base != 2 && base != 8 && base != 10 && base != 16))
return false;
m_integer_base = base;
return true;
}
bool SymbolTreeDisplayOptions::showLeadingZeroes() const
{
return m_show_leading_zeroes;
}
bool SymbolTreeDisplayOptions::setShowLeadingZeroes(bool show)
{
if (show == m_show_leading_zeroes)
return false;
m_show_leading_zeroes = show;
return true;
}
std::optional<u64> SymbolTreeDisplayOptions::stringToUnsignedInteger(QString string) const
{
bool ok;
u64 value = string.toULongLong(&ok, m_integer_base);
if (!ok)
{
// Try parsing it as a signed integer too, just in case the user tried
// to use a minus sign.
value = static_cast<u64>(string.toLongLong(&ok, m_integer_base));
if (!ok)
return std::nullopt;
}
return value;
}
QString SymbolTreeDisplayOptions::unsignedIntegerToString(u64 value, s32 size_bits) const
{
int field_width = 0;
if (m_show_leading_zeroes)
field_width = static_cast<int>(ceilf(size_bits / log2f(m_integer_base)));
return QStringLiteral("%1").arg(value, field_width, m_integer_base, QLatin1Char('0'));
}
std::optional<s64> SymbolTreeDisplayOptions::stringToSignedInteger(QString string) const
{
bool ok;
s64 value = string.toLongLong(&ok, m_integer_base);
if (!ok)
{
// Try to parse it as an unsigned integer too to handle bases other than
// decimal (see below), and to handle the case that the user entered a
// value that was too big for a signed integer.
value = static_cast<s64>(string.toULongLong(&ok, m_integer_base));
if (!ok)
return std::nullopt;
}
return value;
}
QString SymbolTreeDisplayOptions::signedIntegerToString(s64 value, s32 size_bits) const
{
// For bases other than decimal, the user most likely just wants to view the
// underlying representation, so we want to display it as unsigned.
if (m_integer_base != 10)
{
// Truncate sign extended bits.
u64 mask = (static_cast<u64>(1) << size_bits) - 1;
return unsignedIntegerToString(static_cast<u64>(value) & mask, size_bits);
}
int field_width = 0;
if (m_show_leading_zeroes)
{
field_width = static_cast<int>(ceilf(size_bits / log2f(m_integer_base)));
// An extra character is needed for the minus sign.
if (value < 0)
field_width++;
}
return QStringLiteral("%1").arg(value, field_width, m_integer_base, QLatin1Char('0'));
}

View File

@@ -9,9 +9,10 @@
#include "SymbolTreeLocation.h"
class DebugInterface;
class SymbolTreeDisplayOptions;
// A node in a symbol tree model.
struct SymbolTreeNode
class SymbolTreeNode
{
public:
enum Tag
@@ -49,16 +50,29 @@ public:
// Read the value from the VM memory, update liveness information, and
// generate a display string. Returns true if the data changed.
bool readFromVM(DebugInterface& cpu, const ccc::SymbolDatabase& database);
bool readFromVM(
DebugInterface& cpu,
const ccc::SymbolDatabase& database,
const SymbolTreeDisplayOptions& display_options);
// Write the value back to the VM memory. Returns true on success.
bool writeToVM(QVariant value, DebugInterface& cpu, const ccc::SymbolDatabase& database);
bool writeToVM(
QVariant value,
DebugInterface& cpu,
const ccc::SymbolDatabase& database,
const SymbolTreeDisplayOptions& display_options);
QVariant readValueAsVariant(const ccc::ast::Node& physical_type, DebugInterface& cpu, const ccc::SymbolDatabase& database) const;
bool writeValueFromVariant(QVariant value, const ccc::ast::Node& physical_type, DebugInterface& cpu) const;
bool updateDisplayString(DebugInterface& cpu, const ccc::SymbolDatabase& database);
QString generateDisplayString(const ccc::ast::Node& physical_type, DebugInterface& cpu, const ccc::SymbolDatabase& database, s32 depth) const;
bool updateDisplayString(
DebugInterface& cpu, const ccc::SymbolDatabase& database, const SymbolTreeDisplayOptions& display);
QString generateDisplayString(
const ccc::ast::Node& physical_type,
DebugInterface& cpu,
const ccc::SymbolDatabase& database,
const SymbolTreeDisplayOptions& display_options,
s32 depth) const;
bool updateLiveness(DebugInterface& cpu);
@@ -80,7 +94,7 @@ public:
void sortChildrenRecursively(bool sort_by_if_type_is_known);
protected:
private:
QVariant m_value;
QString m_display_value;
std::optional<bool> m_liveness;
@@ -90,3 +104,25 @@ protected:
std::vector<std::unique_ptr<SymbolTreeNode>> m_children;
bool m_children_fetched = false;
};
// Settings that control how text in the value column is displayed, including
// for the editor widgets.
class SymbolTreeDisplayOptions
{
public:
int integerBase() const;
bool setIntegerBase(int base);
bool showLeadingZeroes() const;
bool setShowLeadingZeroes(bool show);
std::optional<u64> stringToUnsignedInteger(QString string) const;
QString unsignedIntegerToString(u64 value, s32 size_bits) const;
std::optional<s64> stringToSignedInteger(QString string) const;
QString signedIntegerToString(s64 value, s32 size_bits) const;
private:
int m_integer_base = 10;
bool m_show_leading_zeroes = false;
};

View File

@@ -7,6 +7,7 @@
#include "Debugger/SymbolTree/NewSymbolDialogs.h"
#include "Debugger/SymbolTree/SymbolTreeDelegates.h"
#include <QtGui/QActionGroup>
#include <QtGui/QClipboard>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMenu>
@@ -81,6 +82,12 @@ void SymbolTreeView::toJson(JsonValueWrapper& json)
{
json.value().AddMember("sortByIfTypeIsKnown", m_sort_by_if_type_is_known, json.allocator());
}
if (m_flags & ALLOW_TYPE_ACTIONS)
{
json.value().AddMember("integerBase", m_display_options.integerBase(), json.allocator());
json.value().AddMember("showLeadingZeroes", m_display_options.showLeadingZeroes(), json.allocator());
}
}
bool SymbolTreeView::fromJson(const JsonValueWrapper& json)
@@ -89,6 +96,7 @@ bool SymbolTreeView::fromJson(const JsonValueWrapper& json)
return false;
bool needs_reset = false;
bool needs_update = false;
auto show_size_column = json.value().FindMember("showSizeColumn");
if (show_size_column != json.value().MemberEnd() && show_size_column->value.IsBool())
@@ -131,8 +139,26 @@ bool SymbolTreeView::fromJson(const JsonValueWrapper& json)
}
}
if (m_flags & ALLOW_TYPE_ACTIONS)
{
auto integer_base = json.value().FindMember("integerBase");
if (integer_base != json.value().MemberEnd() && integer_base->value.IsInt())
needs_update |= m_display_options.setIntegerBase(integer_base->value.GetInt());
auto show_leading_zeroes = json.value().FindMember("showLeadingZeroes");
if (show_leading_zeroes != json.value().MemberEnd() && show_leading_zeroes->value.IsBool())
needs_update |= m_display_options.setShowLeadingZeroes(show_leading_zeroes->value.GetBool());
}
if (needs_reset)
{
reset();
}
else if (needs_update && m_model)
{
m_model->setDisplayOptions(m_display_options);
updateVisibleNodes(false);
}
return true;
}
@@ -221,6 +247,7 @@ void SymbolTreeView::expandGroups(QModelIndex index)
void SymbolTreeView::setupTree()
{
m_model = new SymbolTreeModel(cpu(), this);
m_model->setDisplayOptions(m_display_options);
m_ui.treeView->setModel(m_model);
auto location_delegate = new SymbolTreeLocationDelegate(cpu(), m_symbol_address_alignment, this);
@@ -556,6 +583,47 @@ void SymbolTreeView::openContextMenu(QPoint pos)
QAction* change_type_temporarily = menu->addAction(tr("Change Type Temporarily"));
change_type_temporarily->setEnabled(node_is_object);
connect(change_type_temporarily, &QAction::triggered, this, &SymbolTreeView::onChangeTypeTemporarily);
struct IntegerDisplayBase
{
int base;
QString name;
};
const std::array<IntegerDisplayBase, 4> bases = {{
{2, tr("Binary")},
{8, tr("Octal")},
{10, tr("Decimal")},
{16, tr("Hexadecimal")},
}};
QMenu* integer_base_menu = menu->addMenu(tr("Integer Base"));
QActionGroup* base_actions = new QActionGroup(integer_base_menu);
for (const auto& [base, name] : bases)
{
QAction* base_action = integer_base_menu->addAction(name);
base_action->setCheckable(true);
base_action->setChecked(m_model->displayOptions().integerBase() == base);
connect(base_action, &QAction::toggled, this, [this, base](bool checked) {
m_display_options.setIntegerBase(base);
m_model->setDisplayOptions(m_display_options);
updateVisibleNodes(false);
});
base_actions->addAction(base_action);
}
QAction* show_leading_zeroes = menu->addAction(tr("Show Leading Zeroes"));
show_leading_zeroes->setCheckable(true);
show_leading_zeroes->setChecked(m_model->displayOptions().showLeadingZeroes());
connect(show_leading_zeroes, &QAction::toggled, this, [this](bool checked) {
m_display_options.setShowLeadingZeroes(checked);
m_model->setDisplayOptions(m_display_options);
updateVisibleNodes(false);
});
}
menu->popup(m_ui.treeView->viewport()->mapToGlobal(pos));
@@ -855,8 +923,8 @@ std::vector<SymbolTreeView::SymbolWork> GlobalVariableTreeView::getSymbols(
function_name = tr("unknown function");
QString name = QString("%1 (%2)")
.arg(QString::fromStdString(local_variable.name()))
.arg(function_name);
.arg(QString::fromStdString(local_variable.name()))
.arg(function_name);
if (!testName(name, filter))
continue;

View File

@@ -8,6 +8,8 @@
#include "Debugger/DebuggerView.h"
#include "Debugger/SymbolTree/SymbolTreeModel.h"
class SymbolTreeValueDelegate;
// A symbol tree view with its associated refresh button, filter box and
// right-click menu. Supports grouping, sorting and various other settings.
class SymbolTreeView : public DebuggerView
@@ -112,6 +114,8 @@ protected:
bool m_group_by_section = false;
bool m_group_by_source_file = false;
bool m_sort_by_if_type_is_known = false;
SymbolTreeDisplayOptions m_display_options;
};
class FunctionTreeView : public SymbolTreeView

View File

@@ -116,6 +116,11 @@
</item>
<item row="5" column="1">
<widget class="QComboBox" name="blending">
<item>
<property name="text">
<string>Automatic (Default)</string>
</property>
</item>
<item>
<property name="text">
<string>Minimum</string>
@@ -123,7 +128,7 @@
</item>
<item>
<property name="text">
<string>Basic (Recommended)</string>
<string>Basic</string>
</property>
</item>
<item>

View File

@@ -121,7 +121,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_hw.dithering, "EmuCore/GS", "dithering_ps2", 2);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.mipmapping, "EmuCore/GS", "hw_mipmap", true);
SettingWidgetBinder::BindWidgetToIntSetting(
sif, m_hw.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
sif, m_hw.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Automatic), -1);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.enableHWFixes, "EmuCore/GS", "UserHacks", false);
connect(m_hw.upscaleMultiplier, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onUpscaleMultiplierChanged);

View File

@@ -44,8 +44,8 @@ const char* InterfaceSettingsWidget::THEME_NAMES[] = {
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Sapphire (Black/Blue) [Dark]"),
//: Ignore what Crowdin says in this string about "[Light]/[Dark]" being untouchable here, these are not variables in this case and must be translated.
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Emerald (Black/Green) [Dark]"),
//: "Custom.qss" must be kept as-is.
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Custom.qss [Drop in PCSX2 Folder]"),
//: "custom.qss" must be kept as-is.
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "custom.qss [Drop in PCSX2 Folder]"),
nullptr};
const char* InterfaceSettingsWidget::THEME_VALUES[] = {

View File

@@ -12779,7 +12779,7 @@ Scanning recursively takes more time, but will identify files in subdirectories.
<context>
<name>GlobalVariableTreeView</name>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="855"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="923"/>
<source>unknown function</source>
<translation type="unfinished"></translation>
</message>
@@ -16213,148 +16213,148 @@ Swap chain: see Microsoft&apos;s Terminology Portal.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="233"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="238"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="243"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="248"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="253"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="258"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="266"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="234"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="239"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="244"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="249"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="254"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="259"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="267"/>
<source>Save States</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="234"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="235"/>
<source>Select Previous Save Slot</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="239"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="240"/>
<source>Select Next Save Slot</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="244"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="245"/>
<source>Save State To Selected Slot</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="249"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="250"/>
<source>Load State From Selected Slot</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="254"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="255"/>
<source>Load Backup State From Selected Slot</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="259"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="260"/>
<source>Save State and Select Next Slot</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="267"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="268"/>
<source>Select Next Slot and Save State</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="285"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="286"/>
<source>Save State To Slot 1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="286"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="287"/>
<source>Load State From Slot 1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="287"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="288"/>
<source>Save State To Slot 2</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="288"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="289"/>
<source>Load State From Slot 2</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="289"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="290"/>
<source>Save State To Slot 3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="290"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="291"/>
<source>Load State From Slot 3</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="291"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="292"/>
<source>Save State To Slot 4</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="292"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="293"/>
<source>Load State From Slot 4</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="293"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="294"/>
<source>Save State To Slot 5</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="294"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="295"/>
<source>Load State From Slot 5</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="295"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="296"/>
<source>Save State To Slot 6</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="296"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="297"/>
<source>Load State From Slot 6</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="297"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="298"/>
<source>Save State To Slot 7</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="298"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="299"/>
<source>Load State From Slot 7</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="299"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="300"/>
<source>Save State To Slot 8</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="300"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="301"/>
<source>Load State From Slot 8</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="301"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="302"/>
<source>Save State To Slot 9</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="302"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="303"/>
<source>Load State From Slot 9</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="303"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="304"/>
<source>Save State To Slot 10</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../../pcsx2/Hotkeys.cpp" line="304"/>
<location filename="../../pcsx2/Hotkeys.cpp" line="305"/>
<source>Load State From Slot 10</source>
<translation type="unfinished"></translation>
</message>
@@ -17000,12 +17000,6 @@ Right click to clear binding</source>
<extracomment>Ignore what Crowdin says in this string about &quot;[Light]/[Dark]&quot; being untouchable here, these are not variables in this case and must be translated.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Settings/InterfaceSettingsWidget.cpp" line="48"/>
<source>Custom.qss [Drop in PCSX2 Folder]</source>
<extracomment>&quot;Custom.qss&quot; must be kept as-is.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Settings/InterfaceSettingsWidget.cpp" line="121"/>
<location filename="../Settings/InterfaceSettingsWidget.cpp" line="150"/>
@@ -17095,6 +17089,12 @@ Right click to clear binding</source>
<source>Fusion [Light/Dark]</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Settings/InterfaceSettingsWidget.cpp" line="48"/>
<source>custom.qss [Drop in PCSX2 Folder]</source>
<extracomment>&quot;custom.qss&quot; must be kept as-is.</extracomment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Settings/InterfaceSettingsWidget.cpp" line="157"/>
<source>Pauses the emulator when a game is started.</source>
@@ -21323,32 +21323,32 @@ Scanning recursively takes more time, but will identify files in subdirectories.
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="272"/>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="278"/>
<source>Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="274"/>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="280"/>
<source>Value</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="276"/>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="282"/>
<source>Location</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="278"/>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="284"/>
<source>Size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="280"/>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="286"/>
<source>Type</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="282"/>
<location filename="../Debugger/SymbolTree/SymbolTreeModel.cpp" line="288"/>
<source>Liveness</source>
<translation type="unfinished"></translation>
</message>
@@ -21356,12 +21356,12 @@ Scanning recursively takes more time, but will identify files in subdirectories.
<context>
<name>SymbolTreeTypeDelegate</name>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeDelegates.cpp" line="464"/>
<location filename="../Debugger/SymbolTree/SymbolTreeDelegates.cpp" line="467"/>
<source>Symbol no longer exists.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeDelegates.cpp" line="482"/>
<location filename="../Debugger/SymbolTree/SymbolTreeDelegates.cpp" line="485"/>
<source>Cannot Change Type</source>
<translation type="unfinished"></translation>
</message>
@@ -21394,109 +21394,139 @@ Scanning recursively takes more time, but will identify files in subdirectories.
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="355"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="382"/>
<source>(unknown source file)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="394"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="421"/>
<source>(unknown section)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="439"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="466"/>
<source>(unknown module)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="464"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="491"/>
<source>Copy Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="469"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="496"/>
<source>Copy Mangled Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="473"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="500"/>
<source>Copy Location</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="478"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="624"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="505"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="692"/>
<source>Rename Symbol</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="498"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="525"/>
<source>Show Size Column</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="510"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="537"/>
<source>Group by Module</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="518"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="545"/>
<source>Group by Section</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="526"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="553"/>
<source>Group by Source File</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="539"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="566"/>
<source>Sort by if type is known</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="552"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="579"/>
<source>Reset Children</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="556"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="583"/>
<source>Change Type Temporarily</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="578"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="594"/>
<source>Binary</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="595"/>
<source>Octal</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="596"/>
<source>Decimal</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="597"/>
<source>Hexadecimal</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="600"/>
<source>Integer Base</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="618"/>
<source>Show Leading Zeroes</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="646"/>
<source>Confirm Deletion</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="578"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="646"/>
<source>Delete &apos;%1&apos;?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="625"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="693"/>
<source>Name:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="667"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="735"/>
<source>Change Type To</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="668"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="736"/>
<source>Type:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="672"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="683"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="740"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="751"/>
<source>Cannot Change Type</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="672"/>
<location filename="../Debugger/SymbolTree/SymbolTreeViews.cpp" line="740"/>
<source>That node cannot have a type.</source>
<translation type="unfinished"></translation>
</message>

View File

@@ -75,7 +75,7 @@ void InputIsoFile::BeginRead2(uint lsn)
{
// While this usually indicates that the ISO is corrupted, some games do attempt
// to read past the end of the disc, so don't error here.
ERROR_LOG("isoFile error: Block index is past the end of file! (%u >= %u).", lsn, m_blocks);
ERROR_LOG("isoFile error: Block index is past the end of file! ({} >= {}).", lsn, m_blocks);
return;
}

View File

@@ -327,8 +327,9 @@ enum class TriFiltering : s8
Forced,
};
enum class AccBlendLevel : u8
enum class AccBlendLevel : s8
{
Automatic = -1,
Minimum,
Basic,
Medium,
@@ -811,7 +812,7 @@ struct Pcsx2Config
GSRendererType Renderer = GSRendererType::Auto;
float UpscaleMultiplier = 1.0f;
AccBlendLevel AccurateBlendingUnit = AccBlendLevel::Basic;
AccBlendLevel AccurateBlendingUnit = AccBlendLevel::Automatic;
BiFiltering TextureFiltering = BiFiltering::PS2;
TexturePreloadingLevel TexturePreloading = TexturePreloadingLevel::Full;
GSDumpCompressionMethod GSDumpCompression = GSDumpCompressionMethod::Zstandard;

View File

@@ -2741,12 +2741,6 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
OMSetRenderTargets(draw_rt, draw_ds, &config.scissor, read_only_dsv);
SetupOM(config.depth, OMBlendSelector(config.colormask, config.blend), config.blend.constant);
// Clear stencil as close as possible to the RT bind, to avoid framebuffer swaps.
if (draw_ds && config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne &&
m_features.multidraw_fb_copy && (config.require_one_barrier || config.require_full_barrier))
m_ctx->ClearDepthStencilView(*static_cast<GSTexture11*>(draw_ds), D3D11_CLEAR_STENCIL, 0.0f, 1);
SendHWDraw(config, draw_rt_clone, draw_rt, config.require_one_barrier, config.require_full_barrier, false);
if (config.blend_multi_pass.enable)

View File

@@ -5180,6 +5180,8 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask(GSTextureCache::Target* rt, GS
enable_fbmask_emulation = true;
break;
case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Enable Fbmask emulation excluding triangle class because it is quite slow.
enable_fbmask_emulation = (m_vt.m_primclass != GS_TRIANGLE_CLASS);
break;
@@ -5204,7 +5206,7 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask(GSTextureCache::Target* rt, GS
// If date is enabled you need to test the green channel instead of the alpha channel.
// Only enable this code in DATE mode to reduce the number of shaders.
m_conf.ps.write_rg = (process_rg & SHUFFLE_WRITE) && m_cached_ctx.TEST.DATE;
m_conf.ps.write_rg = (process_rg & SHUFFLE_WRITE) && (features.texture_barrier || features.multidraw_fb_copy) && m_cached_ctx.TEST.DATE;
m_conf.ps.real16src = m_copy_16bit_to_target_shuffle;
m_conf.ps.shuffle_same = m_same_group_texture_shuffle;
// Please bang my head against the wall!
@@ -5784,7 +5786,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
const bool blend_ad = m_conf.ps.blend_c == 1;
const bool alpha_mask = (m_cached_ctx.FRAME.FBMSK & 0xFF000000) == 0xFF000000;
bool blend_ad_alpha_masked = blend_ad && alpha_mask;
const bool is_basic_blend = GSConfig.AccurateBlendingUnit >= AccBlendLevel::Basic;
const bool is_basic_blend = GSConfig.AccurateBlendingUnit != AccBlendLevel::Minimum;
if (blend_ad_alpha_masked && (((is_basic_blend || (COLCLAMP.CLAMP == 0)) && (features.texture_barrier || features.multidraw_fb_copy))
|| ((GSConfig.AccurateBlendingUnit >= AccBlendLevel::Medium) || m_conf.require_one_barrier)))
{
@@ -5894,6 +5896,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
sw_blending |= m_vt.m_primclass == GS_SPRITE_CLASS && m_drawlist.size() < 100;
[[fallthrough]];
case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Prefer sw blend if possible.
color_dest_blend &= !prefer_sw_blend;
color_dest_blend2 &= !prefer_sw_blend;
@@ -5935,6 +5939,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
sw_blending |= !(blend_ad_alpha_masked || ad_second_pass) && (alpha_c1_high_max_one || alpha_c1_high_no_rta_correct) && no_prim_overlap;
[[fallthrough]];
case AccBlendLevel::Basic:
case AccBlendLevel::Automatic:
default:
// Prefer sw blend if possible.
color_dest_blend &= !prefer_sw_blend;
color_dest_blend2 &= !prefer_sw_blend;
@@ -6441,7 +6447,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
// Switch DATE_PRIMID with DATE_BARRIER in such cases to ensure accuracy.
// No mix of COLCLIP + sw blend + DATE_PRIMID, neither sw fbmask + DATE_PRIMID.
// Note: Do the swap in the end, saves the expensive draw splitting/barriers when mixed software blending is used.
if (sw_blending && DATE_PRIMID && m_conf.require_full_barrier)
if (sw_blending && DATE_PRIMID && m_conf.require_full_barrier &&
(features.texture_barrier || (features.multidraw_fb_copy && !no_prim_overlap)))
{
GL_PERF("DATE: Swap DATE_PRIMID with DATE_BARRIER");
DATE_PRIMID = false;
@@ -6869,7 +6876,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
{
m_conf.tex = nullptr;
m_conf.ps.tex_is_fb = true;
if (m_prim_overlap == PRIM_OVERLAP_NO || !g_gs_device->Features().texture_barrier)
if (m_prim_overlap == PRIM_OVERLAP_NO || !(g_gs_device->Features().texture_barrier || g_gs_device->Features().multidraw_fb_copy))
m_conf.require_one_barrier = true;
else
m_conf.require_full_barrier = true;
@@ -7129,21 +7136,14 @@ bool GSRendererHW::CanUseTexIsFB(const GSTextureCache::Target* rt, const GSTextu
return false;
}
// If it's a channel shuffle, tex-is-fb should be fine, even on DX.
// If it's a channel shuffle, tex-is-fb should be fine.
if (m_channel_shuffle)
{
GL_CACHE("HW: Enabling tex-is-fb for channel shuffle.");
return true;
}
// No barriers -> we can't use tex-is-fb.
if (!g_gs_device->Features().texture_barrier)
{
GL_CACHE("HW: Disabling tex-is-fb due to no barriers.");
return false;
}
// If it's a channel shuffle, tex-is-fb is always fine, except on DX.
// If it's a channel shuffle, tex-is-fb is always fine.
if (m_texture_shuffle)
{
// We can't do tex is FB if the source and destination aren't pointing to the same bit of texture.
@@ -7154,6 +7154,13 @@ bool GSRendererHW::CanUseTexIsFB(const GSTextureCache::Target* rt, const GSTextu
return true;
}
// No barriers -> we can't use tex-is-fb when there's overlap.
if (!(g_gs_device->Features().texture_barrier || g_gs_device->Features().multidraw_fb_copy) && m_prim_overlap != PRIM_OVERLAP_NO)
{
GL_CACHE("HW: Disabling tex-is-fb due to no barriers.");
return false;
}
static constexpr auto check_clamp = [](u32 clamp, u32 min, u32 max, s32 tmin, s32 tmax) {
if (clamp == CLAMP_REGION_CLAMP)
{
@@ -7969,8 +7976,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
}
else if (DATE_one)
{
const bool multidraw_fb_copy = features.multidraw_fb_copy && (m_conf.require_one_barrier || m_conf.require_full_barrier);
if (features.texture_barrier || multidraw_fb_copy)
if (features.texture_barrier)
{
m_conf.require_one_barrier = true;
m_conf.ps.date = 5 + m_cached_ctx.TEST.DATM;
@@ -9544,7 +9550,7 @@ void GSRendererHW::EndHLEHardwareDraw(bool force_copy_on_hazard /* = false */)
{
const GSDevice::FeatureSupport features = g_gs_device->Features();
if (!force_copy_on_hazard && config.tex == config.rt && features.texture_barrier)
if (!force_copy_on_hazard && config.tex == config.rt)
{
// Sample RT 1:1.
config.require_one_barrier = !features.framebuffer_fetch;

View File

@@ -664,10 +664,10 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
return (config.GPUPaletteConversion == ((value > 1) ? (config.TexturePreloading == TexturePreloadingLevel::Full) : (value != 0)));
case GSHWFixId::MinimumBlendingLevel:
return (static_cast<int>(config.AccurateBlendingUnit) >= value);
return (config.AccurateBlendingUnit == AccBlendLevel::Automatic || static_cast<int>(config.AccurateBlendingUnit) >= value);
case GSHWFixId::MaximumBlendingLevel:
return (static_cast<int>(config.AccurateBlendingUnit) <= value);
return (config.AccurateBlendingUnit == AccBlendLevel::Automatic || static_cast<int>(config.AccurateBlendingUnit) <= value);
case GSHWFixId::RecommendedBlendingLevel:
return true;
@@ -868,21 +868,23 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
case GSHWFixId::MinimumBlendingLevel:
{
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum))
config.AccurateBlendingUnit = std::max(config.AccurateBlendingUnit, static_cast<AccBlendLevel>(value));
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && config.AccurateBlendingUnit == AccBlendLevel::Automatic)
config.AccurateBlendingUnit = static_cast<AccBlendLevel>(value);
}
break;
case GSHWFixId::MaximumBlendingLevel:
{
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum))
config.AccurateBlendingUnit = std::min(config.AccurateBlendingUnit, static_cast<AccBlendLevel>(value));
if (value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && config.AccurateBlendingUnit == AccBlendLevel::Automatic)
config.AccurateBlendingUnit = static_cast<AccBlendLevel>(value);
}
break;
case GSHWFixId::RecommendedBlendingLevel:
{
if (!is_sw_renderer && value >= 0 && value <= static_cast<int>(AccBlendLevel::Maximum) && static_cast<int>(EmuConfig.GS.AccurateBlendingUnit) < value)
// Need to increment by 1 because Automatic is -1.
const int blend_level = static_cast<int>(config.AccurateBlendingUnit) + 1;
if (!is_sw_renderer && value >= static_cast<int>(AccBlendLevel::Automatic) && value <= static_cast<int>(AccBlendLevel::Maximum) && blend_level < value)
{
Host::AddKeyedOSDMessage("HWBlendingWarning",
fmt::format(TRANSLATE_FS("GameDatabase",
@@ -891,8 +893,7 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
"You can adjust the blending level in Game Properties to improve\n"
"graphical quality, but this will increase system requirements."),
ICON_FA_PAINTBRUSH,
Pcsx2Config::GSOptions::BlendingLevelNames[static_cast<int>(
EmuConfig.GS.AccurateBlendingUnit)],
Pcsx2Config::GSOptions::BlendingLevelNames[blend_level],
Pcsx2Config::GSOptions::BlendingLevelNames[value]),
Host::OSD_WARNING_DURATION);
}

View File

@@ -4066,8 +4066,9 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
FSUI_NSTR("Force 32bit"),
};
static constexpr const char* s_blending_options[] = {
FSUI_NSTR("Automatic (Default)"),
FSUI_NSTR("Minimum"),
FSUI_NSTR("Basic (Recommended)"),
FSUI_NSTR("Basic"),
FSUI_NSTR("Medium"),
FSUI_NSTR("High"),
FSUI_NSTR("Full (Slow)"),
@@ -4199,7 +4200,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
"EmuCore/GS", "dithering_ps2", 2, s_dithering_options, std::size(s_dithering_options), true);
DrawIntListSetting(bsi, FSUI_ICONSTR(ICON_FA_SPLOTCH, "Blending Accuracy"),
FSUI_CSTR("Determines the level of accuracy when emulating blend modes not supported by the host graphics API."), "EmuCore/GS",
"accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic), s_blending_options, std::size(s_blending_options), true);
"accurate_blending_unit", static_cast<int>(AccBlendLevel::Automatic), s_blending_options, std::size(s_blending_options), true);
DrawToggleSetting(
bsi, FSUI_ICONSTR(ICON_FA_BULLSEYE, "Mipmapping"), FSUI_CSTR("Enables emulation of the GS's texture mipmapping."), "EmuCore/GS", "hw_mipmap", true);
}

View File

@@ -653,6 +653,7 @@ const char* Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames[(size_t)FMVAspectR
nullptr};
const char* Pcsx2Config::GSOptions::BlendingLevelNames[] = {
"Automatic",
"Minimum",
"Basic",
"Medium",

View File

@@ -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 = 71;
static constexpr u32 SHADER_CACHE_VERSION = 72;

View File

@@ -3150,12 +3150,12 @@ void VMManager::WarnAboutUnsafeSettings()
if (EmuConfig.GS.TriFilter != TriFiltering::Automatic)
{
append(ICON_FA_PAGER,
TRANSLATE_SV("VMManager", "Trilinear filtering is not set to automatic. This may break rendering in some games."));
TRANSLATE_SV("VMManager", "Trilinear filtering is not set to Automatic. This may break rendering in some games."));
}
if (EmuConfig.GS.AccurateBlendingUnit <= AccBlendLevel::Minimum)
if (EmuConfig.GS.AccurateBlendingUnit == AccBlendLevel::Minimum)
{
append(ICON_FA_PAINTBRUSH,
TRANSLATE_SV("VMManager", "Blending Accuracy is below Basic, this may break effects in some games."));
TRANSLATE_SV("VMManager", "Blending Accuracy is set to Minimum. This may break rendering in some games."));
}
if (EmuConfig.GS.HWDownloadMode != GSHardwareDownloadMode::Enabled)
{

View File

@@ -29,6 +29,8 @@
#include "fmt/format.h"
#include "GS/GSVector.h"
#include <bit>
#include <map>
#include <unordered_set>
@@ -109,16 +111,6 @@ vtlb_private::VTLBVirtual::VTLBVirtual(VTLBPhysical phys, u32 paddr, u32 vaddr)
}
}
#if defined(_M_X86)
#include <immintrin.h>
#elif defined(_M_ARM64)
#if defined(_MSC_VER) && !defined(__clang__)
#include <arm64_neon.h>
#else
#include <arm_neon.h>
#endif
#endif
__inline int CheckCache(u32 addr)
{
// Check if the cache is enabled
@@ -130,83 +122,28 @@ __inline int CheckCache(u32 addr)
size_t i = 0;
const size_t size = cachedTlbs.count;
#if defined(_M_X86)
const int stride = 4;
const __m128i addr_vec = _mm_set1_epi32(addr);
const GSVector4i addr_vec = GSVector4i::load(addr);
for (; i + stride <= size; i += stride)
{
const __m128i pfn1_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&cachedTlbs.PFN1s[i]));
const __m128i pfn0_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&cachedTlbs.PFN0s[i]));
const __m128i mask_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&cachedTlbs.PageMasks[i]));
const GSVector4i pfn1_vec = GSVector4i::load<true>(&cachedTlbs.PFN1s[i]);
const GSVector4i pfn0_vec = GSVector4i::load<true>(&cachedTlbs.PFN0s[i]);
const GSVector4i mask_vec = GSVector4i::load<true>(&cachedTlbs.PageMasks[i]);
const __m128i cached1_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&cachedTlbs.CacheEnabled1[i]));
const __m128i cached0_vec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(&cachedTlbs.CacheEnabled0[i]));
const GSVector4i cached1_enable_vec = GSVector4i::load<true>(&cachedTlbs.CacheEnabled1[i]);
const GSVector4i cached0_enable_vec = GSVector4i::load<true>(&cachedTlbs.CacheEnabled0[i]);
const __m128i pfn1_end_vec = _mm_add_epi32(pfn1_vec, mask_vec);
const __m128i pfn0_end_vec = _mm_add_epi32(pfn0_vec, mask_vec);
const GSVector4i cmp1 = addr_vec.ge32(pfn1_vec) & addr_vec.le32(pfn1_vec + mask_vec);
const GSVector4i cmp0 = addr_vec.ge32(pfn0_vec) & addr_vec.le32(pfn1_vec + mask_vec);
// pfn0 <= addr
const __m128i gteLowerBound0 = _mm_or_si128(
_mm_cmpgt_epi32(addr_vec, pfn0_vec),
_mm_cmpeq_epi32(addr_vec, pfn0_vec));
// pfn0 + mask >= addr
const __m128i gteUpperBound0 = _mm_or_si128(
_mm_cmpgt_epi32(pfn0_end_vec, addr_vec),
_mm_cmpeq_epi32(pfn0_end_vec, addr_vec));
const GSVector4i lanes_enabled = (cmp1 & cached1_enable_vec) | (cmp0 & cached0_enable_vec);
// pfn1 <= addr
const __m128i gteUpperBound1 = _mm_or_si128(
_mm_cmpgt_epi32(pfn1_end_vec, addr_vec),
_mm_cmpeq_epi32(pfn1_end_vec, addr_vec));
// pfn1 + mask >= addr
const __m128i gteLowerBound1 = _mm_or_si128(
_mm_cmpgt_epi32(addr_vec, pfn1_vec),
_mm_cmpeq_epi32(addr_vec, pfn1_vec));
// pfn0 <= addr <= pfn0 + mask
__m128i cmp0 = _mm_and_si128(gteLowerBound0, gteUpperBound0);
// pfn1 <= addr <= pfn1 + mask
__m128i cmp1 = _mm_and_si128(gteLowerBound1, gteUpperBound1);
cmp1 = _mm_and_si128(cmp1, cached1_vec);
cmp0 = _mm_and_si128(cmp0, cached0_vec);
const __m128i cmp = _mm_or_si128(cmp1, cmp0);
if (!_mm_testz_si128(cmp, cmp))
{
return true;
}
}
#elif defined(_M_ARM64)
const int stride = 4;
const uint32x4_t addr_vec = vld1q_dup_u32(&addr);
for (; i + stride <= size; i += stride)
{
const uint32x4_t pfn1_vec = vld1q_u32(&cachedTlbs.PFN1s[i]);
const uint32x4_t pfn0_vec = vld1q_u32(&cachedTlbs.PFN0s[i]);
const uint32x4_t mask_vec = vld1q_u32(&cachedTlbs.PageMasks[i]);
const uint32x4_t cached1_vec = vld1q_u32(&cachedTlbs.CacheEnabled1[i]);
const uint32x4_t cached0_vec = vld1q_u32(&cachedTlbs.CacheEnabled0[i]);
const uint32x4_t pfn1_end_vec = vaddq_u32(pfn1_vec, mask_vec);
const uint32x4_t pfn0_end_vec = vaddq_u32(pfn0_vec, mask_vec);
const uint32x4_t cmp1 = vandq_u32(vcgeq_u32(addr_vec, pfn1_vec), vcleq_u32(addr_vec, pfn1_end_vec));
const uint32x4_t cmp0 = vandq_u32(vcgeq_u32(addr_vec, pfn0_vec), vcleq_u32(addr_vec, pfn0_end_vec));
const uint32x4_t lanes_enabled = vorrq_u32(vandq_u32(cached1_vec, cmp1), vandq_u32(cached0_vec, cmp0));
const uint32x2_t tmp = vorr_u32(vget_low_u32(lanes_enabled), vget_high_u32(lanes_enabled));
if (vget_lane_u32(vpmax_u32(tmp, tmp), 0))
if (!lanes_enabled.allfalse())
return true;
}
#endif
for (; i < size; i++)
{
const u32 mask = cachedTlbs.PageMasks[i];
@@ -637,7 +574,7 @@ static void TAKES_R128 vtlbUnmappedVWriteLg(u32 addr, r128 data) { vtlb_Miss(add
template <typename OperandType>
static OperandType vtlbUnmappedPReadSm(u32 addr) {
vtlb_BusError(addr, 0);
if(!CHECK_EEREC && CHECK_CACHE && CheckCache(addr)){
if (!CHECK_EEREC && CHECK_CACHE && CheckCache(addr)){
switch (sizeof(OperandType)) {
case 1: return readCache8(addr, false);
case 2: return readCache16(addr, false);