Compare commits

...
220 Commits
Author SHA1 Message Date
refractionpcsx2 054cb9e9fa GS/HW: Correctly remove offset when detecting shuffle coords 2023-08-12 19:39:25 +01:00
refractionpcsx2 1f77e7d90a GS/CRC: Fix the sizing on Sonic Unleashed copy CRC 2023-08-12 19:34:06 +01:00
lightningterror 7ed33832b8 GS/HW: Isolate early returns for blending.
Optimization.
2023-08-12 18:14:37 +02:00
lightningterror d19e9cc662 GS: Bump shader cache version. 2023-08-12 18:14:37 +02:00
lightningterror 846c9cec6a GS/HW: Adjust how we handle RT alpha in blending.
When both rt min and max are equal then we know what Ad value is,
if so use Af bit instead and set AFIX value from rt alpha value that we know.

On OpenGL when BLEND C == 1 but reading the rt is disabled, set the value to 0 instead
of reading an undefined value.
2023-08-12 18:14:37 +02:00
Sanjay Govindandrefractionpcsx2 460e4b8bb3 USB-Turntable: Default multiplier to 1 2023-08-12 14:07:37 +01:00
Stenzek 2e6bd23f22 Qt: Fix arrow key handling on macOS 2023-08-12 16:17:47 +10:00
refractionpcsx2 7763948fe4 GS/HW: Restrict double buffer detection to widths greater than 256 2023-08-12 01:54:31 +01:00
refractionpcsx2 2a0f001902 GIF: Adjust run length of split in intermittent packets 2023-08-12 00:28:28 +01:00
refractionpcsx2 14df69e180 GS/HW: Fix crash where it could process a texture with no RT 2023-08-12 00:28:28 +01:00
refractionpcsx2 28b6389b36 GS/HW: Stop errantly halfing normal height 2023-08-12 00:28:28 +01:00
lightningterror 905c0b8c7a GS: Fix warnings.
GSRendererHW:
Fix Wtautological-constant-out-of-range-compare.

GSSstate:
Fix Wunused-variable.
Fix Wsign-compare.
2023-08-11 21:46:29 +02:00
lightningterror b674cc95ac Qt: Fix Wreorder-ctor warning. 2023-08-11 21:46:29 +02:00
Mrlinkwiiandlightningterror bccb2509b5 GameDB: Fixes for Ghost Recon - Advanced Warfighter & Battlefield 2 2023-08-11 18:16:33 +02:00
refractionpcsx2 cd980c6604 GS/TC: Fix crash in debug message (only affects debug device) 2023-08-11 16:08:38 +01:00
lightningterror ddff4ec083 GameDB: Add full mipmap plus triliear ps2 to The Godfather.
Improves building textures to match sw renderer.
2023-08-11 17:05:21 +02:00
kamfretozandrefractionpcsx2 5bf97be8ef Qt: Even further icon refinement 2023-08-11 15:24:04 +01:00
lightningterrorandrefractionpcsx2 7fadb6ed05 GS/HW: Cleanup texture shuffle shaders. 2023-08-11 15:23:50 +01:00
lightningterrorandrefractionpcsx2 89688d67dd GS: Bump shader cache version. 2023-08-11 15:23:50 +01:00
refractionpcsx2 279007544a GS/HW: Allow double clear when src is lowest bitsize denominator 2023-08-11 14:28:34 +01:00
lightningterrorandrefractionpcsx2 1c0f0e1423 GS: Bump shader cache version. 2023-08-11 13:14:19 +01:00
lightningterrorandrefractionpcsx2 1ab909addc Config/gamedb: Remove screen fix from config entirely.
No longer needed.
2023-08-11 13:14:19 +01:00
lightningterrorandrefractionpcsx2 99dfd15469 ImGui: Remove Half Screen Fix from the ui.
No longer needed.
2023-08-11 13:14:19 +01:00
lightningterrorandrefractionpcsx2 be18ecf74e Qt: Remove Half Screen Fix from the ui.
No longer needed.
2023-08-11 13:14:19 +01:00
lightningterrorandrefractionpcsx2 713bd132dc GS/D3D: Add initial support for complex shuffles. 2023-08-11 13:14:19 +01:00
refractionpcsx2 20f03e237e GameDB: Add Autoflush to Minority Report 2023-08-11 13:14:19 +01:00
refractionpcsx2 7d3c3911ea GS/HW: Update BigMuthaTruckers hack to a GSC 2023-08-11 13:14:19 +01:00
refractionpcsx2 ccfee2be83 GameDB: Add Tex in RT to Godfather + remove skipdraw 2023-08-11 13:14:19 +01:00
refractionpcsx2 1193b0b990 GS/TC: Delete old targets which aren't preserved and don't match size 2023-08-11 13:14:19 +01:00
refractionpcsx2 5a3ba4e563 GS/HW: Add support for complex offset shuffles 2023-08-11 13:14:19 +01:00
refractionpcsx2 e9c342ef74 GS/Autoflush: Account for CLAMP & better handle different formats 2023-08-11 12:35:42 +01:00
refractionpcsx2 8927ffa035 GS: Fix autoflush behaviour when using Z + C formats together 2023-08-11 12:35:42 +01:00
Ty Lamontagneandrefractionpcsx2 fdb0312326 Dis5900: Mask and extend the pmfhl & pmthl LUT
Fixes an OOB access when disassembling an invalid opcode (71756972h)
2023-08-11 00:09:25 +01:00
refractionpcsx2 2f21caa41c GameDB: Add Instant DMA to Jak X Combat Racing 2023-08-10 10:40:43 +01:00
Stenzekandrefractionpcsx2 51a35d40e5 3rdparty: Bump rcheevos to 3af1e2fc5188d6e932ee379942f4049ea877e648 2023-08-10 01:27:20 +01:00
Stenzekandrefractionpcsx2 6ec524adec USB/GunCon2: Fix cursor not starting in center 2023-08-10 01:27:10 +01:00
Stenzekandrefractionpcsx2 7d4a7ec8c7 ImGuiManager: Fix window width/height not being initialized 2023-08-10 01:27:10 +01:00
Silentandrefractionpcsx2 0256c4521d GameList: Support adding custom title and region to files 2023-08-10 01:26:06 +01:00
Silentandrefractionpcsx2 be3ed181c1 SettingsInterface: Fix constness of a few methods 2023-08-10 01:26:06 +01:00
PCSX2 BotandConnor McLaughlin 38cf7884fe Qt: Update Base Translation 2023-08-09 21:37:15 +10:00
JordanTheToasterandConnor McLaughlin 25d426e8b2 GameDB: Various fixes
Fixes for missing recommended blending on MGS 2 Sub and post processing positioning on Project Snowblind.
2023-08-09 21:35:34 +10:00
TellowKrinkleandConnor McLaughlin edff9ae684 GS:MTL: Include full error messages in aborts 2023-08-09 21:34:38 +10:00
TellowKrinkleandConnor McLaughlin a622e3bda6 Mac: Mark crash info as used so it doesn't get DCE'd 2023-08-09 21:34:38 +10:00
MrlinkwiiandConnor McLaughlin 4d54e28e63 GameDB: remove all god hand getSkipCount 2023-08-09 21:34:07 +10:00
MrlinkwiiandConnor McLaughlin c89d023f91 CRC/HW: remove god hand GSC 2023-08-09 21:34:07 +10:00
Stenzek c7cfea1daa GS/Vulkan: Make VK_EXT_provoking_vertex optional again
RenderDoc doesn't support it.
2023-08-09 21:33:45 +10:00
Stenzek beb07365a0 Build: Disable Vulkan on macOS builds
MoltenVK does not support the extensions we now require.
2023-08-09 19:34:23 +10:00
Stenzek 0787c65e51 GS/Vulkan: Mandate well-supported extensions
- VK_EXT_provoking_vertex and provokingVertexLast
 - VK_EXT_line_rasterization and bresenhamLines
 - VK_KHR_shader_draw_parameters

Lack of these would cause rendering issues anyway.
2023-08-09 19:34:23 +10:00
Stenzek d48dea7273 GS/Vulkan: Don't track vertex buffer state
It never changes.
2023-08-09 19:34:23 +10:00
Stenzek 2432cc6ed2 GS/Vulkan: clang-format 2023-08-09 19:34:23 +10:00
Stenzek cf523d4215 GS/Vulkan: Use push descriptors instead of per-frame allocations 2023-08-09 19:34:23 +10:00
lightningterror 906d87c4b8 GS/HW: Fix nfs undercover crashing on dev/debug builds.
We were reading the wrong value.
2023-08-09 10:23:47 +02:00
Connor McLaughlinandTellowKrinkle 9c4a92c015 GS/Metal: Fix crash when Z write is on second pass 2023-08-08 18:27:54 -05:00
lightningterror 0c056ba691 USB: Fix function parameter should be passed by const reference warnings.
Codacy.
2023-08-08 21:27:36 +02:00
lightningterror 424158b28d DEV9: Fix function parameter should be passed by const reference warnings.
Codacy.
2023-08-08 21:27:36 +02:00
JordanTheToasterandrefractionpcsx2 57f118a5b5 GameDB: Various fixes
Fixes line across the screen and offset blur in Samurai Westerner and corrects region of Chinese entry's to properly use the flag included in the icons folder.
2023-08-08 08:58:55 +01:00
refractionpcsx2 65e75f3da2 GS/TC: Ignore linear part of rect when translating 2023-08-08 08:57:09 +01:00
refractionpcsx2 41174cde45 GS: Elide flushes on GS transfer if not required 2023-08-08 08:57:09 +01:00
refractionpcsx2 cb7d01fb36 GameDB: Improve Myst 3 patch 2023-08-08 08:56:52 +01:00
refractionpcsx2 3e78f8e87d IPU: Improve DMA/IPU call locations to reduce looping 2023-08-08 08:56:52 +01:00
BacklogOdysseyandConnor McLaughlin f2c032ba07 RetroAchievements/Qt: Add configurable achievement notification duration 2023-08-08 13:17:28 +10:00
refractionpcsx2 2ef1589e76 GameDB: Remove NFS HP2 GS fix which did nothing. 2023-08-07 23:03:11 +01:00
refractionpcsx2 5c394557e3 GS/HW: Handle split shuffles with a width of 1 2023-08-07 23:03:11 +01:00
PCSX2 Botandrefractionpcsx2 5c4a5b0a61 PAD: Update to latest controller database. 2023-08-07 17:10:55 +01:00
Silentandrefractionpcsx2 be22b7349d GameList: Add an option to exclude entire directories 2023-08-07 16:50:15 +01:00
refractionpcsx2 023e4774a1 UI: Only allow relative memcard files in memcard interface 2023-08-07 16:49:45 +01:00
Stenzekandrefractionpcsx2 56b706f25e Achievements: Tag a few missing strings for translation 2023-08-07 16:49:34 +01:00
Stenzekandrefractionpcsx2 9d07ee43eb VMManager: Fix achievements HC mode not applying on reset 2023-08-07 16:49:34 +01:00
Connor McLaughlinandTellowKrinkle 147a6c81a1 GS/Metal: Don't end up with two encoders on readback 2023-08-06 16:38:59 -05:00
RedPanda4552andrefractionpcsx2 5972f4947d InputManager: Fix incorrect compare for multitap enabled 2023-08-06 00:45:58 +01:00
refractionpcsx2 9c99a624d7 GS/HW: Optimise usage of 24bit alphas 2023-08-05 22:01:59 +01:00
refractionpcsx2 d812d83dda GS/HW: Limit alpha range on 16bit targets 2023-08-05 22:01:59 +01:00
refractionpcsx2 f81c5c2455 GS/HW: Guess alpha values when using 16bit RT as TEX = RT 2023-08-05 22:01:59 +01:00
refractionpcsx2 dc8c5e6209 GS/HW: Use texture alpha for 16bit textures in CalcAlphaMinMax 2023-08-05 22:01:59 +01:00
Stenzekandrefractionpcsx2 14833582b2 GS/HW: Re-optimize alpha test after updating direct alpha range 2023-08-05 22:01:59 +01:00
Mrlinkwiiandrefractionpcsx2 cca813fd1d GameDB: fixes for Panzer Elite Action & Totally Spies 2023-08-04 16:30:19 +01:00
lightningterror d4102e75c5 Readme: Update requirements.
Minimum: Lower STR requirements to 1500 from 1800.
Recommended: Lower STR requirements to 2000 from 2500.
Add Heavy category with STR requirements 2600.
2023-08-04 16:32:16 +02:00
Tyler Wildingandrefractionpcsx2 76a04efc5c ci: properly fetch release info to make announcement 2023-08-03 21:41:46 +01:00
JordanTheToasterandrefractionpcsx2 a34e139843 GameDB: Remove CCLUT from Raw Danger
Doesn't appear to do anything currently and causes the game to do almost 100 readbacks totally killing performance in hardware mode.
2023-08-03 11:59:09 +01:00
Tyler Wildingandrefractionpcsx2 a1727a2ac7 ci: announce release after it's published
It's no longer working because workflows will not implicitly trigger from another workflow when initiated by the default token.

You must explicitly call them via a `workflow_dispatch` or use a distinct PAT.

The announce workflow isn't really used anywhere else so simplifying and consolidating the steps feels appropriate.
2023-08-03 01:51:58 +01:00
Stenzekandrefractionpcsx2 7ac224adf3 MemoryCardFolder: Initialize hostFilePath 2023-08-02 16:06:37 +01:00
RedDevilusandrefractionpcsx2 d5e3d02a98 GameDB: Missing Korean entries + maintenance
Based on:
https://github.com/PCSX2/pcsx2/pull/9671#issuecomment-1657337888

I do see a lot of the missing entries actually come from the PCSX2 wiki, and the csv was mostly duplicates but I checked and cleaned it up while looking at other things to potentially fix.

GGeneration is faulty naming though, G Genereration needs a space.

There are also 2 reasons why we don't fully follow redump:
For starters Windows uses specific characters in their code and following that would make it impossible to make covers for them and some other things
The other thing is when The blablabla  turns into blablabla, The for filtering purposes.

In future we should probably have a display language for specific languages, ex. Korean entries show Japanese, English or others
2023-08-02 16:02:53 +01:00
Connor McLaughlin 68ad3e8db4 FileSystem: Partial revert of c82f800
Mixing stdio and raw FD access is a bad thing, filelength() isn't going to return correct results when extending a file has been buffered.
2023-08-02 18:45:52 +10:00
Stenzek 31029b2fe4 InputManager: Don't connect bindings for disabled multitap ports 2023-08-02 12:44:31 +10:00
Stenzek 8b0c101768 Pad: Move multitap into its own config section
And more config cleanups.
2023-08-02 12:44:31 +10:00
JordanTheToasterandrefractionpcsx2 50b66f526b GameDB: Various fixes
Fixes menu corruption and likely other issues the game may have had similar to all future entry's.
2023-08-02 01:07:45 +01:00
RedDevilusandrefractionpcsx2 f3fcf010fb GameDB: Remove accidental addition Growlanser 5+6
Texture Inside RT was fixed in https://github.com/PCSX2/pcsx2/pull/9187
2023-08-01 17:31:47 +01:00
PCSX2 Botandrefractionpcsx2 4da53bd00d Qt: Update Base Translation 2023-08-01 17:18:23 +01:00
Mrlinkwiiandrefractionpcsx2 c6cef45f0e Inputmanager: fix possible build issue 2023-08-01 17:07:51 +01:00
Mrlinkwiiandrefractionpcsx2 e36cd7fe5c Build: remove -32 notation from core filenames 2023-08-01 16:09:09 +01:00
Stenzek 0c24f2db7b GS/HW: Don't discard target when SCANMSK is set 2023-08-01 13:31:42 +10:00
Stenzek 8866faa8d5 GS: Remove GSCrc
Finally!
2023-08-01 12:42:06 +10:00
Stenzek b2dc31ba80 GS/HW: Move Tekken 5 CRC hack to the GSC 2023-08-01 12:42:06 +10:00
pgertandrefractionpcsx2 061ea30199 GameDB: entry correction 2023-07-31 22:36:56 +01:00
refractionpcsx2 0e9e94d090 UI: Delete rogue quote breaking HTML in Memcard Convert dialog 2023-07-31 16:36:14 +01:00
Stenzek 3321cb37ef GS/HW: Don't invalidate alpha on display target lookup 2023-07-31 21:08:33 +10:00
JordanTheToasterandrefractionpcsx2 d60a818791 GameDB: Go Go Golf Fixes
Fixes for the pretty awful brightness on pretty PS1 looking textures.
2023-07-31 10:59:54 +01:00
PCSX2 BotandConnor McLaughlin 3937a52b4f Qt: Update Base Translation 2023-07-31 19:28:43 +10:00
Stenzek 2c3902b1a1 GS/HW: Fix bilinear-over-self targets getting discarded 2023-07-31 19:24:08 +10:00
RedPanda4552andrefractionpcsx2 f43b5ee76f Pad: Respect non-standard vibration mappings and pure digital button query 2023-07-30 23:48:12 +01:00
refractionpcsx2 bab16a5251 UI: Update glyphs for asian languages. 2023-07-30 19:20:29 +01:00
Mrlinkwiiandrefractionpcsx2 08c734d7fd GameDB: various fixes 2023-07-30 14:23:45 +01:00
Connor McLaughlin 36126a3ad9 GS: Drop alignment from ClearValue 2023-07-30 21:44:44 +10:00
kamfretozandConnor McLaughlin ce505d33bd Qt: Make incompatible savestate message translateable 2023-07-30 20:28:50 +10:00
Stenzek de0d859502 Qt: Fix changing cover file formats 2023-07-30 19:25:51 +10:00
Stenzek ce96d4bcc5 SaveState: Store the current PCSX2 version in the save state 2023-07-30 18:13:25 +10:00
ChromaryuandConnor McLaughlin fb242274d5 GameDB: Fix PoPoLoCrois Naming 2023-07-30 16:18:55 +10:00
Stenzek 938bc7cdd7 GS/HW: Allow fast clears even when expanding
Doesn't make sense not to.
2023-07-30 16:18:04 +10:00
Stenzek 36865f2930 GS/HW: Skip target conversion when alpha doesn't exist 2023-07-30 16:18:04 +10:00
refractionpcsx2 12e79cccf6 GS/HW: Improve detection of reverse texture shuffles 2023-07-30 07:04:39 +01:00
PCSX2 BotandConnor McLaughlin 6180f12ba3 Qt: Update Base Translation 2023-07-30 12:26:53 +10:00
refractionpcsx2 c00b6c6237 GameDB: Sort and append missing entried from Redump 2023-07-30 02:37:18 +01:00
RedPanda4552andrefractionpcsx2 dbdc74fdef Memcard: Remove erroneous auto eject decrement 2023-07-29 19:11:33 +01:00
pgertandrefractionpcsx2 5bb0a07164 GameDB: correct an entry 2023-07-29 18:32:26 +01:00
Stenzek 543f09999f GS/HW: Fix target memory usage underflowing 2023-07-30 01:03:46 +10:00
Connor McLaughlinandGitHub 812f32efdd README: Update DirectX Requirements 2023-07-29 22:32:20 +10:00
Stenzek 784264eba4 GS: Drop alpha gather from FXAA
It's not used by any backends.
2023-07-29 22:28:49 +10:00
Stenzek ff9ca059c7 GS/DX11: Require feature level 11.0
Feature level 11.0 GPUs were first released in 2009, almost 14 years ago
now. Older GPUs have not had drivers released in a long time, and are
known to be buggy.

