Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d915a0b945 | ||
|
|
ac9c5eaae9 | ||
|
|
0891da303c | ||
|
|
55e9b51faa | ||
|
|
55dc0ade47 | ||
|
|
2cf7083718 | ||
|
|
15df532d68 | ||
|
|
884d2302a9 | ||
|
|
bacdfd6018 | ||
|
|
dc7a3bbbd3 | ||
|
|
ff0d791783 | ||
|
|
a3d8a0dde0 | ||
|
|
a8c908d113 | ||
|
|
01849d5305 | ||
|
|
23968d3e2b | ||
|
|
7246a64ae5 | ||
|
|
729e050adb | ||
|
|
003452fbbb | ||
|
|
419b6bd0a3 | ||
|
|
668c3d9a08 | ||
|
|
9a6f878051 | ||
|
|
50fc750154 | ||
|
|
9fe8235eda | ||
|
|
f7b9c48998 | ||
|
|
17bf27c018 | ||
|
|
80ca5ea5fd | ||
|
|
3afa9ca403 | ||
|
|
842190e15e | ||
|
|
717775d9ab | ||
|
|
a19bb91041 | ||
|
|
a545982a28 | ||
|
|
2109df04ca | ||
|
|
f485cf8ebc | ||
|
|
bb48110f95 | ||
|
|
718adda749 | ||
|
|
a170c7ccb1 | ||
|
|
fec3fe3b6b | ||
|
|
00f19c9777 | ||
|
|
93aae28593 | ||
|
|
8be2b907b3 | ||
|
|
fcca07765b | ||
|
|
559e4e75eb |
4
.github/ISSUE_TEMPLATE/emu_bug_report.yaml
vendored
@@ -66,10 +66,6 @@ body:
|
||||
|
||||
Performance issues as a result of not meeting our hardware requirements are not valid.
|
||||
|
||||
Please read our known issues pages for AMD and Intel drivers.
|
||||
- [Intel Drivers](https://github.com/PCSX2/pcsx2/wiki/OpenGL-and-Intel-GPUs-All-you-need-to-know).
|
||||
- [AMD Drivers](https://github.com/PCSX2/pcsx2/wiki/OpenGL-and-AMD-GPUs---All-you-need-to-know).
|
||||
|
||||
We are **not** accepting issues related to the **libretro** core. The libretro core is being maintained separately at this time
|
||||
- type: input
|
||||
id: rev
|
||||
|
||||
8
.github/workflows/linux_build_flatpak.yml
vendored
@@ -96,7 +96,7 @@ jobs:
|
||||
|
||||
- name: Build Flatpak (beta)
|
||||
if: ${{ inputs.stableBuild == false || inputs.stableBuild == 'false' }}
|
||||
uses: flathub-infra/flatpak-github-actions/flatpak-builder@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
with:
|
||||
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
|
||||
upload-artifact: false
|
||||
@@ -112,7 +112,7 @@ jobs:
|
||||
|
||||
- name: Build Flatpak (stable)
|
||||
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
|
||||
uses: flathub-infra/flatpak-github-actions/flatpak-builder@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
with:
|
||||
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
|
||||
upload-artifact: false
|
||||
@@ -132,7 +132,7 @@ jobs:
|
||||
|
||||
- name: Push to Flathub (beta)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == false || inputs.stableBuild == 'false') }}
|
||||
uses: flathub-infra/flatpak-github-actions/flat-manager@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: beta
|
||||
@@ -141,7 +141,7 @@ jobs:
|
||||
|
||||
- name: Push to Flathub (stable)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == true || inputs.stableBuild == 'true') }}
|
||||
uses: flathub-infra/flatpak-github-actions/flat-manager@23796715b3dfa4c86ddf50cf29c3cc8b3c82dca8
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: stable
|
||||
|
||||
@@ -1274,7 +1274,7 @@ SCAJ-10015:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes post effects.
|
||||
getSkipCount: "GSC_Tekken5" # Fixes upscaling grid, same engine.
|
||||
getSkipCount: "GSC_NamcoGames" # Fixes upscaling grid, same engine.
|
||||
SCAJ-20001:
|
||||
name: "Ratchet & Clank"
|
||||
region: "NTSC-Unk"
|
||||
@@ -1987,7 +1987,7 @@ SCAJ-20125:
|
||||
alignSprite: 1
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SCAJ-20126:
|
||||
name: "Tekken 5"
|
||||
region: "NTSC-Unk"
|
||||
@@ -1998,7 +1998,7 @@ SCAJ-20126:
|
||||
alignSprite: 1
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SCAJ-20127:
|
||||
name: "EyeToy - Play 2 [with Camera]"
|
||||
region: "NTSC-Unk"
|
||||
@@ -2248,7 +2248,7 @@ SCAJ-20163:
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 2 # Fixes ghosting.
|
||||
autoFlush: 2 # Fixes post lighting.
|
||||
getSkipCount: "GSC_Tekken5" # Fixes upscaling grid, same engine.
|
||||
getSkipCount: "GSC_NamcoGames" # Fixes upscaling grid, same engine.
|
||||
SCAJ-20164:
|
||||
name: "Kingdom Hearts II"
|
||||
region: "NTSC-Unk"
|
||||
@@ -2477,7 +2477,7 @@ SCAJ-20199:
|
||||
alignSprite: 1
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SCAJ-25002:
|
||||
name: "Shinobi"
|
||||
region: "NTSC-Unk"
|
||||
@@ -4188,7 +4188,7 @@ SCED-53538:
|
||||
alignSprite: 1
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SCED-53611:
|
||||
name: "Official PlayStation 2 Magazine - German Kids Special"
|
||||
region: "PAL-G"
|
||||
@@ -4578,6 +4578,17 @@ SCED-55120:
|
||||
SCED-55432:
|
||||
name: "Buzz! Junior - Ace Racers [Demo]"
|
||||
region: "PAL-M15"
|
||||
SCES-00000:
|
||||
name: "Ico [Preview]"
|
||||
region: "PAL-M5"
|
||||
compat: 5
|
||||
clampModes:
|
||||
eeClampMode: 2 # Otherwise freezes in various spots, check full intro.
|
||||
vuClampMode: 1 # Otherwise camera does not focus correctly on main character.
|
||||
gsHWFixes:
|
||||
mipmap: 1
|
||||
halfPixelOffset: 1 # Fixes effect misalignment.
|
||||
moveHandler: "MV_Ico" # Fixes depth buffer post-processing.
|
||||
SCES-50000:
|
||||
name: "Ridge Racer V"
|
||||
region: "PAL-M5"
|
||||
@@ -5816,7 +5827,7 @@ SCES-53202:
|
||||
alignSprite: 1
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SCES-53247:
|
||||
name: "WRC Rally Evolved"
|
||||
region: "PAL-M8"
|
||||
@@ -7274,7 +7285,7 @@ SCKA-20049:
|
||||
alignSprite: 1
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SCKA-20050:
|
||||
name: "Tales of Legendia"
|
||||
region: "NTSC-K"
|
||||
@@ -7501,7 +7512,7 @@ SCKA-20081:
|
||||
alignSprite: 1
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SCKA-20082:
|
||||
name: "Ace Combat 5 - The Unsung War [PlayStation 2 Big Hit Series]"
|
||||
region: "NTSC-K"
|
||||
@@ -54877,7 +54888,7 @@ SLPS-20485:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes post effects.
|
||||
getSkipCount: "GSC_Tekken5" # Fixes upscaling grid, same engine.
|
||||
getSkipCount: "GSC_NamcoGames" # Fixes upscaling grid, same engine.
|
||||
SLPS-20486:
|
||||
name: "太鼓の達人 ドカッ!と大盛り七代目 [ソフト単体]"
|
||||
name-sort: "たいこのたつじん どかっ!とおおもりななだいめ [そふとたんたい]"
|
||||
@@ -54886,7 +54897,7 @@ SLPS-20486:
|
||||
gsHWFixes:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
textureInsideRT: 1 # Fixes post effects.
|
||||
getSkipCount: "GSC_Tekken5" # Fixes upscaling grid, same engine.
|
||||
getSkipCount: "GSC_NamcoGames" # Fixes upscaling grid, same engine.
|
||||
SLPS-20487:
|
||||
name: "パチスロキング! 科学忍者隊ガッチャマン"
|
||||
name-sort: "ぱちすろきんぐ! かがくにんじゃたいがっちゃまん"
|
||||
@@ -58032,7 +58043,7 @@ SLPS-25510:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SLPS-25511:
|
||||
name: "羅刹 -Alternative-"
|
||||
name-sort: "らせつ -Alternative-"
|
||||
@@ -58473,7 +58484,7 @@ SLPS-25586:
|
||||
halfPixelOffset: 4 # Fixes post positioning.
|
||||
nativeScaling: 1 # Fixes post effects.
|
||||
autoFlush: 2 # Fixes post lighting.
|
||||
getSkipCount: "GSC_Tekken5" # Fixes upscaling grid, same engine.
|
||||
getSkipCount: "GSC_NamcoGames" # Fixes upscaling grid, same engine.
|
||||
SLPS-25587:
|
||||
name: "シュガシュガルーン 恋もおしゃれもピックアップ!"
|
||||
name-sort: "しゅがしゅがるーん こいもおしゃれもぴっくあっぷ!"
|
||||
@@ -61211,7 +61222,7 @@ SLPS-73223:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SLPS-73224:
|
||||
name: "ゼノサーガ エピソードⅡ [善悪の彼岸] [PlayStation2 the Best] [ディスク1/2]"
|
||||
name-sort: "ぜのさーが えぴそーど2 ぜんあくのひがん [PlayStation2 the Best] [でぃすく1/2]"
|
||||
@@ -61511,7 +61522,7 @@ SLPS-73252:
|
||||
halfPixelOffset: 4 # Fixes post positioning.
|
||||
nativeScaling: 1 # Fixes post effects.
|
||||
autoFlush: 2 # Fixes post lighting.
|
||||
getSkipCount: "GSC_Tekken5" # Fixes upscaling grid, same engine.
|
||||
getSkipCount: "GSC_NamcoGames" # Fixes upscaling grid, same engine.
|
||||
SLPS-73253:
|
||||
name: "るろうに剣心-明治剣客浪漫譚- 炎上!京都輪廻 [PlayStation2 the Best]"
|
||||
name-sort: "るろうにけんしん めいじけんかくろまんたん えんじょう きょうとりんね [PlayStation2 the Best]"
|
||||
@@ -67238,7 +67249,7 @@ SLUS-21059:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SLUS-21060:
|
||||
name: "WWE SmackDown! vs. RAW"
|
||||
region: "NTSC-U"
|
||||
@@ -67790,7 +67801,7 @@ SLUS-21160:
|
||||
alignSprite: 1 # Fixes vertical lines.
|
||||
halfPixelOffset: 4 # Align post.
|
||||
nativeScaling: 1 # Fixes depth of field effect.
|
||||
getSkipCount: "GSC_Tekken5"
|
||||
getSkipCount: "GSC_NamcoGames"
|
||||
SLUS-21161:
|
||||
name: "Fight Night Round 2"
|
||||
region: "NTSC-U"
|
||||
@@ -69376,7 +69387,7 @@ SLUS-21386:
|
||||
halfPixelOffset: 4 # Fixes post positioning.
|
||||
nativeScaling: 1 # Fixes post effects.
|
||||
autoFlush: 2 # Fixes post lighting.
|
||||
getSkipCount: "GSC_Tekken5" # Fixes upscaling grid, same engine.
|
||||
getSkipCount: "GSC_NamcoGames" # Fixes upscaling grid, same engine.
|
||||
SLUS-21387:
|
||||
name: "Warship Gunner 2"
|
||||
region: "NTSC-U"
|
||||
@@ -69521,6 +69532,9 @@ SLUS-21410:
|
||||
name: "Mortal Kombat - Armageddon"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
memcardFilters: # Saves from the non-Premium can be imported
|
||||
- "SLUS-21410"
|
||||
- "SLUS-21543"
|
||||
SLUS-21411:
|
||||
name: "M2 Rock"
|
||||
region: "NTSC-U"
|
||||
@@ -70163,6 +70177,9 @@ SLUS-21543:
|
||||
name: "Mortal Kombat - Armageddon [Premium Edition]"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
memcardFilters: # Saves from the non-Premium can be imported
|
||||
- "SLUS-21543"
|
||||
- "SLUS-21410"
|
||||
SLUS-21544:
|
||||
name: "Fantastic 4 - Rise of Silver Surfer"
|
||||
region: "NTSC-U"
|
||||
|
||||
@@ -1749,7 +1749,7 @@
|
||||
- hashes:
|
||||
- md5: f95ea9eb021181b888229df60ba8effd
|
||||
size: 2159050752
|
||||
name: Shadow the Hedgehog (Europe, Australia) (En,Fr,De,Es,It)
|
||||
name: Shadow the Hedgehog (Europe, Australia) (En,Ja,Fr,De,Es,It)
|
||||
serial: SLES-53542
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -8524,7 +8524,7 @@
|
||||
- hashes:
|
||||
- md5: ce030f48dcb588682902b5a569baa24e
|
||||
size: 4677795840
|
||||
name: 007 - Quantum of Solace (USA)
|
||||
name: 007 - Quantum of Solace (USA) (En,Fr)
|
||||
serial: SLUS-21813
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -8620,7 +8620,7 @@
|
||||
- hashes:
|
||||
- md5: c15a1707d1c89728e0c596b97ba91b27
|
||||
size: 4313153536
|
||||
name: Official PlayStation 2 Magazine Sonderausgabe 2004-3 (Germany) (En,Fr,De,Es,It)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2004-03 (Germany) (En,Fr,De,Es,It)
|
||||
serial: SCED-52997
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -8854,7 +8854,7 @@
|
||||
- hashes:
|
||||
- md5: fab56e6f617b0a64ad35221341bd167c
|
||||
size: 3529965568
|
||||
name: Rock Band - Metal Track Pack (USA)
|
||||
name: Rock Band - Metal Track Pack (USA, Canada)
|
||||
serial: SLUS-21889
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -9753,7 +9753,7 @@
|
||||
- hashes:
|
||||
- md5: 63d3e8e5da0305650160bc50f46df87b
|
||||
size: 4033478656
|
||||
name: Fight Night Round 3 (Europe) (En,Fr)
|
||||
name: Fight Night Round 3 (Europe, Australia) (En,Fr)
|
||||
serial: SLES-53982
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -13331,7 +13331,7 @@
|
||||
- hashes:
|
||||
- md5: aac303724ce688c8f242245ea0f4b9e4
|
||||
size: 877953024
|
||||
name: Tokyo Bus Guide - Kyou kara Kimi mo Untenshu (Japan)
|
||||
name: SuperLite 2000 Vol. 5 - Tokyo Bus Guide - Kyou kara Kimi mo Untenshu (Japan)
|
||||
serial: SLPM-65032
|
||||
version: '1.04'
|
||||
- hashes:
|
||||
@@ -15880,7 +15880,7 @@
|
||||
- hashes:
|
||||
- md5: 29e5cf458549ca5321dd0c12619a002b
|
||||
size: 3846504448
|
||||
name: Bakugan - Battle Brawlers (USA)
|
||||
name: Bakugan - Battle Brawlers (USA) (En,Fr)
|
||||
serial: SLUS-21902
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -20525,7 +20525,7 @@
|
||||
- hashes:
|
||||
- md5: 2e7fcee5a1333b72eef8a18c7a673e9f
|
||||
size: 8539766784
|
||||
name: Guitar Hero - Metallica (USA)
|
||||
name: Guitar Hero - Metallica (USA) (En,Fr)
|
||||
serial: SLUS-21843
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -20868,7 +20868,7 @@
|
||||
- hashes:
|
||||
- md5: 35d939b30458790cf58ddd16ef11e159
|
||||
size: 697149264
|
||||
name: Online Start-Up Disc 4.0 - Broadband Only (USA)
|
||||
name: Online Start-Up Disc 4.0 - Broadband Only (USA) (v1.02)
|
||||
serial: PBPX-95248
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
@@ -21320,8 +21320,7 @@
|
||||
- hashes:
|
||||
- md5: 4f18266ee64804fc1ba858c5d5bee759
|
||||
size: 3782836224
|
||||
name: Official PlayStation 2 Magazine Germany Special Edition 01-2004 (Germany)
|
||||
(En,Fr,De,Es,It)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2004-01 (Germany) (En,Fr,De,Es,It)
|
||||
serial: SCED-52119
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -21764,7 +21763,7 @@
|
||||
- hashes:
|
||||
- md5: e6159c29d23cd03252e94823045b4ff8
|
||||
size: 4071424000
|
||||
name: DJ Hero (USA)
|
||||
name: DJ Hero (USA) (En,Fr)
|
||||
serial: SLUS-21909
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -22190,7 +22189,7 @@
|
||||
- hashes:
|
||||
- md5: 007f0ccc933f59b65f28c72ad227843d
|
||||
size: 4580573184
|
||||
name: Score International Baja 1000 - World Championship Off Road Racing (Europe)
|
||||
name: SCORE International Baja 1000 - World Championship Off Road Racing (Europe)
|
||||
serial: SLES-55295
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -22862,7 +22861,7 @@
|
||||
- hashes:
|
||||
- md5: cadce0add00903396577b5d53cff1929
|
||||
size: 4679565312
|
||||
name: Marvel Super Hero Squad (USA)
|
||||
name: Marvel Super Hero Squad (USA) (En,Fr,Es)
|
||||
serial: SLUS-21910
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -22946,7 +22945,7 @@
|
||||
- hashes:
|
||||
- md5: 77ae418d710142291b5d6eb5d5d904d1
|
||||
size: 3007021056
|
||||
name: Buzz! The Schools Quiz (Europe)
|
||||
name: Buzz! The Schools Quiz (UK) (v2.00)
|
||||
serial: SCES-54941
|
||||
version: '2.00'
|
||||
- hashes:
|
||||
@@ -30411,7 +30410,7 @@
|
||||
- hashes:
|
||||
- md5: 01abdbe56de95af5b5379cf7fea1bec0
|
||||
size: 3683680256
|
||||
name: Ratchet & Clank 2 - Gagaga! Ginga no Commando-ssu (Japan, Asia)
|
||||
name: Ratchet & Clank 2 - Gagaga! Ginga no Commando ssu (Japan, Asia)
|
||||
serial: SCAJ-20052
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -32035,7 +32034,7 @@
|
||||
- hashes:
|
||||
- md5: 47e03c7b246239330d5e41efb5160fda
|
||||
size: 1328939008
|
||||
name: Nickelodeon Bob L'eponge - Silence on Tourne! (France)
|
||||
name: Nickelodeon Bob L'eponge - Silence on Tourne ! (France)
|
||||
serial: SLES-53495
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -33603,19 +33602,19 @@
|
||||
- hashes:
|
||||
- md5: ac71dddc4a60475a689fcb6f1836e607
|
||||
size: 4307582976
|
||||
name: Buzz! The Big Quiz (Europe) (En,Fr,Nl)
|
||||
name: Buzz! The Big Quiz (Belgium, Netherlands) (En,Fr,Nl)
|
||||
serial: SCES-53925
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 0f457023f2a436d38a0cd53599115846
|
||||
size: 4611080192
|
||||
name: Buzz! The Mega Quiz (Europe) (En,Fr,Nl)
|
||||
name: Buzz! The Mega Quiz (Belgium, Netherlands) (En,Fr,Nl)
|
||||
serial: SCES-54505
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 409302dffc2512d1ccd2227d17ff6bf2
|
||||
size: 4688314368
|
||||
name: Buzz! The Pop Quiz (Europe) (En,Fr,Nl)
|
||||
name: Buzz! The Pop Quiz (Belgium, Netherlands) (En,Fr,Nl)
|
||||
serial: SCES-55098
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -34577,7 +34576,7 @@
|
||||
- hashes:
|
||||
- md5: 4703eb006c9921927145c878acd7324c
|
||||
size: 3536748544
|
||||
name: Buzz! The Sports Quiz (Europe) (En,Fr,Nl)
|
||||
name: Buzz! The Sports Quiz (Belgium, Netherlands) (En,Fr,Nl)
|
||||
serial: SCES-54265
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -36547,7 +36546,7 @@
|
||||
- hashes:
|
||||
- md5: fa7523e49dc9825589504430857c5c25
|
||||
size: 564202464
|
||||
name: LEGO Island Xtreme Stunts (USA)
|
||||
name: Island Xtreme Stunts (USA)
|
||||
serial: SLUS-20575
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -38437,7 +38436,7 @@
|
||||
- hashes:
|
||||
- md5: 06553f511a16b8cc0396bab31cc910a6
|
||||
size: 2924576768
|
||||
name: DreamWorks Madagascar - Escape 2 Africa (USA)
|
||||
name: DreamWorks Madagascar - Escape 2 Africa (USA) (En,Fr)
|
||||
serial: SLUS-21840
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -39061,7 +39060,7 @@
|
||||
- hashes:
|
||||
- md5: cc5e862a633532654176096888dfacba
|
||||
size: 2679865344
|
||||
name: PES 2011 - Pro Evolution Soccer (USA)
|
||||
name: PES 2011 - Pro Evolution Soccer (USA) (En,Fr,Es,Pt)
|
||||
serial: SLUS-21942
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -39355,7 +39354,7 @@
|
||||
- hashes:
|
||||
- md5: 298ad8520c82f4edbaacb3194bc46d5c
|
||||
size: 3530391552
|
||||
name: PES 2010 - Pro Evolution Soccer (USA)
|
||||
name: PES 2010 - Pro Evolution Soccer (USA) (En,Fr,Es,Pt)
|
||||
serial: SLUS-21918
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
@@ -39421,7 +39420,7 @@
|
||||
- hashes:
|
||||
- md5: 491a3f6a39ce290de2f6dbb9ba98575f
|
||||
size: 2129297408
|
||||
name: PES 2013 - Pro Evolution Soccer (USA)
|
||||
name: PES 2013 - Pro Evolution Soccer (USA) (En,Fr,Es,Pt)
|
||||
serial: SLUS-21955
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -39433,7 +39432,7 @@
|
||||
- hashes:
|
||||
- md5: b2d139590f169442a46d21ed2f8558ab
|
||||
size: 2437316608
|
||||
name: PES 2012 - Pro Evolution Soccer (USA)
|
||||
name: PES 2012 - Pro Evolution Soccer (USA) (En,Fr,Es,Pt)
|
||||
serial: SLUS-21948
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -39511,7 +39510,7 @@
|
||||
- hashes:
|
||||
- md5: 6821bded97877694e8cf4ccf9ca64ad4
|
||||
size: 4659347456
|
||||
name: Vitamin Z - Welcome Our New Supplement Boys (Japan) (Genteiban)
|
||||
name: VitaminZ - Welcome Our New Supplement Boys (Japan) (Genteiban)
|
||||
serial: SLPS-25922
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
@@ -39770,7 +39769,7 @@
|
||||
- hashes:
|
||||
- md5: 6f2533c2ae433f1beac4f1aa3a88f4c6
|
||||
size: 4588797952
|
||||
name: AND 1 Streetball (USA) (v1.03)
|
||||
name: AND 1 Streetball (USA) (En,Fr,Es) (v1.03)
|
||||
serial: SLUS-21237
|
||||
version: '1.03'
|
||||
- hashes:
|
||||
@@ -39902,7 +39901,7 @@
|
||||
- hashes:
|
||||
- md5: 2d3dd4cd0d8c16e97a1a887b70349658
|
||||
size: 4636672000
|
||||
name: Score International Baja 1000 - The Official Game (USA)
|
||||
name: SCORE International Baja 1000 - The Official Game (USA)
|
||||
serial: SLUS-21850
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -40463,7 +40462,7 @@
|
||||
- md5: 08a63db4f248acdc24cdaa0b9507b854
|
||||
size: 2205908992
|
||||
name: Umishou (Japan)
|
||||
serial: SLPM-66864
|
||||
serial: FVGK-0001
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
- md5: d3b19450aea4a9688e876fa71830aa77
|
||||
@@ -40745,7 +40744,7 @@
|
||||
- hashes:
|
||||
- md5: 9be1477e6c0bd67bb6aff3a02601b4a6
|
||||
size: 1534427136
|
||||
name: Freaky Flyers (USA) (Demo)
|
||||
name: Freaky Flyers (USA) (Demo) (Rev 1)
|
||||
serial: SLUS-29061
|
||||
version: '0.30'
|
||||
- hashes:
|
||||
@@ -41497,7 +41496,7 @@
|
||||
- hashes:
|
||||
- md5: 6dc613680039ba59d20f8baa61e56fc5
|
||||
size: 739706352
|
||||
name: Momotarou Dentetsu 11 - Black Bombee Shutsugen! no Maki (Japan)
|
||||
name: Momotarou Dentetsu 11 - Black Bonby Shutsugen! no Maki (Japan)
|
||||
serial: SLPM-62475
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -44241,7 +44240,7 @@
|
||||
- md5: 34d981b3883eaeb95c82fbed14dcad26
|
||||
size: 3115188224
|
||||
name: Harukanaru Toki no Naka de 3 (Japan) (History Box)
|
||||
serial: SLPM-66005
|
||||
serial: SLPM-65849
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
- md5: d8ecac6d03a601d4a81f1389bfe25962
|
||||
@@ -45207,13 +45206,13 @@
|
||||
- hashes:
|
||||
- md5: 29a454ebd230549939654022af5db917
|
||||
size: 4107206656
|
||||
name: Vitamin X - We are Super Supriment Boys (Japan)
|
||||
name: VitaminX - We are Super Supriment Boys (Japan)
|
||||
serial: SLPS-25761
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
- md5: 19cc959d502b7eebae156ee760731454
|
||||
size: 4659347456
|
||||
name: Vitamin Z - Welcome Our New Supplement Boys (Japan)
|
||||
name: VitaminZ - Welcome Our New Supplement Boys (Japan)
|
||||
serial: SLPS-25923
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
@@ -46244,7 +46243,7 @@
|
||||
- hashes:
|
||||
- md5: ecb21ce06339ab6b628e077f3c03690b
|
||||
size: 3962535936
|
||||
name: Suigetsu - Mayoi Gokoro (Japan)
|
||||
name: Suigetsu - Mayoigokoro (Japan)
|
||||
serial: SLPM-65751
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -47270,7 +47269,7 @@
|
||||
- hashes:
|
||||
- md5: 68634f9b74fe47e4a039ada615970ca1
|
||||
size: 541969008
|
||||
name: Momotarou Dentetsu 15 - Godai Bombee Toujou! no Maki (Japan) (v2.00)
|
||||
name: Momotarou Dentetsu 15 - Godai Bonby Toujou! no Maki (Japan) (v2.00)
|
||||
serial: SLPM-74104
|
||||
version: '2.00'
|
||||
- hashes:
|
||||
@@ -49343,8 +49342,7 @@
|
||||
- hashes:
|
||||
- md5: 72e49d4201496dea3e0851abf58098cf
|
||||
size: 4677992448
|
||||
name: Official PlayStation 2 Magazine Germany Special Edition 2003-01 (Germany)
|
||||
(En,De)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2003-01 (Germany) (En,De)
|
||||
serial: SCED-51512
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -49422,7 +49420,7 @@
|
||||
- hashes:
|
||||
- md5: aa26f473fc9ecf2df7fad3a9acc30351
|
||||
size: 3115188224
|
||||
name: Harukanaru Toki no Naka de 3 (Japan) (Triple Pack)
|
||||
name: Harukanaru Toki no Naka de 3 (Japan) (Premium Box)
|
||||
serial: SLPM-65850
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
@@ -51309,12 +51307,6 @@
|
||||
name: Magazine Ufficiale PlayStation 2 Demo Italia 05-2006 (Italy) (En,Fr,De,Es,It)
|
||||
serial: SCED-54180
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 0b14951eb38e4f5f4730bcf48bf64898
|
||||
size: 4569923584
|
||||
name: Magazine Ufficiale PlayStation 2 Italia 05-04 (Italy) (En,Fr,De,Es,It)
|
||||
serial: SCED-52443
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 771bfe48ce1a10c8a638da8bedc9acf6
|
||||
size: 4175429632
|
||||
@@ -51698,13 +51690,13 @@
|
||||
- hashes:
|
||||
- md5: cf45002cd37168e4a2b3a8f96c560941
|
||||
size: 3983638528
|
||||
name: Official PlayStation 2 Magazine Germany Special 2-2005 (Germany)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2005-02 (Germany)
|
||||
serial: SCED-53662
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 8191fa8441cd8c947ab80b9db6de0ce3
|
||||
size: 4583129088
|
||||
name: Official PlayStation 2 Magazine Germany Special 3-2005 (Germany)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2005-03 (Germany)
|
||||
serial: SCED-53938
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -51818,7 +51810,7 @@
|
||||
- hashes:
|
||||
- md5: 8e18b5399008416a7d012f2ea1bf9353
|
||||
size: 663976656
|
||||
name: Pro Evolution Soccer 3 (Europe) (Demo 1)
|
||||
name: Pro Evolution Soccer 3 (UK) (Demo)
|
||||
serial: SLED-51992
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -51950,7 +51942,7 @@
|
||||
- hashes:
|
||||
- md5: 209c4247ffb84795b23ce2cec0f090a4
|
||||
size: 3793453056
|
||||
name: Official PlayStation 2 Magazine Germany Special Edition 2003-03 (Germany)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2003-03 (Germany)
|
||||
serial: SCED-51551
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -52038,7 +52030,7 @@
|
||||
- hashes:
|
||||
- md5: e8e5b428c642c78d510cbd854c17b9cc
|
||||
size: 1616740352
|
||||
name: Primal + The Mark of Kri + War of the Monsters (Europe) (En,Fr,De,Es,It)
|
||||
name: Primal & The Mark of Kri & War of the Monsters (Europe) (En,Fr,De,Es,It)
|
||||
serial: SCED-51506
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -52350,7 +52342,7 @@
|
||||
- hashes:
|
||||
- md5: d42eed1d14cdaf8add8295116776a447
|
||||
size: 3765108736
|
||||
name: Best PS2 Games Ever 10 (Europe)
|
||||
name: Official PlayStation 2 Magazine-UK Special Edition - Yearbook 2002 (Europe)
|
||||
serial: SCED-51389
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -52637,7 +52629,7 @@
|
||||
- hashes:
|
||||
- md5: cded45ee044b5a7614644fa444a59989
|
||||
size: 4334157824
|
||||
name: Official PlayStation 2 Magazine Germany Special Edition 2003-02 (Germany)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2003-02 (Germany)
|
||||
serial: SCED-51549
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -53111,7 +53103,7 @@
|
||||
- hashes:
|
||||
- md5: f309b4b48dc775dbbde635a1ef3b662b
|
||||
size: 4522639360
|
||||
name: Germany Special Issue 3 (Germany)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 3 (Germany)
|
||||
serial: SCED-51375
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -54054,7 +54046,7 @@
|
||||
- hashes:
|
||||
- md5: ac5b76bd39b0cabd1acfe4dcb08df502
|
||||
size: 1649803264
|
||||
name: Primal + The Mark of Kri (Europe)
|
||||
name: Primal & The Mark of Kri (Europe)
|
||||
serial: SCED-51491
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -54085,7 +54077,7 @@
|
||||
- hashes:
|
||||
- md5: 2475b61666f06dc2aa9ca032f15a4cde
|
||||
size: 4241293312
|
||||
name: Official PlayStation 2 Magazine Germany Special Edition 2007-1 (Germany)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2007-01 (Germany)
|
||||
serial: SCED-54693
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
@@ -54462,7 +54454,7 @@
|
||||
- hashes:
|
||||
- md5: 97a9156abd199f588d4f46e9af7ab5a7
|
||||
size: 4107206656
|
||||
name: Vitamin X - We are Super Supriment Boys (Japan) (Genteiban)
|
||||
name: VitaminX - We are Super Supriment Boys (Japan) (Genteiban)
|
||||
serial: SLPS-25760
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -54767,7 +54759,7 @@
|
||||
- hashes:
|
||||
- md5: a4b5b1d6c13c15bc1bac6fc63622c9ee
|
||||
size: 2925920256
|
||||
name: Ever 17 - The Out of Infinity Premium Edition (Japan)
|
||||
name: Ever 17 - The Out of Infinity - Premium Edition (Japan)
|
||||
serial: SLPM-65421
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -55910,7 +55902,7 @@
|
||||
- hashes:
|
||||
- md5: 05b210d50d92a418ac1e37a1fff0df8a
|
||||
size: 243996480
|
||||
name: Giant Robo - The Animation - Chikyuu ga Seishi suru Hi (Japan)
|
||||
name: Giant Robo - The Animation - Chikyuu ga Seishi Suru Hi (Japan)
|
||||
serial: SLPM-62526
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
@@ -56111,7 +56103,7 @@
|
||||
- hashes:
|
||||
- md5: 45d62f1cf862b8e6c47d373a5c55d2f2
|
||||
size: 708511776
|
||||
name: Pro Evolution Soccer 4 (Europe) (Demo)
|
||||
name: Pro Evolution Soccer 4 (UK) (Demo)
|
||||
serial: SLED-52873
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
@@ -56171,7 +56163,7 @@
|
||||
- hashes:
|
||||
- md5: 139585af1bf276d5f2e17a32def4f66d
|
||||
size: 4528504832
|
||||
name: Official PlayStation 2 Magazine Germany Special Edition 1 (Germany)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 1 (Germany)
|
||||
serial: SCED-50780
|
||||
version: '1.10'
|
||||
- hashes:
|
||||
@@ -57668,7 +57660,7 @@
|
||||
- hashes:
|
||||
- md5: 1ce4a9368f7c6c73dcd983ad5f86f3eb
|
||||
size: 718702992
|
||||
name: MaxPlay (Europe) (Unl)
|
||||
name: Max Play (Europe) (Unl)
|
||||
version: 1.00 (European)
|
||||
- hashes:
|
||||
- md5: 8182f27cc5a0cac14da217e45861e49e
|
||||
@@ -57841,8 +57833,7 @@
|
||||
- hashes:
|
||||
- md5: 4fb718d2059a1843882a70b17922b483
|
||||
size: 4613996544
|
||||
name: Official PlayStation 2 Magazine Germany Special Edition 2005-01 (Germany)
|
||||
(En,De)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2005-01 (Germany) (En,De)
|
||||
serial: SCED-53298
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
@@ -57854,7 +57845,7 @@
|
||||
- hashes:
|
||||
- md5: 739a2f519751c64f7291d036105c2c0d
|
||||
size: 1670316032
|
||||
name: Buzz! Junior - Robojam (Europe) (Beta) (2007-01-12)
|
||||
name: Buzz! Junior - RoboJam (Europe) (Beta) (2007-01-12)
|
||||
serial: SCES-54676
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -58392,7 +58383,7 @@
|
||||
- hashes:
|
||||
- md5: 6969a8f3623387131e2e1d49fff4c3f5
|
||||
size: 4492853248
|
||||
name: Magical Tale - Chiicha na Mahoutsukai (Japan)
|
||||
name: Magical Tale - Chitcha na Mahoutsukai (Japan)
|
||||
serial: SLPM-65965
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -59340,7 +59331,7 @@
|
||||
- hashes:
|
||||
- md5: 8d61b97a6dd45165b012b338d42e53a8
|
||||
size: 2358018048
|
||||
name: Harry Potter and the Prisoner of Azkaban (Korea)
|
||||
name: Harry Potter-wa Azkaban-ui Joesu (Korea)
|
||||
serial: SLKA-25172
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -59646,7 +59637,7 @@
|
||||
- hashes:
|
||||
- md5: 1162e6411d9e16fbefc9fd8a9e886d70
|
||||
size: 4412145664
|
||||
name: Official PlayStation 2 Magazine Germany Winter 2006 (Germany) (En,De)
|
||||
name: Official PlayStation 2 Magazine - Winter 2006 (Germany) (En,De)
|
||||
serial: SCED-54558
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -60504,7 +60495,7 @@
|
||||
- hashes:
|
||||
- md5: 78f327cd6c0f2bd6f99a299e982b9a93
|
||||
size: 1253867520
|
||||
name: TOCA Race Driver 3 + V8 Supercars Australia 3 (Australia) (Demo)
|
||||
name: TOCA Race Driver 3 (Australia) (Demo)
|
||||
serial: SLED-53888
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -60764,7 +60755,7 @@
|
||||
- hashes:
|
||||
- md5: 7e964b27119adc590228452d42c634b0
|
||||
size: 4614062080
|
||||
name: Buzz! Hollywood Quiz (Europe) (En,Fr,Nl)
|
||||
name: Buzz! Hollywood Quiz (Belgium, Netherlands) (En,Fr,Nl)
|
||||
serial: SCES-54854
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -62041,7 +62032,7 @@
|
||||
- hashes:
|
||||
- md5: dd5ccdc3e325716d7f7ed08a9836f3f0
|
||||
size: 3938189312
|
||||
name: PlayStation 2 Revista Oficial - Portugal 9 (Portugal)
|
||||
name: Official PlayStation 2 Magazine Demo 32 (Portugal)
|
||||
serial: SCED-51657
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -62487,7 +62478,7 @@
|
||||
- hashes:
|
||||
- md5: fe79ea717184a278802679ef78f6df7b
|
||||
size: 7774928896
|
||||
name: Zhen San Guo Wu Shuang 5 Special (Taiwan)
|
||||
name: Zhen Sanguo Wushuang 5 Special (Taiwan)
|
||||
serial: SLAJ-35007
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -63024,7 +63015,7 @@
|
||||
- hashes:
|
||||
- md5: 18e6281d238ccb19e8975d45e8c157f0
|
||||
size: 3816554496
|
||||
name: Offizielle PlayStation 2 Magazin 02-2004, Das - Uncut Edition (Germany)
|
||||
name: Official PlayStation 2 Magazine 02-2004 - Uncut Edition (Germany)
|
||||
serial: SCED-52082
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -63141,7 +63132,7 @@
|
||||
- hashes:
|
||||
- md5: d38ab694e14843f16af11a15d1883023
|
||||
size: 4677795840
|
||||
name: Koi suru Otome to Shugo no Tate - The Shield of AIGIS (Japan)
|
||||
name: Koi Suru Otome to Shugo no Tate - The Shield of AIGIS (Japan)
|
||||
serial: SLPM-55098
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
@@ -63554,7 +63545,7 @@
|
||||
- hashes:
|
||||
- md5: 3acdf0ae8cc67fe9e0db9f4707cb3905
|
||||
size: 2638381056
|
||||
name: I Love Baseball - Pro Yakyuu o Koyonaku Ai suru Hitotachi e (Japan)
|
||||
name: I Love Baseball - Pro Yakyuu o Koyonaku Ai Suru Hitotachi e (Japan)
|
||||
serial: SLPM-65633
|
||||
version: '1.04'
|
||||
- hashes:
|
||||
@@ -63941,13 +63932,13 @@
|
||||
- hashes:
|
||||
- md5: 7ea2da0f39ae55794fd9fd5006b417cc
|
||||
size: 4446388224
|
||||
name: Offizielle PlayStation 2 Magazin 09-2004, Das (Germany)
|
||||
name: Official PlayStation 2 Magazine 09-2004 (Germany)
|
||||
serial: SCED-52089
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
- md5: 11b80bd02a0a874212b014c56e44a4c5
|
||||
size: 4033347584
|
||||
name: Offizielle PlayStation 2 Magazin 12-2003, Das (Germany)
|
||||
name: Official PlayStation Magazine 12-2003 (Germany)
|
||||
serial: SCED-51936
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -64181,7 +64172,7 @@
|
||||
- hashes:
|
||||
- md5: 8990d1c3b88b04b1bbc7a78ee3e9df2f
|
||||
size: 33821760
|
||||
name: Karat PS2-you Pro Action Replay 2 Taikenban (Japan) (Unl)
|
||||
name: Karat PS2-you Pro Action Replay 2 Taikenban (Japan) (Unl) (Rev 1)
|
||||
version: '1.7'
|
||||
- hashes:
|
||||
- md5: 4a2754811946ef9badbbd872f541a03f
|
||||
@@ -64254,7 +64245,7 @@
|
||||
- hashes:
|
||||
- md5: 0e35e8fd22fe57f8727b9764685bbc29
|
||||
size: 3871703040
|
||||
name: Offizielle PlayStation 2 Magazin, Das - Special Edition 2 (Germany)
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2 (Germany)
|
||||
serial: SCED-51161
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -64563,7 +64554,7 @@
|
||||
- hashes:
|
||||
- md5: 477eb508b08f59386478908e481eb8a1
|
||||
size: 4519690240
|
||||
name: Official PlayStation 2 Magazine - German Kids Special (Germany) (En,De)
|
||||
name: Official PlayStation 2 Magazine - Kids Special (Germany) (En,De)
|
||||
serial: SCED-53611
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -64580,7 +64571,7 @@
|
||||
- hashes:
|
||||
- md5: ac9cb481855792415314e06e5c12b291
|
||||
size: 664183632
|
||||
name: Pro Evolution Soccer 3 (Europe) (Demo 2)
|
||||
name: Pro Evolution Soccer 3 (Europe) (Demo)
|
||||
serial: SLED-51994
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -65185,7 +65176,7 @@
|
||||
- hashes:
|
||||
- md5: 86af0c99c8a8566e5f9307110f339e20
|
||||
size: 364475328
|
||||
name: Monopoly - Mezase!! Daifugou Jinsei!! (Japan)
|
||||
name: Monopoly - Mezase!! Daifugou Jinsei!! (Japan) (v2.00)
|
||||
serial: SLPS-20281
|
||||
version: '2.00'
|
||||
- hashes:
|
||||
@@ -66352,7 +66343,7 @@
|
||||
- hashes:
|
||||
- md5: ff59d561b843dbbb940c631d53294d63
|
||||
size: 1552318464
|
||||
name: Monsterspass (Austria, Switzerland) (En,Fr,De,Es,It,Nl,Pt)
|
||||
name: Monsterspass (Austria) (En,Fr,De,Es,It,Nl,Pt)
|
||||
serial: SCES-54704
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -66436,7 +66427,7 @@
|
||||
- hashes:
|
||||
- md5: 79fc6bc53ff748088a36d2f6778d0a0b
|
||||
size: 1943797760
|
||||
name: Big! Sports Quiz, The (Austria, Switzerland)
|
||||
name: Big! Sports Quiz, The (Austria)
|
||||
serial: SCES-54526
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -66803,7 +66794,7 @@
|
||||
- hashes:
|
||||
- md5: 91450691bed8af904b291c4d86c0c338
|
||||
size: 1645182976
|
||||
name: Jungle Party (Austria, Switzerland)
|
||||
name: Jungle Party (Austria)
|
||||
serial: SCES-54524
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -66934,7 +66925,7 @@
|
||||
- hashes:
|
||||
- md5: 777cd430a73b95945cee679a27446eed
|
||||
size: 2297200640
|
||||
name: Disney-Pixar Finding Nemo (Korea)
|
||||
name: Disney-Pixar Nemo-reul Chajaseo (Korea)
|
||||
serial: SLKA-25056
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -68550,7 +68541,7 @@
|
||||
- hashes:
|
||||
- md5: 5b315096f6bfc1897e52fec9c877b81d
|
||||
size: 4250206208
|
||||
name: Offizielle PlayStation 2 Magazin 13-2003, Das - Uncut Edition (Germany)
|
||||
name: Official PlayStation 2 Magazine 13-2003 - Uncut Edition (Germany)
|
||||
serial: SCED-51937
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
@@ -69278,7 +69269,7 @@
|
||||
- hashes:
|
||||
- md5: 6905874bbb6167417bac324464d70d28
|
||||
size: 541969008
|
||||
name: Momotarou Dentetsu 15 - Godai Bombee Toujou! no Maki (Japan) (v1.01)
|
||||
name: Momotarou Dentetsu 15 - Godai Bonby Toujou! no Maki (Japan) (v1.01)
|
||||
serial: SLPM-62702
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -69326,7 +69317,7 @@
|
||||
- hashes:
|
||||
- md5: 950783ce0723d41ff7aa46659a6eafbc
|
||||
size: 4492853248
|
||||
name: Magical Tale - Chiicha na Mahoutsukai (Japan) (Shokai Genteiban)
|
||||
name: Magical Tale - Chitcha na Mahoutsukai (Japan) (Shokai Genteiban)
|
||||
serial: SLPM-65964
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
@@ -69341,3 +69332,240 @@
|
||||
name: Quilt - Anata to Tsumugu Yume to Koi no Dress (Japan)
|
||||
serial: SLPM-66735
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
- md5: ad64473c57824cf607cf40a7d85cf36c
|
||||
size: 2300313600
|
||||
name: Guitar Hero (USA) (Demo)
|
||||
serial: SLUS-29177
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 667607deb941380aa4d13db387b93077
|
||||
size: 93254448
|
||||
name: Codes Exclusifs (France) (Unl)
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 589e37362d073b8ad52670cdd5664415
|
||||
size: 1822326784
|
||||
name: DearS (Japan) (Genteiban)
|
||||
serial: SLPS-25371
|
||||
version: '1.04'
|
||||
- hashes:
|
||||
- md5: 4afb874dc19e35051e79f7a881a584b4
|
||||
size: 1524793344
|
||||
name: Winning Post 6 - 2005-nendoban (Japan) (Premium Pack)
|
||||
serial: SLPM-65893
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
- md5: 132ce8a9e16ca7ef5a356aa111bce318
|
||||
size: 4354473984
|
||||
name: Jak 3 (Europe) (En,Fr,De,Es,It,Pt,Ko,Ru) (Beta) (2004-09-14)
|
||||
serial: SCES-52460
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 6432d610b89d00eb1eea2ee71cf27147
|
||||
size: 3007119360
|
||||
name: Buzz! The Schools Quiz (UK) (v1.00)
|
||||
serial: SCES-54941
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 3c47093b42a1e1a39692b220e7659ad9
|
||||
size: 4601774080
|
||||
name: Big! Pop Quiz, The (Austria)
|
||||
serial: SCES-55099
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 859073451dbb344df7cee32703245ed5
|
||||
size: 306380800
|
||||
name: Freaky Flyers (USA) (Demo)
|
||||
serial: SLUS-29051
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 8d987ddccb1e2ec4c068896a4182bc4c
|
||||
size: 1542029312
|
||||
name: Tennis no Oujisama - Smash Hit! 2 (Japan) (Shokai SP Genteiban C-Type)
|
||||
serial: SLPM-65453
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
- md5: b0a2a871249538d80b92e7ef837f20dd
|
||||
size: 761692848
|
||||
name: CD avec les Codes Action Replay Exclusivement pour le Jeu Enter the Matrix
|
||||
(France)
|
||||
version: 1.01 (European)
|
||||
- hashes:
|
||||
- md5: db0c13bd5bddb659d563b4e2c0fcd5e8
|
||||
size: 226549344
|
||||
name: Action Replay Ultimate Cheats for Use with Grand Theft Auto - Vice City (UK)
|
||||
(Unl)
|
||||
version: '1.30'
|
||||
- hashes:
|
||||
- md5: 7866eaffddb52bbf7375ab4deca20dd6
|
||||
size: 33821760
|
||||
name: Karat PS2-you Pro Action Replay 2 Taikenban (Japan) (Unl)
|
||||
version: '1.7'
|
||||
- hashes:
|
||||
- md5: 76b15475cac6977f2510ea07d9b87043
|
||||
size: 4348444672
|
||||
name: Official PlayStation 2 Magazine - Special Edition 2006-01 (Germany)
|
||||
serial: SCED-54034
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: c9f8be1699b50935c1e1989cd76bdbe1
|
||||
size: 697118688
|
||||
name: Online Start-Up Disc 4.0 - Broadband Only (USA) (v1.01)
|
||||
serial: PBPX-95248
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
- md5: d7cfe2da9a3598cb10bc61abd2657acd
|
||||
size: 3497885696
|
||||
name: Big! Movie Quiz, The (Austria)
|
||||
serial: SCES-54857
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 875894a624cc3d7bc81311985b5eeff7
|
||||
size: 549201408
|
||||
name: Argus-ui Jeonsa (Korea) (Cheheompan)
|
||||
serial: SCKA-90005
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 7f3b5e111ca4c77039a1641fe2785423
|
||||
size: 3271229440
|
||||
name: Mai-Otome HiME - Otome Butoushi!! (Japan) (Limited Edition)
|
||||
serial: SLPS-25680
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
- md5: 5626f8c491117a0924380c786ab7e458
|
||||
size: 3049783296
|
||||
name: Fire It Up Kids (Europe)
|
||||
serial: SCED-53678
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 7d6503407ba1ea104753be2bfe1283e3
|
||||
size: 2560065536
|
||||
name: Nickelodeon SpongeBob SquarePants - Movin' with Friends (Europe) (En,Fr,De,Es)
|
||||
(Beta) (2004-10-29)
|
||||
- hashes:
|
||||
- md5: baf280135d74603e097a813d52e25afa
|
||||
size: 707949648
|
||||
name: Pro Evolution Soccer 4 (Europe) (Demo)
|
||||
serial: SLED-52878
|
||||
version: '1.03'
|
||||
- hashes:
|
||||
- md5: 1fa77218061839d6ac9b39159fa46680
|
||||
size: 1249804288
|
||||
name: SingStar Rocks! (Europe) (Demo)
|
||||
serial: SCED-54086
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 2d91ab06f6fc0f918c9389990df71a63
|
||||
size: 1378156544
|
||||
name: This Is Football 2004 (Belgium) (Demo)
|
||||
serial: SCED-52321
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
- md5: 6917a832cf75177a18c4ef4499966ba4
|
||||
size: 3448471552
|
||||
name: Official PlayStation 2 Magazine Demo 10 (Spain)
|
||||
serial: SCED-50406
|
||||
- hashes:
|
||||
- md5: e1615a414d9b561e70b395155edb7e39
|
||||
size: 4697686016
|
||||
name: Chaos Legion (Europe) (Demo)
|
||||
serial: SLED-51808
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 670fabe932a7ad8b81f6356d162cdac6
|
||||
size: 4569923584
|
||||
name: Magazine Ufficiale PlayStation 2 Italia 05-04 (Italy) (En,Fr,De,Es,It)
|
||||
serial: SCED-52443
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: dd4dd82c735f0189b5cd91c0c5e4b327
|
||||
size: 364472976
|
||||
name: Monopoly - Mezase!! Daifugou Jinsei!! (Japan) (v1.04)
|
||||
serial: SLPS-20281
|
||||
version: '1.04'
|
||||
- hashes:
|
||||
- md5: 2be7a399436665d532383e9e6d21f7fb
|
||||
size: 1632665600
|
||||
name: Musashiden II - Blademaster (Japan) (Taikenban)
|
||||
serial: SLPM-61117
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 85f8dd4c84ac2fd97f4b154280c01910
|
||||
size: 1239580672
|
||||
name: Bratz - Rock Angelz (Denmark)
|
||||
serial: SLES-53578
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 36c27c981bfdd9f311ecc36da4ad7071
|
||||
size: 598507520
|
||||
name: Metal Gear Solid 2 - Sons of Liberty (Europe) (En,Fr,De) (Demo)
|
||||
serial: SLED-50782
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 626b946f71116a9ec455b41c0fb8aa3a
|
||||
size: 2710274048
|
||||
name: Bonus Demo 7 (15-16) (Europe)
|
||||
serial: SCED-52437
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
- md5: 2696c838c64d0f7f0c86adc5bbc1f54a
|
||||
size: 4292870144
|
||||
name: Buzz! The Big Quiz (Switzerland) (Fr,De,It)
|
||||
serial: SCES-54071
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 865cb20ccc3b938879eb3cae955ab70c
|
||||
size: 4598398976
|
||||
name: Buzz! The Mega Quiz (Switzerland) (Fr,De,It)
|
||||
serial: SCES-54506
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: f543c17d10aa576cc4ea74622a7050ee
|
||||
size: 750130416
|
||||
name: Code Breaker (USA) (Unl) (v4.0)
|
||||
version: '4.0'
|
||||
- hashes:
|
||||
- md5: bae22925feb7587573b663cc83bc1eb3
|
||||
size: 2719285248
|
||||
name: Kaido Battle 2 - Chain Reaction (Korea)
|
||||
serial: SLKA-25146
|
||||
version: '1.02'
|
||||
- hashes:
|
||||
- md5: 92c7a59eb4650bbc8a429970640b871b
|
||||
size: 748700400
|
||||
name: Time Crisis II (Europe) (Demo)
|
||||
serial: SCED-50473
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
- md5: fd46dd639a28f9f8ec7475f999d8b653
|
||||
size: 2786852864
|
||||
name: Call of Duty - World at War - Final Fronts (Korea)
|
||||
serial: SLKA-25449
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 41ccada9d75b88b20adf6db41349df52
|
||||
size: 4511367168
|
||||
name: Shijag-ui Ilbo All Stars (Korea)
|
||||
serial: SLKA-25152
|
||||
version: '1.01'
|
||||
- hashes:
|
||||
- md5: d46987283a22024d4b8e3e36c597035f
|
||||
size: 4116643840
|
||||
name: Fight Night Round 2 (Europe, Australia) (Demo)
|
||||
serial: SLED-53126
|
||||
version: '1.00'
|
||||
- hashes:
|
||||
- md5: 22a1b12df6fae4ecd8da5bed8cd91dd6
|
||||
size: 4192600064
|
||||
name: SOCOM 3 - U.S. Navy SEALs (USA) (Beta) (2005-09-08)
|
||||
- hashes:
|
||||
- md5: 3a04c1e3548d8169271336a73ae67e93
|
||||
size: 566942544
|
||||
name: Taz - Wanted (Europe) (2002-01-29)
|
||||
version: Beta
|
||||
- hashes:
|
||||
- md5: ecb58db2de607ed68a215d052381a83b
|
||||
size: 245814576
|
||||
name: Taz - Wanted (Europe) (2001-05-31)
|
||||
version: Beta
|
||||
|
||||
BIN
bin/resources/fullscreenui/flags/NTSC-B.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
bin/resources/fullscreenui/flags/NTSC-C.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
bin/resources/fullscreenui/flags/NTSC-HK.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
bin/resources/fullscreenui/flags/NTSC-J.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
bin/resources/fullscreenui/flags/NTSC-K.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
bin/resources/fullscreenui/flags/NTSC-T.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
bin/resources/fullscreenui/flags/NTSC-U.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
bin/resources/fullscreenui/flags/Other.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
bin/resources/fullscreenui/flags/PAL-A.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
bin/resources/fullscreenui/flags/PAL-AF.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
bin/resources/fullscreenui/flags/PAL-AU.png
Normal file
|
After Width: | Height: | Size: 144 B |
BIN
bin/resources/fullscreenui/flags/PAL-BE.png
Normal file
|
After Width: | Height: | Size: 322 B |
BIN
bin/resources/fullscreenui/flags/PAL-E.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
bin/resources/fullscreenui/flags/PAL-F.png
Normal file
|
After Width: | Height: | Size: 261 B |
BIN
bin/resources/fullscreenui/flags/PAL-FI.png
Normal file
|
After Width: | Height: | Size: 334 B |
BIN
bin/resources/fullscreenui/flags/PAL-G.png
Normal file
|
After Width: | Height: | Size: 361 B |
BIN
bin/resources/fullscreenui/flags/PAL-GR.png
Normal file
|
After Width: | Height: | Size: 655 B |
BIN
bin/resources/fullscreenui/flags/PAL-I.png
Normal file
|
After Width: | Height: | Size: 247 B |
BIN
bin/resources/fullscreenui/flags/PAL-IN.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
bin/resources/fullscreenui/flags/PAL-M.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
bin/resources/fullscreenui/flags/PAL-NL.png
Normal file
|
After Width: | Height: | Size: 265 B |
BIN
bin/resources/fullscreenui/flags/PAL-NO.png
Normal file
|
After Width: | Height: | Size: 675 B |
BIN
bin/resources/fullscreenui/flags/PAL-P.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
bin/resources/fullscreenui/flags/PAL-PL.png
Normal file
|
After Width: | Height: | Size: 140 B |
BIN
bin/resources/fullscreenui/flags/PAL-R.png
Normal file
|
After Width: | Height: | Size: 265 B |
BIN
bin/resources/fullscreenui/flags/PAL-S.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
bin/resources/fullscreenui/flags/PAL-SC.png
Normal file
|
After Width: | Height: | Size: 587 B |
BIN
bin/resources/fullscreenui/flags/PAL-SW.png
Normal file
|
After Width: | Height: | Size: 331 B |
BIN
bin/resources/fullscreenui/flags/PAL-SWI.png
Normal file
|
After Width: | Height: | Size: 751 B |
BIN
bin/resources/fullscreenui/flags/PAL-UK.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
bin/resources/fullscreenui/star-0.png
Normal file
|
After Width: | Height: | Size: 296 B |
BIN
bin/resources/fullscreenui/star-1.png
Normal file
|
After Width: | Height: | Size: 442 B |
BIN
bin/resources/fullscreenui/star-2.png
Normal file
|
After Width: | Height: | Size: 534 B |
BIN
bin/resources/fullscreenui/star-3.png
Normal file
|
After Width: | Height: | Size: 505 B |
BIN
bin/resources/fullscreenui/star-4.png
Normal file
|
After Width: | Height: | Size: 442 B |
BIN
bin/resources/fullscreenui/star-5.png
Normal file
|
After Width: | Height: | Size: 297 B |
@@ -1478,13 +1478,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux,
|
||||
05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
|
||||
050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,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,
|
||||
050000005a1d00000218000003000000,Nokia GC 5000,a:b9,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,
|
||||
030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
|
||||
030000007e0500001920000011810000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux,
|
||||
030000007e0500001920000011810000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux,
|
||||
050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux,
|
||||
050000007e0500001920000001800000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux,
|
||||
030000007e0500001720000011810000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
|
||||
050000007e0500001920000001800000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux,
|
||||
030000007e0500001720000011810000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
|
||||
050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b8,start:b10,x:b3,y:b2,platform:Linux,
|
||||
050000007e0500001720000001800000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
|
||||
050000007e0500001720000001800000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
|
||||
03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000550900001472000011010000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
|
||||
05000000550900001472000001000000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
|
||||
|
||||
@@ -160,10 +160,7 @@ float FxaaLuma(float4 rgba)
|
||||
|
||||
float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaSubpix, float fxaaEdgeThreshold, float fxaaEdgeThresholdMin)
|
||||
{
|
||||
float2 posM;
|
||||
posM.x = pos.x;
|
||||
posM.y = pos.y;
|
||||
|
||||
float2 posM = pos;
|
||||
float4 rgbyM = FxaaTexTop(tex, posM);
|
||||
rgbyM.w = RGBLuminance(rgbyM.xyz);
|
||||
#define lumaM rgbyM.w
|
||||
@@ -186,9 +183,10 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
|
||||
float rangeMaxScaled = rangeMax * fxaaEdgeThreshold;
|
||||
float rangeMaxClamped = max(fxaaEdgeThresholdMin, rangeMaxScaled);
|
||||
|
||||
bool earlyExit = range < rangeMaxClamped;
|
||||
#if (FxaaEarlyExit == 1)
|
||||
if(earlyExit) { return rgbyM; }
|
||||
// Potential optimization, early exit.
|
||||
if (range < rangeMaxClamped)
|
||||
return rgbyM;
|
||||
#endif
|
||||
|
||||
float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1,-1), fxaaRcpFrame.xy));
|
||||
|
||||
@@ -170,7 +170,7 @@ PS_OUTPUT ps_rta_decorrection(PS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_hdr_init(PS_INPUT input)
|
||||
PS_OUTPUT ps_colclip_init(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
float4 value = sample_c(input.t);
|
||||
@@ -178,7 +178,7 @@ PS_OUTPUT ps_hdr_init(PS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_hdr_resolve(PS_INPUT input)
|
||||
PS_OUTPUT ps_colclip_resolve(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
float4 value = sample_c(input.t);
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
#define PS_CHANNEL_FETCH 0
|
||||
#define PS_TALES_OF_ABYSS_HLE 0
|
||||
#define PS_URBAN_CHAOS_HLE 0
|
||||
#define PS_HDR 0
|
||||
#define PS_COLCLIP_HW 0
|
||||
#define PS_RTA_CORRECTION 0
|
||||
#define PS_RTA_SRC_CORRECTION 0
|
||||
#define PS_COLCLIP 0
|
||||
@@ -799,7 +799,7 @@ void ps_fbmask(inout float4 C, float2 pos_xy)
|
||||
{
|
||||
if (PS_FBMASK)
|
||||
{
|
||||
float multi = PS_HDR ? 65535.0f : 255.0f;
|
||||
float multi = PS_COLCLIP_HW ? 65535.0f : 255.0f;
|
||||
float4 RT = trunc(RtTexture.Load(int3(pos_xy, 0)) * multi + 0.1f);
|
||||
C = (float4)(((uint4)C & ~FbMask) | ((uint4)RT & FbMask));
|
||||
}
|
||||
@@ -843,13 +843,13 @@ void ps_color_clamp_wrap(inout float3 C)
|
||||
C += 7.0f; // Need to round up, not down since the shader will invert
|
||||
|
||||
// Standard Clamp
|
||||
if (PS_COLCLIP == 0 && PS_HDR == 0)
|
||||
if (PS_COLCLIP == 0 && PS_COLCLIP_HW == 0)
|
||||
C = clamp(C, (float3)0.0f, (float3)255.0f);
|
||||
|
||||
// In 16 bits format, only 5 bits of color are used. It impacts shadows computation of Castlevania
|
||||
if (PS_DST_FMT == FMT_16 && PS_DITHER != 3 && (PS_BLEND_MIX == 0 || PS_DITHER))
|
||||
C = (float3)((int3)C & (int3)0xF8);
|
||||
else if (PS_COLCLIP == 1 || PS_HDR == 1)
|
||||
else if (PS_COLCLIP == 1 || PS_COLCLIP_HW == 1)
|
||||
C = (float3)((int3)C & (int3)0xFF);
|
||||
}
|
||||
else if (PS_DST_FMT == FMT_16 && PS_DITHER != 3 && PS_BLEND_MIX == 0 && PS_BLEND_HW == 0)
|
||||
@@ -898,7 +898,7 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
|
||||
}
|
||||
|
||||
float Ad = PS_RTA_CORRECTION ? trunc(RT.a * 128.0f + 0.1f) / 128.0f : trunc(RT.a * 255.0f + 0.1f) / 128.0f;
|
||||
float color_multi = PS_HDR ? 65535.0f : 255.0f;
|
||||
float color_multi = PS_COLCLIP_HW ? 65535.0f : 255.0f;
|
||||
float3 Cd = trunc(RT.rgb * color_multi + 0.1f);
|
||||
float3 Cs = Color.rgb;
|
||||
|
||||
@@ -1157,7 +1157,7 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
|
||||
#if !PS_NO_COLOR
|
||||
output.c0.a = PS_RTA_CORRECTION ? C.a / 128.0f : C.a / 255.0f;
|
||||
output.c0.rgb = PS_HDR ? float3(C.rgb / 65535.0f) : C.rgb / 255.0f;
|
||||
output.c0.rgb = PS_COLCLIP_HW ? float3(C.rgb / 65535.0f) : C.rgb / 255.0f;
|
||||
#if !PS_NO_COLOR1
|
||||
output.c1 = alpha_blend;
|
||||
#endif
|
||||
|
||||
@@ -348,16 +348,16 @@ void ps_rta_decorrection()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_hdr_init
|
||||
void ps_hdr_init()
|
||||
#ifdef ps_colclip_init
|
||||
void ps_colclip_init()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_hdr_resolve
|
||||
void ps_hdr_resolve()
|
||||
#ifdef ps_colclip_resolve
|
||||
void ps_colclip_resolve()
|
||||
{
|
||||
vec4 value = sample_c();
|
||||
SV_Target0 = vec4(vec3(uvec3(value.rgb * 65535.0f) & 255u) / 255.0f, value.a);
|
||||
|
||||
@@ -707,7 +707,7 @@ void ps_fbmask(inout vec4 C)
|
||||
{
|
||||
// FIXME do I need special case for 16 bits
|
||||
#if PS_FBMASK
|
||||
#if PS_HDR == 1
|
||||
#if PS_COLCLIP_HW == 1
|
||||
vec4 RT = trunc(sample_from_rt() * 65535.0f);
|
||||
#else
|
||||
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);
|
||||
@@ -757,7 +757,7 @@ void ps_color_clamp_wrap(inout vec3 C)
|
||||
#endif
|
||||
|
||||
// Correct the Color value based on the output format
|
||||
#if PS_COLCLIP == 0 && PS_HDR == 0
|
||||
#if PS_COLCLIP == 0 && PS_COLCLIP_HW == 0
|
||||
// Standard Clamp
|
||||
C = clamp(C, vec3(0.0f), vec3(255.0f));
|
||||
#endif
|
||||
@@ -771,7 +771,7 @@ void ps_color_clamp_wrap(inout vec3 C)
|
||||
#if PS_DST_FMT == FMT_16 && PS_DITHER < 3 && (PS_BLEND_MIX == 0 || PS_DITHER)
|
||||
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
|
||||
C = vec3(ivec3(C) & ivec3(0xF8));
|
||||
#elif PS_COLCLIP == 1 || PS_HDR == 1
|
||||
#elif PS_COLCLIP == 1 || PS_COLCLIP_HW == 1
|
||||
C = vec3(ivec3(C) & ivec3(0xFF));
|
||||
#endif
|
||||
|
||||
@@ -828,7 +828,7 @@ float As = As_rgba.a;
|
||||
#endif
|
||||
|
||||
// Let the compiler do its jobs !
|
||||
#if PS_HDR == 1
|
||||
#if PS_COLCLIP_HW == 1
|
||||
vec3 Cd = trunc(RT.rgb * 65535.0f);
|
||||
#else
|
||||
vec3 Cd = trunc(RT.rgb * 255.0f + 0.1f);
|
||||
@@ -1125,7 +1125,7 @@ void ps_main()
|
||||
#else
|
||||
SV_Target0.a = C.a / 255.0f;
|
||||
#endif
|
||||
#if PS_HDR == 1
|
||||
#if PS_COLCLIP_HW == 1
|
||||
SV_Target0.rgb = vec3(C.rgb / 65535.0f);
|
||||
#else
|
||||
SV_Target0.rgb = C.rgb / 255.0f;
|
||||
|
||||
@@ -148,16 +148,16 @@ void ps_rta_decorrection()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_hdr_init
|
||||
void ps_hdr_init()
|
||||
#ifdef ps_colclip_init
|
||||
void ps_colclip_init()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(roundEven(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_hdr_resolve
|
||||
void ps_hdr_resolve()
|
||||
#ifdef ps_colclip_resolve
|
||||
void ps_colclip_resolve()
|
||||
{
|
||||
vec4 value = sample_c(v_tex);
|
||||
o_col0 = vec4(vec3(uvec3(value.rgb * 65535.5f) & 255u) / 255.0f, value.a);
|
||||
|
||||
@@ -281,7 +281,7 @@ void main()
|
||||
#define PS_CHANNEL_FETCH 0
|
||||
#define PS_TALES_OF_ABYSS_HLE 0
|
||||
#define PS_URBAN_CHAOS_HLE 0
|
||||
#define PS_HDR 0
|
||||
#define PS_COLCLIP_HW 0
|
||||
#define PS_COLCLIP 0
|
||||
#define PS_BLEND_A 0
|
||||
#define PS_BLEND_B 0
|
||||
@@ -974,7 +974,7 @@ void ps_fbmask(inout vec4 C)
|
||||
{
|
||||
#if PS_FBMASK
|
||||
|
||||
#if PS_HDR == 1
|
||||
#if PS_COLCLIP_HW == 1
|
||||
vec4 RT = trunc(sample_from_rt() * 65535.0f);
|
||||
#else
|
||||
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);
|
||||
@@ -1027,7 +1027,7 @@ void ps_color_clamp_wrap(inout vec3 C)
|
||||
#endif
|
||||
|
||||
// Correct the Color value based on the output format
|
||||
#if PS_COLCLIP == 0 && PS_HDR == 0
|
||||
#if PS_COLCLIP == 0 && PS_COLCLIP_HW == 0
|
||||
// Standard Clamp
|
||||
C = clamp(C, vec3(0.0f), vec3(255.0f));
|
||||
#endif
|
||||
@@ -1041,7 +1041,7 @@ void ps_color_clamp_wrap(inout vec3 C)
|
||||
#if PS_DST_FMT == FMT_16 && PS_DITHER != 3 && (PS_BLEND_MIX == 0 || PS_DITHER > 0)
|
||||
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
|
||||
C = vec3(ivec3(C) & ivec3(0xF8));
|
||||
#elif PS_COLCLIP == 1 || PS_HDR == 1
|
||||
#elif PS_COLCLIP == 1 || PS_COLCLIP_HW == 1
|
||||
C = vec3(ivec3(C) & ivec3(0xFF));
|
||||
#endif
|
||||
|
||||
@@ -1098,7 +1098,7 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
|
||||
#endif
|
||||
|
||||
// Let the compiler do its jobs !
|
||||
#if PS_HDR == 1
|
||||
#if PS_COLCLIP_HW == 1
|
||||
vec3 Cd = trunc(RT.rgb * 65535.0f);
|
||||
#else
|
||||
vec3 Cd = trunc(RT.rgb * 255.0f + 0.1f);
|
||||
@@ -1390,7 +1390,7 @@ void main()
|
||||
#else
|
||||
o_col0.a = C.a / 255.0f;
|
||||
#endif
|
||||
#if PS_HDR == 1
|
||||
#if PS_COLCLIP_HW == 1
|
||||
o_col0.rgb = vec3(C.rgb / 65535.0f);
|
||||
#else
|
||||
o_col0.rgb = C.rgb / 255.0f;
|
||||
|
||||
@@ -50,6 +50,32 @@ u64 GetPhysicalMemory()
|
||||
return getmem;
|
||||
}
|
||||
|
||||
u64 GetAvailablePhysicalMemory()
|
||||
{
|
||||
const mach_port_t host_port = mach_host_self();
|
||||
vm_size_t page_size;
|
||||
|
||||
// Get the system's page size.
|
||||
if (host_page_size(host_port, &page_size) != KERN_SUCCESS)
|
||||
return 0;
|
||||
|
||||
vm_statistics64_data_t vm_stat;
|
||||
mach_msg_type_number_t host_size = sizeof(vm_statistics64_data_t) / sizeof(integer_t);
|
||||
|
||||
// Get system memory statistics.
|
||||
if (host_statistics64(host_port, HOST_VM_INFO, reinterpret_cast<host_info64_t>(&vm_stat), &host_size) != KERN_SUCCESS)
|
||||
return 0;
|
||||
|
||||
// Get the number of free and inactive pages.
|
||||
const u64 free_pages = static_cast<u64>(vm_stat.free_count);
|
||||
const u64 inactive_pages = static_cast<u64>(vm_stat.inactive_count);
|
||||
|
||||
// Calculate available memory.
|
||||
const u64 get_available_mem = (free_pages + inactive_pages) * page_size;
|
||||
|
||||
return get_available_mem;
|
||||
}
|
||||
|
||||
static mach_timebase_info_data_t s_timebase_info;
|
||||
static const u64 tickfreq = []() {
|
||||
if (mach_timebase_info(&s_timebase_info) != KERN_SUCCESS)
|
||||
|
||||
@@ -181,10 +181,7 @@ private:
|
||||
extern u64 GetTickFrequency();
|
||||
extern u64 GetCPUTicks();
|
||||
extern u64 GetPhysicalMemory();
|
||||
#ifdef _WIN32
|
||||
// TODO: Someone do linux/mac.
|
||||
extern u64 GetAvailablePhysicalMemory();
|
||||
#endif
|
||||
/// Spin for a short period of time (call while spinning waiting for a lock)
|
||||
/// Returns the approximate number of ns that passed
|
||||
extern u32 ShortSpin();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <spawn.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
@@ -40,6 +41,49 @@ u64 GetPhysicalMemory()
|
||||
return pages * getpagesize();
|
||||
}
|
||||
|
||||
u64 GetAvailablePhysicalMemory()
|
||||
{
|
||||
// Try to read MemAvailable from /proc/meminfo.
|
||||
FILE* file = fopen("/proc/meminfo", "r");
|
||||
if (file)
|
||||
{
|
||||
u64 mem_available = 0;
|
||||
u64 mem_free = 0, buffers = 0, cached = 0, sreclaimable = 0, shmem = 0;
|
||||
char line[256];
|
||||
|
||||
while (fgets(line, sizeof(line), file))
|
||||
{
|
||||
// Modern kernels provide MemAvailable directly - preferred and most accurate.
|
||||
if (sscanf(line, "MemAvailable: %llu kB", &mem_available) == 1)
|
||||
{
|
||||
fclose(file);
|
||||
return mem_available * _1kb;
|
||||
}
|
||||
|
||||
// Fallback values for manual approximation.
|
||||
sscanf(line, "MemFree: %llu kB", &mem_free);
|
||||
sscanf(line, "Buffers: %llu kB", &buffers);
|
||||
sscanf(line, "Cached: %llu kB", &cached);
|
||||
sscanf(line, "SReclaimable: %llu kB", &sreclaimable);
|
||||
sscanf(line, "Shmem: %llu kB", &shmem);
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
// Fallback approximation: Linux-like heuristic.
|
||||
// available = MemFree + Buffers + Cached + SReclaimable - Shmem.
|
||||
const u64 available_kb = mem_free + buffers + cached + sreclaimable - shmem;
|
||||
return available_kb * _1kb;
|
||||
}
|
||||
|
||||
// Fallback to sysinfo if /proc/meminfo couldn't be read.
|
||||
struct sysinfo info = {};
|
||||
if (sysinfo(&info) != 0)
|
||||
return 0;
|
||||
|
||||
// Note: This does NOT include cached memory - only free + buffer.
|
||||
return (static_cast<u64>(info.freeram) + static_cast<u64>(info.bufferram)) * static_cast<u64>(info.mem_unit);
|
||||
}
|
||||
|
||||
u64 GetTickFrequency()
|
||||
{
|
||||
return 1000000000; // unix measures in nanoseconds
|
||||
|
||||
@@ -42,6 +42,7 @@ BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu, Breakpo
|
||||
m_ui.rdoExecute->setChecked(true);
|
||||
m_ui.chkEnable->setChecked(bp->enabled);
|
||||
m_ui.txtAddress->setText(QtUtils::FilledQStringFromValue(bp->addr, 16));
|
||||
m_ui.txtDescription->setText(QString::fromStdString(bp->description));
|
||||
|
||||
if (bp->hasCond)
|
||||
m_ui.txtCondition->setText(QString::fromStdString(bp->cond.expressionString));
|
||||
@@ -53,6 +54,8 @@ BreakpointDialog::BreakpointDialog(QWidget* parent, DebugInterface* cpu, Breakpo
|
||||
m_ui.txtAddress->setText(QtUtils::FilledQStringFromValue(mc->start, 16));
|
||||
m_ui.txtSize->setText(QtUtils::FilledQStringFromValue(mc->end - mc->start, 16));
|
||||
|
||||
m_ui.txtDescription->setText(QString::fromStdString(mc->description));
|
||||
|
||||
m_ui.chkRead->setChecked(mc->memCond & MEMCHECK_READ);
|
||||
m_ui.chkWrite->setChecked(mc->memCond & MEMCHECK_WRITE);
|
||||
m_ui.chkChange->setChecked(mc->memCond & MEMCHECK_WRITE_ONCHANGE);
|
||||
@@ -102,6 +105,7 @@ void BreakpointDialog::accept()
|
||||
}
|
||||
|
||||
bp->addr = address;
|
||||
bp->description = m_ui.txtDescription->text().toStdString();
|
||||
|
||||
bp->enabled = m_ui.chkEnable->isChecked();
|
||||
|
||||
@@ -138,6 +142,7 @@ void BreakpointDialog::accept()
|
||||
|
||||
mc->start = startAddress;
|
||||
mc->end = startAddress + size;
|
||||
mc->description = m_ui.txtDescription->text().toStdString();
|
||||
|
||||
if (!m_ui.txtCondition->text().isEmpty())
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>375</width>
|
||||
<height>250</height>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@@ -22,19 +22,19 @@
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>375</width>
|
||||
<height>250</height>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>375</width>
|
||||
<height>250</height>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>375</width>
|
||||
<height>250</height>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -44,7 +44,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
<y>210</y>
|
||||
<y>260</y>
|
||||
<width>341</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
@@ -102,14 +102,17 @@
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>10</y>
|
||||
<width>251</width>
|
||||
<height>41</height>
|
||||
<width>250</width>
|
||||
<height>79</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
@@ -139,6 +142,29 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="txtDescription">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>19</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>19</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="grpMemory">
|
||||
@@ -148,7 +174,7 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>50</y>
|
||||
<y>100</y>
|
||||
<width>251</width>
|
||||
<height>91</height>
|
||||
</rect>
|
||||
@@ -224,13 +250,13 @@
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>110</x>
|
||||
<y>140</y>
|
||||
<y>190</y>
|
||||
<width>251</width>
|
||||
<height>61</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string></string>
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_3">
|
||||
<item row="0" column="0">
|
||||
|
||||
@@ -72,11 +72,13 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
|
||||
switch (index.column())
|
||||
{
|
||||
case BreakpointColumns::ENABLED:
|
||||
return "";
|
||||
return (bp->enabled) ? tr("Enabled") : tr("Disabled");
|
||||
case BreakpointColumns::TYPE:
|
||||
return tr("Execute");
|
||||
case BreakpointColumns::OFFSET:
|
||||
return QtUtils::FilledQStringFromValue(bp->addr, 16);
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return QString::fromStdString(bp->description);
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return QString::fromStdString(m_cpu.GetSymbolGuardian().FunctionStartingAtAddress(bp->addr).name);
|
||||
case BreakpointColumns::OPCODE:
|
||||
@@ -105,6 +107,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
|
||||
}
|
||||
case BreakpointColumns::OFFSET:
|
||||
return QtUtils::FilledQStringFromValue(mc->start, 16);
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return QString::fromStdString(mc->description);
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return QString::number(mc->end - mc->start, 16);
|
||||
case BreakpointColumns::OPCODE:
|
||||
@@ -116,6 +120,29 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == Qt::EditRole)
|
||||
{
|
||||
if (const auto* bp = std::get_if<BreakPoint>(&bp_mc))
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case BreakpointColumns::CONDITION:
|
||||
return bp->hasCond ? QString::fromStdString(bp->cond.expressionString) : "";
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return QString::fromStdString(bp->description);
|
||||
}
|
||||
}
|
||||
else if (const auto* mc = std::get_if<MemCheck>(&bp_mc))
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case BreakpointColumns::CONDITION:
|
||||
return mc->hasCond ? QString::fromStdString(mc->cond.expressionString) : "";
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return QString::fromStdString(mc->description);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (role == BreakpointModel::DataRole)
|
||||
{
|
||||
if (const auto* bp = std::get_if<BreakPoint>(&bp_mc))
|
||||
@@ -128,6 +155,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
|
||||
return MEMCHECK_INVALID;
|
||||
case BreakpointColumns::OFFSET:
|
||||
return bp->addr;
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return QString::fromStdString(bp->description);
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return QString::fromStdString(m_cpu.GetSymbolGuardian().FunctionStartingAtAddress(bp->addr).name);
|
||||
case BreakpointColumns::OPCODE:
|
||||
@@ -149,6 +178,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
|
||||
return mc->memCond;
|
||||
case BreakpointColumns::OFFSET:
|
||||
return mc->start;
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return QString::fromStdString(mc->description);
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return mc->end - mc->start;
|
||||
case BreakpointColumns::OPCODE:
|
||||
@@ -172,6 +203,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
|
||||
return MEMCHECK_INVALID;
|
||||
case BreakpointColumns::OFFSET:
|
||||
return QtUtils::FilledQStringFromValue(bp->addr, 16);
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return QString::fromStdString(bp->description);
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return QString::fromStdString(m_cpu.GetSymbolGuardian().FunctionStartingAtAddress(bp->addr).name);
|
||||
case BreakpointColumns::OPCODE:
|
||||
@@ -191,6 +224,8 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
|
||||
return mc->memCond;
|
||||
case BreakpointColumns::OFFSET:
|
||||
return QtUtils::FilledQStringFromValue(mc->start, 16);
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return QString::fromStdString(mc->description);
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return mc->end - mc->start;
|
||||
case BreakpointColumns::OPCODE:
|
||||
@@ -233,6 +268,8 @@ QVariant BreakpointModel::headerData(int section, Qt::Orientation orientation, i
|
||||
case BreakpointColumns::OFFSET:
|
||||
//: Warning: limited space available. Abbreviate if needed.
|
||||
return tr("OFFSET");
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return "DESCRIPTION";
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
//: Warning: limited space available. Abbreviate if needed.
|
||||
return tr("SIZE / LABEL");
|
||||
@@ -260,6 +297,8 @@ QVariant BreakpointModel::headerData(int section, Qt::Orientation orientation, i
|
||||
return "TYPE";
|
||||
case BreakpointColumns::OFFSET:
|
||||
return "OFFSET";
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return "DESCRIPTION";
|
||||
case BreakpointColumns::SIZE_LABEL:
|
||||
return "SIZE / LABEL";
|
||||
case BreakpointColumns::OPCODE:
|
||||
@@ -282,6 +321,7 @@ Qt::ItemFlags BreakpointModel::flags(const QModelIndex& index) const
|
||||
switch (index.column())
|
||||
{
|
||||
case BreakpointColumns::CONDITION:
|
||||
case BreakpointColumns::DESCRIPTION:
|
||||
return Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable | Qt::ItemFlag::ItemIsEditable;
|
||||
case BreakpointColumns::TYPE:
|
||||
case BreakpointColumns::OPCODE:
|
||||
@@ -395,6 +435,27 @@ bool BreakpointModel::setData(const QModelIndex& index, const QVariant& value, i
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
else if (role == Qt::EditRole && index.column() == BreakpointColumns::DESCRIPTION)
|
||||
{
|
||||
// Update BreakPoint description
|
||||
if (auto* bp = std::get_if<BreakPoint>(&bp_mc))
|
||||
{
|
||||
const QString descValue = value.toString();
|
||||
Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), bp, descValue] {
|
||||
CBreakPoints::ChangeBreakPointDescription(cpu, bp->addr, descValue.toStdString());
|
||||
});
|
||||
}
|
||||
// Update MemCheck description
|
||||
else if (auto* mc = std::get_if<MemCheck>(&bp_mc))
|
||||
{
|
||||
const QString descValue = value.toString();
|
||||
Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), mc, descValue] {
|
||||
CBreakPoints::ChangeMemCheckDescription(cpu, mc->start, mc->end, descValue.toStdString());
|
||||
});
|
||||
}
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -451,7 +512,7 @@ bool BreakpointModel::insertBreakpointRows(int row, int count, std::vector<Break
|
||||
{
|
||||
Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), bp = *bp] {
|
||||
CBreakPoints::AddBreakPoint(cpu, bp.addr, false, bp.enabled);
|
||||
|
||||
CBreakPoints::ChangeBreakPointDescription(cpu, bp.addr, bp.description);
|
||||
if (bp.hasCond)
|
||||
{
|
||||
CBreakPoints::ChangeBreakPointAddCond(cpu, bp.addr, bp.cond);
|
||||
@@ -462,6 +523,7 @@ bool BreakpointModel::insertBreakpointRows(int row, int count, std::vector<Break
|
||||
{
|
||||
Host::RunOnCPUThread([cpu = m_cpu.getCpuType(), mc = *mc] {
|
||||
CBreakPoints::AddMemCheck(cpu, mc.start, mc.end, mc.memCond, mc.result);
|
||||
CBreakPoints::ChangeMemCheckDescription(cpu, mc.start, mc.end, mc.description);
|
||||
if (mc.hasCond)
|
||||
{
|
||||
CBreakPoints::ChangeMemCheckAddCond(cpu, mc.start, mc.end, mc.cond);
|
||||
@@ -548,6 +610,12 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields)
|
||||
return;
|
||||
}
|
||||
|
||||
// Description
|
||||
if (!fields[BreakpointColumns::DESCRIPTION].isEmpty())
|
||||
{
|
||||
bp.description = fields[BreakpointColumns::DESCRIPTION].toStdString();
|
||||
}
|
||||
|
||||
insertBreakpointRows(0, 1, {bp});
|
||||
}
|
||||
else
|
||||
@@ -608,6 +676,12 @@ void BreakpointModel::loadBreakpointFromFieldList(QStringList fields)
|
||||
}
|
||||
mc.result = static_cast<MemCheckResult>(result);
|
||||
|
||||
// Description
|
||||
if (!fields[BreakpointColumns::DESCRIPTION].isEmpty())
|
||||
{
|
||||
mc.description = fields[BreakpointColumns::DESCRIPTION].toStdString();
|
||||
}
|
||||
|
||||
insertBreakpointRows(0, 1, {mc});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public:
|
||||
ENABLED = 0,
|
||||
TYPE,
|
||||
OFFSET,
|
||||
DESCRIPTION,
|
||||
SIZE_LABEL,
|
||||
OPCODE,
|
||||
CONDITION,
|
||||
@@ -38,6 +39,7 @@ public:
|
||||
QHeaderView::ResizeMode::ResizeToContents,
|
||||
QHeaderView::ResizeMode::ResizeToContents,
|
||||
QHeaderView::ResizeMode::ResizeToContents,
|
||||
QHeaderView::ResizeMode::ResizeToContents,
|
||||
QHeaderView::ResizeMode::Stretch,
|
||||
QHeaderView::ResizeMode::Stretch,
|
||||
QHeaderView::ResizeMode::ResizeToContents,
|
||||
|
||||
@@ -21,11 +21,7 @@ BreakpointView::BreakpointView(const DebuggerViewParameters& parameters)
|
||||
connect(m_ui.breakpointList, &QTableView::doubleClicked, this, &BreakpointView::onDoubleClicked);
|
||||
|
||||
m_ui.breakpointList->setModel(m_model);
|
||||
for (std::size_t i = 0; auto mode : BreakpointModel::HeaderResizeModes)
|
||||
{
|
||||
m_ui.breakpointList->horizontalHeader()->setSectionResizeMode(i, mode);
|
||||
i++;
|
||||
}
|
||||
this->resizeColumns();
|
||||
}
|
||||
|
||||
void BreakpointView::onDoubleClicked(const QModelIndex& index)
|
||||
@@ -124,6 +120,7 @@ void BreakpointView::contextDelete()
|
||||
void BreakpointView::contextNew()
|
||||
{
|
||||
BreakpointDialog* bpDialog = new BreakpointDialog(this, &cpu(), *m_model);
|
||||
connect(bpDialog, &QDialog::accepted, this, &BreakpointView::resizeColumns);
|
||||
bpDialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
bpDialog->show();
|
||||
}
|
||||
@@ -140,6 +137,7 @@ void BreakpointView::contextEdit()
|
||||
auto bpObject = m_model->at(selectedRow);
|
||||
|
||||
BreakpointDialog* bpDialog = new BreakpointDialog(this, &cpu(), *m_model, bpObject, selectedRow);
|
||||
connect(bpDialog, &QDialog::accepted, this, &BreakpointView::resizeColumns);
|
||||
bpDialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
bpDialog->show();
|
||||
}
|
||||
@@ -172,3 +170,12 @@ void BreakpointView::saveBreakpointsToDebuggerSettings()
|
||||
{
|
||||
DebuggerSettingsManager::saveGameSettings(m_model);
|
||||
}
|
||||
|
||||
void BreakpointView::resizeColumns()
|
||||
{
|
||||
for (std::size_t i = 0; auto mode : BreakpointModel::HeaderResizeModes)
|
||||
{
|
||||
m_ui.breakpointList->horizontalHeader()->setSectionResizeMode(i, mode);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ public:
|
||||
void contextEdit();
|
||||
void contextPasteCSV();
|
||||
|
||||
void resizeColumns();
|
||||
|
||||
void saveBreakpointsToDebuggerSettings();
|
||||
|
||||
private:
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "VMManager.h"
|
||||
|
||||
std::mutex DebuggerSettingsManager::writeLock;
|
||||
const QString DebuggerSettingsManager::settingsFileVersion = "0.00";
|
||||
const QString DebuggerSettingsManager::settingsFileVersion = "0.01";
|
||||
|
||||
QJsonObject DebuggerSettingsManager::loadGameSettingsJSON()
|
||||
{
|
||||
@@ -62,6 +62,17 @@ void DebuggerSettingsManager::loadGameSettings(BreakpointModel* bpModel)
|
||||
return;
|
||||
}
|
||||
|
||||
// Breakpoint descriptions were added at debugger settings file version 0.01. If loading
|
||||
// saved breakpoints from a previous version (only 0.00 existed prior), the breakpoints will be
|
||||
// missing a description. This code will add in an empty description so that the previous
|
||||
// version, 0.00, is compatible with 0.01.
|
||||
bool isMissingDescription = false;
|
||||
const QJsonValue savedVersionValue = loadGameSettingsJSON().value("Version");
|
||||
if (!savedVersionValue.isUndefined())
|
||||
{
|
||||
isMissingDescription = savedVersionValue.toString().toStdString() == "0.00";
|
||||
}
|
||||
|
||||
const QJsonArray breakpointsArray = breakpointsValue.toArray();
|
||||
for (u32 row = 0; row < breakpointsArray.size(); row++)
|
||||
{
|
||||
@@ -71,7 +82,13 @@ void DebuggerSettingsManager::loadGameSettings(BreakpointModel* bpModel)
|
||||
Console.WriteLn("Debugger Settings Manager: Failed to load invalid Breakpoint object.");
|
||||
continue;
|
||||
}
|
||||
const QJsonObject rowObject = rowValue.toObject();
|
||||
QJsonObject rowObject = rowValue.toObject();
|
||||
|
||||
// Add empty description for saved breakpoints from debugger settings versions prior to 0.01
|
||||
if (isMissingDescription)
|
||||
{
|
||||
rowObject.insert(QString("DESCRIPTION"), QJsonValue(""));
|
||||
}
|
||||
|
||||
QStringList fields;
|
||||
u32 col = 0;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1000</width>
|
||||
<height>20</height>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
@@ -50,6 +50,7 @@
|
||||
<property name="title">
|
||||
<string>Windows</string>
|
||||
</property>
|
||||
<addaction name="actionWindowsDummy"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
@@ -72,6 +73,7 @@
|
||||
<property name="title">
|
||||
<string>Tools</string>
|
||||
</property>
|
||||
<addaction name="actionToolsDummy"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuView"/>
|
||||
@@ -318,6 +320,16 @@
|
||||
<enum>QAction::NoRole</enum>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionToolsDummy">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionWindowsDummy">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@@ -298,7 +298,10 @@ void DockManager::resetAllLayouts()
|
||||
m_layouts.clear();
|
||||
|
||||
for (const DockTables::DefaultDockLayout& layout : DockTables::DEFAULT_DOCK_LAYOUTS)
|
||||
createLayout(tr(layout.name.c_str()), layout.cpu, true, layout.name);
|
||||
{
|
||||
QString name = QCoreApplication::translate("DebuggerLayout", layout.name.c_str());
|
||||
createLayout(name, layout.cpu, true, layout.name);
|
||||
}
|
||||
|
||||
switchToLayout(0);
|
||||
updateLayoutSwitcher();
|
||||
@@ -313,7 +316,10 @@ void DockManager::resetDefaultLayouts()
|
||||
m_layouts = std::vector<DockLayout>();
|
||||
|
||||
for (const DockTables::DefaultDockLayout& layout : DockTables::DEFAULT_DOCK_LAYOUTS)
|
||||
createLayout(tr(layout.name.c_str()), layout.cpu, true, layout.name);
|
||||
{
|
||||
QString name = QCoreApplication::translate("DebuggerLayout", layout.name.c_str());
|
||||
createLayout(name, layout.cpu, true, layout.name);
|
||||
}
|
||||
|
||||
for (DockLayout& layout : old_layouts)
|
||||
if (!layout.isDefault())
|
||||
|
||||
@@ -502,7 +502,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.aspectRatio, tr("Aspect Ratio"), tr("Auto Standard (4:3/3:2 Progressive)"),
|
||||
tr("Changes the aspect ratio used to display the console's output to the screen. The default is Auto Standard (4:3/3:2 "
|
||||
"Progressive) which automatically adjusts the aspect ratio to match how a game would be shown on a typical TV of the era."));
|
||||
"Progressive) which automatically adjusts the aspect ratio to match how a game would be shown on a typical TV of the era, and adapts to widescreen/ultrawide game patches."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.interlacing, tr("Deinterlacing"), tr("Automatic (Default)"), tr("Determines the deinterlacing method to be used on the interlaced screen of the emulated console. Automatic should be able to correctly deinterlace most games, but if you see visibly shaky graphics, try one of the available options."));
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Native (10:7)</string>
|
||||
<string>Native/Full (10:7)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
@@ -142,7 +142,7 @@
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Native (10:7)</string>
|
||||
<string>Native/Full (10:7)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
|
||||
@@ -266,34 +266,19 @@ bool ThreadedFileReader::Precache2(ProgressCallback* progress, Error* error)
|
||||
|
||||
bool ThreadedFileReader::CheckAvailableMemoryForPrecaching(u64 required_size, Error* error)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// We want to check available physical memory instead of total.
|
||||
const u64 memory_available = GetAvailablePhysicalMemory();
|
||||
// Reserve 2GB of available memory for headroom.
|
||||
constexpr u64 memory_reserve = 2147483648;
|
||||
const u64 max_precache_size = std::max(0LL, static_cast<s64>(memory_available - memory_reserve));
|
||||
const u64 max_precache_size = std::max(s64{0}, static_cast<s64>(memory_available - memory_reserve));
|
||||
|
||||
if (required_size > max_precache_size)
|
||||
{
|
||||
Error::SetStringFmt(error,
|
||||
TRANSLATE_FS("CDVD", "Not enough free memory available for precaching, ({}GB) required."),
|
||||
(required_size + memory_reserve) / _1gb);
|
||||
TRANSLATE_FS("CDVD", "Not enough memory available for precaching ({:.2f} GB required)."),
|
||||
static_cast<double>(required_size + memory_reserve) / static_cast<double>(_1gb));
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
// Don't allow precaching to use more than 50% of system memory.
|
||||
// Hopefully nobody's running 2-4GB potatoes anymore....
|
||||
const u64 memory_size = GetPhysicalMemory();
|
||||
const u64 max_precache_size = memory_size / 2;
|
||||
|
||||
if (required_size > max_precache_size)
|
||||
{
|
||||
Error::SetStringFmt(error,
|
||||
TRANSLATE_FS("CDVD", "Required memory ({}GB) is the above the maximum allowed ({}GB)."),
|
||||
required_size / _1gb, max_precache_size / _1gb);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -223,8 +223,8 @@ enum class DebugFunctionScanMode
|
||||
|
||||
enum class AspectRatioType : u8
|
||||
{
|
||||
Stretch,
|
||||
RAuto4_3_3_2,
|
||||
Stretch, // Stretches to the whole window/display size
|
||||
RAuto4_3_3_2, // Automatically scales to the target aspect ratio if there's a widescreen patch
|
||||
R4_3,
|
||||
R16_9,
|
||||
R10_7,
|
||||
@@ -233,7 +233,7 @@ enum class AspectRatioType : u8
|
||||
|
||||
enum class FMVAspectRatioSwitchType : u8
|
||||
{
|
||||
Off,
|
||||
Off, // Falls back on the selected generic aspect ratio type
|
||||
RAuto4_3_3_2,
|
||||
R4_3,
|
||||
R16_9,
|
||||
@@ -1324,6 +1324,8 @@ struct Pcsx2Config
|
||||
std::string CurrentIRX;
|
||||
std::string CurrentGameArgs;
|
||||
AspectRatioType CurrentAspectRatio = AspectRatioType::RAuto4_3_3_2;
|
||||
// Fall back aspect ratio for games that have patches (when AspectRatioType::RAuto4_3_3_2) is active.
|
||||
float CurrentCustomAspectRatio = 0.f;
|
||||
bool IsPortableMode = false;
|
||||
|
||||
Pcsx2Config();
|
||||
|
||||
@@ -285,6 +285,16 @@ BreakPointCond* CBreakPoints::GetBreakPointCondition(BreakPointCpu cpu, u32 addr
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CBreakPoints::ChangeBreakPointDescription(BreakPointCpu cpu, u32 addr, const std::string& description)
|
||||
{
|
||||
const size_t bp = FindBreakpoint(cpu, addr, true, false);
|
||||
if (bp != INVALID_BREAKPOINT)
|
||||
{
|
||||
breakPoints_[bp].description = description;
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::AddMemCheck(BreakPointCpu cpu, u32 start, u32 end, MemCheckCondition cond, MemCheckResult result)
|
||||
{
|
||||
// This will ruin any pending memchecks.
|
||||
@@ -356,6 +366,16 @@ void CBreakPoints::ChangeMemCheckAddCond(BreakPointCpu cpu, u32 start, u32 end,
|
||||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::ChangeMemCheckDescription(BreakPointCpu cpu, u32 start, u32 end, const std::string& description)
|
||||
{
|
||||
const size_t mc = FindMemCheck(cpu, start, end);
|
||||
if (mc != INVALID_MEMCHECK)
|
||||
{
|
||||
memChecks_[mc].description = description;
|
||||
Update(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
void CBreakPoints::ClearAllMemChecks()
|
||||
{
|
||||
// This will ruin any pending memchecks.
|
||||
|
||||
@@ -37,6 +37,8 @@ struct BreakPoint
|
||||
BreakPointCond cond;
|
||||
BreakPointCpu cpu;
|
||||
|
||||
std::string description;
|
||||
|
||||
bool operator==(const BreakPoint& other) const
|
||||
{
|
||||
return addr == other.addr;
|
||||
@@ -78,6 +80,8 @@ struct MemCheck
|
||||
MemCheckResult result;
|
||||
BreakPointCpu cpu;
|
||||
|
||||
std::string description;
|
||||
|
||||
u32 numHits;
|
||||
|
||||
u32 lastPC;
|
||||
@@ -119,12 +123,14 @@ public:
|
||||
static void ChangeBreakPointAddCond(BreakPointCpu cpu, u32 addr, const BreakPointCond& cond);
|
||||
static void ChangeBreakPointRemoveCond(BreakPointCpu cpu, u32 addr);
|
||||
static BreakPointCond* GetBreakPointCondition(BreakPointCpu cpu, u32 addr);
|
||||
static void ChangeBreakPointDescription(BreakPointCpu cpu, u32 addr, const std::string& description);
|
||||
|
||||
static void AddMemCheck(BreakPointCpu cpu, u32 start, u32 end, MemCheckCondition cond, MemCheckResult result);
|
||||
static void RemoveMemCheck(BreakPointCpu cpu, u32 start, u32 end);
|
||||
static void ChangeMemCheck(BreakPointCpu cpu, u32 start, u32 end, MemCheckCondition cond, MemCheckResult result);
|
||||
static void ChangeMemCheckRemoveCond(BreakPointCpu cpu, u32 start, u32 end);
|
||||
static void ChangeMemCheckAddCond(BreakPointCpu cpu, u32 start, u32 end, const BreakPointCond& cond);
|
||||
static void ChangeMemCheckDescription(BreakPointCpu cpu, u32 start, u32 end, const std::string& description);
|
||||
static void ClearAllMemChecks();
|
||||
|
||||
static void SetSkipFirst(BreakPointCpu cpu, u32 pc);
|
||||
|
||||
@@ -2899,17 +2899,24 @@ bool GSState::TrianglesAreQuads(bool shuffle_check)
|
||||
if (idx > 0)
|
||||
{
|
||||
const u16* const prev_tri= m_index.buff + (idx - 3);
|
||||
GIFRegXYZ vert = v[i[0]].XYZ;
|
||||
GIFRegXYZ last_vert = v[i[2]].XYZ;
|
||||
GIFRegXYZ new_verts[3] = {v[i[0]].XYZ, v[i[1]].XYZ, v[i[2]].XYZ};
|
||||
|
||||
if (shuffle_check)
|
||||
{
|
||||
vert.X -= 8 << 4;
|
||||
last_vert.X -= 8 << 4;
|
||||
new_verts[0].X -= 8 << 4;
|
||||
new_verts[1].X -= 8 << 4;
|
||||
new_verts[2].X -= 8 << 4;
|
||||
}
|
||||
u32 match_vert_count = 0;
|
||||
|
||||
if (vert != m_vertex.buff[prev_tri[0]].XYZ && vert != m_vertex.buff[prev_tri[1]].XYZ && vert != m_vertex.buff[prev_tri[2]].XYZ &&
|
||||
last_vert != m_vertex.buff[prev_tri[0]].XYZ && last_vert != m_vertex.buff[prev_tri[1]].XYZ && last_vert != m_vertex.buff[prev_tri[2]].XYZ)
|
||||
if (!(new_verts[0] != m_vertex.buff[prev_tri[0]].XYZ && new_verts[0] != m_vertex.buff[prev_tri[1]].XYZ && new_verts[0] != m_vertex.buff[prev_tri[2]].XYZ))
|
||||
match_vert_count++;
|
||||
if (!(new_verts[1] != m_vertex.buff[prev_tri[0]].XYZ && new_verts[1] != m_vertex.buff[prev_tri[1]].XYZ && new_verts[1] != m_vertex.buff[prev_tri[2]].XYZ))
|
||||
match_vert_count++;
|
||||
if (!(new_verts[2] != m_vertex.buff[prev_tri[0]].XYZ && new_verts[2] != m_vertex.buff[prev_tri[1]].XYZ && new_verts[2] != m_vertex.buff[prev_tri[2]].XYZ))
|
||||
match_vert_count++;
|
||||
|
||||
if (match_vert_count != 2)
|
||||
return false;
|
||||
}
|
||||
// Degenerate triangles should've been culled already, so we can check indices.
|
||||
|
||||
@@ -46,8 +46,8 @@ const char* shaderName(ShaderConvert value)
|
||||
case ShaderConvert::DATM_0: return "ps_datm0";
|
||||
case ShaderConvert::DATM_1_RTA_CORRECTION: return "ps_datm1_rta_correction";
|
||||
case ShaderConvert::DATM_0_RTA_CORRECTION: return "ps_datm0_rta_correction";
|
||||
case ShaderConvert::HDR_INIT: return "ps_hdr_init";
|
||||
case ShaderConvert::HDR_RESOLVE: return "ps_hdr_resolve";
|
||||
case ShaderConvert::COLCLIP_INIT: return "ps_colclip_init";
|
||||
case ShaderConvert::COLCLIP_RESOLVE: return "ps_colclip_resolve";
|
||||
case ShaderConvert::RTA_CORRECTION: return "ps_rta_correction";
|
||||
case ShaderConvert::RTA_DECORRECTION: return "ps_rta_decorrection";
|
||||
case ShaderConvert::TRANSPARENCY_FILTER: return "ps_filter_transparency";
|
||||
@@ -103,7 +103,9 @@ const char* shaderName(PresentShader value)
|
||||
enum class TextureLabel
|
||||
{
|
||||
ColorRT,
|
||||
HDRRT,
|
||||
ColorHQRT,
|
||||
ColorHDRRT,
|
||||
ColorClipRT,
|
||||
U16RT,
|
||||
U32RT,
|
||||
DepthStencil,
|
||||
@@ -127,8 +129,12 @@ static TextureLabel GetTextureLabel(GSTexture::Type type, GSTexture::Format form
|
||||
{
|
||||
case GSTexture::Format::Color:
|
||||
return TextureLabel::ColorRT;
|
||||
case GSTexture::Format::HDRColor:
|
||||
return TextureLabel::HDRRT;
|
||||
case GSTexture::Format::ColorHQ:
|
||||
return TextureLabel::ColorHQRT;
|
||||
case GSTexture::Format::ColorHDR:
|
||||
return TextureLabel::ColorHDRRT;
|
||||
case GSTexture::Format::ColorClip:
|
||||
return TextureLabel::ColorClipRT;
|
||||
case GSTexture::Format::UInt16:
|
||||
return TextureLabel::U16RT;
|
||||
case GSTexture::Format::UInt32:
|
||||
@@ -149,6 +155,7 @@ static TextureLabel GetTextureLabel(GSTexture::Type type, GSTexture::Format form
|
||||
case GSTexture::Format::BC2:
|
||||
case GSTexture::Format::BC3:
|
||||
case GSTexture::Format::BC7:
|
||||
case GSTexture::Format::ColorHDR:
|
||||
return TextureLabel::ReplacementTexture;
|
||||
default:
|
||||
return TextureLabel::Other;
|
||||
@@ -163,14 +170,19 @@ static TextureLabel GetTextureLabel(GSTexture::Type type, GSTexture::Format form
|
||||
}
|
||||
}
|
||||
|
||||
// Debug names
|
||||
static const char* TextureLabelString(TextureLabel label)
|
||||
{
|
||||
switch (label)
|
||||
{
|
||||
case TextureLabel::ColorRT:
|
||||
return "Color RT";
|
||||
case TextureLabel::HDRRT:
|
||||
return "HDR RT";
|
||||
case TextureLabel::ColorHQRT:
|
||||
return "Color HQ RT";
|
||||
case TextureLabel::ColorHDRRT:
|
||||
return "Color HDR RT";
|
||||
case TextureLabel::ColorClipRT:
|
||||
return "Color Clip RT";
|
||||
case TextureLabel::U16RT:
|
||||
return "U16 RT";
|
||||
case TextureLabel::U32RT:
|
||||
@@ -904,6 +916,7 @@ bool GSHWDrawConfig::BlendState::IsEffective(ColorMaskSelector colormask) const
|
||||
|
||||
// clang-format off
|
||||
|
||||
// Maps PS2 blend modes to our best approximation of them with PC hardware
|
||||
const std::array<HWBlend, 3*3*3*3> GSDevice::m_blendMap =
|
||||
{{
|
||||
{ BLEND_NO_REC , OP_ADD , CONST_ONE , CONST_ZERO} , // 0000: (Cs - Cs)*As + Cs ==> Cs
|
||||
|
||||
@@ -22,8 +22,8 @@ enum class ShaderConvert
|
||||
DATM_0,
|
||||
DATM_1_RTA_CORRECTION,
|
||||
DATM_0_RTA_CORRECTION,
|
||||
HDR_INIT,
|
||||
HDR_RESOLVE,
|
||||
COLCLIP_INIT,
|
||||
COLCLIP_RESOLVE,
|
||||
RTA_CORRECTION,
|
||||
RTA_DECORRECTION,
|
||||
TRANSPARENCY_FILTER,
|
||||
@@ -257,11 +257,15 @@ enum HWBlendFlags
|
||||
BLEND_A_MAX = 0x8000, // Impossible blending uses coeff bigger than 1
|
||||
};
|
||||
|
||||
// Determines the HW blend function for DX11/OGL
|
||||
// Determines the HW blend function for the video backend
|
||||
struct HWBlend
|
||||
{
|
||||
typedef u8 BlendOp; /*GSDevice::BlendOp*/
|
||||
typedef u8 BlendFactor; /*GSDevice::BlendFactor*/
|
||||
|
||||
u16 flags;
|
||||
u8 op, src, dst;
|
||||
BlendOp op;
|
||||
BlendFactor src, dst;
|
||||
};
|
||||
|
||||
struct alignas(16) GSHWDrawConfig
|
||||
@@ -354,12 +358,12 @@ struct alignas(16) GSHWDrawConfig
|
||||
u32 blend_c : 2;
|
||||
u32 blend_d : 2;
|
||||
u32 fixed_one_a : 1;
|
||||
u32 blend_hw : 3;
|
||||
u32 blend_hw : 3; /*HWBlendType*/
|
||||
u32 a_masked : 1;
|
||||
u32 hdr : 1;
|
||||
u32 colclip_hw : 1; // colclip (COLCLAMP off) emulation through HQ textures
|
||||
u32 rta_correction : 1;
|
||||
u32 rta_source_correction : 1;
|
||||
u32 colclip : 1;
|
||||
u32 colclip : 1; // COLCLAMP off (color blend outputs wrap around 0-255)
|
||||
u32 blend_mix : 2;
|
||||
u32 round_inv : 1; // Blending will invert the value, so rounding needs to go the other way
|
||||
u32 pabe : 1;
|
||||
@@ -631,26 +635,30 @@ struct alignas(16) GSHWDrawConfig
|
||||
return true;
|
||||
}
|
||||
};
|
||||
// For hardware rendering backends
|
||||
struct BlendState
|
||||
{
|
||||
typedef u8 BlendOp; /*GSDevice::BlendOp*/
|
||||
typedef u8 BlendFactor; /*GSDevice::BlendFactor*/
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 enable : 1;
|
||||
u8 constant_enable : 1;
|
||||
u8 op : 6;
|
||||
u8 src_factor : 4;
|
||||
u8 dst_factor : 4;
|
||||
u8 src_factor_alpha : 4;
|
||||
u8 dst_factor_alpha : 4;
|
||||
bool enable : 1;
|
||||
bool constant_enable : 1;
|
||||
BlendOp op : 6;
|
||||
BlendFactor src_factor : 4;
|
||||
BlendFactor dst_factor : 4;
|
||||
BlendFactor src_factor_alpha : 4;
|
||||
BlendFactor dst_factor_alpha : 4;
|
||||
u8 constant;
|
||||
};
|
||||
u32 key;
|
||||
};
|
||||
constexpr BlendState(): key(0) {}
|
||||
constexpr BlendState(bool enable_, u8 src_factor_, u8 dst_factor_, u8 op_,
|
||||
u8 src_alpha_factor_, u8 dst_alpha_factor_, bool constant_enable_, u8 constant_)
|
||||
constexpr BlendState(bool enable_, BlendFactor src_factor_, BlendFactor dst_factor_, BlendOp op_,
|
||||
BlendFactor src_alpha_factor_, BlendFactor dst_alpha_factor_, bool constant_enable_, u8 constant_)
|
||||
: key(0)
|
||||
{
|
||||
enable = enable_;
|
||||
@@ -675,7 +683,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
Full, ///< Full emulation (using barriers / ROV)
|
||||
};
|
||||
|
||||
enum class HDRMode : u8
|
||||
enum class ColClipMode : u8
|
||||
{
|
||||
NoModify = 0,
|
||||
ConvertOnly = 1,
|
||||
@@ -730,7 +738,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
struct BlendMultiPass
|
||||
{
|
||||
BlendState blend;
|
||||
u8 blend_hw;
|
||||
u8 blend_hw; /*HWBlendType*/
|
||||
u8 dither;
|
||||
bool enable;
|
||||
};
|
||||
@@ -742,9 +750,9 @@ struct alignas(16) GSHWDrawConfig
|
||||
PSConstantBuffer cb_ps;
|
||||
|
||||
// These are here as they need to be preserved between draws, and the state clear only does up to the constant buffers.
|
||||
HDRMode hdr_mode;
|
||||
GIFRegFRAME hdr_frame;
|
||||
GSVector4i hdr_update_area; ///< Area in the framebuffer which HDR will modify;
|
||||
ColClipMode colclip_mode;
|
||||
GIFRegFRAME colclip_frame;
|
||||
GSVector4i colclip_update_area; ///< Area in the framebuffer which colclip will modify;
|
||||
};
|
||||
|
||||
class GSDevice : public GSAlignedClass<32>
|
||||
@@ -865,7 +873,7 @@ protected:
|
||||
GSTexture* m_target_tmp = nullptr;
|
||||
GSTexture* m_current = nullptr;
|
||||
GSTexture* m_cas = nullptr;
|
||||
GSTexture* m_hdr_rt = nullptr; ///< Temp HDR texture
|
||||
GSTexture* m_colclip_rt = nullptr; ///< Temp hw colclip texture
|
||||
|
||||
bool AcquireWindow(bool recreate_window);
|
||||
|
||||
@@ -890,9 +898,9 @@ public:
|
||||
/// Returns a string containing current adapter in use.
|
||||
const std::string& GetName() const { return m_name; }
|
||||
|
||||
GSTexture* GetHDRTexture() const { return m_hdr_rt; }
|
||||
GSTexture* GetColorClipTexture() const { return m_colclip_rt; }
|
||||
|
||||
void SetHDRTexture(GSTexture* tex) { m_hdr_rt = tex; }
|
||||
void SetColorClipTexture(GSTexture* tex) { m_colclip_rt = tex; }
|
||||
|
||||
/// Returns a string representing the specified API.
|
||||
static const char* RenderAPIToString(RenderAPI api);
|
||||
|
||||
@@ -268,8 +268,25 @@ float GSRenderer::GetModXYOffset()
|
||||
|
||||
static float GetCurrentAspectRatioFloat(bool is_progressive)
|
||||
{
|
||||
static constexpr std::array<float, static_cast<size_t>(AspectRatioType::MaxCount) + 1> ars = {{4.0f / 3.0f, 4.0f / 3.0f, 4.0f / 3.0f, 16.0f / 9.0f, 10.0f / 7.0f, 3.0f / 2.0f}};
|
||||
return ars[static_cast<u32>(GSConfig.AspectRatio) + (3u * (is_progressive && GSConfig.AspectRatio == AspectRatioType::RAuto4_3_3_2))];
|
||||
switch (GSConfig.AspectRatio)
|
||||
{
|
||||
default:
|
||||
// We don't know the AR of the display here, nor we care about it
|
||||
case AspectRatioType::Stretch:
|
||||
case AspectRatioType::RAuto4_3_3_2:
|
||||
if (EmuConfig.CurrentCustomAspectRatio > 0.f)
|
||||
return EmuConfig.CurrentCustomAspectRatio;
|
||||
else if (is_progressive)
|
||||
return 3.0f / 2.0f;
|
||||
else
|
||||
return 4.0f / 3.0f;
|
||||
case AspectRatioType::R4_3:
|
||||
return 4.0f / 3.0f;
|
||||
case AspectRatioType::R16_9:
|
||||
return 16.0f / 9.0f;
|
||||
case AspectRatioType::R10_7:
|
||||
return 10.0f / 7.0f;
|
||||
}
|
||||
}
|
||||
|
||||
static GSVector4 CalculateDrawDstRect(s32 window_width, s32 window_height, const GSVector4i& src_rect, const GSVector2i& src_size, GSDisplayAlignment alignment, bool flip_y, bool is_progressive)
|
||||
@@ -285,6 +302,9 @@ static GSVector4 CalculateDrawDstRect(s32 window_width, s32 window_height, const
|
||||
targetAr = 3.0f / 2.0f;
|
||||
else
|
||||
targetAr = 4.0f / 3.0f;
|
||||
// Fall back on the custom aspect ratio set by patches (e.g. 16:9, 21:9)
|
||||
if (EmuConfig.CurrentCustomAspectRatio > 0.f)
|
||||
targetAr = EmuConfig.CurrentCustomAspectRatio;
|
||||
}
|
||||
else if (EmuConfig.CurrentAspectRatio == AspectRatioType::R4_3)
|
||||
{
|
||||
|
||||
@@ -66,7 +66,9 @@ const char* GSTexture::GetFormatName(Format format)
|
||||
static constexpr const char* format_names[] = {
|
||||
"Invalid",
|
||||
"Color",
|
||||
"HDRColor",
|
||||
"ColorHQ",
|
||||
"ColorHDR",
|
||||
"ColorClip",
|
||||
"DepthStencil",
|
||||
"UNorm8",
|
||||
"UInt16",
|
||||
@@ -90,7 +92,9 @@ u32 GSTexture::GetCompressedBytesPerBlock(Format format)
|
||||
static constexpr u32 bytes_per_block[] = {
|
||||
1, // Invalid
|
||||
4, // Color/RGBA8
|
||||
8, // HDRColor/RGBA16
|
||||
4, // ColorHQ/RGB10A2
|
||||
8, // ColorHDR/RGBA16F
|
||||
8, // ColorClip/RGBA16
|
||||
4, // DepthStencil
|
||||
1, // UNorm8/R8
|
||||
2, // UInt16/R16UI
|
||||
@@ -99,7 +103,7 @@ u32 GSTexture::GetCompressedBytesPerBlock(Format format)
|
||||
8, // BC1 - 16 pixels in 64 bits
|
||||
16, // BC2 - 16 pixels in 128 bits
|
||||
16, // BC3 - 16 pixels in 128 bits
|
||||
16, // BC4 - 16 pixels in 128 bits
|
||||
16, // BC7 - 16 pixels in 128 bits
|
||||
};
|
||||
|
||||
return bytes_per_block[static_cast<u32>(format)];
|
||||
|
||||
@@ -22,15 +22,17 @@ public:
|
||||
Invalid = 0,
|
||||
RenderTarget = 1,
|
||||
DepthStencil,
|
||||
Texture,
|
||||
RWTexture,
|
||||
Texture, // Generic texture (usually is color textures loaded by the game)
|
||||
RWTexture, // UAV
|
||||
};
|
||||
|
||||
enum class Format : u8
|
||||
{
|
||||
Invalid = 0, ///< Used for initialization
|
||||
Color, ///< Standard (RGBA8) color texture
|
||||
HDRColor, ///< Color texture with more bits for colclip emulation (RGBA16Unorm)
|
||||
Color, ///< Standard (RGBA8) color texture (used to store most of PS2's textures)
|
||||
ColorHQ, ///< High quality (RGB10A2) color texture (no proper alpha)
|
||||
ColorHDR, ///< High dynamic range (RGBA16F) color texture
|
||||
ColorClip, ///< Color texture with more bits for colclip (wrap) emulation, given that blending requires 9bpc (RGBA16Unorm)
|
||||
DepthStencil, ///< Depth stencil texture
|
||||
UNorm8, ///< A8UNorm texture for paletted textures and the OSD font
|
||||
UInt16, ///< UInt16 texture for reading back 16-bit depth
|
||||
@@ -40,6 +42,7 @@ public:
|
||||
BC2, ///< BC2, aka DXT2/3 compressed texture for replacements
|
||||
BC3, ///< BC3, aka DXT4/5 compressed texture for replacements
|
||||
BC7, ///< BC7, aka BPTC compressed texture for replacements
|
||||
Last = BC7,
|
||||
};
|
||||
|
||||
enum class State : u8
|
||||
|
||||
@@ -87,6 +87,7 @@ std::vector<GSAdapterInfo> D3D::GetAdapterInfo(IDXGIFactory5* factory)
|
||||
ai.max_upscale_multiplier = GSGetMaxUpscaleMultiplier(ai.max_texture_size);
|
||||
|
||||
wil::com_ptr_nothrow<IDXGIOutput> output;
|
||||
// Only check the first output, which would be the primary display (if any is connected)
|
||||
if (SUCCEEDED(hr = adapter->EnumOutputs(0, &output)))
|
||||
{
|
||||
UINT num_modes = 0;
|
||||
@@ -111,7 +112,7 @@ std::vector<GSAdapterInfo> D3D::GetAdapterInfo(IDXGIFactory5* factory)
|
||||
ERROR_LOG("GetDisplayModeList() failed: {:08X}", static_cast<unsigned>(hr));
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (hr != DXGI_ERROR_NOT_FOUND)
|
||||
{
|
||||
ERROR_LOG("EnumOutputs() failed: {:08X}", static_cast<unsigned>(hr));
|
||||
}
|
||||
@@ -515,7 +516,7 @@ wil::com_ptr_nothrow<ID3DBlob> D3D::CompileShader(D3D::ShaderType type, D3D_FEAT
|
||||
}
|
||||
|
||||
static constexpr UINT flags_non_debug = D3DCOMPILE_OPTIMIZATION_LEVEL3;
|
||||
static constexpr UINT flags_debug = D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG;
|
||||
static constexpr UINT flags_debug = D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG | D3DCOMPILE_DEBUG_NAME_FOR_SOURCE;
|
||||
|
||||
wil::com_ptr_nothrow<ID3DBlob> blob;
|
||||
wil::com_ptr_nothrow<ID3DBlob> error_blob;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "GS/Renderers/DX11/D3D11ShaderCache.h"
|
||||
#include "GS/Renderers/DX11/GSDevice11.h"
|
||||
#include "GS/GS.h"
|
||||
|
||||
#include "Config.h"
|
||||
@@ -300,6 +301,12 @@ wil::com_ptr_nothrow<ID3D11VertexShader> D3D11ShaderCache::GetVertexShader(ID3D1
|
||||
return {};
|
||||
}
|
||||
|
||||
const char* shader_name = entry_point; // Ideally we'd feed in a proper name
|
||||
if (shader_name)
|
||||
{
|
||||
GSDevice11::SetD3DDebugObjectName(shader.get(), shader_name);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
@@ -320,6 +327,12 @@ bool D3D11ShaderCache::GetVertexShaderAndInputLayout(ID3D11Device* device, ID3D1
|
||||
return {};
|
||||
}
|
||||
|
||||
const char* shader_name = entry_point; // Ideally we'd feed in a proper name
|
||||
if (shader_name)
|
||||
{
|
||||
GSDevice11::SetD3DDebugObjectName(actual_vs.get(), shader_name);
|
||||
}
|
||||
|
||||
hr = device->CreateInputLayout(layout, layout_size, blob->GetBufferPointer(), blob->GetBufferSize(), il);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
@@ -348,6 +361,12 @@ wil::com_ptr_nothrow<ID3D11PixelShader> D3D11ShaderCache::GetPixelShader(ID3D11D
|
||||
return {};
|
||||
}
|
||||
|
||||
const char* shader_name = entry_point; // Ideally we'd feed in a proper name
|
||||
if (shader_name)
|
||||
{
|
||||
GSDevice11::SetD3DDebugObjectName(shader.get(), shader_name);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
@@ -368,6 +387,12 @@ wil::com_ptr_nothrow<ID3D11ComputeShader> D3D11ShaderCache::GetComputeShader(ID3
|
||||
return {};
|
||||
}
|
||||
|
||||
const char* shader_name = entry_point; // Ideally we'd feed in a proper name
|
||||
if (shader_name)
|
||||
{
|
||||
GSDevice11::SetD3DDebugObjectName(shader.get(), shader_name);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
||||
@@ -1307,7 +1307,6 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
else
|
||||
{
|
||||
ds = GSVector2i(m_window_info.surface_width, m_window_info.surface_height);
|
||||
|
||||
}
|
||||
|
||||
// om
|
||||
@@ -1318,8 +1317,6 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
|
||||
OMSetBlendState(bs, 0);
|
||||
|
||||
|
||||
|
||||
// ia
|
||||
|
||||
const float left = dRect.x * 2 / ds.x - 1.0f;
|
||||
@@ -1336,7 +1333,6 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
};
|
||||
|
||||
|
||||
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices));
|
||||
IASetInputLayout(m_convert.il.get());
|
||||
IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
@@ -1345,7 +1341,6 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
|
||||
VSSetShader(m_convert.vs.get(), nullptr);
|
||||
|
||||
|
||||
// ps
|
||||
|
||||
PSSetShaderResource(0, sTex);
|
||||
@@ -1382,8 +1377,6 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
OMSetDepthStencilState(m_convert.dss.get(), 0);
|
||||
OMSetBlendState(m_convert.bs[D3D11_COLOR_WRITE_ENABLE_ALL].get(), 0);
|
||||
|
||||
|
||||
|
||||
// ia
|
||||
|
||||
const float left = dRect.x * 2 / ds.x - 1.0f;
|
||||
@@ -1399,8 +1392,6 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
{GSVector4(right, bottom, 0.5f, 1.0f), GSVector2(sRect.z, sRect.w)},
|
||||
};
|
||||
|
||||
|
||||
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices));
|
||||
IASetInputLayout(m_present.il.get());
|
||||
IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
@@ -1409,7 +1400,6 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
|
||||
VSSetShader(m_present.vs.get(), nullptr);
|
||||
|
||||
|
||||
// ps
|
||||
|
||||
PSSetShaderResource(0, sTex);
|
||||
@@ -1748,7 +1738,7 @@ void GSDevice11::SetupPS(const PSSelector& sel, const GSHWDrawConfig::PSConstant
|
||||
sm.AddMacro("PS_DST_FMT", sel.dst_fmt);
|
||||
sm.AddMacro("PS_DEPTH_FMT", sel.depth_fmt);
|
||||
sm.AddMacro("PS_PAL_FMT", sel.pal_fmt);
|
||||
sm.AddMacro("PS_HDR", sel.hdr);
|
||||
sm.AddMacro("PS_COLCLIP_HW", sel.colclip_hw);
|
||||
sm.AddMacro("PS_RTA_CORRECTION", sel.rta_correction);
|
||||
sm.AddMacro("PS_RTA_SRC_CORRECTION", sel.rta_source_correction);
|
||||
sm.AddMacro("PS_COLCLIP", sel.colclip);
|
||||
@@ -2182,8 +2172,6 @@ void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vert
|
||||
//
|
||||
|
||||
DrawPrimitive();
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
void* GSDevice11::IAMapVertexBuffer(u32 stride, u32 count)
|
||||
@@ -2521,43 +2509,43 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();
|
||||
|
||||
GSTexture* hdr_rt = g_gs_device->GetHDRTexture();
|
||||
GSTexture* colclip_rt = g_gs_device->GetColorClipTexture();
|
||||
|
||||
if (hdr_rt)
|
||||
if (colclip_rt)
|
||||
{
|
||||
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
|
||||
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::EarlyResolve)
|
||||
{
|
||||
const GSVector2i size = config.rt->GetSize();
|
||||
const GSVector4 dRect(config.hdr_update_area);
|
||||
const GSVector4 dRect(config.colclip_update_area);
|
||||
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
|
||||
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
|
||||
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
Recycle(hdr_rt);
|
||||
Recycle(colclip_rt);
|
||||
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
|
||||
hdr_rt = nullptr;
|
||||
colclip_rt = nullptr;
|
||||
}
|
||||
else
|
||||
config.ps.hdr = 1;
|
||||
config.ps.colclip_hw = 1;
|
||||
}
|
||||
|
||||
if (config.ps.hdr)
|
||||
if (config.ps.colclip_hw)
|
||||
{
|
||||
if (!hdr_rt)
|
||||
if (!colclip_rt)
|
||||
{
|
||||
config.hdr_update_area = config.drawarea;
|
||||
config.colclip_update_area = config.drawarea;
|
||||
|
||||
const GSVector4 dRect = GSVector4((config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
hdr_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::HDRColor);
|
||||
if (!hdr_rt)
|
||||
colclip_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip);
|
||||
if (!colclip_rt)
|
||||
return;
|
||||
|
||||
g_gs_device->SetHDRTexture(hdr_rt);
|
||||
g_gs_device->SetColorClipTexture(colclip_rt);
|
||||
// Warning: StretchRect must be called before BeginScene otherwise
|
||||
// vertices will be overwritten. Trust me you don't want to do that.
|
||||
StretchRect(config.rt, sRect, hdr_rt, dRect, ShaderConvert::HDR_INIT, false);
|
||||
StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, false);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
}
|
||||
}
|
||||
@@ -2569,7 +2557,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
if (!primid_tex)
|
||||
return;
|
||||
|
||||
StretchRect(hdr_rt ? hdr_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
|
||||
StretchRect(colclip_rt ? colclip_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
|
||||
primid_tex, GSVector4(config.drawarea), m_date.primid_init_ps[static_cast<u8>(config.datm)].get(), nullptr, false);
|
||||
}
|
||||
else if (config.destination_alpha != GSHWDrawConfig::DestinationAlphaMode::Off)
|
||||
@@ -2585,7 +2573,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
|
||||
};
|
||||
|
||||
SetupDATE(hdr_rt ? hdr_rt : config.rt, config.ds, vertices, config.datm);
|
||||
SetupDATE(colclip_rt ? colclip_rt : config.rt, config.ds, vertices, config.datm);
|
||||
}
|
||||
|
||||
if (config.vs.expand != GSHWDrawConfig::VSExpand::None)
|
||||
@@ -2643,13 +2631,13 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
|
||||
GSTexture* rt_copy = nullptr;
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported.
|
||||
{
|
||||
// Bind the RT.This way special effect can use it.
|
||||
// Do not always bind the rt when it's not needed,
|
||||
// only bind it when effects use it such as fbmask emulation currently
|
||||
// because we copy the frame buffer and it is quite slow.
|
||||
CloneTexture(hdr_rt ? hdr_rt : config.rt, &rt_copy, config.drawarea);
|
||||
CloneTexture(colclip_rt ? colclip_rt : config.rt, &rt_copy, config.drawarea);
|
||||
if (rt_copy)
|
||||
{
|
||||
if (config.require_one_barrier)
|
||||
@@ -2679,7 +2667,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
|
||||
SetupOM(config.depth, OMBlendSelector(config.colormask, config.blend), config.blend.constant);
|
||||
OMSetRenderTargets(hdr_rt ? hdr_rt : config.rt, config.ds, &config.scissor);
|
||||
OMSetRenderTargets(colclip_rt ? colclip_rt : config.rt, config.ds, &config.scissor);
|
||||
DrawIndexedPrimitive();
|
||||
|
||||
if (config.blend_multi_pass.enable)
|
||||
@@ -2714,20 +2702,20 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
||||
if (primid_tex)
|
||||
Recycle(primid_tex);
|
||||
|
||||
if (hdr_rt)
|
||||
if (colclip_rt)
|
||||
{
|
||||
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);
|
||||
config.colclip_update_area = config.colclip_update_area.runion(config.drawarea);
|
||||
|
||||
if (config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve)
|
||||
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve)
|
||||
{
|
||||
const GSVector2i size = config.rt->GetSize();
|
||||
const GSVector4 dRect(config.hdr_update_area);
|
||||
const GSVector4 dRect(config.colclip_update_area);
|
||||
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
|
||||
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
|
||||
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
Recycle(hdr_rt);
|
||||
Recycle(colclip_rt);
|
||||
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ DXGI_FORMAT GSTexture11::GetDXGIFormat(Format format)
|
||||
switch (format)
|
||||
{
|
||||
case GSTexture::Format::Color: return DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
case GSTexture::Format::HDRColor: return DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||
case GSTexture::Format::ColorHQ: return DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
case GSTexture::Format::ColorHDR: return DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
case GSTexture::Format::ColorClip: return DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||
case GSTexture::Format::DepthStencil: return DXGI_FORMAT_R32G8X24_TYPELESS;
|
||||
case GSTexture::Format::UNorm8: return DXGI_FORMAT_A8_UNORM;
|
||||
case GSTexture::Format::UInt16: return DXGI_FORMAT_R16_UINT;
|
||||
|
||||
@@ -739,7 +739,9 @@ bool GSDevice12::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
return false;
|
||||
}
|
||||
|
||||
CompileCASPipelines();
|
||||
if (!CompileCASPipelines())
|
||||
return false;
|
||||
|
||||
if (!CompileImGuiPipeline())
|
||||
return false;
|
||||
|
||||
@@ -1265,13 +1267,17 @@ void GSDevice12::DrawIndexedPrimitive(int offset, int count)
|
||||
void GSDevice12::LookupNativeFormat(GSTexture::Format format, DXGI_FORMAT* d3d_format, DXGI_FORMAT* srv_format,
|
||||
DXGI_FORMAT* rtv_format, DXGI_FORMAT* dsv_format) const
|
||||
{
|
||||
static constexpr std::array<std::array<DXGI_FORMAT, 4>, static_cast<int>(GSTexture::Format::BC7) + 1>
|
||||
static constexpr std::array<std::array<DXGI_FORMAT, 4>, static_cast<int>(GSTexture::Format::Last) + 1>
|
||||
s_format_mapping = {{
|
||||
{DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN}, // Invalid
|
||||
{DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
DXGI_FORMAT_UNKNOWN}, // Color
|
||||
{DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM,
|
||||
DXGI_FORMAT_UNKNOWN}, // ColorHQ
|
||||
{DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
DXGI_FORMAT_UNKNOWN}, // ColorHDR
|
||||
{DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
DXGI_FORMAT_UNKNOWN}, // HDRColor
|
||||
DXGI_FORMAT_UNKNOWN}, // ColorClip
|
||||
{DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN,
|
||||
DXGI_FORMAT_D32_FLOAT_S8X24_UINT}, // DepthStencil
|
||||
{DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN}, // UNorm8
|
||||
@@ -1424,9 +1430,10 @@ void GSDevice12::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
GL_PUSH("ColorCopy Red:%d Green:%d Blue:%d Alpha:%d", red, green, blue, alpha);
|
||||
|
||||
const u32 index = (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
|
||||
int rta_offset = (shader == ShaderConvert::RTA_CORRECTION) ? 16 : 0;
|
||||
const bool allow_discard = (index == 0xf);
|
||||
DoStretchRect(static_cast<GSTexture12*>(sTex), sRect, static_cast<GSTexture12*>(dTex), dRect,
|
||||
m_color_copy[index].get(), false, allow_discard);
|
||||
m_color_copy[index + rta_offset].get(), false, allow_discard);
|
||||
}
|
||||
|
||||
void GSDevice12::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
|
||||
@@ -2520,13 +2527,6 @@ bool GSDevice12::CompileConvertPipelines()
|
||||
// compile color copy pipelines
|
||||
gpb.SetRenderTarget(0, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
gpb.SetDepthStencilFormat(DXGI_FORMAT_UNKNOWN);
|
||||
|
||||
ComPtr<ID3DBlob> ps(GetUtilityPixelShader(*shader, shaderName(i)));
|
||||
if (!ps)
|
||||
return false;
|
||||
|
||||
gpb.SetPixelShader(ps.get());
|
||||
|
||||
for (u32 j = 16; j < 32; j++)
|
||||
{
|
||||
pxAssert(!m_color_copy[j]);
|
||||
@@ -2540,10 +2540,10 @@ bool GSDevice12::CompileConvertPipelines()
|
||||
j & 1u, (j >> 1) & 1u, (j >> 2) & 1u, (j >> 3) & 1u));
|
||||
}
|
||||
}
|
||||
else if (i == ShaderConvert::HDR_INIT || i == ShaderConvert::HDR_RESOLVE)
|
||||
else if (i == ShaderConvert::COLCLIP_INIT || i == ShaderConvert::COLCLIP_RESOLVE)
|
||||
{
|
||||
const bool is_setup = i == ShaderConvert::HDR_INIT;
|
||||
std::array<ComPtr<ID3D12PipelineState>, 2>& arr = is_setup ? m_hdr_setup_pipelines : m_hdr_finish_pipelines;
|
||||
const bool is_setup = i == ShaderConvert::COLCLIP_INIT;
|
||||
std::array<ComPtr<ID3D12PipelineState>, 2>& arr = is_setup ? m_colclip_setup_pipelines : m_colclip_finish_pipelines;
|
||||
for (u32 ds = 0; ds < 2; ds++)
|
||||
{
|
||||
pxAssert(!arr[ds]);
|
||||
@@ -2554,7 +2554,7 @@ bool GSDevice12::CompileConvertPipelines()
|
||||
if (!arr[ds])
|
||||
return false;
|
||||
|
||||
D3D12::SetObjectName(arr[ds].get(), TinyString::from_format("HDR {}/copy pipeline (ds={})", is_setup ? "setup" : "finish", ds));
|
||||
D3D12::SetObjectName(arr[ds].get(), TinyString::from_format("ColorClip {}/copy pipeline (ds={})", is_setup ? "setup" : "finish", ds));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2598,8 +2598,8 @@ bool GSDevice12::CompilePresentPipelines()
|
||||
return false;
|
||||
}
|
||||
|
||||
ComPtr<ID3DBlob> m_convert_vs = GetUtilityVertexShader(*shader, "vs_main");
|
||||
if (!m_convert_vs)
|
||||
ComPtr<ID3DBlob> vs = GetUtilityVertexShader(*shader, "vs_main");
|
||||
if (!vs)
|
||||
return false;
|
||||
|
||||
D3D12::GraphicsPipelineBuilder gpb;
|
||||
@@ -2607,7 +2607,7 @@ bool GSDevice12::CompilePresentPipelines()
|
||||
AddUtilityVertexAttributes(gpb);
|
||||
gpb.SetNoCullRasterizationState();
|
||||
gpb.SetNoBlendingState();
|
||||
gpb.SetVertexShader(m_convert_vs.get());
|
||||
gpb.SetVertexShader(vs.get());
|
||||
gpb.SetDepthState(false, false, D3D12_COMPARISON_FUNC_ALWAYS);
|
||||
gpb.SetNoStencilState();
|
||||
gpb.SetRenderTarget(0, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
@@ -2663,7 +2663,7 @@ bool GSDevice12::CompileInterlacePipelines()
|
||||
if (!m_interlace[i])
|
||||
return false;
|
||||
|
||||
D3D12::SetObjectName(m_convert[i].get(), TinyString::from_format("Interlace pipeline {}", static_cast<int>(i)));
|
||||
D3D12::SetObjectName(m_interlace[i].get(), TinyString::from_format("Interlace pipeline {}", static_cast<int>(i)));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2700,7 +2700,7 @@ bool GSDevice12::CompileMergePipelines()
|
||||
if (!m_merge[i])
|
||||
return false;
|
||||
|
||||
D3D12::SetObjectName(m_convert[i].get(), TinyString::from_format("Merge pipeline {}", i));
|
||||
D3D12::SetObjectName(m_merge[i].get(), TinyString::from_format("Merge pipeline {}", i));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2780,8 +2780,8 @@ void GSDevice12::DestroyResources()
|
||||
m_color_copy = {};
|
||||
m_present = {};
|
||||
m_convert = {};
|
||||
m_hdr_setup_pipelines = {};
|
||||
m_hdr_finish_pipelines = {};
|
||||
m_colclip_setup_pipelines = {};
|
||||
m_colclip_finish_pipelines = {};
|
||||
m_date_image_setup_pipelines = {};
|
||||
m_fxaa_pipeline.reset();
|
||||
m_shadeboost_pipeline.reset();
|
||||
@@ -2897,7 +2897,7 @@ const ID3DBlob* GSDevice12::GetTFXPixelShader(const GSHWDrawConfig::PSSelector&
|
||||
sm.AddMacro("PS_DST_FMT", sel.dst_fmt);
|
||||
sm.AddMacro("PS_DEPTH_FMT", sel.depth_fmt);
|
||||
sm.AddMacro("PS_PAL_FMT", sel.pal_fmt);
|
||||
sm.AddMacro("PS_HDR", sel.hdr);
|
||||
sm.AddMacro("PS_COLCLIP_HW", sel.colclip_hw);
|
||||
sm.AddMacro("PS_RTA_CORRECTION", sel.rta_correction);
|
||||
sm.AddMacro("PS_RTA_SRC_CORRECTION", sel.rta_source_correction);
|
||||
sm.AddMacro("PS_COLCLIP", sel.colclip);
|
||||
@@ -2955,7 +2955,7 @@ GSDevice12::ComPtr<ID3D12PipelineState> GSDevice12::CreateTFXPipeline(const Pipe
|
||||
{
|
||||
const GSTexture::Format format = IsDATEModePrimIDInit(p.ps.date) ?
|
||||
GSTexture::Format::PrimID :
|
||||
(p.ps.hdr ? GSTexture::Format::HDRColor : GSTexture::Format::Color);
|
||||
(p.ps.colclip_hw ? GSTexture::Format::ColorClip : GSTexture::Format::Color);
|
||||
|
||||
DXGI_FORMAT native_format;
|
||||
LookupNativeFormat(format, nullptr, nullptr, &native_format, nullptr);
|
||||
@@ -3817,7 +3817,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
const bool stencil_DATE = (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil ||
|
||||
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne);
|
||||
|
||||
GSTexture12* hdr_rt = static_cast<GSTexture12*>(g_gs_device->GetHDRTexture());
|
||||
GSTexture12* colclip_rt = static_cast<GSTexture12*>(g_gs_device->GetColorClipTexture());
|
||||
GSTexture12* draw_rt = static_cast<GSTexture12*>(config.rt);
|
||||
GSTexture12* draw_ds = static_cast<GSTexture12*>(config.ds);
|
||||
GSTexture12* draw_rt_clone = nullptr;
|
||||
@@ -3830,15 +3830,15 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
// figure out the pipeline
|
||||
UpdateHWPipelineSelector(config);
|
||||
|
||||
// now blit the hdr texture back to the original target
|
||||
if (hdr_rt)
|
||||
// now blit the colclip texture back to the original target
|
||||
if (colclip_rt)
|
||||
{
|
||||
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
|
||||
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::EarlyResolve)
|
||||
{
|
||||
GL_PUSH("Blit HDR back to RT");
|
||||
GL_PUSH("Blit ColorClip back to RT");
|
||||
|
||||
EndRenderPass();
|
||||
hdr_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
colclip_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
|
||||
draw_rt = static_cast<GSTexture12*>(config.rt);
|
||||
OMSetRenderTargets(draw_rt, draw_ds, config.scissor);
|
||||
@@ -3850,19 +3850,19 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS,
|
||||
draw_rt->GetUNormClearColor(), 0.0f, 0);
|
||||
|
||||
const GSVector4 sRect(GSVector4(config.hdr_update_area) / GSVector4(rtsize.x, rtsize.y).xyxy());
|
||||
SetPipeline(m_hdr_finish_pipelines[pipe.ds].get());
|
||||
SetUtilityTexture(hdr_rt, m_point_sampler_cpu);
|
||||
DrawStretchRect(sRect, GSVector4(config.hdr_update_area), rtsize);
|
||||
const GSVector4 sRect(GSVector4(config.colclip_update_area) / GSVector4(rtsize.x, rtsize.y).xyxy());
|
||||
SetPipeline(m_colclip_finish_pipelines[pipe.ds].get());
|
||||
SetUtilityTexture(colclip_rt, m_point_sampler_cpu);
|
||||
DrawStretchRect(sRect, GSVector4(config.colclip_update_area), rtsize);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
|
||||
Recycle(hdr_rt);
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
Recycle(colclip_rt);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
draw_rt = hdr_rt;
|
||||
pipe.ps.hdr = 1;
|
||||
draw_rt = colclip_rt;
|
||||
pipe.ps.colclip_hw = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3900,10 +3900,10 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
}
|
||||
|
||||
if (config.require_one_barrier)
|
||||
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported.
|
||||
{
|
||||
// requires a copy of the RT
|
||||
draw_rt_clone = static_cast<GSTexture12*>(CreateTexture(rtsize.x, rtsize.y, 1, hdr_rt ? GSTexture::Format::HDRColor : GSTexture::Format::Color, true));
|
||||
draw_rt_clone = static_cast<GSTexture12*>(CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true));
|
||||
if (draw_rt_clone)
|
||||
{
|
||||
EndRenderPass();
|
||||
@@ -3913,23 +3913,26 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
draw_rt_clone->SetState(GSTexture::State::Invalidated);
|
||||
CopyRect(draw_rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
PSSetShaderResource(2, draw_rt_clone, true);
|
||||
if (config.require_one_barrier)
|
||||
PSSetShaderResource(2, draw_rt_clone, true);
|
||||
if (config.tex && config.tex == config.rt)
|
||||
PSSetShaderResource(0, draw_rt_clone, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Switch to hdr target for colclip rendering
|
||||
if (pipe.ps.hdr)
|
||||
// Switch to colclip target for colclip hw rendering
|
||||
if (pipe.ps.colclip_hw)
|
||||
{
|
||||
if (!hdr_rt)
|
||||
if (!colclip_rt)
|
||||
{
|
||||
config.hdr_update_area = config.drawarea;
|
||||
config.colclip_update_area = config.drawarea;
|
||||
|
||||
EndRenderPass();
|
||||
|
||||
hdr_rt = static_cast<GSTexture12*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::HDRColor, false));
|
||||
if (!hdr_rt)
|
||||
colclip_rt = static_cast<GSTexture12*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false));
|
||||
if (!colclip_rt)
|
||||
{
|
||||
Console.WriteLn("D3D12: Failed to allocate HDR render target, aborting draw.");
|
||||
Console.WriteLn("D3D12: Failed to allocate ColorClip render target, aborting draw.");
|
||||
|
||||
if (date_image)
|
||||
Recycle(date_image);
|
||||
@@ -3937,17 +3940,17 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
return;
|
||||
}
|
||||
|
||||
g_gs_device->SetHDRTexture(static_cast<GSTexture*>(hdr_rt));
|
||||
g_gs_device->SetColorClipTexture(static_cast<GSTexture*>(colclip_rt));
|
||||
|
||||
// propagate clear value through if the hdr render is the first
|
||||
// propagate clear value through if the colclip render is the first
|
||||
if (draw_rt->GetState() == GSTexture::State::Cleared)
|
||||
{
|
||||
hdr_rt->SetState(GSTexture::State::Cleared);
|
||||
hdr_rt->SetClearColor(draw_rt->GetClearColor());
|
||||
colclip_rt->SetState(GSTexture::State::Cleared);
|
||||
colclip_rt->SetClearColor(draw_rt->GetClearColor());
|
||||
}
|
||||
else if (draw_rt->GetState() == GSTexture::State::Dirty)
|
||||
{
|
||||
GL_PUSH_("HDR Render Target Setup");
|
||||
GL_PUSH_("ColorClip Render Target Setup");
|
||||
draw_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
}
|
||||
|
||||
@@ -3956,7 +3959,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
PSSetShaderResource(2, draw_rt, true);
|
||||
}
|
||||
|
||||
draw_rt = hdr_rt;
|
||||
draw_rt = colclip_rt;
|
||||
}
|
||||
|
||||
// clear texture binding when it's bound to RT or DS
|
||||
@@ -3966,11 +3969,10 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
PSSetShaderResource(0, nullptr, false);
|
||||
}
|
||||
|
||||
// avoid restarting the render pass just to switch from rt+depth to rt and vice versa
|
||||
if (m_in_render_pass && (m_current_render_target == draw_rt || m_current_depth_target == draw_ds))
|
||||
{
|
||||
// avoid restarting the render pass just to switch from rt+depth to rt and vice versa
|
||||
// keep the depth even if doing HDR draws, because the next draw will probably re-enable depth
|
||||
// keep the depth even if doing colclip hw draws, because the next draw will probably re-enable depth
|
||||
if (!draw_rt && m_current_render_target && config.tex != m_current_render_target &&
|
||||
m_current_render_target->GetSize() == draw_ds->GetSize())
|
||||
{
|
||||
@@ -3991,9 +3993,9 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
if (!m_in_render_pass)
|
||||
{
|
||||
GSVector4 clear_color = draw_rt ? draw_rt->GetUNormClearColor() : GSVector4::zero();
|
||||
if (pipe.ps.hdr)
|
||||
if (pipe.ps.colclip_hw)
|
||||
{
|
||||
// Denormalize clear color for HDR.
|
||||
// Denormalize clear color for hw colclip.
|
||||
clear_color *= GSVector4::cxpr(255.0f / 65535.0f, 255.0f / 65535.0f, 255.0f / 65535.0f, 1.0f);
|
||||
}
|
||||
BeginRenderPass(GetLoadOpForTexture(draw_rt),
|
||||
@@ -4007,13 +4009,13 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
clear_color, draw_ds ? draw_ds->GetClearDepth() : 0.0f, 1);
|
||||
}
|
||||
|
||||
// rt -> hdr blit if enabled
|
||||
if (hdr_rt && (config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve) && config.rt->GetState() == GSTexture::State::Dirty)
|
||||
// rt -> colclip hw blit if enabled
|
||||
if (colclip_rt && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve) && config.rt->GetState() == GSTexture::State::Dirty)
|
||||
{
|
||||
SetUtilityTexture(static_cast<GSTexture12*>(config.rt), m_point_sampler_cpu);
|
||||
SetPipeline(m_hdr_setup_pipelines[pipe.ds].get());
|
||||
SetPipeline(m_colclip_setup_pipelines[pipe.ds].get());
|
||||
|
||||
const GSVector4 drawareaf = GSVector4((config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 drawareaf = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 sRect(drawareaf / GSVector4(rtsize.x, rtsize.y).xyxy());
|
||||
DrawStretchRect(sRect, GSVector4(drawareaf), rtsize);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
@@ -4021,9 +4023,9 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
GL_POP();
|
||||
}
|
||||
|
||||
// VB/IB upload, if we did DATE setup and it's not HDR this has already been done
|
||||
// VB/IB upload, if we did DATE setup and it's not colclip hw this has already been done
|
||||
SetPrimitiveTopology(s_primitive_topology_mapping[static_cast<u8>(config.topology)]);
|
||||
if (!date_image || hdr_rt)
|
||||
if (!date_image || colclip_rt)
|
||||
UploadHWDrawVerticesAndIndices(config);
|
||||
|
||||
// now we can do the actual draw
|
||||
@@ -4067,17 +4069,17 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
if (date_image)
|
||||
Recycle(date_image);
|
||||
|
||||
// now blit the hdr texture back to the original target
|
||||
if (hdr_rt)
|
||||
// now blit the colclip texture back to the original target
|
||||
if (colclip_rt)
|
||||
{
|
||||
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);
|
||||
config.colclip_update_area = config.colclip_update_area.runion(config.drawarea);
|
||||
|
||||
if ((config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve))
|
||||
if ((config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve))
|
||||
{
|
||||
GL_PUSH("Blit HDR back to RT");
|
||||
GL_PUSH("Blit ColorClip back to RT");
|
||||
|
||||
EndRenderPass();
|
||||
hdr_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
colclip_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||
|
||||
draw_rt = static_cast<GSTexture12*>(config.rt);
|
||||
OMSetRenderTargets(draw_rt, draw_ds, config.scissor);
|
||||
@@ -4089,14 +4091,14 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS,
|
||||
draw_rt->GetUNormClearColor(), 0.0f, 0);
|
||||
|
||||
const GSVector4 sRect(GSVector4(config.hdr_update_area) / GSVector4(rtsize.x, rtsize.y).xyxy());
|
||||
SetPipeline(m_hdr_finish_pipelines[pipe.ds].get());
|
||||
SetUtilityTexture(hdr_rt, m_point_sampler_cpu);
|
||||
DrawStretchRect(sRect, GSVector4(config.hdr_update_area), rtsize);
|
||||
const GSVector4 sRect(GSVector4(config.colclip_update_area) / GSVector4(rtsize.x, rtsize.y).xyxy());
|
||||
SetPipeline(m_colclip_finish_pipelines[pipe.ds].get());
|
||||
SetUtilityTexture(colclip_rt, m_point_sampler_cpu);
|
||||
DrawStretchRect(sRect, GSVector4(config.colclip_update_area), rtsize);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
|
||||
Recycle(hdr_rt);
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
Recycle(colclip_rt);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,8 +315,8 @@ private:
|
||||
std::array<ComPtr<ID3D12PipelineState>, 32> m_color_copy{};
|
||||
std::array<ComPtr<ID3D12PipelineState>, 2> m_merge{};
|
||||
std::array<ComPtr<ID3D12PipelineState>, NUM_INTERLACE_SHADERS> m_interlace{};
|
||||
std::array<ComPtr<ID3D12PipelineState>, 2> m_hdr_setup_pipelines{}; // [depth]
|
||||
std::array<ComPtr<ID3D12PipelineState>, 2> m_hdr_finish_pipelines{}; // [depth]
|
||||
std::array<ComPtr<ID3D12PipelineState>, 2> m_colclip_setup_pipelines{}; // [depth]
|
||||
std::array<ComPtr<ID3D12PipelineState>, 2> m_colclip_finish_pipelines{}; // [depth]
|
||||
std::array<std::array<ComPtr<ID3D12PipelineState>, 4>, 2> m_date_image_setup_pipelines{}; // [depth][datm]
|
||||
ComPtr<ID3D12PipelineState> m_fxaa_pipeline;
|
||||
ComPtr<ID3D12PipelineState> m_shadeboost_pipeline;
|
||||
|
||||
@@ -178,7 +178,7 @@ bool GSHwHack::GSC_DTGames(GSRendererHW& r, int& skip)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_Tekken5(GSRendererHW& r, int& skip)
|
||||
bool GSHwHack::GSC_NamcoGames(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
{
|
||||
@@ -195,7 +195,7 @@ bool GSHwHack::GSC_Tekken5(GSRendererHW& r, int& skip)
|
||||
if (!rt)
|
||||
return false;
|
||||
|
||||
GL_INS("GSC_Tekken5(): HLE channel shuffle");
|
||||
GL_INS("GSC_NamcoGames(): HLE channel shuffle");
|
||||
|
||||
// have to set up the palette ourselves too, since GSC executes before it does
|
||||
r.m_mem.m_clut.Read32(RTEX0, r.m_draw_env->TEXA);
|
||||
@@ -1502,14 +1502,12 @@ const GSHwHack::Entry<GSRendererHW::GSC_Ptr> GSHwHack::s_get_skip_count_function
|
||||
CRC_F(GSC_Battlefield2),
|
||||
|
||||
// Channel Effect
|
||||
CRC_F(GSC_NamcoGames),
|
||||
CRC_F(GSC_SteambotChronicles),
|
||||
|
||||
// Depth Issue
|
||||
CRC_F(GSC_BurnoutGames),
|
||||
|
||||
// Half Screen bottom issue
|
||||
CRC_F(GSC_Tekken5),
|
||||
|
||||
// Upscaling hacks
|
||||
CRC_F(GSC_UltramanFightingEvolution),
|
||||
};
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
static bool GSC_GuitarHero(GSRendererHW& r, int& skip);
|
||||
static bool GSC_SFEX3(GSRendererHW& r, int& skip);
|
||||
static bool GSC_DTGames(GSRendererHW& r, int& skip);
|
||||
static bool GSC_Tekken5(GSRendererHW& r, int& skip);
|
||||
static bool GSC_NamcoGames(GSRendererHW& r, int& skip);
|
||||
static bool GSC_BurnoutGames(GSRendererHW& r, int& skip);
|
||||
static bool GSC_BlackAndBurnoutSky(GSRendererHW& r, int& skip);
|
||||
static bool GSC_MidnightClub3(GSRendererHW& r, int& skip);
|
||||
|
||||
@@ -1135,7 +1135,7 @@ GSVector2i GSRendererHW::GetTargetSize(const GSTextureCache::Source* tex, const
|
||||
return g_texture_cache->GetTargetSize(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, valid_size.x, valid_size.y, can_expand);
|
||||
}
|
||||
|
||||
bool GSRendererHW::NextDrawHDR() const
|
||||
bool GSRendererHW::NextDrawColClip() const
|
||||
{
|
||||
const int get_next_ctx = (m_state_flush_reason == CONTEXTCHANGE) ? m_env.PRIM.CTXT : m_backed_up_ctx;
|
||||
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
|
||||
@@ -2438,31 +2438,31 @@ void GSRendererHW::Draw()
|
||||
|
||||
// I hate that I have to do this, but some games (like Pac-Man World Rally) troll us by causing a flush with degenerate triangles, so we don't have all available information about the next draw.
|
||||
// So we have to check when the next draw happens if our frame has changed or if it's become recursive.
|
||||
const bool has_HDR_texture = g_gs_device->GetHDRTexture() != nullptr;
|
||||
if (!no_rt && has_HDR_texture && (m_conf.hdr_frame.FBP != m_cached_ctx.FRAME.FBP || m_conf.hdr_frame.Block() == m_cached_ctx.TEX0.TBP0))
|
||||
const bool has_colclip_texture = g_gs_device->GetColorClipTexture() != nullptr;
|
||||
if (!no_rt && has_colclip_texture && (m_conf.colclip_frame.FBP != m_cached_ctx.FRAME.FBP || m_conf.colclip_frame.Block() == m_cached_ctx.TEX0.TBP0))
|
||||
{
|
||||
GIFRegTEX0 FRAME;
|
||||
FRAME.TBP0 = m_conf.hdr_frame.Block();
|
||||
FRAME.TBW = m_conf.hdr_frame.FBW;
|
||||
FRAME.PSM = m_conf.hdr_frame.PSM;
|
||||
FRAME.TBP0 = m_conf.colclip_frame.Block();
|
||||
FRAME.TBW = m_conf.colclip_frame.FBW;
|
||||
FRAME.PSM = m_conf.colclip_frame.PSM;
|
||||
|
||||
GSTextureCache::Target* old_rt = g_texture_cache->LookupTarget(FRAME, GSVector2i(1, 1), GetTextureScaleFactor(), GSTextureCache::RenderTarget, true,
|
||||
fm, false, false, true, true, GSVector4i(0, 0, 1, 1), true, false, false);
|
||||
|
||||
if (old_rt)
|
||||
{
|
||||
GL_CACHE("Pre-draw resolve of HDR! Address: %x", FRAME.TBP0);
|
||||
GSTexture* hdr_texture = g_gs_device->GetHDRTexture();
|
||||
g_gs_device->StretchRect(hdr_texture, GSVector4(m_conf.hdr_update_area) / GSVector4(GSVector4i(hdr_texture->GetSize()).xyxy()), old_rt->m_texture, GSVector4(m_conf.hdr_update_area),
|
||||
ShaderConvert::HDR_RESOLVE, false);
|
||||
GL_CACHE("Pre-draw resolve of colclip! Address: %x", FRAME.TBP0);
|
||||
GSTexture* colclip_texture = g_gs_device->GetColorClipTexture();
|
||||
g_gs_device->StretchRect(colclip_texture, GSVector4(m_conf.colclip_update_area) / GSVector4(GSVector4i(colclip_texture->GetSize()).xyxy()), old_rt->m_texture, GSVector4(m_conf.colclip_update_area),
|
||||
ShaderConvert::COLCLIP_RESOLVE, false);
|
||||
|
||||
g_gs_device->Recycle(hdr_texture);
|
||||
g_gs_device->Recycle(colclip_texture);
|
||||
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
|
||||
}
|
||||
else
|
||||
DevCon.Warning("Error resolving HDR texture for pre-draw resolve");
|
||||
DevCon.Warning("Error resolving colclip texture for pre-draw resolve");
|
||||
}
|
||||
|
||||
const bool draw_sprite_tex = PRIM->TME && (m_vt.m_primclass == GS_SPRITE_CLASS);
|
||||
@@ -2482,7 +2482,7 @@ void GSRendererHW::Draw()
|
||||
// | 0.5,2.25 | 1-1 | 1 |
|
||||
// | 0.5,2.5 | 1-2 | 2 |
|
||||
// --------------------------------------
|
||||
m_r = GSVector4i(m_vt.m_min.p.upld(m_vt.m_max.p) + GSVector4::cxpr(0.5f));
|
||||
m_r = GSVector4i((m_vt.m_min.p.upld(m_vt.m_max.p) + GSVector4::cxpr(0.4f)).round<Round_NearestInt>());
|
||||
m_r = m_r.blend8(m_r + GSVector4i::cxpr(0, 0, 1, 1), (m_r.xyxy() == m_r.zwzw()));
|
||||
m_r_no_scissor = m_r;
|
||||
m_r = m_r.rintersect(context->scissor.in);
|
||||
@@ -4267,12 +4267,12 @@ void GSRendererHW::Draw()
|
||||
|
||||
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
|
||||
{
|
||||
const bool writeback_HDR_texture = g_gs_device->GetHDRTexture() != nullptr;
|
||||
if (writeback_HDR_texture)
|
||||
const bool writeback_colclip_texture = g_gs_device->GetColorClipTexture() != nullptr;
|
||||
if (writeback_colclip_texture)
|
||||
{
|
||||
GSTexture* hdr_texture = g_gs_device->GetHDRTexture();
|
||||
g_gs_device->StretchRect(hdr_texture, GSVector4(m_conf.hdr_update_area) / GSVector4(GSVector4i(hdr_texture->GetSize()).xyxy()), rt->m_texture, GSVector4(m_conf.hdr_update_area),
|
||||
ShaderConvert::HDR_RESOLVE, false);
|
||||
GSTexture* colclip_texture = g_gs_device->GetColorClipTexture();
|
||||
g_gs_device->StretchRect(colclip_texture, GSVector4(m_conf.colclip_update_area) / GSVector4(GSVector4i(colclip_texture->GetSize()).xyxy()), rt->m_texture, GSVector4(m_conf.colclip_update_area),
|
||||
ShaderConvert::COLCLIP_RESOLVE, false);
|
||||
}
|
||||
|
||||
const u64 frame = g_perfmon.GetFrame();
|
||||
@@ -5228,10 +5228,10 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
// Per pixel alpha blending.
|
||||
const bool PABE = m_draw_env->PABE.PABE && GetAlphaMinMax().min < 128;
|
||||
|
||||
// HW blend can handle it, no need for sw or hdr colclip, Cd*Alpha or Cd*(1 - Alpha) where Alpha <= 128.
|
||||
// HW blend can handle it, no need for sw or hw colclip, Cd*Alpha or Cd*(1 - Alpha) where Alpha <= 128.
|
||||
bool color_dest_blend2 = !PABE && ((m_conf.ps.blend_a == 1 && m_conf.ps.blend_b == 2 && m_conf.ps.blend_d == 2) || (m_conf.ps.blend_a == 2 && m_conf.ps.blend_b == 1 && m_conf.ps.blend_d == 1)) &&
|
||||
(alpha_eq_less_one || (alpha_c1_eq_less_max_one && new_rt_alpha_scale));
|
||||
// HW blend can handle it, no need for sw or hdr colclip, Cs*Alpha + Cd*(1 - Alpha) or Cd*Alpha + Cs*(1 - Alpha) where Alpha <= 128.
|
||||
// HW blend can handle it, no need for sw or hw colclip, Cs*Alpha + Cd*(1 - Alpha) or Cd*Alpha + Cs*(1 - Alpha) where Alpha <= 128.
|
||||
bool blend_zero_to_one_range = !PABE && ((m_conf.ps.blend_a == 0 && m_conf.ps.blend_b == 1 && m_conf.ps.blend_d == 1) || (blend_flag & BLEND_MIX3)) &&
|
||||
(alpha_eq_less_one || (alpha_c1_eq_less_max_one && new_rt_alpha_scale));
|
||||
|
||||
@@ -5382,36 +5382,35 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
// Color clip
|
||||
if (COLCLAMP.CLAMP == 0)
|
||||
{
|
||||
bool has_HDR_texture = g_gs_device->GetHDRTexture() != nullptr;
|
||||
bool has_colclip_texture = g_gs_device->GetColorClipTexture() != nullptr;
|
||||
|
||||
// Don't know any game that resizes the RT mid HDR, but gotta be careful.
|
||||
if (has_HDR_texture)
|
||||
// Don't know any game that resizes the RT mid colclip, but gotta be careful.
|
||||
if (has_colclip_texture)
|
||||
{
|
||||
GSTexture* hdr_texture = g_gs_device->GetHDRTexture();
|
||||
GSTexture* colclip_texture = g_gs_device->GetColorClipTexture();
|
||||
|
||||
if (hdr_texture->GetSize() != rt->m_texture->GetSize())
|
||||
if (colclip_texture->GetSize() != rt->m_texture->GetSize())
|
||||
{
|
||||
GL_CACHE("Pre-Blend resolve of colclip due to size change! Address: %x", rt->m_TEX0.TBP0);
|
||||
g_gs_device->StretchRect(colclip_texture, GSVector4(m_conf.colclip_update_area) / GSVector4(GSVector4i(colclip_texture->GetSize()).xyxy()), rt->m_texture, GSVector4(m_conf.colclip_update_area),
|
||||
ShaderConvert::COLCLIP_RESOLVE, false);
|
||||
|
||||
GL_CACHE("Pre-Blend resolve of HDR due to size change! Address: %x", rt->m_TEX0.TBP0);
|
||||
g_gs_device->StretchRect(hdr_texture, GSVector4(m_conf.hdr_update_area) / GSVector4(GSVector4i(hdr_texture->GetSize()).xyxy()), rt->m_texture, GSVector4(m_conf.hdr_update_area),
|
||||
ShaderConvert::HDR_RESOLVE, false);
|
||||
g_gs_device->Recycle(colclip_texture);
|
||||
|
||||
g_gs_device->Recycle(hdr_texture);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
|
||||
has_HDR_texture = false;
|
||||
has_colclip_texture = false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool free_colclip = !has_HDR_texture && (features.framebuffer_fetch || no_prim_overlap || blend_non_recursive);
|
||||
const bool free_colclip = !has_colclip_texture && (features.framebuffer_fetch || no_prim_overlap || blend_non_recursive);
|
||||
GL_DBG("COLCLIP Info (Blending: %u/%u/%u/%u, OVERLAP: %d)", m_conf.ps.blend_a, m_conf.ps.blend_b, m_conf.ps.blend_c, m_conf.ps.blend_d, m_prim_overlap);
|
||||
if (color_dest_blend || color_dest_blend2 || blend_zero_to_one_range)
|
||||
{
|
||||
// No overflow, disable colclip.
|
||||
GL_INS("COLCLIP mode DISABLED");
|
||||
sw_blending = false;
|
||||
m_conf.hdr_mode = (has_HDR_texture && !NextDrawHDR()) ? GSHWDrawConfig::HDRMode::ResolveOnly : GSHWDrawConfig::HDRMode::NoModify;
|
||||
m_conf.colclip_mode = (has_colclip_texture && !NextDrawColClip()) ? GSHWDrawConfig::ColClipMode::ResolveOnly : GSHWDrawConfig::ColClipMode::NoModify;
|
||||
}
|
||||
else if (free_colclip)
|
||||
{
|
||||
@@ -5419,35 +5418,35 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
GL_INS("COLCLIP Free mode ENABLED");
|
||||
m_conf.ps.colclip = 1;
|
||||
sw_blending = true;
|
||||
// Disable the HDR algo
|
||||
// Disable the colclip hw algo
|
||||
accumulation_blend = false;
|
||||
blend_mix = false;
|
||||
m_conf.hdr_mode = (has_HDR_texture && !NextDrawHDR()) ? GSHWDrawConfig::HDRMode::ResolveOnly : GSHWDrawConfig::HDRMode::NoModify;
|
||||
m_conf.colclip_mode = (has_colclip_texture && !NextDrawColClip()) ? GSHWDrawConfig::ColClipMode::ResolveOnly : GSHWDrawConfig::ColClipMode::NoModify;
|
||||
}
|
||||
else if (accumulation_blend)
|
||||
{
|
||||
// A fast algo that requires 2 passes
|
||||
GL_INS("COLCLIP Fast HDR mode ENABLED");
|
||||
m_conf.ps.hdr = 1;
|
||||
sw_blending = true; // Enable sw blending for the HDR algo
|
||||
GL_INS("COLCLIP Fast HW mode ENABLED");
|
||||
m_conf.ps.colclip_hw = 1;
|
||||
sw_blending = true; // Enable sw blending for the colclip algo
|
||||
|
||||
m_conf.hdr_mode = has_HDR_texture ? (NextDrawHDR() ? GSHWDrawConfig::HDRMode::NoModify : GSHWDrawConfig::HDRMode::ResolveOnly) : (NextDrawHDR() ? GSHWDrawConfig::HDRMode::ConvertOnly : GSHWDrawConfig::HDRMode::ConvertAndResolve);
|
||||
m_conf.colclip_mode = has_colclip_texture ? (NextDrawColClip() ? GSHWDrawConfig::ColClipMode::NoModify : GSHWDrawConfig::ColClipMode::ResolveOnly) : (NextDrawColClip() ? GSHWDrawConfig::ColClipMode::ConvertOnly : GSHWDrawConfig::ColClipMode::ConvertAndResolve);
|
||||
}
|
||||
else if (sw_blending)
|
||||
{
|
||||
// A slow algo that could requires several passes (barely used)
|
||||
GL_INS("COLCLIP SW mode ENABLED");
|
||||
m_conf.ps.colclip = 1;
|
||||
m_conf.hdr_mode = (has_HDR_texture && !NextDrawHDR()) ? GSHWDrawConfig::HDRMode::ResolveOnly : GSHWDrawConfig::HDRMode::NoModify;
|
||||
m_conf.colclip_mode = (has_colclip_texture && !NextDrawColClip()) ? GSHWDrawConfig::ColClipMode::ResolveOnly : GSHWDrawConfig::ColClipMode::NoModify;
|
||||
}
|
||||
else
|
||||
{
|
||||
GL_INS("COLCLIP HDR mode ENABLED");
|
||||
m_conf.ps.hdr = 1;
|
||||
m_conf.hdr_mode = has_HDR_texture ? (NextDrawHDR() ? GSHWDrawConfig::HDRMode::NoModify : GSHWDrawConfig::HDRMode::ResolveOnly) : (NextDrawHDR() ? GSHWDrawConfig::HDRMode::ConvertOnly : GSHWDrawConfig::HDRMode::ConvertAndResolve);
|
||||
GL_INS("COLCLIP HW mode ENABLED");
|
||||
m_conf.ps.colclip_hw = 1;
|
||||
m_conf.colclip_mode = has_colclip_texture ? (NextDrawColClip() ? GSHWDrawConfig::ColClipMode::NoModify : GSHWDrawConfig::ColClipMode::ResolveOnly) : (NextDrawColClip() ? GSHWDrawConfig::ColClipMode::ConvertOnly : GSHWDrawConfig::ColClipMode::ConvertAndResolve);
|
||||
}
|
||||
|
||||
m_conf.hdr_frame = m_cached_ctx.FRAME;
|
||||
m_conf.colclip_frame = m_cached_ctx.FRAME;
|
||||
}
|
||||
|
||||
// Per pixel alpha blending
|
||||
@@ -5478,13 +5477,13 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
blend_mix = false;
|
||||
m_conf.ps.pabe = 1;
|
||||
|
||||
// HDR mode should be disabled when doing sw blend, swap with sw colclip.
|
||||
if (m_conf.ps.hdr)
|
||||
// hw colclip mode should be disabled when doing sw blend, swap with sw colclip.
|
||||
if (m_conf.ps.colclip_hw)
|
||||
{
|
||||
const bool has_HDR_texture = g_gs_device->GetHDRTexture() != nullptr;
|
||||
m_conf.ps.hdr = 0;
|
||||
const bool has_colclip_texture = g_gs_device->GetColorClipTexture() != nullptr;
|
||||
m_conf.ps.colclip_hw = 0;
|
||||
m_conf.ps.colclip = 1;
|
||||
m_conf.hdr_mode = has_HDR_texture ? GSHWDrawConfig::HDRMode::EarlyResolve : GSHWDrawConfig::HDRMode::NoModify;
|
||||
m_conf.colclip_mode = has_colclip_texture ? GSHWDrawConfig::ColClipMode::EarlyResolve : GSHWDrawConfig::ColClipMode::NoModify;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -5552,9 +5551,9 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
if (blend.op == GSDevice::OP_REV_SUBTRACT)
|
||||
{
|
||||
pxAssert(m_conf.ps.blend_a == 2);
|
||||
if (m_conf.ps.hdr)
|
||||
if (m_conf.ps.colclip_hw)
|
||||
{
|
||||
// HDR uses unorm, which is always positive
|
||||
// HW colclip uses unorm, which is always positive
|
||||
// Have the shader do the inversion, then clip to remove the negative
|
||||
m_conf.blend.op = GSDevice::OP_ADD;
|
||||
}
|
||||
@@ -6493,8 +6492,9 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
// Can't use box filtering on depth (yet), or fractional scales.
|
||||
if (src_target->m_texture->IsDepthStencil() || std::floor(src_target->GetScale()) != src_target->GetScale())
|
||||
{
|
||||
const GSVector4 dst_rect = GSVector4(GSVector4i::loadh(src_unscaled_size));
|
||||
g_gs_device->StretchRect(src_target->m_texture, GSVector4::cxpr(0.0f, 0.0f, 1.0f, 1.0f), src_copy.get(), dst_rect,
|
||||
GSVector4 src_rect = GSVector4(tmm.coverage) / GSVector4(GSVector4i::loadh(src_unscaled_size).zwzw());
|
||||
const GSVector4 dst_rect = GSVector4(tmm.coverage);
|
||||
g_gs_device->StretchRect(src_target->m_texture, src_rect, src_copy.get(), dst_rect,
|
||||
src_target->m_texture->IsDepthStencil() ? ShaderConvert::DEPTH_COPY : ShaderConvert::COPY, false);
|
||||
}
|
||||
else
|
||||
@@ -7405,7 +7405,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
m_conf.require_full_barrier = false;
|
||||
}
|
||||
// Multi-pass algorithms shouldn't be needed with full barrier and backends may not handle this correctly
|
||||
pxAssert(!m_conf.require_full_barrier || !m_conf.ps.hdr);
|
||||
pxAssert(!m_conf.require_full_barrier || !m_conf.ps.colclip_hw);
|
||||
|
||||
// Swap full barrier for one barrier when there's no overlap, or a texture shuffle.
|
||||
if (m_conf.require_full_barrier && (m_prim_overlap == PRIM_OVERLAP_NO || m_conf.ps.shuffle))
|
||||
|
||||
@@ -111,7 +111,7 @@ private:
|
||||
void EmulateATST(float& AREF, GSHWDrawConfig::PSSelector& ps, bool pass_2);
|
||||
|
||||
void SetTCOffset();
|
||||
bool NextDrawHDR() const;
|
||||
bool NextDrawColClip() const;
|
||||
bool IsPossibleChannelShuffle() const;
|
||||
bool IsPageCopy() const;
|
||||
bool NextDrawMatchesShuffle() const;
|
||||
|
||||
@@ -1530,7 +1530,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
GL_CACHE("TC: Attempt to repopulate RGB for target [%x] on source lookup", t->m_TEX0.TBP0);
|
||||
for (Target* dst_match : m_dst[DepthStencil])
|
||||
{
|
||||
if (dst_match->m_TEX0.TBP0 != t->m_TEX0.TBP0 || !dst_match->m_valid_rgb)
|
||||
// Be careful of dirty overlap on the targets, we don't really want dirty data.
|
||||
if (dst_match->m_TEX0.TBP0 != t->m_TEX0.TBP0 || !dst_match->m_valid_rgb ||(!dst_match->m_dirty.empty() && !dst_match->m_dirty.GetTotalRect(dst_match->m_TEX0, dst_match->m_unscaled_size).rintersect(block_boundary_rect).rempty()))
|
||||
continue;
|
||||
|
||||
if (!CopyRGBFromDepthToColor(t, dst_match))
|
||||
@@ -2147,7 +2148,23 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
// 2. Preserved data will be in the correct place (in most cases)
|
||||
// 3. Less deleting sources/targets
|
||||
// 4. We can basically do clears in hardware, if they aren't insane ones
|
||||
if (can_use && ((!is_shuffle && t->m_dirty.size() >= 1) || (is_shuffle && src && GSLocalMemory::m_psm[src->m_TEX0.PSM].bpp == 8 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 16)) && ((preserve_alpha && preserve_rgb) || (draw_rect.w > GSLocalMemory::m_psm[t->m_TEX0.PSM].pgs.y && !possible_clear)) && TEX0.TBW != t->m_TEX0.TBW)
|
||||
bool dirtied_area = t->m_dirty.size() >= 1;
|
||||
|
||||
// Check it covers the whole area of the new draw
|
||||
if (!is_shuffle && dirtied_area)
|
||||
{
|
||||
const u32 draw_start = GSLocalMemory::GetStartBlockAddress(TEX0.TBP0, TEX0.TBW, TEX0.PSM, draw_rect);
|
||||
const u32 draw_end = GSLocalMemory::GetEndBlockAddress(TEX0.TBP0, TEX0.TBW, TEX0.PSM, draw_rect);
|
||||
|
||||
const GSVector4i dirty_rect = t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size);
|
||||
const u32 dirty_start = GSLocalMemory::GetStartBlockAddress(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, dirty_rect);
|
||||
const u32 dirty_end = GSLocalMemory::GetEndBlockAddress(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, dirty_rect);
|
||||
|
||||
if (dirty_end < draw_end || dirty_start > draw_start)
|
||||
dirtied_area = false;
|
||||
}
|
||||
|
||||
if (can_use && ((!is_shuffle && dirtied_area) || (is_shuffle && src && GSLocalMemory::m_psm[src->m_TEX0.PSM].bpp == 8 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 16)) && ((preserve_alpha && preserve_rgb) || (draw_rect.w > GSLocalMemory::m_psm[t->m_TEX0.PSM].pgs.y && !possible_clear)) && TEX0.TBW != t->m_TEX0.TBW)
|
||||
{
|
||||
can_use = false;
|
||||
}
|
||||
@@ -2206,7 +2223,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (t->m_dirty.empty() || (t->m_TEX0.TBP0 <= bp && t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size).rintersect(GSVector4i(0, 0, 0, 0) .max_i32(TranslateAlignedRectByPage(t, TEX0.TBP0, TEX0.PSM, TEX0.TBW, min_rect))).rempty()))
|
||||
else if (t->m_dirty.empty() || (t->m_TEX0.TBP0 <= bp && t->m_last_draw >= (GSState::s_n - 1) &&
|
||||
t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size).rintersect(GSVector4i(0, 0, 0, 0).max_i32(TranslateAlignedRectByPage(t, TEX0.TBP0, TEX0.PSM, TEX0.TBW, min_rect))).rempty()))
|
||||
{
|
||||
if (TEX0.TBW == t->m_TEX0.TBW && !is_shuffle && widthpage_offset == 0 && ((min_rect.w + 63)/ 64) > 1)
|
||||
{
|
||||
@@ -2677,6 +2695,15 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
// Probably an old target, get rid of it.
|
||||
if (remove_target)
|
||||
{
|
||||
// DT Racer hits this path and causes a crash when RT in RT is disabled,
|
||||
// so let's make sure source and target texture isn't linked/shared before deleting the target.
|
||||
if (src && src->m_target && src->m_from_target == t && src->m_target_direct)
|
||||
{
|
||||
src->m_target_direct = false;
|
||||
src->m_shared_texture = false;
|
||||
t->m_texture = nullptr;
|
||||
}
|
||||
|
||||
InvalidateSourcesFromTarget(t);
|
||||
i = rev_list.erase(i);
|
||||
delete t;
|
||||
|
||||
@@ -465,7 +465,7 @@ static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)
|
||||
}
|
||||
|
||||
const GSDevice::FeatureSupport features(g_gs_device->Features());
|
||||
if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '1') || dxt10_format == 71)
|
||||
if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '1') || dxt10_format == 71 /*DXGI_FORMAT_BC1_UNORM*/)
|
||||
{
|
||||
info->format = GSTexture::Format::BC1;
|
||||
info->block_size = 4;
|
||||
@@ -473,7 +473,7 @@ static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)
|
||||
if (!features.dxt_textures)
|
||||
return false;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '2') || header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3') || dxt10_format == 74)
|
||||
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '2') || header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '3') || dxt10_format == 74 /*DXGI_FORMAT_BC2_UNORM*/)
|
||||
{
|
||||
info->format = GSTexture::Format::BC2;
|
||||
info->block_size = 4;
|
||||
@@ -481,7 +481,7 @@ static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)
|
||||
if (!features.dxt_textures)
|
||||
return false;
|
||||
}
|
||||
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '4') || header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '5') || dxt10_format == 77)
|
||||
else if (header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '4') || header.ddspf.dwFourCC == MAKEFOURCC('D', 'X', 'T', '5') || dxt10_format == 77 /*DXGI_FORMAT_BC3_UNORM*/)
|
||||
{
|
||||
info->format = GSTexture::Format::BC3;
|
||||
info->block_size = 4;
|
||||
@@ -489,7 +489,7 @@ static bool ParseDDSHeader(std::FILE* fp, DDSLoadInfo* info)
|
||||
if (!features.dxt_textures)
|
||||
return false;
|
||||
}
|
||||
else if (dxt10_format == 98)
|
||||
else if (dxt10_format == 98 /*DXGI_FORMAT_BC7_UNORM*/)
|
||||
{
|
||||
info->format = GSTexture::Format::BC7;
|
||||
info->block_size = 4;
|
||||
|
||||
@@ -256,11 +256,9 @@ public:
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_clut_pipeline[2];
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_stencil_clear_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_primid_init_pipeline[2][4];
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_hdr_init_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_hdr_rta_init_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_hdr_clear_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_hdr_resolve_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_hdr_rta_resolve_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_colclip_init_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_colclip_clear_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_colclip_resolve_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_fxaa_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_shadeboost_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_imgui_pipeline;
|
||||
|
||||
@@ -510,7 +510,9 @@ static constexpr MTLPixelFormat ConvertPixelFormat(GSTexture::Format format)
|
||||
case GSTexture::Format::UInt16: return MTLPixelFormatR16Uint;
|
||||
case GSTexture::Format::UNorm8: return MTLPixelFormatA8Unorm;
|
||||
case GSTexture::Format::Color: return MTLPixelFormatRGBA8Unorm;
|
||||
case GSTexture::Format::HDRColor: return MTLPixelFormatRGBA16Unorm;
|
||||
case GSTexture::Format::ColorHQ: return MTLPixelFormatRGB10A2Unorm;
|
||||
case GSTexture::Format::ColorHDR: return MTLPixelFormatRGBA16Float;
|
||||
case GSTexture::Format::ColorClip: return MTLPixelFormatRGBA16Unorm;
|
||||
case GSTexture::Format::DepthStencil: return MTLPixelFormatDepth32Float_Stencil8;
|
||||
case GSTexture::Format::Invalid: return MTLPixelFormatInvalid;
|
||||
case GSTexture::Format::BC1: return MTLPixelFormatBC1_RGBA;
|
||||
@@ -1065,14 +1067,14 @@ bool GSDeviceMTL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
auto pdesc = [[MTLRenderPipelineDescriptor new] autorelease];
|
||||
// FS Triangle Pipelines
|
||||
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::Color);
|
||||
m_hdr_resolve_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_hdr_resolve"), @"HDR Resolve");
|
||||
m_colclip_resolve_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_colclip_resolve"), @"ColorClip Resolve");
|
||||
m_fxaa_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_fxaa"), @"fxaa");
|
||||
m_shadeboost_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_shadeboost"), @"shadeboost");
|
||||
m_clut_pipeline[0] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_convert_clut_4"), @"4-bit CLUT Update");
|
||||
m_clut_pipeline[1] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_convert_clut_8"), @"8-bit CLUT Update");
|
||||
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::HDRColor);
|
||||
m_hdr_init_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_hdr_init"), @"HDR Init");
|
||||
m_hdr_clear_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_clear"), @"HDR Clear");
|
||||
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::ColorClip);
|
||||
m_colclip_init_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_colclip_init"), @"ColorClip Init");
|
||||
m_colclip_clear_pipeline = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_clear"), @"ColorClip Clear");
|
||||
pdesc.colorAttachments[0].pixelFormat = MTLPixelFormatInvalid;
|
||||
pdesc.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||
m_datm_pipeline[0] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_datm0"), @"datm0");
|
||||
@@ -1116,8 +1118,8 @@ bool GSDeviceMTL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
case ShaderConvert::DATM_1_RTA_CORRECTION:
|
||||
case ShaderConvert::CLUT_4:
|
||||
case ShaderConvert::CLUT_8:
|
||||
case ShaderConvert::HDR_INIT:
|
||||
case ShaderConvert::HDR_RESOLVE:
|
||||
case ShaderConvert::COLCLIP_INIT:
|
||||
case ShaderConvert::COLCLIP_RESOLVE:
|
||||
continue;
|
||||
case ShaderConvert::FLOAT32_TO_32_BITS:
|
||||
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::UInt32);
|
||||
@@ -1174,7 +1176,7 @@ bool GSDeviceMTL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
m_present_pipeline[i] = MakePipeline(pdesc, vs_convert, LoadShader(name), [NSString stringWithFormat:@"present_%s", shaderName(conv) + 3]);
|
||||
}
|
||||
|
||||
pdesc.colorAttachments[0].pixelFormat = MTLPixelFormatRGBA8Unorm;
|
||||
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::Color);
|
||||
for (size_t i = 0; i < std::size(m_convert_pipeline_copy_mask); i++)
|
||||
{
|
||||
MTLColorWriteMask mask = MTLColorWriteMaskNone;
|
||||
@@ -1852,7 +1854,7 @@ void GSDeviceMTL::MRESetHWPipelineState(GSHWDrawConfig::VSSelector vssel, GSHWDr
|
||||
setFnConstantI(m_fn_constants, pssel.blend_d, GSMTLConstantIndex_PS_BLEND_D);
|
||||
setFnConstantI(m_fn_constants, pssel.blend_hw, GSMTLConstantIndex_PS_BLEND_HW);
|
||||
setFnConstantB(m_fn_constants, pssel.a_masked, GSMTLConstantIndex_PS_A_MASKED);
|
||||
setFnConstantB(m_fn_constants, pssel.hdr, GSMTLConstantIndex_PS_HDR);
|
||||
setFnConstantB(m_fn_constants, pssel.colclip_hw, GSMTLConstantIndex_PS_COLCLIP_HW);
|
||||
setFnConstantB(m_fn_constants, pssel.rta_correction, GSMTLConstantIndex_PS_RTA_CORRECTION);
|
||||
setFnConstantB(m_fn_constants, pssel.rta_source_correction, GSMTLConstantIndex_PS_RTA_SRC_CORRECTION);
|
||||
setFnConstantB(m_fn_constants, pssel.colclip, GSMTLConstantIndex_PS_COLCLIP);
|
||||
@@ -2142,53 +2144,53 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
|
||||
GSTexture* stencil = nullptr;
|
||||
GSTexture* primid_tex = nullptr;
|
||||
GSTexture* rt = config.rt;
|
||||
GSTexture* hdr_rt = g_gs_device->GetHDRTexture();
|
||||
GSTexture* colclip_rt = g_gs_device->GetColorClipTexture();
|
||||
|
||||
if (hdr_rt)
|
||||
if (colclip_rt)
|
||||
{
|
||||
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
|
||||
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::EarlyResolve)
|
||||
{
|
||||
BeginRenderPass(@"HDR Resolve", config.rt, MTLLoadActionLoad, nullptr, MTLLoadActionDontCare);
|
||||
RenderCopy(hdr_rt, m_hdr_resolve_pipeline, config.hdr_update_area);
|
||||
BeginRenderPass(@"ColorClip Resolve", config.rt, MTLLoadActionLoad, nullptr, MTLLoadActionDontCare);
|
||||
RenderCopy(colclip_rt, m_colclip_resolve_pipeline, config.colclip_update_area);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
|
||||
Recycle(hdr_rt);
|
||||
Recycle(colclip_rt);
|
||||
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
|
||||
hdr_rt = nullptr;
|
||||
colclip_rt = nullptr;
|
||||
}
|
||||
else
|
||||
config.ps.hdr = 1;
|
||||
config.ps.colclip_hw = 1;
|
||||
}
|
||||
|
||||
if (config.ps.hdr)
|
||||
if (config.ps.colclip_hw)
|
||||
{
|
||||
if (!hdr_rt)
|
||||
if (!colclip_rt)
|
||||
{
|
||||
config.hdr_update_area = config.drawarea;
|
||||
config.colclip_update_area = config.drawarea;
|
||||
|
||||
GSVector2i size = config.rt->GetSize();
|
||||
rt = hdr_rt = CreateRenderTarget(size.x, size.y, GSTexture::Format::HDRColor, false);
|
||||
rt = colclip_rt = CreateRenderTarget(size.x, size.y, GSTexture::Format::ColorClip, false);
|
||||
|
||||
g_gs_device->SetHDRTexture(hdr_rt);
|
||||
g_gs_device->SetColorClipTexture(colclip_rt);
|
||||
|
||||
const GSVector4i copy_rect = (config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(size) : config.drawarea;
|
||||
const GSVector4i copy_rect = (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(size) : config.drawarea;
|
||||
|
||||
switch (config.rt->GetState())
|
||||
{
|
||||
case GSTexture::State::Dirty:
|
||||
BeginRenderPass(@"HDR Init", hdr_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare);
|
||||
RenderCopy(config.rt, m_hdr_init_pipeline, copy_rect);
|
||||
BeginRenderPass(@"ColorClip Init", colclip_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare);
|
||||
RenderCopy(config.rt, m_colclip_init_pipeline, copy_rect);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
break;
|
||||
|
||||
case GSTexture::State::Cleared:
|
||||
{
|
||||
BeginRenderPass(@"HDR Clear", hdr_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare);
|
||||
BeginRenderPass(@"ColorClip Clear", colclip_rt, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare);
|
||||
GSVector4 color = GSVector4::rgba32(config.rt->GetClearColor()) / GSVector4::cxpr(65535, 65535, 65535, 255);
|
||||
[m_current_render.encoder setFragmentBytes:&color length:sizeof(color) atIndex:GSMTLBufferIndexUniforms];
|
||||
RenderCopy(nullptr, m_hdr_clear_pipeline, copy_rect);
|
||||
RenderCopy(nullptr, m_colclip_clear_pipeline, copy_rect);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2197,7 +2199,7 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
}
|
||||
|
||||
rt = hdr_rt;
|
||||
rt = colclip_rt;
|
||||
}
|
||||
|
||||
switch (config.destination_alpha)
|
||||
@@ -2284,19 +2286,19 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
|
||||
SendHWDraw(config, mtlenc, index_buffer, index_buffer_offset);
|
||||
}
|
||||
|
||||
if (hdr_rt)
|
||||
if (colclip_rt)
|
||||
{
|
||||
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);
|
||||
config.colclip_update_area = config.colclip_update_area.runion(config.drawarea);
|
||||
|
||||
if ((config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve))
|
||||
if ((config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve))
|
||||
{
|
||||
BeginRenderPass(@"HDR Resolve", config.rt, MTLLoadActionLoad, nullptr, MTLLoadActionDontCare);
|
||||
RenderCopy(hdr_rt, m_hdr_resolve_pipeline, config.hdr_update_area);
|
||||
BeginRenderPass(@"ColorClip Resolve", config.rt, MTLLoadActionLoad, nullptr, MTLLoadActionDontCare);
|
||||
RenderCopy(colclip_rt, m_colclip_resolve_pipeline, config.colclip_update_area);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
|
||||
Recycle(hdr_rt);
|
||||
Recycle(colclip_rt);
|
||||
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@ enum GSMTLFnConstants
|
||||
GSMTLConstantIndex_PS_BLEND_D,
|
||||
GSMTLConstantIndex_PS_BLEND_HW,
|
||||
GSMTLConstantIndex_PS_A_MASKED,
|
||||
GSMTLConstantIndex_PS_HDR,
|
||||
GSMTLConstantIndex_PS_COLCLIP_HW,
|
||||
GSMTLConstantIndex_PS_RTA_CORRECTION,
|
||||
GSMTLConstantIndex_PS_RTA_SRC_CORRECTION,
|
||||
GSMTLConstantIndex_PS_COLCLIP,
|
||||
|
||||
@@ -138,13 +138,13 @@ fragment float4 ps_rta_decorrection(ConvertShaderData data [[stage_in]], Convert
|
||||
return float4(in.rgb, in.a * (128.25f / 255.0f));
|
||||
}
|
||||
|
||||
fragment float4 ps_hdr_init(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
fragment float4 ps_colclip_init(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
{
|
||||
float4 in = tex.read(p);
|
||||
return float4(round(in.rgb * 255.f) / 65535.f, in.a);
|
||||
}
|
||||
|
||||
fragment float4 ps_hdr_resolve(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
fragment float4 ps_colclip_resolve(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
{
|
||||
float4 in = tex.read(p);
|
||||
return float4(float3(uint3(in.rgb * 65535.5f) & 255) / 255.f, in.a);
|
||||
|
||||
@@ -47,7 +47,7 @@ constant uint PS_BLEND_C [[function_constant(GSMTLConstantIndex_PS_BL
|
||||
constant uint PS_BLEND_D [[function_constant(GSMTLConstantIndex_PS_BLEND_D)]];
|
||||
constant uint PS_BLEND_HW [[function_constant(GSMTLConstantIndex_PS_BLEND_HW)]];
|
||||
constant bool PS_A_MASKED [[function_constant(GSMTLConstantIndex_PS_A_MASKED)]];
|
||||
constant bool PS_HDR [[function_constant(GSMTLConstantIndex_PS_HDR)]];
|
||||
constant bool PS_COLCLIP_HW [[function_constant(GSMTLConstantIndex_PS_COLCLIP_HW)]];
|
||||
constant bool PS_RTA_CORRECTION [[function_constant(GSMTLConstantIndex_PS_RTA_CORRECTION)]];
|
||||
constant bool PS_RTA_SRC_CORRECTION [[function_constant(GSMTLConstantIndex_PS_RTA_SRC_CORRECTION)]];
|
||||
constant bool PS_COLCLIP [[function_constant(GSMTLConstantIndex_PS_COLCLIP)]];
|
||||
@@ -858,7 +858,7 @@ struct PSMain
|
||||
{
|
||||
if (PS_FBMASK)
|
||||
{
|
||||
float multi = PS_HDR ? 65535.0 : 255.5;
|
||||
float multi = PS_COLCLIP_HW ? 65535.0 : 255.5;
|
||||
C = float4((uint4(int4(C)) & (cb.fbmask ^ 0xff)) | (uint4(current_color * float4(multi, multi, multi, 255)) & cb.fbmask));
|
||||
}
|
||||
}
|
||||
@@ -898,7 +898,7 @@ struct PSMain
|
||||
C.rgb += 7.f; // Need to round up, not down since the shader will invert
|
||||
|
||||
// Correct the Color value based on the output format
|
||||
if (PS_COLCLIP == 0 && PS_HDR == 0)
|
||||
if (PS_COLCLIP == 0 && PS_COLCLIP_HW == 0)
|
||||
C.rgb = clamp(C.rgb, 0.f, 255.f); // Standard Clamp
|
||||
|
||||
// FIXME rouding of negative float?
|
||||
@@ -910,7 +910,7 @@ struct PSMain
|
||||
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
|
||||
if (PS_DST_FMT == FMT_16 && PS_DITHER != 3 && (PS_BLEND_MIX == 0 || PS_DITHER))
|
||||
C.rgb = float3(short3(C.rgb) & 0xF8);
|
||||
else if (PS_COLCLIP == 1 || PS_HDR == 1)
|
||||
else if (PS_COLCLIP == 1 || PS_COLCLIP_HW == 1)
|
||||
C.rgb = float3(short3(C.rgb) & 0xFF);
|
||||
}
|
||||
else if (PS_DST_FMT == FMT_16 && PS_DITHER != 3 && PS_BLEND_MIX == 0 && PS_BLEND_HW == 0)
|
||||
@@ -963,7 +963,7 @@ struct PSMain
|
||||
current_color.a = float(denorm_rt.g & 0x80);
|
||||
}
|
||||
}
|
||||
float multi = PS_HDR ? 65535.0 : 255.5;
|
||||
float multi = PS_COLCLIP_HW ? 65535.0 : 255.5;
|
||||
float3 Cd = trunc(current_color.rgb * multi);
|
||||
float3 Cs = Color.rgb;
|
||||
|
||||
@@ -1205,7 +1205,7 @@ struct PSMain
|
||||
if (PS_COLOR0)
|
||||
{
|
||||
out.c0.a = PS_RTA_CORRECTION ? C.a / 128.f : C.a / 255.f;
|
||||
out.c0.rgb = PS_HDR ? float3(C.rgb / 65535.f) : C.rgb / 255.f;
|
||||
out.c0.rgb = PS_COLCLIP_HW ? float3(C.rgb / 65535.f) : C.rgb / 255.f;
|
||||
if (PS_AFAIL == 3 && !PS_COLOR1 && !atst_pass) // Doing RGB_ONLY without COLOR1
|
||||
out.c0.a = current_color.a;
|
||||
}
|
||||
|
||||
@@ -1394,7 +1394,7 @@ std::string GSDeviceOGL::GetPSSource(const PSSelector& sel)
|
||||
+ fmt::format("#define PS_READ16_SRC {}\n", sel.real16src)
|
||||
+ fmt::format("#define PS_WRITE_RG {}\n", sel.write_rg)
|
||||
+ fmt::format("#define PS_FBMASK {}\n", sel.fbmask)
|
||||
+ fmt::format("#define PS_HDR {}\n", sel.hdr)
|
||||
+ fmt::format("#define PS_COLCLIP_HW {}\n", sel.colclip_hw)
|
||||
+ fmt::format("#define PS_RTA_CORRECTION {}\n", sel.rta_correction)
|
||||
+ fmt::format("#define PS_RTA_SRC_CORRECTION {}\n", sel.rta_source_correction)
|
||||
+ fmt::format("#define PS_DITHER {}\n", sel.dither)
|
||||
@@ -2414,43 +2414,43 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();
|
||||
|
||||
GSTexture* primid_texture = nullptr;
|
||||
GSTexture* hdr_rt = g_gs_device->GetHDRTexture();
|
||||
GSTexture* colclip_rt = g_gs_device->GetColorClipTexture();
|
||||
|
||||
if (hdr_rt)
|
||||
if (colclip_rt)
|
||||
{
|
||||
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
|
||||
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::EarlyResolve)
|
||||
{
|
||||
const GSVector2i size = config.rt->GetSize();
|
||||
const GSVector4 dRect(config.hdr_update_area);
|
||||
const GSVector4 dRect(config.colclip_update_area);
|
||||
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
|
||||
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
|
||||
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
|
||||
|
||||
Recycle(hdr_rt);
|
||||
Recycle(colclip_rt);
|
||||
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
|
||||
hdr_rt = nullptr;
|
||||
colclip_rt = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
config.ps.hdr = 1;
|
||||
config.ps.colclip_hw = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.ps.hdr)
|
||||
if (config.ps.colclip_hw)
|
||||
{
|
||||
if (!hdr_rt)
|
||||
if (!colclip_rt)
|
||||
{
|
||||
config.hdr_update_area = config.drawarea;
|
||||
config.colclip_update_area = config.drawarea;
|
||||
|
||||
hdr_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::HDRColor, false);
|
||||
OMSetRenderTargets(hdr_rt, config.ds, nullptr);
|
||||
colclip_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false);
|
||||
OMSetRenderTargets(colclip_rt, config.ds, nullptr);
|
||||
|
||||
g_gs_device->SetHDRTexture(hdr_rt);
|
||||
g_gs_device->SetColorClipTexture(colclip_rt);
|
||||
|
||||
const GSVector4 dRect = GSVector4((config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
|
||||
StretchRect(config.rt, sRect, hdr_rt, dRect, ShaderConvert::HDR_INIT, false);
|
||||
StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2461,7 +2461,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
case GSHWDrawConfig::DestinationAlphaMode::Full:
|
||||
break; // No setup
|
||||
case GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking:
|
||||
primid_texture = InitPrimDateTexture(hdr_rt ? hdr_rt : config.rt, config.drawarea, config.datm);
|
||||
primid_texture = InitPrimDateTexture(colclip_rt ? colclip_rt : config.rt, config.drawarea, config.datm);
|
||||
break;
|
||||
case GSHWDrawConfig::DestinationAlphaMode::StencilOne:
|
||||
if (m_features.texture_barrier)
|
||||
@@ -2481,7 +2481,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
{GSVector4(dst.x, dst.w, 0.0f, 0.0f), GSVector2(src.x, src.w)},
|
||||
{GSVector4(dst.z, dst.w, 0.0f, 0.0f), GSVector2(src.z, src.w)},
|
||||
};
|
||||
SetupDATE(hdr_rt ? hdr_rt : config.rt, config.ds, vertices, config.datm);
|
||||
SetupDATE(colclip_rt ? colclip_rt : config.rt, config.ds, vertices, config.datm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2490,11 +2490,11 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
if (config.require_one_barrier && !m_features.texture_barrier)
|
||||
{
|
||||
// Requires a copy of the RT
|
||||
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, hdr_rt ? GSTexture::Format::HDRColor : GSTexture::Format::Color, true);
|
||||
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true);
|
||||
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}",
|
||||
config.drawarea.left, config.drawarea.top,
|
||||
config.drawarea.width(), config.drawarea.height());
|
||||
CopyRect(hdr_rt ? hdr_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
|
||||
}
|
||||
|
||||
IASetVertexBuffer(config.verts, config.nverts);
|
||||
@@ -2534,7 +2534,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
if (draw_rt_clone)
|
||||
PSSetShaderResource(2, draw_rt_clone);
|
||||
else if (config.require_one_barrier || config.require_full_barrier)
|
||||
PSSetShaderResource(2, hdr_rt ? hdr_rt : config.rt);
|
||||
PSSetShaderResource(2, colclip_rt ? colclip_rt : config.rt);
|
||||
|
||||
SetupSampler(config.sampler);
|
||||
|
||||
@@ -2622,7 +2622,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
|
||||
// avoid changing framebuffer just to switch from rt+depth to rt and vice versa
|
||||
GSTexture* draw_rt = hdr_rt ? hdr_rt : config.rt;
|
||||
GSTexture* draw_rt = colclip_rt ? colclip_rt : config.rt;
|
||||
GSTexture* draw_ds = config.ds;
|
||||
if (!draw_rt && GLState::rt && GLState::ds == draw_ds && config.tex != GLState::rt &&
|
||||
GLState::rt->GetSize() == draw_ds->GetSize())
|
||||
@@ -2700,20 +2700,20 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
if (draw_rt_clone)
|
||||
Recycle(draw_rt_clone);
|
||||
|
||||
if (hdr_rt)
|
||||
if (colclip_rt)
|
||||
{
|
||||
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);
|
||||
config.colclip_update_area = config.colclip_update_area.runion(config.drawarea);
|
||||
|
||||
if ((config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve))
|
||||
if ((config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve))
|
||||
{
|
||||
const GSVector2i size = config.rt->GetSize();
|
||||
const GSVector4 dRect(config.hdr_update_area);
|
||||
const GSVector4 dRect(config.colclip_update_area);
|
||||
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
|
||||
StretchRect(hdr_rt, sRect, config.rt, dRect, ShaderConvert::HDR_RESOLVE, false);
|
||||
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
|
||||
|
||||
Recycle(hdr_rt);
|
||||
Recycle(colclip_rt);
|
||||
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,8 @@ GSTextureOGL::GSTextureOGL(Type type, int width, int height, int levels, Format
|
||||
|
||||
// 4 channel normalized
|
||||
case Format::Color:
|
||||
case Format::ColorHQ:
|
||||
case Format::ColorHDR:
|
||||
gl_fmt = GL_RGBA8;
|
||||
m_int_format = GL_RGBA;
|
||||
m_int_type = GL_UNSIGNED_BYTE;
|
||||
@@ -72,7 +74,7 @@ GSTextureOGL::GSTextureOGL(Type type, int width, int height, int levels, Format
|
||||
break;
|
||||
|
||||
// 4 channel float
|
||||
case Format::HDRColor:
|
||||
case Format::ColorClip:
|
||||
gl_fmt = GL_RGBA16;
|
||||
m_int_format = GL_RGBA;
|
||||
m_int_type = GL_UNSIGNED_SHORT;
|
||||
|
||||
@@ -2104,7 +2104,8 @@ bool GSDeviceVK::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
return false;
|
||||
}
|
||||
|
||||
CompileCASPipelines();
|
||||
if (!CompileCASPipelines())
|
||||
return false;
|
||||
|
||||
if (!CompileImGuiPipeline())
|
||||
return false;
|
||||
@@ -2715,10 +2716,12 @@ void GSDeviceVK::DrawIndexedPrimitive(int offset, int count)
|
||||
|
||||
VkFormat GSDeviceVK::LookupNativeFormat(GSTexture::Format format) const
|
||||
{
|
||||
static constexpr std::array<VkFormat, static_cast<int>(GSTexture::Format::BC7) + 1> s_format_mapping = {{
|
||||
static constexpr std::array<VkFormat, static_cast<int>(GSTexture::Format::Last) + 1> s_format_mapping = {{
|
||||
VK_FORMAT_UNDEFINED, // Invalid
|
||||
VK_FORMAT_R8G8B8A8_UNORM, // Color
|
||||
VK_FORMAT_R16G16B16A16_UNORM, // HDRColor
|
||||
VK_FORMAT_A2B10G10R10_UNORM_PACK32, // ColorHQ
|
||||
VK_FORMAT_R16G16B16A16_SFLOAT, // ColorHDR
|
||||
VK_FORMAT_R16G16B16A16_UNORM, // ColorClip
|
||||
VK_FORMAT_D32_SFLOAT_S8_UINT, // DepthStencil
|
||||
VK_FORMAT_R8_UNORM, // UNorm8
|
||||
VK_FORMAT_R16_UINT, // UInt16
|
||||
@@ -3764,7 +3767,7 @@ bool GSDeviceVK::CreatePipelineLayouts()
|
||||
plb.AddDescriptorSet(m_utility_ds_layout);
|
||||
if ((m_utility_pipeline_layout = plb.Create(dev)) == VK_NULL_HANDLE)
|
||||
return false;
|
||||
Vulkan::SetObjectName(dev, m_utility_ds_layout, "Convert pipeline layout");
|
||||
Vulkan::SetObjectName(dev, m_utility_pipeline_layout, "Convert pipeline layout");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Draw/TFX Pipeline Layout
|
||||
@@ -3820,14 +3823,14 @@ bool GSDeviceVK::CreateRenderPasses()
|
||||
} while (0)
|
||||
|
||||
const VkFormat rt_format = LookupNativeFormat(GSTexture::Format::Color);
|
||||
const VkFormat hdr_rt_format = LookupNativeFormat(GSTexture::Format::HDRColor);
|
||||
const VkFormat colclip_rt_format = LookupNativeFormat(GSTexture::Format::ColorClip);
|
||||
const VkFormat depth_format = LookupNativeFormat(GSTexture::Format::DepthStencil);
|
||||
|
||||
for (u32 rt = 0; rt < 2; rt++)
|
||||
{
|
||||
for (u32 ds = 0; ds < 2; ds++)
|
||||
{
|
||||
for (u32 hdr = 0; hdr < 2; hdr++)
|
||||
for (u32 colclip = 0; colclip < 2; colclip++)
|
||||
{
|
||||
for (u32 stencil = 0; stencil < 2; stencil++)
|
||||
{
|
||||
@@ -3841,12 +3844,12 @@ bool GSDeviceVK::CreateRenderPasses()
|
||||
opb++)
|
||||
{
|
||||
const VkFormat rp_rt_format =
|
||||
(rt != 0) ? ((hdr != 0) ? hdr_rt_format : rt_format) : VK_FORMAT_UNDEFINED;
|
||||
(rt != 0) ? ((colclip != 0) ? colclip_rt_format : rt_format) : VK_FORMAT_UNDEFINED;
|
||||
const VkFormat rp_depth_format = (ds != 0) ? depth_format : VK_FORMAT_UNDEFINED;
|
||||
const VkAttachmentLoadOp opc = (!stencil || !m_features.stencil_buffer) ?
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE :
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
GET(m_tfx_render_pass[rt][ds][hdr][stencil][fbl][dsp][opa][opb], rp_rt_format,
|
||||
GET(m_tfx_render_pass[rt][ds][colclip][stencil][fbl][dsp][opa][opb], rp_rt_format,
|
||||
rp_depth_format, (fbl != 0), (dsp != 0), static_cast<VkAttachmentLoadOp>(opa),
|
||||
static_cast<VkAttachmentLoadOp>(opb), static_cast<VkAttachmentLoadOp>(opc));
|
||||
}
|
||||
@@ -3999,15 +4002,7 @@ bool GSDeviceVK::CompileConvertPipelines()
|
||||
}
|
||||
else if (i == ShaderConvert::RTA_CORRECTION)
|
||||
{
|
||||
// compile color copy pipelines
|
||||
gpb.SetRenderPass(m_utility_color_render_pass_discard, 0);
|
||||
VkShaderModule ps = GetUtilityFragmentShader(*shader, shaderName(i));
|
||||
if (ps == VK_NULL_HANDLE)
|
||||
return false;
|
||||
|
||||
ScopedGuard ps_guard([this, &ps]() { vkDestroyShaderModule(m_device, ps, nullptr); });
|
||||
gpb.SetFragmentShader(ps);
|
||||
|
||||
for (u32 j = 16; j < 32; j++)
|
||||
{
|
||||
pxAssert(!m_color_copy[j]);
|
||||
@@ -4023,10 +4018,10 @@ bool GSDeviceVK::CompileConvertPipelines()
|
||||
(j >> 1) & 1u, (j >> 2) & 1u, (j >> 3) & 1u);
|
||||
}
|
||||
}
|
||||
else if (i == ShaderConvert::HDR_INIT || i == ShaderConvert::HDR_RESOLVE)
|
||||
else if (i == ShaderConvert::COLCLIP_INIT || i == ShaderConvert::COLCLIP_RESOLVE)
|
||||
{
|
||||
const bool is_setup = i == ShaderConvert::HDR_INIT;
|
||||
VkPipeline(&arr)[2][2] = *(is_setup ? &m_hdr_setup_pipelines : &m_hdr_finish_pipelines);
|
||||
const bool is_setup = i == ShaderConvert::COLCLIP_INIT;
|
||||
VkPipeline(&arr)[2][2] = *(is_setup ? &m_colclip_setup_pipelines : &m_colclip_finish_pipelines);
|
||||
for (u32 ds = 0; ds < 2; ds++)
|
||||
{
|
||||
for (u32 fbl = 0; fbl < 2; fbl++)
|
||||
@@ -4040,7 +4035,7 @@ bool GSDeviceVK::CompileConvertPipelines()
|
||||
if (!arr[ds][fbl])
|
||||
return false;
|
||||
|
||||
Vulkan::SetObjectName(m_device, arr[ds][fbl], "HDR %s/copy pipeline (ds=%u, fbl=%u)",
|
||||
Vulkan::SetObjectName(m_device, arr[ds][fbl], "ColorClip %s/copy pipeline (ds=%u, fbl=%u)",
|
||||
is_setup ? "setup" : "finish", i, ds, fbl);
|
||||
}
|
||||
}
|
||||
@@ -4196,7 +4191,7 @@ bool GSDeviceVK::CompileInterlacePipelines()
|
||||
if (!m_interlace[i])
|
||||
return false;
|
||||
|
||||
Vulkan::SetObjectName(m_device, m_convert[i], "Interlace pipeline %d", i);
|
||||
Vulkan::SetObjectName(m_device, m_interlace[i], "Interlace pipeline %d", i);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -4248,7 +4243,7 @@ bool GSDeviceVK::CompileMergePipelines()
|
||||
if (!m_merge[i])
|
||||
return false;
|
||||
|
||||
Vulkan::SetObjectName(m_device, m_convert[i], "Merge pipeline %d", i);
|
||||
Vulkan::SetObjectName(m_device, m_merge[i], "Merge pipeline %d", i);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -4610,10 +4605,10 @@ void GSDeviceVK::DestroyResources()
|
||||
{
|
||||
for (u32 fbl = 0; fbl < 2; fbl++)
|
||||
{
|
||||
if (m_hdr_setup_pipelines[ds][fbl] != VK_NULL_HANDLE)
|
||||
vkDestroyPipeline(m_device, m_hdr_setup_pipelines[ds][fbl], nullptr);
|
||||
if (m_hdr_finish_pipelines[ds][fbl] != VK_NULL_HANDLE)
|
||||
vkDestroyPipeline(m_device, m_hdr_finish_pipelines[ds][fbl], nullptr);
|
||||
if (m_colclip_setup_pipelines[ds][fbl] != VK_NULL_HANDLE)
|
||||
vkDestroyPipeline(m_device, m_colclip_setup_pipelines[ds][fbl], nullptr);
|
||||
if (m_colclip_finish_pipelines[ds][fbl] != VK_NULL_HANDLE)
|
||||
vkDestroyPipeline(m_device, m_colclip_finish_pipelines[ds][fbl], nullptr);
|
||||
}
|
||||
}
|
||||
for (u32 ds = 0; ds < 2; ds++)
|
||||
@@ -4782,7 +4777,7 @@ VkShaderModule GSDeviceVK::GetTFXFragmentShader(const GSHWDrawConfig::PSSelector
|
||||
AddMacro(ss, "PS_READ16_SRC", sel.real16src);
|
||||
AddMacro(ss, "PS_WRITE_RG", sel.write_rg);
|
||||
AddMacro(ss, "PS_FBMASK", sel.fbmask);
|
||||
AddMacro(ss, "PS_HDR", sel.hdr);
|
||||
AddMacro(ss, "PS_COLCLIP_HW", sel.colclip_hw);
|
||||
AddMacro(ss, "PS_RTA_CORRECTION", sel.rta_correction);
|
||||
AddMacro(ss, "PS_RTA_SRC_CORRECTION", sel.rta_source_correction);
|
||||
AddMacro(ss, "PS_DITHER", sel.dither);
|
||||
@@ -4838,7 +4833,7 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p)
|
||||
else
|
||||
{
|
||||
gpb.SetRenderPass(
|
||||
GetTFXRenderPass(p.rt, p.ds, p.ps.hdr, p.dss.date,
|
||||
GetTFXRenderPass(p.rt, p.ds, p.ps.colclip_hw, p.dss.date,
|
||||
p.IsRTFeedbackLoop(), p.IsTestingAndSamplingDepth(),
|
||||
p.rt ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
||||
p.ds ? VK_ATTACHMENT_LOAD_OP_LOAD : VK_ATTACHMENT_LOAD_OP_DONT_CARE),
|
||||
@@ -4967,7 +4962,7 @@ void GSDeviceVK::InitializeState()
|
||||
Vulkan::SetObjectName(m_device, m_point_sampler, "Point sampler");
|
||||
m_linear_sampler = GetSampler(GSHWDrawConfig::SamplerSelector::Linear());
|
||||
if (m_linear_sampler)
|
||||
Vulkan::SetObjectName(m_device, m_point_sampler, "Linear sampler");
|
||||
Vulkan::SetObjectName(m_device, m_linear_sampler, "Linear sampler");
|
||||
|
||||
m_tfx_sampler_sel = GSHWDrawConfig::SamplerSelector::Point().key;
|
||||
m_tfx_sampler = m_point_sampler;
|
||||
@@ -5595,7 +5590,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
GSTextureVK* draw_rt = static_cast<GSTextureVK*>(config.rt);
|
||||
GSTextureVK* draw_ds = static_cast<GSTextureVK*>(config.ds);
|
||||
GSTextureVK* draw_rt_clone = nullptr;
|
||||
GSTextureVK* hdr_rt = static_cast<GSTextureVK*>(g_gs_device->GetHDRTexture());
|
||||
GSTextureVK* colclip_rt = static_cast<GSTextureVK*>(g_gs_device->GetColorClipTexture());
|
||||
|
||||
// stream buffer in first, in case we need to exec
|
||||
SetVSConstantBuffer(config.cb_vs);
|
||||
@@ -5621,11 +5616,11 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
GSTextureVK* date_image = nullptr;
|
||||
if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking)
|
||||
{
|
||||
// If we have a HDR in progress, we need to use the HDR texture, but we can't check this later as there's a chicken/egg problem with the pipe setup.
|
||||
// If we have a colclip in progress, we need to use the colclip texture, but we can't check this later as there's a chicken/egg problem with the pipe setup.
|
||||
GSTexture* backup_rt = config.rt;
|
||||
|
||||
if(hdr_rt)
|
||||
config.rt = hdr_rt;
|
||||
if(colclip_rt)
|
||||
config.rt = colclip_rt;
|
||||
|
||||
date_image = SetupPrimitiveTrackingDATE(config);
|
||||
if (!date_image)
|
||||
@@ -5645,15 +5640,15 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
if (InRenderPass() && !pipe.IsRTFeedbackLoop() && (config.tex == m_current_render_target || config.tex == m_current_depth_target))
|
||||
EndRenderPass();
|
||||
|
||||
// now blit the hdr texture back to the original target
|
||||
if (hdr_rt)
|
||||
// now blit the colclip texture back to the original target
|
||||
if (colclip_rt)
|
||||
{
|
||||
if (config.hdr_mode == GSHWDrawConfig::HDRMode::EarlyResolve)
|
||||
if (config.colclip_mode == GSHWDrawConfig::ColClipMode::EarlyResolve)
|
||||
{
|
||||
GL_PUSH("Blit HDR back to RT");
|
||||
GL_PUSH("Blit ColorClip back to RT");
|
||||
|
||||
EndRenderPass();
|
||||
hdr_rt->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
|
||||
colclip_rt->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
|
||||
|
||||
draw_rt = static_cast<GSTextureVK*>(config.rt);
|
||||
OMSetRenderTargets(draw_rt, draw_ds, GSVector4i::loadh(rtsize), static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
|
||||
@@ -5681,22 +5676,22 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
draw_rt->GetRect());
|
||||
}
|
||||
|
||||
const GSVector4 drawareaf = GSVector4(config.hdr_update_area);
|
||||
const GSVector4 drawareaf = GSVector4(config.colclip_update_area);
|
||||
const GSVector4 sRect(drawareaf / GSVector4(rtsize).xyxy());
|
||||
SetPipeline(m_hdr_finish_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
|
||||
SetUtilityTexture(hdr_rt, m_point_sampler);
|
||||
SetPipeline(m_colclip_finish_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
|
||||
SetUtilityTexture(colclip_rt, m_point_sampler);
|
||||
DrawStretchRect(sRect, drawareaf, rtsize);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
|
||||
Recycle(hdr_rt);
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
Recycle(colclip_rt);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
|
||||
hdr_rt = nullptr;
|
||||
colclip_rt = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
pipe.ps.hdr = 1;
|
||||
draw_rt = hdr_rt;
|
||||
pipe.ps.colclip_hw = 1;
|
||||
draw_rt = colclip_rt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5726,7 +5721,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
if (config.require_one_barrier && !m_features.texture_barrier)
|
||||
{
|
||||
// requires a copy of the RT
|
||||
draw_rt_clone = static_cast<GSTextureVK*>(CreateTexture(rtsize.x, rtsize.y, 1, hdr_rt ? GSTexture::Format::HDRColor : GSTexture::Format::Color, true));
|
||||
draw_rt_clone = static_cast<GSTextureVK*>(CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true));
|
||||
if (draw_rt_clone)
|
||||
{
|
||||
EndRenderPass();
|
||||
@@ -5739,17 +5734,17 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
}
|
||||
|
||||
// Switch to hdr target for colclip rendering
|
||||
if (pipe.ps.hdr)
|
||||
// Switch to colclip target for colclip hw rendering
|
||||
if (pipe.ps.colclip_hw)
|
||||
{
|
||||
if (!hdr_rt)
|
||||
if (!colclip_rt)
|
||||
{
|
||||
config.hdr_update_area = config.drawarea;
|
||||
config.colclip_update_area = config.drawarea;
|
||||
EndRenderPass();
|
||||
hdr_rt = static_cast<GSTextureVK*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::HDRColor, false));
|
||||
if (!hdr_rt)
|
||||
colclip_rt = static_cast<GSTextureVK*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false));
|
||||
if (!colclip_rt)
|
||||
{
|
||||
Console.WriteLn("Failed to allocate HDR render target, aborting draw.");
|
||||
Console.WriteLn("Failed to allocate ColorClip render target, aborting draw.");
|
||||
|
||||
if (date_image)
|
||||
Recycle(date_image);
|
||||
@@ -5757,13 +5752,13 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
GL_POP();
|
||||
return;
|
||||
}
|
||||
g_gs_device->SetHDRTexture(static_cast<GSTexture*>(hdr_rt));
|
||||
g_gs_device->SetColorClipTexture(static_cast<GSTexture*>(colclip_rt));
|
||||
|
||||
// propagate clear value through if the hdr render is the first
|
||||
// propagate clear value through if the colclip render is the first
|
||||
if (draw_rt->GetState() == GSTexture::State::Cleared)
|
||||
{
|
||||
hdr_rt->SetState(GSTexture::State::Cleared);
|
||||
hdr_rt->SetClearColor(draw_rt->GetClearColor());
|
||||
colclip_rt->SetState(GSTexture::State::Cleared);
|
||||
colclip_rt->SetClearColor(draw_rt->GetClearColor());
|
||||
|
||||
// If depth is cleared, we need to commit it, because we're only going to draw to the active part of the FB.
|
||||
if (draw_ds && draw_ds->GetState() == GSTexture::State::Cleared && !config.drawarea.eq(GSVector4i::loadh(rtsize)))
|
||||
@@ -5771,7 +5766,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
else if (draw_rt->GetState() == GSTexture::State::Dirty)
|
||||
{
|
||||
GL_PUSH_("HDR Render Target Setup");
|
||||
GL_PUSH_("ColorClip Render Target Setup");
|
||||
draw_rt->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
|
||||
}
|
||||
|
||||
@@ -5779,7 +5774,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
if (config.require_one_barrier && !m_features.texture_barrier)
|
||||
PSSetShaderResource(2, draw_rt, true);
|
||||
}
|
||||
draw_rt = hdr_rt;
|
||||
draw_rt = colclip_rt;
|
||||
}
|
||||
|
||||
// clear texture binding when it's bound to RT or DS.
|
||||
@@ -5790,15 +5785,15 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
|
||||
// render pass restart optimizations
|
||||
if (hdr_rt && (config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly))
|
||||
if (colclip_rt && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly))
|
||||
{
|
||||
// HDR requires blitting.
|
||||
// colclip hw requires blitting.
|
||||
EndRenderPass();
|
||||
}
|
||||
else if (InRenderPass() && (m_current_render_target == draw_rt || m_current_depth_target == draw_ds))
|
||||
{
|
||||
// avoid restarting the render pass just to switch from rt+depth to rt and vice versa
|
||||
// keep the depth even if doing HDR draws, because the next draw will probably re-enable depth
|
||||
// keep the depth even if doing colclip hw draws, because the next draw will probably re-enable depth
|
||||
if (!draw_rt && m_current_render_target && config.tex != m_current_render_target &&
|
||||
m_current_render_target->GetSize() == draw_ds->GetSize())
|
||||
{
|
||||
@@ -5817,15 +5812,15 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
}
|
||||
|
||||
// We don't need the very first barrier if this is the first draw after switching to feedback loop,
|
||||
// because the layout change in itself enforces the execution dependency. HDR needs a barrier between
|
||||
// setup and the first draw to read it. TODO: Make HDR use subpasses instead.
|
||||
// because the layout change in itself enforces the execution dependency. colclip hw needs a barrier between
|
||||
// setup and the first draw to read it. TODO: Make colclip hw use subpasses instead.
|
||||
|
||||
// However, it turns out *not* doing this causes GPU resets on RDNA3, specifically Windows drivers.
|
||||
// Despite the layout changing enforcing the execution dependency between previous draws and the first
|
||||
// input attachment read, it still wants the region/fragment-local barrier...
|
||||
|
||||
const bool skip_first_barrier =
|
||||
(draw_rt && draw_rt->GetLayout() != GSTextureVK::Layout::FeedbackLoop && !pipe.ps.hdr && !IsDeviceAMD());
|
||||
(draw_rt && draw_rt->GetLayout() != GSTextureVK::Layout::FeedbackLoop && !pipe.ps.colclip_hw && !IsDeviceAMD());
|
||||
|
||||
OMSetRenderTargets(draw_rt, draw_ds, config.scissor, static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
|
||||
if (pipe.IsRTFeedbackLoop())
|
||||
@@ -5843,14 +5838,14 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
{
|
||||
const VkAttachmentLoadOp rt_op = GetLoadOpForTexture(draw_rt);
|
||||
const VkAttachmentLoadOp ds_op = GetLoadOpForTexture(draw_ds);
|
||||
const VkRenderPass rp = GetTFXRenderPass(pipe.rt, pipe.ds, pipe.ps.hdr,
|
||||
const VkRenderPass rp = GetTFXRenderPass(pipe.rt, pipe.ds, pipe.ps.colclip_hw,
|
||||
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil, pipe.IsRTFeedbackLoop(),
|
||||
pipe.IsTestingAndSamplingDepth(), rt_op, ds_op);
|
||||
const bool is_clearing_rt = (rt_op == VK_ATTACHMENT_LOAD_OP_CLEAR || ds_op == VK_ATTACHMENT_LOAD_OP_CLEAR);
|
||||
|
||||
// Only draw to the active area of the HDR target. Except when depth is cleared, we need to use the full
|
||||
// Only draw to the active area of the colclip hw target. Except when depth is cleared, we need to use the full
|
||||
// buffer size, otherwise it'll only clear the draw part of the depth buffer.
|
||||
const GSVector4i render_area = (pipe.ps.hdr && (config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve) && ds_op != VK_ATTACHMENT_LOAD_OP_CLEAR) ? config.drawarea :
|
||||
const GSVector4i render_area = (pipe.ps.colclip_hw && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve) && ds_op != VK_ATTACHMENT_LOAD_OP_CLEAR) ? config.drawarea :
|
||||
GSVector4i::loadh(rtsize);
|
||||
|
||||
if (is_clearing_rt)
|
||||
@@ -5861,9 +5856,9 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
if (draw_rt)
|
||||
{
|
||||
GSVector4 clear_color = draw_rt->GetUNormClearColor();
|
||||
if (pipe.ps.hdr)
|
||||
if (pipe.ps.colclip_hw)
|
||||
{
|
||||
// Denormalize clear color for HDR.
|
||||
// Denormalize clear color for hw colclip.
|
||||
clear_color *= GSVector4::cxpr(255.0f / 65535.0f, 255.0f / 65535.0f, 255.0f / 65535.0f, 1.0f);
|
||||
}
|
||||
GSVector4::store<true>(&cvs[cv_count++].color, clear_color);
|
||||
@@ -5888,14 +5883,14 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
vkCmdClearAttachments(m_current_command_buffer, 1, &ca, 1, &rc);
|
||||
}
|
||||
|
||||
// rt -> hdr blit if enabled
|
||||
if (hdr_rt && (config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve) && config.rt->GetState() == GSTexture::State::Dirty)
|
||||
// rt -> colclip hw blit if enabled
|
||||
if (colclip_rt && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve) && config.rt->GetState() == GSTexture::State::Dirty)
|
||||
{
|
||||
OMSetRenderTargets(draw_rt, draw_ds, GSVector4i::loadh(rtsize), static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
|
||||
SetUtilityTexture(static_cast<GSTextureVK*>(config.rt), m_point_sampler);
|
||||
SetPipeline(m_hdr_setup_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
|
||||
SetPipeline(m_colclip_setup_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
|
||||
|
||||
const GSVector4 drawareaf = GSVector4((config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 drawareaf = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
|
||||
const GSVector4 sRect(drawareaf / GSVector4(rtsize).xyxy());
|
||||
DrawStretchRect(sRect, drawareaf, rtsize);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
@@ -5904,8 +5899,8 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
OMSetRenderTargets(draw_rt, draw_ds, config.scissor, static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
|
||||
}
|
||||
|
||||
// VB/IB upload, if we did DATE setup and it's not HDR this has already been done
|
||||
if (!date_image || hdr_rt)
|
||||
// VB/IB upload, if we did DATE setup and it's not colclip hw this has already been done
|
||||
if (!date_image || colclip_rt)
|
||||
UploadHWDrawVerticesAndIndices(config);
|
||||
|
||||
// now we can do the actual draw
|
||||
@@ -5955,21 +5950,21 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
if (date_image)
|
||||
Recycle(date_image);
|
||||
|
||||
// now blit the hdr texture back to the original target
|
||||
if (hdr_rt)
|
||||
// now blit the colclip texture back to the original target
|
||||
if (colclip_rt)
|
||||
{
|
||||
config.hdr_update_area = config.hdr_update_area.runion(config.drawarea);
|
||||
config.colclip_update_area = config.colclip_update_area.runion(config.drawarea);
|
||||
|
||||
if ((config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly || config.hdr_mode == GSHWDrawConfig::HDRMode::ConvertAndResolve))
|
||||
if ((config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve))
|
||||
{
|
||||
GL_PUSH("Blit HDR back to RT");
|
||||
GL_PUSH("Blit ColorClip back to RT");
|
||||
|
||||
EndRenderPass();
|
||||
|
||||
hdr_rt->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
|
||||
colclip_rt->TransitionToLayout(GSTextureVK::Layout::ShaderReadOnly);
|
||||
|
||||
draw_rt = static_cast<GSTextureVK*>(config.rt);
|
||||
OMSetRenderTargets(draw_rt, draw_ds, (config.hdr_mode == GSHWDrawConfig::HDRMode::ResolveOnly) ? GSVector4i::loadh(rtsize) : config.scissor, static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
|
||||
OMSetRenderTargets(draw_rt, draw_ds, (config.colclip_mode == GSHWDrawConfig::ColClipMode::ResolveOnly) ? GSVector4i::loadh(rtsize) : config.scissor, static_cast<FeedbackLoopFlag>(pipe.feedback_loop_flags));
|
||||
|
||||
// if this target was cleared and never drawn to, perform the clear as part of the resolve here.
|
||||
if (draw_rt->GetState() == GSTexture::State::Cleared)
|
||||
@@ -5994,19 +5989,19 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
draw_rt->GetRect());
|
||||
}
|
||||
|
||||
const GSVector4 drawareaf = GSVector4(config.hdr_update_area);
|
||||
const GSVector4 drawareaf = GSVector4(config.colclip_update_area);
|
||||
const GSVector4 sRect(drawareaf / GSVector4(rtsize).xyxy());
|
||||
SetPipeline(m_hdr_finish_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
|
||||
SetUtilityTexture(hdr_rt, m_point_sampler);
|
||||
SetPipeline(m_colclip_finish_pipelines[pipe.ds][pipe.IsRTFeedbackLoop()]);
|
||||
SetUtilityTexture(colclip_rt, m_point_sampler);
|
||||
DrawStretchRect(sRect, drawareaf, rtsize);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
|
||||
Recycle(hdr_rt);
|
||||
g_gs_device->SetHDRTexture(nullptr);
|
||||
Recycle(colclip_rt);
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
config.hdr_mode = GSHWDrawConfig::HDRMode::NoModify;
|
||||
config.colclip_mode = GSHWDrawConfig::ColClipMode::NoModify;
|
||||
}
|
||||
|
||||
void GSDeviceVK::UpdateHWPipelineSelector(GSHWDrawConfig& config, PipelineSelector& pipe)
|
||||
|
||||
@@ -394,8 +394,8 @@ private:
|
||||
std::array<VkPipeline, 32> m_color_copy{};
|
||||
std::array<VkPipeline, 2> m_merge{};
|
||||
std::array<VkPipeline, NUM_INTERLACE_SHADERS> m_interlace{};
|
||||
VkPipeline m_hdr_setup_pipelines[2][2] = {}; // [depth][feedback_loop]
|
||||
VkPipeline m_hdr_finish_pipelines[2][2] = {}; // [depth][feedback_loop]
|
||||
VkPipeline m_colclip_setup_pipelines[2][2] = {}; // [depth][feedback_loop]
|
||||
VkPipeline m_colclip_finish_pipelines[2][2] = {}; // [depth][feedback_loop]
|
||||
VkRenderPass m_date_image_setup_render_passes[2][2] = {}; // [depth][clear]
|
||||
VkPipeline m_date_image_setup_pipelines[2][4] = {}; // [depth][datm]
|
||||
VkPipeline m_fxaa_pipeline = {};
|
||||
@@ -415,7 +415,7 @@ private:
|
||||
VkRenderPass m_date_setup_render_pass = VK_NULL_HANDLE;
|
||||
VkRenderPass m_swap_chain_render_pass = VK_NULL_HANDLE;
|
||||
|
||||
VkRenderPass m_tfx_render_pass[2][2][2][3][2][2][3][3] = {}; // [rt][ds][hdr][date][fbl][dsp][rt_op][ds_op]
|
||||
VkRenderPass m_tfx_render_pass[2][2][2][3][2][2][3][3] = {}; // [rt][ds][colclip][date][fbl][dsp][rt_op][ds_op]
|
||||
|
||||
VkDescriptorSetLayout m_cas_ds_layout = VK_NULL_HANDLE;
|
||||
VkPipelineLayout m_cas_pipeline_layout = VK_NULL_HANDLE;
|
||||
@@ -486,10 +486,10 @@ public:
|
||||
/// Returns true if Vulkan is suitable as a default for the devices in the system.
|
||||
static bool IsSuitableDefaultRenderer();
|
||||
|
||||
__fi VkRenderPass GetTFXRenderPass(bool rt, bool ds, bool hdr, bool stencil, bool fbl, bool dsp,
|
||||
__fi VkRenderPass GetTFXRenderPass(bool rt, bool ds, bool colclip, bool stencil, bool fbl, bool dsp,
|
||||
VkAttachmentLoadOp rt_op, VkAttachmentLoadOp ds_op) const
|
||||
{
|
||||
return m_tfx_render_pass[rt][ds][hdr][stencil][fbl][dsp][rt_op][ds_op];
|
||||
return m_tfx_render_pass[rt][ds][colclip][stencil][fbl][dsp][rt_op][ds_op];
|
||||
}
|
||||
__fi VkSampler GetPointSampler() const { return m_point_sampler; }
|
||||
__fi VkSampler GetLinearSampler() const { return m_linear_sampler; }
|
||||
|
||||
@@ -1054,7 +1054,7 @@ bool FullscreenUI::LoadResources()
|
||||
for (u32 i = static_cast<u32>(GameDatabaseSchema::Compatibility::Nothing);
|
||||
i <= static_cast<u32>(GameDatabaseSchema::Compatibility::Perfect); i++)
|
||||
{
|
||||
s_game_compatibility_textures[i - 1] = LoadTexture(fmt::format("icons/star-{}.png", i - 1).c_str());
|
||||
s_game_compatibility_textures[i - 1] = LoadTexture(fmt::format("fullscreenui/star-{}.png", i - 1).c_str());
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -6499,7 +6499,7 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
|
||||
|
||||
// region
|
||||
{
|
||||
std::string flag_texture(fmt::format("icons/flags/{}.png", GameList::RegionToString(selected_entry->region)));
|
||||
std::string flag_texture(fmt::format("fullscreenui/flags/{}.png", GameList::RegionToString(selected_entry->region)));
|
||||
ImGui::TextUnformatted(FSUI_CSTR("Region: "));
|
||||
ImGui::SameLine();
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(GetCachedTextureAsync(flag_texture.c_str())->GetNativeHandle()), LayoutScale(23.0f, 16.0f));
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace Patch
|
||||
struct PatchGroup
|
||||
{
|
||||
std::string name;
|
||||
std::optional<AspectRatioType> override_aspect_ratio;
|
||||
std::optional<float> override_aspect_ratio;
|
||||
std::optional<GSInterlaceMode> override_interlace_mode;
|
||||
std::vector<PatchCommand> patches;
|
||||
std::vector<DynamicPatch> dpatches;
|
||||
@@ -186,7 +186,7 @@ namespace Patch
|
||||
static EnablePatchList s_just_enabled_cheats;
|
||||
static EnablePatchList s_just_enabled_patches;
|
||||
static u32 s_patches_crc;
|
||||
static std::optional<AspectRatioType> s_override_aspect_ratio;
|
||||
static std::optional<float> s_override_aspect_ratio;
|
||||
static std::optional<GSInterlaceMode> s_override_interlace_mode;
|
||||
|
||||
static const PatchTextTable s_patch_commands[] = {
|
||||
@@ -797,17 +797,13 @@ void Patch::UpdateActivePatches(bool reload_enabled_list, bool verbose, bool ver
|
||||
|
||||
void Patch::ApplyPatchSettingOverrides()
|
||||
{
|
||||
// Switch to 16:9 if widescreen patches are enabled, and AR is auto.
|
||||
// Switch to 16:9 (or any custom aspect ratio) if widescreen patches are enabled, and AR is auto.
|
||||
if (s_override_aspect_ratio.has_value() && EmuConfig.GS.AspectRatio == AspectRatioType::RAuto4_3_3_2)
|
||||
{
|
||||
// Don't change when reloading settings in the middle of a FMV with switch.
|
||||
if (EmuConfig.CurrentAspectRatio == EmuConfig.GS.AspectRatio)
|
||||
EmuConfig.CurrentAspectRatio = s_override_aspect_ratio.value();
|
||||
EmuConfig.CurrentCustomAspectRatio = s_override_aspect_ratio.value();
|
||||
|
||||
Console.WriteLn(Color_Gray,
|
||||
fmt::format("Patch: Setting aspect ratio to {} by patch request.",
|
||||
Pcsx2Config::GSOptions::AspectRatioNames[static_cast<int>(s_override_aspect_ratio.value())]));
|
||||
EmuConfig.GS.AspectRatio = s_override_aspect_ratio.value();
|
||||
fmt::format("Patch: Setting aspect ratio to {} by patch request.", s_override_aspect_ratio.value()));
|
||||
}
|
||||
|
||||
// Disable interlacing in GS if active.
|
||||
@@ -821,9 +817,13 @@ void Patch::ApplyPatchSettingOverrides()
|
||||
|
||||
bool Patch::ReloadPatchAffectingOptions()
|
||||
{
|
||||
// Restore the aspect ratio + interlacing setting the user had set before reloading the patch,
|
||||
// as the custom patch settings only apply if the "Auto" settings are selected.
|
||||
|
||||
const AspectRatioType current_ar = EmuConfig.GS.AspectRatio;
|
||||
const GSInterlaceMode current_interlace = EmuConfig.GS.InterlaceMode;
|
||||
|
||||
const float custom_aspect_ratio = EmuConfig.CurrentCustomAspectRatio;
|
||||
|
||||
// This is pretty gross, but we're not using a config layer, so...
|
||||
AspectRatioType new_ar = Pcsx2Config::GSOptions::DEFAULT_ASPECT_RATIO;
|
||||
const std::string ar_value = Host::GetStringSettingValue("EmuCore/GS", "AspectRatio",
|
||||
@@ -836,15 +836,14 @@ bool Patch::ReloadPatchAffectingOptions()
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (EmuConfig.CurrentAspectRatio == EmuConfig.GS.AspectRatio)
|
||||
EmuConfig.CurrentAspectRatio = new_ar;
|
||||
EmuConfig.GS.AspectRatio = new_ar;
|
||||
EmuConfig.GS.InterlaceMode = static_cast<GSInterlaceMode>(Host::GetIntSettingValue(
|
||||
"EmuCore/GS", "deinterlace_mode", static_cast<int>(Pcsx2Config::GSOptions::DEFAULT_INTERLACE_MODE)));
|
||||
|
||||
ApplyPatchSettingOverrides();
|
||||
|
||||
return (current_ar != EmuConfig.GS.AspectRatio || current_interlace != EmuConfig.GS.InterlaceMode);
|
||||
// Return true if any config setting changed
|
||||
return current_ar != EmuConfig.GS.AspectRatio || custom_aspect_ratio != EmuConfig.CurrentCustomAspectRatio || current_interlace != EmuConfig.GS.InterlaceMode;
|
||||
}
|
||||
|
||||
void Patch::UnloadPatches()
|
||||
@@ -941,13 +940,22 @@ void Patch::PatchFunc::patch(PatchGroup* group, const std::string_view cmd, cons
|
||||
|
||||
void Patch::PatchFunc::gsaspectratio(PatchGroup* group, const std::string_view cmd, const std::string_view param)
|
||||
{
|
||||
for (u32 i = 0; i < static_cast<u32>(AspectRatioType::MaxCount); i++)
|
||||
std::string str(param);
|
||||
std::istringstream ss(str);
|
||||
uint dividend, divisor;
|
||||
char delimiter;
|
||||
float aspect_ratio = 0.f;
|
||||
|
||||
ss >> dividend >> delimiter >> divisor;
|
||||
if (!ss.fail() && delimiter == ':' && divisor != 0)
|
||||
{
|
||||
if (param == Pcsx2Config::GSOptions::AspectRatioNames[i])
|
||||
{
|
||||
group->override_aspect_ratio = static_cast<AspectRatioType>(i);
|
||||
return;
|
||||
}
|
||||
aspect_ratio = static_cast<float>(dividend) / static_cast<float>(divisor);
|
||||
}
|
||||
|
||||
if (aspect_ratio > 0.f)
|
||||
{
|
||||
group->override_aspect_ratio = aspect_ratio;
|
||||
return;
|
||||
}
|
||||
|
||||
Console.Error(fmt::format("Patch error: {} is an unknown aspect ratio.", param));
|
||||
|
||||
@@ -636,7 +636,7 @@ void Pcsx2Config::CpuOptions::LoadSave(SettingsWrapper& wrap)
|
||||
Recompiler.LoadSave(wrap);
|
||||
}
|
||||
|
||||
const char* Pcsx2Config::GSOptions::AspectRatioNames[] = {
|
||||
const char* Pcsx2Config::GSOptions::AspectRatioNames[(size_t)AspectRatioType::MaxCount + 1] = {
|
||||
"Stretch",
|
||||
"Auto 4:3/3:2",
|
||||
"4:3",
|
||||
@@ -644,7 +644,7 @@ const char* Pcsx2Config::GSOptions::AspectRatioNames[] = {
|
||||
"10:7",
|
||||
nullptr};
|
||||
|
||||
const char* Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames[] = {
|
||||
const char* Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames[(size_t)FMVAspectRatioSwitchType::MaxCount + 1] = {
|
||||
"Off",
|
||||
"Auto 4:3/3:2",
|
||||
"4:3",
|
||||
@@ -1983,7 +1983,12 @@ void Pcsx2Config::LoadSaveCore(SettingsWrapper& wrap)
|
||||
|
||||
if (wrap.IsLoading())
|
||||
{
|
||||
// Patches will get re-applied after loading the state so this doesn't matter too much
|
||||
CurrentAspectRatio = GS.AspectRatio;
|
||||
if (CurrentAspectRatio == AspectRatioType::RAuto4_3_3_2)
|
||||
{
|
||||
CurrentCustomAspectRatio = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2035,6 +2040,7 @@ void Pcsx2Config::CopyRuntimeConfig(Pcsx2Config& cfg)
|
||||
CurrentIRX = std::move(cfg.CurrentIRX);
|
||||
CurrentGameArgs = std::move(cfg.CurrentGameArgs);
|
||||
CurrentAspectRatio = cfg.CurrentAspectRatio;
|
||||
CurrentCustomAspectRatio = cfg.CurrentCustomAspectRatio;
|
||||
IsPortableMode = cfg.IsPortableMode;
|
||||
|
||||
for (u32 i = 0; i < sizeof(Mcd) / sizeof(Mcd[0]); i++)
|
||||
|
||||
@@ -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 = 62;
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 64;
|
||||
|
||||
@@ -876,7 +876,9 @@ void VMManager::RequestDisplaySize(float scale /*= 0.0f*/)
|
||||
switch (GSConfig.AspectRatio)
|
||||
{
|
||||
case AspectRatioType::RAuto4_3_3_2:
|
||||
if (GSgetDisplayMode() == GSVideoMode::SDTV_480P)
|
||||
if (EmuConfig.CurrentCustomAspectRatio > 0.f)
|
||||
x_scale = EmuConfig.CurrentCustomAspectRatio / (static_cast<float>(iwidth) / static_cast<float>(iheight));
|
||||
else if (GSgetDisplayMode() == GSVideoMode::SDTV_480P)
|
||||
x_scale = (3.0f / 2.0f) / (static_cast<float>(iwidth) / static_cast<float>(iheight));
|
||||
else
|
||||
x_scale = (4.0f / 3.0f) / (static_cast<float>(iwidth) / static_cast<float>(iheight));
|
||||
@@ -2504,9 +2506,13 @@ void VMManager::LogCPUCapabilities()
|
||||
|
||||
Console.WriteLnFmt(
|
||||
" Operating System = {}\n"
|
||||
" Physical RAM = {} MB",
|
||||
" Available RAM = {} MB ({:.2f} GB)\n"
|
||||
" Physical RAM = {} MB ({:.2f} GB)\n",
|
||||
GetOSVersionString(),
|
||||
GetPhysicalMemory() / _1mb);
|
||||
GetAvailablePhysicalMemory() / _1mb,
|
||||
static_cast<double>(GetAvailablePhysicalMemory()) / static_cast<double>(_1gb),
|
||||
GetPhysicalMemory() / _1mb,
|
||||
static_cast<double>(GetPhysicalMemory()) / static_cast<double>(_1gb));
|
||||
|
||||
Console.WriteLnFmt(" Processor = {}", cpuinfo_get_package(0)->name);
|
||||
Console.WriteLnFmt(" Core Count = {} cores", cpuinfo_get_cores_count());
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import xml.etree.ElementTree as ET
|
||||
import re
|
||||
|
||||