mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ea33400a9 | ||
|
|
32a3e8e62d | ||
|
|
fa953d7bb3 | ||
|
|
66cd51bcd5 | ||
|
|
ed7ebb77ca | ||
|
|
10fc9a790d | ||
|
|
c42330eebf | ||
|
|
680e05fead | ||
|
|
1f7b98bf6b | ||
|
|
c3a20d421e | ||
|
|
f03ab6f728 | ||
|
|
e9275d78b5 | ||
|
|
8ababb3890 | ||
|
|
422aba4b20 | ||
|
|
045b9bbf40 | ||
|
|
1f519acf92 | ||
|
|
ac9ebdecba | ||
|
|
1861394216 | ||
|
|
11cc884c96 | ||
|
|
5710c2740c | ||
|
|
ec96feb22e | ||
|
|
a1173c53d3 | ||
|
|
ac0deff9b2 | ||
|
|
3ae707464c | ||
|
|
00ef419023 | ||
|
|
448a279cd4 | ||
|
|
70e13adfde | ||
|
|
25bc280818 | ||
|
|
32e073002a | ||
|
|
911314e948 | ||
|
|
a73fcb343c | ||
|
|
251b2960f8 | ||
|
|
5bb99105c3 |
@@ -25,7 +25,7 @@ LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBPNG=1.6.53
|
||||
LIBWEBP=1.6.0
|
||||
NVENC=11.1.5.3
|
||||
NVENC=13.0.19.0
|
||||
SDL=SDL3-3.4.0
|
||||
QT=6.10.1
|
||||
QTAPNG=1.3.0
|
||||
@@ -57,7 +57,7 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
|
||||
082cbf5f429e0d80820f68dc2b507a94d4cc1b4e70817b119bbb8ec6a69584b8 $SDL.tar.gz
|
||||
452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c libpng-$LIBPNG-apng.patch.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
2974b91062197e0527dffa3aadd8fe3bfa6681ae45f5ff9181bc0ca6479abd59 nv-codec-headers-$NVENC.tar.gz
|
||||
13da39edb3a40ed9713ae390ca89faa2f1202c9dda869ef306a8d4383e242bee nv-codec-headers-$NVENC.tar.gz
|
||||
c465aa56757e7746ac707f582b6e2d51546569a4a2488c1172fb543aa5fdfc2c vulkan-sdk-$VULKAN.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
5a6226f7e23db51fdc3223121eba53f3f5447cf0cc4d6cb82a3a2df7a65d265d qtbase-everywhere-src-$QT.tar.xz
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<url type="donation">https://github.com/sponsors/PCSX2</url>
|
||||
<url type="faq">https://pcsx2.net/docs/</url>
|
||||
<url type="help">https://pcsx2.net/discord</url>
|
||||
<url type="contribute">https://github.com/PCSX2/pcsx2/blob/master/.github/CONTRIBUTING.md</url>
|
||||
<url type="contribute">https://pcsx2.net/docs/category/contributing</url>
|
||||
<url type="translate">https://crowdin.com/project/pcsx2-emulator</url>
|
||||
<url type="contact">https://mastodon.social/@PCSX2</url>
|
||||
<screenshots>
|
||||
|
||||
@@ -2075,6 +2075,8 @@ SCAJ-20128:
|
||||
SCAJ-20129:
|
||||
name: "Ponkotsu Roman Daikatsugeki Bumpy Trot"
|
||||
region: "NTSC-Unk"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
@@ -7614,6 +7616,8 @@ SCKA-20058:
|
||||
name: "액션 로망 범피 트롯"
|
||||
name-en: "Action Romance Bumpy Trot"
|
||||
region: "NTSC-K"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
@@ -25578,6 +25582,8 @@ SLES-54137:
|
||||
SLES-54138:
|
||||
name: "Steambot Chronicles"
|
||||
region: "PAL-E"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
@@ -26228,6 +26234,8 @@ SLES-54333:
|
||||
SLES-54335:
|
||||
name: "Steambot Chronicles"
|
||||
region: "PAL-F"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
@@ -35853,6 +35861,8 @@ SLPM-60255:
|
||||
name-sort: "ぽんこつろまんだいかつげきばんぴーとろっと [たいけんばん]"
|
||||
name-en: "Ponkotsu Roeman Daikatsugeki Bumpy Trot [Trial]"
|
||||
region: "NTSC-J"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
@@ -35924,6 +35934,8 @@ SLPM-60266:
|
||||
name-sort: "ぽんこつろまんだいかつげきばんぴーとろっと [たいけんばん]"
|
||||
name-en: "Ponkotsu Roeman Daikatsugeki Bumpy Trot [Trial]"
|
||||
region: "NTSC-J"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
@@ -59824,6 +59836,8 @@ SLPS-25457:
|
||||
name-sort: "ぽんこつろまんだいかつげきばんぴーとろっと"
|
||||
name-en: "Ponkotsu Roeman Daikatsugeki Bumpy Trot"
|
||||
region: "NTSC-J"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
@@ -61228,6 +61242,8 @@ SLPS-25683:
|
||||
name-sort: "ぽんこつろまんだいかつげきばんぴーとろっと [Irem COLLECTION]"
|
||||
name-en: "Ponkotsu Roman Daikatsugeki Bumpy Trot [Irem Collection]"
|
||||
region: "NTSC-J"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
@@ -71360,6 +71376,8 @@ SLUS-21344:
|
||||
name: "Steambot Chronicles"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
@@ -74901,6 +74919,8 @@ SLUS-28059:
|
||||
SLUS-28061:
|
||||
name: "Steambot Chronicles [Trade Demo]"
|
||||
region: "NTSC-U"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
@@ -75679,6 +75699,8 @@ SLUS-29185:
|
||||
SLUS-29188:
|
||||
name: "Steambot Chronicles [Regular Demo]"
|
||||
region: "NTSC-U"
|
||||
roundModes:
|
||||
eeRoundMode: 0 # Fixes broken load triggers.
|
||||
gsHWFixes:
|
||||
getSkipCount: "GSC_IRem"
|
||||
halfPixelOffset: 2 # Aligns effects.
|
||||
|
||||
@@ -236,6 +236,7 @@
|
||||
03000000ac0500005b05000000000000,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:Windows,
|
||||
03000000ac0500002d02000000000000,GameSir G4,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,
|
||||
03000000ac0500004d04000000000000,GameSir G4,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:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
|
||||
03000000373500002210000000000000,GameSir G7 Pro,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,lefty:a2,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Window,
|
||||
03000000ac0500001a06000000000000,GameSir T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,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,
|
||||
03000000373500009410000000000000,GameSir Tegenaria Lite,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,
|
||||
030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
|
||||
@@ -245,8 +246,8 @@
|
||||
03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows,
|
||||
030000008f0e00001411000000000000,Gamo2 Divaller,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:a3,start:b9,x:b0,y:b3,platform:Windows,
|
||||
03000000120c0000a857000000000000,Gator Claw,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,
|
||||
03000000c21100000791000000000000,Be1 GC101 Controller 1.03,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,
|
||||
03000000c9110000f055000000000000,Be1 GC100XF Controller,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,
|
||||
03000000c21100000791000000000000,Nacon GC101 1.03,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,
|
||||
03000000c9110000f055000000000000,Nacon GC100XF,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,
|
||||
030000008305000009a0000000000000,Genius,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,
|
||||
030000008305000031b0000000000000,Genius Maxfire Blaze 3,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,
|
||||
03000000451300000010000000000000,Genius Maxfire Grandias 12,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,
|
||||
@@ -463,7 +464,7 @@
|
||||
03000000250900006688000000000000,MP-8866 Super Dual Box,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,
|
||||
03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows,
|
||||
03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows,
|
||||
030000006b140000010c000000000000,Nacon GC 400ES,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:Windows,
|
||||
030000006b140000010c000000000000,Nacon GC400ES,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:Windows,
|
||||
030000006b1400001106000000000000,Nacon Revolution 3 PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
|
||||
0300000085320000170d000000000000,Nacon Revolution 5 Pro,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:Windows,
|
||||
0300000085320000190d000000000000,Nacon Revolution 5 Pro,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:Windows,
|
||||
@@ -1305,7 +1306,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
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,
|
||||
03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
|
||||
030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000c11100000191000011010000,EasySMX,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,
|
||||
@@ -1512,9 +1512,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,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,
|
||||
03000000f70600000100000000010000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Linux,
|
||||
030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 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,
|
||||
030000006b140000010c000010010000,Nacon GC 400ES,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:Linux,
|
||||
03000000853200000706000012010000,Nacon GC-100,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,
|
||||
05000000853200000503000000010000,Nacon MG-X Pro,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,
|
||||
030000006b140000010c000010010000,Nacon GC400ES,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:Linux,
|
||||
0300000085320000030c000011010000,Nacon GC100,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,
|
||||
03000000853200000706000012010000,Nacon GC100,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,
|
||||
05000000853200000503000000010000,Nacon MGX Pro,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,
|
||||
0300000085320000170d000011010000,Nacon Revolution 5 Pro,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,
|
||||
0300000085320000190d000011010000,Nacon Revolution 5 Pro,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,
|
||||
030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
@@ -1799,18 +1800,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000434f4d4d414e440000000000,VX Gaming Command Series,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
0000000058626f782033363020576900,Xbox 360 Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400001907000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
|
||||
030000005e0400008e02000010010000,Xbox 360 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,
|
||||
030000005e0400008e02000014010000,Xbox 360 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,
|
||||
030000005e0400009102000007010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
|
||||
030000005e040000a102000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
|
||||
030000005e040000a102000007010000,Xbox 360 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,
|
||||
030000005e040000a102000030060000,Xbox 360 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,
|
||||
030000006f0e00001503000000020000,Xbox 360 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,
|
||||
030000005e0400008e02000000010000,Xbox 360 EasySMX,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,
|
||||
030000005e0400008e02000000010000,Xbox 360 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,
|
||||
030000005e0400008e02000010010000,Xbox 360 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,
|
||||
030000005e0400008e02000002010000,Xbox 360 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,
|
||||
030000005e0400008e02000014010000,Xbox 360 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,
|
||||
030000005e0400008e02000047010000,Xbox 360 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,
|
||||
030000005e0400008e02000072050000,Xbox 360 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,
|
||||
030000005e040000a102000014010000,Xbox 360 Receiver,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,
|
||||
0000000058626f782047616d65706100,Xbox 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400008e02000072050000,Xbox 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,
|
||||
030000006f0e00001304000000010000,Xbox 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,
|
||||
03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
|
||||
030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
|
||||
|
||||
@@ -112,7 +112,7 @@ struct VS_OUTPUT
|
||||
|
||||
struct PS_INPUT
|
||||
{
|
||||
float4 p : SV_Position;
|
||||
noperspective centroid float4 p : SV_Position;
|
||||
float4 t : TEXCOORD0;
|
||||
float4 ti : TEXCOORD2;
|
||||
#if VS_IIP != 0 || GS_IIP != 0 || PS_IIP != 0
|
||||
@@ -140,7 +140,7 @@ struct PS_OUTPUT
|
||||
#endif
|
||||
#endif
|
||||
#if PS_ZCLAMP || PS_ZFLOOR
|
||||
float depth : SV_Depth;
|
||||
float depth : SV_DepthLessEqual;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -113,6 +113,10 @@ layout(binding = 3) uniform sampler2D img_prim_min;
|
||||
//layout(pixel_center_integer) in vec4 gl_FragCoord;
|
||||
#endif
|
||||
|
||||
#if (PS_ZFLOOR || PS_ZCLAMP) && HAS_CONSERVATIVE_DEPTH
|
||||
layout(depth_less) out float gl_FragDepth;
|
||||
#endif
|
||||
|
||||
vec4 sample_from_rt()
|
||||
{
|
||||
#if !NEEDS_RT
|
||||
|
||||
@@ -361,6 +361,10 @@ layout(set = 1, binding = 1) uniform texture2D Palette;
|
||||
layout(set = 1, binding = 3) uniform texture2D PrimMinTexture;
|
||||
#endif
|
||||
|
||||
#if PS_ZFLOOR || PS_ZCLAMP
|
||||
layout(depth_less) out float gl_FragDepth;
|
||||
#endif
|
||||
|
||||
#if NEEDS_TEX
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
|
||||
@@ -123,6 +123,11 @@ void BreakpointDialog::accept()
|
||||
bp->cond.expression = expr;
|
||||
bp->cond.expressionString = m_ui.txtCondition->text().toStdString();
|
||||
}
|
||||
else
|
||||
{
|
||||
bp->hasCond = false;
|
||||
bp->cond = {};
|
||||
}
|
||||
}
|
||||
if (auto* mc = std::get_if<MemCheck>(&m_bp_mc))
|
||||
{
|
||||
@@ -159,6 +164,11 @@ void BreakpointDialog::accept()
|
||||
mc->cond.expression = expr;
|
||||
mc->cond.expressionString = m_ui.txtCondition->text().toStdString();
|
||||
}
|
||||
else
|
||||
{
|
||||
mc->hasCond = false;
|
||||
mc->cond = {};
|
||||
}
|
||||
|
||||
int condition = 0;
|
||||
if (m_ui.chkRead->isChecked())
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Options and Patches</string>
|
||||
<string>Fast Boot Options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
|
||||
@@ -40,7 +40,6 @@ MemoryCardSettingsWidget::MemoryCardSettingsWidget(SettingsWindow* settings_dial
|
||||
|
||||
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.directory, m_ui.browse, m_ui.open, m_ui.reset, "Folders",
|
||||
"MemoryCards", Path::Combine(EmuFolders::DataRoot, "memcards"));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.automaticManagement, "EmuCore", "McdFolderAutoManage", true);
|
||||
|
||||
setupAdditionalUi();
|
||||
|
||||
@@ -58,11 +57,6 @@ MemoryCardSettingsWidget::MemoryCardSettingsWidget(SettingsWindow* settings_dial
|
||||
connect(m_ui.deleteCard, &QPushButton::clicked, this, &MemoryCardSettingsWidget::deleteCard);
|
||||
|
||||
refresh();
|
||||
|
||||
dialog()->registerWidgetHelp(m_ui.automaticManagement, tr("Automatically manage saves based on running game"),
|
||||
tr("Checked"),
|
||||
tr("(Folder type only / Card size: Auto) Loads only the relevant booted game saves, ignoring others. Avoids "
|
||||
"running out of space for saves."));
|
||||
}
|
||||
|
||||
MemoryCardSettingsWidget::~MemoryCardSettingsWidget() = default;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <QtWidgets/QTreeWidget>
|
||||
#include <QtWidgets/QToolButton>
|
||||
#include <QtWidgets/QListWidget>
|
||||
#include <QtWidgets/QCheckBox>
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
|
||||
@@ -175,22 +175,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="settingsGroupBox">
|
||||
<property name="title">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="automaticManagement">
|
||||
<property name="text">
|
||||
<string>Automatically manage saves based on running game</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
@@ -211,7 +195,6 @@
|
||||
<tabstop>renameCard</tabstop>
|
||||
<tabstop>convertCard</tabstop>
|
||||
<tabstop>deleteCard</tabstop>
|
||||
<tabstop>automaticManagement</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@@ -140,27 +140,34 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
|
||||
return;
|
||||
}
|
||||
|
||||
// Locate home directory
|
||||
// Get path to Desktop or per-user Start Menu\Programs directory
|
||||
// https://superuser.com/questions/1489874/how-can-i-get-the-real-path-of-desktop-in-windows-explorer/1789849#1789849
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
|
||||
// https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
|
||||
std::string link_file;
|
||||
if (const char* home = std::getenv("USERPROFILE"))
|
||||
if (PWSTR directory; SUCCEEDED(SHGetKnownFolderPath(is_desktop ? FOLDERID_Desktop : FOLDERID_Programs, 0, NULL, &directory)))
|
||||
{
|
||||
std::string directory_utf8 = StringUtil::WideStringToUTF8String(directory);
|
||||
CoTaskMemFree(directory);
|
||||
|
||||
if (is_desktop)
|
||||
link_file = Path::ToNativePath(fmt::format("{}/Desktop/{}.lnk", home, clean_name));
|
||||
link_file = Path::ToNativePath(fmt::format("{}/{}.lnk", directory_utf8, clean_name));
|
||||
else
|
||||
{
|
||||
const std::string start_menu_dir = Path::ToNativePath(fmt::format("{}/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/PCSX2", home));
|
||||
if (!FileSystem::EnsureDirectoryExists(start_menu_dir.c_str(), false))
|
||||
const std::string pcsx2_start_menu_dir = Path::ToNativePath(fmt::format("{}/PCSX2", directory_utf8));
|
||||
if (!FileSystem::EnsureDirectoryExists(pcsx2_start_menu_dir.c_str(), false))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Failed to create shortcut"), tr("Could not create start menu directory."), QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
link_file = Path::ToNativePath(fmt::format("{}/{}.lnk", start_menu_dir, clean_name));
|
||||
link_file = Path::ToNativePath(fmt::format("{}/{}.lnk", pcsx2_start_menu_dir, clean_name));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, tr("Failed to create shortcut"), tr("Home path is empty."), QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
|
||||
CoTaskMemFree(directory);
|
||||
QMessageBox::critical(this, tr("Failed to create shortcut"), is_desktop ? tr("'Desktop' directory not found") : tr("User's 'Start Menu\\Programs' directory not found"), QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -295,6 +295,9 @@
|
||||
<property name="text">
|
||||
<string>Desktop</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -2223,7 +2223,7 @@ Leaderboard Position: {1} of {2}</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/BIOSSettingsWidget.ui" line="138"/>
|
||||
<source>Options and Patches</source>
|
||||
<source>Fast Boot Options</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
@@ -2339,18 +2339,18 @@ Leaderboard Position: {1} of {2}</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="103"/>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="132"/>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="137"/>
|
||||
<source>Invalid Address</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="119"/>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="155"/>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="160"/>
|
||||
<source>Invalid Condition</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="139"/>
|
||||
<location filename="../Debugger/Breakpoints/BreakpointDialog.cpp" line="144"/>
|
||||
<source>Invalid Size</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -6804,11 +6804,6 @@ The URL was: %1</source>
|
||||
<source>BIOS Selection</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/ImGui/FullscreenUI.cpp" line="9512"/>
|
||||
<source>Options and Patches</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/ImGui/FullscreenUI.cpp" line="9513"/>
|
||||
<source>Skips the intro screen, and bypasses region checks.</source>
|
||||
@@ -9942,6 +9937,11 @@ Do you want to shutdown anyway and IRREVERSIBLY CORRUPT YOUR MEMORY CARD?</sourc
|
||||
<source>Shows the number of dumped and loaded texture replacements on the OSD.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/ImGui/FullscreenUI.cpp" line="9512"/>
|
||||
<source>Fast Boot Options</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/ImGui/FullscreenUI.cpp" line="9604"/>
|
||||
<source>Bilinear Dirty Upscale</source>
|
||||
@@ -11888,12 +11888,12 @@ This action cannot be undone.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp" line="2788"/>
|
||||
<location filename="../../pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp" line="2713"/>
|
||||
<source>Stencil buffers and texture barriers are both unavailable, this will break some graphical effects.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp" line="5130"/>
|
||||
<location filename="../../pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp" line="5052"/>
|
||||
<source>Spin GPU During Readbacks is enabled, but calibrated timestamps are unavailable. This might be really slow.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -11995,7 +11995,7 @@ Please see our official documentation for more information.</source>
|
||||
<context>
|
||||
<name>GSDeviceVK</name>
|
||||
<message>
|
||||
<location filename="../../pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp" line="2153"/>
|
||||
<location filename="../../pcsx2/GS/Renderers/Vulkan/GSDeviceVK.cpp" line="2078"/>
|
||||
<source>Your GPU does not support the required Vulkan features.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -19742,12 +19742,12 @@ Savestates should not be used in place of in-game saves.</source>
|
||||
<context>
|
||||
<name>MemoryCardListWidget</name>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="456"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="450"/>
|
||||
<source>Yes</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="456"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="450"/>
|
||||
<source>No</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -19781,7 +19781,7 @@ Savestates should not be used in place of in-game saves.</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.ui" line="90"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="113"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="107"/>
|
||||
<source>Reset</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -19812,170 +19812,149 @@ Savestates should not be used in place of in-game saves.</source>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.ui" line="148"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="305"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="299"/>
|
||||
<source>Create</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.ui" line="155"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="299"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="293"/>
|
||||
<source>Rename</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.ui" line="162"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="300"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="294"/>
|
||||
<source>Convert</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.ui" line="169"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="301"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="295"/>
|
||||
<source>Delete</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.ui" line="181"/>
|
||||
<source>Settings</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.ui" line="187"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="62"/>
|
||||
<source>Automatically manage saves based on running game</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="63"/>
|
||||
<source>Checked</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="64"/>
|
||||
<source>(Folder type only / Card size: Auto) Loads only the relevant booted game saves, ignoring others. Avoids running out of space for saves.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="93"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="87"/>
|
||||
<source>Swap Memory Cards</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="113"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="107"/>
|
||||
<source>Eject Memory Card</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="152"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="275"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="340"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="146"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="269"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="334"/>
|
||||
<source>Error</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="212"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="222"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="206"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="216"/>
|
||||
<source>Delete Memory Card</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="237"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="244"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="251"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="258"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="231"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="238"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="245"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="252"/>
|
||||
<source>Rename Memory Card</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="237"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="231"/>
|
||||
<source>New Card Name</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="244"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="238"/>
|
||||
<source>New name is invalid, it must end with .ps2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="252"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="246"/>
|
||||
<source>New name is invalid, a card with this name already exists.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="105"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="99"/>
|
||||
<source>Slot %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="152"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="146"/>
|
||||
<source>This Memory Card cannot be recognized or is not a valid file type.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="213"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="207"/>
|
||||
<source>Are you sure you wish to delete the Memory Card '%1'?
|
||||
|
||||
This action cannot be reversed, and you will lose any saves on the card.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="223"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="217"/>
|
||||
<source>Failed to delete the Memory Card. The log may have more information.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="259"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="253"/>
|
||||
<source>Failed to rename Memory Card. The log may contain more information.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="275"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="269"/>
|
||||
<source>Cannot convert an unformatted memory card.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="294"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="288"/>
|
||||
<source>Use for Slot %1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="340"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="334"/>
|
||||
<source>Both slots must have a card selected to swap.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="356"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="350"/>
|
||||
<source>PS2 (8MB)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="359"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="353"/>
|
||||
<source>PS2 (16MB)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="362"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="356"/>
|
||||
<source>PS2 (32MB)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="365"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="359"/>
|
||||
<source>PS2 (64MB)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="368"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="362"/>
|
||||
<source>PS1 (128KB)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="372"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="381"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="366"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="375"/>
|
||||
<source>Unknown</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="377"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="371"/>
|
||||
<source>PS2 (Folder)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -19983,12 +19962,12 @@ This action cannot be reversed, and you will lose any saves on the card.</source
|
||||
<context>
|
||||
<name>MemoryCardSlotWidget</name>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="513"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="507"/>
|
||||
<source>%1 [%2]</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="519"/>
|
||||
<location filename="../Settings/MemoryCardSettingsWidget.cpp" line="513"/>
|
||||
<source>%1 [Missing]</source>
|
||||
<extracomment>Ignore Crowdin's warning for [Missing], the text should be translated.</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
@@ -22483,115 +22462,120 @@ Scanning recursively takes more time, but will identify files in subdirectories.
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="139"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="154"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="163"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="160"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="170"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="181"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="203"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="214"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="290"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="301"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="309"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="337"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="370"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="409"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="177"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="188"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="210"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="221"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="297"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="308"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="316"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="344"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="377"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="416"/>
|
||||
<source>Failed to create shortcut</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="139"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="301"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="308"/>
|
||||
<source>Filename contains illegal character.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="154"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="160"/>
|
||||
<source>Could not create start menu directory.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="163"/>
|
||||
<source>Home path is empty.</source>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="170"/>
|
||||
<source>'Desktop' directory not found</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="170"/>
|
||||
<source>User's 'Start Menu\Programs' directory not found</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="177"/>
|
||||
<source>A shortcut with the same name already exists.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="181"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="370"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="188"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="377"/>
|
||||
<source>File path contains invalid character(s).</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="203"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="210"/>
|
||||
<source>CoInitialize failed (%1)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="223"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="230"/>
|
||||
<source>CoCreateInstance failed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="232"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="239"/>
|
||||
<source>SetPath failed (%1)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="241"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="248"/>
|
||||
<source>SetWorkingDirectory failed (%1)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="252"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="259"/>
|
||||
<source>SetArguments failed (%1)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="263"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="270"/>
|
||||
<source>SetIconLocation failed (%1)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="271"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="278"/>
|
||||
<source>QueryInterface failed (%1)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="280"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="287"/>
|
||||
<source>Failed to save the shortcut (%1)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="290"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="297"/>
|
||||
<source>Cannot create a shortcut without a title.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="309"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="316"/>
|
||||
<source>Executable path is empty.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="337"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="344"/>
|
||||
<source>Path to the Home directory is empty.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="399"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="406"/>
|
||||
<source>Desktop Shortcut Files (*.desktop)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="401"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="408"/>
|
||||
<source>Select Shortcut Save Destination</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="409"/>
|
||||
<location filename="../ShortcutCreationDialog.cpp" line="416"/>
|
||||
<source>Failed to create .desktop file</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -25524,42 +25508,42 @@ Error was: {}</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3171"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3169"/>
|
||||
<source>Fast CDVD is enabled, this may break games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3175"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3173"/>
|
||||
<source>Cycle rate/skip is not at default, this may crash or make games run too slow.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3185"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3183"/>
|
||||
<source>Upscale multiplier is below native, this will break rendering.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3225"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3223"/>
|
||||
<source>Mipmapping is disabled. This may break rendering in some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3230"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3228"/>
|
||||
<source>Debug device is enabled. This will massively reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3260"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3258"/>
|
||||
<source>Texture filtering is not set to Bilinear (PS2). This will break rendering in some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3723"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3721"/>
|
||||
<source>No Game Running</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3190"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3188"/>
|
||||
<source>Trilinear filtering is not set to automatic. This may break rendering in some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -25643,142 +25627,142 @@ PCSX2 will be able to run once you've placed your BIOS image inside the fol
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3118"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3116"/>
|
||||
<source>Cheats have been disabled due to RetroAchievements Hardcore Mode.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3195"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3193"/>
|
||||
<source>Blending Accuracy is below Basic, this may break effects in some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3200"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3198"/>
|
||||
<source>Hardware Download Mode is not set to Accurate, this may break rendering in some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3235"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3233"/>
|
||||
<source>Dithering is set to Force 32 bit. This will break rendering in some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3240"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3238"/>
|
||||
<source>Dithering is disabled. This will cause color banding in some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3245"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3243"/>
|
||||
<source>Integer scaling is enabled. This may shrink the image.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3254"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3252"/>
|
||||
<source>Graphics API is not set to Automatic. This may cause performance problems and graphical issues.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3266"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3264"/>
|
||||
<source>EE FPU Round Mode is not set to default, this may break some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3272"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3270"/>
|
||||
<source>EE FPU Clamp Mode is not set to default, this may break some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3277"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3275"/>
|
||||
<source>VU0 Round Mode is not set to default, this may break some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3282"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3280"/>
|
||||
<source>VU1 Round Mode is not set to default, this may break some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3289"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3287"/>
|
||||
<source>VU Clamp Mode is not set to default, this may break some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3294"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3292"/>
|
||||
<source>128MB RAM is enabled. Compatibility with some games may be affected.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3299"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3297"/>
|
||||
<source>Game Fixes are not enabled. Compatibility with some games may be affected.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3304"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3302"/>
|
||||
<source>Compatibility Patches are not enabled. Compatibility with some games may be affected.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3308"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3306"/>
|
||||
<source>Frame rate for NTSC is not default. This may break some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3310"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3308"/>
|
||||
<source>Frame rate for PAL is not default. This may break some games.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3329"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3327"/>
|
||||
<source>EE Recompiler is not enabled, this will significantly reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3334"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3332"/>
|
||||
<source>VU0 Recompiler is not enabled, this will significantly reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3339"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3337"/>
|
||||
<source>VU1 Recompiler is not enabled, this will significantly reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3344"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3342"/>
|
||||
<source>IOP Recompiler is not enabled, this will significantly reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3349"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3347"/>
|
||||
<source>EE Cache is enabled, this will significantly reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3354"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3352"/>
|
||||
<source>EE Wait Loop Detection is not enabled, this may reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3359"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3357"/>
|
||||
<source>INTC Spin Detection is not enabled, this may reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3362"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3360"/>
|
||||
<source>Fastmem is not enabled, this will reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3366"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3364"/>
|
||||
<source>Instant VU1 is disabled, this may reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3371"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3369"/>
|
||||
<source>mVU Flag Hack is not enabled, this may reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3205"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3203"/>
|
||||
<source>GPU Palette Conversion is enabled, this may reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@@ -25788,17 +25772,17 @@ PCSX2 will be able to run once you've placed your BIOS image inside the fol
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3210"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3208"/>
|
||||
<source>Texture Preloading is not Full, this may reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3215"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3213"/>
|
||||
<source>Estimate texture region is enabled, this may reduce performance.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3220"/>
|
||||
<location filename="../../pcsx2/VMManager.cpp" line="3218"/>
|
||||
<source>Texture dumping is enabled, this will continually dump textures to disk.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
|
||||
@@ -1326,7 +1326,6 @@ struct Pcsx2Config
|
||||
UseSavestateSelector : 1,
|
||||
InhibitScreensaver : 1,
|
||||
BackupSavestate : 1,
|
||||
McdFolderAutoManage : 1,
|
||||
ManuallySetRealTimeClock : 1, // passes user-set real-time clock information to cdvd at startup
|
||||
UseSystemLocaleFormat : 1, // presents OS time format instead of yyyy-MM-dd HH:mm:ss for manual RTC
|
||||
|
||||
|
||||
@@ -1899,6 +1899,30 @@ void GSState::FlushWrite()
|
||||
|
||||
r = m_tr.rect;
|
||||
|
||||
// If the end isn't where it said it would be, we need to calculate the end point.
|
||||
// Star Wars - The Clone Wars just sets the rect to 16x4095 then YOLO's about half a page, then kills the transfer.
|
||||
// If we just nuke the whole lot, even though nothing has been transferred, we risk killing data we don't mean to.
|
||||
if (m_tr.end < m_tr.total && GSIsHardwareRenderer())
|
||||
{
|
||||
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[m_tr.m_blit.DPSM];
|
||||
// Convert to nibbles then back to bytes after, in case trbpp is 4.
|
||||
const u32 in_data_pixel_count = (((len * 2) + ((psm_s.trbpp / 4) - 1)) / (psm_s.trbpp / 4));
|
||||
const u32 rect_pixel_count = r.width() * r.height();
|
||||
|
||||
if (rect_pixel_count > in_data_pixel_count)
|
||||
{
|
||||
const int calculated_height = ((in_data_pixel_count + (r.width() - 1)) / r.width());
|
||||
|
||||
// Just setting the height should be okay...
|
||||
r.w = std::max(r.y + calculated_height, psm_s.bs.y);
|
||||
|
||||
if (m_draw_transfers.size() > 0 && m_tr.m_blit.DBP == m_draw_transfers.back().blit.DBP)
|
||||
{
|
||||
m_draw_transfers.back().rect = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InvalidateVideoMem(m_env.BITBLTBUF, r);
|
||||
|
||||
const GSLocalMemory::writeImage wi = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].wi;
|
||||
@@ -3755,7 +3779,7 @@ GSState::PRIM_OVERLAP GSState::GetPrimitiveOverlapDrawlistImpl(bool save_drawlis
|
||||
}
|
||||
|
||||
PRIM_OVERLAP overlap = PRIM_OVERLAP_NO;
|
||||
bool check_quads = primclass == GS_TRIANGLE_CLASS;
|
||||
bool check_quads = (primclass == GS_TRIANGLE_CLASS);
|
||||
|
||||
u32 i = 0;
|
||||
u32 skip = 0; // Number of indices to skip if we have the bbox from the previous iteration.
|
||||
@@ -3766,11 +3790,85 @@ GSState::PRIM_OVERLAP GSState::GetPrimitiveOverlapDrawlistImpl(bool save_drawlis
|
||||
{
|
||||
u32 j = i + skip;
|
||||
|
||||
skip = 0;
|
||||
|
||||
GSVector4i bbox(INT_MAX, INT_MAX, -INT_MAX, -INT_MAX);
|
||||
|
||||
while (j < count)
|
||||
{
|
||||
if (check_quads && j + 3 < count)
|
||||
bool got_bbox = false;
|
||||
|
||||
// Assuming that indices 0-5 represent two triangles:
|
||||
// Triangle strips: indices 1, 2 are identical to indices 3, 4. Indices 0, 5 are different.
|
||||
// Triangles fans: indices 0, 2 are identical to indices 3, 4. Indices 1, 5 are different.
|
||||
// Warning: this depends on how the vertices are arranged in the vertex kick.
|
||||
// if that changes this detection will break.
|
||||
constexpr std::array<std::array<std::array<int, 3>, 2>, 2> tri_order({
|
||||
// Triangle strip expected indices.
|
||||
std::array{ std::array<int, 3>{ 1, 2, 0 }, std::array<int, 3>{ 3, 4, 5 } },
|
||||
|
||||
// Triangle fan expected indices.
|
||||
std::array{ std::array<int, 3>{ 0, 2, 1 }, std::array<int, 3>{ 3, 4, 5 } },
|
||||
});
|
||||
|
||||
const auto CheckTriangleQuads = [&]<int type>() {
|
||||
constexpr std::array<int, 3> tri0 = tri_order[type][0];
|
||||
constexpr std::array<int, 3> tri1 = tri_order[type][1];
|
||||
|
||||
if (!got_bbox && primclass == GS_TRIANGLE_CLASS && j + 3 < count &&
|
||||
index[j + tri0[0]] == index[j + tri1[0]] &&
|
||||
index[j + tri0[1]] == index[j + tri1[1]])
|
||||
{
|
||||
// Get the initial triangle bbox.
|
||||
bbox = GSVector4i(v[index[j + 0]].m[1]).upl16().xyxy();
|
||||
bbox = bbox.runion(GSVector4i(v[index[j + 1]].m[1]).upl16().xyxy());
|
||||
bbox = bbox.runion(GSVector4i(v[index[j + 2]].m[1]).upl16().xyxy());
|
||||
|
||||
while (true)
|
||||
{
|
||||
// There is a shared edge between this and next triangle.
|
||||
// Check if the unshared point is on opposite sides of the shared edge.
|
||||
const GSVector4i shared0 = GSVector4i(v[index[j + skip + tri0[0]]].m[1]).upl16();
|
||||
const GSVector4i shared1 = GSVector4i(v[index[j + skip + tri0[1]]].m[1]).upl16() - shared0;
|
||||
const GSVector4i unshared0 = GSVector4i(v[index[j + skip + tri0[2]]].m[1]).upl16() - shared0;
|
||||
const GSVector4i unshared1 = GSVector4i(v[index[j + skip + tri1[2]]].m[1]).upl16() - shared0;
|
||||
|
||||
// Cross product signs comparison.
|
||||
if ((unshared0.x * shared1.y - unshared0.y * shared1.x >= 0) ==
|
||||
(unshared1.x * shared1.y - unshared1.y * shared1.x >= 0))
|
||||
{
|
||||
break; // Triangles are on same side of the shared edge so there's overlap.
|
||||
}
|
||||
|
||||
// Corners are on opposite sides so we can assume a non-axis-aligned quad.
|
||||
// Take union with the single unshared point.
|
||||
bbox = bbox.runion(GSVector4i(v[index[j + skip + tri1[2]]].m[1]).upl16().xyxy());
|
||||
|
||||
skip += 3;
|
||||
|
||||
got_bbox = true;
|
||||
|
||||
if (!(j + skip + 3 < count &&
|
||||
index[j + skip + tri0[0]] == index[j + skip + tri1[0]] &&
|
||||
index[j + skip + tri0[1]] == index[j + skip + tri1[1]]))
|
||||
{
|
||||
// Cannot continue the strip/fan. Consume the last triangle and exit.
|
||||
skip += 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// First check: see if the triangles are part of triangle strip/fan.
|
||||
if (primclass == GS_TRIANGLE_CLASS)
|
||||
{
|
||||
CheckTriangleQuads.template operator()<0>(); // Check triangle strips.
|
||||
CheckTriangleQuads.template operator()<1>(); // Check triangle fans.
|
||||
}
|
||||
|
||||
// Second check: see if triangles form an axis-aligned quad.
|
||||
if (!got_bbox && primclass == GS_TRIANGLE_CLASS && check_quads && j + 3 < count)
|
||||
{
|
||||
const u16* RESTRICT idx0 = &index[j + 0];
|
||||
const u16* RESTRICT idx1 = &index[j + 3];
|
||||
@@ -3780,31 +3878,30 @@ GSState::PRIM_OVERLAP GSState::GetPrimitiveOverlapDrawlistImpl(bool save_drawlis
|
||||
if (AreTrianglesQuad<0, 0>(v, idx0, idx1, &tri0, &tri1))
|
||||
{
|
||||
// tri.b is right angle corner
|
||||
GSVector4i corner0 = GSVector4i(v[idx0[tri0.b]].m[1]).upl16().xyxy();
|
||||
GSVector4i corner1 = GSVector4i(v[idx1[tri1.b]].m[1]).upl16().xyxy();
|
||||
bbox = corner0.runion(corner1);
|
||||
bbox = GSVector4i(v[idx0[tri0.b]].m[1]).upl16().xyxy();
|
||||
bbox = bbox.runion(GSVector4i(v[idx1[tri1.b]].m[1]).upl16().xyxy());
|
||||
|
||||
skip = 6;
|
||||
|
||||
got_bbox = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bbox = GSVector4i(v[index[j + 0]].m[1]).upl16().xyxy();
|
||||
bbox = bbox.runion(GSVector4i(v[index[j + 1]].m[1]).upl16().xyxy());
|
||||
bbox = bbox.runion(GSVector4i(v[index[j + 2]].m[1]).upl16().xyxy());
|
||||
|
||||
skip = 3;
|
||||
|
||||
// If we fail a quad check assume the rest are not quads.
|
||||
// If we fail a quad check assume the rest are not quads since the check is relatively expensive.
|
||||
check_quads = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// Default case: just take the bbox of the prim vertices.
|
||||
if (!got_bbox)
|
||||
{
|
||||
bbox = GSVector4i(v[GetIndex(j)].m[1]).upl16().xyxy();
|
||||
for (int k = 1; k < n; k++) // Unroll
|
||||
bbox = bbox.runion(GSVector4i(v[GetIndex(j + k)].m[1]).upl16().xyxy());
|
||||
|
||||
skip = n;
|
||||
|
||||
got_bbox = true;
|
||||
}
|
||||
|
||||
// Avoid degenerate bbox.
|
||||
@@ -5496,6 +5593,11 @@ bool GSState::IsOpaque()
|
||||
return true;
|
||||
|
||||
const GSDrawingContext* context = m_context;
|
||||
const u32 fmsk = GSLocalMemory::m_psm[context->FRAME.PSM].fmsk;
|
||||
|
||||
// If we aren't drawing color, it's equivilant to opaque.
|
||||
if ((context->FRAME.FBMSK & fmsk) == (fmsk & 0x00FFFFFF))
|
||||
return true;
|
||||
|
||||
int amin = 0;
|
||||
int amax = 0xff;
|
||||
|
||||
@@ -244,7 +244,7 @@ const char* GSDevice::RenderAPIToString(RenderAPI api)
|
||||
|
||||
bool GSDevice::GetRequestedExclusiveFullscreenMode(u32* width, u32* height, float* refresh_rate)
|
||||
{
|
||||
const std::string mode = Host::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", "");
|
||||
const std::string mode = Host::GetStringSettingValue("EmuCore/GS", "FullscreenMode", "");
|
||||
if (!mode.empty())
|
||||
{
|
||||
const std::string_view mode_view = mode;
|
||||
@@ -899,14 +899,13 @@ void GSDevice::ShadeBoost()
|
||||
if (ResizeRenderTarget(&m_target_tmp, m_current->GetWidth(), m_current->GetHeight(), false, false))
|
||||
{
|
||||
// predivide to avoid the divide (multiply) in the shader
|
||||
const float params[4] = {
|
||||
const GSVector4 params(
|
||||
static_cast<float>(GSConfig.ShadeBoost_Brightness) * (1.0f / 50.0f),
|
||||
static_cast<float>(GSConfig.ShadeBoost_Contrast) * (1.0f / 50.0f),
|
||||
static_cast<float>(GSConfig.ShadeBoost_Saturation) * (1.0f / 50.0f),
|
||||
static_cast<float>(GSConfig.ShadeBoost_Gamma) * (1.0f / 50.0f),
|
||||
};
|
||||
static_cast<float>(GSConfig.ShadeBoost_Gamma) * (1.0f / 50.0f));
|
||||
|
||||
DoShadeBoost(m_current, m_target_tmp, params);
|
||||
DoShadeBoost(m_current, m_target_tmp, params.v);
|
||||
|
||||
m_current = m_target_tmp;
|
||||
}
|
||||
|
||||
@@ -426,7 +426,8 @@ GSRendererType D3D::GetPreferredRenderer()
|
||||
if (!feature_level.has_value())
|
||||
return GSRendererType::DX11;
|
||||
else if (feature_level == D3D_FEATURE_LEVEL_12_0)
|
||||
return check_vulkan_supported() ? GSRendererType::VK : GSRendererType::OGL;
|
||||
//return check_vulkan_supported() ? GSRendererType::VK : GSRendererType::OGL;
|
||||
return GSRendererType::DX12;
|
||||
else if (feature_level == D3D_FEATURE_LEVEL_11_0)
|
||||
return GSRendererType::OGL;
|
||||
else
|
||||
@@ -439,7 +440,8 @@ GSRendererType D3D::GetPreferredRenderer()
|
||||
if (!feature_level.has_value())
|
||||
return GSRendererType::DX11;
|
||||
else if (feature_level == D3D_FEATURE_LEVEL_12_0)
|
||||
return check_vulkan_supported() ? GSRendererType::VK : GSRendererType::DX12;
|
||||
//return check_vulkan_supported() ? GSRendererType::VK : GSRendererType::DX12;
|
||||
return GSRendererType::DX12;
|
||||
else if (feature_level == D3D_FEATURE_LEVEL_11_1)
|
||||
return GSRendererType::DX12;
|
||||
else
|
||||
|
||||
@@ -1397,7 +1397,7 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
const float right = dRect.z * 2 / ds.x - 1.0f;
|
||||
const float bottom = 1.0f - dRect.w * 2 / ds.y;
|
||||
|
||||
GSVertexPT1 vertices[] =
|
||||
const GSVertexPT1 vertices[] =
|
||||
{
|
||||
{GSVector4(left, top, 0.5f, 1.0f), GSVector2(sRect.x, sRect.y)},
|
||||
{GSVector4(right, top, 0.5f, 1.0f), GSVector2(sRect.z, sRect.y)},
|
||||
@@ -1427,13 +1427,14 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
void GSDevice11::UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize)
|
||||
{
|
||||
// match merge cb
|
||||
struct Uniforms
|
||||
struct alignas(16) Uniforms
|
||||
{
|
||||
float scale;
|
||||
float pad1[3];
|
||||
u32 offsetX, offsetY, dOffset;
|
||||
u32 pad2;
|
||||
};
|
||||
const Uniforms cb = {sScale, {}, offsetX, offsetY, dOffset};
|
||||
const Uniforms cb = {sScale, {}, offsetX, offsetY, dOffset, 0};
|
||||
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
|
||||
|
||||
const GSVector4 dRect(0, 0, dSize, 1);
|
||||
@@ -1444,14 +1445,15 @@ void GSDevice11::UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX, u
|
||||
void GSDevice11::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM)
|
||||
{
|
||||
// match merge cb
|
||||
struct Uniforms
|
||||
struct alignas(16) Uniforms
|
||||
{
|
||||
float scale;
|
||||
float pad1[3];
|
||||
u32 SBW, DBW, SPSM;
|
||||
u32 pad2;
|
||||
};
|
||||
|
||||
const Uniforms cb = {sScale, {}, SBW, DBW, SPSM};
|
||||
const Uniforms cb = {sScale, {}, SBW, DBW, SPSM, 0};
|
||||
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
|
||||
|
||||
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
|
||||
@@ -1461,7 +1463,7 @@ void GSDevice11::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offs
|
||||
|
||||
void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect)
|
||||
{
|
||||
struct Uniforms
|
||||
struct alignas(16) Uniforms
|
||||
{
|
||||
float weight;
|
||||
float step_multiplier;
|
||||
@@ -2063,13 +2065,13 @@ void GSDevice11::RenderImGui()
|
||||
|
||||
UpdateImGuiTextures();
|
||||
|
||||
const float L = 0.0f;
|
||||
constexpr float L = 0.0f;
|
||||
const float R = static_cast<float>(m_window_info.surface_width);
|
||||
const float T = 0.0f;
|
||||
constexpr float T = 0.0f;
|
||||
const float B = static_cast<float>(m_window_info.surface_height);
|
||||
|
||||
// clang-format off
|
||||
const float ortho_projection[4][4] =
|
||||
const GSVector4 ortho_projection[4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
|
||||
@@ -193,11 +193,24 @@ void GSDevice12::LoadAgilitySDK()
|
||||
if (agility_loaded)
|
||||
return;
|
||||
|
||||
HRESULT hr;
|
||||
// On older versions of Windows 10 (example 2019 LTSC) D3D12GetInterface may fail because it doesn't exist,
|
||||
// in such case we can check if D3D12GetInterface exists first.
|
||||
const HMODULE d3d12 = GetModuleHandleW(L"d3d12.dll");
|
||||
if (!d3d12)
|
||||
return;
|
||||
|
||||
using PFN_D3D12GetInterface = HRESULT(WINAPI*)(REFCLSID rclsid, REFIID riid, void** ppv);
|
||||
auto pD3D12GetInterface = reinterpret_cast<PFN_D3D12GetInterface>(GetProcAddress(d3d12, "D3D12GetInterface"));
|
||||
if (!pD3D12GetInterface)
|
||||
{
|
||||
Console.Error("D3D12: Agility SDK configuration is not available");
|
||||
return;
|
||||
}
|
||||
|
||||
// See https://microsoft.github.io/DirectX-Specs/d3d/IndependentDevices.html
|
||||
ComPtr<ID3D12SDKConfiguration1> sdk_configuration;
|
||||
hr = D3D12GetInterface(CLSID_D3D12SDKConfiguration, IID_PPV_ARGS(sdk_configuration.put()));
|
||||
HRESULT hr;
|
||||
hr = pD3D12GetInterface(CLSID_D3D12SDKConfiguration, IID_PPV_ARGS(sdk_configuration.put()));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
Console.Error("D3D12: Agility SDK configuration is not available");
|
||||
@@ -925,6 +938,7 @@ void GSDevice12::SetVSyncMode(GSVSyncMode mode, bool allow_present_throttle)
|
||||
|
||||
if (GetSwapChainBufferCount() != old_buffer_count)
|
||||
{
|
||||
ExecuteCommandList(true);
|
||||
DestroySwapChain();
|
||||
if (!CreateSwapChain())
|
||||
pxFailRel("Failed to recreate swap chain after vsync change.");
|
||||
@@ -1622,14 +1636,14 @@ void GSDevice12::UpdateCLUTTexture(
|
||||
GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize)
|
||||
{
|
||||
// match merge cb
|
||||
struct Uniforms
|
||||
struct alignas(16) Uniforms
|
||||
{
|
||||
float scale;
|
||||
float pad1[3];
|
||||
u32 offsetX, offsetY, dOffset;
|
||||
u32 pad2;
|
||||
};
|
||||
const Uniforms cb = {sScale, {}, offsetX, offsetY, dOffset};
|
||||
const Uniforms cb = {sScale, {}, offsetX, offsetY, dOffset, 0};
|
||||
SetUtilityRootSignature();
|
||||
SetUtilityPushConstants(&cb, sizeof(cb));
|
||||
|
||||
@@ -1643,14 +1657,15 @@ void GSDevice12::ConvertToIndexedTexture(
|
||||
GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM)
|
||||
{
|
||||
// match merge cb
|
||||
struct Uniforms
|
||||
struct alignas(16) Uniforms
|
||||
{
|
||||
float scale;
|
||||
float pad1[3];
|
||||
u32 SBW, DBW, SPSM;
|
||||
u32 pad2;
|
||||
};
|
||||
|
||||
const Uniforms cb = {sScale, {}, SBW, DBW, SPSM};
|
||||
const Uniforms cb = {sScale, {}, SBW, DBW, SPSM, 0};
|
||||
SetUtilityRootSignature();
|
||||
SetUtilityPushConstants(&cb, sizeof(cb));
|
||||
|
||||
@@ -1662,7 +1677,7 @@ void GSDevice12::ConvertToIndexedTexture(
|
||||
|
||||
void GSDevice12::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect)
|
||||
{
|
||||
struct Uniforms
|
||||
struct alignas(16) Uniforms
|
||||
{
|
||||
float weight;
|
||||
float step_multiplier;
|
||||
@@ -2171,7 +2186,7 @@ void GSDevice12::RenderImGui()
|
||||
const float B = static_cast<float>(m_window_info.surface_height);
|
||||
|
||||
// clang-format off
|
||||
const float ortho_projection[4][4] =
|
||||
const GSVector4 ortho_projection[4] =
|
||||
{
|
||||
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },
|
||||
|
||||
@@ -165,11 +165,12 @@ GSTexture* GSRendererHW::GetOutput(int i, float& scale, int& y_offset)
|
||||
|
||||
if (GSTextureCache::Target* rt = g_texture_cache->LookupDisplayTarget(TEX0, framebufferSize, GetTextureScaleFactor(), false))
|
||||
{
|
||||
const u32 bp_adj = (TEX0.TBP0 < rt->m_TEX0.TBP0 && rt->UnwrappedEndBlock() > GS_MAX_BLOCKS) ? (TEX0.TBP0 + GS_MAX_BLOCKS) : TEX0.TBP0;
|
||||
rt->Update();
|
||||
t = rt->m_texture;
|
||||
scale = rt->m_scale;
|
||||
|
||||
const int delta = TEX0.TBP0 - rt->m_TEX0.TBP0;
|
||||
const int delta = bp_adj - rt->m_TEX0.TBP0;
|
||||
if (delta > 0 && curFramebuffer.FBW != 0)
|
||||
{
|
||||
const int pages = delta >> 5u;
|
||||
@@ -2338,6 +2339,12 @@ void GSRendererHW::Draw()
|
||||
return;
|
||||
}
|
||||
|
||||
// Sometimes everything will get reset and it will draw a single black point in the top left corner,
|
||||
// which can cause invalid targets to be created, so might as well skip it.
|
||||
if (GSVector4i(m_vt.m_min.p.xyxy(m_vt.m_max.p)).eq(GSVector4i::zero()) && m_vt.m_eq.rgba == 0xffff &&
|
||||
m_vt.m_max.c.rgba32() == 0 && m_draw_env->PRIM.PRIM == GS_POINTLIST && m_env.PRIM.PRIM != GS_POINTLIST)
|
||||
return;
|
||||
|
||||
// Channel shuffles repeat lots of draws. Get out early if we can.
|
||||
if (m_channel_shuffle)
|
||||
{
|
||||
@@ -2844,7 +2851,7 @@ void GSRendererHW::Draw()
|
||||
const bool page_aligned = (m_r.w % pgs.y) == (pgs.y - 1) || (m_r.w % pgs.y) == 0;
|
||||
const bool is_zero_color_clear = (GetConstantDirectWriteMemClearColor() == 0 && !preserve_rt_color && page_aligned);
|
||||
const bool is_zero_depth_clear = (GetConstantDirectWriteMemClearDepth() == 0 && !preserve_depth && page_aligned);
|
||||
|
||||
bool gs_mem_cleared = false;
|
||||
// If it's an invalid-sized draw, do the mem clear on the CPU, we don't want to create huge targets.
|
||||
// If clearing to zero, don't bother creating the target. Games tend to clear more than they use, wasting VRAM/bandwidth.
|
||||
if (is_zero_color_clear || is_zero_depth_clear || height_invalid)
|
||||
@@ -2876,7 +2883,7 @@ void GSRendererHW::Draw()
|
||||
{
|
||||
g_texture_cache->InvalidateTemporaryZ();
|
||||
}
|
||||
|
||||
gs_mem_cleared |= overwriting_whole_rt && overwriting_whole_ds && (!no_rt || !no_ds);
|
||||
if (overwriting_whole_rt && overwriting_whole_ds &&
|
||||
TryGSMemClear(no_rt, preserve_rt_color, is_zero_color_clear, rt_end_bp,
|
||||
no_ds, preserve_depth, is_zero_depth_clear, ds_end_bp))
|
||||
@@ -2906,6 +2913,27 @@ void GSRendererHW::Draw()
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If not a zero clear or the RT's aren't fully overwritten, we need to see if this is clearing for a future operation.
|
||||
// So if the FBP or Z being cleared isn't getting used next frame, clear the actual GS memory.
|
||||
if (!gs_mem_cleared)
|
||||
{
|
||||
const int get_next_ctx = m_env.PRIM.CTXT;
|
||||
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
|
||||
if ((!no_rt && next_ctx.FRAME.FBP != m_cached_ctx.FRAME.FBP) || (!no_ds && next_ctx.ZBUF.ZBP != m_cached_ctx.ZBUF.ZBP))
|
||||
{
|
||||
bool frame_masked = no_rt || (m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) || !IsOpaque() || !IsRTWritten();
|
||||
const bool z_masked = no_ds || m_cached_ctx.ZBUF.ZMSK;
|
||||
|
||||
if (frame_masked && m_cached_ctx.FRAME.PSM == PSMCT32 && m_cached_ctx.FRAME.FBMSK == 0xFF000000u)
|
||||
{
|
||||
frame_masked = no_rt || !IsOpaque() || !IsRTWritten();
|
||||
}
|
||||
|
||||
// Force clear of memory but don't invalidate anything.
|
||||
TryGSMemClear(frame_masked, false, false, 0, z_masked, false, false, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GIFRegTEX0 TEX0 = {};
|
||||
@@ -3215,6 +3243,7 @@ void GSRendererHW::Draw()
|
||||
float target_scale = GetTextureScaleFactor();
|
||||
bool scaled_copy = false;
|
||||
int scale_draw = IsScalingDraw(src, m_primitive_covers_without_gaps != NoGapsType::GapsFound);
|
||||
m_downscale_source = false;
|
||||
|
||||
if (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off)
|
||||
{
|
||||
@@ -3248,8 +3277,6 @@ void GSRendererHW::Draw()
|
||||
scale_draw = 1;
|
||||
scaled_copy = true;
|
||||
}
|
||||
|
||||
m_downscale_source = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5168,7 +5195,9 @@ void GSRendererHW::EmulateZbuffer(const GSTextureCache::Target* ds)
|
||||
m_conf.cb_vs.max_depth = GSVector2i(0xFFFFFFFF);
|
||||
//ps_cb.MaxDepth = GSVector4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
m_conf.ps.zclamp = 0;
|
||||
m_conf.ps.zfloor = !m_cached_ctx.ZBUF.ZMSK;
|
||||
m_conf.ps.zfloor = !m_vt.m_eq.z &&
|
||||
(m_vt.m_primclass == GS_TRIANGLE_CLASS || m_vt.m_primclass == GS_LINE_CLASS) &&
|
||||
(m_cached_ctx.DepthWrite() || (m_cached_ctx.DepthRead() && m_cached_ctx.TEST.ZTST == ZTST_GREATER));
|
||||
|
||||
if (clamp_z)
|
||||
{
|
||||
@@ -8935,17 +8964,17 @@ bool GSRendererHW::TryGSMemClear(bool no_rt, bool preserve_rt, bool invalidate_r
|
||||
if (m_r.width() < ((static_cast<int>(m_cached_ctx.FRAME.FBW) - 1) * 64))
|
||||
return false;
|
||||
|
||||
if (!no_rt && !preserve_rt)
|
||||
if (!no_rt && (!preserve_rt || (IsOpaque() && m_cached_ctx.FRAME.FBMSK)))
|
||||
{
|
||||
ClearGSLocalMemory(m_context->offset.fb, m_r, GetConstantDirectWriteMemClearColor());
|
||||
|
||||
if (invalidate_rt)
|
||||
if (invalidate_rt && !preserve_rt)
|
||||
{
|
||||
g_texture_cache->InvalidateVideoMem(m_context->offset.fb, m_r, false);
|
||||
g_texture_cache->InvalidateContainedTargets(
|
||||
GSLocalMemory::GetStartBlockAddress(
|
||||
m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r),
|
||||
rt_end_bp, m_cached_ctx.FRAME.PSM, m_cached_ctx.FRAME.FBW);
|
||||
rt_end_bp, m_cached_ctx.FRAME.PSM, m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.FBMSK);
|
||||
|
||||
GSUploadQueue clear_queue;
|
||||
clear_queue.draw = s_n;
|
||||
@@ -8956,6 +8985,13 @@ bool GSRendererHW::TryGSMemClear(bool no_rt, bool preserve_rt, bool invalidate_r
|
||||
clear_queue.zero_clear = true;
|
||||
m_draw_transfers.push_back(clear_queue);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_texture_cache->InvalidateContainedTargets(
|
||||
GSLocalMemory::GetStartBlockAddress(
|
||||
m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r),
|
||||
rt_end_bp, m_cached_ctx.FRAME.PSM, m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.FBMSK, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!no_ds && !preserve_z)
|
||||
@@ -8969,6 +9005,15 @@ bool GSRendererHW::TryGSMemClear(bool no_rt, bool preserve_rt, bool invalidate_r
|
||||
GSLocalMemory::GetStartBlockAddress(
|
||||
m_cached_ctx.ZBUF.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.ZBUF.PSM, m_r),
|
||||
ds_end_bp, m_cached_ctx.ZBUF.PSM, m_cached_ctx.FRAME.FBW);
|
||||
|
||||
GSUploadQueue clear_queue;
|
||||
clear_queue.draw = s_n;
|
||||
clear_queue.rect = m_r;
|
||||
clear_queue.blit.DBP = m_cached_ctx.ZBUF.Block();
|
||||
clear_queue.blit.DBW = m_cached_ctx.FRAME.FBW;
|
||||
clear_queue.blit.DPSM = m_cached_ctx.ZBUF.PSM;
|
||||
clear_queue.zero_clear = true;
|
||||
m_draw_transfers.push_back(clear_queue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8987,6 +9032,7 @@ void GSRendererHW::ClearGSLocalMemory(const GSOffset& off, const GSVector4i& r,
|
||||
const int right = r.right;
|
||||
const int bottom = r.bottom;
|
||||
int top = r.top;
|
||||
u32 drawing_mask = GSLocalMemory::m_psm[psm].depth ? 0x0 : m_cached_ctx.FRAME.FBMSK;
|
||||
|
||||
// Process the page aligned region first, then fall back to anything which is not.
|
||||
// Since pages are linear in memory, we can do it basically with a vector memset.
|
||||
@@ -9002,22 +9048,34 @@ void GSRendererHW::ClearGSLocalMemory(const GSOffset& off, const GSVector4i& r,
|
||||
|
||||
if (format == GSLocalMemory::PSM_FMT_32)
|
||||
{
|
||||
const GSVector4i vcolor = GSVector4i(vert_color);
|
||||
const GSVector4i vcolor = GSVector4i(vert_color & ~drawing_mask);
|
||||
const u32 iterations_per_page = (pages_wide * pixels_per_page) / 4;
|
||||
const GSVector4i mask = GSVector4i(drawing_mask);
|
||||
pxAssert((off.bp() & (GS_BLOCKS_PER_PAGE - 1)) == 0);
|
||||
for (u32 current_page = off.bp() >> 5; top < page_aligned_bottom; top += pgs.y, current_page += fbw)
|
||||
{
|
||||
current_page &= (GS_MAX_PAGES - 1);
|
||||
GSVector4i* ptr = reinterpret_cast<GSVector4i*>(m_mem.vm8() + current_page * GS_PAGE_SIZE);
|
||||
GSVector4i* const ptr_end = ptr + iterations_per_page;
|
||||
while (ptr != ptr_end)
|
||||
*(ptr++) = vcolor;
|
||||
if (drawing_mask)
|
||||
{
|
||||
while (ptr != ptr_end)
|
||||
{
|
||||
*ptr = (*ptr & mask) | vcolor;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (ptr != ptr_end)
|
||||
*(ptr++) = vcolor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (format == GSLocalMemory::PSM_FMT_24)
|
||||
{
|
||||
const GSVector4i mask = GSVector4i::xff000000();
|
||||
const GSVector4i vcolor = GSVector4i(vert_color & 0x00ffffffu);
|
||||
const GSVector4i mask = GSVector4i::xff000000() | GSVector4i(drawing_mask);
|
||||
const GSVector4i vcolor = GSVector4i((vert_color & 0x00ffffffu) & ~drawing_mask);
|
||||
const u32 iterations_per_page = (pages_wide * pixels_per_page) / 4;
|
||||
pxAssert((off.bp() & (GS_BLOCKS_PER_PAGE - 1)) == 0);
|
||||
for (u32 current_page = off.bp() >> 5; top < page_aligned_bottom; top += pgs.y, current_page += fbw)
|
||||
@@ -9036,7 +9094,10 @@ void GSRendererHW::ClearGSLocalMemory(const GSOffset& off, const GSVector4i& r,
|
||||
{
|
||||
const u16 converted_color = ((vert_color >> 16) & 0x8000) | ((vert_color >> 9) & 0x7C00) |
|
||||
((vert_color >> 6) & 0x7E0) | ((vert_color >> 3) & 0x1F);
|
||||
const u16 converted_mask = ((drawing_mask >> 16) & 0x8000) | ((drawing_mask >> 9) & 0x7C00) |
|
||||
((drawing_mask >> 6) & 0x7E0) | ((drawing_mask >> 3) & 0x1F);
|
||||
const GSVector4i vcolor = GSVector4i::broadcast16(converted_color);
|
||||
const GSVector4i mask = GSVector4i::broadcast16(converted_mask);
|
||||
const u32 iterations_per_page = (pages_wide * pixels_per_page) / 8;
|
||||
pxAssert((off.bp() & (GS_BLOCKS_PER_PAGE - 1)) == 0);
|
||||
for (u32 current_page = off.bp() >> 5; top < page_aligned_bottom; top += pgs.y, current_page += fbw)
|
||||
@@ -9044,14 +9105,27 @@ void GSRendererHW::ClearGSLocalMemory(const GSOffset& off, const GSVector4i& r,
|
||||
current_page &= (GS_MAX_PAGES - 1);
|
||||
GSVector4i* ptr = reinterpret_cast<GSVector4i*>(m_mem.vm8() + current_page * GS_PAGE_SIZE);
|
||||
GSVector4i* const ptr_end = ptr + iterations_per_page;
|
||||
while (ptr != ptr_end)
|
||||
*(ptr++) = vcolor;
|
||||
if (converted_mask)
|
||||
{
|
||||
while (ptr != ptr_end)
|
||||
{
|
||||
*ptr = (*ptr & mask) | vcolor;
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (ptr != ptr_end)
|
||||
*(ptr++) = vcolor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (format == GSLocalMemory::PSM_FMT_32)
|
||||
{
|
||||
const u32 mask = drawing_mask;
|
||||
const u32 vcolor = vert_color & ~mask;
|
||||
// Based on WritePixel32
|
||||
u32* vm = m_mem.vm32();
|
||||
for (int y = top; y < bottom; y++)
|
||||
@@ -9059,25 +9133,28 @@ void GSRendererHW::ClearGSLocalMemory(const GSOffset& off, const GSVector4i& r,
|
||||
GSOffset::PAHelper pa = off.assertSizesMatch(GSLocalMemory::swizzle32).paMulti(0, y);
|
||||
|
||||
for (int x = left; x < right; x++)
|
||||
vm[pa.value(x)] = vert_color;
|
||||
vm[pa.value(x)] = vcolor | (vm[pa.value(x)] & mask);
|
||||
}
|
||||
}
|
||||
else if (format == GSLocalMemory::PSM_FMT_24)
|
||||
{
|
||||
// Based on WritePixel24
|
||||
u32* vm = m_mem.vm32();
|
||||
const u32 write_color = vert_color & 0xffffffu;
|
||||
const u32 mask = drawing_mask | 0xff000000u;
|
||||
const u32 write_color = (vert_color & 0xffffffu) & ~mask;
|
||||
for (int y = top; y < bottom; y++)
|
||||
{
|
||||
GSOffset::PAHelper pa = off.assertSizesMatch(GSLocalMemory::swizzle32).paMulti(0, y);
|
||||
|
||||
for (int x = left; x < right; x++)
|
||||
vm[pa.value(x)] = (vm[pa.value(x)] & 0xff000000u) | write_color;
|
||||
vm[pa.value(x)] = (vm[pa.value(x)] & mask) | write_color;
|
||||
}
|
||||
}
|
||||
else if (format == GSLocalMemory::PSM_FMT_16)
|
||||
{
|
||||
const u16 converted_color = ((vert_color >> 16) & 0x8000) | ((vert_color >> 9) & 0x7C00) | ((vert_color >> 6) & 0x7E0) | ((vert_color >> 3) & 0x1F);
|
||||
const u16 converted_mask = ((drawing_mask >> 16) & 0x8000) | ((drawing_mask >> 9) & 0x7C00) |
|
||||
((drawing_mask >> 6) & 0x7E0) | ((drawing_mask >> 3) & 0x1F);
|
||||
const u16 converted_color = (((vert_color >> 16) & 0x8000) | ((vert_color >> 9) & 0x7C00) | ((vert_color >> 6) & 0x7E0) | ((vert_color >> 3) & 0x1F)) & ~converted_mask;
|
||||
|
||||
// Based on WritePixel16
|
||||
u16* vm = m_mem.vm16();
|
||||
@@ -9086,7 +9163,7 @@ void GSRendererHW::ClearGSLocalMemory(const GSOffset& off, const GSVector4i& r,
|
||||
GSOffset::PAHelper pa = off.assertSizesMatch(GSLocalMemory::swizzle16).paMulti(0, y);
|
||||
|
||||
for (int x = left; x < right; x++)
|
||||
vm[pa.value(x)] = converted_color;
|
||||
vm[pa.value(x)] = converted_color | (vm[pa.value(x)] & converted_mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1788,8 +1788,10 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
(GSLocalMemory::m_psm[color_psm].bpp >= 16 || (/*possible_shuffle &&*/ GSLocalMemory::m_psm[color_psm].bpp == 8 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp >= 16)) && // Channel shuffles or non indexed lookups.
|
||||
t->m_age <= 1 && (!found_t || t->m_last_draw > dst->m_last_draw) /*&& CanTranslate(bp, bw, psm, block_boundary_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW)*/)
|
||||
{
|
||||
const u32 end_block = GSLocalMemory::GetEndBlockAddress(bp, TEX0.TBW, TEX0.PSM, r);
|
||||
const u32 adj_bp = (end_block < t->m_TEX0.TBP0 && t->UnwrappedEndBlock() > GS_MAX_BLOCKS) ? (bp + GS_MAX_BLOCKS) : bp;
|
||||
u32 rt_tbw = std::max(1U, t->m_TEX0.TBW);
|
||||
u32 horz_page_offset = ((bp - t->m_TEX0.TBP0) >> 5) % rt_tbw;
|
||||
u32 horz_page_offset = ((adj_bp - t->m_TEX0.TBP0) >> 5) % rt_tbw;
|
||||
|
||||
if (GSLocalMemory::m_psm[psm].bpp == GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp && bw != rt_tbw && block_boundary_rect.height() > GSLocalMemory::m_psm[psm].pgs.y)
|
||||
continue;
|
||||
@@ -1802,7 +1804,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
((t->m_TEX0.TBW < (horz_page_offset + ((block_boundary_rect.z + GSLocalMemory::m_psm[psm].pgs.x - 1) / GSLocalMemory::m_psm[psm].pgs.x)) ||
|
||||
(t->m_TEX0.TBW != bw && block_boundary_rect.w > GSLocalMemory::m_psm[psm].pgs.y))))
|
||||
{
|
||||
DbgCon.Warning("BP %x - 16bit bad match for target bp %x bw %d src %d format %d", bp, t->m_TEX0.TBP0, t->m_TEX0.TBW, bw, t->m_TEX0.PSM);
|
||||
DbgCon.Warning("BP %x - 16bit bad match for target bp %x bw %d src %d format %d", adj_bp, t->m_TEX0.TBP0, t->m_TEX0.TBW, bw, t->m_TEX0.PSM);
|
||||
continue;
|
||||
}
|
||||
// Keep note that 2 bw is basically 1 normal page, as bw is in 64 pixels, and 8bit pages are 128 pixels wide, aka 2 bw.
|
||||
@@ -1814,7 +1816,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
((GSLocalMemory::m_psm[psm].bpp == 32) ? bw : ((bw + 1) / 2)) <= t->m_TEX0.TBW) &&
|
||||
!(((GSLocalMemory::m_psm[psm].bpp == 32) ? bw : ((bw + 1) / 2)) == rt_tbw)))))
|
||||
{
|
||||
DbgCon.Warning("BP %x - 8bit bad match for target bp %x bw %d src %d format %d", bp, t->m_TEX0.TBP0, t->m_TEX0.TBW, bw, t->m_TEX0.PSM);
|
||||
DbgCon.Warning("BP %x - 8bit bad match for target bp %x bw %d src %d format %d", adj_bp, t->m_TEX0.TBP0, t->m_TEX0.TBW, bw, t->m_TEX0.PSM);
|
||||
continue;
|
||||
}
|
||||
else if (!possible_shuffle && GSLocalMemory::m_psm[psm].bpp <= 8 && TEX0.TBW == 1)
|
||||
@@ -1852,16 +1854,16 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
else // Formats are not compatible for normal draws, only shuffles.
|
||||
continue;
|
||||
}
|
||||
if (bp > t->m_TEX0.TBP0)
|
||||
if (adj_bp > t->m_TEX0.TBP0)
|
||||
{
|
||||
if (!region.HasEither() && GSLocalMemory::m_psm[psm].bpp == 32 && (t->m_TEX0.TBW - (((bp - t->m_TEX0.TBP0) >> 5) % rt_tbw)) < static_cast<u32>((block_boundary_rect.width() + 63) / 64))
|
||||
if (!region.HasEither() && GSLocalMemory::m_psm[psm].bpp == 32 && (t->m_TEX0.TBW - (((adj_bp - t->m_TEX0.TBP0) >> 5) % rt_tbw)) < static_cast<u32>((block_boundary_rect.width() + 63) / 64))
|
||||
{
|
||||
DbgCon.Warning("Bad alignmenet");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure it's inside if not a shuffle, sometimes valid areas can get messy, like TOCA Race Driver 2 where it goes over to 480, but it's rounded up to 512 in the shuffle.
|
||||
if (!possible_shuffle && !t->Inside(bp, bw, psm, block_boundary_rect))
|
||||
if (!possible_shuffle && !t->Inside(adj_bp, bw, psm, block_boundary_rect))
|
||||
continue;
|
||||
|
||||
GSVector4i new_rect = (GSLocalMemory::m_psm[color_psm].bpp != GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp && (psm & 0x7) != PSMCT16) ? block_boundary_rect : rect;
|
||||
@@ -1871,7 +1873,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
// Hitman Blood Money is an example of this in the theatre.
|
||||
const u32 rt_tbw = (possible_shuffle || bw == 1 || GSUtil::GetChannelMask(psm) != 0x8 || frame.FBW <= bw || frame.FBW == t->m_TEX0.TBW || bw == t->m_TEX0.TBW) ? t->m_TEX0.TBW : frame.FBW;
|
||||
|
||||
const bool can_translate = CanTranslate(bp, bw, src_psm, new_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, rt_tbw);
|
||||
const bool can_translate = CanTranslate(adj_bp, bw, src_psm, new_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, rt_tbw);
|
||||
if (can_translate)
|
||||
{
|
||||
const bool swizzle_match = GSLocalMemory::m_psm[src_psm].depth == GSLocalMemory::m_psm[t->m_TEX0.PSM].depth;
|
||||
@@ -1881,7 +1883,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
|
||||
if (swizzle_match)
|
||||
{
|
||||
rect = TranslateAlignedRectByPage(t->m_TEX0.TBP0, t->m_end_block, rt_tbw, t->m_TEX0.PSM, t->m_valid, bp, src_psm, bw, new_rect);
|
||||
rect = TranslateAlignedRectByPage(t->m_TEX0.TBP0, t->m_end_block, rt_tbw, t->m_TEX0.PSM, t->m_valid, adj_bp, src_psm, bw, new_rect);
|
||||
rect.x -= new_rect.x;
|
||||
rect.y -= new_rect.y;
|
||||
}
|
||||
@@ -1901,7 +1903,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
new_rect.z = (new_rect.z + (page_size.x - 1)) & ~(page_size.x - 1);
|
||||
new_rect.w = (new_rect.w + (page_size.y - 1)) & ~(page_size.y - 1);
|
||||
}
|
||||
rect = TranslateAlignedRectByPage(t, bp & ~((1 << 5) - 1), src_psm, bw, new_rect);
|
||||
rect = TranslateAlignedRectByPage(t, adj_bp & ~((1 << 5) - 1), src_psm, bw, new_rect);
|
||||
rect.x -= new_rect.x & ~(page_size.x - 1);
|
||||
rect.y -= new_rect.y & ~(page_size.y - 1);
|
||||
}
|
||||
@@ -1933,7 +1935,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
}
|
||||
else
|
||||
{
|
||||
SurfaceOffset so = ComputeSurfaceOffset(bp, bw, src_psm, new_rect, t);
|
||||
SurfaceOffset so = ComputeSurfaceOffset(adj_bp, bw, src_psm, new_rect, t);
|
||||
if (!so.is_valid && t->Wraps())
|
||||
{
|
||||
// Improves Beyond Good & Evil shadow.
|
||||
@@ -2692,10 +2694,12 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
for (auto i = list.begin(); i != list.end(); ++i)
|
||||
{
|
||||
Target* t = *i;
|
||||
const u32 end_block = GSLocalMemory::GetEndBlockAddress(bp, TEX0.TBW, TEX0.PSM, GSVector4i(0, size.y, size.x, size.y + 1));
|
||||
const u32 bp_adj = (end_block < t->m_TEX0.TBP0 && t->UnwrappedEndBlock() > GS_MAX_BLOCKS) ? (bp + GS_MAX_BLOCKS) : bp;
|
||||
const bool half_buffer_match = GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets && TEX0.TBW == t->m_TEX0.TBW && TEX0.PSM == t->m_TEX0.PSM &&
|
||||
bp == GSLocalMemory::GetStartBlockAddress(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, GSVector4i(0, size.y, size.x, size.y + 1));
|
||||
// Make sure the target is inside the texture
|
||||
if (t->m_TEX0.TBP0 <= bp && bp <= t->m_end_block && (half_buffer_match || t->Inside(bp, TEX0.TBW, TEX0.PSM, GSVector4i::loadh(size))))
|
||||
if (t->m_TEX0.TBP0 <= bp_adj && bp_adj <= t->UnwrappedEndBlock() && (half_buffer_match || t->Inside(bp_adj, TEX0.TBW, TEX0.PSM, GSVector4i::loadh(size))))
|
||||
{
|
||||
if (dst && (GSState::s_n - dst->m_last_draw) < (GSState::s_n - t->m_last_draw))
|
||||
continue;
|
||||
@@ -4306,23 +4310,27 @@ bool GSTextureCache::PrepareDownloadTexture(u32 width, u32 height, GSTexture::Fo
|
||||
}
|
||||
}
|
||||
}*/
|
||||
void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 write_psm, u32 write_bw)
|
||||
void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 write_psm, u32 write_bw, u32 fb_mask, bool ignore_exact)
|
||||
{
|
||||
const bool preserve_alpha = (GSLocalMemory::m_psm[write_psm].trbpp == 24);
|
||||
for (int type = 0; type < 2; type++)
|
||||
const bool preserve_alpha = (GSLocalMemory::m_psm[write_psm].trbpp == 24) || (fb_mask & 0xFF000000);
|
||||
for (int type = 0; type < (ignore_exact ? 1 : 2); type++)
|
||||
{
|
||||
auto& list = m_dst[type];
|
||||
for (auto i = list.begin(); i != list.end();)
|
||||
{
|
||||
Target* const t = *i;
|
||||
if (start_bp != t->m_TEX0.TBP0 && (t->m_TEX0.TBP0 > end_bp || t->UnwrappedEndBlock() < start_bp))
|
||||
|
||||
if ((ignore_exact && start_bp == t->m_TEX0.TBP0) || (start_bp != t->m_TEX0.TBP0 && (t->m_TEX0.TBP0 > end_bp || t->UnwrappedEndBlock() < start_bp)))
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool compatible_fmt = GSUtil::HasCompatibleBits(t->m_TEX0.PSM, write_psm);
|
||||
const bool compatible_width = std::max(t->m_TEX0.TBW, 1U) == std::max(write_bw, 1U);
|
||||
|
||||
// If not fully contained but they are aligned and or clean, just dirty the area.
|
||||
if (type != DepthStencil && start_bp != t->m_TEX0.TBP0 && (t->m_TEX0.TBP0 < start_bp || t->UnwrappedEndBlock() > end_bp))
|
||||
if ((type != DepthStencil || !compatible_fmt || !compatible_width) && start_bp != t->m_TEX0.TBP0 && (t->m_TEX0.TBP0 < start_bp || t->UnwrappedEndBlock() > end_bp))
|
||||
{
|
||||
const u32 offset = (std::abs(static_cast<int>(start_bp - t->m_TEX0.TBP0)) >> 5) % std::max(1U, t->m_TEX0.TBW);
|
||||
const GSVector4i dirty_rect = t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size).rintersect(t->m_valid);
|
||||
@@ -4338,7 +4346,7 @@ void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 wr
|
||||
{
|
||||
|
||||
RGBAMask mask;
|
||||
mask._u32 = GSUtil::GetChannelMask(write_psm);
|
||||
mask._u32 = GSUtil::GetChannelMask(write_psm, fb_mask);
|
||||
AddDirtyRectTarget(t, invalidate_r, t->m_TEX0.PSM, t->m_TEX0.TBW, mask, false);
|
||||
}
|
||||
|
||||
@@ -4368,7 +4376,7 @@ void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 wr
|
||||
|
||||
t->m_valid_alpha_low &= preserve_alpha;
|
||||
t->m_valid_alpha_high &= preserve_alpha;
|
||||
t->m_valid_rgb = false;
|
||||
t->m_valid_rgb &= (fb_mask & 0x00FFFFFF) != 0;
|
||||
|
||||
// Don't keep partial depth buffers around.
|
||||
if ((!t->m_valid_alpha_low && !t->m_valid_alpha_high && !t->m_valid_rgb) || type == DepthStencil)
|
||||
@@ -4390,6 +4398,16 @@ void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 wr
|
||||
delete t;
|
||||
continue;
|
||||
}
|
||||
else if (ignore_exact && GSUtil::HasCompatibleBits(t->m_TEX0.PSM, write_psm))
|
||||
{
|
||||
RGBAMask mask;
|
||||
mask._u32 = GSUtil::GetChannelMask(write_psm, fb_mask);
|
||||
|
||||
AddDirtyRectTarget(t, t->m_valid, t->m_TEX0.PSM, t->m_TEX0.TBW, mask, false);
|
||||
t->m_valid_rgb |= !!(mask._u32 & 0x7);
|
||||
t->m_valid_alpha_low |= mask.c.a;
|
||||
t->m_valid_alpha_high |= mask.c.a;
|
||||
}
|
||||
|
||||
GL_CACHE("TC: InvalidateContainedTargets: Clear RGB valid on %s[%x, %s]", to_string(type), t->m_TEX0.TBP0, GSUtil::GetPSMName(t->m_TEX0.PSM));
|
||||
++i;
|
||||
@@ -5073,14 +5091,14 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
|
||||
// We use dx/dy == 0 and the TBW check as a safeguard to make sure these go through to local memory.
|
||||
// We can also recreate the target if it's previously been created in the height cache with a valid size.
|
||||
// Good test case for this is the Xenosaga I cutscene transitions, or Gradius V.
|
||||
if (src && !dst && ((dx == 0 && dy == 0 && ((static_cast<u32>(w) + 63) / 64) <= DBW) || HasTargetInHeightCache(DBP, DBW, DPSM, 10)))
|
||||
if (src && !dst && ((((dx == 0 && dy == 0) || (dx == sx && dy == sy && DBW == src->m_TEX0.TBW)) && ((static_cast<u32>(w) + 63) / 64) <= DBW) || HasTargetInHeightCache(DBP, DBW, DPSM, 10)))
|
||||
{
|
||||
GIFRegTEX0 new_TEX0 = {};
|
||||
new_TEX0.TBP0 = DBP;
|
||||
new_TEX0.TBW = DBW;
|
||||
new_TEX0.PSM = DPSM;
|
||||
|
||||
const GSVector2i target_size = GetTargetSize(DBP, DBW, DPSM, Common::AlignUpPow2(w, 64), h);
|
||||
const GSVector2i target_size = (dx == 0 && dy == 0) ? GetTargetSize(DBP, DBW, DPSM, Common::AlignUpPow2(w, 64), h) : GSVector2i(src->m_valid.z, src->m_valid.w);
|
||||
dst = LookupTarget(new_TEX0, target_size, src->m_scale, src->m_type);
|
||||
if (!dst)
|
||||
{
|
||||
|
||||
@@ -32,8 +32,18 @@ public:
|
||||
|
||||
constexpr static bool CheckOverlap(const u32 a_bp, const u32 a_bp_end, const u32 b_bp, const u32 b_bp_end) noexcept
|
||||
{
|
||||
const bool valid = a_bp <= a_bp_end && b_bp <= b_bp_end;
|
||||
const bool overlap = a_bp <= b_bp_end && a_bp_end >= b_bp;
|
||||
u32 b_bp_start_synced = b_bp;
|
||||
u32 b_bp_end_synced = b_bp_end;
|
||||
|
||||
// Check for wrapping
|
||||
if (a_bp_end > GS_MAX_BLOCKS && b_bp_end < a_bp)
|
||||
{
|
||||
b_bp_start_synced += GS_MAX_BLOCKS;
|
||||
b_bp_end_synced += GS_MAX_BLOCKS;
|
||||
}
|
||||
|
||||
const bool valid = a_bp <= a_bp_end && b_bp_start_synced <= b_bp_end_synced;
|
||||
const bool overlap = a_bp <= b_bp_end_synced && a_bp_end >= b_bp_start_synced;
|
||||
return valid && overlap;
|
||||
}
|
||||
|
||||
@@ -522,7 +532,7 @@ public:
|
||||
bool HasTargetInHeightCache(u32 bp, u32 fbw, u32 psm, u32 max_age = std::numeric_limits<u32>::max(), bool move_front = true);
|
||||
bool Has32BitTarget(u32 bp);
|
||||
|
||||
void InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 write_psm = PSMCT32, u32 write_bw = 1);
|
||||
void InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 write_psm = PSMCT32, u32 write_bw = 1, u32 fb_mask = 0x00000000, bool ignore_exact = false);
|
||||
void InvalidateVideoMemType(int type, u32 bp, u32 write_psm = PSMCT32, u32 write_fbmsk = 0, bool dirty_only = false);
|
||||
void InvalidateVideoMemSubTarget(GSTextureCache::Target* rt);
|
||||
void InvalidateVideoMem(const GSOffset& off, const GSVector4i& r, bool target = true);
|
||||
|
||||
@@ -770,6 +770,11 @@ bool GSDeviceOGL::CheckFeatures()
|
||||
m_features.line_expand ? "hardware" : (m_features.vs_expand ? "vertex expanding" : "UNSUPPORTED"),
|
||||
m_features.vs_expand ? "vertex expanding" : "CPU");
|
||||
|
||||
if (!GLAD_GL_ARB_conservative_depth)
|
||||
{
|
||||
Console.Warning("GLAD_GL_ARB_conservative_depth is not supported. This will reduce performance.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1293,6 +1298,16 @@ std::string GSDeviceOGL::GenGlslHeader(const std::string_view entry, GLenum type
|
||||
else
|
||||
header += "#define HAS_FRAMEBUFFER_FETCH 0\n";
|
||||
|
||||
if (GLAD_GL_ARB_conservative_depth)
|
||||
{
|
||||
header += "#extension GL_ARB_conservative_depth : enable\n";
|
||||
header += "#define HAS_CONSERVATIVE_DEPTH 1\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
header += "#define HAS_CONSERVATIVE_DEPTH 0\n";
|
||||
}
|
||||
|
||||
// Allow to puts several shader in 1 files
|
||||
switch (type)
|
||||
{
|
||||
|
||||
@@ -481,72 +481,26 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(m_physical_device, &queue_family_count, queue_family_properties.data());
|
||||
DevCon.WriteLn("%u vulkan queue families", queue_family_count);
|
||||
|
||||
std::vector<uint32_t> queue_family_users(queue_family_count, 0);
|
||||
|
||||
// Find graphics and present queues.
|
||||
m_graphics_queue_family_index = queue_family_count;
|
||||
m_present_queue_family_index = queue_family_count;
|
||||
u32 present_queue_index = 0;
|
||||
m_spin_queue_family_index = queue_family_count;
|
||||
u32 spin_queue_index = 0;
|
||||
|
||||
// Graphics Queue
|
||||
for (uint32_t i = 0; i < queue_family_count; i++)
|
||||
{
|
||||
if (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
||||
VkBool32 graphics_supported = queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT;
|
||||
if (graphics_supported)
|
||||
{
|
||||
m_graphics_queue_family_index = i;
|
||||
queue_family_users[i]++;
|
||||
break;
|
||||
// Quit now, no need for a present queue.
|
||||
if (!surface)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Spinwait Queue
|
||||
for (uint32_t i = 0; i < queue_family_count; i++)
|
||||
{
|
||||
if (queue_family_properties[i].queueCount == queue_family_users[i])
|
||||
continue;
|
||||
if (!(queue_family_properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT))
|
||||
continue;
|
||||
if (queue_family_properties[i].timestampValidBits == 0)
|
||||
continue; // We need timing
|
||||
|
||||
if (!(queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
|
||||
if (surface)
|
||||
{
|
||||
m_spin_queue_family_index = i;
|
||||
break;
|
||||
}
|
||||
else if (m_spin_queue_family_index == queue_family_count)
|
||||
m_spin_queue_family_index = i;
|
||||
}
|
||||
|
||||
if (m_spin_queue_family_index != queue_family_count)
|
||||
{
|
||||
spin_queue_index = queue_family_users[m_spin_queue_family_index];
|
||||
queue_family_users[m_spin_queue_family_index]++;
|
||||
m_spin_queue_is_graphics_queue = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No spare queue? Try the graphics queue.
|
||||
if ((queue_family_properties[m_graphics_queue_family_index].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
|
||||
(queue_family_properties[m_graphics_queue_family_index].timestampValidBits != 0))
|
||||
{
|
||||
m_spin_queue_family_index = m_graphics_queue_family_index;
|
||||
spin_queue_index = 0;
|
||||
m_spin_queue_is_graphics_queue = true;
|
||||
}
|
||||
else
|
||||
m_spin_queue_is_graphics_queue = false;
|
||||
}
|
||||
|
||||
// Present Queue
|
||||
if (surface)
|
||||
{
|
||||
for (uint32_t i = 0; i < queue_family_count; i++)
|
||||
{
|
||||
if (queue_family_properties[i].queueCount == queue_family_users[i])
|
||||
continue;
|
||||
|
||||
VkBool32 present_supported;
|
||||
VkResult res = vkGetPhysicalDeviceSurfaceSupportKHR(m_physical_device, i, surface, &present_supported);
|
||||
if (res != VK_SUCCESS)
|
||||
@@ -555,48 +509,35 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!present_supported)
|
||||
continue;
|
||||
|
||||
// Perfer aync compute queue
|
||||
if ((queue_family_properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) &&
|
||||
!(queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
|
||||
{
|
||||
m_present_queue_family_index = i;
|
||||
break;
|
||||
}
|
||||
else if (m_present_queue_family_index == queue_family_count)
|
||||
m_present_queue_family_index = i;
|
||||
}
|
||||
|
||||
if (m_present_queue_family_index != queue_family_count)
|
||||
{
|
||||
present_queue_index = queue_family_users[m_present_queue_family_index];
|
||||
queue_family_users[m_present_queue_family_index]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No spare queue? Try the graphics queue.
|
||||
VkBool32 present_supported;
|
||||
VkResult res = vkGetPhysicalDeviceSurfaceSupportKHR(m_physical_device, m_graphics_queue_family_index, surface, &present_supported);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkGetPhysicalDeviceSurfaceSupportKHR failed: ");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (present_supported)
|
||||
{
|
||||
m_present_queue_family_index = m_graphics_queue_family_index;
|
||||
present_queue_index = 0;
|
||||
m_present_queue_family_index = i;
|
||||
}
|
||||
|
||||
// Prefer one queue family index that does both graphics and present.
|
||||
if (graphics_supported && present_supported)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Swap spin and present to simplify queue priorities logic.
|
||||
if (!m_spin_queue_is_graphics_queue && m_present_queue_family_index == m_spin_queue_family_index)
|
||||
std::swap(spin_queue_index, present_queue_index);
|
||||
|
||||
for (uint32_t i = 0; i < queue_family_count; i++)
|
||||
{
|
||||
// Pick a queue for spinning
|
||||
if (!(queue_family_properties[i].queueFlags & VK_QUEUE_COMPUTE_BIT))
|
||||
continue; // We need compute
|
||||
if (queue_family_properties[i].timestampValidBits == 0)
|
||||
continue; // We need timing
|
||||
const bool queue_is_used = i == m_graphics_queue_family_index || i == m_present_queue_family_index;
|
||||
if (queue_is_used && m_spin_queue_family_index != queue_family_count)
|
||||
continue; // Found a non-graphics queue to use
|
||||
spin_queue_index = 0;
|
||||
m_spin_queue_family_index = i;
|
||||
if (queue_is_used && queue_family_properties[i].queueCount > 1)
|
||||
spin_queue_index = 1;
|
||||
if (!(queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
|
||||
break; // Async compute queue, definitely pick this one
|
||||
}
|
||||
if (m_graphics_queue_family_index == queue_family_count)
|
||||
{
|
||||
Console.Error("VK: Failed to find an acceptable graphics queue.");
|
||||
@@ -614,16 +555,14 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
|
||||
device_info.flags = 0;
|
||||
device_info.queueCreateInfoCount = 0;
|
||||
|
||||
// Low priority for the spin queue
|
||||
static constexpr float queue_priorities[] = {1.0f, 1.0f, 0.0f};
|
||||
|
||||
static constexpr float queue_priorities[] = {1.0f, 0.0f}; // Low priority for the spin queue
|
||||
std::array<VkDeviceQueueCreateInfo, 3> queue_infos;
|
||||
VkDeviceQueueCreateInfo& graphics_queue_info = queue_infos[device_info.queueCreateInfoCount++];
|
||||
graphics_queue_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
graphics_queue_info.pNext = nullptr;
|
||||
graphics_queue_info.flags = 0;
|
||||
graphics_queue_info.queueFamilyIndex = m_graphics_queue_family_index;
|
||||
graphics_queue_info.queueCount = queue_family_users[m_graphics_queue_family_index];
|
||||
graphics_queue_info.queueCount = 1;
|
||||
graphics_queue_info.pQueuePriorities = queue_priorities;
|
||||
|
||||
if (surface != VK_NULL_HANDLE && m_graphics_queue_family_index != m_present_queue_family_index)
|
||||
@@ -633,19 +572,19 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
|
||||
present_queue_info.pNext = nullptr;
|
||||
present_queue_info.flags = 0;
|
||||
present_queue_info.queueFamilyIndex = m_present_queue_family_index;
|
||||
present_queue_info.queueCount = queue_family_users[m_present_queue_family_index];
|
||||
present_queue_info.queueCount = 1;
|
||||
present_queue_info.pQueuePriorities = queue_priorities;
|
||||
}
|
||||
|
||||
if (m_spin_queue_family_index == m_graphics_queue_family_index)
|
||||
{
|
||||
if (spin_queue_index == 1)
|
||||
graphics_queue_info.pQueuePriorities = queue_priorities + 1;
|
||||
if (spin_queue_index != 0)
|
||||
graphics_queue_info.queueCount = 2;
|
||||
}
|
||||
else if (m_spin_queue_family_index == m_present_queue_family_index)
|
||||
{
|
||||
if (spin_queue_index == 1)
|
||||
queue_infos[1].pQueuePriorities = queue_priorities + 1;
|
||||
if (spin_queue_index != 0)
|
||||
queue_infos[1].queueCount = 2; // present queue
|
||||
}
|
||||
else if (m_spin_queue_family_index != queue_family_count)
|
||||
{
|
||||
@@ -655,7 +594,7 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
|
||||
spin_queue_info.flags = 0;
|
||||
spin_queue_info.queueFamilyIndex = m_spin_queue_family_index;
|
||||
spin_queue_info.queueCount = 1;
|
||||
spin_queue_info.pQueuePriorities = queue_priorities + 2;
|
||||
spin_queue_info.pQueuePriorities = queue_priorities + 1;
|
||||
}
|
||||
|
||||
device_info.pQueueCreateInfos = queue_infos.data();
|
||||
@@ -744,11 +683,13 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
|
||||
vkGetDeviceQueue(m_device, m_graphics_queue_family_index, 0, &m_graphics_queue);
|
||||
if (surface)
|
||||
{
|
||||
vkGetDeviceQueue(m_device, m_present_queue_family_index, present_queue_index, &m_present_queue);
|
||||
vkGetDeviceQueue(m_device, m_present_queue_family_index, 0, &m_present_queue);
|
||||
}
|
||||
m_spinning_supported = m_spin_queue_family_index != queue_family_count &&
|
||||
queue_family_properties[m_graphics_queue_family_index].timestampValidBits > 0 &&
|
||||
m_device_properties.limits.timestampPeriod > 0;
|
||||
m_spin_queue_is_graphics_queue =
|
||||
m_spin_queue_family_index == m_graphics_queue_family_index && spin_queue_index == 0;
|
||||
|
||||
m_gpu_timing_supported = (m_device_properties.limits.timestampComputeAndGraphics != 0 &&
|
||||
queue_family_properties[m_graphics_queue_family_index].timestampValidBits > 0 &&
|
||||
@@ -1348,24 +1289,8 @@ void GSDeviceVK::SubmitCommandBuffer(VKSwapChain* present_swap_chain)
|
||||
|
||||
if (present_swap_chain)
|
||||
{
|
||||
// vkQueuePresentKHR on NVidia dosn't seem to properly wait on the passed semaphore, causing artifacts.
|
||||
// OBS capture with BPM encouters issues, but can apparently occur on the presented image aswell.
|
||||
// Instead, wait on the RenderingFinished semaphore with vkQueueSubmit.
|
||||
const uint32_t present_wait_bits = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
const VkSubmitInfo submit_present_wait_info = {VK_STRUCTURE_TYPE_SUBMIT_INFO, nullptr, 1,
|
||||
present_swap_chain->GetRenderingFinishedSemaphorePtr(), &present_wait_bits, 0,
|
||||
nullptr, 1, present_swap_chain->GetPresentReadySemaphorePtr()};
|
||||
|
||||
res = vkQueueSubmit(m_present_queue, 1, &submit_present_wait_info, nullptr);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkQueueSubmit failed: ");
|
||||
m_last_submit_failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const VkPresentInfoKHR present_info = {VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, nullptr, 1,
|
||||
present_swap_chain->GetPresentReadySemaphorePtr(), 1, present_swap_chain->GetSwapChainPtr(),
|
||||
present_swap_chain->GetRenderingFinishedSemaphorePtr(), 1, present_swap_chain->GetSwapChainPtr(),
|
||||
present_swap_chain->GetCurrentImageIndexPtr(), nullptr};
|
||||
|
||||
present_swap_chain->ResetImageAcquireResult();
|
||||
@@ -3206,7 +3131,7 @@ void GSDeviceVK::UpdateCLUTTexture(
|
||||
GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, GSTexture* dTex, u32 dOffset, u32 dSize)
|
||||
{
|
||||
// Super annoying, but apparently NVIDIA doesn't like floats/ints packed together in the same vec4?
|
||||
struct Uniforms
|
||||
struct alignas(16) Uniforms
|
||||
{
|
||||
u32 offsetX, offsetY, dOffset, pad1;
|
||||
float scale;
|
||||
@@ -3225,7 +3150,7 @@ void GSDeviceVK::UpdateCLUTTexture(
|
||||
void GSDeviceVK::ConvertToIndexedTexture(
|
||||
GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM)
|
||||
{
|
||||
struct Uniforms
|
||||
struct alignas(16) Uniforms
|
||||
{
|
||||
u32 SBW;
|
||||
u32 DBW;
|
||||
@@ -3246,7 +3171,7 @@ void GSDeviceVK::ConvertToIndexedTexture(
|
||||
|
||||
void GSDeviceVK::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32 downsample_factor, const GSVector2i& clamp_min, const GSVector4& dRect)
|
||||
{
|
||||
struct Uniforms
|
||||
struct alignas(16) Uniforms
|
||||
{
|
||||
GSVector2i clamp_min;
|
||||
int downsample_factor;
|
||||
@@ -4509,16 +4434,13 @@ void GSDeviceVK::RenderImGui()
|
||||
|
||||
UpdateImGuiTextures();
|
||||
|
||||
const float uniforms[2][2] = {{
|
||||
2.0f / static_cast<float>(m_window_info.surface_width),
|
||||
2.0f / static_cast<float>(m_window_info.surface_height),
|
||||
},
|
||||
{
|
||||
-1.0f,
|
||||
-1.0f,
|
||||
}};
|
||||
const GSVector4 uniforms(
|
||||
2.0f / static_cast<float>(m_window_info.surface_width),
|
||||
2.0f / static_cast<float>(m_window_info.surface_height),
|
||||
-1.0f,
|
||||
-1.0f);
|
||||
|
||||
SetUtilityPushConstants(uniforms, sizeof(uniforms));
|
||||
SetUtilityPushConstants(&uniforms, sizeof(uniforms));
|
||||
SetPipeline(m_imgui_pipeline);
|
||||
|
||||
if (m_utility_sampler != m_linear_sampler)
|
||||
|
||||
@@ -490,18 +490,6 @@ bool VKSwapChain::CreateSwapChain()
|
||||
sema.available_semaphore = VK_NULL_HANDLE;
|
||||
return false;
|
||||
}
|
||||
|
||||
res = vkCreateSemaphore(
|
||||
GSDeviceVK::GetInstance()->GetDevice(), &semaphore_info, nullptr, &sema.present_ready_semaphore);
|
||||
if (res != VK_SUCCESS)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkCreateSemaphore failed: ");
|
||||
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), sema.rendering_finished_semaphore, nullptr);
|
||||
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), sema.available_semaphore, nullptr);
|
||||
sema.rendering_finished_semaphore = VK_NULL_HANDLE;
|
||||
sema.available_semaphore = VK_NULL_HANDLE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -517,8 +505,6 @@ void VKSwapChain::DestroySwapChainImages()
|
||||
m_images.clear();
|
||||
for (auto& it : m_semaphores)
|
||||
{
|
||||
if (it.present_ready_semaphore != VK_NULL_HANDLE)
|
||||
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), it.present_ready_semaphore, nullptr);
|
||||
if (it.rendering_finished_semaphore != VK_NULL_HANDLE)
|
||||
vkDestroySemaphore(GSDeviceVK::GetInstance()->GetDevice(), it.rendering_finished_semaphore, nullptr);
|
||||
if (it.available_semaphore != VK_NULL_HANDLE)
|
||||
|
||||
@@ -64,14 +64,6 @@ public:
|
||||
{
|
||||
return &m_semaphores[m_current_semaphore].rendering_finished_semaphore;
|
||||
}
|
||||
__fi VkSemaphore GetPresentReadySemaphore() const
|
||||
{
|
||||
return m_semaphores[m_current_semaphore].present_ready_semaphore;
|
||||
}
|
||||
__fi const VkSemaphore* GetPresentReadySemaphorePtr() const
|
||||
{
|
||||
return &m_semaphores[m_current_semaphore].present_ready_semaphore;
|
||||
}
|
||||
|
||||
VkFormat GetTextureFormat() const;
|
||||
VkResult AcquireNextImage();
|
||||
@@ -100,7 +92,6 @@ private:
|
||||
{
|
||||
VkSemaphore available_semaphore;
|
||||
VkSemaphore rendering_finished_semaphore;
|
||||
VkSemaphore present_ready_semaphore;
|
||||
};
|
||||
|
||||
WindowInfo m_window_info;
|
||||
|
||||
@@ -4461,7 +4461,7 @@ void FullscreenUI::DrawBIOSSettingsPage()
|
||||
});
|
||||
}
|
||||
|
||||
MenuHeading(FSUI_CSTR("Options and Patches"));
|
||||
MenuHeading(FSUI_CSTR("Fast Boot Options"));
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_FORWARD_FAST, "Fast Boot"), FSUI_CSTR("Skips the intro screen, and bypasses region checks."),
|
||||
"EmuCore", "EnableFastBoot", true);
|
||||
|
||||
@@ -9509,7 +9509,7 @@ TRANSLATE_NOOP("FullscreenUI", "Resets configuration to defaults (excluding cont
|
||||
TRANSLATE_NOOP("FullscreenUI", "BIOS Configuration");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Changes the BIOS image used to start future sessions.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "BIOS Selection");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Options and Patches");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Fast Boot Options");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Skips the intro screen, and bypasses region checks.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Speed Control");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Sets the speed when running without fast forwarding.");
|
||||
|
||||
@@ -1923,7 +1923,6 @@ Pcsx2Config::Pcsx2Config()
|
||||
{
|
||||
bitset = 0;
|
||||
// Set defaults for fresh installs / reset settings
|
||||
McdFolderAutoManage = true;
|
||||
EnablePatches = true;
|
||||
EnableFastBoot = true;
|
||||
EnableRecordingTools = true;
|
||||
@@ -1979,7 +1978,6 @@ void Pcsx2Config::LoadSaveCore(SettingsWrapper& wrap)
|
||||
SettingsWrapBitBool(HostFs);
|
||||
|
||||
SettingsWrapBitBool(BackupSavestate);
|
||||
SettingsWrapBitBool(McdFolderAutoManage);
|
||||
|
||||
SettingsWrapBitBool(WarnAboutUnsafeSettings);
|
||||
|
||||
|
||||
@@ -611,7 +611,7 @@ void FileMcd_EmuOpen()
|
||||
|
||||
|
||||
Mcd::impl.Open();
|
||||
Mcd::implFolder.SetFiltering(EmuConfig.McdFolderAutoManage);
|
||||
Mcd::implFolder.SetFiltering(true);
|
||||
Mcd::implFolder.Open();
|
||||
}
|
||||
|
||||
@@ -823,7 +823,7 @@ int FileMcd_ReIndex(uint port, uint slot, const std::string& filter)
|
||||
// return Mcd::impl.ReIndex( combinedSlot, filter );
|
||||
// break;
|
||||
case MemoryCardType::Folder:
|
||||
if (!Mcd::implFolder.ReIndex(combinedSlot, EmuConfig.McdFolderAutoManage, filter))
|
||||
if (!Mcd::implFolder.ReIndex(combinedSlot, true, filter))
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
@@ -930,7 +930,7 @@ std::vector<AvailableMcdInfo> FileMcd_GetAvailableCards(bool include_in_use_card
|
||||
Pcsx2Config::McdOptions config;
|
||||
config.Enabled = true;
|
||||
config.Type = MemoryCardType::Folder;
|
||||
sourceFolderMemoryCard.Open(fd.FileName, config, (8 * 1024 * 1024) / FolderMemoryCard::ClusterSize, EmuConfig.McdFolderAutoManage, "");
|
||||
sourceFolderMemoryCard.Open(fd.FileName, config, (8 * 1024 * 1024) / FolderMemoryCard::ClusterSize, true, "");
|
||||
|
||||
mcds.push_back({std::move(basename), std::move(fd.FileName), fd.ModificationTime,
|
||||
MemoryCardType::Folder, MemoryCardFileType::Unknown, 0u, sourceFolderMemoryCard.IsFormatted()});
|
||||
|
||||
@@ -200,7 +200,6 @@ void SPU2::DoFullDump()
|
||||
fprintf(dump, " - Sound Start Address: %x\n", Cores[c].Voices[v].StartA);
|
||||
fprintf(dump, " - Next Data Address: %x\n", Cores[c].Voices[v].NextA);
|
||||
fprintf(dump, " - Play Status: %s\n", (Cores[c].Voices[v].ADSR.Phase > 0) ? "Playing" : "Not Playing");
|
||||
fprintf(dump, " - Block Sample: %d\n", Cores[c].Voices[v].SCurrent);
|
||||
}
|
||||
fprintf(dump, "#### END OF DUMP.\n\n");
|
||||
}
|
||||
|
||||
@@ -89,55 +89,13 @@ int g_counter_cache_ignores = 0;
|
||||
#define XAFLAG_LOOP (1ul << 1)
|
||||
#define XAFLAG_LOOP_START (1ul << 2)
|
||||
|
||||
static __forceinline s32 GetNextDataBuffered(V_Core& thiscore, uint voiceidx)
|
||||
static __forceinline void GetNextDataBuffered(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
if ((vc.SCurrent & 3) == 0)
|
||||
if (vc.SBuffer == nullptr)
|
||||
{
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
|
||||
if ((vc.NextA & 7) == 0) // vc.SCurrent == 24 equivalent
|
||||
{
|
||||
if (vc.LoopFlags & XAFLAG_LOOP_END)
|
||||
{
|
||||
thiscore.Regs.ENDX |= (1 << voiceidx);
|
||||
vc.NextA = vc.LoopStartA | 1;
|
||||
if (!(vc.LoopFlags & XAFLAG_LOOP))
|
||||
{
|
||||
vc.Stop();
|
||||
|
||||
if (IsDevBuild)
|
||||
{
|
||||
if (SPU2::MsgVoiceOff())
|
||||
SPU2::ConLog("* SPU2: Voice Off by EndPoint: %d \n", voiceidx);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
vc.NextA++; // no, don't IncrementNextA here. We haven't read the header yet.
|
||||
}
|
||||
}
|
||||
|
||||
if (vc.SCurrent == 28)
|
||||
{
|
||||
vc.SCurrent = 0;
|
||||
|
||||
// We'll need the loop flags and buffer pointers regardless of cache status:
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
|
||||
SetIrqCall(i);
|
||||
|
||||
s16* memptr = GetMemPtr(vc.NextA & 0xFFFF8);
|
||||
vc.LoopFlags = *memptr >> 8; // grab loop flags from the upper byte.
|
||||
|
||||
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
|
||||
{
|
||||
vc.LoopStartA = vc.NextA & 0xFFFF8;
|
||||
}
|
||||
|
||||
const int cacheIdx = vc.NextA / pcm_WordsPerBlock;
|
||||
const int cacheIdx = (vc.NextA & 0xFFFF8) / pcm_WordsPerBlock;
|
||||
PcmCacheEntry& cacheLine = pcm_cache_data[cacheIdx];
|
||||
vc.SBuffer = cacheLine.Sampledata;
|
||||
|
||||
@@ -172,46 +130,18 @@ static __forceinline s32 GetNextDataBuffered(V_Core& thiscore, uint voiceidx)
|
||||
g_counter_cache_misses++;
|
||||
}
|
||||
|
||||
|
||||
s16* memptr = GetMemPtr(vc.NextA & 0xFFFF8);
|
||||
XA_decode_block(vc.SBuffer, memptr, vc.Prev1, vc.Prev2);
|
||||
}
|
||||
}
|
||||
|
||||
return vc.SBuffer[vc.SCurrent++];
|
||||
}
|
||||
|
||||
static __forceinline void GetNextDataDummy(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
|
||||
if ((vc.NextA & 7) == 0) // vc.SCurrent == 24 equivalent
|
||||
// Get the sample index for NextA, we have to subtract 1 to ignore the loop header
|
||||
int sampleIdx = ((vc.NextA % pcm_WordsPerBlock) - 1) * 4;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (vc.LoopFlags & XAFLAG_LOOP_END)
|
||||
{
|
||||
thiscore.Regs.ENDX |= (1 << voiceidx);
|
||||
vc.NextA = vc.LoopStartA | 1;
|
||||
}
|
||||
else
|
||||
vc.NextA++; // no, don't IncrementNextA here. We haven't read the header yet.
|
||||
vc.DecodeFifo[(vc.DecPosWrite + i) % 32] = vc.SBuffer[sampleIdx + i];
|
||||
}
|
||||
|
||||
if (vc.SCurrent == 28)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
|
||||
SetIrqCall(i);
|
||||
|
||||
vc.LoopFlags = *GetMemPtr(vc.NextA & 0xFFFF8) >> 8; // grab loop flags from the upper byte.
|
||||
|
||||
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
|
||||
vc.LoopStartA = vc.NextA & 0xFFFF8;
|
||||
|
||||
vc.SCurrent = 0;
|
||||
}
|
||||
|
||||
vc.SP -= 0x1000 * (4 - (vc.SCurrent & 3));
|
||||
vc.SCurrent += 4 - (vc.SCurrent & 3);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -237,6 +167,69 @@ static __forceinline StereoOut32 ApplyVolume(const StereoOut32& data, const V_Vo
|
||||
ApplyVolume(data.Right, volume.Right.Value));
|
||||
}
|
||||
|
||||
static __forceinline void UpdateBlockHeader(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
if (Cores[i].IRQEnable && Cores[i].IRQA == (vc.NextA & 0xFFFF8))
|
||||
SetIrqCall(i);
|
||||
|
||||
s16* memptr = GetMemPtr(vc.NextA & 0xFFFF8);
|
||||
vc.LoopFlags = *memptr >> 8; // grab loop flags from the upper byte.
|
||||
|
||||
if ((vc.LoopFlags & XAFLAG_LOOP_START) && !vc.LoopMode)
|
||||
{
|
||||
vc.LoopStartA = vc.NextA & 0xFFFF8;
|
||||
}
|
||||
}
|
||||
|
||||
static __forceinline void DecodeSamples(uint coreidx, uint voiceidx)
|
||||
{
|
||||
V_Core& thiscore(Cores[coreidx]);
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
// Update the block header on every audio frame
|
||||
UpdateBlockHeader(thiscore, voiceidx);
|
||||
|
||||
// When a voice is started at 0 pitch, NAX quickly advances to SSA + 5
|
||||
// So that would mean the decode buffer holds around 12 samples
|
||||
if (((int)(vc.DecPosWrite - vc.DecPosRead)) > 12) {
|
||||
// Sufficient data buffered
|
||||
return;
|
||||
}
|
||||
|
||||
if (vc.ADSR.Phase > V_ADSR::PHASE_STOPPED)
|
||||
{
|
||||
GetNextDataBuffered(thiscore, voiceidx);
|
||||
}
|
||||
|
||||
vc.DecPosWrite += 4;
|
||||
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
if ((vc.NextA & 7) == 0)
|
||||
{
|
||||
if (vc.LoopFlags & XAFLAG_LOOP_END)
|
||||
{
|
||||
thiscore.Regs.ENDX |= (1 << voiceidx);
|
||||
vc.NextA = vc.LoopStartA;
|
||||
if (!(vc.LoopFlags & XAFLAG_LOOP))
|
||||
{
|
||||
vc.Stop();
|
||||
|
||||
if (IsDevBuild)
|
||||
{
|
||||
if (SPU2::MsgVoiceOff())
|
||||
SPU2::ConLog("* SPU2: Voice Off by EndPoint: %d \n", voiceidx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IncrementNextA(thiscore, voiceidx);
|
||||
vc.SBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static void __forceinline UpdatePitch(uint coreidx, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(Cores[coreidx].Voices[voiceidx]);
|
||||
@@ -278,33 +271,27 @@ static __forceinline void CalculateADSR(V_Core& thiscore, uint voiceidx)
|
||||
pxAssume(vc.ADSR.Value >= 0); // ADSR should never be negative...
|
||||
}
|
||||
|
||||
__forceinline static s32 GaussianInterpolate(s32 pv4, s32 pv3, s32 pv2, s32 pv1, s32 i)
|
||||
static __forceinline void ConsumeSamples(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
s32 out = 0;
|
||||
out = (interpTable[i][0] * pv4) >> 15;
|
||||
out += (interpTable[i][1] * pv3) >> 15;
|
||||
out += (interpTable[i][2] * pv2) >> 15;
|
||||
out += (interpTable[i][3] * pv1) >> 15;
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
return out;
|
||||
int consumed = vc.SP >> 12;
|
||||
vc.SP &= 0xfff;
|
||||
vc.DecPosRead += consumed;
|
||||
}
|
||||
|
||||
static __forceinline s32 GetVoiceValues(V_Core& thiscore, uint voiceidx)
|
||||
{
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
while (vc.SP >= 0)
|
||||
{
|
||||
vc.PV4 = vc.PV3;
|
||||
vc.PV3 = vc.PV2;
|
||||
vc.PV2 = vc.PV1;
|
||||
vc.PV1 = GetNextDataBuffered(thiscore, voiceidx);
|
||||
vc.SP -= 0x1000;
|
||||
}
|
||||
int phase = (vc.SP & 0x0ff0) >> 4;
|
||||
s32 out = 0;
|
||||
out += (interpTable[phase][0] * vc.DecodeFifo[(vc.DecPosRead + 0) % 32]) >> 15;
|
||||
out += (interpTable[phase][1] * vc.DecodeFifo[(vc.DecPosRead + 1) % 32]) >> 15;
|
||||
out += (interpTable[phase][2] * vc.DecodeFifo[(vc.DecPosRead + 2) % 32]) >> 15;
|
||||
out += (interpTable[phase][3] * vc.DecodeFifo[(vc.DecPosRead + 3) % 32]) >> 15;
|
||||
|
||||
const s32 mu = vc.SP + 0x1000;
|
||||
|
||||
return GaussianInterpolate(vc.PV4, vc.PV3, vc.PV2, vc.PV1, (mu & 0x0ff0) >> 4);
|
||||
return out;
|
||||
}
|
||||
|
||||
// This is Dr. Hell's noise algorithm as implemented in pcsxr
|
||||
@@ -382,21 +369,13 @@ static __forceinline StereoOut32 MixVoice(uint coreidx, uint voiceidx)
|
||||
V_Core& thiscore(Cores[coreidx]);
|
||||
V_Voice& vc(thiscore.Voices[voiceidx]);
|
||||
|
||||
// If this assertion fails, it mans SCurrent is being corrupted somewhere, or is not initialized
|
||||
// properly. Invalid values in SCurrent will cause errant IRQs and corrupted audio.
|
||||
pxAssertMsg((vc.SCurrent <= 28) && (vc.SCurrent != 0), "Current sample should always range from 1->28");
|
||||
|
||||
// Most games don't use much volume slide effects. So only call the UpdateVolume
|
||||
// methods when needed by checking the flag outside the method here...
|
||||
// (Note: Ys 6 : Ark of Nephistm uses these effects)
|
||||
|
||||
vc.Volume.Update();
|
||||
|
||||
// SPU2 Note: The spu2 continues to process voices for eternity, always, so we
|
||||
// have to run through all the motions of updating the voice regardless of it's
|
||||
// audible status. Otherwise IRQs might not trigger and emulation might fail.
|
||||
|
||||
UpdatePitch(coreidx, voiceidx);
|
||||
DecodeSamples(coreidx, voiceidx);
|
||||
|
||||
StereoOut32 voiceOut(0, 0);
|
||||
s32 Value = 0;
|
||||
@@ -419,11 +398,14 @@ static __forceinline StereoOut32 MixVoice(uint coreidx, uint voiceidx)
|
||||
|
||||
voiceOut = ApplyVolume(StereoOut32(Value, Value), vc.Volume);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (vc.SP >= 0)
|
||||
GetNextDataDummy(thiscore, voiceidx); // Dummy is enough
|
||||
}
|
||||
|
||||
// SPU2 Note: The spu2 continues to process voices for eternity, always, so we
|
||||
// have to run through all the motions of updating the voice regardless of it's
|
||||
// audible status. Otherwise IRQs might not trigger and emulation might fail.
|
||||
|
||||
UpdatePitch(coreidx, voiceidx);
|
||||
|
||||
ConsumeSamples(thiscore, voiceidx);
|
||||
|
||||
// Write-back of raw voice data (post ADSR applied)
|
||||
if (voiceidx == 1)
|
||||
@@ -533,7 +515,8 @@ StereoOut32 V_Core::Mix(const VoiceMixSet& inVoices, const StereoOut32& Input, c
|
||||
return TD + ApplyVolume(RV, FxVol);
|
||||
}
|
||||
|
||||
static StereoOut32 DCFilter(StereoOut32 input) {
|
||||
static StereoOut32 DCFilter(StereoOut32 input)
|
||||
{
|
||||
// A simple DC blocking high-pass filter
|
||||
// Implementation from http://peabody.sapp.org/class/dmp2/lab/dcblock/
|
||||
// The magic number 0x7f5c is ceil(INT16_MAX * 0.995)
|
||||
@@ -634,9 +617,9 @@ __forceinline void spu2Mix()
|
||||
if (SPU2::MsgCache())
|
||||
{
|
||||
SPU2::ConLog(" * SPU2 > CacheStats > Hits: %d Misses: %d Ignores: %d\n",
|
||||
g_counter_cache_hits,
|
||||
g_counter_cache_misses,
|
||||
g_counter_cache_ignores);
|
||||
g_counter_cache_hits,
|
||||
g_counter_cache_misses,
|
||||
g_counter_cache_ignores);
|
||||
}
|
||||
|
||||
g_counter_cache_hits =
|
||||
|
||||
@@ -256,29 +256,16 @@ struct V_Voice
|
||||
// Sample pointer (19:12 bit fixed point)
|
||||
s32 SP;
|
||||
|
||||
// Sample pointer for Cubic Interpolation
|
||||
// Cubic interpolation mixes a sample behind Linear, so that it
|
||||
// can have sample data to either side of the end points from which
|
||||
// to extrapolate. This SP represents that late sample position.
|
||||
s32 SPc;
|
||||
|
||||
// Previous sample values - used for interpolation
|
||||
// Inverted order of these members to match the access order in the
|
||||
// code (might improve cache hits).
|
||||
s32 PV4;
|
||||
s32 PV3;
|
||||
s32 PV2;
|
||||
s32 PV1;
|
||||
|
||||
// Last outputted audio value, used for voice modulation.
|
||||
s32 OutX;
|
||||
s32 NextCrest; // temp value for Crest calculation
|
||||
|
||||
// SBuffer now points directly to an ADPCM cache entry.
|
||||
s16* SBuffer;
|
||||
|
||||
// sample position within the current decoded packet.
|
||||
s32 SCurrent;
|
||||
// Each voice has a buffer of decoded samples
|
||||
s32 DecodeFifo[32];
|
||||
u32 DecPosWrite;
|
||||
u32 DecPosRead;
|
||||
|
||||
// it takes a few ticks for voices to start on the real SPU2?
|
||||
void Start();
|
||||
|
||||
@@ -181,7 +181,6 @@ void V_Core::Init(int index)
|
||||
VoiceGates[v].WetR = -1;
|
||||
|
||||
Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;
|
||||
Voices[v].SCurrent = 28;
|
||||
|
||||
Voices[v].ADSR.Counter = 0;
|
||||
Voices[v].ADSR.Value = 0;
|
||||
@@ -190,6 +189,10 @@ void V_Core::Init(int index)
|
||||
Voices[v].NextA = 0x2801;
|
||||
Voices[v].StartA = 0x2800;
|
||||
Voices[v].LoopStartA = 0x2800;
|
||||
|
||||
memset(Voices[v].DecodeFifo, 0, sizeof(Voices[v].DecodeFifo));
|
||||
Voices[v].DecPosRead = 0;
|
||||
Voices[v].DecPosWrite = 0;
|
||||
}
|
||||
|
||||
DMAICounter = 0;
|
||||
@@ -212,23 +215,18 @@ void V_Voice::Start()
|
||||
}
|
||||
|
||||
ADSR.Attack();
|
||||
SCurrent = 28;
|
||||
LoopMode = 0;
|
||||
|
||||
// When SP >= 0 the next sample will be grabbed, we don't want this to happen
|
||||
// instantly because in the case of pitch being 0 we want to delay getting
|
||||
// the next block header. This is a hack to work around the fact that unlike
|
||||
// the HW we don't update the block header on every cycle.
|
||||
SP = -1;
|
||||
SP = 0;
|
||||
|
||||
LoopFlags = 0;
|
||||
NextA = StartA | 1;
|
||||
Prev1 = 0;
|
||||
Prev2 = 0;
|
||||
|
||||
PV1 = PV2 = 0;
|
||||
PV3 = PV4 = 0;
|
||||
NextCrest = -0x8000;
|
||||
SBuffer = nullptr;
|
||||
DecPosRead = 0;
|
||||
DecPosWrite = 0;
|
||||
}
|
||||
|
||||
void V_Voice::Stop()
|
||||
@@ -989,12 +987,10 @@ static void RegWrite_VoiceAddr(u16 value)
|
||||
// Wallace And Gromit: Curse Of The Were-Rabbit.
|
||||
|
||||
thisvoice.NextA = ((u32)(value & 0x0F) << 16) | (thisvoice.NextA & 0xFFF8) | 1;
|
||||
thisvoice.SCurrent = 28;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
thisvoice.NextA = (thisvoice.NextA & 0x0F0000) | (value & 0xFFF8) | 1;
|
||||
thisvoice.SCurrent = 28;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1212,7 +1208,6 @@ static void RegWrite_Core(u16 value)
|
||||
for (uint v = 0; v < 24; ++v)
|
||||
{
|
||||
Cores[1].Voices[v].Volume = V_VolumeSlideLR(0, 0); // V_VolumeSlideLR::Max;
|
||||
Cores[1].Voices[v].SCurrent = 28;
|
||||
|
||||
Cores[1].Voices[v].ADSR.Value = 0;
|
||||
Cores[1].Voices[v].ADSR.Phase = 0;
|
||||
|
||||
@@ -26,7 +26,7 @@ enum class FreezeAction
|
||||
// [SAVEVERSION+]
|
||||
// This informs the auto updater that the users savestates will be invalidated.
|
||||
|
||||
static const u32 g_SaveVersion = (0x9A55 << 16) | 0x0000;
|
||||
static const u32 g_SaveVersion = (0x9A57 << 16) | 0x0000;
|
||||
|
||||
|
||||
// the freezing data between submodules and core
|
||||
|
||||
@@ -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 = 80;
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 81;
|
||||
|
||||
@@ -2993,8 +2993,6 @@ void VMManager::CheckForMemoryCardConfigChanges(const Pcsx2Config& old_config)
|
||||
}
|
||||
}
|
||||
|
||||
changed |= (EmuConfig.McdFolderAutoManage != old_config.McdFolderAutoManage);
|
||||
|
||||
if (!changed)
|
||||
return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user