None of us have hardware this old, so it's impossible for us to support
it.
2023-07-29 22:28:49 +10:00
SilentandConnor McLaughlin d4b0c39485 Achievements: Fix Leaderboard submission UI when multiple leaderboards update at once 2023-07-29 22:23:11 +10:00
Ty Lamontagneandrefractionpcsx2 87c42aeaf4 Debugger: Fix mismatch sign compare & bitwise on different enum warnings 2023-07-28 22:00:08 +01:00
Ty Lamontagneandrefractionpcsx2 5ba6e57c71 CDVD: Fix unused qualifier warning 2023-07-28 22:00:08 +01:00
Ty Lamontagneandrefractionpcsx2 6d2ba5c2d0 Common | TextureDecompress: Fix unused variable warning 2023-07-28 22:00:08 +01:00
Ty Lamontagneandrefractionpcsx2 0d42b81285 Debugger: Fix 'run-to-cursor' context action 2023-07-28 22:00:08 +01:00
Stenzek 9ce2ae613b GS/HW: Update vertex trace in ReplaceVerticesWithSprite() 2023-07-29 02:56:59 +10:00
PCSX2 Botandrefractionpcsx2 13c9e0e666 Qt: Update Base Translation 2023-07-28 16:32:23 +01:00
Stenzekandrefractionpcsx2 784118e9c1 GS/HW: Don't drop fractional colour before modulating
Fixes banding in Xenosaga, Tales of the Abyss, Beyond Good and Evil.
2023-07-28 16:31:35 +01:00
Mrlinkwiiandrefractionpcsx2 df32a32d99 GameDB: add missing serials 2023-07-28 16:29:25 +01:00
JordanTheToasterandrefractionpcsx2 655241aed3 Translations: Add Latvija to the menu
Adds missing Latvija option to the menu of selectable languages.
2023-07-28 16:28:29 +01:00
refractionpcsx2 60a2b246e2 GS: Correct alpha test for RGB Only and non-32bit colours 2023-07-28 15:57:28 +01:00
Tyler WildingandGitHub ebd60d93f3 translations: Syncing Crowdin translations (#9655) 2023-07-28 14:50:23 +01:00
Connor McLaughlinandGitHub cc4ba935b5 CI/Linux: Fetch tags for Flatpak scheduled builds
Regression from #9224.
2023-07-28 21:48:35 +10:00
RedPanda4552andrefractionpcsx2 824147fd7d [SAVEVERSION+] Fix vibration motors backwards and too low power delivery to small motor
Also fix inconsequential but (technically) incorrect return values for vibration mapping command
2023-07-28 11:27:51 +01:00
refractionpcsx2 c3446a16cc GS: Kill SMT Nocturne CRC hack 2023-07-28 01:48:45 +01:00
Stenzekandrefractionpcsx2 82135d1892 GS/OGL: Fix depth state in MultiStretchRects 2023-07-28 01:48:27 +01:00
refractionpcsx2 1cff63bc01 UI: Add some missing string translations 2023-07-27 20:25:17 +01:00
refractionpcsx2 e488e74313 UI: Fix minor typo 2023-07-27 20:25:17 +01:00
refractionpcsx2 1a17c9da86 GameDB: Add Preload Frame to remaining versions of Keroro Gunsou 2023-07-27 20:25:17 +01:00
refractionpcsx2 20e1f773fc GS/HW: Mark alpha invalid on framebuffer resize. 2023-07-27 20:25:17 +01:00
refractionpcsx2 56d80ff293 GS/HW: Update Blue Tongue CRC and remove frame width hacks 2023-07-27 20:25:17 +01:00
refractionpcsx2 80e176136a GS/HW: Adjust Burnout bloom CRC to work better with upscaling 2023-07-27 20:23:21 +01:00
RedPanda4552andrefractionpcsx2 0ae66d3e24 Pad: Set data low when no pad present
Fixes uLaunchELF spinning waiting for second pad to come online.
2023-07-27 20:19:45 +01:00
RedDevilusandrefractionpcsx2 802ab8238e GameDB: Beeg fixing about everything
Sims M6 to M8 (more languages)
Tarzan (Slight Blurring)
Winnie Poo (Misaligned sprites and models)
Blood Will Tell: More vibrant text with medium blending
Recommended blending for SSX series

etc Because I keep forgetting to PR this otherwise
2023-07-27 17:09:31 +01:00
refractionpcsx2 ec9c07a646 GS/HW: Tweak Burnout bloom CRC coords 2023-07-27 14:50:29 +01:00
refractionpcsx2 b75ad663f2 USB/UI: Fix small typo 2023-07-27 13:08:08 +01:00
Stenzek e4a017fc00 Qt: Add callback for forcing achievements re-login 2023-07-27 20:40:58 +10:00
SilentandConnor McLaughlin 5b486ca6b8 Achievements: Log-in explicitly on startup to refresh the token 2023-07-27 20:40:58 +10:00
PCSX2 BotandConnor McLaughlin 1c39ed6130 Qt: Update Base Translation 2023-07-27 12:50:26 +10:00
lightningterror a47563b12f GSRunner: Fixes runner compile.
Pad include from previous refactor.
2023-07-26 21:56:56 +02:00
refractionpcsx2 84491ff655 GS/HW: Modify Burnout IO CRC hack to not affect online mode screen 2023-07-26 20:23:37 +01:00
refractionpcsx2 e5991a4379 GameDB: Add Partial Target Invalidation to Racing Simulation 3 2023-07-26 16:07:57 +01:00
JordanTheToasterandrefractionpcsx2 0b3d4615b8 ImGuiOverlays: Fix missing space
Text gets bunched up otherwise with no space.
2023-07-26 14:38:18 +01:00
JordanTheToasterandrefractionpcsx2 a8f6336b47 GameDB: Various fixes
Fixes for flickering lights in Area 51 and missing fixes for Burnout Revenge and Dominator.
2023-07-26 14:38:18 +01:00
RedPanda4552andConnor McLaughlin 0b33df3341 Pad: Change button query response depending on current mode
Fixes CoD 3 not understanding which buttons the controller has available
2023-07-26 21:23:21 +10:00
kamfretozandConnor McLaughlin 744cc4b705 Qt: Add an instruction to the autoupdater pop up. 2023-07-26 15:03:11 +10:00
kamfretozandConnor McLaughlin 9d3cd5784f Qt: Further icon refinement and additions 2023-07-26 13:28:23 +10:00
Stenzek 06ea58198a GameDB: Use nearest dirty upload for Burnout 3 and Onimusha 3
Burnout 3: Fixes sun banding in some stages.
Onimusha 3: Fixes vertical line down screen.
2023-07-26 13:21:35 +10:00
Stenzek 3692d7d090 GS/HW: Extend bilinear dirty upscale fix to force nearest 2023-07-26 13:21:35 +10:00
Stenzek 460a2dbbd3 Qt: Add custom binding widget for GunCon2 2023-07-26 13:20:44 +10:00
Stenzek 228f4f1010 USB-GunCon2: Support binding to controller 2023-07-26 13:20:44 +10:00
Stenzek 2703b91e41 USB: Add ConfigKeyExists() 2023-07-26 13:20:44 +10:00
Stenzek 24171787f8 ImGuiManager: Add software cursor support
Can be used to render a crosshair for GunCon.
2023-07-26 13:20:44 +10:00
PCSX2 BotandConnor McLaughlin 49d3338d4a Qt: Update Base Translation 2023-07-26 13:19:37 +10:00
Stenzek a9d693e1c3 GS/HW: Improve readback-avoiding CLUT heuristics
Use target overlap instead of exact match.
2023-07-26 13:18:04 +10:00
Stenzek 4ef69248d0 GSRunner: Add readbacks to stats 2023-07-26 13:18:04 +10:00
Stenzek 247b3ed740 GS/HW: HLE the Burnout games bloom effect 2023-07-26 13:18:04 +10:00
Stenzekandrefractionpcsx2 1edca6235c Sio: Migrate to StateWrapper
Also fixes the crash due to serializing pointers.

[SAVEVERSION+] and actually bump the save version.
2023-07-26 01:22:11 +01:00
Connor McLaughlinandGitHub ab5c03b1d9 Pad: Fixes and cleanup (#9623)
* Pad: Get rid of redundant object lookup

* Pad: Serialize 'stage' state

[SAVEVERSION+]

* Pad: Reduce Freeze duplication and add markers

Catch any possible unhandled device type change.

[SAVEVERSION+]

* Pad: Localize controller type names

* Pad: Handle mismatch between state and current config

* Misc: Drop .at() from vector/array access

We don't use exceptions.

* Pad: Remove redundant GetUnifiedSlot()

Sio has routines for converting these.

* Sio2: Remove redundant optional in Pad()

* Pad: Constify and finalize controller classes

* Pad: Move PadManager to Pad namespace

No point having a class when there's only a single instance.

* Pad: Move PadConfig to Pad namespace

* Pad: Move PadMacros to Pad namespace

* Pad: Re-localize controller bindings/settings

* Pad: Make controller info local

Don't want to create duplicates.

* Pad: Use span for ControllerInfo settings/bindings

* Pad: Fix auto-toggled macro buttons

* Pad: Fix pressure for macros

* Pad: Merge PadConfig/PadManager/PadMacros

Faster compile time.

* Pad: Fix incorrect condition in Sio0::SetTxData()

* Pad: Add deadzone for macro triggers
2023-07-26 01:10:02 +10:00
TheLastRarandrefractionpcsx2 d4cb35469d DEV9: Perform a null check on ifa_addr when searching adapters 2023-07-25 13:23:01 +01:00
Stenzek fd1b1d0c24 GS/HW: Improve Basic blending
- Don't assume no overlap = free. Reduces a number of barriers.
 - Prefer SW blend for Ad blends, except when it's constant. It's
   impossible to emulate accurately in HW, because 128 is 1, not 255.
 - Prefer SW blend for AFIX > 128 on no-overlap sprites.
2023-07-25 13:04:45 +10:00
Stenzek bf96ceeacc GS/HW: Assume primitive does not overlap if it is a single quad
Enables one-barrier software blending for fullscreen quads.
We can also use tex-is-fb safely in these scenarios too.

Fixes Persona 4 menu background, Hard Hitter Tennis shadows at
Basic blending.
2023-07-25 13:04:45 +10:00
RedPanda4552andrefractionpcsx2 2c08b385e5 Pad: Revert back to old Constant 1 behavior
Fixes pad detection in NBA 2K7, possibly others.
2023-07-25 00:27:53 +01:00
JordanTheToasterandrefractionpcsx2 051d13ec7a GameDB: Various fixes
Adds missing fixes and game entry's for guitar hero and re fixes LOTR Third Age.
2023-07-24 23:18:30 +01:00
refractionpcsx2 a2a9643123 GameDB: Move Haunting Ground over to HPO Special + Round Sprite Half 2023-07-24 21:44:24 +01:00
refractionpcsx2 1286bfe75b UI/UX: Added popup when updating if savestate version changes 2023-07-24 19:42:36 +01:00
RedPanda4552andrefractionpcsx2 1f74f82796 [SAVEVERSION+] Reimplement PAD system
Force pushed because git hates me

[SAVEVERSION+] Bump savestate version

CI: Update locations of pad/memcard sources

Discard leftover old PAD code

Fix additional merge oddities

Add translations for OSD messages

Copyright headers

Version bump

Fix a whole boatload of concurrency problems from file moves and other miscellaneous update problems

Partial redo of PS1 pad support

Fix incorrect mode due to analog behavior at startup

Mostly reimplement SIO0 memory card logic

Still needs pocketstation

Use new runtime wrapped translate function

Dead code

Fix multiple port/slot/presence issues for PS1

Save State version bump

Clean up some duplicate/unused headers

More header consistency

Remove old stray files

Fix incorrect return

Fix uninitialized array

Add missing overrides

Switch to init/close model used by other subsystems

Remove old input recording references

Rename SIO globals

Rename SIO2 FIFO globals

Remove commented SIO0 code for illegal write

Add guitar icon
2023-07-24 16:41:17 +01:00
Stenzek 876b576679 CI: Pin flat-manager-client version 2023-07-24 21:26:41 +10:00
Stenzek c927e4785b GS/HW: Get rid of 2 frame forced preload 2023-07-24 18:31:07 +10:00
refractionpcsx2 97672828e8 GameDB: Add patch for Shadow Hearts NTSC-U bad clip arrangement 2023-07-24 09:01:44 +01:00
refractionpcsx2 b96978494b GS/HW: Fix Double Half Clear bug + better detect double buffer changes 2023-07-23 19:40:14 +01:00
Stenzekandrefractionpcsx2 2f105cbe15 VMManager: Display title as serial or ELF 2023-07-23 19:09:41 +01:00
Stenzekandrefractionpcsx2 2539a07b7d Qt: Add dump verification to game properties 2023-07-23 19:09:31 +01:00
Stenzekandrefractionpcsx2 73f903f402 GameDatabase: Add hash database parse/lookup 2023-07-23 19:09:31 +01:00
Stenzekandrefractionpcsx2 94c48a4c2d CDVD: Add IsoHasher 2023-07-23 19:09:31 +01:00
Stenzekandrefractionpcsx2 eb8d938c94 Resources: Add redump database 2023-07-23 19:09:31 +01:00
CRASHARKIandrefractionpcsx2 92b8316182 GameDB: Add nativePaletteDraw and halfPixelOffset to Crash Tag Team Racing 2023-07-23 19:09:15 +01:00
Stenzekandrefractionpcsx2 610cb2626b GS/HW: Use GetUnwrappedEndBlockAddress() where appropriate 2023-07-23 19:09:01 +01:00
Stenzekandrefractionpcsx2 2033f813da GS/HW: Fix incorrect usage of bit_ceil() 2023-07-23 19:09:01 +01:00
pgertandrefractionpcsx2 a6fbd0fe69 GameDB: correct an entry 2023-07-23 19:00:55 +01:00
Stenzek abadb7f80f GSRunner: Fix Unicode command line on Win32 2023-07-24 00:55:54 +10:00
JordanTheToasterandrefractionpcsx2 1c6be3f400 GameDB: Various fixes
Fixes for Link being a doughnut and missing a line and for crusty field textures in all NCAA Football games TW PGA golf games and Madden games.
2023-07-23 13:28:40 +01:00
CRASHARKIandrefractionpcsx2 52111be20a GameDB: Change halfPixelOffset to Spyro: A Hero's Tail 2023-07-23 13:27:51 +01:00
Stenzek eae29bb1f2 Common: Make __pagesize unsigned 2023-07-23 21:52:36 +10:00
Stenzek 9191e8ce91 Misc: Use std::bit_ceil()/std::has_single_bit() 2023-07-23 21:52:36 +10:00
Stenzek 2b4c7d12b6 Common: Merge MathUtils.h into BitUtils.h 2023-07-23 21:52:36 +10:00
Stenzek 7dd1f7321a Misc: Replace _BitScanForward() with std::countr_zero() 2023-07-23 21:52:36 +10:00
Stenzek 088630a999 Misc: Replace bit_cast wrapper with std::bit_cast 2023-07-23 21:52:36 +10:00
Stenzek d2a5cdcca7 Misc: Remove string map lookup wrappers
No longer needed.
2023-07-23 21:52:36 +10:00
Stenzek 4b50d016b5 CI: Add qtimageformats for Linux/Mac 2023-07-23 17:34:50 +10:00
PCSX2 BotandConnor McLaughlin 7a073e0e8d Qt: Update Base Translation 2023-07-23 13:41:25 +10:00
Stenzek b56958abe4 USB-Turntable: Implement Freeze() 2023-07-23 13:41:00 +10:00
CRASHARKIandrefractionpcsx2 57d042ca4a GameDB: Add Blending Accuracy to Spyro: Enter the Dragonfly
Added Blending Accuracy 3 to fix Gems not shining properly.

Revert "GameDB: Add Blending Accuracy to Spyro: Enter the Dragonfly"

This reverts commit d2b8017e59cfbb99beee8cb7f912b327c5ffaf9e.

GameDB: Add Blending Accuracy to Spyro: Enter the Dragonfly
2023-07-23 00:34:28 +01:00
Rileyandrefractionpcsx2 3895f3c826 CDVD: Fix DevCon typo for cdvdUncheckedLoadDiscElf 2023-07-23 00:04:54 +01:00
75aed7c44f GameDB: Adding Cop 2 patches for French & German versions of Kessen II
Co-Authored-By: prafullpcsx2 <12788199+prafullpcsx2@users.noreply.github.com>
2023-07-22 16:46:34 +01:00
Stenzek 041c0ce86c CI/Linux: Include AppStream XML in AppImage 2023-07-22 18:47:47 +10:00
Stenzek 90aabdf499 CI/Linux: Fix AppImage getting symbols stripped 2023-07-22 18:47:47 +10:00
Stenzek 40f7ec3ca1 GS/HW: Fix alpha min/max crashing on BC1 textures 2023-07-22 17:15:27 +10:00
TellowKrinkleandTellowKrinkle 1e32fcaebe GS:Capture: Prefer h264 as the default codec
FFmpeg's default is mpeg4 for a number of containers if it was compiled without x264
2023-07-22 00:40:24 -05:00
TellowKrinkleandTellowKrinkle 9f23755a62 GS:Capture: Support user pixel format overrides 2023-07-22 00:40:24 -05:00
TellowKrinkleandTellowKrinkle dad03478fd GS:Capture: Fix s16 audio output 2023-07-22 00:40:24 -05:00
TellowKrinkleandTellowKrinkle 484b75f755 GHActions:MacOS: Bundle a minimal ffmpeg 2023-07-22 00:40:24 -05:00
TellowKrinkleandTellowKrinkle 7138faa5cd CMake: Support linked ffmpeg on macOS 2023-07-22 00:40:24 -05:00
TellowKrinkleandTellowKrinkle fef1706fc8 GS: Add mov capture option 2023-07-22 00:40:24 -05:00
Stenzekandrefractionpcsx2 1929b20a6c GSRunner: Add modal comparison
Click on a dump to open.
Left/right arrow keys switch between dumps.
Space bar toggles between before/after.
Escape closes.
2023-07-22 05:15:21 +01:00
Stenzekandrefractionpcsx2 3991ff5d3a GSRunner: Fix incorrect total/average counters 2023-07-22 05:15:21 +01:00
PCSX2 BotandConnor McLaughlin e4b1c89719 Qt: Update Base Translation 2023-07-22 12:12:28 +10:00
Stenzekandrefractionpcsx2 3d51eec89c VMManager: Notify MTGS in UpdateDiscDetails() 2023-07-21 18:05:14 +01:00
lightningterror f9016f3ea7 vcxproj: Add missing shader filters.
All renderers: present and imgui.
Vulkan: shadeboost.
2023-07-21 10:24:15 +02:00
lightningterror 3dce969a5e GS-shaders: Add missing copyright headers. 2023-07-21 10:24:15 +02:00
PCSX2 BotandConnor McLaughlin 542d257b8f Qt: Update Base Translation 2023-07-21 12:58:34 +10:00
Stenzek 2eb7c47572 Qt: Fix game properties for unscanned files 2023-07-21 12:57:25 +10:00
324 changed files with 196248 additions and 63104 deletions
+4 -4
View File
@@ -115,11 +115,11 @@
- 'pcsx2/IPU/*'
- 'pcsx2/IPU/**/*'
'Memory Card':
- 'pcsx2/gui/MemoryCard*'
- 'pcsx2/gui/**/MemoryCard*'
- 'pcsx2/SIO/Memcard/*'
- 'pcsx2/SIO/Memcard/**/*'
'PAD':
- 'pcsx2/PAD/*'
- 'pcsx2/PAD/**/*'
- 'pcsx2/SIO/Pad/*'
- 'pcsx2/SIO/Pad/**/*'
'SPU2':
- 'pcsx2/SPU2/*'
- 'pcsx2/SPU2/**/*'
@@ -37,5 +37,6 @@ jobs:
cmakeflags: ""
publish: true
branch: stable
fetchTags: true
secrets: inherit
+4 -2
View File
@@ -67,9 +67,9 @@ jobs:
brew unlink libjpeg || true # Conflicts with our self-built dependencies
brew unlink libpng || true
# Unlike other packages, brew's MoltenVK build uses MoltenVK's minimum macOS version of 10.13 so we can use it
if ! brew install molten-vk ccache; then
if ! brew install molten-vk ccache nasm; then
brew update
brew install molten-vk ccache
brew install molten-vk ccache nasm
fi
- name: Cache Dependencies
@@ -105,10 +105,12 @@ jobs:
cmake -DCMAKE_PREFIX_PATH="$HOME/deps" \
-DCMAKE_BUILD_TYPE=Release \
-DUSE_OPENGL=OFF \
-DUSE_VULKAN=OFF \
-DDISABLE_ADVANCE_SIMD=ON \
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
-DUSE_SYSTEM_LIBS=OFF \
-DUSE_SYSTEM_SDL2=ON \
-DUSE_LINKED_FFMPEG=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \
-24
View File
@@ -1,24 +0,0 @@
name: 📢 Announce Release
on:
release:
types: [published]
jobs:
announce:
if: github.repository == 'PCSX2/pcsx2'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Announce Release
env:
DISCORD_BUILD_WEBHOOK: ${{ secrets.DISCORD_BUILD_WEBHOOK }}
run: |
cd ./.github/workflows/scripts/releases/announce-release
npm ci
node index.js
+22 -7
View File
@@ -27,8 +27,10 @@ permissions:
jobs:
cut-release:
if: github.repository == 'PCSX2/pcsx2'
runs-on: ubuntu-latest
name: "Create Tag and Release"
runs-on: ubuntu-latest
outputs:
new_tag: ${{ steps.tag_version.outputs.new_tag }}
steps:
- uses: actions/checkout@v3
@@ -131,6 +133,7 @@ jobs:
upload_artifacts:
if: github.repository == 'PCSX2/pcsx2'
needs:
- cut-release
- build_linux_flatpak
- build_linux_qt
- build_windows_qt
@@ -140,10 +143,6 @@ jobs:
steps:
- uses: actions/checkout@v3
# actions/checkout elides tags, fetch them primarily for releases
- name: Fetch Tags
run: git fetch --tags --no-recurse-submodules
- name: Prepare Artifact Folder
run: mkdir ./ci-artifacts/
@@ -169,7 +168,7 @@ jobs:
SCAN_DIR: ${{ github.WORKSPACE }}/ci-artifacts
OUT_DIR: ${{ github.WORKSPACE }}/ci-artifacts/out
run: |
TAG_VAL=$(git tag --points-at HEAD)
TAG_VAL=${{needs.cut-release.outputs.new_tag}}
echo "TAG_VAL=${TAG_VAL}"
gh release list --repo PCSX2/pcsx2
mkdir -p ${{ github.WORKSPACE }}/ci-artifacts/out
@@ -181,6 +180,22 @@ jobs:
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
TAG_VAL=$(git tag --points-at HEAD)
TAG_VAL=${{needs.cut-release.outputs.new_tag}}
echo "TAG_VAL=${TAG_VAL}"
gh release edit ${TAG_VAL} --draft=false --repo PCSX2/pcsx2
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Announce Release
env:
OWNER: PCSX2
REPO: pcsx2
DISCORD_BUILD_WEBHOOK: ${{ secrets.DISCORD_BUILD_WEBHOOK }}
GITHUB_TOKEN: ${{ github.token }}
run: |
TAG_VAL=${{needs.cut-release.outputs.new_tag}}
cd ./.github/workflows/scripts/releases/announce-release
npm ci
TAG_VAL=${TAG_VAL} node index.js
+28 -4
View File
@@ -78,16 +78,33 @@ OUTDIR=$(realpath "./$APPDIRNAME")
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
rm -fr "$OUTDIR"
# Why the nastyness? linuxdeploy strips our main binary, and there's no option to turn it off.
# It also doesn't strip the Qt libs. We can't strip them after running linuxdeploy, because
# patchelf corrupts the libraries (but they still work), but patchelf+strip makes them crash
# on load. So, make a backup copy, strip the original (since that's where linuxdeploy finds
# the libs to copy), then swap them back after we're done.
# Isn't Linux packaging amazing?
rm -fr "$DEPSDIR.bak"
cp -a "$DEPSDIR" "$DEPSDIR.bak"
IFS="
"
for i in $(find "$DEPSDIR" -iname '*.so'); do
echo "Stripping deps library ${i}"
strip "$i"
done
echo "Copying desktop file..."
cp "$PCSX2DIR/.github/workflows/scripts/linux/pcsx2-qt.desktop" .
cp "$PCSX2DIR/.github/workflows/scripts/linux/pcsx2-qt.desktop" "net.pcsx2.PCSX2.desktop"
cp "$PCSX2DIR/bin/resources/icons/AppIconLarge.png" "PCSX2.png"
echo "Running linuxdeploy to create AppDir..."
EXTRA_QT_PLUGINS="core;gui;network;svg;waylandclient;widgets;xcbqpa" \
EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so" \
QMAKE="$DEPSDIR/bin/qmake" \
NO_STRIP="1" \
$LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/pcsx2-qt" \
--desktop-file="pcsx2-qt.desktop" --icon-file="PCSX2.png"
--desktop-file="net.pcsx2.PCSX2.desktop" --icon-file="PCSX2.png"
echo "Copying resources into AppDir..."
cp -a "$BUILDDIR/bin/resources" "$OUTDIR/usr/bin"
@@ -100,7 +117,6 @@ for lib in "${MANUAL_QT_LIBS[@]}"; do
echo " $srcpath -> $dstpath"
cp "$srcpath" "$dstpath"
$PATCHELF --set-rpath '$ORIGIN' "$dstpath"
$STRIP "$dstpath"
done
# .. and plugins.
@@ -118,15 +134,23 @@ for GROUP in "${MANUAL_QT_PLUGINS[@]}"; do
echo " $srcsopath -> $dstsopath"
cp "$srcsopath" "$dstsopath"
$PATCHELF --set-rpath '$ORIGIN/../../lib:$ORIGIN' "$dstsopath"
$STRIP "$dstsopath"
done
done
# Restore unstripped deps (for cache).
rm -fr "$DEPSDIR"
mv "$DEPSDIR.bak" "$DEPSDIR"
# Fix up translations.
rm -fr "$OUTDIR/usr/bin/translations"
mv "$OUTDIR/usr/translations" "$OUTDIR/usr/bin"
cp -a "$BUILDDIR/bin/translations" "$OUTDIR/usr/bin"
# Generate AppStream meta-info.
echo "Generating AppStream metainfo..."
mkdir -p "$OUTDIR/usr/share/metainfo"
"$SCRIPTDIR/generate-metainfo.sh" "$OUTDIR/usr/share/metainfo/net.pcsx2.PCSX2.appdata.xml"
echo "Generating AppImage..."
rm -f "$NAME.AppImage"
$APPIMAGETOOL -v "$OUTDIR" "$NAME.AppImage"
@@ -5,7 +5,7 @@ set -e
INSTALLDIR="$HOME/deps"
NPROCS="$(getconf _NPROCESSORS_ONLN)"
SDL=SDL2-2.28.1
QT=6.5.0
QT=6.5.2
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
mkdir -p deps-build
@@ -14,17 +14,19 @@ cd deps-build
cat > SHASUMS <<EOF
4977ceba5c0054dbe6c2f114641aced43ce3bf2b41ea64b6a372d6ba129cb15d $SDL.tar.gz
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
fde1aa7b4fbe64ec1b4fc576a57f4688ad1453d2fab59cbadd948a10a6eaf5ef qtbase-everywhere-src-$QT.tar.xz
64ca7e61f44d51e28bcbb4e0509299b53a9a7e38879e00a7fe91643196067a4f qtsvg-everywhere-src-$QT.tar.xz
49c33d96b0a44988be954269b8ce3d1a495b439726e03a6be7c0d50a686369c4 qttools-everywhere-src-$QT.tar.xz
fc85d0fd8393f518653ccada1014177a56df6e73f30f3b64eea0c2e4a0067a3d qttranslations-everywhere-src-$QT.tar.xz
ccc57fa277fc5f1c1c2c4733eae80a60996b67a067233c47809e542aa31759a3 qtwayland-everywhere-src-$QT.tar.xz
3db4c729b4d80a9d8fda8dd77128406353baff4755ca619177eda4cddae71269 qtbase-everywhere-src-$QT.tar.xz
aae0c08924c6a5e47f9d57e031673d611ffff7aab2bee2e1cc460471ecac6743 qtimageformats-everywhere-src-$QT.tar.xz
48b4cc1093af2e0ab3bea30f60651bddd877a2335d16e7207879a2e9e81963a3 qtsvg-everywhere-src-$QT.tar.xz
551ffb22751d8fd4d88e9ebd55b9131f4ca55341ee497fdbbba4da8d10d94341 qttools-everywhere-src-$QT.tar.xz
337c45637e757e754c2f0ea65c20de3e6e53a841dda1253db15baa622515beeb qttranslations-everywhere-src-$QT.tar.xz
3020be86fb7fd0abb8509906ca6583cadcaee168159abceaeb5b3e9d42563c9a qtwayland-everywhere-src-$QT.tar.xz
EOF
curl -L \
-O "https://libsdl.org/release/$SDL.tar.gz" \
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
@@ -73,6 +75,16 @@ cmake --build . --parallel
cmake --install .
cd ../../
echo "Building Qt Image Formats..."
tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
cd "qtimageformats-everywhere-src-$QT"
mkdir build
cd build
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release ..
cmake --build . --parallel
cmake --install .
cd ../../
echo "Building Qt Wayland..."
tar xf "qtwayland-everywhere-src-$QT.tar.xz"
cd "qtwayland-everywhere-src-$QT"
@@ -49,7 +49,7 @@ retry_command sudo flatpak -y install "${FLATPAK_PACKAGES[@]}"
echo "Downloading flat-manager-client"
mkdir -p "$FLAT_MANAGER_CLIENT_DIR"
pushd "$FLAT_MANAGER_CLIENT_DIR"
aria2c -Z "https://raw.githubusercontent.com/flatpak/flat-manager/master/flat-manager-client"
aria2c -Z "https://raw.githubusercontent.com/flatpak/flat-manager/9401efbdc0d6bd489507d8401c567ba219d735d5/flat-manager-client"
chmod +x flat-manager-client
echo "$FLAT_MANAGER_CLIENT_DIR" >> $GITHUB_PATH
popd
@@ -10,7 +10,8 @@ SDL=SDL2-2.28.1
PNG=1.6.37
JPG=9e
SOUNDTOUCH=soundtouch-2.3.1
QT=6.4.3
FFMPEG=6.0
QT=6.4.3 # Currently stuck on Qt 6.4 due to 6.5 requiring macOS 11.0.
mkdir deps-build
cd deps-build
@@ -25,7 +26,9 @@ cat > SHASUMS <<EOF
505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca libpng-$PNG.tar.xz
4077d6a6a75aeb01884f708919d25934c93305e49f7e3f36db9129320e6f4f3d jpegsrc.v$JPG.tar.gz
6900996607258496ce126924a19fe9d598af9d892cf3f33d1e4daaa9b42ae0b1 $SOUNDTOUCH.tar.gz
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
5087c9e5b0165e7bc3c1a4ab176b35d0cd8f52636aea903fa377bdba00891a60 qtbase-everywhere-src-$QT.tar.xz
0aff58062e74b84617c5da8325d8cdad5368d8f4d2a11ceafcd58329fe99b798 qtimageformats-everywhere-src-$QT.tar.xz
88315f886cf81898705e487cedba6e6160724359d23c518c92c333c098879a4a qtsvg-everywhere-src-$QT.tar.xz
867df829cd5cd3ae8efe62e825503123542764b13c96953511e567df70c5a091 qttools-everywhere-src-$QT.tar.xz
79e56b7800d49649a8a8010818538c367a829e0b7a09d5f60bd3aecf5abe972c qttranslations-everywhere-src-$QT.tar.xz
@@ -36,7 +39,9 @@ curl -L \
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$PNG/libpng-$PNG.tar.xz" \
-O "https://www.ijg.org/files/jpegsrc.v$JPG.tar.gz" \
-O "https://www.surina.net/soundtouch/$SOUNDTOUCH.tar.gz" \
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
@@ -75,6 +80,18 @@ make -C build "-j$NPROCS"
make -C build install
cd ..
echo "Installing FFmpeg..."
tar xf "ffmpeg-$FFMPEG.tar.xz"
cd "ffmpeg-$FFMPEG"
./configure --prefix="$INSTALLDIR" --disable-all --disable-autodetect --disable-static --enable-shared \
--enable-avcodec --enable-avformat --enable-avutil --enable-swresample --enable-swscale \
--enable-audiotoolbox --enable-videotoolbox \
--enable-encoder=ffv1,qtrle,pcm_s16be,pcm_s16le,*_at,*_videotoolbox \
--enable-muxer=avi,matroska,mov,mp3,mp4,wav \
--enable-protocol=file
make "-j$NPROCS"
make install
cd ..
echo "Installing Qt Base..."
tar xf "qtbase-everywhere-src-$QT.tar.xz"
@@ -174,6 +191,13 @@ cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTAL
make -C build "-j$NPROCS"
make -C build install
cd ..
echo "Installing Qt Image Formats..."
tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
cd "qtimageformats-everywhere-src-$QT"
cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=MinSizeRel
make -C build "-j$NPROCS"
make -C build install
cd ..
echo "Installing Qt Tools..."
tar xf "qttools-everywhere-src-$QT.tar.xz"
cd "qttools-everywhere-src-$QT"
@@ -1,7 +1,58 @@
import { MessageEmbed, WebhookClient } from "discord.js";
import * as github from '@actions/github';
import { Octokit } from "@octokit/rest";
import { throttling } from "@octokit/plugin-throttling";
import { retry } from "@octokit/plugin-retry";
const releaseInfo = github.context.payload.release;
let owner = process.env.OWNER;
let repo = process.env.REPO;
Octokit.plugin(throttling);
Octokit.plugin(retry);
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN,
userAgent: `${owner}/${repo}`,
log: {
debug: () => { },
info: () => { },
warn: console.warn,
error: console.error
},
throttle: {
onRateLimit: (retryAfter, options) => {
octokit.log.warn(
`Request quota exhausted for request ${options.method} ${options.url}`
);
// Retry twice after hitting a rate limit error, then give up
if (options.request.retryCount <= 2) {
console.log(`Retrying after ${retryAfter} seconds!`);
return true;
}
},
onAbuseLimit: (retryAfter, options) => {
// does not retry, only logs a warning
octokit.log.warn(
`Abuse detected for request ${options.method} ${options.url}`
);
},
}
});
if (process.env.TAG_VAL === undefined || process.env.TAG_VAL === "") {
console.log(`Not announcing - TAG_VAL not defined`);
process.exit(1);
}
const { data: releaseInfo } = await octokit.rest.repos.getReleaseByTag({
owner: owner,
repo: repo,
tag: process.env.TAG_VAL,
});
if (releaseInfo === undefined) {
console.log(`Not announcing - could not locate release with tag ${process.env.TAG_VAL}`);
process.exit(1);
}
if (!releaseInfo.prerelease) {
console.log("Not announcing - release was not a pre-release (aka a Nightly)");
@@ -18,6 +69,7 @@ const embed = new MessageEmbed()
{ name: 'Installation Steps', value: '[See Here](https://github.com/PCSX2/pcsx2/wiki/Nightly-Build-Usage-Guide)', inline: true },
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
);
console.log(embed);
// Get all webhooks, simple comma-sep string
const webhookUrls = process.env.DISCORD_BUILD_WEBHOOK.split(",");
@@ -5,32 +5,16 @@
"requires": true,
"packages": {
"": {
"name": "announce-release",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@actions/github": "^5.0.0",
"@octokit/plugin-retry": "^3.0.9",
"@octokit/plugin-throttling": "^3.5.2",
"@octokit/rest": "^18.12.0",
"discord.js": "^13.2.0"
}
},
"node_modules/@actions/github": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.0.tgz",
"integrity": "sha512-QvE9eAAfEsS+yOOk0cylLBIO/d6WyWIOvsxxzdrPFaud39G6BOkUwScXZn1iBzQzHyu9SBkkLSWlohDWdsasAQ==",
"dependencies": {
"@actions/http-client": "^1.0.11",
"@octokit/core": "^3.4.0",
"@octokit/plugin-paginate-rest": "^2.13.3",
"@octokit/plugin-rest-endpoint-methods": "^5.1.1"
}
},
"node_modules/@actions/http-client": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
"dependencies": {
"tunnel": "0.0.6"
}
},
"node_modules/@discordjs/builders": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.6.0.tgz",
@@ -131,6 +115,14 @@
"@octokit/types": "^6.33.0"
}
},
"node_modules/@octokit/plugin-request-log": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
"peerDependencies": {
"@octokit/core": ">=3"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "5.12.1",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.12.1.tgz",
@@ -140,6 +132,27 @@
"deprecation": "^2.3.1"
}
},
"node_modules/@octokit/plugin-retry": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz",
"integrity": "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ==",
"dependencies": {
"@octokit/types": "^6.0.3",
"bottleneck": "^2.15.3"
}
},
"node_modules/@octokit/plugin-throttling": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz",
"integrity": "sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow==",
"dependencies": {
"@octokit/types": "^6.0.1",
"bottleneck": "^2.15.3"
},
"peerDependencies": {
"@octokit/core": "^3.5.0"
}
},
"node_modules/@octokit/request": {
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
@@ -163,6 +176,17 @@
"once": "^1.4.0"
}
},
"node_modules/@octokit/rest": {
"version": "18.12.0",
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
"integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
"dependencies": {
"@octokit/core": "^3.5.1",
"@octokit/plugin-paginate-rest": "^2.16.8",
"@octokit/plugin-request-log": "^1.0.4",
"@octokit/plugin-rest-endpoint-methods": "^5.12.0"
}
},
"node_modules/@octokit/types": {
"version": "6.33.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.33.0.tgz",
@@ -214,6 +238,11 @@
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
},
"node_modules/bottleneck": {
"version": "2.19.5",
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -388,14 +417,6 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
"node_modules/type-fest": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
@@ -461,25 +482,6 @@
}
},
"dependencies": {
"@actions/github": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.0.tgz",
"integrity": "sha512-QvE9eAAfEsS+yOOk0cylLBIO/d6WyWIOvsxxzdrPFaud39G6BOkUwScXZn1iBzQzHyu9SBkkLSWlohDWdsasAQ==",
"requires": {
"@actions/http-client": "^1.0.11",
"@octokit/core": "^3.4.0",
"@octokit/plugin-paginate-rest": "^2.13.3",
"@octokit/plugin-rest-endpoint-methods": "^5.1.1"
}
},
"@actions/http-client": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
"requires": {
"tunnel": "0.0.6"
}
},
"@discordjs/builders": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.6.0.tgz",
@@ -569,6 +571,12 @@
"@octokit/types": "^6.33.0"
}
},
"@octokit/plugin-request-log": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
"integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
"requires": {}
},
"@octokit/plugin-rest-endpoint-methods": {
"version": "5.12.1",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.12.1.tgz",
@@ -578,6 +586,24 @@
"deprecation": "^2.3.1"
}
},
"@octokit/plugin-retry": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz",
"integrity": "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ==",
"requires": {
"@octokit/types": "^6.0.3",
"bottleneck": "^2.15.3"
}
},
"@octokit/plugin-throttling": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-3.7.0.tgz",
"integrity": "sha512-qrKT1Yl/KuwGSC6/oHpLBot3ooC9rq0/ryDYBCpkRtoj+R8T47xTMDT6Tk2CxWopFota/8Pi/2SqArqwC0JPow==",
"requires": {
"@octokit/types": "^6.0.1",
"bottleneck": "^2.15.3"
}
},
"@octokit/request": {
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz",
@@ -601,6 +627,17 @@
"once": "^1.4.0"
}
},
"@octokit/rest": {
"version": "18.12.0",
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz",
"integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==",
"requires": {
"@octokit/core": "^3.5.1",
"@octokit/plugin-paginate-rest": "^2.16.8",
"@octokit/plugin-request-log": "^1.0.4",
"@octokit/plugin-rest-endpoint-methods": "^5.12.0"
}
},
"@octokit/types": {
"version": "6.33.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.33.0.tgz",
@@ -642,6 +679,11 @@
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz",
"integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ=="
},
"bottleneck": {
"version": "2.19.5",
"resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
"integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
},
"callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -765,11 +807,6 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
},
"type-fest": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
@@ -10,7 +10,9 @@
"author": "",
"license": "ISC",
"dependencies": {
"@actions/github": "^5.0.0",
"@octokit/plugin-retry": "^3.0.9",
"@octokit/plugin-throttling": "^3.5.2",
"@octokit/rest": "^18.12.0",
"discord.js": "^13.2.0"
}
}
+10 -4
View File
@@ -22,17 +22,23 @@ Installers and binaries for both stable and development builds are available fro
| Operating System | CPU | GPU | RAM |
| ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| - Windows 10 Version 1809 or later (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1800<br/> - Two physical cores, with hyperthreading | - Direct3D10 support <br/> - OpenGL 3.x support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
_Note: Recommended Single Thread Performance is based on moderately complex games. Games that pushed the PS2 hardware to its limits will struggle on CPUs at this level. Some release titles and 2D games which underutilized the PS2 hardware may run on CPUs rated as low as 1200. A quick reference for CPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:CPU_intensive_games), [Forum](https://forums.pcsx2.net/Thread-LIST-The-Most-CPU-Intensive-Games) and CPU **light** games: [Forum](https://forums.pcsx2.net/Thread-LIST-Games-that-don-t-need-a-strong-CPU-to-emulate)_
| - Windows 10 Version 1809 or later (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1500<br/> - Two physical cores, with hyperthreading | - Direct3D 11 (Feature Level 11.0) support <br/> - OpenGL 3.3 support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
### Recommended
| Operating System | CPU | GPU | RAM |
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| - Windows 10 22H2 (64-bit) <br/> - Ubuntu 23.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 2000<br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650, Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
### Heavy
| Operating System | CPU | GPU | RAM |
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| - Windows 10 22H2 (64-bit) <br/> - Ubuntu 23.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 2600<br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650, Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
_Note: Recommended GPU is based on 3x Internal, ~1080p resolution requirements. Higher resolutions will require stronger cards; 6x Internal, ~4K resolution will require a [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 12000 (GeForce RTX 2060 Radeon RX 6600 Intel Arc A750). Just like CPU requirements, this is also highly game dependent. A quick reference for GPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:GPU_intensive_games)_
_Note1: Recommended Single Thread Performance is based on moderately complex games. Games that pushed the PS2 hardware to its limits will struggle on CPUs at this level. Some release titles and 2D games which underutilized the PS2 hardware may run on CPUs rated as low as 1200. A quick reference for CPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:CPU_intensive_games), [Forum](https://forums.pcsx2.net/Thread-LIST-The-Most-CPU-Intensive-Games) and CPU **light** games: [Forum](https://forums.pcsx2.net/Thread-LIST-Games-that-don-t-need-a-strong-CPU-to-emulate)_
_Note2: Recommended GPU is based on 3x Internal, ~1080p resolution requirements. Higher resolutions will require stronger cards; 6x Internal, ~4K resolution will require a [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 12000 (GeForce RTX 2060 Radeon RX 6600 Intel Arc A750). Just like CPU requirements, this is also highly game dependent. A quick reference for GPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:GPU_intensive_games)_
### Technical Notes
+4747 -232
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+5 -3
View File
@@ -315,6 +315,7 @@
03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows,
03000000696400006964000000000000,iDroidCon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000511d00000230000000000000,iGUGU Gamecore,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b1,leftstick:b4,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b2,platform:Windows,
03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
030000006f0e00002401000000000000,Injustice Fightstick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
@@ -1065,10 +1066,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000c82d00002038000000010000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000751000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
03000000c82d00000631000014010000,8BitDo Pro 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
03000000c82d00001030000011010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,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:b4,y:b3,platform:Linux,
03000000c82d00000020000000000000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
06000000c82d00000020000006010000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
@@ -1094,9 +1095,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001130000011010000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00001230000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -1462,6 +1463,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000321500000b10000011010000,Razer Wolverine PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux,
190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
0300000081170000990a000001010000,Retronic Adapter,a:b0,leftx:a0,lefty:a1,platform:Linux,
+19 -68
View File
@@ -1,11 +1,18 @@
#if defined(SHADER_MODEL) || defined(FXAA_GLSL_130) || defined(FXAA_GLSL_VK) || defined(__METAL_VERSION__)
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SHADER_MODEL
#define SHADER_MODEL 0
#endif
#ifndef FXAA_HLSL_4
#define FXAA_HLSL_4 0
#endif
#ifndef FXAA_HLSL_5
#define FXAA_HLSL_5 0
#endif
@@ -36,7 +43,7 @@ layout(location = 0) in vec2 PSin_t;
layout(location = 0) out vec4 SV_Target0;
layout(set = 0, binding = 0) uniform sampler2D TextureSampler;
#elif (SHADER_MODEL >= 0x400)
#elif (FXAA_HLSL_5 == 1)
Texture2D Texture : register(t0);
SamplerState TextureSampler : register(s0);
@@ -65,26 +72,6 @@ static constexpr sampler MAIN_SAMPLER(coord::normalized, address::clamp_to_edge,
[FXAA CODE SECTION]
------------------------------------------------------------------------------*/
// We don't use gather4 for alpha/luminance because it would require an additional
// pass to compute the values, which would be slower than the extra shader loads.
#if (SHADER_MODEL >= 0x500)
#undef FXAA_HLSL_5
#define FXAA_HLSL_5 1
#define FXAA_GATHER4_ALPHA 0
#elif (SHADER_MODEL >= 0x400)
#undef FXAA_HLSL_4
#define FXAA_HLSL_4 1
#define FXAA_GATHER4_ALPHA 0
#elif (FXAA_GLSL_130 == 1 || FXAA_GLSL_VK == 1)
#define FXAA_GATHER4_ALPHA 0
#elif defined(__METAL_VERSION__)
#define FXAA_GATHER4_ALPHA 0
#endif
#if (FXAA_HLSL_5 == 1)
struct FxaaTex { SamplerState smpl; Texture2D tex; };
#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
@@ -94,13 +81,6 @@ struct FxaaTex { SamplerState smpl; Texture2D tex; };
#define FxaaDiscard clip(-1)
#define FxaaSat(x) saturate(x)
#elif (FXAA_HLSL_4 == 1)
struct FxaaTex { SamplerState smpl; Texture2D tex; };
#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
#define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
#define FxaaDiscard clip(-1)
#define FxaaSat(x) saturate(x)
#elif (FXAA_GLSL_130 == 1 || FXAA_GLSL_VK == 1)
#define int2 ivec2
#define float2 vec2
@@ -112,12 +92,6 @@ struct FxaaTex { SamplerState smpl; Texture2D tex; };
#define FxaaTexTop(t, p) textureLod(t, p, 0.0)
#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
#if (FXAA_GATHER4_ALPHA == 1)
// use #extension GL_ARB_gpu_shader5 : enable
#define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
#define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
#endif
#elif defined(__METAL_VERSION__)
#define FxaaTex texture2d<float>
#define FxaaTexTop(t, p) t.sample(MAIN_SAMPLER, p)
@@ -206,21 +180,6 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
posM.x = pos.x;
posM.y = pos.y;
#if (FXAA_GATHER4_ALPHA == 1)
float4 rgbyM = FxaaTexTop(tex, posM);
float4 luma4A = FxaaTexAlpha4(tex, posM);
float4 luma4B = FxaaTexOffAlpha4(tex, posM, int2(-1, -1));
rgbyM.w = RGBLuminance(rgbyM.xyz);
#define lumaM rgbyM.w
#define lumaE luma4A.z
#define lumaS luma4A.x
#define lumaSE luma4A.y
#define lumaNW luma4B.w
#define lumaN luma4B.z
#define lumaW luma4B.x
#else
float4 rgbyM = FxaaTexTop(tex, posM);
rgbyM.w = RGBLuminance(rgbyM.xyz);
#define lumaM rgbyM.w
@@ -229,7 +188,6 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
float lumaE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1, 0), fxaaRcpFrame.xy));
float lumaN = FxaaLuma(FxaaTexOff(tex, posM, int2( 0,-1), fxaaRcpFrame.xy));
float lumaW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 0), fxaaRcpFrame.xy));
#endif
float maxSM = max(lumaS, lumaM);
float minSM = min(lumaS, lumaM);
@@ -249,15 +207,10 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
if(earlyExit) { return rgbyM; }
#endif
#if (FXAA_GATHER4_ALPHA == 0)
float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1,-1), fxaaRcpFrame.xy));
float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1, 1), fxaaRcpFrame.xy));
float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1,-1), fxaaRcpFrame.xy));
float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 1), fxaaRcpFrame.xy));
#else
float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1,-1), fxaaRcpFrame.xy));
float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 1), fxaaRcpFrame.xy));
#endif
float lumaNS = lumaN + lumaS;
float lumaWE = lumaW + lumaE;
@@ -503,14 +456,14 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
#if (FXAA_GLSL_130 == 1 || FXAA_GLSL_VK == 1)
float4 FxaaPass(float4 FxaaColor, float2 uv0)
#elif (SHADER_MODEL >= 0x400)
#elif (FXAA_HLSL_5 == 1)
float4 FxaaPass(float4 FxaaColor : COLOR0, float2 uv0 : TEXCOORD0)
#elif defined(__METAL_VERSION__)
float4 FxaaPass(float4 FxaaColor, float2 uv0, texture2d<float> tex)
#endif
{
#if (SHADER_MODEL >= 0x400)
#if (FXAA_HLSL_5 == 1)
FxaaTex tex;
tex.tex = Texture;
tex.smpl = TextureSampler;
@@ -544,8 +497,8 @@ void main()
SV_Target0 = float4(color.rgb, 1.0);
}
#elif (SHADER_MODEL >= 0x400)
PS_OUTPUT ps_main(VS_OUTPUT input)
#elif (FXAA_HLSL_5 == 1)
PS_OUTPUT main(VS_OUTPUT input)
{
PS_OUTPUT output;
@@ -561,5 +514,3 @@ PS_OUTPUT ps_main(VS_OUTPUT input)
// Metal main function in in fxaa.metal
#endif
#endif
+14 -3
View File
@@ -1,4 +1,17 @@
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
struct VS_INPUT
{
@@ -398,5 +411,3 @@ float ps_stencil_image_init_1(PS_INPUT input) : SV_Target
c = float(0x7FFFFFFF);
return c;
}
#endif
+15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
cbuffer vertexBuffer : register(b0)
{
float4x4 ProjectionMatrix;
+14 -3
View File
@@ -1,4 +1,17 @@
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
Texture2D Texture;
SamplerState Sampler;
@@ -180,5 +193,3 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
return float4(0.0f, 0.0f, 0.0f, 0.0f);
}
#endif
+14 -2
View File
@@ -1,4 +1,17 @@
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
Texture2D Texture;
SamplerState Sampler;
@@ -30,4 +43,3 @@ float4 ps_main1(PS_INPUT input) : SV_Target0
c.a = BGColor.a;
return c;
}
#endif
+14 -7
View File
@@ -1,8 +1,17 @@
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
#ifndef PS_SCALE_FACTOR
#define PS_SCALE_FACTOR 1
#endif
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
struct VS_INPUT
{
@@ -436,5 +445,3 @@ PS_OUTPUT ps_automagical_supersampling(PS_INPUT input)
output.c = float4(col / div, 1);
return output;
}
#endif
+14 -3
View File
@@ -1,4 +1,17 @@
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
Texture2D Texture;
SamplerState Sampler;
@@ -49,5 +62,3 @@ float4 ps_main(PS_INPUT input) : SV_Target0
float4 c = Texture.Sample(Sampler, input.t);
return ContrastSaturationBrightness(c);
}
#endif
+41 -21
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#define FMT_32 0
#define FMT_24 1
#define FMT_16 2
@@ -37,6 +52,7 @@
#define PS_POINT_SAMPLER 0
#define PS_REGION_RECT 0
#define PS_SHUFFLE 0
#define PS_SHUFFLE_SAME 0
#define PS_READ_BA 0
#define PS_READ16_SRC 0
#define PS_DFMT 0
@@ -646,7 +662,7 @@ float4 sample_color(float2 st, float uv_w)
float4 tfx(float4 T, float4 C)
{
float4 C_out;
float4 FxT = trunc(trunc(C) * T / 128.0f);
float4 FxT = trunc((C * T) / 128.0f);
#if (PS_TFX == 0)
C_out = FxT;
@@ -925,8 +941,17 @@ PS_OUTPUT ps_main(PS_INPUT input)
{
uint4 denorm_c = uint4(C);
uint2 denorm_TA = uint2(float2(TA.xy) * 255.0f + 0.5f);
if (PS_READ16_SRC)
// Special case for 32bit input and 16bit output, shuffle used by The Godfather
if (PS_SHUFFLE_SAME)
{
if (PS_READ_BA)
C = (float4)(float((denorm_c.b & 0x7Fu) | (denorm_c.a & 0x80u)));
else
C.ga = C.rg;
}
// Copy of a 16bit source in to this target
else if (PS_READ16_SRC)
{
C.rb = (float2)float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5));
if (denorm_c.a & 0x80u)
@@ -934,28 +959,23 @@ PS_OUTPUT ps_main(PS_INPUT input)
else
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u));
}
// Write RB part. Mask will take care of the correct destination
else if (PS_READ_BA)
{
C.rb = C.bb;
if (denorm_c.a & 0x80u)
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
else
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
}
else
{
// Mask will take care of the correct destination
if (PS_READ_BA)
C.rb = C.bb;
else
C.rb = C.rr;
C.rb = C.rr;
if (denorm_c.g & 0x80u)
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
if (PS_READ_BA)
{
if (denorm_c.a & 0x80u)
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
else
C.ga = (float2)(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
}
else
{
if (denorm_c.g & 0x80u)
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
else
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
}
C.ga = (float2)(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
}
}
+15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
//#version 420 // Keep it for editor detection
+15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef VERTEX_SHADER
layout(location = 0) in vec2 Position;
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
//#version 420 // Keep it for editor detection
#ifdef FRAGMENT_SHADER
+15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
//#version 420 // Keep it for editor detection
#ifdef FRAGMENT_SHADER
+15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
//#version 420 // Keep it for editor detection
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
//#version 420 // Keep it for editor detection
/*
+36 -15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
//#version 420 // Keep it for text editor detection
#define FMT_32 0
@@ -599,7 +614,7 @@ vec4 sample_color(vec2 st)
vec4 tfx(vec4 T, vec4 C)
{
vec4 C_out;
vec4 FxT = trunc(trunc(C) * T / 128.0f);
vec4 FxT = trunc((C * T) / 128.0f);
#if (PS_TFX == 0)
C_out = FxT;
@@ -764,17 +779,19 @@ float As = As_rgba.a;
return;
#endif
vec3 Cs = Color.rgb;
#if SW_BLEND_NEEDS_RT
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
#else
// Not used, but we define it to make the selection below simpler.
vec4 RT = vec4(0.0f);
#endif
// FIXME FMT_16 case
// FIXME Ad or Ad * 2?
float Ad = RT.a / 128.0f;
// Let the compiler do its jobs !
vec3 Cd = RT.rgb;
#endif
vec3 Cs = Color.rgb;
#if PS_BLEND_A == 0
vec3 A = Cs;
@@ -935,26 +952,30 @@ void ps_main()
#if PS_SHUFFLE
uvec4 denorm_c = uvec4(C);
uvec2 denorm_TA = uvec2(vec2(TA.xy) * 255.0f + 0.5f);
#if PS_READ16_SRC
// Special case for 32bit input and 16bit output, shuffle used by The Godfather
#if PS_SHUFFLE_SAME
#if (PS_READ_BA)
C = vec4(float((denorm_c.b & 0x7Fu) | (denorm_c.a & 0x80u)));
#else
C.ga = C.rg;
#endif
// Copy of a 16bit source in to this target
#elif PS_READ16_SRC
C.rb = vec2(float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5)));
if (bool(denorm_c.a & 0x80u))
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u)));
else
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u)));
#else
// Write RB part. Mask will take care of the correct destination
#if PS_READ_BA
// Write RB part. Mask will take care of the correct destination
#elif PS_READ_BA
C.rb = C.bb;
#else
C.rb = C.rr;
#endif
// FIXME precompute my_TA & 0x80
// Write GA part. Mask will take care of the correct destination
// Note: GLSL 4.50/GL_EXT_shader_integer_mix support a mix instruction to select a component\n"
// However Nvidia emulate it with an if (at least on kepler arch) ...\n"
#if PS_READ_BA
// bit field operation requires GL4 HW. Could be nice to merge it with step/mix below
// uint my_ta = (bool(bitfieldExtract(denorm_c.a, 7, 1))) ? denorm_TA.y : denorm_TA.x;
// denorm_c.a = bitfieldInsert(denorm_c.a, bitfieldExtract(my_ta, 7, 1), 7, 1);
@@ -966,6 +987,7 @@ void ps_main()
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
#else
C.rb = C.rr;
if (bool(denorm_c.g & 0x80u))
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
else
@@ -977,9 +999,8 @@ void ps_main()
// float sel = step(128.0f, c.g);
// vec2 c_shuffle = vec2((denorm_c.gg & 0x7Fu) | (denorm_TA & 0x80u));
// c.ga = mix(c_shuffle.xx, c_shuffle.yy, sel);
#endif // PS_READ_BA
#endif // READ16_SRC
#endif // PS_SHUFFLE_SAME
#endif // PS_SHUFFLE
// Must be done before alpha correction
+15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
//#version 420 // Keep it for text editor detection
layout(std140, binding = 1) uniform cb20
+15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef VERTEX_SHADER
layout(location = 0) in vec4 a_pos;
+15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef VERTEX_SHADER
layout(location = 0) in vec2 Position;
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef VERTEX_SHADER
layout(location = 0) in vec4 a_pos;
+15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef VERTEX_SHADER
layout(location = 0) in vec4 a_pos;
+15
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef VERTEX_SHADER
layout(location = 0) in vec4 a_pos;
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
//#version 420 // Keep it for editor detection
#ifdef VERTEX_SHADER
+46 -26
View File
@@ -1,3 +1,18 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
//////////////////////////////////////////////////////////////////////
// Vertex Shader
//////////////////////////////////////////////////////////////////////
@@ -262,7 +277,9 @@ void main()
#define PS_TCOFFSETHACK 0
#define PS_POINT_SAMPLER 0
#define PS_SHUFFLE 0
#define PS_SHUFFLE_SAME 0
#define PS_READ_BA 0
#define PS_WRITE_RG 0
#define PS_READ16_SRC 0
#define PS_DFMT 0
#define PS_DEPTH_FMT 0
@@ -285,7 +302,7 @@ void main()
#endif
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
#define SW_BLEND_NEEDS_RT (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1)
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
#define PS_FEEDBACK_LOOP_IS_NEEDED (PS_TEX_IS_FB == 1 || PS_FBMASK || SW_BLEND_NEEDS_RT || (PS_DATE >= 5))
@@ -337,16 +354,16 @@ layout(set = 1, binding = 1) uniform texture2D Palette;
#if PS_FEEDBACK_LOOP_IS_NEEDED
#if defined(DISABLE_TEXTURE_BARRIER) || defined(HAS_FEEDBACK_LOOP_LAYOUT)
layout(set = 2, binding = 0) uniform texture2D RtSampler;
layout(set = 1, binding = 2) uniform texture2D RtSampler;
vec4 sample_from_rt() { return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0); }
#else
layout(input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput RtSampler;
layout(input_attachment_index = 0, set = 1, binding = 2) uniform subpassInput RtSampler;
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
#endif
#endif
#if PS_DATE > 0
layout(set = 2, binding = 1) uniform texture2D PrimMinTexture;
layout(set = 1, binding = 3) uniform texture2D PrimMinTexture;
#endif
#if NEEDS_TEX
@@ -834,7 +851,7 @@ vec4 sample_color(vec2 st)
vec4 tfx(vec4 T, vec4 C)
{
vec4 C_out;
vec4 FxT = trunc(trunc(C) * T / 128.0f);
vec4 FxT = trunc((C * T) / 128.0f);
#if (PS_TFX == 0)
C_out = FxT;
@@ -1182,33 +1199,36 @@ void main()
#if PS_SHUFFLE
uvec4 denorm_c = uvec4(C);
uvec2 denorm_TA = uvec2(vec2(TA.xy) * 255.0f + 0.5f);
#if PS_READ16_SRC
// Special case for 32bit input and 16bit output, shuffle used by The Godfather
#if PS_SHUFFLE_SAME
#if (PS_READ_BA)
C = vec4(float((denorm_c.b & 0x7Fu) | (denorm_c.a & 0x80u)));
#else
C.ga = C.rg;
#endif
// Copy of a 16bit source in to this target
#elif PS_READ16_SRC
C.rb = vec2(float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5)));
if ((denorm_c.a & 0x80u) != 0u)
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u)));
else
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u)));
// Write RB part. Mask will take care of the correct destination
#elif PS_READ_BA
C.rb = C.bb;
if ((denorm_c.a & 0x80u) != 0u)
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
else
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
#else
// Mask will take care of the correct destination
#if PS_READ_BA
C.rb = C.bb;
#else
C.rb = C.rr;
#endif
#if PS_READ_BA
if ((denorm_c.a & 0x80u) != 0u)
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
else
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
#else
if ((denorm_c.g & 0x80u) != 0u)
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
else
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
#endif
#endif
#endif
C.rb = C.rr;
if ((denorm_c.g & 0x80u) != 0u)
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
else
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
#endif // PS_SHUFFLE_SAME
#endif // PS_SHUFFLE
// Must be done before alpha correction
+3
View File
@@ -36,6 +36,9 @@ if(UNIX AND NOT APPLE)
option(X11_API "Enable X11 support" ON)
option(WAYLAND_API "Enable Wayland support" ON)
option(DBUS_API "Enable DBus support for screensaver inhibiting" ON)
endif()
if(UNIX)
option(USE_LINKED_FFMPEG "Links with ffmpeg instead of using dynamic loading" OFF)
endif()
-29
View File
@@ -1,29 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
// An implementation of bit_cast until we get c++20
template<class T2, class T1>
T2 bit_cast(const T1& src)
{
static_assert(sizeof(T2) == sizeof(T1), "bit_cast: types must be equal size");
static_assert(std::is_pod<T1>::value, "bit_cast: source must be POD");
static_assert(std::is_pod<T2>::value, "bit_cast: destination must be POD");
T2 dst;
memcpy(&dst, &src, sizeof(T2));
return dst;
}
+37 -38
View File
@@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@@ -14,8 +14,29 @@
*/
#pragma once
#include "common/Pcsx2Defs.h"
#include <bit>
#ifdef _MSC_VER
#include <intrin.h>
#else
static inline int _BitScanReverse(unsigned long* const Index, const unsigned long Mask)
{
if (Mask == 0)
return 0;
// For some reason, clang won't emit bsr if we use std::countl_zeros()...
*Index = 31 - __builtin_clz(Mask);
return 1;
}
#endif
namespace Common
{
template <typename T>
@@ -54,46 +75,24 @@ namespace Common
return value & static_cast<T>(~static_cast<T>(alignment - 1));
}
template <typename T>
static constexpr __fi bool IsPow2(T value)
{
return (value & (value - 1)) == 0;
}
template <typename T>
static constexpr __fi T PreviousPow2(T value)
{
if (value == static_cast<T>(0))
return 0;
value |= (value >> 1);
value |= (value >> 2);
value |= (value >> 4);
value |= (value >> 8);
value |= (value >> 16);
return value - (value >> 1);
}
template<typename T>
static constexpr __fi T NextPow2(T value)
{
if (value == static_cast<T>(0))
return 0;
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value++;
return value;
}
template <typename T>
static constexpr T PageAlign(T size)
{
static_assert(Common::IsPow2(__pagesize), "Page size is a power of 2");
static_assert(std::has_single_bit(__pagesize), "Page size is a power of 2");
return Common::AlignUpPow2(size, __pagesize);
}
__fi static u32 CountLeadingSignBits(s32 n)
{
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
if (n < 0)
n = ~n;
// If BSR is used directly, it would have an undefined value for 0.
if (n == 0)
return 32;
// Perform our count leading zero.
return std::countl_zero(static_cast<u32>(n));
}
} // namespace Common
+1 -1
View File
@@ -61,10 +61,10 @@ target_sources(common PRIVATE
# x86emitter headers
target_sources(common PRIVATE
Align.h
AlignedMalloc.h
Assertions.h
boost_spsc_queue.hpp
BitUtils.h
ByteSwap.h
Console.h
CrashHandler.h
-8
View File
@@ -748,13 +748,6 @@ s64 FileSystem::FTell64(std::FILE* fp)
s64 FileSystem::FSize64(std::FILE* fp)
{
#ifdef _WIN32
const int fd = _fileno(fp);
if (fd >= 0)
{
return _filelengthi64(fd);
}
#else
const s64 pos = FTell64(fp);
if (pos >= 0)
{
@@ -765,7 +758,6 @@ s64 FileSystem::FSize64(std::FILE* fp)
return size;
}
}
#endif
return -1;
}
-37
View File
@@ -71,43 +71,6 @@ using UnorderedStringSet =
using UnorderedStringMultiSet =
std::unordered_multiset<std::string, detail::transparent_string_hash, detail::transparent_string_equal>;
template <typename KeyType, typename ValueType>
__fi typename UnorderedStringMap<ValueType>::const_iterator
UnorderedStringMapFind(const UnorderedStringMap<ValueType>& map, const KeyType& key)
{
return map.find(key);
}
template <typename KeyType, typename ValueType>
__fi typename UnorderedStringMap<ValueType>::iterator
UnorderedStringMapFind(UnorderedStringMap<ValueType>& map, const KeyType& key)
{
return map.find(key);
}
template <typename KeyType, typename ValueType>
__fi typename UnorderedStringMultimap<ValueType>::const_iterator
UnorderedStringMultiMapFind(const UnorderedStringMultimap<ValueType>& map, const KeyType& key)
{
return map.find(key);
}
template <typename KeyType, typename ValueType>
__fi std::pair<typename UnorderedStringMultimap<ValueType>::const_iterator, typename UnorderedStringMultimap<ValueType>::const_iterator>
UnorderedStringMultiMapEqualRange(const UnorderedStringMultimap<ValueType>& map, const KeyType& key)
{
return map.equal_range(key);
}
template <typename KeyType, typename ValueType>
__fi typename UnorderedStringMultimap<ValueType>::iterator
UnorderedStringMultiMapFind(UnorderedStringMultimap<ValueType>& map, const KeyType& key)
{
return map.find(key);
}
template <typename KeyType, typename ValueType>
__fi std::pair<typename UnorderedStringMultimap<ValueType>::iterator, typename UnorderedStringMultimap<ValueType>::iterator>
UnorderedStringMultiMapEqualRange(UnorderedStringMultimap<ValueType>& map, const KeyType& key)
{
return map.equal_range(key);
}
template <typename ValueType>
using StringMap = std::map<std::string, ValueType, detail::transparent_string_less>;
template <typename ValueType>
+3 -2
View File
@@ -25,7 +25,7 @@
#include "fmt/core.h"
#include "common/Align.h"
#include "common/BitUtils.h"
#include "common/Assertions.h"
#include "common/Console.h"
#include "common/General.h"
@@ -108,7 +108,8 @@ static void SysPageFaultSignalFilter(int signal, siginfo_t* siginfo, void* ctx)
void* const exception_pc = nullptr;
#endif
const PageFaultInfo pfi{(uptr)exception_pc, (uptr)siginfo->si_addr & ~__pagemask};
const PageFaultInfo pfi{
reinterpret_cast<uptr>(exception_pc), reinterpret_cast<uptr>(siginfo->si_addr) & ~static_cast<uptr>(__pagemask)};
s_in_exception_handler = true;
-41
View File
@@ -1,41 +0,0 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2014- PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
// Hopefully this file will be used for cross-source math utilities.
// Currently these are strewn across the code base. Please collect them all!
#include "common/Pcsx2Defs.h"
// On GCC >= 4.7, this is equivalent to __builtin_clrsb(n);
inline u32 count_leading_sign_bits(s32 n)
{
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
if (n < 0)
n = ~n;
// If BSR is used directly, it would have an undefined value for 0.
if (n == 0)
return 32;
// Perform our count leading zero.
#ifdef _MSC_VER
unsigned long ret;
_BitScanReverse(&ret, n);
return 31 - (u32)ret;
#else
return __builtin_clz(n);
#endif
}
+27 -27
View File
@@ -32,7 +32,7 @@ void MemorySettingsInterface::Clear()
bool MemorySettingsInterface::GetIntValue(const char* section, const char* key, s32* value) const
{
const auto sit = UnorderedStringMapFind(m_sections, section);
const auto sit = m_sections.find(section);
if (sit == m_sections.end())
return false;
@@ -50,11 +50,11 @@ bool MemorySettingsInterface::GetIntValue(const char* section, const char* key,
bool MemorySettingsInterface::GetUIntValue(const char* section, const char* key, u32* value) const
{
const auto sit = UnorderedStringMapFind(m_sections, section);
const auto sit = m_sections.find(section);
if (sit == m_sections.end())
return false;
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
const auto iter = sit->second.find(key);
if (iter == sit->second.end())
return false;
@@ -68,11 +68,11 @@ bool MemorySettingsInterface::GetUIntValue(const char* section, const char* key,
bool MemorySettingsInterface::GetFloatValue(const char* section, const char* key, float* value) const
{
const auto sit = UnorderedStringMapFind(m_sections, section);
const auto sit = m_sections.find(section);
if (sit == m_sections.end())
return false;
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
const auto iter = sit->second.find(key);
if (iter == sit->second.end())
return false;
@@ -86,11 +86,11 @@ bool MemorySettingsInterface::GetFloatValue(const char* section, const char* key
bool MemorySettingsInterface::GetDoubleValue(const char* section, const char* key, double* value) const
{
const auto sit = UnorderedStringMapFind(m_sections, section);
const auto sit = m_sections.find(section);
if (sit == m_sections.end())
return false;
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
const auto iter = sit->second.find(key);
if (iter == sit->second.end())
return false;
@@ -104,11 +104,11 @@ bool MemorySettingsInterface::GetDoubleValue(const char* section, const char* ke
bool MemorySettingsInterface::GetBoolValue(const char* section, const char* key, bool* value) const
{
const auto sit = UnorderedStringMapFind(m_sections, section);
const auto sit = m_sections.find(section);
if (sit == m_sections.end())
return false;
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
const auto iter = sit->second.find(key);
if (iter == sit->second.end())
return false;
@@ -122,11 +122,11 @@ bool MemorySettingsInterface::GetBoolValue(const char* section, const char* key,
bool MemorySettingsInterface::GetStringValue(const char* section, const char* key, std::string* value) const
{
const auto sit = UnorderedStringMapFind(m_sections, section);
const auto sit = m_sections.find(section);
if (sit == m_sections.end())
return false;
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
const auto iter = sit->second.find(key);
if (iter == sit->second.end())
return false;
@@ -167,7 +167,7 @@ void MemorySettingsInterface::SetStringValue(const char* section, const char* ke
std::vector<std::pair<std::string, std::string>> MemorySettingsInterface::GetKeyValueList(const char* section) const
{
std::vector<std::pair<std::string, std::string>> output;
auto sit = UnorderedStringMapFind(m_sections, section);
auto sit = m_sections.find(section);
if (sit != m_sections.end())
{
for (const auto& it : sit->second)
@@ -178,7 +178,7 @@ std::vector<std::pair<std::string, std::string>> MemorySettingsInterface::GetKey
void MemorySettingsInterface::SetKeyValueList(const char* section, const std::vector<std::pair<std::string, std::string>>& items)
{
auto sit = UnorderedStringMapFind(m_sections, section);
auto sit = m_sections.find(section);
sit->second.clear();
for (const auto& [key, value] : items)
sit->second.emplace(key, value);
@@ -186,11 +186,11 @@ void MemorySettingsInterface::SetKeyValueList(const char* section, const std::ve
void MemorySettingsInterface::SetValue(const char* section, const char* key, std::string value)
{
auto sit = UnorderedStringMapFind(m_sections, section);
auto sit = m_sections.find(section);
if (sit == m_sections.end())
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
const auto range = sit->second.equal_range(key);
if (range.first == sit->second.end())
{
sit->second.emplace(std::string(key), std::move(value));
@@ -213,10 +213,10 @@ std::vector<std::string> MemorySettingsInterface::GetStringList(const char* sect
{
std::vector<std::string> ret;
const auto sit = UnorderedStringMapFind(m_sections, section);
const auto sit = m_sections.find(section);
if (sit != m_sections.end())
{
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
const auto range = sit->second.equal_range(key);
for (auto iter = range.first; iter != range.second; ++iter)
ret.emplace_back(iter->second);
}
@@ -226,11 +226,11 @@ std::vector<std::string> MemorySettingsInterface::GetStringList(const char* sect
void MemorySettingsInterface::SetStringList(const char* section, const char* key, const std::vector<std::string>& items)
{
auto sit = UnorderedStringMapFind(m_sections, section);
auto sit = m_sections.find(section);
if (sit == m_sections.end())
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
const auto range = sit->second.equal_range(key);
for (auto iter = range.first; iter != range.second;)
sit->second.erase(iter++);
@@ -241,11 +241,11 @@ void MemorySettingsInterface::SetStringList(const char* section, const char* key
bool MemorySettingsInterface::RemoveFromStringList(const char* section, const char* key, const char* item)
{
auto sit = UnorderedStringMapFind(m_sections, section);
auto sit = m_sections.find(section);
if (sit == m_sections.end())
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
const auto range = sit->second.equal_range(key);
bool result = false;
for (auto iter = range.first; iter != range.second;)
{
@@ -265,11 +265,11 @@ bool MemorySettingsInterface::RemoveFromStringList(const char* section, const ch
bool MemorySettingsInterface::AddToStringList(const char* section, const char* key, const char* item)
{
auto sit = UnorderedStringMapFind(m_sections, section);
auto sit = m_sections.find(section);
if (sit == m_sections.end())
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
const auto range = sit->second.equal_range(key);
for (auto iter = range.first; iter != range.second; ++iter)
{
if (iter->second == item)
@@ -282,7 +282,7 @@ bool MemorySettingsInterface::AddToStringList(const char* section, const char* k
bool MemorySettingsInterface::ContainsValue(const char* section, const char* key) const
{
const auto sit = UnorderedStringMapFind(m_sections, section);
const auto sit = m_sections.find(section);
if (sit == m_sections.end())
return false;
@@ -291,18 +291,18 @@ bool MemorySettingsInterface::ContainsValue(const char* section, const char* key
void MemorySettingsInterface::DeleteValue(const char* section, const char* key)
{
auto sit = UnorderedStringMapFind(m_sections, section);
auto sit = m_sections.find(section);
if (sit == m_sections.end())
return;
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
const auto range = sit->second.equal_range(key);
for (auto iter = range.first; iter != range.second;)
sit->second.erase(iter++);
}
void MemorySettingsInterface::ClearSection(const char* section)
{
auto sit = UnorderedStringMapFind(m_sections, section);
auto sit = m_sections.find(section);
if (sit == m_sections.end())
return;
+1 -1
View File
@@ -110,7 +110,7 @@ struct crash_info_t
u64 reserved;
u64 reserved2;
};
#define CRASH_ANNOTATION __attribute__((section("__DATA,__crash_info")))
#define CRASH_ANNOTATION __attribute__((used, section("__DATA,__crash_info")))
#define CRASH_VERSION 4
extern "C" crash_info_t gCRAnnotations CRASH_ANNOTATION = { CRASH_VERSION };
#endif
+3 -4
View File
@@ -81,10 +81,9 @@
// Defines the memory page size for the target platform at compilation. All supported platforms
// (which means Intel only right now) have a 4k granularity.
#define PCSX2_PAGESIZE 0x1000
static constexpr int __pagesize = PCSX2_PAGESIZE;
static constexpr int __pageshift = 12;
static constexpr size_t __pagemask = PCSX2_PAGESIZE - 1;
static constexpr unsigned int __pagesize = 0x1000;
static constexpr unsigned int __pageshift = 12;
static constexpr unsigned int __pagemask = __pagesize - 1;
// --------------------------------------------------------------------------------------
// Microsoft Visual Studio
+5 -5
View File
@@ -92,31 +92,31 @@ public:
return value;
}
__fi std::optional<int> GetOptionalIntValue(const char* section, const char* key, std::optional<int> default_value = std::nullopt)
__fi std::optional<int> GetOptionalIntValue(const char* section, const char* key, std::optional<int> default_value = std::nullopt) const
{
int ret;
return GetIntValue(section, key, &ret) ? std::optional<int>(ret) : default_value;
}
__fi std::optional<uint> GetOptionalUIntValue(const char* section, const char* key, std::optional<uint> default_value = std::nullopt)
__fi std::optional<uint> GetOptionalUIntValue(const char* section, const char* key, std::optional<uint> default_value = std::nullopt) const
{
uint ret;
return GetUIntValue(section, key, &ret) ? std::optional<uint>(ret) : default_value;
}
__fi std::optional<float> GetOptionalFloatValue(const char* section, const char* key, std::optional<float> default_value = std::nullopt)
__fi std::optional<float> GetOptionalFloatValue(const char* section, const char* key, std::optional<float> default_value = std::nullopt) const
{
float ret;
return GetFloatValue(section, key, &ret) ? std::optional<float>(ret) : default_value;
}
__fi std::optional<double> GetOptionalDoubleValue(const char* section, const char* key, std::optional<double> default_value = std::nullopt)
__fi std::optional<double> GetOptionalDoubleValue(const char* section, const char* key, std::optional<double> default_value = std::nullopt) const
{
double ret;
return GetDoubleValue(section, key, &ret) ? std::optional<double>(ret) : default_value;
}
__fi std::optional<bool> GetOptionalBoolValue(const char* section, const char* key, std::optional<bool> default_value = std::nullopt)
__fi std::optional<bool> GetOptionalBoolValue(const char* section, const char* key, std::optional<bool> default_value = std::nullopt) const
{
bool ret;
return GetBoolValue(section, key, &ret) ? std::optional<bool>(ret) : default_value;
+4
View File
@@ -643,7 +643,9 @@ bool unpack_bc7_mode0_2(uint32_t mode, const uint64_t* data_chunks, color_rgba*
const uint32_t ENDPOINT_BITS = (mode == 0) ? 4 : 5;
const uint32_t ENDPOINT_MASK = (1 << ENDPOINT_BITS) - 1;
const uint32_t PBITS = (mode == 0) ? 6 : 0;
#ifndef BC7DECOMP_USE_SSE2
const uint32_t WEIGHT_VALS = 1 << WEIGHT_BITS;
#endif
const uint32_t PART_BITS = (mode == 0) ? 4 : 6;
const uint32_t PART_MASK = (1 << PART_BITS) - 1;
@@ -740,7 +742,9 @@ bool unpack_bc7_mode1_3_7(uint32_t mode, const uint64_t* data_chunks, color_rgba
const uint32_t ENDPOINT_MASK = (1 << ENDPOINT_BITS) - 1;
const uint32_t PBITS = (mode == 1) ? 2 : 4;
const uint32_t SHARED_PBITS = (mode == 1) ? true : false;
#ifndef BC7DECOMP_USE_SSE2
const uint32_t WEIGHT_VALS = 1 << WEIGHT_BITS;
#endif
const uint64_t low_chunk = data_chunks[0];
const uint64_t high_chunk = data_chunks[1];
+1 -1
View File
@@ -15,7 +15,7 @@
#if defined(_WIN32)
#include "common/Align.h"
#include "common/BitUtils.h"
#include "common/RedtapeWindows.h"
#include "common/Console.h"
#include "common/General.h"
+1 -3
View File
@@ -103,9 +103,8 @@
<MASM Include="FastJmp.asm" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Align.h" />
<ClInclude Include="BitUtils.h" />
<ClInclude Include="AlignedMalloc.h" />
<ClInclude Include="BitCast.h" />
<ClInclude Include="ByteSwap.h" />
<ClInclude Include="CrashHandler.h" />
<ClInclude Include="DynamicLibrary.h" />
@@ -135,7 +134,6 @@
<ClInclude Include="Assertions.h" />
<ClInclude Include="Console.h" />
<ClInclude Include="General.h" />
<ClInclude Include="MathUtils.h" />
<ClInclude Include="Path.h" />
<ClInclude Include="PrecompiledHeader.h" />
<ClInclude Include="ReadbackSpinManager.h" />
+1 -7
View File
@@ -201,9 +201,6 @@
<ClInclude Include="emitter\legacy_types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MathUtils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Path.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -270,15 +267,12 @@
<ClInclude Include="SettingsWrapper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Align.h">
<ClInclude Include="BitUtils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="WindowInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BitCast.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="StringUtil.h">
<Filter>Header Files</Filter>
</ClInclude>
+49 -10
View File
@@ -48,7 +48,7 @@
#include "pcsx2/Input/InputManager.h"
#include "pcsx2/LogSink.h"
#include "pcsx2/MTGS.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/SIO/Pad/Pad.h"
#include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/VMManager.h"
@@ -80,11 +80,18 @@ static bool s_no_console = false;
// Owned by the GS thread.
static u32 s_dump_frame_number = 0;
static u32 s_loop_number = s_loop_count;
static double s_last_draws = 0;
static double s_last_render_passes = 0;
static double s_last_barriers = 0;
static double s_last_copies = 0;
static double s_last_uploads = 0;
static double s_last_readbacks = 0;
static u64 s_total_draws = 0;
static u64 s_total_render_passes = 0;
static u64 s_total_barriers = 0;
static u64 s_total_copies = 0;
static u64 s_total_uploads = 0;
static u64 s_total_readbacks = 0;
static u32 s_total_frames = 0;
bool GSRunner::InitializeConfig()
@@ -110,7 +117,7 @@ bool GSRunner::InitializeConfig()
si.SetStringValue("SPU2/Output", "OutputModule", "nullout");
// none of the bindings are going to resolve to anything
PAD::ClearPortBindings(si, 0);
Pad::ClearPortBindings(si, 0);
si.ClearSection("Hotkeys");
// make sure any gamesettings inis in your tree don't get loaded
@@ -250,7 +257,7 @@ void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
{
}
void Host::SetRelativeMouseMode(bool enabled)
void Host::SetMouseMode(bool relative_mode, bool hide_cursor)
{
}
@@ -277,11 +284,18 @@ void Host::BeginPresentFrame()
if (GSConfig.UseHardwareRenderer())
{
s_total_draws += static_cast<u64>(g_perfmon.GetCounter(GSPerfMon::DrawCalls));
s_total_render_passes += static_cast<u64>(g_perfmon.GetCounter(GSPerfMon::RenderPasses));
s_total_barriers += static_cast<u64>(g_perfmon.GetCounter(GSPerfMon::Barriers));
s_total_copies += static_cast<u64>(g_perfmon.GetCounter(GSPerfMon::TextureCopies));
s_total_uploads += static_cast<u64>(g_perfmon.GetCounter(GSPerfMon::TextureUploads));
static constexpr auto update_stat = [](GSPerfMon::counter_t counter, u64& dst, double& last) {
// perfmon resets every 30 frames to zero
const double val = g_perfmon.GetCounter(counter);
dst += static_cast<u64>((val < last) ? val : (val - last));
last = val;
};
update_stat(GSPerfMon::DrawCalls, s_total_draws, s_last_draws);
update_stat(GSPerfMon::RenderPasses, s_total_render_passes, s_last_render_passes);
update_stat(GSPerfMon::Barriers, s_total_barriers, s_last_barriers);
update_stat(GSPerfMon::TextureCopies, s_total_copies, s_last_copies);
update_stat(GSPerfMon::TextureUploads, s_total_uploads, s_last_uploads);
update_stat(GSPerfMon::Readbacks, s_total_readbacks, s_last_readbacks);
s_total_frames++;
std::atomic_thread_fence(std::memory_order_release);
}
@@ -371,12 +385,15 @@ void Host::RequestVMShutdown(bool allow_confirm, bool allow_save_state, bool def
VMManager::SetState(VMState::Stopping);
}
#ifdef ENABLE_ACHIEVEMENTS
void Host::OnAchievementsLoginRequested(Achievements::LoginRequestReason reason)
{
// noop
}
void Host::OnAchievementsRefreshed()
{
// noop
}
#endif
std::optional<u32> InputManager::ConvertHostKeyboardStringToCode(const std::string_view& str)
{
@@ -630,9 +647,15 @@ void GSRunner::DumpStats()
Console.WriteLn(fmt::format("@HWSTAT@ Barriers: {} (avg {})", s_total_barriers, static_cast<u64>(std::ceil(s_total_barriers / static_cast<double>(s_total_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Copies: {} (avg {})", s_total_copies, static_cast<u64>(std::ceil(s_total_copies / static_cast<double>(s_total_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Uploads: {} (avg {})", s_total_uploads, static_cast<u64>(std::ceil(s_total_uploads / static_cast<double>(s_total_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Readbacks: {} (avg {})", s_total_readbacks, static_cast<u64>(std::ceil(s_total_readbacks / static_cast<double>(s_total_frames)))));
Console.WriteLn("============================================");
}
#ifdef _WIN32
// We can't handle unicode in filenames if we don't use wmain on Win32.
#define main real_main
#endif
int main(int argc, char* argv[])
{
GSRunner::InitializeConsole();
@@ -797,4 +820,20 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
int wmain(int argc, wchar_t** argv)
{
std::vector<std::string> u8_args;
u8_args.reserve(static_cast<size_t>(argc));
for (int i = 0; i < argc; i++)
u8_args.push_back(StringUtil::WideStringToUTF8String(argv[i]));
std::vector<char*> u8_argptrs;
u8_argptrs.reserve(u8_args.size());
for (int i = 0; i < argc; i++)
u8_argptrs.push_back(u8_args[i].data());
u8_argptrs.push_back(nullptr);
return real_main(argc, u8_argptrs.data());
}
#endif // _WIN32
+97
View File
@@ -0,0 +1,97 @@
.modal {
display: none;
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: black;
}
.modal-content {
position: relative;
margin: auto;
padding: 0;
width: 90%;
max-width: 1200px;
}
.close {
color: white;
position: absolute;
top: 10px;
right: 25px;
font-size: 35px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #999;
text-decoration: none;
cursor: pointer;
}
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -50px;
color: white;
font-weight: bold;
font-size: 20px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
}
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
.prev:hover,
.next:hover {
background-color: rgba(0, 0, 0, 0.8);
}
.item img {
cursor: pointer;
}
#compareTitle {
color: white;
font-size: 20px;
font-family: sans-serif;
margin-bottom: 10px;
}
#compareCaption {
color: white;
font-family: sans-serif;
}
#compareState {
display: block;
position: absolute;
right: 0;
top: 0;
color: red;
font-family: sans-serif;
font-size: 20px;
font-weight: bold;
}
#compareImage {
display: block;
margin: 0 auto;
width: 100%;
height: auto;
}
+111
View File
@@ -0,0 +1,111 @@
/* Worst script known to man */
/* Sources:
https://www.w3schools.com/howto/howto_js_lightbox.asp
https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/
*/
function openModal() {
document.body.style.position = 'fixed';
document.body.style.top = `-${window.scrollY}px`;
document.getElementById("myModal").style.display = "block";
document.getElementById("myModal").focus();
setImageIndex(0);
}
function closeModal() {
document.getElementById("myModal").style.display = "none";
const scrollY = document.body.style.top;
document.body.style.position = '';
document.body.style.top = '';
window.scrollTo(0, parseInt(scrollY || '0') * -1);
}
function isModalOpen() {
return (document.getElementById("myModal").style.display == "block");
}
function formatLines(str) {
let lines = str.split("\n")
lines = lines.filter(line => !line.startsWith("Difference in frames"))
return lines.join("<br>")
}
function extractItem(elem) {
return {
name: elem.querySelector("h1").innerText,
beforeImg: elem.querySelector(".before").getAttribute("src"),
afterImg: elem.querySelector(".after").getAttribute("src"),
details: formatLines(elem.querySelector("pre").innerText)
};
}
const items = [...document.querySelectorAll(".item")].map(extractItem)
let currentImage = 0;
let currentState = 0;
function getImageIndexForUri(uri) {
for (let i = 0; i < items.length; i++) {
if (items[i].beforeImg == uri || items[i].afterImg == uri)
return i;
}
return -1;
}
function setImageState(state) {
const item = items[currentImage]
const uri = (state === 0) ? item.beforeImg : item.afterImg;
const stateText = (state === 0) ? "BEFORE" : "AFTER";
const posText = "(" + (currentImage + 1).toString() + "/" + (items.length).toString() + ") ";
document.getElementById("compareImage").setAttribute("src", uri);
document.getElementById("compareState").innerText = stateText;
document.getElementById("compareTitle").innerText = posText + item.name;
document.getElementById("compareCaption").innerHTML = item.details;
currentState = state;
}
function setImageIndex(index) {
if (index < 0 || index > items.length)
return;
currentImage = index;
setImageState(0);
}
function handleKey(key) {
if (key == " ") {
setImageState((currentState === 0) ? 1 : 0);
return true;
} else if (key == "ArrowLeft") {
setImageIndex(currentImage - 1);
return true;
} else if (key == "ArrowRight") {
setImageIndex(currentImage + 1);
return true;
} else if (key == "Escape") {
closeModal();
return true;
} else {
console.log(key);
return false;
}
}
document.getElementById("myModal").addEventListener("keydown", function(ev) {
if (ev.defaultPrevented)
return;
if (handleKey(ev.key))
ev.preventDefault();
});
document.querySelector("#myModal .prev").addEventListener("click", function() {
setImageIndex(currentImage - 1);
});
document.querySelector("#myModal .next").addEventListener("click", function() {
setImageIndex(currentImage + 1);
});
document.querySelectorAll(".item img").forEach(elem => elem.addEventListener("click", function() {
if (!isModalOpen())
openModal();
setImageIndex(getImageIndexForUri(this.getAttribute("src")));
}));
+27 -3
View File
@@ -7,17 +7,35 @@ import hashlib
from pathlib import Path
MAX_DIFF_FRAMES = 9999
SCRIPTDIR = os.path.abspath(os.path.dirname(__file__))
CSS_PATH = Path(os.path.join(SCRIPTDIR, "comparer.css")).as_uri()
JS_PATH = Path(os.path.join(SCRIPTDIR, "comparer.js")).as_uri()
FILE_HEADER = """
<!DOCTYPE html>
<html>
<head>
<title>Comparison</title>
""" + f"<link rel=\"stylesheet\" href=\"{CSS_PATH}\" />" + """
</head>
<body>
"""
FILE_FOOTER = """
<div id="myModal" class="modal" tabindex="0">
<span class="close cursor" onclick="closeModal()">&times;</span>
<div class="modal-content">
<div id="compareTitle"></div>
<img id="compareImage" />
<div id="compareState"></div>
<a class="prev">&#10094;</a>
<a class="next">&#10095;</a>
<div id="compareCaption"></div>
</div>
</div>
""" + f"<script src=\"{JS_PATH}\"></script>\n" + """
</body>
</html>
"""
@@ -103,6 +121,7 @@ def check_regression_test(baselinedir, testdir, name):
diff_frames.append(framenum)
if first_fail:
write("<div class=\"item\">")
write("<h1>{}</h1>".format(name))
write("<table width=\"100%\">")
first_fail = False
@@ -110,14 +129,17 @@ def check_regression_test(baselinedir, testdir, name):
imguri1 = Path(path1).as_uri()
imguri2 = Path(path2).as_uri()
write("<tr><td colspan=\"2\">Frame %d</td></tr>" % (framenum))
write("<tr><td><img src=\"%s\" /></td><td><img src=\"%s\" /></td></tr>" % (imguri1, imguri2))
write("<tr><td><img class=\"before\" src=\"%s\" /></td><td><img class=\"after\" src=\"%s\" /></td></tr>" % (imguri1, imguri2))
if len(diff_frames) == MAX_DIFF_FRAMES:
break
if len(diff_frames) > 0:
write("</table>")
write("<pre>Difference in frames [%s] for %s</pre>" % (",".join(map(str, diff_frames)), name))
write("<pre>Difference in frames [%s] for %s%s%s</pre>" % (",".join(map(str, diff_frames)), name, "\n" if len(stats) > 0 else "", "\n".join(stats)))
write("</div>")
print("*** Difference in frames [%s] for %s" % (",".join(map(str, diff_frames)), name))
if len(stats) > 0:
write("<pre>%s</pre>" % "\n".join(stats))
print(stats)
elif len(stats) > 0:
write("<h1>{}</h1>".format(name))
@@ -149,9 +171,11 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Check frame dump images for regression tests")
parser.add_argument("-baselinedir", action="store", required=True, help="Directory containing baseline frames to check against")
parser.add_argument("-testdir", action="store", required=True, help="Directory containing frames to check")
parser.add_argument("-maxframes", type=int, action="store", required=False, default=9999, help="Max frames to compare")
parser.add_argument("outfile", action="store", help="The file to write the output to")
args = parser.parse_args()
MAX_DIFF_FRAMES = args.maxframes
outfile = open(args.outfile, "w")
write(FILE_HEADER)
+19
View File
@@ -380,6 +380,8 @@ void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
changes_html.prepend(tr("<h2>Save State Warning</h2><p>Installing this update will make your save states "
"<b>incompatible</b>. Please ensure you have saved your games to a Memory Card "
"before installing this update or you will lose progress.</p>"));
m_update_will_break_save_states = true;
}
if (update_increases_settings_version)
@@ -407,6 +409,23 @@ void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
void AutoUpdaterDialog::downloadUpdateClicked()
{
if (m_update_will_break_save_states)
{
QMessageBox msgbox;
msgbox.setIcon(QMessageBox::Critical);
msgbox.setWindowTitle(tr("Savestate Warning"));
msgbox.setText(tr("<h1>WARNING</h1><p style='font-size:12pt;'>Installing this update will make your <b>save states incompatible</b>, <i>be sure to save any progress to your memory cards before proceeding</i>.</p><p>Do you wish to continue?</p>"));
msgbox.addButton(QMessageBox::Yes);
msgbox.addButton(QMessageBox::No);
msgbox.setDefaultButton(QMessageBox::No);
// This makes the box wider, for some reason sizing boxes in Qt is hard - Source: The internet.
QSpacerItem* horizontalSpacer = new QSpacerItem(500, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
QGridLayout* layout = (QGridLayout*)msgbox.layout();
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
if (msgbox.exec() != QMessageBox::Yes)
return;
}
m_display_messages = true;
QUrl url(m_download_url);
QNetworkRequest request(url);
+2
View File
@@ -55,6 +55,7 @@ target_sources(pcsx2-qt PRIVATE
Settings/BIOSSettingsWidget.ui
Settings/ControllerBindingWidget.ui
Settings/ControllerBindingWidget_DualShock2.ui
Settings/ControllerBindingWidget_Guitar.ui
Settings/ControllerBindingWidgets.cpp
Settings/ControllerBindingWidgets.h
Settings/ControllerLEDSettingsDialog.ui
@@ -133,6 +134,7 @@ target_sources(pcsx2-qt PRIVATE
Settings/SettingsDialog.ui
Settings/USBBindingWidget_DrivingForce.ui
Settings/USBBindingWidget_GTForce.ui
Settings/USBBindingWidget_GunCon2.ui
Debugger/CpuWidget.cpp
Debugger/CpuWidget.h
Debugger/CpuWidget.ui
+4 -5
View File
@@ -26,7 +26,6 @@
#include "DebugTools/Breakpoints.h"
#include "DebugTools/BiosDebugData.h"
#include "DebugTools/MipsStackWalk.h"
#include "common/BitCast.h"
#include "QtUtils.h"
#include <QtGui/QClipboard>
@@ -539,7 +538,7 @@ static std::vector<u32> searchWorker(DebugInterface* cpu, u32 start, u32 end, T
{
const float fTop = value + 0.00001f;
const float fBottom = value - 0.00001f;
const float memValue = bit_cast<float, u32>(cpu->read32(addr));
const float memValue = std::bit_cast<float, u32>(cpu->read32(addr));
if (fBottom < memValue && memValue < fTop)
{
hitAddresses.emplace_back(addr);
@@ -556,7 +555,7 @@ static std::vector<u32> searchWorker(DebugInterface* cpu, u32 start, u32 end, T
{
const double dTop = value + 0.00001f;
const double dBottom = value - 0.00001f;
const double memValue = bit_cast<double, u64>(cpu->read64(addr));
const double memValue = std::bit_cast<double, u64>(cpu->read64(addr));
if (dBottom < memValue && memValue < dTop)
{
hitAddresses.emplace_back(addr);
@@ -588,9 +587,9 @@ static std::vector<u32> searchWorkerByteArray(DebugInterface* cpu, u32 start, u3
for (u32 addr = start; addr < end; addr += 1)
{
bool hit = true;
for (size_t i = 0; i < value.length(); i++)
for (qsizetype i = 0; i < value.length(); i++)
{
if (cpu->read8(addr + i) != value[i])
if (static_cast<char>(cpu->read8(addr + i)) != value[i])
{
hit = false;
break;
+4 -3
View File
@@ -151,9 +151,10 @@ void DisassemblyWidget::contextNoopInstruction()
void DisassemblyWidget::contextRunToCursor()
{
Host::RunOnCPUThread([&] { CBreakPoints::AddBreakPoint(m_cpu->getCpuType(), m_selectedAddressStart); });
m_cpu->resumeCpu();
Host::RunOnCPUThread([&] {
CBreakPoints::AddBreakPoint(m_cpu->getCpuType(), m_selectedAddressStart, true);
m_cpu->resumeCpu();
});
}
void DisassemblyWidget::contextJumpToCursor()
-2
View File
@@ -17,8 +17,6 @@
#include "MemoryViewWidget.h"
#include "common/BitCast.h"
#include "QtHost.h"
#include "QtUtils.h"
#include <QtGui/QMouseEvent>
+1 -1
View File
@@ -78,7 +78,7 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
{
QString type("");
type += (mc->cond & MEMCHECK_READ) ? tr("Read") : "";
type += ((mc->cond & MEMCHECK_BOTH) == MEMCHECK_BOTH) ? ", " : " ";
type += ((mc->cond & MEMCHECK_READWRITE) == MEMCHECK_READWRITE) ? ", " : " ";
//: (C) = changes, as in "look for changes".
type += (mc->cond & MEMCHECK_WRITE) ? (mc->cond & MEMCHECK_WRITE_ONCHANGE) ? tr("Write(C)") : tr("Write") : "";
return type;
+7 -8
View File
@@ -17,8 +17,6 @@
#include "RegisterWidget.h"
#include "common/BitCast.h"
#include "QtUtils.h"
#include <QtGui/QMouseEvent>
#include <QtWidgets/QTabBar>
@@ -30,6 +28,7 @@
#include <QtWidgets/QMessageBox>
#include <algorithm>
#include <bit>
#define CAT_SHOW_FLOAT (categoryIndex == EECAT_FPR && m_showFPRFloat) || (categoryIndex == EECAT_VU0F && m_showVU0FFloat)
@@ -151,7 +150,7 @@ void RegisterWidget::paintEvent(QPaintEvent* event)
if (categoryIndex == EECAT_VU0F && m_showVU0FFloat)
painter.drawText(m_fieldStartX[j], yStart, m_fieldWidth, m_rowHeight, Qt::AlignLeft,
painter.fontMetrics().elidedText(QString::number(bit_cast<float>(m_cpu->getRegister(categoryIndex, registerIndex)._u32[regIndex])), Qt::ElideRight, m_fieldWidth - painter.fontMetrics().averageCharWidth()));
painter.fontMetrics().elidedText(QString::number(std::bit_cast<float>(m_cpu->getRegister(categoryIndex, registerIndex)._u32[regIndex])), Qt::ElideRight, m_fieldWidth - painter.fontMetrics().averageCharWidth()));
else
painter.drawText(m_fieldStartX[j], yStart, m_fieldWidth, m_rowHeight,
Qt::AlignLeft, FilledQStringFromValue(curRegister._u32[regIndex], 16));
@@ -168,7 +167,7 @@ void RegisterWidget::paintEvent(QPaintEvent* event)
if (categoryIndex == EECAT_FPR && m_showFPRFloat)
painter.drawText(safeValueStartX, yStart, renderSize.width(), m_rowHeight, Qt::AlignLeft,
QString("%1").arg(QString::number(bit_cast<float>(m_cpu->getRegister(categoryIndex, registerIndex)._u32[0]))).toUpper());
QString("%1").arg(QString::number(std::bit_cast<float>(m_cpu->getRegister(categoryIndex, registerIndex)._u32[0]))).toUpper());
else if (m_cpu->getRegisterSize(categoryIndex) == 64)
painter.drawText(safeValueStartX, yStart, renderSize.width(), m_rowHeight, Qt::AlignLeft,
FilledQStringFromValue(m_cpu->getRegister(categoryIndex, registerIndex).lo, 16));
@@ -299,7 +298,7 @@ void RegisterWidget::contextCopyValue()
const int categoryIndex = ui.registerTabs->currentIndex();
const u128 val = m_cpu->getRegister(categoryIndex, m_selectedRow);
if (CAT_SHOW_FLOAT)
QApplication::clipboard()->setText(QString("%1").arg(QString::number(bit_cast<float>(val._u32[0])).toUpper(), 16));
QApplication::clipboard()->setText(QString("%1").arg(QString::number(std::bit_cast<float>(val._u32[0])).toUpper(), 16));
else
QApplication::clipboard()->setText(QString("%1").arg(QString::number(val._u64[0], 16).toUpper(), 16));
}
@@ -323,7 +322,7 @@ void RegisterWidget::contextCopySegment()
const int categoryIndex = ui.registerTabs->currentIndex();
const u128 val = m_cpu->getRegister(categoryIndex, m_selectedRow);
if (CAT_SHOW_FLOAT)
QApplication::clipboard()->setText(FilledQStringFromValue(bit_cast<float>(val._u32[3 - m_selected128Field]), 10));
QApplication::clipboard()->setText(FilledQStringFromValue(std::bit_cast<float>(val._u32[3 - m_selected128Field]), 10));
else
QApplication::clipboard()->setText(FilledQStringFromValue(val._u32[3 - m_selected128Field], 16));
}
@@ -340,7 +339,7 @@ bool RegisterWidget::contextFetchNewValue(u64& out, u64 currentValue, bool segme
if (!floatingPoint)
existingValue = existingValue.arg(currentValue, regSize == 64 ? 16 : 8, 16, QChar('0'));
else
existingValue = existingValue.arg(bit_cast<float>((u32)currentValue));
existingValue = existingValue.arg(std::bit_cast<float>((u32)currentValue));
//: Changing the value in a CPU register (e.g. "Change t0")
QString input = QInputDialog::getText(this, tr("Change %1").arg(m_cpu->getRegisterName(categoryIndex, m_selectedRow)), "",
@@ -360,7 +359,7 @@ bool RegisterWidget::contextFetchNewValue(u64& out, u64 currentValue, bool segme
}
else
{
out = bit_cast<u32>(input.toFloat(&ok));
out = std::bit_cast<u32>(input.toFloat(&ok));
if (!ok)
{
QMessageBox::warning(this, tr("Invalid register value"), tr("Invalid floating-point register value."));
+7 -5
View File
@@ -20,7 +20,6 @@
#include "QtHost.h"
#include "QtUtils.h"
#include "pcsx2/GS/GSIntrin.h" // _BitScanForward
#include "pcsx2/ImGui/ImGuiManager.h"
#include "common/Assertions.h"
@@ -32,6 +31,8 @@
#include <QtGui/QScreen>
#include <QtGui/QWindow>
#include <QtGui/QWindowStateChangeEvent>
#include <bit>
#include <cmath>
#if defined(_WIN32)
@@ -301,11 +302,12 @@ bool DisplayWidget::event(QEvent* event)
case QEvent::MouseButtonDblClick:
case QEvent::MouseButtonRelease:
{
unsigned long button_index;
if (_BitScanForward(&button_index, static_cast<u32>(static_cast<const QMouseEvent*>(event)->button())))
if (const u32 button_mask = static_cast<u32>(static_cast<const QMouseEvent*>(event)->button()))
{
Host::RunOnCPUThread([button_index, pressed = (event->type() != QEvent::MouseButtonRelease)]() {
InputManager::InvokeEvents(InputManager::MakePointerButtonKey(0, button_index), static_cast<float>(pressed));
Host::RunOnCPUThread([button_index = std::countr_zero(button_mask),
pressed = (event->type() != QEvent::MouseButtonRelease)]() {
InputManager::InvokeEvents(
InputManager::MakePointerButtonKey(0, button_index), static_cast<float>(pressed));
});
}
+41 -13
View File
@@ -25,6 +25,7 @@
#include "QtHost.h"
#include "QtUtils.h"
#include "SettingWidgetBinder.h"
#include "Settings/AchievementLoginDialog.h"
#include "Settings/ControllerSettingsDialog.h"
#include "Settings/GameListSettingsWidget.h"
#include "Settings/InterfaceSettingsWidget.h"
@@ -414,7 +415,7 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
connect(thread, &EmuThread::onAcquireRenderWindowRequested, this, &MainWindow::acquireRenderWindow, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onReleaseRenderWindowRequested, this, &MainWindow::releaseRenderWindow, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onResizeRenderWindowRequested, this, &MainWindow::displayResizeRequested);
connect(thread, &EmuThread::onRelativeMouseModeRequested, this, &MainWindow::relativeMouseModeRequested);
connect(thread, &EmuThread::onMouseModeRequested, this, &MainWindow::mouseModeRequested);
connect(thread, &EmuThread::onVMStarting, this, &MainWindow::onVMStarting);
connect(thread, &EmuThread::onVMStarted, this, &MainWindow::onVMStarted);
connect(thread, &EmuThread::onVMPaused, this, &MainWindow::onVMPaused);
@@ -423,6 +424,7 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
connect(thread, &EmuThread::onGameChanged, this, &MainWindow::onGameChanged);
connect(thread, &EmuThread::onCaptureStarted, this, &MainWindow::onCaptureStarted);
connect(thread, &EmuThread::onCaptureStopped, this, &MainWindow::onCaptureStopped);
connect(thread, &EmuThread::onAchievementsLoginRequested, this, &MainWindow::onAchievementsLoginRequested);
connect(m_ui.actionReset, &QAction::triggered, thread, &EmuThread::resetVM);
connect(m_ui.actionPause, &QAction::toggled, thread, &EmuThread::setVMPaused);
@@ -628,6 +630,14 @@ void MainWindow::onCaptureStopped()
m_ui.actionToolsVideoCapture->setChecked(false);
}
void MainWindow::onAchievementsLoginRequested(Achievements::LoginRequestReason reason)
{
auto lock = pauseAndLockVM();
AchievementLoginDialog dlg(this, reason);
dlg.exec();
}
void MainWindow::onSettingsTriggeredFromToolbar()
{
if (s_vm_valid)
@@ -887,7 +897,8 @@ bool MainWindow::isRenderingToMain() const
bool MainWindow::shouldHideMouseCursor() const
{
return (isRenderingFullscreen() && Host::GetBoolSettingValue("UI", "HideMouseCursor", false)) || m_relative_mouse_mode;
return ((isRenderingFullscreen() && Host::GetBoolSettingValue("UI", "HideMouseCursor", false)) ||
m_relative_mouse_mode || m_hide_mouse_cursor);
}
bool MainWindow::shouldHideMainWindow() const
@@ -1126,8 +1137,9 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
if (action->isEnabled())
{
connect(action, &QAction::triggered, [entry]() {
SettingsDialog::openGamePropertiesDialog(
entry, (entry->type != GameList::EntryType::ELF) ? std::string_view(entry->serial) : std::string_view(), entry->crc);
SettingsDialog::openGamePropertiesDialog(entry, entry->title,
(entry->type != GameList::EntryType::ELF) ? entry->serial : std::string(),
entry->crc);
});
}
@@ -1319,13 +1331,15 @@ void MainWindow::onViewGamePropertiesActionTriggered()
return;
// prefer to use a game list entry, if we have one, that way the summary is populated
if (!m_current_disc_path.isEmpty() && m_current_elf_override.isEmpty())
if (!m_current_disc_path.isEmpty() || !m_current_elf_override.isEmpty())
{
auto lock = GameList::GetLock();
const GameList::Entry* entry = GameList::GetEntryForPath(m_current_disc_path.toUtf8().constData());
const QString& path = (m_current_elf_override.isEmpty() ? m_current_disc_path : m_current_elf_override);
const GameList::Entry* entry = GameList::GetEntryForPath(path.toUtf8().constData());
if (entry)
{
SettingsDialog::openGamePropertiesDialog(entry, entry->serial, entry->crc);
SettingsDialog::openGamePropertiesDialog(
entry, entry->title, m_current_elf_override.isEmpty() ? entry->serial : std::string(), entry->crc);
return;
}
}
@@ -1339,9 +1353,15 @@ void MainWindow::onViewGamePropertiesActionTriggered()
// can't use serial for ELFs, because they might have a disc set
if (m_current_elf_override.isEmpty())
SettingsDialog::openGamePropertiesDialog(nullptr, m_current_disc_serial.toStdString(), m_current_disc_crc);
{
SettingsDialog::openGamePropertiesDialog(
nullptr, m_current_title.toStdString(), m_current_disc_serial.toStdString(), m_current_disc_crc);
}
else
SettingsDialog::openGamePropertiesDialog(nullptr, std::string_view(), m_current_disc_crc);
{
SettingsDialog::openGamePropertiesDialog(
nullptr, m_current_title.toStdString(), std::string(), m_current_disc_crc);
}
}
void MainWindow::onGitHubRepositoryActionTriggered()
@@ -1994,12 +2014,13 @@ void MainWindow::displayResizeRequested(qint32 width, qint32 height)
QtUtils::ResizePotentiallyFixedSizeWindow(this, width, height + extra_height);
}
void MainWindow::relativeMouseModeRequested(bool enabled)
void MainWindow::mouseModeRequested(bool relative_mode, bool hide_cursor)
{
if (m_relative_mouse_mode == enabled)
if (m_relative_mouse_mode == relative_mode && m_hide_mouse_cursor == hide_cursor)
return;
m_relative_mouse_mode = enabled;
m_relative_mouse_mode = relative_mode;
m_hide_mouse_cursor = hide_cursor;
if (m_display_widget && !s_vm_paused)
updateDisplayWidgetCursor();
}
@@ -2264,7 +2285,8 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
if (filename.isEmpty())
return;
if (!GameList::GetCoverImagePathForEntry(entry).empty())
const QString old_filename = QString::fromStdString(GameList::GetCoverImagePathForEntry(entry));
if (!old_filename.isEmpty())
{
if (QMessageBox::question(this, tr("Cover Already Exists"),
tr("A cover image for this game already exists, do you wish to replace it?"), QMessageBox::Yes,
@@ -2290,6 +2312,12 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
return;
}
if (!old_filename.isEmpty() && old_filename != new_filename && !QFile::remove(old_filename))
{
QMessageBox::critical(this, tr("Copy Error"), tr("Failed to remove '%1'").arg(old_filename));
return;
}
m_game_list_widget->refreshGridCovers();
}
+9 -1
View File
@@ -39,6 +39,11 @@ class ControllerSettingsDialog;
class EmuThread;
namespace Achievements
{
enum class LoginRequestReason;
}
namespace GameList
{
struct Entry;
@@ -124,7 +129,7 @@ private Q_SLOTS:
std::optional<WindowInfo> acquireRenderWindow(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
void displayResizeRequested(qint32 width, qint32 height);
void relativeMouseModeRequested(bool enabled);
void mouseModeRequested(bool relative_mode, bool hide_cursor);
void releaseRenderWindow();
void focusDisplayWidget();
@@ -186,6 +191,8 @@ private Q_SLOTS:
void onCaptureStarted(const QString& filename);
void onCaptureStopped();
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
protected:
void showEvent(QShowEvent* event) override;
void closeEvent(QCloseEvent* event) override;
@@ -293,6 +300,7 @@ private:
bool m_display_created = false;
bool m_relative_mouse_mode = false;
bool m_hide_mouse_cursor = false;
bool m_was_paused_on_surface_loss = false;
bool m_was_disc_change_request = false;
bool m_is_closing = false;
+16
View File
@@ -184,6 +184,10 @@
<property name="title">
<string>Input Recording</string>
</property>
<property name="icon">
<iconset theme="keyboard-line">
<normaloff>.</normaloff>.</iconset>
</property>
<addaction name="actionInputRecNew"/>
<addaction name="actionInputRecPlay"/>
<addaction name="actionInputRecStop"/>
@@ -863,6 +867,10 @@
<property name="text">
<string>Toggle Software Rendering</string>
</property>
<property name="icon">
<iconset theme="brush-line">
<normaloff>.</normaloff>.</iconset>
</property>
</action>
<action name="actionDebugger">
<property name="icon">
@@ -877,6 +885,10 @@
<property name="text">
<string>Reload Cheats/Patches</string>
</property>
<property name="icon">
<iconset theme="refresh-line">
<normaloff>.</normaloff>.</iconset>
</property>
</action>
<action name="actionEnableSystemConsole">
<property name="checkable">
@@ -914,6 +926,10 @@
<property name="text">
<string>Save Single Frame GS Dump</string>
</property>
<property name="icon">
<iconset theme="save-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
</action>
<action name="actionInputRecNew">
<property name="enabled">
+8 -3
View File
@@ -40,7 +40,6 @@
#include "pcsx2/Input/InputManager.h"
#include "pcsx2/LogSink.h"
#include "pcsx2/MTGS.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/SysForwardDefs.h"
#include "pcsx2/VMManager.h"
@@ -1080,6 +1079,11 @@ void Host::OnSaveStateSaved(const std::string_view& filename)
}
#ifdef ENABLE_ACHIEVEMENTS
void Host::OnAchievementsLoginRequested(Achievements::LoginRequestReason reason)
{
emit g_emu_thread->onAchievementsLoginRequested(reason);
}
void Host::OnAchievementsRefreshed()
{
u32 game_id = 0;
@@ -1469,9 +1473,9 @@ void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
emit g_emu_thread->onInputDeviceDisconnected(identifier.empty() ? QString() : QString::fromUtf8(identifier.data(), identifier.size()));
}
void Host::SetRelativeMouseMode(bool enabled)
void Host::SetMouseMode(bool relative_mode, bool hide_cursor)
{
emit g_emu_thread->onRelativeMouseModeRequested(enabled);
emit g_emu_thread->onMouseModeRequested(relative_mode, hide_cursor);
}
//////////////////////////////////////////////////////////////////////////
@@ -1779,6 +1783,7 @@ void QtHost::RegisterTypes()
qRegisterMetaType<InputBindingKey>();
qRegisterMetaType<CDVD_SourceType>();
qRegisterMetaType<const GameList::Entry*>();
qRegisterMetaType<Achievements::LoginRequestReason>();
}
bool QtHost::RunSetupWizard()
+10 -1
View File
@@ -41,11 +41,17 @@ struct VMBootParameters;
enum class CDVD_SourceType : uint8_t;
namespace Achievements
{
enum class LoginRequestReason;
}
Q_DECLARE_METATYPE(std::shared_ptr<VMBootParameters>);
Q_DECLARE_METATYPE(std::optional<bool>);
Q_DECLARE_METATYPE(GSRendererType);
Q_DECLARE_METATYPE(InputBindingKey);
Q_DECLARE_METATYPE(CDVD_SourceType);
Q_DECLARE_METATYPE(Achievements::LoginRequestReason);
class EmuThread : public QThread
{
@@ -119,7 +125,7 @@ Q_SIGNALS:
std::optional<WindowInfo> onAcquireRenderWindowRequested(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
void onResizeRenderWindowRequested(qint32 width, qint32 height);
void onReleaseRenderWindowRequested();
void onRelativeMouseModeRequested(bool enabled);
void onMouseModeRequested(bool relative_mode, bool hide_cursor);
/// Called when the VM is starting initialization, but has not been completed yet.
void onVMStarting();
@@ -155,6 +161,9 @@ Q_SIGNALS:
/// just signifies that the save has started, not necessarily completed.
void onSaveStateSaved(const QString& path);
/// Called when achievements login is requested.
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
/// Called when achievements are reloaded/refreshed (e.g. game change, login, option change).
void onAchievementsRefreshed(quint32 id, const QString& game_info_string, quint32 total, quint32 points);
+18 -1
View File
@@ -513,5 +513,22 @@ std::optional<std::string> InputManager::ConvertHostKeyboardCodeToString(u32 cod
u32 QtUtils::KeyEventToCode(const QKeyEvent* ev)
{
return static_cast<u32>(ev->key()) | (static_cast<u32>(ev->modifiers()) & static_cast<u32>(Qt::KeypadModifier));
int key = ev->key();
Qt::KeyboardModifiers modifiers = ev->modifiers();
#ifdef __APPLE__
// On macOS, Qt applies the Keypad modifier regardless of whether the arrow keys, or numpad was pressed.
// The only way to differentiate between the keypad and the arrow keys is by the text.
// Hopefully some keyboard layouts don't change the numpad positioning...
if (modifiers & Qt::KeypadModifier && key >= Qt::Key_Insert && key <= Qt::Key_PageDown)
{
if (ev->text().isEmpty())
{
// Drop the modifier, because it's probably not actually a numpad push.
modifiers &= ~Qt::KeypadModifier;
}
}
#endif
return static_cast<u32>(key) | (static_cast<u32>(modifiers) & static_cast<u32>(Qt::KeypadModifier));
}
+11 -4
View File
@@ -1078,7 +1078,10 @@ namespace SettingWidgetBinder
static inline void BindSliderToIntSetting(SettingsInterface* sif, QSlider* slider, QLabel* label, const QString& label_suffix,
std::string section, std::string key, s32 default_value)
{
const s32 global_value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value);
s32 global_value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value);
//Clamp in case setting was updated manually using INI
global_value = std::clamp(global_value, slider->minimum(), slider->maximum());
if (sif)
{
@@ -1086,7 +1089,9 @@ namespace SettingWidgetBinder
QFont bold_font(orig_font);
bold_font.setBold(true);
const s32 current_value = sif->GetOptionalIntValue(section.c_str(), key.c_str()).value_or(global_value);
s32 current_value = sif->GetOptionalIntValue(section.c_str(), key.c_str()).value_or(global_value);
current_value = std::clamp(current_value, slider->minimum(), slider->maximum());
slider->setValue(current_value);
label->setText(QStringLiteral("%1%2").arg(current_value).arg(label_suffix));
@@ -1100,8 +1105,10 @@ namespace SettingWidgetBinder
[sif, slider, label, label_suffix, orig_font = std::move(orig_font), section, key, default_value](const QPoint& pt) {
QMenu menu(slider);
slider->connect(menu.addAction(qApp->translate("SettingWidgetBinder", "Reset")), &QAction::triggered, slider,
[sif, label, label_suffix, orig_font, section, key, default_value]() {
const s32 global_value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value);
[sif, slider, label, label_suffix, orig_font, section, key, default_value]() {
s32 global_value = Host::GetBaseIntSettingValue(section.c_str(), key.c_str(), default_value);
global_value = std::clamp(global_value, slider->minimum(), slider->maximum());
label->setText(QStringLiteral("%1%2").arg(global_value).arg(label_suffix));
label->setFont(orig_font);
+10 -1
View File
@@ -22,13 +22,22 @@
#include <QtWidgets/QMessageBox>
AchievementLoginDialog::AchievementLoginDialog(QWidget* parent)
AchievementLoginDialog::AchievementLoginDialog(QWidget* parent, Achievements::LoginRequestReason reason)
: QDialog(parent)
{
m_ui.setupUi(this);
m_ui.loginIcon->setPixmap(QIcon::fromTheme("login-box-line").pixmap(32));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
// Adjust text if needed based on reason.
if (reason == Achievements::LoginRequestReason::TokenInvalid)
{
m_ui.instructionText->setText(
tr("<strong>Your RetroAchievements login token is no longer valid.</strong> You must re-enter your "
"credentials for achievements to be tracked. Your password will not be saved in PCSX2, an access token "
"will be generated and used instead."));
}
m_login = m_ui.buttonBox->addButton(tr("&Login"), QDialogButtonBox::AcceptRole);
m_login->setEnabled(false);
connectUi();
+7 -1
View File
@@ -18,12 +18,17 @@
#include <QtWidgets/QDialog>
#include <QtWidgets/QPushButton>
namespace Achievements
{
enum class LoginRequestReason;
}
class AchievementLoginDialog : public QDialog
{
Q_OBJECT
public:
AchievementLoginDialog(QWidget* parent);
AchievementLoginDialog(QWidget* parent, Achievements::LoginRequestReason reason);
~AchievementLoginDialog();
private Q_SLOTS:
@@ -38,4 +43,5 @@ private:
Ui::AchievementLoginDialog m_ui;
QPushButton* m_login;
Achievements::LoginRequestReason m_reason;
};
+1 -1
View File
@@ -51,7 +51,7 @@
</layout>
</item>
<item>
<widget class="QLabel" name="label_3">
<widget class="QLabel" name="instructionText">
<property name="text">
<string>Please enter user name and password for retroachievements.org below. Your password will not be saved in PCSX2, an access token will be generated and used instead.</string>
</property>
@@ -30,6 +30,8 @@
#include <QtCore/QDateTime>
#include <QtWidgets/QMessageBox>
static constexpr s32 DEFAULT_NOTIFICATIONS_DURATION = 5;
AchievementSettingsWidget::AchievementSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
, m_dialog(dialog)
@@ -48,6 +50,9 @@ AchievementSettingsWidget::AchievementSettingsWidget(SettingsDialog* dialog, QWi
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.soundEffects, "Achievements", "SoundEffects", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.primedIndicators, "Achievements", "PrimedIndicators", true);
SettingWidgetBinder::BindSliderToIntSetting(sif, m_ui.notifications_duration, m_ui.notifications_duration_seconds,
tr(" seconds"), "Achievements", "NotificationsDuration", DEFAULT_NOTIFICATIONS_DURATION);
dialog->registerWidgetHelp(m_ui.enable, tr("Enable Achievements"), tr("Unchecked"),
tr("When enabled and logged in, PCSX2 will scan for achievements on game load."));
dialog->registerWidgetHelp(m_ui.testMode, tr("Enable Test Mode"), tr("Unchecked"),
@@ -70,10 +75,18 @@ AchievementSettingsWidget::AchievementSettingsWidget(SettingsDialog* dialog, QWi
dialog->registerWidgetHelp(m_ui.primedIndicators, tr("Show Challenge Indicators"), tr("Checked"),
tr("Shows icons in the lower-right corner of the screen when a challenge/primed achievement is active."));
dialog->registerWidgetHelp(m_ui.notifications_duration, tr("Notification Duration"),
tr("5 seconds"), tr("The duration, in seconds, an achievement popup notification will remain on screen."));
dialog->registerWidgetHelp(m_ui.notifications_duration_label, tr("Notification Duration"),
tr("5 seconds"), tr("The duration, in seconds, an achievement popup notification will remain on screen."));
dialog->registerWidgetHelp(m_ui.notifications_duration_seconds, tr("Notification Duration"),
tr("5 seconds"), tr("The duration, in seconds, an achievement popup notification will remain on screen."));
connect(m_ui.enable, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
connect(m_ui.notifications, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
connect(m_ui.challengeMode, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::updateEnableState);
connect(m_ui.challengeMode, &QCheckBox::stateChanged, this, &AchievementSettingsWidget::onChallengeModeStateChanged);
connect(m_ui.notifications_duration, &QSlider::valueChanged, this, &AchievementSettingsWidget::onNotificationsDurationChanged);
if (!m_dialog->isPerGameSettings())
{
@@ -105,6 +118,8 @@ void AchievementSettingsWidget::updateEnableState()
{
const bool enabled = m_dialog->getEffectiveBoolValue("Achievements", "Enabled", false);
const bool challenge = m_dialog->getEffectiveBoolValue("Achievements", "ChallengeMode", false);
const bool notifications = m_dialog->getEffectiveBoolValue("Achievements", "Notifications", true);
m_ui.testMode->setEnabled(enabled);
m_ui.unofficialTestMode->setEnabled(enabled);
m_ui.richPresence->setEnabled(enabled);
@@ -113,6 +128,10 @@ void AchievementSettingsWidget::updateEnableState()
m_ui.notifications->setEnabled(enabled);
m_ui.soundEffects->setEnabled(enabled);
m_ui.primedIndicators->setEnabled(enabled);
m_ui.notifications_duration->setEnabled(enabled && notifications);
m_ui.notifications_duration_label->setEnabled(enabled && notifications);
m_ui.notifications_duration_seconds->setEnabled(enabled && notifications);
}
void AchievementSettingsWidget::onChallengeModeStateChanged()
@@ -173,7 +192,7 @@ void AchievementSettingsWidget::onLoginLogoutPressed()
return;
}
AchievementLoginDialog login(this);
AchievementLoginDialog login(this, Achievements::LoginRequestReason::UserInitiated);
int res = login.exec();
if (res != 0)
return;
@@ -196,3 +215,9 @@ void AchievementSettingsWidget::onAchievementsRefreshed(quint32 id, const QStrin
{
m_ui.gameInfo->setText(game_info_string);
}
void AchievementSettingsWidget::onNotificationsDurationChanged()
{
m_ui.notifications_duration_seconds->setText(tr("%1 seconds")
.arg(m_ui.notifications_duration->value()));
}
@@ -33,6 +33,7 @@ private Q_SLOTS:
void onLoginLogoutPressed();
void onViewProfilePressed();
void onAchievementsRefreshed(quint32 id, const QString& game_info_string, quint32 total, quint32 points);
void onNotificationsDurationChanged();
private:
void updateLoginState();
+83 -16
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>658</width>
<height>496</height>
<width>829</width>
<height>641</height>
</rect>
</property>
<property name="windowTitle">
@@ -39,13 +39,6 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="primedIndicators">
<property name="text">
<string>Show Challenge Indicators</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="richPresence">
<property name="text">
@@ -74,13 +67,6 @@
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="testMode">
<property name="text">
<string>Enable Test Mode</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="soundEffects">
<property name="text">
@@ -89,12 +75,93 @@
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="primedIndicators">
<property name="text">
<string>Show Challenge Indicators</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="testMode">
<property name="text">
<string>Enable Test Mode</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="notificationBox">
<property name="title">
<string>Notifications</string>
</property>
<layout class="QVBoxLayout" name="notifications_box_layout" stretch="0,0">
<item>
<widget class="QCheckBox" name="notifications">
<property name="text">
<string>Show Notifications</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="notifications_duration_layout" stretch="0,0,0">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="notifications_duration_label">
<property name="text">
<string>Duration</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="notifications_duration">
<property name="minimum">
<number>3</number>
</property>
<property name="maximum">
<number>10</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>5</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>1</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="notifications_duration_seconds">
<property name="text">
<string>5 seconds</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
@@ -0,0 +1,317 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ControllerBindingWidget_Guitar</class>
<widget class="QWidget" name="ControllerBindingWidget_Guitar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1100</width>
<height>500</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1101</width>
<height>322</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="maximumSize">
<size>
<width>800</width>
<height>320</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../resources/resources.qrc">:/images/guitar.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>320</y>
<width>1101</width>
<height>181</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="6">
<widget class="QGroupBox" name="groupBox_7">
<property name="title">
<string>Yellow</string>
</property>
<widget class="InputBindingWidget" name="Yellow">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Start</string>
</property>
<widget class="InputBindingWidget" name="Start">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="7">
<widget class="QGroupBox" name="groupBox_8">
<property name="title">
<string>Red</string>
</property>
<widget class="InputBindingWidget" name="Red">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="8">
<widget class="QGroupBox" name="groupBox_9">
<property name="title">
<string>Green</string>
</property>
<widget class="InputBindingWidget" name="Green">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="3">
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Orange</string>
</property>
<widget class="InputBindingWidget" name="Orange">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Select</string>
</property>
<widget class="InputBindingWidget" name="Select">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Strum Up</string>
</property>
<widget class="InputBindingWidget" name="Up">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="1" column="2">
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Strum Down</string>
</property>
<widget class="InputBindingWidget" name="Down">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="5">
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Blue</string>
</property>
<widget class="InputBindingWidget" name="Blue">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_10">
<property name="title">
<string>Whammy Bar</string>
</property>
<widget class="InputBindingWidget" name="Whammy">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="groupBox_11">
<property name="title">
<string>Tilt</string>
</property>
<widget class="InputBindingWidget" name="Tilt">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>InputBindingWidget</class>
<extends>QPushButton</extends>
<header>Settings/InputBindingWidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../resources/resources.qrc"/>
</resources>
<connections/>
</ui>
+78 -30
View File
@@ -26,7 +26,7 @@
#include "common/StringUtil.h"
#include "pcsx2/Host.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/SIO/Pad/Pad.h"
#include "Settings/ControllerBindingWidgets.h"
#include "Settings/ControllerSettingsDialog.h"
@@ -38,6 +38,7 @@
#include "ui_USBBindingWidget_DrivingForce.h"
#include "ui_USBBindingWidget_GTForce.h"
#include "ui_USBBindingWidget_GunCon2.h"
ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSettingsDialog* dialog, u32 port)
: QWidget(parent)
@@ -51,8 +52,8 @@ ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSett
populateControllerTypes();
onTypeChanged();
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(
m_dialog->getProfileSettingsInterface(), m_ui.controllerType, m_config_section, "Type", PAD::GetDefaultPadType(port));
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(m_dialog->getProfileSettingsInterface(),
m_ui.controllerType, m_config_section, "Type", Pad::GetControllerInfo(Pad::GetDefaultPadType(port))->name);
connect(m_ui.controllerType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ControllerBindingWidget::onTypeChanged);
connect(m_ui.bindings, &QPushButton::clicked, this, &ControllerBindingWidget::onBindingsClicked);
@@ -71,14 +72,22 @@ QIcon ControllerBindingWidget::getIcon() const
void ControllerBindingWidget::populateControllerTypes()
{
for (const auto& [name, display_name] : PAD::GetControllerTypeNames())
m_ui.controllerType->addItem(qApp->translate("Pad", display_name), QString::fromStdString(name));
for (const auto& [name, display_name] : Pad::GetControllerTypeNames())
m_ui.controllerType->addItem(QString::fromUtf8(display_name), QString::fromUtf8(name));
}
void ControllerBindingWidget::onTypeChanged()
{
const bool is_initializing = (m_ui.stackedWidget->count() == 0);
m_controller_type = m_dialog->getStringValue(m_config_section.c_str(), "Type", PAD::GetDefaultPadType(m_port_number));
const std::string type_name = m_dialog->getStringValue(
m_config_section.c_str(), "Type", Pad::GetControllerInfo(Pad::GetDefaultPadType(m_port_number))->name);
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfoByName(type_name);
if (!cinfo)
{
Console.Error(fmt::format("Invalid controller type name '{}' in config, ignoring.", type_name));
cinfo = Pad::GetControllerInfo(Pad::ControllerType::NotConnected);
}
m_controller_type = cinfo->type;
if (m_bindings_widget)
{
@@ -99,25 +108,31 @@ void ControllerBindingWidget::onTypeChanged()
m_macros_widget = nullptr;
}
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(m_controller_type);
const bool has_settings = (cinfo && cinfo->num_settings > 0);
const bool has_macros = (cinfo && cinfo->num_bindings > 0);
const bool has_settings = (!cinfo->settings.empty());
const bool has_macros = (!cinfo->bindings.empty());
m_ui.settings->setEnabled(has_settings);
m_ui.macros->setEnabled(has_macros);
if (m_controller_type == "DualShock2")
if (cinfo->type == Pad::ControllerType::DualShock2)
{
m_bindings_widget = ControllerBindingWidget_DualShock2::createInstance(this);
}
else if (cinfo->type == Pad::ControllerType::Guitar)
{
m_bindings_widget = ControllerBindingWidget_Guitar::createInstance(this);
}
else
{
m_bindings_widget = new ControllerBindingWidget_Base(this);
}
m_ui.stackedWidget->addWidget(m_bindings_widget);
m_ui.stackedWidget->setCurrentWidget(m_bindings_widget);
if (has_settings)
{
const std::span<const SettingInfo> settings(cinfo->settings, cinfo->num_settings);
m_settings_widget = new ControllerCustomSettingsWidget(
settings, m_config_section, std::string(), "Pad", getDialog(), m_ui.stackedWidget);
cinfo->settings, m_config_section, std::string(), "Pad", getDialog(), m_ui.stackedWidget);
m_ui.stackedWidget->addWidget(m_settings_widget);
}
@@ -210,13 +225,13 @@ void ControllerBindingWidget::onClearBindingsClicked()
{
{
auto lock = Host::GetSettingsLock();
PAD::ClearPortBindings(*Host::Internal::GetBaseSettingsLayer(), m_port_number);
Pad::ClearPortBindings(*Host::Internal::GetBaseSettingsLayer(), m_port_number);
}
Host::CommitBaseSettingChanges();
}
else
{
PAD::ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number);
Pad::ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number);
m_dialog->getProfileSettingsInterface()->Save();
}
@@ -240,14 +255,14 @@ void ControllerBindingWidget::doDeviceAutomaticBinding(const QString& device)
{
{
auto lock = Host::GetSettingsLock();
result = PAD::MapController(*Host::Internal::GetBaseSettingsLayer(), m_port_number, mapping);
result = Pad::MapController(*Host::Internal::GetBaseSettingsLayer(), m_port_number, mapping);
}
if (result)
Host::CommitBaseSettingChanges();
}
else
{
result = PAD::MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping);
result = Pad::MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping);
if (result)
{
m_dialog->getProfileSettingsInterface()->Save();
@@ -312,7 +327,7 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare
ControllerSettingsDialog* dialog = m_bwidget->getDialog();
const std::string& section = m_bwidget->getConfigSection();
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(m_bwidget->getControllerType());
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_bwidget->getControllerType());
if (!cinfo)
{
// Shouldn't ever happen.
@@ -325,20 +340,19 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare
for (const std::string_view& button : buttons_split)
{
for (u32 i = 0; i < cinfo->num_bindings; i++)
for (const InputBindingInfo& bi : cinfo->bindings)
{
if (button == cinfo->bindings[i].name)
if (button == bi.name)
{
m_binds.push_back(&cinfo->bindings[i]);
m_binds.push_back(&bi);
break;
}
}
}
// populate list view
for (u32 i = 0; i < cinfo->num_bindings; i++)
for (const InputBindingInfo& bi : cinfo->bindings)
{
const InputBindingInfo& bi = cinfo->bindings[i];
if (bi.bind_type == InputBindingInfo::Type::Motor)
continue;
@@ -350,8 +364,12 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare
ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(
dialog->getProfileSettingsInterface(), m_ui.pressure, section, fmt::format("Macro{}Pressure", index + 1u), 100.0f, 1.0f);
ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(
dialog->getProfileSettingsInterface(), m_ui.deadzone, section, fmt::format("Macro{}Deadzone", index + 1u), 100.0f, 0.0f);
connect(m_ui.pressure, &QSlider::valueChanged, this, &ControllerMacroEditWidget::onPressureChanged);
connect(m_ui.deadzone, &QSlider::valueChanged, this, &ControllerMacroEditWidget::onDeadzoneChanged);
onPressureChanged();
onDeadzoneChanged();
m_frequency = dialog->getIntValue(section.c_str(), fmt::format("Macro{}Frequency", index + 1u).c_str(), 0);
updateFrequencyText();
@@ -384,6 +402,11 @@ void ControllerMacroEditWidget::onPressureChanged()
m_ui.pressureValue->setText(tr("%1%").arg(m_ui.pressure->value()));
}
void ControllerMacroEditWidget::onDeadzoneChanged()
{
m_ui.deadzoneValue->setText(tr("%1%").arg(m_ui.deadzone->value()));
}
void ControllerMacroEditWidget::onSetFrequencyClicked()
{
bool okay;
@@ -423,12 +446,12 @@ void ControllerMacroEditWidget::updateFrequencyText()
void ControllerMacroEditWidget::updateBinds()
{
ControllerSettingsDialog* dialog = m_bwidget->getDialog();
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(m_bwidget->getControllerType());
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_bwidget->getControllerType());
if (!cinfo)
return;
std::vector<const InputBindingInfo*> new_binds;
for (u32 i = 0, bind_index = 0; i < cinfo->num_bindings; i++)
for (u32 i = 0, bind_index = 0; i < static_cast<u32>(cinfo->bindings.size()); i++)
{
const InputBindingInfo& bi = cinfo->bindings[i];
if (bi.bind_type == InputBindingInfo::Type::Motor)
@@ -793,16 +816,15 @@ QIcon ControllerBindingWidget_Base::getIcon() const
void ControllerBindingWidget_Base::initBindingWidgets()
{
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(getControllerType());
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(getControllerType());
if (!cinfo)
return;
const std::string& config_section = getConfigSection();
SettingsInterface* sif = getDialog()->getProfileSettingsInterface();
for (u32 i = 0; i < cinfo->num_bindings; i++)
for (const InputBindingInfo& bi : cinfo->bindings)
{
const InputBindingInfo& bi = cinfo->bindings[i];
if (bi.bind_type == InputBindingInfo::Type::Axis || bi.bind_type == InputBindingInfo::Type::HalfAxis ||
bi.bind_type == InputBindingInfo::Type::Button || bi.bind_type == InputBindingInfo::Type::Pointer ||
bi.bind_type == InputBindingInfo::Type::Device)
@@ -820,7 +842,7 @@ void ControllerBindingWidget_Base::initBindingWidgets()
switch (cinfo->vibration_caps)
{
case PAD::VibrationCapabilities::LargeSmallMotors:
case Pad::VibrationCapabilities::LargeSmallMotors:
{
InputVibrationBindingWidget* widget = findChild<InputVibrationBindingWidget*>(QStringLiteral("LargeMotor"));
if (widget)
@@ -832,7 +854,7 @@ void ControllerBindingWidget_Base::initBindingWidgets()
}
break;
case PAD::VibrationCapabilities::SingleMotor:
case Pad::VibrationCapabilities::SingleMotor:
{
InputVibrationBindingWidget* widget = findChild<InputVibrationBindingWidget*>(QStringLiteral("Motor"));
if (widget)
@@ -840,7 +862,7 @@ void ControllerBindingWidget_Base::initBindingWidgets()
}
break;
case PAD::VibrationCapabilities::NoVibration:
case Pad::VibrationCapabilities::NoVibration:
default:
break;
}
@@ -867,6 +889,27 @@ ControllerBindingWidget_Base* ControllerBindingWidget_DualShock2::createInstance
return new ControllerBindingWidget_DualShock2(parent);
}
ControllerBindingWidget_Guitar::ControllerBindingWidget_Guitar(ControllerBindingWidget* parent)
: ControllerBindingWidget_Base(parent)
{
m_ui.setupUi(this);
initBindingWidgets();
}
ControllerBindingWidget_Guitar::~ControllerBindingWidget_Guitar()
{
}
QIcon ControllerBindingWidget_Guitar::getIcon() const
{
return QIcon::fromTheme("guitar-line");
}
ControllerBindingWidget_Base* ControllerBindingWidget_Guitar::createInstance(ControllerBindingWidget* parent)
{
return new ControllerBindingWidget_Guitar(parent);
}
//////////////////////////////////////////////////////////////////////////
USBDeviceWidget::USBDeviceWidget(QWidget* parent, ControllerSettingsDialog* dialog, u32 port)
@@ -1240,6 +1283,11 @@ USBBindingWidget* USBBindingWidget::createInstance(
has_template = true;
}
}
else if (type == "guncon2")
{
Ui::USBBindingWidget_GunCon2().setupUi(widget);
has_template = true;
}
if (has_template)
widget->bindWidgets(bindings);
+23 -5
View File
@@ -15,7 +15,7 @@
#pragma once
#include "PAD/Host/PAD.h"
#include "pcsx2/SIO/Pad/PadTypes.h"
#include <QtWidgets/QWidget>
@@ -23,6 +23,7 @@
#include "ui_ControllerBindingWidget.h"
#include "ui_ControllerBindingWidget_DualShock2.h"
#include "ui_ControllerBindingWidget_Guitar.h"
#include "ui_ControllerMacroWidget.h"
#include "ui_ControllerMacroEditWidget.h"
#include "ui_USBDeviceWidget.h"
@@ -48,7 +49,7 @@ public:
__fi ControllerSettingsDialog* getDialog() const { return m_dialog; }
__fi const std::string& getConfigSection() const { return m_config_section; }
__fi const std::string& getControllerType() const { return m_controller_type; }
__fi Pad::ControllerType getControllerType() const { return m_controller_type; }
__fi u32 getPortNumber() const { return m_port_number; }
private Q_SLOTS:
@@ -69,7 +70,7 @@ private:
ControllerSettingsDialog* m_dialog;
std::string m_config_section;
std::string m_controller_type;
Pad::ControllerType m_controller_type;
u32 m_port_number;
ControllerBindingWidget_Base* m_bindings_widget = nullptr;
@@ -91,7 +92,7 @@ public:
void updateListItem(u32 index);
private:
static constexpr u32 NUM_MACROS = PAD::NUM_MACRO_BUTTONS_PER_CONTROLLER;
static constexpr u32 NUM_MACROS = Pad::NUM_MACRO_BUTTONS_PER_CONTROLLER;
void createWidgets(ControllerBindingWidget* parent);
@@ -114,6 +115,7 @@ public:
private Q_SLOTS:
void onPressureChanged();
void onDeadzoneChanged();
void onSetFrequencyClicked();
void updateBinds();
@@ -168,7 +170,7 @@ public:
__fi ControllerSettingsDialog* getDialog() const { return static_cast<ControllerBindingWidget*>(parent())->getDialog(); }
__fi const std::string& getConfigSection() const { return static_cast<ControllerBindingWidget*>(parent())->getConfigSection(); }
__fi const std::string& getControllerType() const { return static_cast<ControllerBindingWidget*>(parent())->getControllerType(); }
__fi Pad::ControllerType getControllerType() const { return static_cast<ControllerBindingWidget*>(parent())->getControllerType(); }
__fi u32 getPortNumber() const { return static_cast<ControllerBindingWidget*>(parent())->getPortNumber(); }
virtual QIcon getIcon() const;
@@ -193,6 +195,22 @@ private:
Ui::ControllerBindingWidget_DualShock2 m_ui;
};
class ControllerBindingWidget_Guitar final : public ControllerBindingWidget_Base
{
Q_OBJECT
public:
ControllerBindingWidget_Guitar(ControllerBindingWidget* parent);
~ControllerBindingWidget_Guitar();
QIcon getIcon() const override;
static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent);
private:
Ui::ControllerBindingWidget_Guitar m_ui;
};
//////////////////////////////////////////////////////////////////////////
class USBDeviceWidget final : public QWidget
+44 -1
View File
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>691</width>
<height>547</height>
<height>433</height>
</rect>
</property>
<property name="windowTitle">
@@ -83,6 +83,9 @@
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item>
@@ -123,6 +126,46 @@
</property>
</widget>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="deadzoneLayout" stretch="0,1,0">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Deadzone:</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="deadzone">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="deadzoneValue">
<property name="text">
<string>100%</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
+10 -10
View File
@@ -22,8 +22,8 @@
#include "Settings/HotkeySettingsWidget.h"
#include "pcsx2/INISettingsInterface.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/Sio.h"
#include "pcsx2/SIO/Pad/Pad.h"
#include "pcsx2/SIO/Sio.h"
#include "pcsx2/VMManager.h"
#include "common/Assertions.h"
@@ -130,7 +130,7 @@ void ControllerSettingsDialog::onNewProfileClicked()
{
// from global
auto lock = Host::GetSettingsLock();
PAD::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true, false);
Pad::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true, false);
USB::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true);
}
else
@@ -138,7 +138,7 @@ void ControllerSettingsDialog::onNewProfileClicked()
// from profile
const bool copy_hotkey_bindings = m_profile_interface->GetBoolValue("Pad", "UseProfileHotkeyBindings", false);
temp_si.SetBoolValue("Pad", "UseProfileHotkeyBindings", copy_hotkey_bindings);
PAD::CopyConfiguration(&temp_si, *m_profile_interface, true, true, copy_hotkey_bindings);
Pad::CopyConfiguration(&temp_si, *m_profile_interface, true, true, copy_hotkey_bindings);
USB::CopyConfiguration(&temp_si, *m_profile_interface, true, true);
}
}
@@ -167,7 +167,7 @@ void ControllerSettingsDialog::onLoadProfileClicked()
{
auto lock = Host::GetSettingsLock();
PAD::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false);
Pad::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false);
USB::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true);
}
Host::CommitBaseSettingChanges();
@@ -403,8 +403,8 @@ void ControllerSettingsDialog::createWidgets()
m_port_bindings[global_slot] = new ControllerBindingWidget(m_ui.settingsContainer, this, global_slot);
m_ui.settingsContainer->addWidget(m_port_bindings[global_slot]);
const PAD::ControllerInfo* ci = PAD::GetControllerInfo(m_port_bindings[global_slot]->getControllerType());
const QString display_name(ci ? qApp->translate("Pad", ci->display_name) : QStringLiteral("Unknown"));
const Pad::ControllerInfo* ci = Pad::GetControllerInfo(m_port_bindings[global_slot]->getControllerType());
const QString display_name(QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown"));
QListWidgetItem* item = new QListWidgetItem();
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
@@ -459,8 +459,8 @@ void ControllerSettingsDialog::updateListDescription(u32 global_slot, Controller
const auto [port, slot] = sioConvertPadToPortAndSlot(global_slot);
const bool mtap_enabled = getBoolValue("Pad", (port == 0) ? "MultitapPort1" : "MultitapPort2", false);
const PAD::ControllerInfo* ci = PAD::GetControllerInfo(widget->getControllerType());
const QString display_name(ci ? qApp->translate("Pad", ci->display_name) : QStringLiteral("Unknown"));
const Pad::ControllerInfo* ci = Pad::GetControllerInfo(widget->getControllerType());
const QString display_name = QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown");
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
item->setText(mtap_enabled ? (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name)) :
@@ -492,7 +492,7 @@ void ControllerSettingsDialog::updateListDescription(u32 port, USBDeviceWidget*
void ControllerSettingsDialog::refreshProfileList()
{
const std::vector<std::string> names(PAD::GetInputProfileNames());
const std::vector<std::string> names = Pad::GetInputProfileNames();
QSignalBlocker sb(m_ui.currentProfile);
m_ui.currentProfile->clear();
@@ -27,10 +27,8 @@
#include "common/HeterogeneousContainers.h"
GameCheatSettingsWidget::GameCheatSettingsWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent)
GameCheatSettingsWidget::GameCheatSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: m_dialog(dialog)
, m_serial(entry->serial)
, m_crc(entry->crc)
{
m_ui.setupUi(this);
QtUtils::ResizeColumnsForTreeView(m_ui.cheatList, {300, 100, -1});
@@ -154,7 +152,7 @@ void GameCheatSettingsWidget::setStateRecursively(QTreeWidgetItem* parent, bool
void GameCheatSettingsWidget::reloadList()
{
u32 num_unlabelled_codes = 0;
m_patches = Patch::GetPatchInfo(m_serial, m_crc, true, &num_unlabelled_codes);
m_patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), true, &num_unlabelled_codes);
m_enabled_patches =
m_dialog->getSettingsInterface()->GetStringList(Patch::CHEATS_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY);
@@ -194,7 +192,7 @@ QTreeWidgetItem* GameCheatSettingsWidget::getTreeWidgetParent(const std::string_
if (parent.empty())
return nullptr;
auto it = UnorderedStringMapFind(m_parent_map, parent);
auto it = m_parent_map.find(parent);
if (it != m_parent_map.end())
return it->second;
+1 -4
View File
@@ -39,7 +39,7 @@ class GameCheatSettingsWidget : public QWidget
Q_OBJECT
public:
GameCheatSettingsWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent);
GameCheatSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~GameCheatSettingsWidget();
private Q_SLOTS:
@@ -59,9 +59,6 @@ private:
Ui::GameCheatSettingsWidget m_ui;
SettingsDialog* m_dialog;
std::string m_serial;
u32 m_crc;
UnorderedStringMap<QTreeWidgetItem*> m_parent_map;
std::vector<Patch::PatchInfo> m_patches;
std::vector<std::string> m_enabled_patches;
+13 -1
View File
@@ -51,6 +51,7 @@ GameListSettingsWidget::GameListSettingsWidget(SettingsDialog* dialog, QWidget*
&GameListSettingsWidget::onAddSearchDirectoryButtonClicked);
connect(m_ui.removeSearchDirectoryButton, &QPushButton::clicked, this,
&GameListSettingsWidget::onRemoveSearchDirectoryButtonClicked);
connect(m_ui.addExcludedFile, &QPushButton::clicked, this, &GameListSettingsWidget::onAddExcludedFileButtonClicked);
connect(m_ui.addExcludedPath, &QPushButton::clicked, this, &GameListSettingsWidget::onAddExcludedPathButtonClicked);
connect(m_ui.removeExcludedPath, &QPushButton::clicked, this,
&GameListSettingsWidget::onRemoveExcludedPathButtonClicked);
@@ -215,10 +216,21 @@ void GameListSettingsWidget::onRemoveSearchDirectoryButtonClicked()
delete item;
}
void GameListSettingsWidget::onAddExcludedFileButtonClicked()
{
QString path =
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("Select File")));
if (path.isEmpty())
return;
addExcludedPath(path.toStdString());
}
void GameListSettingsWidget::onAddExcludedPathButtonClicked()
{
QString path =
QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(this), tr("Select Path")));
QDir::toNativeSeparators(QFileDialog::getExistingDirectory(QtUtils::GetRootWidget(this), tr("Select Directory")));
if (path.isEmpty())
return;
@@ -39,6 +39,7 @@ private Q_SLOTS:
void onDirectoryListContextMenuRequested(const QPoint& point);
void onAddSearchDirectoryButtonClicked();
void onRemoveSearchDirectoryButtonClicked();
void onAddExcludedFileButtonClicked();
void onAddExcludedPathButtonClicked();
void onRemoveExcludedPathButtonClicked();
void onScanForNewGamesClicked();
+34 -2
View File
@@ -57,12 +57,15 @@
</sizepolicy>
</property>
<property name="text">
<string>Add</string>
<string>Add...</string>
</property>
<property name="icon">
<iconset theme="folder-add-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
</widget>
</item>
<item>
@@ -80,6 +83,9 @@
<iconset theme="folder-reduce-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
</widget>
</item>
</layout>
@@ -129,12 +135,35 @@
</sizepolicy>
</property>
<property name="text">
<string>Add</string>
<string>Directory...</string>
</property>
<property name="icon">
<iconset theme="folder-add-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="addExcludedFile">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>File...</string>
</property>
<property name="icon">
<iconset theme="file-add-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
</widget>
</item>
<item>
@@ -152,6 +181,9 @@
<iconset theme="file-reduce-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
</widget>
</item>
</layout>
@@ -59,10 +59,8 @@ void GamePatchDetailsWidget::onEnabledStateChanged(int state)
g_emu_thread->reloadGameSettings();
}
GamePatchSettingsWidget::GamePatchSettingsWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent)
GamePatchSettingsWidget::GamePatchSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: m_dialog(dialog)
, m_serial(entry->serial)
, m_crc(entry->crc)
{
m_ui.setupUi(this);
m_ui.scrollArea->setFrameShape(QFrame::WinPanel);
@@ -86,7 +84,7 @@ void GamePatchSettingsWidget::onReloadClicked()
void GamePatchSettingsWidget::reloadList()
{
// Patches shouldn't have any unlabelled patch groups, because they're new.
std::vector<Patch::PatchInfo> patches = Patch::GetPatchInfo(m_serial, m_crc, false, nullptr);
std::vector<Patch::PatchInfo> patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), false, nullptr);
std::vector<std::string> enabled_list =
m_dialog->getSettingsInterface()->GetStringList(Patch::PATCHES_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY);
+1 -4
View File
@@ -52,7 +52,7 @@ class GamePatchSettingsWidget : public QWidget
Q_OBJECT
public:
GamePatchSettingsWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent);
GamePatchSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~GamePatchSettingsWidget();
private Q_SLOTS:
@@ -63,7 +63,4 @@ private:
Ui::GamePatchSettingsWidget m_ui;
SettingsDialog* m_dialog;
std::string m_serial;
u32 m_crc;
};
+269 -8
View File
@@ -15,21 +15,28 @@
#include "PrecompiledHeader.h"
#include "pcsx2/SIO/Pad/Pad.h"
#include "GameSummaryWidget.h"
#include "SettingsDialog.h"
#include "MainWindow.h"
#include "QtHost.h"
#include "QtProgressCallback.h"
#include "QtUtils.h"
#include "pcsx2/CDVD/IsoHasher.h"
#include "pcsx2/GameDatabase.h"
#include "pcsx2/GameList.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "common/Error.h"
#include "common/MD5Digest.h"
#include "common/ScopedGuard.h"
#include "common/StringUtil.h"
#include "fmt/format.h"
#include <QtCore/QDir>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QMessageBox>
GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent)
: m_dialog(dialog)
@@ -51,15 +58,23 @@ GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsDialo
populateInputProfiles();
populateDetails(entry);
populateDiscPath(entry);
populateTrackList(entry);
connect(m_ui.inputProfile, &QComboBox::currentIndexChanged, this, &GameSummaryWidget::onInputProfileChanged);
connect(m_ui.verify, &QAbstractButton::clicked, this, &GameSummaryWidget::onVerifyClicked);
connect(m_ui.searchHash, &QAbstractButton::clicked, this, &GameSummaryWidget::onSearchHashClicked);
bool has_custom_title = false, has_custom_region = false;
GameList::CheckCustomAttributesForPath(m_entry_path, has_custom_title, has_custom_region);
m_ui.restoreTitle->setEnabled(has_custom_title);
m_ui.restoreRegion->setEnabled(has_custom_region);
}
GameSummaryWidget::~GameSummaryWidget() = default;
void GameSummaryWidget::populateInputProfiles()
{
for (const std::string& name : PAD::GetInputProfileNames())
for (const std::string& name : Pad::GetInputProfileNames())
m_ui.inputProfile->addItem(QString::fromStdString(name));
}
@@ -78,6 +93,24 @@ void GameSummaryWidget::populateDetails(const GameList::Entry* entry)
m_ui.inputProfile->setCurrentIndex(m_ui.inputProfile->findText(QString::fromStdString(profile.value())));
else
m_ui.inputProfile->setCurrentIndex(0);
connect(m_ui.title, &QLineEdit::editingFinished, this, [this]() {
if (m_ui.title->isModified())
{
setCustomTitle(m_ui.title->text().toStdString());
m_ui.title->setModified(false);
}
});
connect(m_ui.restoreTitle, &QAbstractButton::clicked, this, [this]() {
setCustomTitle("");
});
connect(m_ui.region, &QComboBox::currentIndexChanged, this, [this](int index) {
setCustomRegion(index);
});
connect(m_ui.restoreRegion, &QAbstractButton::clicked, this, [this]() {
setCustomRegion(-1);
});
}
void GameSummaryWidget::populateDiscPath(const GameList::Entry* entry)
@@ -119,12 +152,7 @@ void GameSummaryWidget::onDiscPathChanged(const QString& value)
// force rescan of elf to update the serial
g_main_window->rescanFile(m_entry_path);
// and re-fill our details (mainly the serial)
auto lock = GameList::GetLock();
const GameList::Entry* entry = GameList::GetEntryForPath(m_entry_path.c_str());
if (entry)
populateDetails(entry);
repopulateCurrentDetails();
}
void GameSummaryWidget::onDiscPathBrowseClicked()
@@ -137,3 +165,236 @@ void GameSummaryWidget::onDiscPathBrowseClicked()
// let the signal take care of it
m_ui.discPath->setText(QDir::toNativeSeparators(filename));
}
void GameSummaryWidget::populateTrackList(const GameList::Entry* entry)
{
if (entry->type != GameList::EntryType::PS1Disc && entry->type != GameList::EntryType::PS2Disc)
{
m_ui.verify->setEnabled(false);
m_ui.verifyResult->setPlainText(tr("Game is not a CD/DVD."));
return;
}
if (QtHost::IsVMValid())
{
m_ui.verify->setEnabled(false);
m_ui.verifyResult->setPlainText(tr("Track list unavailable while virtual machine is running."));
return;
}
IsoHasher hasher;
Error error;
if (!hasher.Open(m_entry_path, &error))
{
m_ui.verify->setEnabled(false);
m_ui.verifyResult->setPlainText(QString::fromStdString(error.GetDescription()));
return;
}
const auto AddColumn = [this](const QString& text) {
QTableWidgetItem* item = new QTableWidgetItem(text);
const int column = m_ui.tracks->columnCount();
m_ui.tracks->insertColumn(column);
m_ui.tracks->setHorizontalHeaderItem(column, item);
};
const auto SetColumn = [this](int row, int column, const QString& text) {
QTableWidgetItem* item = new QTableWidgetItem(text);
m_ui.tracks->setItem(row, column, item);
};
// columns depend on CD vs DVD.
AddColumn(tr("#"));
if (hasher.IsCD())
{
AddColumn(tr("Mode"));
AddColumn(tr("Start"));
AddColumn(tr("Sectors"));
AddColumn(tr("Size"));
AddColumn(tr("MD5"));
AddColumn(tr("Status"));
}
else
{
AddColumn(tr("Start"));
AddColumn(tr("Sectors"));
AddColumn(tr("Size"));
AddColumn(tr("MD5"));
AddColumn(tr("Status"));
}
for (const IsoHasher::Track& track : hasher.GetTracks())
{
const int row = m_ui.tracks->rowCount();
m_ui.tracks->insertRow(row);
SetColumn(row, 0, tr("%1").arg(track.number));
if (hasher.IsCD())
{
SetColumn(row, 1, QtUtils::StringViewToQString(IsoHasher::GetTrackTypeString(track.type)));
SetColumn(row, 2, tr("%1").arg(track.start_lsn));
SetColumn(row, 3, tr("%1").arg(track.sectors));
SetColumn(row, 4, tr("%1").arg(track.size));
SetColumn(row, 5, tr("<not computed>"));
SetColumn(row, 6, QString());
}
else
{
SetColumn(row, 1, tr("%1").arg(track.start_lsn));
SetColumn(row, 2, tr("%1").arg(track.sectors));
SetColumn(row, 3, tr("%1").arg(track.size));
SetColumn(row, 4, tr("<not computed>"));
SetColumn(row, 5, QString());
}
}
if (hasher.IsCD())
QtUtils::ResizeColumnsForTableView(m_ui.tracks, {20, 60, 70, 70, 100, 220, 40});
else
QtUtils::ResizeColumnsForTableView(m_ui.tracks, {20, 100, 100, 100, 220, 40});
}
void GameSummaryWidget::onVerifyClicked()
{
// Can't do this while a VM is running because of stupid CDVD.
if (QtHost::IsVMValid())
{
QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Error"), tr("Cannot verify image while a game is running."));
return;
}
IsoHasher hasher;
Error error;
if (!hasher.Open(m_entry_path, &error))
{
setVerifyResult(QString::fromStdString(error.GetDescription()));
return;
}
QtModalProgressCallback callback(this);
hasher.ComputeHashes(&callback);
if (callback.IsCancelled())
return;
const int hash_column = hasher.IsCD() ? 5 : 4;
int row = 0;
// convert to database format
std::vector<GameDatabase::TrackHash> thashes;
thashes.reserve(hasher.GetTrackCount());
for (const IsoHasher::Track& track : hasher.GetTracks())
{
GameDatabase::TrackHash thash;
thash.size = track.size;
if (track.hash.empty() || !thash.parseHash(track.hash))
{
m_ui.verify->setEnabled(false);
m_ui.verifyResult->setPlainText(tr("One or more tracks is missing."));
return;
}
// Use the first track's hash as the redump search term.
if (m_redump_search_keyword.empty())
m_redump_search_keyword = thash.toString();
thashes.push_back(thash);
}
// match the hashes. can't use vector<bool> here because it's not an actual array
std::unique_ptr<bool[]> val_results = std::make_unique<bool[]>(hasher.GetTrackCount());
std::string match_error;
const GameDatabase::HashDatabaseEntry* hentry =
GameDatabase::lookupHash(thashes.data(), thashes.size(), val_results.get(), &match_error);
// fill the UI with both the hashes and validation results
for (u32 i = 0; i < hasher.GetTrackCount(); i++)
{
QTableWidgetItem* const hash_item = m_ui.tracks->item(row, hash_column);
QTableWidgetItem* const status_item = m_ui.tracks->item(row, hash_column + 1);
const bool result = val_results[i];
const QBrush brush(result ? QColor(0, 200, 0) : QColor(200, 0, 0));
hash_item->setText(QString::fromStdString(hasher.GetTrack(i).hash));
hash_item->setForeground(brush);
status_item->setText(result ? QStringLiteral("\u2713") : QStringLiteral("\u2715"));
status_item->setForeground(brush);
row++;
}
if (hentry)
{
if (!hentry->version.empty())
{
setVerifyResult(tr("Verified as %1 [%2] (Version %3).")
.arg(QString::fromStdString(hentry->name))
.arg(QString::fromStdString(hentry->serial))
.arg(QString::fromStdString(hentry->version)));
}
else
{
setVerifyResult(tr("Verified as %1 [%2].")
.arg(QString::fromStdString(hentry->name))
.arg(QString::fromStdString(hentry->serial)));
}
}
else
{
setVerifyResult(QString::fromStdString(match_error));
}
}
void GameSummaryWidget::onSearchHashClicked()
{
if (m_redump_search_keyword.empty())
return;
QtUtils::OpenURL(this, fmt::format("http://redump.org/discs/quicksearch/{}", m_redump_search_keyword).c_str());
}
void GameSummaryWidget::setVerifyResult(QString error)
{
m_ui.verify->setVisible(false);
m_ui.verifyButtonLayout->removeWidget(m_ui.verify);
m_ui.verify->deleteLater();
m_ui.verify = nullptr;
m_ui.verifyButtonLayout->removeItem(m_ui.verifyButtonSpacer);
delete m_ui.verifyButtonSpacer;
m_ui.verifyButtonSpacer = nullptr;
m_ui.verifyLayout->removeItem(m_ui.verifyButtonLayout);
m_ui.verifyButtonLayout->deleteLater();
m_ui.verifyButtonLayout = nullptr;
m_ui.verifyLayout->update();
updateGeometry();
m_ui.verifyResult->setPlainText(error);
m_ui.verifyResult->setVisible(true);
m_ui.searchHash->setVisible(true);
}
void GameSummaryWidget::repopulateCurrentDetails()
{
auto lock = GameList::GetLock();
const GameList::Entry* entry = GameList::GetEntryForPath(m_entry_path.c_str());
if (entry)
{
populateDetails(entry);
m_dialog->setWindowTitle(QString::fromStdString(entry->title));
}
}
void GameSummaryWidget::setCustomTitle(const std::string& text)
{
m_ui.restoreTitle->setEnabled(!text.empty());
GameList::SaveCustomTitleForPath(m_entry_path, text);
repopulateCurrentDetails();
}
void GameSummaryWidget::setCustomRegion(int region)
{
m_ui.restoreRegion->setEnabled(region >= 0);
GameList::SaveCustomRegionForPath(m_entry_path, region);
repopulateCurrentDetails();
}
+13 -3
View File
@@ -34,16 +34,26 @@ public:
GameSummaryWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent);
~GameSummaryWidget();
private Q_SLOTS:
void onInputProfileChanged(int index);
void onDiscPathChanged(const QString& value);
void onDiscPathBrowseClicked();
void onVerifyClicked();
void onSearchHashClicked();
private:
void populateInputProfiles();
void populateDetails(const GameList::Entry* entry);
void populateDiscPath(const GameList::Entry* entry);
void populateTrackList(const GameList::Entry* entry);
void setVerifyResult(QString error);
void repopulateCurrentDetails();
void onInputProfileChanged(int index);
void onDiscPathChanged(const QString& value);
void onDiscPathBrowseClicked();
void setCustomTitle(const std::string& text);
void setCustomRegion(int region);
Ui::GameSummaryWidget m_ui;
SettingsDialog* m_dialog;
std::string m_entry_path;
std::string m_redump_search_keyword;
};
+277 -171
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>692</width>
<height>562</height>
<width>641</width>
<height>467</height>
</rect>
</property>
<layout class="QFormLayout" name="detailsFormLayout">
@@ -34,11 +34,25 @@
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="title">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLineEdit" name="title">
<property name="placeholderText">
<string>Clear the line to restore the original title...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="restoreTitle">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Restore</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
@@ -140,170 +154,178 @@
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="region">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-B (Brazil)</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QComboBox" name="region">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-B (Brazil)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-C (China)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-HK (Hong Kong)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-J (Japan)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-K (Korea)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-T (Taiwan)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-U (US)</string>
</property>
</item>
<item>
<property name="text">
<string>Other</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-A (Australia)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-AF (South Africa)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-AU (Austria)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-BE (Belgium)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-E (Europe/Australia)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-F (France)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-FI (Finland)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-G (Germany)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-GR (Greece)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-I (Italy)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-IN (India)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-M (Europe/Australia)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-NL (Netherlands)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-NO (Norway)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-P (Portugal)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-PL (Poland)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-R (Russia)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-S (Spain)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SC (Scandinavia)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SW (Sweden)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SWI (Switzerland)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-UK (United Kingdom)</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QPushButton" name="restoreRegion">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Restore</string>
</property>
</widget>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-C (China)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-HK (Hong Kong)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-J (Japan)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-K (Korea)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-T (Taiwan)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">NTSC-U (US)</string>
</property>
</item>
<item>
<property name="text">
<string>Other</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-A (Australia)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-AF (South Africa)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-AU (Austria)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-BE (Belgium)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-E (Europe/Australia)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-F (France)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-FI (Finland)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-G (Germany)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-GR (Greece)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-I (Italy)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-IN (India)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-M (Europe/Australia)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-NL (Netherlands)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-NO (Norway)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-P (Portugal)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-PL (Poland)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-R (Russia)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-S (Spain)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SC (Scandinavia)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SW (Sweden)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-SWI (Switzerland)</string>
</property>
</item>
<item>
<property name="text">
<string extracomment="Leave the code as-is, translate the country's name.">PAL-UK (United Kingdom)</string>
</property>
</item>
</widget>
</layout>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_7">
@@ -413,7 +435,7 @@
</item>
</layout>
</item>
<item row="9" column="1">
<item row="10" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -426,6 +448,90 @@
</property>
</spacer>
</item>
<item row="9" column="0" colspan="2">
<layout class="QVBoxLayout" name="verifyLayout">
<item>
<widget class="QTableWidget" name="tracks">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="verifyButtonLayout">
<item>
<spacer name="verifyButtonSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="verify">
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" rowspan="3">
<widget class="QPlainTextEdit" name="verifyResult">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>60</height>
</size>
</property>
<property name="visible">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="searchHash">
<property name="visible">
<bool>false</bool>
</property>
<property name="text">
<string>Search on Redump.org...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
+1 -6
View File
@@ -181,7 +181,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
//////////////////////////////////////////////////////////////////////////
// HW Renderer Fixes
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfScreenFix, "EmuCore/GS", "UserHacks_Half_Bottom_Override", -1, -1);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cpuSpriteRenderBW, "EmuCore/GS", "UserHacks_CPUSpriteRenderBW", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cpuSpriteRenderLevel, "EmuCore/GS", "UserHacks_CPUSpriteRenderLevel", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.cpuCLUTRender, "EmuCore/GS", "UserHacks_CPUCLUTRender", 0);
@@ -218,12 +217,12 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfPixelOffset, "EmuCore/GS", "UserHacks_HalfPixelOffset", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.roundSprite, "EmuCore/GS", "UserHacks_round_sprite_offset", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.bilinearHack, "EmuCore/GS", "UserHacks_BilinearHack", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetX, "EmuCore/GS", "UserHacks_TCOffsetX", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetY, "EmuCore/GS", "UserHacks_TCOffsetY", 0);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.bilinearHack, "EmuCore/GS", "UserHacks_BilinearHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.nativePaletteDraw, "EmuCore/GS", "UserHacks_NativePaletteDraw", false);
//////////////////////////////////////////////////////////////////////////
// Texture Replacements
@@ -515,9 +514,6 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
// Hardware Fixes tab
{
dialog->registerWidgetHelp(m_ui.halfScreenFix, tr("Half Screen Fix"), tr("Automatic (Default)"),
tr("Control the half-screen fix detection on texture shuffling."));
dialog->registerWidgetHelp(m_ui.cpuSpriteRenderBW, tr("CPU Sprite Renderer Size"), tr("0 (Disabled)"), tr(""));
dialog->registerWidgetHelp(m_ui.cpuCLUTRender, tr("Software CLUT Render"), tr("0 (Disabled)"), tr(""));
@@ -1050,7 +1046,6 @@ void GraphicsSettingsWidget::resetManualHardwareFixes()
check_bool("EmuCore/GS", "UserHacks", false);
check_int("EmuCore/GS", "UserHacks_Half_Bottom_Override", -1);
check_int("EmuCore/GS", "UserHacks_CPUSpriteRenderBW", 0);
check_int("EmuCore/GS", "UserHacks_CPUCLUTRender", 0);
check_int("EmuCore/GS", "UserHacks_GPUTargetCLUTMode", 0);
+36 -36
View File
@@ -787,25 +787,6 @@
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="halfScreenFix">
<item>
<property name="text">
<string>Automatic (Default)</string>
</property>
</item>
<item>
<property name="text">
<string>Force Disabled</string>
</property>
</item>
<item>
<property name="text">
<string>Force Enabled</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_36">
<property name="text">
@@ -1168,14 +1149,14 @@
</item>
</widget>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="textureOffsetLabel">
<property name="text">
<string>Texture Offsets:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<layout class="QHBoxLayout" name="textureOffsetLayout" stretch="0,1,0,1">
<item>
<widget class="QLabel" name="textureOffsetXLabel">
@@ -1207,7 +1188,7 @@
</item>
</layout>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QCheckBox" name="alignSprite">
@@ -1216,20 +1197,6 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="bilinearHack">
<property name="text">
<string>Bilinear Dirty Upscale</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="mergeSprite">
<property name="text">
<string>Merge Sprite</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="nativePaletteDraw">
<property name="text">
@@ -1244,8 +1211,41 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="mergeSprite">
<property name="text">
<string>Merge Sprite</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Bilinear Dirty Upscale:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="bilinearHack">
<item>
<property name="text">
<string>Automatic (Default)</string>
</property>
</item>
<item>
<property name="text">
<string>Force Bilinear</string>
</property>
</item>
<item>
<property name="text">
<string>Force Nearest</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
+3 -5
View File
@@ -27,8 +27,7 @@
#include "fmt/format.h"
// _BitScanForward()
#include "pcsx2/GS/GSIntrin.h"
#include <bit>
InputBindingDialog::InputBindingDialog(SettingsInterface* sif, InputBindingInfo::Type bind_type, std::string section_name,
std::string key_name, std::vector<std::string> bindings, QWidget* parent)
@@ -97,9 +96,8 @@ bool InputBindingDialog::eventFilter(QObject* watched, QEvent* event)
else if (event_type == QEvent::MouseButtonPress || event_type == QEvent::MouseButtonDblClick)
{
// double clicks get triggered if we click bind, then click again quickly.
unsigned long button_index;
if (_BitScanForward(&button_index, static_cast<u32>(static_cast<const QMouseEvent*>(event)->button())))
m_new_bindings.push_back(InputManager::MakePointerButtonKey(0, button_index));
if (const u32 button_mask = static_cast<u32>(static_cast<const QMouseEvent*>(event)->button()))
m_new_bindings.push_back(InputManager::MakePointerButtonKey(0, std::countr_zero(button_mask)));
return true;
}
else if (event_type == QEvent::Wheel)
+3 -5
View File
@@ -21,13 +21,12 @@
#include <QtGui/QWheelEvent>
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
#include <bit>
#include <cmath>
#include <sstream>
#include "pcsx2/Host.h"
#include "pcsx2/GS/GSIntrin.h" // _BitScanForward
#include "QtHost.h"
#include "QtUtils.h"
#include "Settings/ControllerSettingsDialog.h"
@@ -134,9 +133,8 @@ bool InputBindingWidget::eventFilter(QObject* watched, QEvent* event)
else if (event_type == QEvent::MouseButtonPress || event_type == QEvent::MouseButtonDblClick)
{
// double clicks get triggered if we click bind, then click again quickly.
unsigned long button_index;
if (_BitScanForward(&button_index, static_cast<u32>(static_cast<const QMouseEvent*>(event)->button())))
m_new_bindings.push_back(InputManager::MakePointerButtonKey(0, button_index));
if (const u32 button_mask = static_cast<u32>(static_cast<const QMouseEvent*>(event)->button()))
m_new_bindings.push_back(InputManager::MakePointerButtonKey(0, std::countr_zero(button_mask)));
return true;
}
else if (event_type == QEvent::Wheel)

Some files were not shown because too many files have changed in this diff Show More