Compare commits

...

146 Commits

Author SHA1 Message Date
refractionpcsx2
b6930c10b9 GS/HW: Clean up target download formats 2025-06-05 13:51:21 +02:00
refractionpcsx2
852734580d GameDB: Update Harry Potter fixes. 2025-06-05 13:51:21 +02:00
refractionpcsx2
d1dc6a9c1d GS/HW: Add 16bit to 8bit conversion shader 2025-06-05 13:51:21 +02:00
Ty
4fa6d3ed3f GSRunner: Add type to shutdown message code 2025-06-04 20:25:32 -04:00
TellowKrinkle
92e190ad6c GSRunner: Fix surfaceless run on macOS 2025-06-04 20:25:32 -04:00
TellowKrinkle
da4fcffef4 Input: Fix crash when shutting down without initializing input 2025-06-04 20:25:32 -04:00
TellowKrinkle
1a5731dd8e MacOS: Better handle directories of non-bundle applications 2025-06-04 20:25:32 -04:00
TellowKrinkle
e764c5cd4e GSRunner: macOS support 2025-06-04 20:25:32 -04:00
TellowKrinkle
e23b247947 GSRunner: Use separate CPU thread 2025-06-04 20:25:32 -04:00
PCSX2 Bot
3d7792436f [ci skip] Qt: Update Base Translation. 2025-06-04 20:03:38 -04:00
chaoticgd
d8187fbea4 Deps: Specify minimum version of KDDockWidgets 2025-06-04 20:02:02 -04:00
chaoticgd
02259ad0a5 Debugger: Add include required for older versions of KDDockWidgets 2025-06-04 20:02:02 -04:00
TellowKrinkle
220a68df9a GS: Warn on texture replacement folder with wrong case 2025-06-04 19:58:41 -04:00
TellowKrinkle
2ced24f69e GS: Create texture dump directory if it doesn't exist 2025-06-04 19:58:41 -04:00
TellowKrinkle
ec91d0dc74 GS: Formatting 2025-06-04 19:58:41 -04:00
TheLastRar
46874f4673 Qt: Add workaround for incorrectly tinted icons after theme switch 2025-06-04 19:39:18 -04:00
TheLastRar
9eac47dc6c Qt: Fix selected gamelist icons being wrong colour after theme switch 2025-06-04 19:39:18 -04:00
RedDevilus
9e3fd5c2e0 CI: Fix flatpak
Try to fix build failing
2025-06-04 20:19:46 +01:00
refractionpcsx2
ae4be6e2b1 GS/CRC: Remove CRC for Simple 2000 Series Vol. 114, update GameDB Fixes 2025-06-04 18:35:00 +02:00
refractionpcsx2
434df49a7d GS/HW: Clear matched target on HW Move 2025-06-04 18:35:00 +02:00
JordanTheToaster
c939c0fcd5 GameDB: Re-add CRC to Death by Degrees 2025-06-04 18:33:36 +02:00
Berylskid
952c39f324 GameDB: Remove SoftwareRendererFMVHack from Armored Core 2 2025-06-03 13:44:40 +02:00
PCSX2 Bot
0fea7e2a70 [ci skip] Qt: Update Base Translation. 2025-06-03 03:40:13 +02:00
lightningterror
c1baab68d0 GS: Better handle hazards when dx12/vk device creation fails.
VK/DX12: Move CreateNullTexture before reading shader resource.
Fixes null pointer dereference.

VK: Check if vertex buffer is valid before binding.
Fixes vertex buffer validation error null handle.
2025-06-02 21:28:41 +02:00
PCSX2 Bot
ccef18f7a9 [ci skip] PAD: Update to latest controller database. 2025-06-02 19:08:36 +02:00
TheLastRar
8cb056bde3 Qt: Use DevicePixelRatioChange to detect DPR changes 2025-06-02 14:58:00 +02:00
TheLastRar
6ecaaee9e0 QtUtils: Remove redundant method 2025-06-02 14:58:00 +02:00
TheLastRar
c5f916bda0 Qt: Fix DPI icon scaling in various settings windows 2025-06-02 14:58:00 +02:00
TheLastRar
52a9a4649c Qt: Improve handling of DPI 2025-06-02 14:58:00 +02:00
refractionpcsx2
d2219b4dbd GS/TC: On RT->Z dst_match delete on format change if not a shuffle 2025-06-02 14:52:46 +02:00
refractionpcsx2
155f603245 GS/HW: Don't make new scaled targets on shuffles if source is downscaled 2025-06-02 14:52:46 +02:00
refractionpcsx2
cb7630a6ab GS/HW: Create new targets on shuffles when no target found
And get rid of some valid sizing thing which is just insane
2025-06-02 14:52:46 +02:00
refractionpcsx2
284fba1ce3 GS/TC: Don't allow Tex in RT 8bit textures from C24
C24 has no alpha channel, 8bit requires all.  This is still allowed for shuffles as that depends which channel it's reading.
2025-06-02 14:52:46 +02:00
refractionpcsx2
aa4bd6c88c GS/HW: Replace frame target if dirty data matches old format. 2025-06-02 14:52:46 +02:00
refractionpcsx2
623993930b GS/HW: Adjust depth size on clear if overlapping by 1 pixel
This is developer misunderstanding of how to use the SCISSOR register, which adds 1 on to the value when it's used, but they put 512x512, when they wanted 512x512.
2025-06-02 14:52:46 +02:00
refractionpcsx2
dbf2c854c6 GS/TC: Adopt valid rgb/alpha from preload merged targets 2025-06-02 14:52:46 +02:00
refractionpcsx2
25351bc05c GS/TC: Correct valid area checks for target combining 2025-06-02 14:52:46 +02:00
refractionpcsx2
27cc5f499c GS/HW: Fix up alpha blending checks 2025-06-02 14:52:46 +02:00
refractionpcsx2
b7c2f39a17 GS/TC: Further matching parameters on preload and tex in rt 2025-06-02 14:52:46 +02:00
refractionpcsx2
3541c1ccf8 GS/TC: Simplify and improve P8 texture conversion inside target 2025-06-02 14:52:46 +02:00
refractionpcsx2
7a05738d11 GS/TC: Allow matching on source if TEX == RT 2025-06-02 14:52:46 +02:00
refractionpcsx2
686220ae0c GS/TC: Improve copying of dst matched data 2025-06-02 14:52:46 +02:00
refractionpcsx2
cf380d36b9 GS/TC: Fix inside target alignment check for ExactTarget lookup 2025-06-02 14:52:46 +02:00
lightningterror
50bc0193ac Core: Bump savestate version.
[SAVEVERSION+]
2025-06-02 01:30:50 +02:00
refractionpcsx2
2162a72831 GS: Bump GS Dump version and add transfer parameters to dump 2025-06-02 00:40:03 +02:00
refractionpcsx2
313666f85b GS: Store entire GS transfer state at TRXDIR write 2025-06-02 00:40:03 +02:00
TheTechnician27
e9d79263b4 UI: Fix Discord Rich Presence not activating in FSUI 2025-06-01 23:21:39 +02:00
JordanTheToaster
4ede6d65fd GameDB: Fix half right issue with Xtreme Bowling 2025-06-01 13:28:25 -04:00
PCSX2 Bot
14d2eee371 [ci skip] Qt: Update Base Translation. 2025-05-31 20:46:33 -04:00
chaoticgd
717f370be0 Debugger: Improve DockTabBar ownership workaround 2025-05-31 03:30:13 +02:00
refractionpcsx2
d05e4b9727 GS/HW: Adjust SpriteNoGaps check for vertical strips 2025-05-31 03:25:47 +02:00
TheTechnician27
697c53b4d8 UI: Standardize order of option groups 2025-05-31 02:51:20 +02:00
refractionpcsx2
d9b58ec3ce GS/HW: Invalidate single columns on small writes when formats mismatch 2025-05-31 02:49:35 +02:00
refractionpcsx2
6c8b37d7ca GS: Add column sizing to psm format information 2025-05-31 02:49:35 +02:00
refractionpcsx2
39f43e766d GameDB: Add Tex in RT to Sand Grain Studios games 2025-05-31 02:37:16 +02:00
refractionpcsx2
5379a13944 GS/HW: Read back 16bit target if read as 8H 2025-05-31 02:37:16 +02:00
chaoticgd
cd0c1607ef GameList: Clip flag and compatibility pixmaps to the available space 2025-05-31 02:35:34 +02:00
chaoticgd
26a4f71385 GameList: Prevent "Invalid" entry type appearing in filter list 2025-05-31 02:35:34 +02:00
chaoticgd
06b3e6ad71 GameList: Fix region flag icons for non-English languages 2025-05-31 02:35:34 +02:00
lightningterror
79d22a8d77 GS/HW: Add/adjust logs for failed texture creation. 2025-05-31 02:04:12 +02:00
lightningterror
9914212600 GS/GL: Add another hazard check, colclip hw.
Bonus, add missing texture copies info when doing shader copies.
2025-05-31 02:04:12 +02:00
lightningterror
765f55e67b GS/TC: Fine tune Frame buffer conversion. 2025-05-31 01:55:40 +02:00
PCSX2 Bot
2d922cc035 [ci skip] Qt: Update Base Translation. 2025-05-30 15:57:49 +02:00
TellowKrinkle
42e0625ab3 Interpreter: Fix FTOI on negative numbers 2025-05-29 13:15:09 +02:00
TellowKrinkle
c72e894fc7 iR5900: Faster FTOI 2025-05-29 13:15:09 +02:00
JordanTheToaster
5bc2342d47 MemoryCardFile: Fix memory card sorting on Linux 2025-05-29 13:07:27 +02:00
Ty
ea2b0b5e59 CI: Fix a regression for flathub uploads 2025-05-28 19:22:47 -04:00
refractionpcsx2
d70cc0221a GS/DX12: Fix HDR copy scissor area 2025-05-28 22:32:12 +02:00
refractionpcsx2
b12587b44e GameDB: Add Tex in RT for Bard's Tale 2025-05-28 18:33:27 +01:00
refractionpcsx2
c4708bdc35 GameDB: Add Tex in RT to required games 2025-05-28 18:01:49 +02:00
refractionpcsx2
1fa2c0bf50 GS/TC: Replace half right with Tex in RT, only update needed dirty 2025-05-28 18:01:49 +02:00
lightningterror
b4c70d357a GS/HW: Restore old coverage after updating mip layers. 2025-05-28 18:00:45 +02:00
PCSX2 Bot
f18262ee96 [ci skip] PAD: Update to latest controller database. 2025-05-26 21:18:58 +02:00
refractionpcsx2
c1f1761482 GS/HW: Invalidate cleared area if overlapping existing dirty 2025-05-26 13:45:47 +02:00
PCSX2 Bot
067c3eea16 [ci skip] Qt: Update Base Translation. 2025-05-26 02:03:40 +02:00
KamFretoZ
6957cc7001 FSUI: Fix save state duplicate entry 2025-05-26 01:46:30 +02:00
PCSX2 Bot
7dea23eea8 [ci skip] Qt: Update Base Translation. 2025-05-24 20:10:08 -04:00
TheTechnician27
319ec1f774 OSD: Fix performance overlay overwriting dump stats when shifted left 2025-05-24 12:33:32 +02:00
JohnSmith774
2079532e83 GameDB: Add memcard filters for some NTSC-J titles. (#12708)
Add memcard filters for OutRun2 SP - SPECIAL TOURS.
Add memcard filters for Another Century's Episode 2 Special Vocal Version.
Add memcard filters for Armored Core - Last Raven.
2025-05-24 12:32:03 +02:00
Mrlinkwii
de1d646fe9 github-workflows: Fix a broken link. 2025-05-24 12:30:08 +02:00
JordanTheToaster
4bc3ab6285 OSD: Add VSync to the OSD 2025-05-24 05:04:39 +02:00
JordanTheToaster
1adc9cbb49 GameDB: Various Fixes Part 4 (one with cheese) 2025-05-24 05:04:39 +02:00
refractionpcsx2
7cdf5eefc9 GS/TC: On clear delete overlapping depth targets 2025-05-24 05:03:48 +02:00
refractionpcsx2
c7ee72647d GS/HW: Improve texture shuffle/copy detection 2025-05-23 20:33:30 +02:00
Imre Eilertsen
5434af348e GameDB: Add listings for PSX Update Disc. 2025-05-23 13:31:40 +02:00
GovanifY
169cea0f01 docs: update in order to redirect from the GH wiki to our website 2025-05-22 17:43:42 +02:00
lightningterror
a8f3ec8184 GSClut: Get rid of m_read.dirty assert in GetAlphaMinMax32.
Replace it with a log.
2025-05-21 03:40:22 +02:00
lightningterror
7796b2a12b GS/HW: Add sanity/hazard checks for DATE and Texture barriers.
When checking for full barrier, also check if texture barriers
are supported.

Get rid of preprocessSel in DX11, turn off full barrier and related
stuff when not supported in rendererhw instead.

Check if StencilDate types are actually enabled, don't want to turn
it on for any others.
2025-05-21 03:40:22 +02:00
RedDevilus
d9cffd58ba GameDB: Add missing variants + fixes
Some games are missing some gamefixes or other type of fixes. Also added comment for like Energy Airforce where a legacy code never had a comment and removed mtvu for some variant + need to check in future to amend properly. Also missing entry SLPS-25875:
  name: "xxxHolic - Shigatsu Tsuitachi no Izayoi Sowa [Best Collection]"
2025-05-21 00:56:32 +02:00
refractionpcsx2
e566386240 GS/TC: only kill old misaligned targets on preload from previous frames. 2025-05-20 20:21:05 +02:00
refractionpcsx2
45af1e172f GS/HW: Improve shuffle pre-detection 2025-05-20 20:21:05 +02:00
refractionpcsx2
768b2e52a6 GS/TC: Don't allow Tex in RT 32bit target use as 16bit if not a shuffle 2025-05-20 20:21:05 +02:00
Ziemas
7abd2009b0 debugger: fix thread view row lookup 2025-05-20 11:57:11 -04:00
chaoticgd
46f075e891 DebugTools: Fix uninitialized variable in breakpoint code 2025-05-19 22:17:54 -04:00
lightningterror
832c381ac4 GS/HW: Allow partial depth copy on dx12. 2025-05-19 22:10:42 +02:00
SquishyLeaf
e021282264 CI: Fix script building universal dependencies on macOS
- Skip arm64 binaries when looking for x86_64 binaries to merge

- Change Qt download link to archive

- Build universal binaries for libjpegturbo, PlutoVG and PlutoSVG
2025-05-19 14:21:14 -04:00
PCSX2 Bot
2a60d385c6 [ci skip] PAD: Update to latest controller database. 2025-05-19 18:42:36 +02:00
refractionpcsx2
4d37e35675 GS/TC: Delete dirty rt's in src lookup + usert in rt on 3 draw old rt's 2025-05-18 11:13:35 +02:00
refractionpcsx2
df3868a280 GS/HW: Avoid target height mistakes on shuffles + Update new src == rt 2025-05-18 11:13:35 +02:00
lightningterror
0799bb8cf1 GS/DX: DX requires a copy to sample the depth buffer. 2025-05-17 22:54:04 +02:00
lightningterror
69048dede4 GS/DX11: Merge CloneTexture with CopyRect.
Unified between renderers, easier to make shared changes.
2025-05-17 22:54:04 +02:00
lightningterror
76df6d1f43 GS/GL: Check for texture creation hazard for fb copy. 2025-05-17 22:54:04 +02:00
refractionpcsx2
2d03b21f2b Formatting: Clean up some if spaces 2025-05-17 22:47:38 +02:00
refractionpcsx2
62cbd44933 GS/HW: Fix up offset Z behaviour + work even when RT isn't offset. 2025-05-17 22:47:38 +02:00
refractionpcsx2
44c8f6d8b0 GS/HW: Correct valid area for depth when taking alpha from rt. Add Tex in RT to Area 51 2025-05-17 22:47:38 +02:00
refractionpcsx2
f3fc1dd59c GS/HW: Fix some regressions relating to overlapping targets and valid rect + rgb 2025-05-17 22:47:38 +02:00
lightningterror
708931e48b GS/HW: Clean up HandleTextureHazards.
Warnings, initializations, dereferencing null pointers.
2025-05-17 22:46:37 +02:00
TheLastRar
81800d2883 CMake: Support more package configurations to import with a Devel build 2025-05-17 09:39:56 -04:00
TellowKrinkle
d0411d7ddf Core:macOS: Initialize all address variables passed to vm_map 2025-05-16 12:41:09 +02:00
Ty
70e232cab3 GitHub: Make authors disclose whether they used AI or not.
Using checkboxes implicitly made it a task list that cluttered up the PR list.

[ci skip]
2025-05-16 12:27:15 +02:00
refractionpcsx2
f90396bda4 GS/DX12: Fix command list not flushing when in surfaceless mode. 2025-05-16 12:25:16 +02:00
lightningterror
ae8808b86e GS/HW: Backport some tex is fb shaders to dx and opengl. 2025-05-15 20:08:16 +02:00
lightningterror
8d5b827432 GS/HW: Fix texture copies when tex is fb draw.
Fixes an issue with texture copies didn't work properly on tex is fb draw:
Fixes Hitman Blood Money on minimum blend.

DX can't do partial depth copy so do a shader based copy which works.
Fixes a bunch of games that couldn't do partial depth copy on dx.
2025-05-15 20:08:16 +02:00
lightningterror
cb672697e7 FullscreenUI: Fix -Wlogical-op-parentheses warning. 2025-05-15 20:08:16 +02:00
JordanTheToaster
0bae9fc29b Deps: Update SDL3 to 3.2.14 2025-05-15 18:43:45 +02:00
lightningterror
49c8b68700 GS/HW: Enable feedback loop if channel shuffle enabled barriers. 2025-05-15 18:43:35 +02:00
refractionpcsx2
1e2fcd17e0 GS/HW: Fix new target creation width when doing a page copy 2025-05-15 01:45:11 +02:00
refractionpcsx2
468b9d2655 GS/TC: Use frame width on PSMT8H read if target width doesn't match frame on Tex in RT.
Also changed LookupSource/Depth to receive the whole FRAME struct, not just the pointer.
2025-05-15 01:45:11 +02:00
refractionpcsx2
a3305ff791 GS/TC: Used unwrapped end blocks for combine 2025-05-15 01:45:11 +02:00
PCSX2 Bot
814b0d5873 [ci skip] Qt: Update Base Translation. 2025-05-13 20:00:55 +02:00
refractionpcsx2
863f3e82ac GS/HW: Combine target using the drawn area, not valid area (some of this can be garbage) 2025-05-13 19:56:39 +02:00
Ty
529c756458 GitHub: Require PR authors to disclose AI usage
[noci]
2025-05-12 18:12:02 -04:00
TheLastRar
67b98dbdaa Deps: Also build KDDockWidgets as Debug 2025-05-12 22:35:07 +02:00
TheLastRar
a16981cbe5 CMake: Pick release packages when building with devel 2025-05-12 22:35:07 +02:00
lightningterror
777bf338fa GS/HW: Fix tex is fb log for palette conversion. 2025-05-12 22:23:14 +02:00
lightningterror
3ba8d9ebff GS/HW: Move texture sampling before EmulateBlending.
Tex is fb setting is done in Texture sampler which resulted
in hw blend being applied before with barriers on.

Tex is fb can use sw blend so this optimizes that with no cost.

Also fixes an issue where hw blend was on with fbfetch.
2025-05-12 21:40:51 +02:00
lightningterror
db5384e19c GS/HW: Add hazard check for date depth buffer creation.
Add fallback to PrimIDTracking if possible.
2025-05-12 21:39:43 +02:00
lightningterror
fd3984287b GS/HW: Add hazard check for temporary depth buffer creation. 2025-05-12 21:39:43 +02:00
lightningterror
31dbea4e0b GS: Retry texture creation after initial retry fails.
This should've been done.
2025-05-12 21:39:43 +02:00
refractionpcsx2
0992e784f1 GS/HW: Tighten shuffle check on source lookup 2025-05-12 21:28:41 +02:00
refractionpcsx2
c59cc1fbb7 GS/TC: Kill partially dirty RT in RT targets which haven't been used recently 2025-05-12 21:28:41 +02:00
refractionpcsx2
903edc79f7 GS/TC: Alter RT in RT target lookup further and expand target on Move if needed 2025-05-12 21:28:41 +02:00
refractionpcsx2
4c94c69f02 GS: Clear Adaptive Interlacing buffer when outputs are disabled 2025-05-12 21:28:41 +02:00
refractionpcsx2
4c57c214bd GS/HW: Expand target to fix requested source rect when dirty covers area 2025-05-12 21:28:41 +02:00
refractionpcsx2
1cbeea3016 GS/HW: Fix up inside target lookup behaviour in HW renderer 2025-05-12 21:28:41 +02:00
PCSX2 Bot
0d18738192 [ci skip] PAD: Update to latest controller database. 2025-05-12 21:01:31 +02:00
JordanTheToaster
1e7c7db29b GameDB: Various Fixes Part 3 Because I Forgot More 2025-05-12 01:05:14 +02:00
PCSX2 Bot
7c098a2665 [ci skip] Qt: Update Base Translation. 2025-05-11 02:02:52 +02:00
Ty
3ab539be1e CDVD: Fix for non-PCH builds 2025-05-10 15:38:02 -04:00
Ty
b46d5e4efc CI: Disable PCH on Linux 2025-05-10 15:38:02 -04:00
Jordan
db06e11a7c GameDB: RT in RT Part Deux.
Adds fixes such as ATNWTO to around 104 games and adjusts the names of even more. Don't ask me what I fixed I don't even remember at this point.
2025-05-10 19:54:21 +02:00
KamFretoZ
757ed33e4f FSUI: Add ImDrawList helper for drawing SVG images
Co-Authored-By: TheLastRar <TheLastRar@users.noreply.github.com>
2025-05-10 19:53:04 +02:00
KamFretoZ
8eb5dfce85 Qt/FSUI: Update branding to the about section 2025-05-10 19:53:04 +02:00
PCSX2 Bot
f34db72a97 [ci skip] Qt: Update Base Translation. 2025-05-09 18:13:36 -04:00
chaoticgd
3dfdc8ee6f Debugger: Fix a typo in the memory search view 2025-05-08 22:16:38 +02:00
chaoticgd
5a846296ca Docs: Add even more missing third party licenses 2025-05-08 09:23:22 -04:00
127 changed files with 5991 additions and 3362 deletions

View File

@@ -1,54 +0,0 @@
# So you want to contribute to PCSX2? Great
As a first step, please review these links as they'll help you understand how the development of PCSX2 works.
* [Just Starting Out](#just-starting-out)
* [Issue Reporting](#issue-reporting)
* [Pull Request Guidelines](#pull-request-guidelines)
* [General Documentation And Coding Strategies](#general-documentation-and-coding-strategies)
* [Tasks](#tasks)
## Just Starting Out
* If you're unfamilar with git, check out this [brief introduction to Git](https://github.com/PCSX2/pcsx2/wiki/07-Git-survival-guide)
* [How to build PCSX2 for Windows](https://github.com/PCSX2/pcsx2/wiki/12-Building-on-Windows)
* [How to build PCSX2 for Linux](https://github.com/PCSX2/pcsx2/wiki/10-Building-on-Linux)
## Issue Reporting
* [How to write a useful issue](https://github.com/PCSX2/pcsx2/wiki/How-to-create-useful-and-valid-issues)
## Pull Request Guidelines
The following is a list of *general* style recommendations that will make reviewing and merging easier:
* Commit Messages
* Please try to prefix your commit message, indicating what area of the project was modified.
* For example `gs: message...`.
* Looking at the project's commit history will help with keeping prefixes consistent overtime, *there is no strictly enforced list*.
* Try to keep messages brief and informative
* Remove unnecessary commits and squash commits together when appropriate.
* If you are not familiar with rebasing with git, check out the following resources:
* CLI - https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history
* GUI (SourceTree) - https://www.atlassian.com/blog/sourcetree/interactive-rebase-sourcetree
* Code Styling and Formatting
* [Consult the style guide](https://github.com/tadanokojin/pcsx2/blob/coding-guide/pcsx2/Docs/Coding_Guidelines.md)
* Run `clang-format` using the configuration file in the root of the repository
* Visual Studio Setup - https://devblogs.microsoft.com/cppblog/clangformat-support-in-visual-studio-2017-15-7-preview-1/
* IMPORTANT - if you are running `clang-format` on unrelated changes (ie. formatting an entire file), please do so in a separate commit.
* If you cannot scope your `clang-format` to just your changes and do not want to format unrelated code. Try your best to stick with the existing formatting already established in the file in question.
## General Documentation And Coding Strategies
* [Commenting Etiquette](https://github.com/PCSX2/pcsx2/wiki/06-Commenting-Etiquette)
* [Coding style](https://github.com/PCSX2/pcsx2/wiki/Code-Formatting-Guidelines)
* [More comprehensive style-guide (Currently in Draft)](https://github.com/tadanokojin/pcsx2/blob/coding-guide/pcsx2/Docs/Coding_Guidelines.md)
## Tasks
* [Issues](https://github.com/PCSX2/pcsx2/issues)

View File

@@ -66,6 +66,10 @@ body:
Performance issues as a result of not meeting our hardware requirements are not valid.
Please read our troubleshooting pages and our issue reporting guide.
- [Troubleshooting page](https://pcsx2.net/docs/category/troubleshooting).
- [Issue reporting guide](https://pcsx2.net/docs/troubleshooting/identify).
We are **not** accepting issues related to the **libretro** core. The libretro core is being maintained separately at this time
- type: input
id: rev

View File

@@ -6,3 +6,6 @@
### Suggested Testing Steps
<!-- If applicable, including examples you've already tested with / recommendations for how to test further is very helpful! -->
### Did you use AI to help find, test, or implement this issue or feature?
<!-- Answer yes or no. If you answer yes, please provide a brief explanation how. -->

View File

@@ -132,7 +132,7 @@ jobs:
- name: Push to Flathub (beta)
if: ${{ inputs.publish == true && (inputs.stableBuild == false || inputs.stableBuild == 'false') }}
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
uses: flatpak/flatpak-github-actions/flat-manager@10a3c29f0162516f0f68006be14c92f34bd4fa6c
with:
flat-manager-url: https://hub.flathub.org/
repository: beta
@@ -141,7 +141,7 @@ jobs:
- name: Push to Flathub (stable)
if: ${{ inputs.publish == true && (inputs.stableBuild == true || inputs.stableBuild == 'true') }}
uses: flatpak/flatpak-github-actions/flatpak-builder@10a3c29f0162516f0f68006be14c92f34bd4fa6c
uses: flatpak/flatpak-github-actions/flat-manager@10a3c29f0162516f0f68006be14c92f34bd4fa6c
with:
flat-manager-url: https://hub.flathub.org/
repository: stable

View File

@@ -140,9 +140,11 @@ jobs:
-DCMAKE_CXX_COMPILER=clang++-17 \
-DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" \
-DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DENABLE_SETCAP=OFF \
-DDISABLE_ADVANCE_SIMD=TRUE \
-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \
$ADDITIONAL_CMAKE_ARGS
- name: Build PCSX2

View File

@@ -18,7 +18,7 @@ LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
LIBJPEGTURBO=3.1.0
LIBPNG=1.6.48
LIBWEBP=1.5.0
SDL=SDL3-3.2.12
SDL=SDL3-3.2.14
QT=6.9.0
LZ4=1.10.0
ZSTD=1.5.7
@@ -39,7 +39,7 @@ fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96 $SDL.tar.gz
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
c1800c2ea835801af04a05d4a32321d79a93954ee3ae2172bbeacf13d1f0598c qtbase-everywhere-src-$QT.tar.xz

View File

@@ -14,8 +14,8 @@
"sources": [
{
"type": "archive",
"url": "https://libsdl.org/release/SDL3-3.2.12.tar.gz",
"sha256": "9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96"
"url": "https://libsdl.org/release/SDL3-3.2.14.tar.gz",
"sha256": "b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f"
}
],
"cleanup": [

View File

@@ -11,10 +11,9 @@
},
"sources": [
{
"type": "git",
"type": "git",
"url": "https://github.com/sammycage/plutovg.git",
"tag": "v0.0.13",
"sha256": "5e4712cf873b0c7829a4a6157763e2ad3ac49164"
"tag": "v0.0.13"
}
],
"cleanup": [

View File

@@ -12,10 +12,9 @@
},
"sources": [
{
"type": "git",
"type": "git",
"url": "https://github.com/sammycage/plutosvg.git",
"tag": "v0.0.6",
"sha256": "c5388fa96feca1f1376a3d0485d5e35159452707"
"tag": "v0.0.6"
}
],
"cleanup": [

View File

@@ -11,7 +11,7 @@ merge_binaries() {
"
pushd "$X86DIR"
for X86BIN in $(find . -type f \( -name '*.dylib' -o -name '*.a' -o -perm +111 \)); do
if file "$X86DIR/$X86BIN" | grep "Mach-O " >/dev/null; then
if file "$X86DIR/$X86BIN" | grep "Mach-O.*x86_64" >/dev/null; then
ARMBIN="${ARMDIR}/${X86BIN}"
echo "Merge $ARMBIN to $X86BIN..."
lipo -create "$X86BIN" "$ARMBIN" -o "$X86BIN"
@@ -40,7 +40,7 @@ fi
FREETYPE=2.13.3
HARFBUZZ=11.2.0
SDL=SDL3-3.2.12
SDL=SDL3-3.2.14
ZSTD=1.5.7
LZ4=1.10.0
LIBPNG=1.6.48
@@ -79,7 +79,7 @@ CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
cat > SHASUMS <<EOF
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96 $SDL.tar.gz
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
@@ -112,11 +112,11 @@ curl -C - -L \
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
-O "https://github.com/KhronosGroup/MoltenVK/archive/refs/tags/v$MOLTENVK.tar.gz" \
-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" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
-o "shaderc-$SHADERC.tar.gz" "https://github.com/google/shaderc/archive/refs/tags/v$SHADERC.tar.gz" \
-o "shaderc-glslang-$SHADERC_GLSLANG.tar.gz" "https://github.com/KhronosGroup/glslang/archive/$SHADERC_GLSLANG.tar.gz" \
-o "shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz" "https://github.com/KhronosGroup/SPIRV-Headers/archive/$SHADERC_SPIRVHEADERS.tar.gz" \
@@ -213,8 +213,11 @@ echo "Installing libjpegturbo..."
rm -fr "libjpeg-turbo-$LIBJPEGTURBO"
tar xf "libjpeg-turbo-$LIBJPEGTURBO.tar.gz"
cd "libjpeg-turbo-$LIBJPEGTURBO"
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build-arm64
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_X64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build
make -C build "-j$NPROCS"
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_ARM64" -DENABLE_STATIC=OFF -DENABLE_SHARED=ON -B build-arm64
make -C build-arm64 "-j$NPROCS"
merge_binaries $(realpath build) $(realpath build-arm64)
make -C build install
cd ..
@@ -380,7 +383,7 @@ echo "Building PlutoVG..."
rm -fr "plutovg-$PLUTOVG"
tar xf "plutovg-$PLUTOVG.tar.gz"
cd "plutovg-$PLUTOVG"
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPLUTOVG_BUILD_EXAMPLES=OFF -B build
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DBUILD_SHARED_LIBS=ON -DPLUTOVG_BUILD_EXAMPLES=OFF -B build
make -C build "-j$NPROCS"
make -C build install
cd ..
@@ -389,7 +392,7 @@ echo "Building PlutoSVG..."
rm -fr "plutosvg-$PLUTOSVG"
tar xf "plutosvg-$PLUTOSVG.tar.gz"
cd "plutosvg-$PLUTOSVG"
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build
make -C build "-j$NPROCS"
make -C build install
cd ..

View File

@@ -22,7 +22,7 @@ fi
FREETYPE=2.13.3
HARFBUZZ=11.2.0
SDL=SDL3-3.2.12
SDL=SDL3-3.2.14
ZSTD=1.5.7
LZ4=1.10.0
LIBPNG=1.6.48
@@ -59,7 +59,7 @@ CMAKE_COMMON=(
cat > SHASUMS <<EOF
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96 $SDL.tar.gz
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz

View File

@@ -66,7 +66,7 @@ const embed = new MessageEmbed()
.setDescription("To download the latest or previous builds, [visit the official downloads page](https://pcsx2.net/downloads/).")
.addFields(
{ name: 'Version', value: releaseInfo.tag_name, inline: true },
{ name: 'Installation Steps', value: '[See Here](https://github.com/PCSX2/pcsx2/wiki/Nightly-Build-Usage-Guide)', inline: true },
{ name: 'Installation Steps', value: '[See Here](https://pcsx2.net/docs/category/setup)', inline: true },
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
);
console.log(embed);

View File

@@ -46,7 +46,7 @@ set FREETYPE=2.13.3
set HARFBUZZ=11.2.0
set LIBJPEGTURBO=3.1.0
set LIBPNG=1648
set SDL=SDL3-3.2.12
set SDL=SDL3-3.2.14
set QT=6.9.0
set QTMINOR=6.9
set LZ4=1.10.0
@@ -68,7 +68,7 @@ call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuz
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1648.zip 2e5f080360f77376eb2bfa9e2ed773b9c7728159aba47b638ad53ca839379040 || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" ebf1efd71527afbca6bdf2b0310caf726d00cc102c0e59ac86c1f8cd201f9593 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 46a17d3ea71fe2580a7f43ca7da286c5b9106dd761e2fd5533bb113e5d86b633 || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 513df15a6365a40f6230ec9463ad8c71b824e181d4b661dac9707e103b24ae0c || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" d428fd17a0d3f92c48a30f1d23806bf20352fbce2e80e5bbee27fa80576480ee || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 54bf06afeb67035f1c6afcd00beec755c0d776626b4cce9ab56992a55215ba69 || goto error
@@ -246,12 +246,21 @@ cmake --build . --parallel || goto error
ninja install || goto error
cd ..\.. || goto error
if %DEBUG%==1 (
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
) else (
rem kddockwidgets slightly changes the name of the dll depending on if CMAKE_BUILD_TYPE or CMAKE_CONFIGURATION_TYPES is used
rem The dll name being kddockwidgets-qt62.dll or kddockwidgets-qt62.dll respectively
rem Always use CMAKE_CONFIGURATION_TYPES to give consistant naming
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES=Release -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=Release -G "Ninja Multi-Config"
)
echo "Building KDDockWidgets..."
rmdir /S /Q "KDDockWidgets-%KDDOCKWIDGETS%"
%SEVENZIP% x "KDDockWidgets-%KDDOCKWIDGETS%.zip" || goto error
cd "KDDockWidgets-%KDDOCKWIDGETS%" || goto error
%PATCH% -p1 < "%SCRIPTDIR%\..\common\kddockwidgets-dodgy-include.patch" || goto error
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja || goto error
cmake -B build %ARM64TOOLCHAIN% -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets %KDDOCKWIDGETSBUILDSPEC% || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error

View File

@@ -44,7 +44,7 @@ set FREETYPE=2.13.3
set HARFBUZZ=11.2.0
set LIBJPEGTURBO=3.1.0
set LIBPNG=1648
set SDL=SDL3-3.2.12
set SDL=SDL3-3.2.14
set QT=6.9.0
set QTMINOR=6.9
set LZ4=1.10.0
@@ -66,7 +66,7 @@ call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuz
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1648.zip 2e5f080360f77376eb2bfa9e2ed773b9c7728159aba47b638ad53ca839379040 || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || goto error
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" ebf1efd71527afbca6bdf2b0310caf726d00cc102c0e59ac86c1f8cd201f9593 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 46a17d3ea71fe2580a7f43ca7da286c5b9106dd761e2fd5533bb113e5d86b633 || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 513df15a6365a40f6230ec9463ad8c71b824e181d4b661dac9707e103b24ae0c || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" d428fd17a0d3f92c48a30f1d23806bf20352fbce2e80e5bbee27fa80576480ee || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 54bf06afeb67035f1c6afcd00beec755c0d776626b4cce9ab56992a55215ba69 || goto error
@@ -250,12 +250,21 @@ cmake --build . --parallel || goto error
ninja install || goto error
cd ..\.. || goto error
if %DEBUG%==1 (
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
) else (
rem kddockwidgets slightly changes the name of the dll depending on if CMAKE_BUILD_TYPE or CMAKE_CONFIGURATION_TYPES is used
rem The dll name being kddockwidgets-qt62.dll or kddockwidgets-qt62.dll respectively
rem Always use CMAKE_CONFIGURATION_TYPES to give consistant naming
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES=Release -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=Release -G "Ninja Multi-Config"
)
echo "Building KDDockWidgets..."
rmdir /S /Q "KDDockWidgets-%KDDOCKWIDGETS%"
%SEVENZIP% x "KDDockWidgets-%KDDOCKWIDGETS%.zip" || goto error
cd "KDDockWidgets-%KDDOCKWIDGETS%" || goto error
%PATCH% -p1 < "%SCRIPTDIR%\..\common\kddockwidgets-dodgy-include.patch" || goto error
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja || goto error
cmake -B build -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets %KDDOCKWIDGETSBUILDSPEC% || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error

View File

@@ -19,7 +19,7 @@ jobs:
pr-message: |-
## Thank you for submitting a contribution to PCSX2
As this is your first pull request, [please be aware of the contributing guidelines](https://github.com/PCSX2/pcsx2/blob/master/.github/CONTRIBUTING.md).
As this is your first pull request, [please be aware of the contributing guidelines](https://pcsx2.net/docs/contributing/).
Additionally, as per recent changes in GitHub Actions, your pull request will need to be approved by a maintainer before GitHub Actions can run against it. [You can find more information about this change here.](https://github.blog/2021-04-22-github-actions-update-helping-maintainers-combat-bad-actors/)

View File

@@ -62,10 +62,12 @@ endif()
# gsrunner
if(ENABLE_GSRUNNER)
if (NOT WIN32)
message(WARNING "GSRunner is only supported on Windows and may not build on your system")
if (NOT WIN32 AND NOT APPLE)
message(WARNING "GSRunner is only supported on Windows and macOS and may not build on your system")
endif()
add_subdirectory(pcsx2-gsrunner)
else()
add_subdirectory(pcsx2-gsrunner EXCLUDE_FROM_ALL)
endif()
#-------------------------------------------------------------------------------

View File

@@ -24,4 +24,4 @@ Please note that a BIOS dump from a legitimately-owned PS2 console is required t
PCSX2 supports translation into other languages using [Crowdin](https://crowdin.com/project/pcsx2-emulator).
See the [Contributing Guidelines](https://github.com/PCSX2/pcsx2/blob/master/.github/CONTRIBUTING.md) or visit the [GitHub Wiki](https://github.com/PCSX2/pcsx2/wiki) for more info on how to contribute.
See the [Contribution Guide](https://pcsx2.net/docs/contributing/) for more info on how to contribute.

View File

@@ -4,7 +4,7 @@
<h1>Third-Party Licenses</h1>
<h2>Index</h2>
<h2>Table of Contents</h2>
<ul>
<li><a href="#pcsx2">PCSX2 - PS2 Emulator for PCs</a></li>
@@ -37,6 +37,7 @@
<li><a href="#llvm">LLVM</a></li>
<li><a href="#lz4">LZ4</a></li>
<li><a href="#lzmasdk">LZMA SDK</a></li>
<li><a href="#notosans">Noto Sans</a></li>
<li><a href="#pixevents">PixEvents</a></li>
<li><a href="#plutosvg">PlutoSVG</a></li>
<li><a href="#plutovg">PlutoVG</a></li>
@@ -45,6 +46,7 @@
<li><a href="#rapidjson">RapidJSON</a></li>
<li><a href="#rcheevos">rcheevos</a></li>
<li><a href="#remixicon">Remix Icon</a></li>
<li><a href="#roboto">Roboto</a></li>
<li><a href="#shaderc">Shaderc</a></li>
<li><a href="#simpleini">simpleini</a></li>
<li><a href="#soundtouch">SoundTouch audio processing library</a></li>
@@ -3636,6 +3638,105 @@ for any purpose, commercial or non-commercial, and by any means.
</pre>
</div>
<div id="notosans">
<h3>Noto Sans - <a href="https://notofonts.github.io/">https://notofonts.github.io/</a></h3>
<pre>
Copyright 2022 The Noto Project Authors (https://github.com/notofonts/hebrew)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
&quot;Font Software&quot; refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
&quot;Reserved Font Name&quot; refers to any names specified as such after the
copyright statement(s).
&quot;Original Version&quot; refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
&quot;Modified Version&quot; refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
&quot;Author&quot; refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION &amp; CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
</pre>
</div>
<div id="pixevents">
<h3>PixEvents - <a href="https://github.com/microsoft/PixEvents">https://github.com/microsoft/PixEvents</a></h3>
<pre>
@@ -4149,6 +4250,105 @@ SOFTWARE.
</pre>
</div>
<div id="roboto">
<h3>Roboto - <a href="https://fonts.google.com/specimen/Roboto">https://fonts.google.com/specimen/Roboto</a></h3>
<pre>
Copyright 2011 The Roboto Project Authors (https://github.com/googlefonts/roboto-classic)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
https://openfontlicense.org
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
&quot;Font Software&quot; refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
&quot;Reserved Font Name&quot; refers to any names specified as such after the
copyright statement(s).
&quot;Original Version&quot; refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
&quot;Modified Version&quot; refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
&quot;Author&quot; refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION &amp; CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
</pre>
</div>
<div id="shaderc">
<h3>Shaderc - <a href="https://github.com/google/shaderc">https://github.com/google/shaderc</a></h3>
<pre>

File diff suppressed because it is too large Load Diff

View File

@@ -154,6 +154,7 @@
03000000120c0000f10e000000000000,Brook PS2 Adapter,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000120c0000310c000000000000,Brook Super Converter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,
030000005a1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
030000005b1c00002400000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
030000005b1c00002500000000000000,Capcom Home Arcade Controller,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
@@ -336,6 +337,7 @@
03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows,
03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows,
03000000242f00000a20000000000000,Hyperkin Scout,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
03000000242e00000a20000000000000,Hyperkin Scout Premium SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows,
03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
03000000d81d00000f00000000000000,iBuffalo BSGP1204 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,
@@ -418,7 +420,7 @@
03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000d620000010a7000000000000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000242e0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
03000000242f0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
03000000242f0000f400000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows,
030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
@@ -484,7 +486,7 @@
030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,start:b11,x:b3,y:b4,platform:Windows,
0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,
03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -691,6 +693,7 @@
03000000317300000100000000000000,Sony DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000666600006706000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
03000000e30500009605000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000fe1400002a23000000000000,Sony PlayStation Adapter,a:b0,b:b1,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,x:b2,y:b3,platform:Windows,
030000004c050000da0c000000000000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000632500002306000000000000,Sony PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000f0250000c183000000000000,Sony PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -1008,6 +1011,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b15,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000550900001472000025050000,NVIDIA Controller,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Mac OS X,
030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X,
0300000009120000072f000000010000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a2,leftx:a0,lefty:a1,righttrigger:a5,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Mac OS X,
030000006f0e00000901000002010000,PDP PS3 Versus Fighting,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:Mac OS X,
030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000d620000011a7000000020000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
@@ -1100,6 +1104,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,
050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,
030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4~,start:b8,x:b2,y:b3,platform:Mac OS X,
030000006f0e00000104000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
03000000c6240000045d000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
@@ -1278,7 +1283,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e00008401000011010000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e00008101000011010000,Faceoff Deluxe Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03005036852100000201000010010000,Final Fantasy XIV Online 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:Linux,
03000000852100000201000010010000,FF GP1,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:Linux,
05000000b40400001224000001010000,Flydigi APEX 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b20,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -1290,6 +1295,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,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,
03000000ac0500007a05000011010000,GameSir G5,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000373500009710000001020000,GameSir Kaleid Flux,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:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000bc2000005656000011010000,GameSir T4w,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
@@ -1600,6 +1606,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
0300132d9b2800006500000001010000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
030000009b2800003200000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
030000009b2800006000000001010000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
030000009b2800006100000001010000,Raphnet N64 Adapter,+rightx:b9,+righty:b7,-rightx:b8,-righty:b6,a:b0,b:b1,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,lefttrigger:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b3,platform:Linux,
030000009b2800008000000020020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux,
030000009b2800008000000001010000,Raphnet Wii Classic Adapter V3,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Linux,
03000000f8270000bf0b000011010000,Razer Kishi,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,
@@ -1765,6 +1772,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
050000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,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,
050000005e040000fd02000030110000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000dd02000003020000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
050000005e040000e302000002090000,Xbox One Elite,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -1795,6 +1803,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
050000005e040000130b000022050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000200b000013050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000200b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="PCSX2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2675 329.6"><g id="vectorized_by_maxihplay"><path id="_2" d="M2181.5,5.7h438.1c27.8,0,50.4,22.6,50.4,50.4v92.5c0,27.8-22.6,50.4-50.4,50.4h-309.5v46.5h359.9v78.6h-488.5v-145.3c0-27.8,22.6-50.4,50.4-50.4h309.5v-50.8h-315l-44.9-71.9h0Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="10" stroke-width="10"/><g id="X"><polygon points="1619.8 5.7 1769.1 5.7 1867.5 102 1961.6 5.9 2115.8 5.9 2115.8 77.2 2039.6 77.2 1954.7 164 2037.1 245.4 2115.8 245.4 2115.8 324.1 1968.4 324.1 1867.8 224 1767.8 324 1619.8 324 1619.8 244.8 1699.3 244.8 1779.3 165.8 1692.8 77.2 1619.8 77.2 1619.8 5.7" fill="#3caeff" stroke-width="0"/><path d="M1623.2,8.7l17.5,17.5v30.1h57c3.1,0,6,1.2,8.2,3.4l93.8,93.4c7.3,7.3,7.2,19.1-.1,26.3l-86,84.2c-3.1,3-7.3,4.8-11.7,4.8h-61.2l-18.5-21.5,77-2.1,80.1-79.1-86.5-88.5h-73V5.7l3.4,3h0Z" fill="#279ff5" stroke-width="0"/><path d="M1623.9,9.7l16.8,16.5h121.8l93.4,93.4c6.7,6.7,17.6,6.7,24.3,0l92.6-92.5h121.8l19.2-19.2-152.1-2-94.1,96.1-98.3-96.3-145.4,4h0Z" fill="#50b6ff" stroke-width="0"/><path d="M2114.7,247.9l-20.2,20.6h-62.1c-3.8,0-7.4-1.5-10-4.1l-85.5-85.5c-7.7-7.6-7.7-20.1,0-27.7l90-90c3.2-3.2,7.5-5,12-5h55.5v-29l20.3-19.9,1.2,70-76.1,1.4-85,85.5,82.4,81.3h78.8l-1.3,2.4Z" fill="#34a2f2" stroke-width="0"/><path d="M1619.8,323.5l1.7-77.8,19.2,22.7v34h115.6c1.1,0,2.1-.4,2.8-1.2l95.2-95.2c7.8-7.8,20.4-7.7,28.1.1l92.9,94.7c.7.7,1.7,1.2,2.8,1.2h116.9l-.5-33.5,22-24.5-.6,80.1h-147.4l-100.6-100.1-100.1,100.1-148-.6h0Z" fill="#43b9f2" stroke-width="0"/><polygon points="1619.8 5.7 1769.1 5.7 1867.5 102 1961.6 5.9 2115.8 5.9 2115.8 77.2 2039.6 77.2 1954.7 164 2037.1 245.4 2115.8 245.4 2115.8 324.1 1968.4 324.1 1867.8 224 1767.8 324 1619.8 324 1619.8 244.8 1699.3 244.8 1779.3 165.8 1692.8 77.2 1619.8 77.2 1619.8 5.7" fill="none" stroke="#5d73cb" stroke-miterlimit="10" stroke-width="11"/></g><path id="S" d="M1554.7,5.7h-434c-27.8,0-50.4,22.6-50.4,50.4v95.9c0,27.9,22.6,50.4,50.4,50.4h302.8v43.3h-353.2v78.4h434c27.8,0,50.4-22.6,50.4-50.4v-97.6c0-27.9-22.6-50.4-50.4-50.4h-303.9v-48.1h306.3l48-71.9Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="10" stroke-width="10"/><path id="C" d="M1008.1,5.1h-395.5c-27.8,0-50.4,22.6-50.4,50.4v217.9c0,28,22.7,50.8,50.8,50.8h385.2v-79.2h-304.3V78.2h263.3l50.9-73.1Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="10" stroke-width="10"/><path id="P" d="M5,55.5C5,27.6,27.6,5,55.5,5h390.3c27.7,0,50.2,22.5,50.2,50.2v139.4c0,27.9-22.6,50.4-50.5,50.4l-284-.6,64.2-71.9h139.8v-95h-225.4v246.5H5V55.5Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="10" stroke-width="10"/></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -313,6 +313,127 @@ float ps_convert_rgb5a1_float16_biln(PS_INPUT input) : SV_Depth
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
}
PS_OUTPUT ps_convert_rgb5a1_8i(PS_INPUT input)
{
PS_OUTPUT output;
// Convert a RGB5A1 texture into a 8 bits packed texture
// Input column: 16x2 RGB5A1 pixels
// 0: 16 RGBA
// 1: 16 RGBA
// Output column: 16x4 Index pixels
// 0: 16 R5G2
// 1: 16 R5G2
// 2: 16 G2B5A1
// 3: 16 G2B5A1
uint2 pos = uint2(input.p.xy);
// Collapse separate R G B A areas into their base pixel
uint2 column = (pos & ~uint2(0u, 3u)) / uint2(1,2);
uint2 subcolumn = (pos & uint2(0u, 1u));
column.x -= (column.x / 128) * 64;
column.y += (column.y / 32) * 32;
uint PSM = uint(DOFFSET);
// Deal with swizzling differences
if ((PSM & 0x8) != 0) // PSMCT16S
{
if ((pos.x & 32) != 0)
{
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32;
}
if ((pos.x & 64) != 0)
{
column.x -= 32;
}
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
{
column.x ^= 32;
column.y ^= 16;
}
}
else // PSMCT16
{
if ((pos.y & 32) != 0)
{
column.y -= 16;
column.x += 32;
}
if ((pos.x & 96) != 0)
{
uint multi = (pos.x & 96) / 32;
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96);
}
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
{
column.x ^= 32;
column.y ^= 32;
}
}
uint2 coord = column | subcolumn;
// Compensate for potentially differing page pitch.
uint SBW = uint(EMODA);
uint DBW = uint(EMODC);
uint2 block_xy = coord / uint2(64,64);
uint block_num = (block_xy.y * (DBW / 128)) + block_xy.x;
uint2 block_offset = uint2((block_num % (SBW / 64)) * 64, (block_num / (SBW / 64)) * 64);
coord = (coord % uint2(64, 64)) + block_offset;
// Apply offset to cols 1 and 2
uint is_col23 = pos.y & 4u;
uint is_col13 = pos.y & 2u;
uint is_col12 = is_col23 ^ (is_col13 << 1);
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
float ScaleFactor = BGColor.x;
if (floor(ScaleFactor) != ScaleFactor)
coord = uint2(float2(coord) * ScaleFactor);
else
coord *= uint(ScaleFactor);
float4 pixel = Texture.Load(int3(int2(coord), 0));
uint4 denorm_c = (uint4)(pixel * 255.5f);
if ((pos.y & 2u) == 0u)
{
uint red = (denorm_c.r >> 3) & 0x1Fu;
uint green = (denorm_c.g >> 3) & 0x1Fu;
float sel0 = (float)(((green << 5) | red) & 0xFF) / 255.0f;
output.c = (float4)(sel0);
}
else
{
uint green = (denorm_c.g >> 3) & 0x1Fu;
uint blue = (denorm_c.b >> 3) & 0x1Fu;
uint alpha = denorm_c.a & 0x80u;
float sel0 = (float)((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
output.c = (float4)(sel0);
}
return output;
}
PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
{
PS_OUTPUT output;

View File

@@ -397,7 +397,11 @@ float4 fetch_raw_color(int2 xy)
float4 fetch_c(int2 uv)
{
#if PS_TEX_IS_FB == 1
return RtTexture.Load(int3(uv, 0));
#else
return Texture.Load(int3(uv, 0));
#endif
}
//////////////////////////////////////////////////////////////////////

View File

@@ -237,9 +237,131 @@ void ps_convert_rgb5a1_float16_biln()
}
#endif
#ifdef ps_convert_rgb5a1_8i
uniform uint SBW;
uniform uint DBW;
uniform uint PSM;
uniform float ScaleFactor;
void ps_convert_rgb5a1_8i()
{
// Convert a RGB5A1 texture into a 8 bits packed texture
// Input column: 16x2 RGB5A1 pixels
// 0: 16 RGBA
// 1: 16 RGBA
// Output column: 16x4 Index pixels
// 0: 16 R5G2
// 1: 16 R5G2
// 2: 16 G2B5A1
// 3: 16 G2B5A1
uvec2 pos = uvec2(gl_FragCoord.xy);
// Collapse separate R G B A areas into their base pixel
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1,2);
uvec2 subcolumn = (pos & uvec2(0u, 1u));
column.x -= (column.x / 128) * 64;
column.y += (column.y / 32) * 32;
// Deal with swizzling differences
if ((PSM & 0x8) != 0) // PSMCT16S
{
if ((pos.x & 32) != 0)
{
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32;
}
if ((pos.x & 64) != 0)
{
column.x -= 32;
}
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
{
column.x ^= 32;
column.y ^= 16;
}
}
else // PSMCT16
{
if ((pos.y & 32) != 0)
{
column.y -= 16;
column.x += 32;
}
if ((pos.x & 96) != 0)
{
uint multi = (pos.x & 96) / 32;
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96);
}
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
{
column.x ^= 32;
column.y ^= 32;
}
}
uvec2 coord = column | subcolumn;
// Compensate for potentially differing page pitch.
uvec2 block_xy = coord / uvec2(64u, 64u);
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 64u);
coord = (coord % uvec2(64u, 64u)) + block_offset;
// Apply offset to cols 1 and 2
uint is_col23 = pos.y & 4u;
uint is_col13 = pos.y & 2u;
uint is_col12 = is_col23 ^ (is_col13 << 1);
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
if (floor(ScaleFactor) != ScaleFactor)
coord = uvec2(vec2(coord) * ScaleFactor);
else
coord *= uvec2(ScaleFactor);
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
uvec4 denorm_c = uvec4(pixel * 255.5f);
if ((pos.y & 2u) == 0u)
{
uint red = (denorm_c.r >> 3) & 0x1Fu;
uint green = (denorm_c.g >> 3) & 0x1Fu;
float sel0 = float(((green << 5) | red) & 0xFF) / 255.0f;
SV_Target0 = vec4(sel0);
}
else
{
uint green = (denorm_c.g >> 3) & 0x1Fu;
uint blue = (denorm_c.b >> 3) & 0x1Fu;
uint alpha = denorm_c.a & 0x80u;
float sel0 = float((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
SV_Target0 = vec4(sel0);
}
}
#endif
#ifdef ps_convert_rgba_8i
uniform uint SBW;
uniform uint DBW;
uniform uint PSM;
uniform float ScaleFactor;
void ps_convert_rgba_8i()

View File

@@ -330,7 +330,11 @@ vec4 fetch_raw_color()
vec4 fetch_c(ivec2 uv)
{
#if PS_TEX_IS_FB == 1
return sample_from_rt();
#else
return texelFetch(TextureSampler, ivec2(uv), 0);
#endif
}
//////////////////////////////////////////////////////////////////////

View File

@@ -307,12 +307,138 @@ void ps_convert_rgb5a1_float16_biln()
}
#endif
#ifdef ps_convert_rgb5a1_8i
layout(push_constant) uniform cb10
{
uint SBW;
uint DBW;
uint PSM;
float cb_pad1;
float ScaleFactor;
vec3 cb_pad2;
};
void ps_convert_rgb5a1_8i()
{
// Convert a RGB5A1 texture into a 8 bits packed texture
// Input column: 16x2 RGB5A1 pixels
// 0: 16 RGBA
// 1: 16 RGBA
// Output column: 16x4 Index pixels
// 0: 16 R5G2
// 1: 16 R5G2
// 2: 16 G2B5A1
// 3: 16 G2B5A1
uvec2 pos = uvec2(gl_FragCoord.xy);
// Collapse separate R G B A areas into their base pixel
uvec2 column = (pos & ~uvec2(0u, 3u)) / uvec2(1,2);
uvec2 subcolumn = (pos & uvec2(0u, 1u));
column.x -= (column.x / 128) * 64;
column.y += (column.y / 32) * 32;
// Deal with swizzling differences
if ((PSM & 0x8) != 0) // PSMCT16S
{
if ((pos.x & 32) != 0)
{
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32;
}
if ((pos.x & 64) != 0)
{
column.x -= 32;
}
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
{
column.x ^= 32;
column.y ^= 16;
}
}
else // PSMCT16
{
if ((pos.y & 32) != 0)
{
column.y -= 16;
column.x += 32;
}
if ((pos.x & 96) != 0)
{
uint multi = (pos.x & 96) / 32;
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96);
}
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16;
column.y ^= 8;
}
if ((PSM & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
{
column.x ^= 32;
column.y ^= 32;
}
}
uvec2 coord = column | subcolumn;
// Compensate for potentially differing page pitch.
uvec2 block_xy = coord / uvec2(64u, 64u);
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 64u);
coord = (coord % uvec2(64u, 64u)) + block_offset;
// Apply offset to cols 1 and 2
uint is_col23 = pos.y & 4u;
uint is_col13 = pos.y & 2u;
uint is_col12 = is_col23 ^ (is_col13 << 1);
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
if (floor(ScaleFactor) != ScaleFactor)
coord = uvec2(vec2(coord) * ScaleFactor);
else
coord *= uvec2(ScaleFactor);
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
uvec4 denorm_c = uvec4(pixel * 255.5f);
if ((pos.y & 2u) == 0u)
{
uint red = (denorm_c.r >> 3) & 0x1Fu;
uint green = (denorm_c.g >> 3) & 0x1Fu;
float sel0 = float(((green << 5) | red) & 0xFF) / 255.0f;
o_col0 = vec4(sel0);
}
else
{
uint green = (denorm_c.g >> 3) & 0x1Fu;
uint blue = (denorm_c.b >> 3) & 0x1Fu;
uint alpha = denorm_c.a & 0x80u;
float sel0 = float((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
o_col0 = vec4(sel0);
}
}
#endif
#ifdef ps_convert_rgba_8i
layout(push_constant) uniform cb10
{
uint SBW;
uint DBW;
uvec2 cb_pad1;
uint PSM;
float cb_pad1;
float ScaleFactor;
vec3 cb_pad2;
};

View File

@@ -7,7 +7,7 @@ include(GNUInstallDirs)
# Misc option
#-------------------------------------------------------------------------------
option(ENABLE_TESTS "Enables building the unit tests" ON)
option(ENABLE_GSRUNNER "Enables building the GSRunner" OFF)
option(ENABLE_GSRUNNER "Enables building the GSRunner by default. It can still be built with `make pcsx2-gsrunner` otherwise." OFF)
option(LTO_PCSX2_CORE "Enable LTO/IPO/LTCG on the subset of pcsx2 that benefits most from it but not anything else")
option(USE_VTUNE "Plug VTUNE to profile GS JIT.")
option(PACKAGE_MODE "Use this option to ease packaging of PCSX2 (developer/distribution option)")
@@ -64,10 +64,13 @@ set(CMAKE_SHARED_LINKER_FLAGS_DEVEL "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}
CACHE STRING "Flags used for linking shared libraries during development builds" FORCE)
set(CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}"
CACHE STRING "Flags used for linking executables during development builds" FORCE)
# Exclude Debug from the configurations we can import from
set(CMAKE_MAP_IMPORTED_CONFIG_DEVEL "RelWithDebInfo" "Release" "MinSizeRel" "None" "NoConfig" ""
CACHE STRING "Configurations used when importing packages for development builds" FORCE)
if(CMAKE_CONFIGURATION_TYPES)
list(INSERT CMAKE_CONFIGURATION_TYPES 0 Devel)
endif()
mark_as_advanced(CMAKE_C_FLAGS_DEVEL CMAKE_CXX_FLAGS_DEVEL CMAKE_LINKER_FLAGS_DEVEL CMAKE_SHARED_LINKER_FLAGS_DEVEL CMAKE_EXE_LINKER_FLAGS_DEVEL)
mark_as_advanced(CMAKE_C_FLAGS_DEVEL CMAKE_CXX_FLAGS_DEVEL CMAKE_LINKER_FLAGS_DEVEL CMAKE_SHARED_LINKER_FLAGS_DEVEL CMAKE_EXE_LINKER_FLAGS_DEVEL CMAKE_MAP_IMPORTED_CONFIG_DEVEL)
#-------------------------------------------------------------------------------
# Select the architecture

View File

@@ -120,7 +120,7 @@ add_subdirectory(3rdparty/demangler EXCLUDE_FROM_ALL)
add_subdirectory(3rdparty/ccc EXCLUDE_FROM_ALL)
# The docking system for the debugger.
find_package(KDDockWidgets-qt6 REQUIRED)
find_package(KDDockWidgets-qt6 2.0.0 REQUIRED)
# Add an extra include path to work around a broken include directive.
# TODO: Remove this the next time we update KDDockWidgets.
get_target_property(KDDOCKWIDGETS_INCLUDE_DIRECTORY KDAB::kddockwidgets INTERFACE_INCLUDE_DIRECTORIES)

View File

@@ -31,6 +31,19 @@ namespace CocoaTools
bool DelayedLaunch(std::string_view file);
/// Open a Finder window to the given URL
bool ShowInFinder(std::string_view file);
/// Get the path to the resources directory of the current application
std::optional<std::string> GetResourcePath();
/// Create a window
void* CreateWindow(std::string_view title, uint32_t width, uint32_t height);
/// Destroy a window
void DestroyWindow(void* window);
/// Make a WindowInfo from the given window
void GetWindowInfoFromWindow(WindowInfo* wi, void* window);
/// Run cocoa event loop
void RunCocoaEventLoop(bool wait_forever = false);
/// Posts an event to the main telling `RunCocoaEventLoop(true)` to exit
void StopMainThreadEventLoop();
}
#endif // __APPLE__

View File

@@ -224,5 +224,103 @@ bool CocoaTools::DelayedLaunch(std::string_view file)
bool CocoaTools::ShowInFinder(std::string_view file)
{
return [[NSWorkspace sharedWorkspace] selectFile:NSStringFromStringView(file)
inFileViewerRootedAtPath:nil];
inFileViewerRootedAtPath:@""];
}
std::optional<std::string> CocoaTools::GetResourcePath()
{ @autoreleasepool {
if (NSBundle* bundle = [NSBundle mainBundle])
{
NSString* rsrc = [bundle resourcePath];
NSString* root = [bundle bundlePath];
if ([rsrc isEqualToString:root])
rsrc = [rsrc stringByAppendingString:@"/resources"];
return [rsrc UTF8String];
}
return std::nullopt;
}}
// MARK: - GSRunner
void* CocoaTools::CreateWindow(std::string_view title, u32 width, u32 height)
{
if (!NSApp)
{
[NSApplication sharedApplication];
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp finishLaunching];
}
constexpr NSWindowStyleMask style = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable;
NSScreen* mainScreen = [NSScreen mainScreen];
// Center the window on the screen, because why not
NSRect screenFrame = [mainScreen frame];
NSRect viewFrame = screenFrame;
viewFrame.size = NSMakeSize(width, height);
viewFrame.origin.x += (screenFrame.size.width - viewFrame.size.width) / 2;
viewFrame.origin.y += (screenFrame.size.height - viewFrame.size.height) / 2;
NSWindow* window = [[NSWindow alloc]
initWithContentRect:viewFrame
styleMask:style
backing:NSBackingStoreBuffered
defer:NO];
[window setTitle:NSStringFromStringView(title)];
[window makeKeyAndOrderFront:window];
return (__bridge_retained void*)window;
}
void CocoaTools::DestroyWindow(void* window)
{
(void)(__bridge_transfer NSWindow*)window;
}
void CocoaTools::GetWindowInfoFromWindow(WindowInfo* wi, void* cf_window)
{
if (cf_window)
{
NSWindow* window = (__bridge NSWindow*)cf_window;
float scale = [window backingScaleFactor];
NSView* view = [window contentView];
NSRect dims = [view frame];
wi->type = WindowInfo::Type::MacOS;
wi->window_handle = (__bridge void*)view;
wi->surface_width = dims.size.width * scale;
wi->surface_height = dims.size.height * scale;
wi->surface_scale = scale;
}
else
{
wi->type = WindowInfo::Type::Surfaceless;
}
}
static constexpr short STOP_EVENT_LOOP = 0x100;
void CocoaTools::RunCocoaEventLoop(bool forever)
{
NSDate* end = forever ? [NSDate distantFuture] : [NSDate distantPast];
[NSApplication sharedApplication]; // Ensure NSApp is initialized
while (true)
{ @autoreleasepool {
NSEvent* ev = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:end
inMode:NSDefaultRunLoopMode
dequeue:YES];
if (!ev || ([ev type] == NSEventTypeApplicationDefined && [ev subtype] == STOP_EVENT_LOOP))
break;
[NSApp sendEvent:ev];
}}
}
void CocoaTools::StopMainThreadEventLoop()
{ @autoreleasepool {
NSEvent* ev = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
location:{}
modifierFlags:0
timestamp:0
windowNumber:0
context:nil
subtype:STOP_EVENT_LOOP
data1:0
data2:0];
[NSApp postEvent:ev atStart:NO];
}}

View File

@@ -437,7 +437,7 @@ std::unique_ptr<SharedMemoryMappingArea> SharedMemoryMappingArea::Create(size_t
{
pxAssertRel(Common::IsAlignedPow2(size, __pagesize), "Size is page aligned");
mach_vm_address_t alloc;
mach_vm_address_t alloc = 0;
const kern_return_t res =
mach_vm_map(mach_task_self(), &alloc, size, 0, VM_FLAGS_ANYWHERE,
MEMORY_OBJECT_NULL, 0, false, VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_NONE);

View File

@@ -4,8 +4,10 @@
<ItemDefinitionGroup>
<Link>
<AdditionalLibraryDirectories>$(DepsLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies);freetype.lib;jpeg.lib;libpng16.lib;libwebp.lib;lz4.lib;SDL3.lib;zlib.lib;zstd.lib;kddockwidgets-qt62.lib;plutovg.lib;plutosvg.lib</AdditionalDependencies>
</Link>
<AdditionalDependencies>%(AdditionalDependencies);freetype.lib;jpeg.lib;libpng16.lib;libwebp.lib;lz4.lib;SDL3.lib;zlib.lib;zstd.lib;plutovg.lib;plutosvg.lib</AdditionalDependencies>
<AdditionalDependencies Condition="$(Configuration.Contains(Debug))">%(AdditionalDependencies);kddockwidgets-qt6d.lib;</AdditionalDependencies>
<AdditionalDependencies Condition="!$(Configuration.Contains(Debug))">%(AdditionalDependencies);kddockwidgets-qt6.lib;</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<DepsDLLs Include="$(DepsBinDir)freetype.dll" />
@@ -19,7 +21,8 @@
<DepsDLLs Include="$(DepsBinDir)shaderc_shared.dll" />
<DepsDLLs Include="$(DepsBinDir)zlib1.dll" />
<DepsDLLs Include="$(DepsBinDir)zstd.dll" />
<DepsDLLs Include="$(DepsBinDir)kddockwidgets-qt62.dll" />
<DepsDLLs Condition="$(Configuration.Contains(Debug))" Include="$(DepsBinDir)kddockwidgets-qt6d.dll" />
<DepsDLLs Condition="!$(Configuration.Contains(Debug))" Include="$(DepsBinDir)kddockwidgets-qt6.dll" />
<DepsDLLs Include="$(DepsBinDir)plutovg.dll" />
<DepsDLLs Include="$(DepsBinDir)plutosvg.dll" />
</ItemGroup>

View File

@@ -16,6 +16,7 @@
#include "fmt/format.h"
#include "common/Assertions.h"
#include "common/CocoaTools.h"
#include "common/Console.h"
#include "common/CrashHandler.h"
#include "common/FileSystem.h"
@@ -56,7 +57,8 @@ namespace GSRunner
static bool CreatePlatformWindow();
static void DestroyPlatformWindow();
static std::optional<WindowInfo> GetPlatformWindowInfo();
static void PumpPlatformMessages();
static void PumpPlatformMessages(bool forever = false);
static void StopPlatformMessagePump();
} // namespace GSRunner
static constexpr u32 WINDOW_WIDTH = 640;
@@ -809,6 +811,22 @@ void GSRunner::DumpStats()
#define main real_main
#endif
static void CPUThreadMain(VMBootParameters* params) {
if (VMManager::Initialize(*params))
{
// run until end
GSDumpReplayer::SetLoopCount(s_loop_count);
VMManager::SetState(VMState::Running);
while (VMManager::GetState() == VMState::Running)
VMManager::Execute();
VMManager::Shutdown(false);
GSRunner::DumpStats();
}
VMManager::Internal::CPUThreadShutdown();
GSRunner::StopPlatformMessagePump();
}
int main(int argc, char* argv[])
{
CrashHandler::Install();
@@ -837,16 +855,9 @@ int main(int argc, char* argv[])
VMManager::ApplySettings();
GSDumpReplayer::SetIsDumpRunner(true);
if (VMManager::Initialize(params))
{
// run until end
GSDumpReplayer::SetLoopCount(s_loop_count);
VMManager::SetState(VMState::Running);
while (VMManager::GetState() == VMState::Running)
VMManager::Execute();
VMManager::Shutdown(false);
GSRunner::DumpStats();
}
std::thread cputhread(CPUThreadMain, &params);
GSRunner::PumpPlatformMessages(/*forever=*/true);
cputhread.join();
VMManager::Internal::CPUThreadShutdown();
GSRunner::DestroyPlatformWindow();
@@ -859,9 +870,6 @@ void Host::PumpMessagesOnCPUThread()
// update GS thread copy of frame number
MTGS::RunOnGSThread([frame_number = GSDumpReplayer::GetFrameNumber()]() { s_dump_frame_number = frame_number; });
MTGS::RunOnGSThread([loop_number = GSDumpReplayer::GetLoopCount()]() { s_loop_number = loop_number; });
// process any window messages (but we shouldn't really have any)
GSRunner::PumpPlatformMessages();
}
s32 Host::Internal::GetTranslatedStringImpl(
@@ -975,16 +983,32 @@ std::optional<WindowInfo> GSRunner::GetPlatformWindowInfo()
return wi;
}
void GSRunner::PumpPlatformMessages()
static constexpr int SHUTDOWN_MSG = WM_APP + 0x100;
static DWORD MainThreadID;
void GSRunner::PumpPlatformMessages(bool forever)
{
MSG msg;
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
while (true)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == SHUTDOWN_MSG)
return;
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
if (!forever)
return;
WaitMessage();
}
}
void GSRunner::StopPlatformMessagePump()
{
PostThreadMessageW(MainThreadID, SHUTDOWN_MSG, 0, 0);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
return DefWindowProcW(hwnd, msg, wParam, lParam);
@@ -1003,7 +1027,51 @@ int wmain(int argc, wchar_t** argv)
u8_argptrs.push_back(u8_args[i].data());
u8_argptrs.push_back(nullptr);
MainThreadID = GetCurrentThreadId();
return real_main(argc, u8_argptrs.data());
}
#endif // _WIN32
#elif defined(__APPLE__)
static void* s_window;
static WindowInfo s_wi;
bool GSRunner::CreatePlatformWindow()
{
pxAssertRel(!s_window, "Tried to create window when there already was one!");
s_window = CocoaTools::CreateWindow("PCSX2 GS Runner", WINDOW_WIDTH, WINDOW_HEIGHT);
CocoaTools::GetWindowInfoFromWindow(&s_wi, s_window);
PumpPlatformMessages();
return s_window;
}
void GSRunner::DestroyPlatformWindow()
{
if (s_window) {
CocoaTools::DestroyWindow(s_window);
s_window = nullptr;
}
}
std::optional<WindowInfo> GSRunner::GetPlatformWindowInfo()
{
WindowInfo wi;
if (s_window)
wi = s_wi;
else
wi.type = WindowInfo::Type::Surfaceless;
return wi;
}
void GSRunner::PumpPlatformMessages(bool forever)
{
CocoaTools::RunCocoaEventLoop(forever);
}
void GSRunner::StopPlatformMessagePump()
{
CocoaTools::StopMainThreadEventLoop();
}
#endif // _WIN32 / __APPLE__

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>576</width>
<height>294</height>
<width>580</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
@@ -19,45 +19,42 @@
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
<property name="sizeType">
<enum>QSizePolicy::Policy::Preferred</enum>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="icon">
<property name="maximumSize">
<property name="minimumSize">
<size>
<width>260</width>
<height>260</height>
<width>1</width>
<height>1</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="resources/resources.qrc">:/icons/logo.png</pixmap>
<pixmap resource="resources/resources.qrc">:/icons/PCSX2logo.svg</pixmap>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
<property name="sizeType">
<enum>QSizePolicy::Policy::Preferred</enum>
</property>
</spacer>
</item>
@@ -69,7 +66,7 @@
<string extracomment="SCM= Source Code Management">SCM Version</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
@@ -79,7 +76,7 @@
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its purpose is to emulate the PS2's hardware, using a combination of MIPS CPU Interpreters, Recompilers and a Virtual Machine which manages hardware states and PS2 system memory. This allows you to play PS2 games on your PC, with many additional features and benefits.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
<set>Qt::AlignmentFlag::AlignJustify|Qt::AlignmentFlag::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -89,23 +86,31 @@
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="disclaimer">
<property name="font">
<font>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;PlayStation 2 and PS2 are registered trademarks of Sony Interactive Entertainment. This application is not affiliated in any way with Sony Interactive Entertainment.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
<set>Qt::AlignmentFlag::AlignJustify|Qt::AlignmentFlag::AlignVCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
@@ -115,12 +120,15 @@
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
@@ -131,19 +139,22 @@
<string notr="true">TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
@@ -151,7 +162,7 @@
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
<set>QDialogButtonBox::StandardButton::Close</set>
</property>
<property name="centerButtons">
<bool>true</bool>
@@ -162,7 +173,6 @@
</widget>
<resources>
<include location="resources/resources.qrc"/>
<include location="resources/icons.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-3.0+
#include "CoverDownloadDialog.h"
#include "QtUtils.h"
#include "pcsx2/GameList.h"
@@ -11,7 +12,7 @@ CoverDownloadDialog::CoverDownloadDialog(QWidget* parent /*= nullptr*/)
: QDialog(parent)
{
m_ui.setupUi(this);
m_ui.coverIcon->setPixmap(QIcon::fromTheme("artboard-2-line").pixmap(32));
QtUtils::SetScalableIcon(m_ui.coverIcon, QIcon::fromTheme(QStringLiteral("artboard-2-line")), QSize(32, 32));
updateEnabled();
connect(m_ui.start, &QPushButton::clicked, this, &CoverDownloadDialog::onStartClicked);

View File

@@ -149,7 +149,9 @@ DockTabBar::DockTabBar(KDDockWidgets::Core::TabBar* controller, QWidget* parent)
// that ends up taking ownerhsip of the style for the entire application!
if (QProxyStyle* proxy_style = qobject_cast<QProxyStyle*>(style()))
{
proxy_style->baseStyle()->setParent(qApp);
if (proxy_style->baseStyle() == qApp->style())
proxy_style->baseStyle()->setParent(qApp);
proxy_style->setBaseStyle(QStyleFactory::create(qApp->style()->name()));
}
}

View File

@@ -10,6 +10,7 @@
#include <kddockwidgets/Config.h>
#include <kddockwidgets/core/Group.h>
#include <kddockwidgets/core/Platform.h>
#include <kddockwidgets/core/indicators/SegmentedDropIndicatorOverlay.h>
#include <kddockwidgets/qtwidgets/ViewFactory.h>

View File

@@ -72,7 +72,7 @@
</item>
<item>
<property name="text">
<string>Array of byte</string>
<string>Byte Array</string>
</property>
</item>
</widget>

View File

@@ -65,16 +65,17 @@ void ThreadView::openContextMenu(QPoint pos)
void ThreadView::onDoubleClick(const QModelIndex& index)
{
auto real_index = m_proxy_model->mapToSource(index);
switch (index.column())
{
case ThreadModel::ThreadColumns::ENTRY:
{
goToInMemoryView(m_model->data(index, Qt::UserRole).toUInt(), true);
goToInDisassembler(m_model->data(real_index, Qt::UserRole).toUInt(), true);
break;
}
default: // Default to PC
{
QModelIndex pc_index = m_model->index(index.row(), ThreadModel::ThreadColumns::PC);
QModelIndex pc_index = m_model->index(real_index.row(), ThreadModel::ThreadColumns::PC);
goToInDisassembler(m_model->data(pc_index, Qt::UserRole).toUInt(), true);
break;
}

View File

@@ -52,12 +52,12 @@ DisplayWidget::~DisplayWidget()
int DisplayWidget::scaledWindowWidth() const
{
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * QtUtils::GetDevicePixelRatioForWidget(this))), 1);
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * devicePixelRatioF())), 1);
}
int DisplayWidget::scaledWindowHeight() const
{
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * QtUtils::GetDevicePixelRatioForWidget(this))), 1);
return std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * devicePixelRatioF())), 1);
}
std::optional<WindowInfo> DisplayWidget::getWindowInfo()
@@ -268,7 +268,7 @@ bool DisplayWidget::event(QEvent* event)
if (!m_relative_mouse_enabled)
{
const qreal dpr = QtUtils::GetDevicePixelRatioForWidget(this);
const qreal dpr = devicePixelRatioF();
const QPoint mouse_pos = mouse_event->pos();
const float scaled_x = static_cast<float>(static_cast<qreal>(mouse_pos.x()) * dpr);
@@ -349,13 +349,12 @@ bool DisplayWidget::event(QEvent* event)
return true;
}
// According to https://bugreports.qt.io/browse/QTBUG-95925 the recommended practice for handling DPI change is responding to paint events
case QEvent::Paint:
case QEvent::DevicePixelRatioChange:
case QEvent::Resize:
{
QWidget::event(event);
const float dpr = QtUtils::GetDevicePixelRatioForWidget(this);
const float dpr = devicePixelRatioF();
const u32 scaled_width = static_cast<u32>(std::max(static_cast<int>(std::ceil(static_cast<qreal>(width()) * dpr)), 1));
const u32 scaled_height = static_cast<u32>(std::max(static_cast<int>(std::ceil(static_cast<qreal>(height()) * dpr)), 1));

View File

@@ -25,17 +25,17 @@ static constexpr int COVER_ART_HEIGHT = 512;
static constexpr int COVER_ART_SPACING = 32;
static constexpr int MIN_COVER_CACHE_SIZE = 256;
static int DPRScale(int size, float dpr)
static int DPRScale(int size, qreal dpr)
{
return static_cast<int>(static_cast<float>(size) * dpr);
return static_cast<int>(static_cast<qreal>(size) * dpr);
}
static int DPRUnscale(int size, float dpr)
static int DPRUnscale(int size, qreal dpr)
{
return static_cast<int>(static_cast<float>(size) / dpr);
return static_cast<int>(static_cast<qreal>(size) / dpr);
}
static void resizeAndPadPixmap(QPixmap* pm, int expected_width, int expected_height, float dpr)
static void resizeAndPadPixmap(QPixmap* pm, int expected_width, int expected_height, qreal dpr)
{
const int dpr_expected_width = DPRScale(expected_width, dpr);
const int dpr_expected_height = DPRScale(expected_height, dpr);
@@ -71,9 +71,8 @@ static void resizeAndPadPixmap(QPixmap* pm, int expected_width, int expected_hei
}
static QPixmap createPlaceholderImage(const QPixmap& placeholder_pixmap, int width, int height, float scale,
const std::string& title)
qreal dpr, const std::string& title)
{
const float dpr = qApp->devicePixelRatio();
QPixmap pm(placeholder_pixmap.copy());
pm.setDevicePixelRatio(dpr);
if (pm.isNull())
@@ -113,9 +112,10 @@ const char* GameListModel::getColumnName(Column col)
return s_column_names[static_cast<int>(col)];
}
GameListModel::GameListModel(float cover_scale, bool show_cover_titles, QObject* parent /* = nullptr */)
GameListModel::GameListModel(float cover_scale, bool show_cover_titles, qreal dpr, QObject* parent /* = nullptr */)
: QAbstractTableModel(parent)
, m_show_titles_for_covers(show_cover_titles)
, m_dpr{dpr}
{
loadSettings();
loadCommonImages();
@@ -160,6 +160,13 @@ void GameListModel::updateCacheSize(int width, int height)
m_cover_pixmap_cache.SetMaxCapacity(static_cast<int>(std::max(num_columns * num_rows, MIN_COVER_CACHE_SIZE)));
}
void GameListModel::setDevicePixelRatio(qreal dpr)
{
m_dpr = dpr;
loadCommonImages();
refreshCovers();
}
void GameListModel::loadOrGenerateCover(const GameList::Entry* ge)
{
// Why this counter: Every time we change the cover scale, we increment the counter variable. This way if the scale is changed
@@ -173,12 +180,11 @@ void GameListModel::loadOrGenerateCover(const GameList::Entry* ge)
const std::string cover_path(GameList::GetCoverImagePathForEntry(&entry));
if (!cover_path.empty())
{
const float dpr = qApp->devicePixelRatio();
image = QPixmap(QString::fromStdString(cover_path));
if (!image.isNull())
{
image.setDevicePixelRatio(dpr);
resizeAndPadPixmap(&image, getCoverArtWidth(), getCoverArtHeight(), dpr);
image.setDevicePixelRatio(m_dpr);
resizeAndPadPixmap(&image, getCoverArtWidth(), getCoverArtHeight(), m_dpr);
}
}
}
@@ -186,7 +192,7 @@ void GameListModel::loadOrGenerateCover(const GameList::Entry* ge)
const std::string& title = entry.GetTitle(m_prefer_english_titles);
if (image.isNull())
image = createPlaceholderImage(m_placeholder_pixmap, getCoverArtWidth(), getCoverArtHeight(), m_cover_scale, title);
image = createPlaceholderImage(m_placeholder_pixmap, getCoverArtWidth(), getCoverArtHeight(), m_cover_scale, m_dpr, title);
if (m_cover_scale_counter.load(std::memory_order_acquire) != counter)
image = {};
@@ -440,7 +446,7 @@ bool GameListModel::titlesLessThan(int left_row, int right_row) const
const GameList::Entry* left = GameList::GetEntryByIndex(left_row);
const GameList::Entry* right = GameList::GetEntryByIndex(right_row);
return QtHost::LocaleSensitiveCompare(QString::fromStdString(left->GetTitleSort(m_prefer_english_titles)),
QString::fromStdString(right->GetTitleSort(m_prefer_english_titles))) < 0;
QString::fromStdString(right->GetTitleSort(m_prefer_english_titles))) < 0;
}
bool GameListModel::lessThan(const QModelIndex& left_index, const QModelIndex& right_index, int column) const
@@ -569,16 +575,16 @@ QIcon GameListModel::getIconForType(GameList::EntryType type)
QIcon GameListModel::getIconForRegion(GameList::Region region)
{
return QIcon(
QStringLiteral("%1/icons/flags/%2.svg").arg(QtHost::GetResourcesBasePath()).arg(GameList::RegionToString(region)));
QStringLiteral("%1/icons/flags/%2.svg").arg(QtHost::GetResourcesBasePath()).arg(GameList::RegionToString(region, false)));
}
void GameListModel::loadThemeSpecificImages()
{
for (u32 type = 0; type < static_cast<u32>(GameList::EntryType::Count); type++)
m_type_pixmaps[type] = getIconForType(static_cast<GameList::EntryType>(type)).pixmap(QSize(24, 24));
m_type_pixmaps[type] = getIconForType(static_cast<GameList::EntryType>(type)).pixmap(QSize(24, 24), m_dpr);
for (u32 i = 0; i < static_cast<u32>(GameList::Region::Count); i++)
m_region_pixmaps[i] = getIconForRegion(static_cast<GameList::Region>(i)).pixmap(QSize(36, 26));
m_region_pixmaps[i] = getIconForRegion(static_cast<GameList::Region>(i)).pixmap(QSize(36, 26), m_dpr);
}
void GameListModel::loadCommonImages()
@@ -587,7 +593,7 @@ void GameListModel::loadCommonImages()
const QString base_path(QtHost::GetResourcesBasePath());
for (u32 i = 1; i < GameList::CompatibilityRatingCount; i++)
m_compatibility_pixmaps[i].load(QStringLiteral("%1/icons/star-%2.svg").arg(base_path).arg(i - 1));
m_compatibility_pixmaps[i] = QIcon((QStringLiteral("%1/icons/star-%2.svg").arg(base_path).arg(i - 1))).pixmap(QSize(88, 16), m_dpr);
m_placeholder_pixmap.load(QStringLiteral("%1/cover-placeholder.png").arg(base_path));
}

View File

@@ -43,7 +43,7 @@ public:
static QIcon getIconForType(GameList::EntryType type);
static QIcon getIconForRegion(GameList::Region region);
GameListModel(float cover_scale, bool show_cover_titles, QObject* parent = nullptr);
GameListModel(float cover_scale, bool show_cover_titles, qreal dpr, QObject* parent = nullptr);
~GameListModel();
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
@@ -71,6 +71,8 @@ public:
void refreshCovers();
void updateCacheSize(int width, int height);
void setDevicePixelRatio(qreal dpr);
Q_SIGNALS:
void coverScaleChanged();
@@ -94,6 +96,7 @@ private:
std::array<QPixmap, static_cast<u32>(GameList::Region::Count)> m_region_pixmaps;
QPixmap m_placeholder_pixmap;
QPixmap m_loading_pixmap;
qreal m_dpr;
std::array<QPixmap, static_cast<int>(GameList::CompatibilityRatingCount)> m_compatibility_pixmaps;
mutable LRUCache<std::string, QPixmap> m_cover_pixmap_cache;

View File

@@ -128,22 +128,25 @@ namespace
const int pix_width = static_cast<int>(pix.width() / pix.devicePixelRatio());
const int pix_height = static_cast<int>(pix.height() / pix.devicePixelRatio());
// Clip the pixmaps so they don't extend outside the column
painter->save();
painter->setClipRect(option.rect);
// Draw the icon, using code derived from QItemDelegate::drawDecoration()
const bool enabled = option.state & QStyle::State_Enabled;
const QPoint p = QPoint((r.width() - pix_width) / 2, (r.height() - pix_height) / 2);
if (option.state & QStyle::State_Selected)
{
// See QItemDelegate::selectedPixmap()
QString key = QString::fromStdString(fmt::format("{:016X}-{:d}", pix.cacheKey(), enabled));
// See QItemDelegate::selectedPixmap()
QColor color = option.palette.color(enabled ? QPalette::Normal : QPalette::Disabled, QPalette::Highlight);
color.setAlphaF(0.3f);
QString key = QString::fromStdString(fmt::format("{:016X}-{:d}-{:08X}", pix.cacheKey(), enabled, color.rgba()));
QPixmap pm;
if (!QPixmapCache::find(key, &pm))
{
QImage img = pix.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
QColor color = option.palette.color(enabled ? QPalette::Normal : QPalette::Disabled,
QPalette::Highlight);
color.setAlphaF(0.3f);
QPainter tinted_painter(&img);
tinted_painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
tinted_painter.fillRect(0, 0, img.width(), img.height(), color);
@@ -159,6 +162,9 @@ namespace
{
painter->drawPixmap(r.topLeft() + p, pix);
}
// Restore the old clip path.
painter->restore();
}
};
} // namespace
@@ -174,22 +180,27 @@ void GameListWidget::initialize()
{
const float cover_scale = Host::GetBaseFloatSettingValue("UI", "GameListCoverArtScale", 0.45f);
const bool show_cover_titles = Host::GetBaseBoolSettingValue("UI", "GameListShowCoverTitles", true);
m_model = new GameListModel(cover_scale, show_cover_titles, this);
m_model = new GameListModel(cover_scale, show_cover_titles, devicePixelRatioF(), this);
m_model->updateCacheSize(width(), height());
m_sort_model = new GameListSortModel(m_model);
m_sort_model->setSourceModel(m_model);
m_ui.setupUi(this);
for (u32 type = 0; type < static_cast<u32>(GameList::EntryType::Count); type++)
{
m_ui.filterType->addItem(GameListModel::getIconForType(static_cast<GameList::EntryType>(type)),
qApp->translate("GameList", GameList::EntryTypeToDisplayString(static_cast<GameList::EntryType>(type))));
if (type != static_cast<u32>(GameList::EntryType::Invalid))
{
m_ui.filterType->addItem(GameListModel::getIconForType(static_cast<GameList::EntryType>(type)),
GameList::EntryTypeToString(static_cast<GameList::EntryType>(type), true));
}
}
for (u32 region = 0; region < static_cast<u32>(GameList::Region::Count); region++)
{
m_ui.filterRegion->addItem(GameListModel::getIconForRegion(static_cast<GameList::Region>(region)),
qApp->translate("GameList", GameList::RegionToString(static_cast<GameList::Region>(region))));
GameList::RegionToString(static_cast<GameList::Region>(region), true));
}
connect(m_ui.viewGameList, &QPushButton::clicked, this, &GameListWidget::showGameList);
@@ -547,6 +558,18 @@ void GameListWidget::resizeEvent(QResizeEvent* event)
m_model->updateCacheSize(width(), height());
}
bool GameListWidget::event(QEvent* event)
{
if (event->type() == QEvent::DevicePixelRatioChange)
{
m_model->setDevicePixelRatio(devicePixelRatioF());
QWidget::event(event);
return true;
}
return QWidget::event(event);
}
void GameListWidget::resizeTableViewColumnsToFit()
{
QtUtils::ResizeColumnsForTableView(m_table_view, {

View File

@@ -93,6 +93,7 @@ public Q_SLOTS:
protected:
void resizeEvent(QResizeEvent* event);
bool event(QEvent* event) override;
private:
void loadTableViewColumnVisibilitySettings();

View File

@@ -103,9 +103,9 @@
<addaction name="actionMemoryCardSettings"/>
<addaction name="actionDEV9Settings"/>
<addaction name="actionFolderSettings"/>
<addaction name="actionAchievementSettings"/>
<addaction name="actionControllerSettings"/>
<addaction name="actionHotkeySettings"/>
<addaction name="actionAchievementSettings"/>
<addaction name="separator"/>
<addaction name="actionAddGameDirectory"/>
<addaction name="actionScanForNewGames"/>

View File

@@ -254,15 +254,6 @@ namespace QtUtils
widget->resize(width, height);
}
qreal GetDevicePixelRatioForWidget(const QWidget* widget)
{
const QScreen* screen_for_ratio = widget->screen();
if (!screen_for_ratio)
screen_for_ratio = QGuiApplication::primaryScreen();
return screen_for_ratio ? screen_for_ratio->devicePixelRatio() : static_cast<qreal>(1);
}
std::optional<WindowInfo> GetWindowInfoForWidget(QWidget* widget)
{
WindowInfo wi;
@@ -303,7 +294,7 @@ namespace QtUtils
}
#endif
const qreal dpr = GetDevicePixelRatioForWidget(widget);
const qreal dpr = widget->devicePixelRatioF();
wi.surface_width = static_cast<u32>(static_cast<qreal>(widget->width()) * dpr);
wi.surface_height = static_cast<u32>(static_cast<qreal>(widget->height()) * dpr);
wi.surface_scale = static_cast<float>(dpr);
@@ -374,4 +365,37 @@ namespace QtUtils
return true;
}
class IconVariableDpiFilter : QObject
{
public:
explicit IconVariableDpiFilter(QLabel* lbl, const QIcon& icon, const QSize& size, QObject* parent = nullptr)
: QObject(parent)
, m_lbl{lbl}
, m_icn{icon}
, m_size{size}
{
lbl->installEventFilter(this);
m_lbl->setPixmap(m_icn.pixmap(m_size, m_lbl->devicePixelRatioF()));
}
protected:
bool eventFilter(QObject* object, QEvent* event) override
{
if (object == m_lbl && event->type() == QEvent::DevicePixelRatioChange)
m_lbl->setPixmap(m_icn.pixmap(m_size, m_lbl->devicePixelRatioF()));
// Don't block the event
return false;
}
private:
QLabel* m_lbl;
QIcon m_icn;
QSize m_size;
};
void SetScalableIcon(QLabel* lbl, const QIcon& icon, const QSize& size)
{
new IconVariableDpiFilter(lbl, icon, size, lbl);
}
} // namespace QtUtils

View File

@@ -20,6 +20,7 @@ class QAction;
class QComboBox;
class QFileInfo;
class QFrame;
class QIcon;
class QLabel;
class QKeyEvent;
class QSlider;
@@ -82,9 +83,6 @@ namespace QtUtils
/// Adjusts the fixed size for a window if it's not resizeable.
void ResizePotentiallyFixedSizeWindow(QWidget* widget, int width, int height);
/// Returns the pixel ratio/scaling factor for a widget.
qreal GetDevicePixelRatioForWidget(const QWidget* widget);
/// Returns the common window info structure for a Qt widget.
std::optional<WindowInfo> GetWindowInfoForWidget(QWidget* widget);
@@ -102,4 +100,8 @@ namespace QtUtils
bool IsLightTheme(const QPalette& palette);
bool IsCompositorManagerRunning();
/// Sets the scalable icon to a given label (svg icons, or icons with multiple size pixmaps)
/// The icon will then be reloaded on DPR changes using an event filter
void SetScalableIcon(QLabel* lbl, const QIcon& icon, const QSize& size);
} // namespace QtUtils

View File

@@ -3,6 +3,7 @@
#include "AchievementLoginDialog.h"
#include "QtHost.h"
#include "QtUtils.h"
#include "pcsx2/Achievements.h"
@@ -15,7 +16,7 @@ AchievementLoginDialog::AchievementLoginDialog(QWidget* parent, Achievements::Lo
, m_reason(reason)
{
m_ui.setupUi(this);
m_ui.loginIcon->setPixmap(QIcon::fromTheme("login-box-line").pixmap(32));
QtUtils::SetScalableIcon(m_ui.loginIcon, QIcon::fromTheme(QStringLiteral("login-box-line")), QSize(32, 32));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
// Adjust text if needed based on reason.
@@ -116,7 +117,6 @@ void AchievementLoginDialog::processLoginResult(bool result, const QString& mess
g_emu_thread->resetVM();
}
}
}
done(0);

View File

@@ -342,7 +342,7 @@ void AudioSettingsWidget::onExpansionSettingsClicked()
QDialog dlg(QtUtils::GetRootWidget(this));
Ui::AudioExpansionSettingsDialog dlgui;
dlgui.setupUi(&dlg);
dlgui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("volume-up-line")).pixmap(32, 32));
QtUtils::SetScalableIcon(dlgui.icon, QIcon::fromTheme(QStringLiteral("volume-up-line")), QSize(32, 32));
SettingsInterface* sif = m_dialog->getSettingsInterface();
SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.blockSize, "SPU2/Output", "ExpandBlockSize",
@@ -431,7 +431,7 @@ void AudioSettingsWidget::onStretchSettingsClicked()
QDialog dlg(QtUtils::GetRootWidget(this));
Ui::AudioStretchSettingsDialog dlgui;
dlgui.setupUi(&dlg);
dlgui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("volume-up-line")).pixmap(32, 32));
QtUtils::SetScalableIcon(dlgui.icon, QIcon::fromTheme(QStringLiteral("volume-up-line")), QSize(32, 32));
SettingsInterface* sif = m_dialog->getSettingsInterface();
SettingWidgetBinder::BindWidgetToIntSetting(sif, dlgui.sequenceLength, "SPU2/Output", "StretchSequenceLengthMS",

View File

@@ -170,7 +170,7 @@ ControllerMouseSettingsDialog::ControllerMouseSettingsDialog(QWidget* parent, Co
SettingsInterface* sif = dialog->getProfileSettingsInterface();
m_ui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("mouse-line")).pixmap(32, 32));
QtUtils::SetScalableIcon(m_ui.icon, QIcon::fromTheme(QStringLiteral("mouse-line")), QSize(32, 32));
ControllerSettingWidgetBinder::BindWidgetToInputProfileFloat(sif, m_ui.pointerXSpeedSlider, "Pad", "PointerXSpeed", 40.0f);
ControllerSettingWidgetBinder::BindWidgetToInputProfileFloat(sif, m_ui.pointerYSpeedSlider, "Pad", "PointerYSpeed", 40.0f);
@@ -202,11 +202,10 @@ ControllerMappingSettingsDialog::ControllerMappingSettingsDialog(ControllerSetti
SettingsInterface* sif = parent->getProfileSettingsInterface();
m_ui.icon->setPixmap(QIcon::fromTheme(QStringLiteral("settings-3-line")).pixmap(32, 32));
QtUtils::SetScalableIcon(m_ui.icon, QIcon::fromTheme(QStringLiteral("settings-3-line")), QSize(32, 32));
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.ignoreInversion, "InputSources", "IgnoreInversion", false);
connect(m_ui.buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &QDialog::accept);
}
ControllerMappingSettingsDialog::~ControllerMappingSettingsDialog() = default;

View File

@@ -33,7 +33,7 @@ GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsWindo
for (int i = 0; i < m_ui.region->count(); i++)
{
m_ui.region->setItemIcon(i,
QIcon(QStringLiteral("%1/icons/flags/%2.svg").arg(base_path).arg(GameList::RegionToString(static_cast<GameList::Region>(i)))));
QIcon(QStringLiteral("%1/icons/flags/%2.svg").arg(base_path).arg(GameList::RegionToString(static_cast<GameList::Region>(i), false))));
}
m_entry_path = entry->path;
@@ -73,16 +73,17 @@ void GameSummaryWidget::populateDetails(const GameList::Entry* entry)
m_ui.type->setCurrentIndex(static_cast<int>(entry->type));
m_ui.region->setCurrentIndex(static_cast<int>(entry->region));
//: First arg is a GameList compat; second is a string with space followed by star rating OR empty if Unknown compat
m_ui.compatibility->setText(tr("%0%1")
.arg(GameList::EntryCompatibilityRatingToString(entry->compatibility_rating))
.arg([entry]() {
if (entry->compatibility_rating == GameList::CompatibilityRating::Unknown)
return QStringLiteral("");
m_ui.compatibility->setText(
tr("%0%1")
.arg(GameList::EntryCompatibilityRatingToString(entry->compatibility_rating, true))
.arg([entry]() {
if (entry->compatibility_rating == GameList::CompatibilityRating::Unknown)
return QStringLiteral("");
const qsizetype compatibility_value = static_cast<qsizetype>(entry->compatibility_rating);
//: First arg is filled-in stars for game compatibility; second is empty stars; should be swapped for RTL languages
return tr(" %0%1").arg(QStringLiteral("").repeated(compatibility_value - 1)).arg(QStringLiteral("").repeated(6 - compatibility_value));
}()));
const qsizetype compatibility_value = static_cast<qsizetype>(entry->compatibility_rating);
//: First arg is filled-in stars for game compatibility; second is empty stars; should be swapped for RTL languages
return tr(" %0%1").arg(QStringLiteral("").repeated(compatibility_value - 1)).arg(QStringLiteral("").repeated(6 - compatibility_value));
}()));
int row = 0;
m_ui.detailsFormLayout->getWidgetPosition(m_ui.titleSort, &row, nullptr);
@@ -156,7 +157,7 @@ void GameSummaryWidget::onDiscPathChanged(const QString& value)
// force rescan of elf to update the serial
g_main_window->rescanFile(m_entry_path);
auto lock = GameList::GetLock();
const GameList::Entry* entry = GameList::GetEntryForPath(m_entry_path.c_str());
if (entry)

View File

@@ -9,6 +9,7 @@
#include <QtWidgets/QPushButton>
#include "Settings/MemoryCardCreateDialog.h"
#include "QtUtils.h"
#include "pcsx2/SIO/Memcard/MemoryCardFile.h"
@@ -16,7 +17,7 @@ MemoryCardCreateDialog::MemoryCardCreateDialog(QWidget* parent /* = nullptr */)
: QDialog(parent)
{
m_ui.setupUi(this);
m_ui.icon->setPixmap(QIcon::fromTheme("memcard-line").pixmap(m_ui.icon->width()));
QtUtils::SetScalableIcon(m_ui.icon, QIcon::fromTheme(QStringLiteral("memcard-line")), QSize(m_ui.icon->width(), m_ui.icon->width()));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);

View File

@@ -10,6 +10,7 @@
#include <QtCore/QFile>
#include <QtGui/QPalette>
#include <QtGui/QPixmapCache>
#include <QtWidgets/QApplication>
#include <QtWidgets/QStyle>
#include <QtWidgets/QStyleFactory>
@@ -43,6 +44,12 @@ void QtHost::UpdateApplicationTheme()
SetStyleFromSettings();
SetIconThemeFromStyle();
// Qt generates tinted versions of icons and stores them in QPixmapCache
// The key used does not seem to include the theme (or tint colour).
// This can cause icons tinted for wrong theme to be used for selected/disabled.
// As a workaround, reset the pixmap cache to clear icons tinted for the old theme.
QPixmapCache::clear();
}
bool QtHost::IsDarkApplicationTheme()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="PCSX2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 280.11 34.51"><g id="vectorized_by_maxihplay"><path id="_2" d="M228.43.6h45.87c2.91,0,5.28,2.37,5.28,5.28v9.69c0,2.91-2.37,5.28-5.28,5.28h-32.41v4.87h37.69v8.23h-51.15v-15.21c0-2.91,2.37-5.28,5.28-5.28h32.41v-5.32h-32.98l-4.7-7.53Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="1.05" stroke-width="1.05"/><g id="X"><polygon id="polygon1" points="221.55 25.7 221.55 33.94 206.12 33.94 195.58 23.46 185.11 33.93 169.61 33.93 169.61 25.63 177.94 25.63 186.32 17.36 177.26 8.08 169.61 8.08 169.61 .6 185.25 .6 195.55 10.68 205.41 .62 221.55 .62 221.55 8.08 213.57 8.08 204.68 17.17 213.31 25.7 221.55 25.7" fill="#3caeff" stroke-width="0"/><path id="path1" d="M169.97.91l1.83,1.83v3.15h5.97c.32,0,.63.13.86.36l9.82,9.78c.76.76.75,2-.01,2.75l-9.01,8.82c-.32.31-.76.5-1.23.5h-6.41l-1.94-2.25,8.06-.22,8.39-8.28-9.06-9.27h-7.64V.6l.36.31Z" fill="#279ff5" stroke-width="0"/><path id="path2" d="M170.04,1.02l1.76,1.73h12.75l9.78,9.78c.7.7,1.84.7,2.54,0l9.7-9.69h12.75l2.01-2.01-15.93-.21-9.85,10.06-10.29-10.08-15.23.42Z" fill="#50b6ff" stroke-width="0"/><path id="path3" d="M221.44,25.96l-2.12,2.16h-6.5c-.4,0-.77-.16-1.05-.43l-8.95-8.95c-.81-.8-.81-2.1,0-2.9l9.42-9.42c.34-.34.79-.52,1.26-.52h5.81v-3.04l2.13-2.08.13,7.33-7.97.15-8.9,8.95,8.63,8.51h8.25l-.14.25Z" fill="#34a2f2" stroke-width="0"/><path id="path4" d="M169.61,33.87l.18-8.15,2.01,2.38v3.56h12.1c.12,0,.22-.04.29-.13l9.97-9.97c.82-.82,2.14-.81,2.94.01l9.73,9.92c.07.07.18.13.29.13h12.24l-.05-3.51,2.3-2.57-.06,8.39h-15.43l-10.53-10.48-10.48,10.48-15.5-.06Z" fill="#43b9f2" stroke-width="0"/><polygon id="polygon4" points="221.55 25.7 221.55 33.94 206.12 33.94 195.58 23.46 185.11 33.93 169.61 33.93 169.61 25.63 177.94 25.63 186.32 17.36 177.26 8.08 169.61 8.08 169.61 .6 185.25 .6 195.55 10.68 205.41 .62 221.55 .62 221.55 8.08 213.57 8.08 204.68 17.17 213.31 25.7 221.55 25.7" fill="none" stroke="#5d73cb" stroke-miterlimit="1.05" stroke-width="1.15"/></g><path id="S" d="M162.8.6h-45.45c-2.91,0-5.28,2.37-5.28,5.28v10.04c0,2.92,2.37,5.28,5.28,5.28h31.71v4.53h-36.98v8.21h45.45c2.91,0,5.28-2.37,5.28-5.28v-10.22c0-2.92-2.37-5.28-5.28-5.28h-31.82v-5.04h32.07l5.03-7.53Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="1.05" stroke-width="1.05"/><path id="C" d="M105.56.53h-41.41c-2.91,0-5.28,2.37-5.28,5.28v22.82c0,2.93,2.38,5.32,5.32,5.32h40.34v-8.29h-31.86V8.19h27.57l5.33-7.65Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="1.05" stroke-width="1.05"/><path id="P" d="M.52,5.81C.52,2.89,2.89.52,5.81.52h40.87c2.9,0,5.26,2.36,5.26,5.26v14.6c0,2.92-2.37,5.28-5.29,5.28l-29.74-.06,6.72-7.53h14.64v-9.95H14.67v25.81H.52V5.81Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="1.05" stroke-width="1.05"/></g></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -103,7 +103,7 @@
<file>icons/black/svg/window-2-line.svg</file>
<file>icons/black/svg/zoom-in-line.svg</file>
<file>icons/black/svg/zoom-out-line.svg</file>
<file>icons/logo.png</file>
<file>icons/PCSX2logo.svg</file>
<file>icons/QT.png</file>
<file>icons/update.png</file>
<file>icons/white/index.theme</file>

View File

@@ -1455,7 +1455,7 @@ static uint cdvdStartSeek(uint newsector, CDVD_MODE_TYPE mode, bool transition_t
}
isSeeking = true;
}
else if(!drive_speed_change_cycles)
else if (!drive_speed_change_cycles)
{
CDVD_LOG("CdSeek Begin > Contiguous block without seek - delta=%d sectors", delta);

View File

@@ -5,6 +5,7 @@
#include "common/Pcsx2Defs.h"
#include <array>
#include <string>
class Error;

View File

@@ -222,7 +222,7 @@ bool IOCtlSrc::ReadDVDInfo()
{
Console.Warning("IOCTL_DVD_READ_STRUCTURE not supported");
}
else if(GetLastError() != ERROR_UNRECOGNIZED_MEDIA) // ERROR_UNRECOGNIZED_MEDIA means probably a CD or no disc
else if (GetLastError() != ERROR_UNRECOGNIZED_MEDIA) // ERROR_UNRECOGNIZED_MEDIA means probably a CD or no disc
{
Console.Warning("IOCTL Unknown Error %d", GetLastError());
}

View File

@@ -1237,9 +1237,16 @@ fixup_file_properties(PCSX2)
force_include_last(PCSX2_FLAGS "/(usr|local)/include/?$")
if (APPLE)
find_library(APPKIT_LIBRARY AppKit)
find_library(IOKIT_LIBRARY IOKit)
find_library(METAL_LIBRARY Metal)
find_library(QUARTZCORE_LIBRARY QuartzCore)
target_link_libraries(PCSX2_FLAGS INTERFACE ${METAL_LIBRARY} ${QUARTZCORE_LIBRARY})
target_link_libraries(PCSX2_FLAGS INTERFACE
${APPKIT_LIBRARY}
${IOKIT_LIBRARY}
${METAL_LIBRARY}
${QUARTZCORE_LIBRARY}
)
endif()
set_property(GLOBAL PROPERTY PCSX2_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
@@ -1286,7 +1293,11 @@ function(setup_main_executable target)
# Copy dependency libraries.
set(DEPS_BINDIR "${CMAKE_SOURCE_DIR}/deps/bin")
set(DEPS_TO_COPY freetype.dll harfbuzz.dll jpeg62.dll libpng16.dll libsharpyuv.dll libwebp.dll lz4.dll SDL3.dll shaderc_shared.dll zlib1.dll zstd.dll kddockwidgets-qt62.dll plutovg.dll plutosvg.dll)
set(DEPS_TO_COPY freetype.dll harfbuzz.dll jpeg62.dll libpng16.dll libsharpyuv.dll libwebp.dll lz4.dll SDL3.dll shaderc_shared.dll zlib1.dll zstd.dll plutovg.dll plutosvg.dll)
set(DEPS_TO_COPY
$<IF:$<CONFIG:Debug>,kddockwidgets-qt6d.dll,kddockwidgets-qt6.dll>
${DEPS_TO_COPY}
)
foreach(DEP_TO_COPY ${DEPS_TO_COPY})
install(FILES "${DEPS_BINDIR}/${DEP_TO_COPY}" DESTINATION "${CMAKE_SOURCE_DIR}/bin")
endforeach()

View File

@@ -33,7 +33,7 @@ struct BreakPoint
bool temporary = false;
bool stepping = false;
bool hasCond;
bool hasCond = false;
BreakPointCond cond;
BreakPointCpu cpu;

View File

@@ -236,7 +236,7 @@ static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
cpuClearInt( 10 );
QueuedDMA._u16 &= ~(1 << 10); //Clear any queued DMA requests for this channel
}
else if(channel == 2)
else if (channel == 2)
{
cpuClearInt( 11 );
QueuedDMA._u16 &= ~(1 << 11); //Clear any queued DMA requests for this channel
@@ -274,7 +274,7 @@ static __ri void DmaExec( void (*func)(), u32 mem, u32 value )
{
func();
}
else if(reg.chcr.STR)
else if (reg.chcr.STR)
{
//DevCon.Warning(L"32bit %s DMA Start while DMAC Disabled\n", ChcrName(mem));
QueuedDMA._u16 |= (1 << ChannelNumber(mem)); //Queue the DMA up to be started then the DMA's are Enabled and or the Suspend is lifted

View File

@@ -20,7 +20,11 @@ There are a number of ways to help the project, whether it be bug reporting, gam
* Want to make changes to emulator code? [Check out the issue tracker](https://github.com/PCSX2/pcsx2/issues), or [fork the PCSX2 repository and work on your own ideas](https://github.com/PCSX2/pcsx2).
* Want to patch games? [Check out the cheats and patches forum thread for inspiration](https://forums.pcsx2.net/Thread-Post-your-PCSX2-cheats-patches-here). There are other threads to find as well, [such as those dedicated to 60 FPS patches](https://forums.pcsx2.net/Thread-60-fps-codes) or [widescreen patches](https://forums.pcsx2.net/Thread-PCSX2-Widescreen-Game-Patches).
<<<<<<< HEAD
* Want to report bugs you have discovered in your games? Head over to [the Bug Reporting section of the PCSX2 forums](https://forums.pcsx2.net/Forum-Bug-reporting), to [the PCSX2 Discord](https://pcsx2.net/discord), or to [the GitHub issues section](https://github.com/PCSX2/pcsx2/issues).
=======
* Want to report bugs you have discovered in your games? [Head over to the Bug Reporting section of the PCSX2 forums](https://forums.pcsx2.net/Forum-Bug-reporting). Also check out our [Issue reporting guide](https://pcsx2.net/docs/troubleshooting/identify) for info on how to better report to us issues.
>>>>>>> 091a4ee5a (docs: update in order to redirect from the GH wiki to our website)
* Want to update us on the compatibility of your games? [Take a look at the Public Compatibility List on the PCSX2 forums](https://forums.pcsx2.net/Forum-Public-compatibility-list)
* Want to improve the PCSX2 wiki? [Here is how to contribute](https://wiki.pcsx2.net/How_to_contribute)
@@ -120,9 +124,7 @@ If you are using a disc:
Fast Boot, enabled by default, will directly mount and launch the game without first launching the PS2 BIOS. You may disable this in Settings > BIOS > Fast Boot if you wish to see the BIOS startup animation or if Fast Boot is causing an issue.
### Question 18: How do I build the PCSX2 source code?
* [Windows build guide](https://github.com/PCSX2/pcsx2/wiki/12-Building-on-Windows)
* [Linux build guide](https://github.com/PCSX2/pcsx2/wiki/10-Building-on-Linux)
* [macOS build guide](https://github.com/PCSX2/pcsx2/wiki/11-Building-on-MacOS)
Have a nice [building guide](https://pcsx2.net/docs/advanced/building) :) .
### Question 19: When will the next version be released?
It will be released when it is ready. Please don't waste your time and ours asking when.

View File

@@ -249,7 +249,6 @@ void CTC1() {
void CVT_S() {
_FdValf_ = (float)_FsValSl_;
_FdValf_ = fpuDouble( _FdValUl_ );
}
void CVT_W() {

View File

@@ -339,7 +339,7 @@ void GSClut::Read(const GIFRegTEX0& TEX0)
break;
}
}
else if(TEX0.CPSM == PSMCT16 || TEX0.CPSM == PSMCT16S)
else if (TEX0.CPSM == PSMCT16 || TEX0.CPSM == PSMCT16S)
{
switch(TEX0.PSM)
{
@@ -462,7 +462,8 @@ void GSClut::GetAlphaMinMax32(int& amin_out, int& amax_out)
{
// call only after Read32
pxAssert(!m_read.dirty);
if (m_read.dirty)
GL_INS("GSClut: GetAlphaMinMax32 m_read.dirty");
if (m_read.adirty)
{

View File

@@ -70,6 +70,7 @@ GSLocalMemory::GSLocalMemory()
psm.wfa = &GSLocalMemory::WritePixel32;
psm.bpp = psm.trbpp = 32;
psm.pal = 0;
psm.cs = GSVector2i(8, 2);
psm.bs = GSVector2i(8, 8);
psm.pgs = GSVector2i(64, 32);
psm.msk = 0xff;
@@ -197,6 +198,11 @@ GSLocalMemory::GSLocalMemory()
m_psm[PSMCT16].fmt = m_psm[PSMZ16].fmt = PSM_FMT_16;
m_psm[PSMCT16S].fmt = m_psm[PSMZ16S].fmt = PSM_FMT_16;
m_psm[PSGPU24].cs = GSVector2i(16, 2);
m_psm[PSMCT16].cs = m_psm[PSMCT16S].bs = GSVector2i(16, 2);
m_psm[PSMT8].cs = GSVector2i(16, 4);
m_psm[PSMT4].cs = GSVector2i(32, 4);
m_psm[PSMZ16].cs = m_psm[PSMZ16S].bs = GSVector2i(16, 2);
m_psm[PSGPU24].bs = GSVector2i(16, 8);
m_psm[PSMCT16].bs = m_psm[PSMCT16S].bs = GSVector2i(16, 8);

View File

@@ -460,7 +460,7 @@ public:
readTexture rtx, rtxP;
readTextureBlock rtxb, rtxbP;
u16 bpp, trbpp, pal, fmt;
GSVector2i bs, pgs;
GSVector2i cs, bs, pgs;
u8 msk, depth;
u32 fmsk;
};

View File

@@ -32,7 +32,7 @@ static __fi bool IsFirstProvokingVertex()
return (GSIsHardwareRenderer() && !g_gs_device->Features().provoking_vertex_last);
}
constexpr int GSState::GetSaveStateSize()
constexpr int GSState::GetSaveStateSize(int version)
{
int size = 0;
@@ -78,6 +78,19 @@ constexpr int GSState::GetSaveStateSize()
size += sizeof(m_tr.x);
size += sizeof(m_tr.y);
if (version >= 9)
{
size += sizeof(m_tr.w);
size += sizeof(m_tr.h);
size += sizeof(m_tr.m_blit);
size += sizeof(m_tr.m_pos);
size += sizeof(m_tr.m_reg);
size += sizeof(m_tr.rect);
size += sizeof(m_tr.total);
size += sizeof(m_tr.start);
size += sizeof(m_tr.end);
size += sizeof(m_tr.write);
}
size += GSLocalMemory::m_vmsize;
size += (sizeof(GIFPath::tag) + sizeof(GIFPath::reg)) * 4 /* std::size(GSState::m_path) */; // std::size won't work without an instance.
size += sizeof(m_q);
@@ -1445,10 +1458,10 @@ void GSState::GIFRegHandlerTRXDIR(const GIFReg* RESTRICT r)
switch (m_env.TRXDIR.XDIR)
{
case 0: // host -> local
m_tr.Init(m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, m_env.BITBLTBUF, true);
m_tr.Init(m_env.TRXPOS, m_env.TRXREG, m_env.BITBLTBUF, true);
break;
case 1: // local -> host
m_tr.Init(m_env.TRXPOS.SSAX, m_env.TRXPOS.SSAY, m_env.BITBLTBUF, false);
m_tr.Init(m_env.TRXPOS, m_env.TRXREG, m_env.BITBLTBUF, false);
break;
case 2: // local -> local
CheckWriteOverlap(true, true);
@@ -1549,16 +1562,13 @@ void GSState::FlushWrite()
GSVector4i r;
r.left = m_env.TRXPOS.DSAX;
r.top = m_env.TRXPOS.DSAY;
r.right = r.left + m_env.TRXREG.RRW;
r.bottom = r.top + m_env.TRXREG.RRH;
r = m_tr.rect;
InvalidateVideoMem(m_env.BITBLTBUF, r);
const GSLocalMemory::writeImage wi = GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].wi;
wi(m_mem, m_tr.x, m_tr.y, &m_tr.buff[m_tr.start], len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG);
wi(m_mem, m_tr.x, m_tr.y, &m_tr.buff[m_tr.start], len, m_tr.m_blit, m_tr.m_pos, m_tr.m_reg);
m_tr.start += len;
@@ -1931,12 +1941,9 @@ void GSState::Write(const u8* mem, int len)
if (m_env.TRXDIR.XDIR == 3)
return;
const int w = m_env.TRXREG.RRW;
const int h = m_env.TRXREG.RRH;
CheckWriteOverlap(true, false);
if (!m_tr.Update(w, h, GSLocalMemory::m_psm[m_env.BITBLTBUF.DPSM].trbpp, len))
if (!m_tr.Update(m_tr.w, m_tr.h, GSLocalMemory::m_psm[m_tr.m_blit.DPSM].trbpp, len))
{
m_env.TRXDIR.XDIR = 3;
return;
@@ -1949,10 +1956,7 @@ void GSState::Write(const u8* mem, int len)
{
GSVector4i r;
r.left = m_env.TRXPOS.DSAX;
r.top = m_env.TRXPOS.DSAY;
r.right = r.left + m_env.TRXREG.RRW;
r.bottom = r.top + m_env.TRXREG.RRH;
r = m_tr.rect;
s_last_transfer_draw_n = s_n;
// Store the transfer for preloading new RT's.
@@ -1974,15 +1978,15 @@ void GSState::Write(const u8* mem, int len)
GL_CACHE("Write! %u ... => 0x%x W:%d F:%s (DIR %d%d), dPos(%d %d) size(%d %d) draw %d", s_transfer_n,
blit.DBP, blit.DBW, psm_str(blit.DPSM),
m_env.TRXPOS.DIRX, m_env.TRXPOS.DIRY,
m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, w, h, s_n);
m_tr.m_pos.DIRX, m_tr.m_pos.DIRY,
m_tr.x, m_tr.y, m_tr.w, m_tr.h, s_n);
if (len >= m_tr.total)
{
// received all data in one piece, no need to buffer it
InvalidateVideoMem(blit, r);
psm.wi(m_mem, m_tr.x, m_tr.y, mem, m_tr.total, blit, m_env.TRXPOS, m_env.TRXREG);
psm.wi(m_mem, m_tr.x, m_tr.y, mem, m_tr.total, blit, m_tr.m_pos, m_tr.m_reg);
m_tr.start = m_tr.end = m_tr.total;
@@ -2260,7 +2264,7 @@ void GSState::Move()
vm[doff] = (vm[doff] & 0xff000000) | (vm[soff] & 0x00ffffff);
});
}
else // if(spsm.trbpp == 16)
else // if (spsm.trbpp == 16)
{
u16* vm = m_mem.vm16();
copy(dpo.assertSizesMatch(GSLocalMemory::swizzle16), spo.assertSizesMatch(GSLocalMemory::swizzle16), [vm](u32 doff, u32 soff)
@@ -2334,7 +2338,7 @@ void GSState::ReadLocalMemoryUnsync(u8* mem, int qwc, GIFRegBITBLTBUF BITBLTBUF,
GSTransferBuffer tb;
if(m_tr.end >= m_tr.total || m_tr.write == true)
tb.Init(TRXPOS.SSAX, TRXPOS.SSAY, BITBLTBUF, false);
tb.Init(TRXPOS, TRXREG, BITBLTBUF, false);
int len = qwc * 16;
if (!tb.Update(w, h, bpp, len))
@@ -2578,13 +2582,14 @@ static void ReadState(T* dst, u8*& src, size_t len = sizeof(T))
int GSState::Freeze(freezeData* fd, bool sizeonly)
{
const u32 version = STATE_VERSION;
if (sizeonly)
{
fd->size = GetSaveStateSize();
fd->size = GetSaveStateSize(version);
return 0;
}
if (!fd->data || fd->size < GetSaveStateSize())
if (!fd->data || fd->size < GetSaveStateSize(version))
return -1;
Flush(GSFlushReason::SAVESTATE);
@@ -2593,7 +2598,6 @@ int GSState::Freeze(freezeData* fd, bool sizeonly)
ReadbackTextureCache();
u8* data = fd->data;
const u32 version = STATE_VERSION;
WriteState(data, &version);
WriteState(data, &m_env.PRIM);
@@ -2636,6 +2640,18 @@ int GSState::Freeze(freezeData* fd, bool sizeonly)
data += sizeof(GIFReg); // obsolite
WriteState(data, &m_tr.x);
WriteState(data, &m_tr.y);
// Version 9 up.
WriteState(data, &m_tr.w);
WriteState(data, &m_tr.h);
WriteState(data, &m_tr.m_blit);
WriteState(data, &m_tr.m_pos);
WriteState(data, &m_tr.m_reg);
WriteState(data, &m_tr.rect);
WriteState(data, &m_tr.total);
WriteState(data, &m_tr.start);
WriteState(data, &m_tr.end);
WriteState(data, &m_tr.write);
// End of version 9 changes.
WriteState(data, m_mem.m_vm8, m_mem.m_vmsize);
for (GIFPath& path : m_path)
@@ -2663,15 +2679,15 @@ int GSState::Defrost(const freezeData* fd)
if (!fd || !fd->data || fd->size == 0)
return -1;
if (fd->size < GetSaveStateSize())
return -1;
u8* data = fd->data;
u32 version;
ReadState(&version, data);
if (fd->size < GetSaveStateSize(version))
return -1;
if (version > STATE_VERSION)
{
Console.Error("GS: Savestate version is incompatible. Load aborted.");
@@ -2701,12 +2717,6 @@ int GSState::Defrost(const freezeData* fd)
ReadState(&m_env.TRXPOS, data);
ReadState(&m_env.TRXREG, data);
ReadState(&m_env.TRXREG, data); // obsolete
// Technically this value ought to be saved like m_tr.x/y (break
// compatibility) but so far only a single game (Motocross Mania) really
// depends on this value (i.e != BITBLTBUF) Savestates are likely done at
// VSYNC, so not in the middle of a texture transfer, therefore register
// will be set again properly
m_tr.m_blit = m_env.BITBLTBUF;
for (int i = 0; i < 2; i++)
{
@@ -2742,9 +2752,36 @@ int GSState::Defrost(const freezeData* fd)
data += sizeof(GIFReg); // obsolite
ReadState(&m_tr.x, data);
ReadState(&m_tr.y, data);
ReadState(m_mem.m_vm8, data, m_mem.m_vmsize);
m_tr.total = 0; // TODO: restore transfer state
if (version >= 9)
{
ReadState(&m_tr.w, data);
ReadState(&m_tr.h, data);
ReadState(&m_tr.m_blit, data);
ReadState(&m_tr.m_pos, data);
ReadState(&m_tr.m_reg, data);
ReadState(&m_tr.rect, data);
ReadState(&m_tr.total, data);
ReadState(&m_tr.start, data);
ReadState(&m_tr.end, data);
ReadState(&m_tr.write, data);
}
else
{
m_tr.w = m_env.TRXREG.RRW;
m_tr.h = m_env.TRXREG.RRH;
m_tr.m_blit = m_env.BITBLTBUF;
m_tr.m_pos = m_env.TRXPOS;
m_tr.m_reg = m_env.TRXREG;
// Assume the last transfer was a write (but nuke it).
m_tr.rect = GSVector4i(m_env.TRXPOS.DSAX, m_env.TRXPOS.DSAY, m_env.TRXPOS.DSAX + m_tr.w, m_env.TRXPOS.DSAY + m_tr.h);
m_tr.total = 0;
m_tr.start = 0;
m_tr.end = 0;
m_tr.write = true;
}
ReadState(m_mem.m_vm8, data, m_mem.m_vmsize);
for (GIFPath& path : m_path)
{
@@ -3140,7 +3177,8 @@ bool GSState::SpriteDrawWithoutGaps()
}
else
{
if ((std::abs(dpX - first_dpX) >= 16 && (i + 2) < m_vertex.next) || std::abs(this_start_X - last_pX) >= 16)
const int dpY = v[i + 1].XYZ.Y - v[i].XYZ.Y;
if ((std::abs(dpY - first_dpY) >= 16 && (i + 2) < m_vertex.next) || std::abs(this_start_X - last_pX) >= 16)
return false;
}
}
@@ -3996,8 +4034,14 @@ GSState::TextureMinMaxResult GSState::GetTextureMinMax(GIFRegTEX0 TEX0, GIFRegCL
// If it's the start of the texture and our little adjustment is all that pushed it over, clamp it to 0.
// This stops the border check failing when using repeat but needed less than the full texture
// since this was making it take the full texture even though it wasn't needed.
if (!clamp_to_tsize && ((m_vt.m_min.t.floor() == GSVector4::zero()).mask() & 0x3) == 0x3)
st = st.max(GSVector4::zero());
if (!clamp_to_tsize)
{
const u32 mask = (m_vt.m_min.t.floor() == GSVector4::zero()).mask();
if (mask & 1) // X == 0
st.x = st.max(GSVector4::zero()).x;
if (mask & 2) // Y == 0
st.y = st.max(GSVector4::zero()).y;
}
}
// draw will get scissored, adjust UVs to suit
@@ -4556,14 +4600,19 @@ GSState::GSTransferBuffer::~GSTransferBuffer()
_aligned_free(buff);
}
void GSState::GSTransferBuffer::Init(int tx, int ty, const GIFRegBITBLTBUF& blit, bool is_write)
void GSState::GSTransferBuffer::Init(GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG, const GIFRegBITBLTBUF& blit, bool is_write)
{
x = tx;
y = ty;
x = is_write ? TRXPOS.DSAX : TRXPOS.SSAX;
y = is_write ? TRXPOS.DSAY : TRXPOS.SSAY;
w = TRXREG.RRW;
h = TRXREG.RRH;
rect = GSVector4i(x, y, x + w, y + h);
total = 0;
start = 0;
end = 0;
m_blit = blit;
m_pos = TRXPOS;
m_reg = TRXREG;
write = is_write;
}

View File

@@ -21,7 +21,7 @@ public:
GSState();
virtual ~GSState();
static constexpr int GetSaveStateSize();
static constexpr int GetSaveStateSize(int version);
private:
// RESTRICT prevents multiple loads of the same part of the register when accessing its bitfields (the compiler is happy to know that memory writes in-between will not go there)
@@ -108,15 +108,19 @@ private:
struct GSTransferBuffer
{
int x = 0, y = 0;
int w = 0, h = 0;
int start = 0, end = 0, total = 0;
u8* buff = nullptr;
GSVector4i rect = GSVector4i::zero();
GIFRegBITBLTBUF m_blit = {};
GIFRegTRXPOS m_pos = {};
GIFRegTRXREG m_reg = {};
bool write = false;
GSTransferBuffer();
~GSTransferBuffer();
void Init(int tx, int ty, const GIFRegBITBLTBUF& blit, bool write);
void Init(GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG, const GIFRegBITBLTBUF& blit, bool is_write);
bool Update(int tw, int th, int bpp, int& len);
} m_tr;
@@ -259,7 +263,7 @@ public:
static int s_last_transfer_draw_n;
static int s_transfer_n;
static constexpr u32 STATE_VERSION = 8;
static constexpr u32 STATE_VERSION = 9;
enum REG_DIRTY
{

View File

@@ -68,6 +68,7 @@ const char* shaderName(ShaderConvert value)
case ShaderConvert::DEPTH_COPY: return "ps_depth_copy";
case ShaderConvert::DOWNSAMPLE_COPY: return "ps_downsample_copy";
case ShaderConvert::RGBA_TO_8I: return "ps_convert_rgba_8i";
case ShaderConvert::RGB5A1_TO_8I: return "ps_convert_rgb5a1_8i";
case ShaderConvert::CLUT_4: return "ps_convert_clut_4";
case ShaderConvert::CLUT_8: return "ps_convert_clut_8";
case ShaderConvert::YUV: return "ps_yuv";
@@ -493,6 +494,7 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int width, int height, i
{
ERROR_LOG("GS: Memory allocation failure for {}x{} texture. Purging pool and retrying.", size.x, size.y);
PurgePool();
t = CreateSurface(type, size.x, size.y, levels, format);
if (!t)
{
ERROR_LOG("GS: Memory allocation failure for {}x{} texture after purging pool.", size.x, size.y);

View File

@@ -44,6 +44,7 @@ enum class ShaderConvert
DEPTH_COPY,
DOWNSAMPLE_COPY,
RGBA_TO_8I,
RGB5A1_TO_8I,
CLUT_4,
CLUT_8,
YUV,
@@ -372,6 +373,7 @@ struct alignas(16) GSHWDrawConfig
// Others ways to fetch the texture
u32 channel : 3;
u32 channel_fb : 1;
// Dithering
u32 dither : 2;
@@ -410,7 +412,7 @@ struct alignas(16) GSHWDrawConfig
{
const u32 sw_blend_bits = blend_a | blend_b | blend_d;
const bool sw_blend_needs_rt = (sw_blend_bits != 0 && ((sw_blend_bits | blend_c) & 1u)) || ((a_masked & blend_c) != 0);
return tex_is_fb || fbmask || (date > 0 && date != 3) || sw_blend_needs_rt;
return channel_fb || tex_is_fb || fbmask || (date > 0 && date != 3) || sw_blend_needs_rt;
}
/// Disables color output from the pixel shader, this is done when all channels are masked.
@@ -934,7 +936,8 @@ public:
__fi bool IsPresentThrottleAllowed() const { return m_allow_present_throttle; }
__fi GSTexture* GetCurrent() const { return m_current; }
__fi GSTexture* GetMAD() const { return m_mad; }
void Recycle(GSTexture* t);
/// Returns true if it's an OpenGL-based renderer.

View File

@@ -118,6 +118,18 @@ bool GSRenderer::Merge(int field)
if (!tex[0] && !tex[1])
{
m_real_size = GSVector2i(0, 0);
// Clear out the MAD buffer as some remnants of the previously shown frame came be left over, causing a flash for one frame.
if (GSConfig.InterlaceMode == GSInterlaceMode::Automatic || GSConfig.InterlaceMode >= GSInterlaceMode::AdaptiveTFF)
{
GSTexture* mad_tex = g_gs_device->GetMAD();
if (mad_tex)
{
g_gs_device->ClearRenderTarget(mad_tex, 0);
mad_tex = nullptr;
}
}
return false;
}

View File

@@ -1236,36 +1236,18 @@ void GSDevice11::CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r,
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
D3D11_BOX box = {(UINT)r.left, (UINT)r.top, 0U, (UINT)r.right, (UINT)r.bottom, 1U};
D3D11_BOX box = {static_cast<UINT>(r.left), static_cast<UINT>(r.top), 0U, static_cast<UINT>(r.right), static_cast<UINT>(r.bottom), 1U};
// DX api isn't happy if we pass a box for depth copy
// It complains that depth/multisample must be a full copy
// and asks us to use a NULL for the box
// DX11 doesn't support partial depth copy so we need to
// either pass a nullptr D3D11_BOX for a full depth copy or use CopyResource instead.
// Alternatively use shader copy StretchRect, or full depth copy with
// adjusting the scissor and UVs in the shader.
const bool depth = (sTex->GetType() == GSTexture::Type::DepthStencil);
auto pBox = depth ? nullptr : &box;
const u32 x = depth ? 0 : destX;
const u32 y = depth ? 0 : destY;
m_ctx->CopySubresourceRegion(*(GSTexture11*)dTex, 0, destX, destY, 0, *(GSTexture11*)sTex, 0, pBox);
}
void GSDevice11::CloneTexture(GSTexture* src, GSTexture** dest, const GSVector4i& rect)
{
pxAssertMsg(src->GetType() == GSTexture::Type::DepthStencil || src->GetType() == GSTexture::Type::RenderTarget, "Source is RT or DS.");
CommitClear(src);
const int w = src->GetWidth();
const int h = src->GetHeight();
if (src->GetType() == GSTexture::Type::DepthStencil)
{
// DX11 requires that you copy the entire depth buffer.
*dest = CreateDepthStencil(w, h, src->GetFormat(), false);
CopyRect(src, *dest, GSVector4i(0, 0, w, h), 0, 0);
}
else
{
*dest = CreateRenderTarget(w, h, src->GetFormat(), false);
CopyRect(src, *dest, rect, rect.left, rect.top);
}
m_ctx->CopySubresourceRegion(*(GSTexture11*)dTex, 0, x, y, 0, *(GSTexture11*)sTex, 0, pBox);
}
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader, bool linear)
@@ -1435,14 +1417,14 @@ void GSDevice11::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offs
{
float scale;
float pad1[3];
u32 SBW, DBW, pad3;
u32 SBW, DBW, SPSM;
};
const Uniforms cb = {sScale, {}, SBW, DBW};
const Uniforms cb = {sScale, {}, SBW, DBW, SPSM};
m_ctx->UpdateSubresource(m_merge.cb.get(), 0, nullptr, &cb, 0, 0);
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
const ShaderConvert shader = ShaderConvert::RGBA_TO_8I;
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
StretchRect(sTex, GSVector4::zero(), dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), m_merge.cb.get(), nullptr, false);
}
@@ -2495,20 +2477,9 @@ D3D_SHADER_MACRO* GSDevice11::ShaderMacro::GetPtr()
return (D3D_SHADER_MACRO*)mout.data();
}
/// Checks that we weren't sent things we declared we don't support
/// Clears things we don't support that can be quietly disabled
static void preprocessSel(GSDevice11::PSSelector& sel)
{
pxAssert(sel.write_rg == 0); // Not supported, shouldn't be sent
}
void GSDevice11::RenderHW(GSHWDrawConfig& config)
{
pxAssert(!config.require_full_barrier); // We always specify no support so it shouldn't request this
preprocessSel(config.ps);
GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();
const GSVector2i rtsize = (config.rt ? config.rt : config.ds)->GetSize();
GSTexture* colclip_rt = g_gs_device->GetColorClipTexture();
if (colclip_rt)
@@ -2536,15 +2507,17 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
{
config.colclip_update_area = config.drawarea;
const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
colclip_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip);
if (!colclip_rt)
{
Console.Warning("D3D11: Failed to allocate ColorClip render target, aborting draw.");
return;
}
g_gs_device->SetColorClipTexture(colclip_rt);
// Warning: StretchRect must be called before BeginScene otherwise
// vertices will be overwritten. Trust me you don't want to do that.
const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
}
@@ -2555,12 +2528,16 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
{
primid_tex = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::PrimID, false);
if (!primid_tex)
{
Console.WriteLn("D3D11: Failed to allocate DATE image, aborting draw.");
return;
}
StretchRect(colclip_rt ? colclip_rt : config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
primid_tex, GSVector4(config.drawarea), m_date.primid_init_ps[static_cast<u8>(config.datm)].get(), nullptr, false);
}
else if (config.destination_alpha != GSHWDrawConfig::DestinationAlphaMode::Off)
else if (config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::Stencil ||
config.destination_alpha == GSHWDrawConfig::DestinationAlphaMode::StencilOne)
{
const GSVector4 src = GSVector4(config.drawarea) / GSVector4(config.ds->GetSize()).xyxy();
const GSVector4 dst = src * 2.0f - 1.0f;
@@ -2630,21 +2607,39 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
PSSetShaderResource(1, config.pal);
}
GSTexture* rt_copy = nullptr;
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported.
GSTexture* draw_rt_clone = nullptr;
if (config.require_one_barrier || (config.tex && config.tex == config.rt))
{
// Bind the RT.This way special effect can use it.
// Do not always bind the rt when it's not needed,
// only bind it when effects use it such as fbmask emulation currently
// because we copy the frame buffer and it is quite slow.
CloneTexture(colclip_rt ? colclip_rt : config.rt, &rt_copy, config.drawarea);
if (rt_copy)
// Requires a copy of the RT.
// Used as "bind rt" flag when texture barrier is unsupported for tex is fb.
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true);
if (draw_rt_clone)
{
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
if (config.require_one_barrier)
PSSetShaderResource(2, rt_copy);
PSSetShaderResource(2, draw_rt_clone);
if (config.tex && config.tex == config.rt)
PSSetShaderResource(0, rt_copy);
PSSetShaderResource(0, draw_rt_clone);
}
else
Console.Warning("D3D11: Failed to allocate temp texture for RT copy.");
}
GSTexture* draw_ds_clone = nullptr;
if (config.tex && config.tex == config.ds)
{
// DX requires a copy when sampling the depth buffer.
draw_ds_clone = CreateDepthStencil(rtsize.x, rtsize.y, config.ds->GetFormat(), false);
if (draw_ds_clone)
{
CopyRect(config.ds, draw_ds_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
PSSetShaderResource(0, draw_ds_clone);
}
else
Console.Warning("D3D11: Failed to allocate temp texture for DS copy.");
}
SetupVS(config.vs, &config.cb_vs);
@@ -2681,7 +2676,6 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
if (config.alpha_second_pass.enable)
{
preprocessSel(config.alpha_second_pass.ps);
if (config.cb_ps.FogColor_AREF.a != config.alpha_second_pass.ps_aref)
{
config.cb_ps.FogColor_AREF.a = config.alpha_second_pass.ps_aref;
@@ -2697,8 +2691,12 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
DrawIndexedPrimitive();
}
if (rt_copy)
Recycle(rt_copy);
if (draw_rt_clone)
Recycle(draw_rt_clone);
if (draw_ds_clone)
Recycle(draw_ds_clone);
if (primid_tex)
Recycle(primid_tex);

View File

@@ -291,7 +291,6 @@ public:
std::unique_ptr<GSDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format) override;
void CommitClear(GSTexture* t);
void CloneTexture(GSTexture* src, GSTexture** dest, const GSVector4i& rect);
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;

View File

@@ -703,11 +703,17 @@ bool GSDevice12::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
if (!AcquireWindow(true) || (m_window_info.type != WindowInfo::Type::Surfaceless && !CreateSwapChain()))
return false;
if (!CreateNullTexture())
{
Host::ReportErrorAsync("GS", "Failed to create dummy texture");
return false;
}
{
std::optional<std::string> shader = ReadShaderSource("shaders/dx11/tfx.fx");
if (!shader.has_value())
{
Host::ReportErrorAsync("GS", "Failed to read shaders/dx11/tfx.fxf.");
Host::ReportErrorAsync("GS", "Failed to read shaders/dx11/tfx.fx.");
return false;
}
@@ -717,12 +723,6 @@ bool GSDevice12::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
if (!m_shader_cache.Open(m_feature_level, GSConfig.UseDebugDevice))
Console.Warning("D3D12: Shader cache failed to open.");
if (!CreateNullTexture())
{
Host::ReportErrorAsync("GS", "Failed to create dummy texture");
return false;
}
if (!CreateRootSignatures())
{
Host::ReportErrorAsync("GS", "Failed to create pipeline layouts");
@@ -1087,7 +1087,14 @@ GSDevice::PresentResult GSDevice12::BeginPresent(bool frame_skip)
return PresentResult::DeviceLost;
if (frame_skip || !m_swap_chain)
{
if (!m_swap_chain)
{
ExecuteCommandList(WaitType::None);
InvalidateCachedState();
}
return PresentResult::FrameSkipped;
}
// Check if we lost exclusive fullscreen. If so, notify the host, so it can switch to windowed mode.
// This might get called repeatedly if it takes a while to switch back, that's the host's problem.
@@ -1479,15 +1486,15 @@ void GSDevice12::ConvertToIndexedTexture(
{
float scale;
float pad1[3];
u32 SBW, DBW, pad2;
u32 SBW, DBW, SPSM;
};
const Uniforms cb = {sScale, {}, SBW, DBW};
const Uniforms cb = {sScale, {}, SBW, DBW, SPSM};
SetUtilityRootSignature();
SetUtilityPushConstants(&cb, sizeof(cb));
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
const ShaderConvert shader = ShaderConvert::RGBA_TO_8I;
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
DoStretchRect(static_cast<GSTexture12*>(sTex), GSVector4::zero(), static_cast<GSTexture12*>(dTex), dRect,
m_convert[static_cast<int>(shader)].get(), false, true);
}
@@ -3821,6 +3828,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
GSTexture12* draw_rt = static_cast<GSTexture12*>(config.rt);
GSTexture12* draw_ds = static_cast<GSTexture12*>(config.ds);
GSTexture12* draw_rt_clone = nullptr;
GSTexture12* draw_ds_clone = nullptr;
// Align the render area to 128x128, hopefully avoiding render pass restarts for small render area changes (e.g. Ratchet and Clank).
const GSVector2i rtsize(config.rt ? config.rt->GetSize() : config.ds->GetSize());
@@ -3841,7 +3849,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
colclip_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
draw_rt = static_cast<GSTexture12*>(config.rt);
OMSetRenderTargets(draw_rt, draw_ds, config.scissor);
OMSetRenderTargets(draw_rt, draw_ds, config.colclip_update_area);
// if this target was cleared and never drawn to, perform the clear as part of the resolve here.
BeginRenderPass(GetLoadOpForTexture(draw_rt), D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE,
@@ -3876,7 +3884,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
// bind textures before checking the render pass, in case we need to transition them
if (config.tex)
{
PSSetShaderResource(0, config.tex, config.tex != config.rt);
PSSetShaderResource(0, config.tex, config.tex != config.rt && config.tex != config.ds);
PSSetSampler(config.sampler);
}
if (config.pal)
@@ -3900,15 +3908,16 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
}
}
if (config.require_one_barrier || (config.tex && config.tex == config.rt)) // Used as "bind rt" flag when texture barrier is unsupported.
if (config.require_one_barrier || (config.tex && config.tex == config.rt))
{
// requires a copy of the RT
// Requires a copy of the RT.
// Used as "bind rt" flag when texture barrier is unsupported for tex is fb.
draw_rt_clone = static_cast<GSTexture12*>(CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true));
if (draw_rt_clone)
{
EndRenderPass();
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
GL_PUSH("D3D12: Copy RT to temp texture {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
draw_rt_clone->SetState(GSTexture::State::Invalidated);
@@ -3918,6 +3927,27 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
if (config.tex && config.tex == config.rt)
PSSetShaderResource(0, draw_rt_clone, true);
}
else
Console.Warning("D3D12: Failed to allocate temp texture for RT copy.");
}
if (config.tex && config.tex == config.ds)
{
// DX requires a copy when sampling the depth buffer.
draw_ds_clone = static_cast<GSTexture12*>(CreateDepthStencil(rtsize.x, rtsize.y, config.ds->GetFormat(), false));
if (draw_ds_clone)
{
EndRenderPass();
GL_PUSH("D3D12: Copy DS to temp texture {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
draw_ds_clone->SetState(GSTexture::State::Invalidated);
CopyRect(config.ds, draw_ds_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
PSSetShaderResource(0, draw_ds_clone, true);
}
else
Console.Warning("D3D12: Failed to allocate temp texture for DS copy.");
}
// Switch to colclip target for colclip hw rendering
@@ -3932,7 +3962,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
colclip_rt = static_cast<GSTexture12*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false));
if (!colclip_rt)
{
Console.WriteLn("D3D12: Failed to allocate ColorClip render target, aborting draw.");
Console.Warning("D3D12: Failed to allocate ColorClip render target, aborting draw.");
if (date_image)
Recycle(date_image);
@@ -4012,6 +4042,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
// rt -> colclip hw blit if enabled
if (colclip_rt && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly || config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve) && config.rt->GetState() == GSTexture::State::Dirty)
{
OMSetRenderTargets(draw_rt, draw_ds, GSVector4i::loadh(rtsize));
SetUtilityTexture(static_cast<GSTexture12*>(config.rt), m_point_sampler_cpu);
SetPipeline(m_colclip_setup_pipelines[pipe.ds].get());
@@ -4021,8 +4052,10 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
GL_POP();
}
// Restore original scissor, not sure if needed since the render pass has already been started. But to be safe.
OMSetRenderTargets(draw_rt, draw_ds, config.scissor);
}
// VB/IB upload, if we did DATE setup and it's not colclip hw this has already been done
SetPrimitiveTopology(s_primitive_topology_mapping[static_cast<u8>(config.topology)]);
if (!date_image || colclip_rt)
@@ -4066,6 +4099,9 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
if (draw_rt_clone)
Recycle(draw_rt_clone);
if (draw_ds_clone)
Recycle(draw_ds_clone);
if (date_image)
Recycle(date_image);
@@ -4082,7 +4118,7 @@ void GSDevice12::RenderHW(GSHWDrawConfig& config)
colclip_rt->TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
draw_rt = static_cast<GSTexture12*>(config.rt);
OMSetRenderTargets(draw_rt, draw_ds, config.scissor);
OMSetRenderTargets(draw_rt, draw_ds, config.colclip_update_area);
// if this target was cleared and never drawn to, perform the clear as part of the resolve here.
BeginRenderPass(GetLoadOpForTexture(draw_rt), D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE,

View File

@@ -557,26 +557,6 @@ bool GSHwHack::GSC_TalesofSymphonia(GSRendererHW& r, int& skip)
return true;
}
bool GSHwHack::GSC_Simple2000Vol114(GSRendererHW& r, int& skip)
{
if (skip == 0)
{
if (!s_nativeres && RTME == 0 && (RFBP == 0x1500) && (RTBP0 == 0x2c97 || RTBP0 == 0x2ace || RTBP0 == 0x03d0 || RTBP0 == 0x2448) && (RFBMSK == 0x0000))
{
// Don't enable hack on native res if crc is below aggressive.
// Upscaling issues, removes glow/blur effect which fixes ghosting.
skip = 1;
}
if (RTME && (RFBP == 0x0e00) && (RTBP0 == 0x1000) && (RFBMSK == 0x0000))
{
// Depth shadows.
skip = 1;
}
}
return true;
}
bool GSHwHack::GSC_UrbanReign(GSRendererHW& r, int& skip)
{
if (skip == 0)
@@ -1419,7 +1399,6 @@ const GSHwHack::Entry<GSRendererHW::GSC_Ptr> GSHwHack::s_get_skip_count_function
CRC_F(GSC_SacredBlaze),
CRC_F(GSC_GuitarHero),
CRC_F(GSC_SakuraWarsSoLongMyLove),
CRC_F(GSC_Simple2000Vol114),
CRC_F(GSC_SFEX3),
CRC_F(GSC_DTGames),
CRC_F(GSC_TalesOfLegendia),

View File

@@ -21,7 +21,6 @@ public:
static bool GSC_SakuraWarsSoLongMyLove(GSRendererHW& r, int& skip);
static bool GSC_UltramanFightingEvolution(GSRendererHW& r, int& skip);
static bool GSC_TalesofSymphonia(GSRendererHW& r, int& skip);
static bool GSC_Simple2000Vol114(GSRendererHW& r, int& skip);
static bool GSC_UrbanReign(GSRendererHW& r, int& skip);
static bool GSC_SteambotChronicles(GSRendererHW& r, int& skip);
static bool GSC_BlueTongueGames(GSRendererHW& r, int& skip);

File diff suppressed because it is too large Load Diff

View File

@@ -129,6 +129,7 @@ private:
bool ContinueSplitClear();
void FinishSplitClear();
bool NeedsBlending();
bool IsRTWritten();
bool IsDepthAlwaysPassing();
bool IsUsingCsInBlend();
@@ -222,8 +223,8 @@ public:
GSVector4i ComputeBoundingBox(const GSVector2i& rtsize, float rtscale);
void MergeSprite(GSTextureCache::Source* tex);
float GetTextureScaleFactor() override;
GSVector2i GetValidSize(const GSTextureCache::Source* tex = nullptr);
GSVector2i GetTargetSize(const GSTextureCache::Source* tex = nullptr, const bool can_expand = true);
GSVector2i GetValidSize(const GSTextureCache::Source* tex = nullptr, const bool is_shuffle = false);
GSVector2i GetTargetSize(const GSTextureCache::Source* tex = nullptr, const bool can_expand = true, const bool is_shuffle = false);
void Reset(bool hardware_reset) override;
void UpdateSettings(const Pcsx2Config::GSOptions& old_config) override;

File diff suppressed because it is too large Load Diff

View File

@@ -209,7 +209,7 @@ public:
struct TempZAddress
{
u32 ZBP;
u32 offset;
int offset;
GSVector4i rect_since;
};
@@ -441,7 +441,7 @@ protected:
std::unique_ptr<GSDownloadTexture> m_uint16_download_texture;
std::unique_ptr<GSDownloadTexture> m_uint32_download_texture;
Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t, bool half_right, int x_offset, int y_offset, const GSVector2i* lod, const GSVector4i* src_range, GSTexture* gpu_clut, SourceRegion region);
Source* CreateSource(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, Target* t, int x_offset, int y_offset, const GSVector2i* lod, const GSVector4i* src_range, GSTexture* gpu_clut, SourceRegion region);
bool PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size, bool is_frame,
bool preload, bool preserve_target, const GSVector4i draw_rect, Target* dst, GSTextureCache::Source* src = nullptr);
@@ -494,8 +494,8 @@ public:
GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, float* scale, const GSVector2i& size);
std::shared_ptr<Palette> LookupPaletteObject(const u32* clut, u16 pal, bool need_gs_texture);
Source* LookupSource(const bool is_color, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear, const u32 frame_fbp = 0xFFFFFFFF, bool req_color = true, bool req_alpha = true);
Source* LookupDepthSource(const bool is_depth, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const u32 frame_fbp = 0xFFFFFFFF, bool req_color = true, bool req_alpha = true, bool palette = false);
Source* LookupSource(const bool is_color, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear, const GIFRegFRAME& frame, bool req_color = true, bool req_alpha = true);
Source* LookupDepthSource(const bool is_depth, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const GIFRegFRAME& frame, bool req_color = true, bool req_alpha = true, bool palette = false);
Target* FindTargetOverlap(Target* target, int type, int psm);
void CombineAlignedInsideTargets(Target* target, GSTextureCache::Source* src = nullptr);

View File

@@ -270,56 +270,57 @@ std::string GSTextureReplacements::GetDumpFilename(const TextureName& name, u32
return ret;
const std::string game_dir(GetGameTextureDirectory());
if (!FileSystem::DirectoryExists(game_dir.c_str()))
const std::string game_subdir(Path::Combine(game_dir, TEXTURE_DUMP_SUBDIRECTORY_NAME));
if (!FileSystem::DirectoryExists(game_subdir.c_str()))
{
// create both dumps and replacements
if (!FileSystem::CreateDirectoryPath(game_dir.c_str(), false) ||
!FileSystem::EnsureDirectoryExists(Path::Combine(game_dir, "dumps").c_str(), false) ||
!FileSystem::EnsureDirectoryExists(Path::Combine(game_dir, "replacements").c_str(), false))
!FileSystem::EnsureDirectoryExists(game_subdir.c_str(), false) ||
!FileSystem::EnsureDirectoryExists(Path::Combine(game_dir, TEXTURE_REPLACEMENT_SUBDIRECTORY_NAME).c_str(), false))
{
// if it fails to create, we're not going to be able to use it anyway
return ret;
}
}
const std::string game_subdir(Path::Combine(game_dir, TEXTURE_DUMP_SUBDIRECTORY_NAME));
std::string filename;
if (name.HasRegion())
{
if (name.HasPalette())
{
filename = (level > 0) ?
StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_CLUT_FORMAT_STRING "-mip%u.png",
name.TEX0Hash, name.CLUTHash, name.region_width, name.region_height, name.bits, level) :
StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_CLUT_FORMAT_STRING ".png",
name.TEX0Hash, name.CLUTHash, name.region_width, name.region_height, name.bits);
filename = (level > 0)
? StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_CLUT_FORMAT_STRING "-mip%u.png",
name.TEX0Hash, name.CLUTHash, name.region_width, name.region_height, name.bits, level)
: StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_CLUT_FORMAT_STRING ".png",
name.TEX0Hash, name.CLUTHash, name.region_width, name.region_height, name.bits);
}
else
{
filename = (level > 0) ? StringUtil::StdStringFromFormat(
TEXTURE_FILENAME_REGION_FORMAT_STRING "-mip%u.png", name.TEX0Hash,
name.region_width, name.region_height, name.bits, level) :
StringUtil::StdStringFromFormat(
TEXTURE_FILENAME_REGION_FORMAT_STRING ".png", name.TEX0Hash,
name.region_width, name.region_height, name.bits);
filename = (level > 0)
? StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_FORMAT_STRING "-mip%u.png",
name.TEX0Hash, name.region_width, name.region_height, name.bits, level)
: StringUtil::StdStringFromFormat(TEXTURE_FILENAME_REGION_FORMAT_STRING ".png",
name.TEX0Hash, name.region_width, name.region_height, name.bits);
}
}
else
{
if (name.HasPalette())
{
filename = (level > 0) ? StringUtil::StdStringFromFormat(TEXTURE_FILENAME_CLUT_FORMAT_STRING "-mip%u.png",
name.TEX0Hash, name.CLUTHash, name.bits, level) :
StringUtil::StdStringFromFormat(TEXTURE_FILENAME_CLUT_FORMAT_STRING ".png",
name.TEX0Hash, name.CLUTHash, name.bits);
filename = (level > 0)
? StringUtil::StdStringFromFormat(TEXTURE_FILENAME_CLUT_FORMAT_STRING "-mip%u.png",
name.TEX0Hash, name.CLUTHash, name.bits, level)
: StringUtil::StdStringFromFormat(TEXTURE_FILENAME_CLUT_FORMAT_STRING ".png",
name.TEX0Hash, name.CLUTHash, name.bits);
}
else
{
filename = (level > 0) ? StringUtil::StdStringFromFormat(
TEXTURE_FILENAME_FORMAT_STRING "-mip%u.png", name.TEX0Hash, name.bits, level) :
StringUtil::StdStringFromFormat(
TEXTURE_FILENAME_FORMAT_STRING ".png", name.TEX0Hash, name.bits);
filename = (level > 0)
? StringUtil::StdStringFromFormat(TEXTURE_FILENAME_FORMAT_STRING "-mip%u.png",
name.TEX0Hash, name.bits, level)
: StringUtil::StdStringFromFormat(TEXTURE_FILENAME_FORMAT_STRING ".png",
name.TEX0Hash, name.bits);
}
}
@@ -349,6 +350,28 @@ void GSTextureReplacements::GameChanged()
ClearDumpedTextureList();
}
/// If the given file exists in the given directory, but with a different case than the original file, write its path to `*output` and return true.
static bool GetWrongCasePath(std::string* output, const char* dir, std::string_view file, FileSystem::FindResultsArray* reuseme)
{
if (FileSystem::FindFiles(dir, "*", FILESYSTEM_FIND_FOLDERS | FILESYSTEM_FIND_HIDDEN_FILES, reuseme))
{
for (const FILESYSTEM_FIND_DATA& fd : *reuseme)
{
std::string_view name = Path::GetFileName(fd.FileName);
if (name.size() != file.size())
continue;
if (0 == strncmp(name.data(), file.data(), name.size()))
continue;
if (0 == StringUtil::Strncasecmp(name.data(), file.data(), name.size()))
{
*output = fd.FileName;
return true;
}
}
}
return false;
}
void GSTextureReplacements::ReloadReplacementMap()
{
SyncWorkerThread();
@@ -368,9 +391,27 @@ void GSTextureReplacements::ReloadReplacementMap()
if (s_current_serial.empty() || !GSConfig.LoadTextureReplacements)
return;
const std::string replacement_dir(Path::Combine(GetGameTextureDirectory(), TEXTURE_REPLACEMENT_SUBDIRECTORY_NAME));
const std::string texture_dir = GetGameTextureDirectory();
const std::string replacement_dir(Path::Combine(texture_dir, TEXTURE_REPLACEMENT_SUBDIRECTORY_NAME));
FileSystem::FindResultsArray files;
// For some reason texture pack authors think it's a good idea to rename the replacements directory to something with the wrong case...
std::string wrong_case_path;
const std::string* right_case_path = nullptr;
if (GetWrongCasePath(&wrong_case_path, EmuFolders::Textures.c_str(), s_current_serial, &files))
right_case_path = &texture_dir;
else if (GetWrongCasePath(&wrong_case_path, texture_dir.c_str(), TEXTURE_REPLACEMENT_SUBDIRECTORY_NAME, &files))
right_case_path = &replacement_dir;
if (right_case_path)
{
Host::AddKeyedOSDMessage("TextureReplacementDirCaseMismatch",
fmt::format(TRANSLATE_FS("TextureReplacement", "Texture replacement directory {} will not work on case sensitive filesystems.\n"
"Rename it to {} to remove this warning."),
wrong_case_path, *right_case_path),
Host::OSD_WARNING_DURATION);
}
if (!FileSystem::FindFiles(replacement_dir.c_str(), "*", FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES | FILESYSTEM_FIND_RECURSIVE, &files))
return;

View File

@@ -1713,12 +1713,12 @@ void GSDeviceMTL::UpdateCLUTTexture(GSTexture* sTex, float sScale, u32 offsetX,
void GSDeviceMTL::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM, GSTexture* dTex, u32 DBW, u32 DPSM)
{ @autoreleasepool {
const ShaderConvert shader = ShaderConvert::RGBA_TO_8I;
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
id<MTLRenderPipelineState> pipeline = m_convert_pipeline[static_cast<int>(shader)];
if (!pipeline)
[NSException raise:@"StretchRect Missing Pipeline" format:@"No pipeline for %d", static_cast<int>(shader)];
GSMTLIndexedConvertPSUniform uniform = { sScale, SBW, DBW };
GSMTLIndexedConvertPSUniform uniform = { sScale, SBW, DBW, SPSM };
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
DoStretchRect(sTex, GSVector4::zero(), dTex, dRect, pipeline, false, LoadAction::DontCareIfFull, &uniform, sizeof(uniform));

View File

@@ -4,12 +4,19 @@
#include "GSMTLDeviceInfo.h"
#include "GS/GS.h"
#include "common/Console.h"
#include "common/Path.h"
#ifdef __APPLE__
static id<MTLLibrary> loadMainLibrary(id<MTLDevice> dev, NSString* name)
{
NSString* path = [[NSBundle mainBundle] pathForResource:name ofType:@"metallib"];
if (!path)
{
std::string ssname = std::string([name UTF8String]) + ".metallib";
std::string sspath = Path::Combine(EmuFolders::Resources, ssname);
path = [[NSString alloc] initWithBytes:sspath.data() length:sspath.length() encoding:NSUTF8StringEncoding];
}
return path ? [dev newLibraryWithFile:path error:nullptr] : nullptr;
}
@@ -24,6 +31,8 @@ static MRCOwned<id<MTLLibrary>> loadMainLibrary(id<MTLDevice> dev)
if (@available(macOS 10.14, iOS 12.0, *))
if (id<MTLLibrary> lib = loadMainLibrary(dev, @"Metal21"))
return MRCTransfer(lib);
if (id<MTLLibrary> lib = loadMainLibrary(dev, @"default"))
return MRCTransfer(lib);
return MRCTransfer([dev newDefaultLibrary]);
}

View File

@@ -64,6 +64,7 @@ struct GSMTLIndexedConvertPSUniform
float scale;
uint sbw;
uint dbw;
uint psm;
};
struct GSMTLDownsamplePSUniform

View File

@@ -296,6 +296,121 @@ fragment DepthOut ps_convert_rgb5a1_float16_biln(ConvertShaderData data [[stage_
return res.sample_biln<rgb5a1_to_depth16>(data.t);
}
fragment float4 ps_convert_rgb5a1_8i(ConvertShaderData data [[stage_in]], DirectReadTextureIn<float> res,
constant GSMTLIndexedConvertPSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
{
// Convert a RGB5A1 texture into a 8 bits packed texture
// Input column: 16x2 RGB5A1 pixels
// 0: 16 RGBA
// 1: 16 RGBA
// Output column: 16x4 Index pixels
// 0: 16 R5G2
// 1: 16 R5G2
// 2: 16 G2B5A1
// 3: 16 G2B5A1
uint2 pos = uint2(data.p.xy);
// Collapse separate R G B A areas into their base pixel
uint2 column = (pos & ~uint2(0u, 3u)) / uint2(1,2);
uint2 subcolumn = (pos & uint2(0u, 1u));
column.x -= (column.x / 128) * 64;
column.y += (column.y / 32) * 32;
// Deal with swizzling differences
if ((uniform.psm & 0x8) != 0) // PSMCT16S
{
if ((pos.x & 32) != 0)
{
column.y += 32; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32;
}
if ((pos.x & 64) != 0)
{
column.x -= 32;
}
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16;
column.y ^= 8;
}
if ((uniform.psm & 0x30) != 0) // PSMZ16S - Untested but hopefully ok if anything uses it.
{
column.x ^= 32;
column.y ^= 16;
}
}
else // PSMCT16
{
if ((pos.y & 32) != 0)
{
column.y -= 16;
column.x += 32;
}
if ((pos.x & 96) != 0)
{
uint multi = (pos.x & 96) / 32;
column.y += 16 * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96);
}
if (((pos.x & 16) != 0) != ((pos.y & 16) != 0))
{
column.x ^= 16;
column.y ^= 8;
}
if ((uniform.psm & 0x30) != 0) // PSMZ16 - Untested but hopefully ok if anything uses it.
{
column.x ^= 32;
column.y ^= 32;
}
}
uint2 coord = column | subcolumn;
// Compensate for potentially differing page pitch.
uint2 block_xy = coord / uint2(64, 64);
uint block_num = (block_xy.y * (uniform.dbw / 128)) + block_xy.x;
uint2 block_offset = uint2((block_num % (uniform.sbw / 64)) * 64, (block_num / (uniform.sbw / 64)) * 64);
coord = (coord % uint2(64, 64)) + block_offset;
// Apply offset to cols 1 and 2
uint is_col23 = pos.y & 4;
uint is_col13 = pos.y & 2;
uint is_col12 = is_col23 ^ (is_col13 << 1);
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
if (any(floor(uniform.scale) != uniform.scale))
coord = uint2(float2(coord) * uniform.scale);
else
coord = mul24(coord, uint2(uniform.scale));
float4 pixel = res.tex.read(coord);
uint4 denorm_c = (uint4)(pixel * 255.5f);
if ((pos.y & 2u) == 0u)
{
uint red = (denorm_c.r >> 3) & 0x1Fu;
uint green = (denorm_c.g >> 3) & 0x1Fu;
float sel0 = (float)(((green << 5) | red) & 0xFF) / 255.0f;
return float4(sel0);
}
else
{
uint green = (denorm_c.g >> 3) & 0x1Fu;
uint blue = (denorm_c.b >> 3) & 0x1Fu;
uint alpha = denorm_c.a & 0x80u;
float sel0 = (float)((alpha | (blue << 2) | (green >> 3)) & 0xFF) / 255.0f;
return float4(sel0);
}
}
fragment float4 ps_convert_rgba_8i(ConvertShaderData data [[stage_in]], DirectReadTextureIn<float> res,
constant GSMTLIndexedConvertPSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
{

View File

@@ -350,10 +350,11 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
return false;
m_convert.ps[i].SetFormattedName("Convert pipe %s", name);
if (static_cast<ShaderConvert>(i) == ShaderConvert::RGBA_TO_8I)
if (static_cast<ShaderConvert>(i) == ShaderConvert::RGBA_TO_8I || static_cast<ShaderConvert>(i) == ShaderConvert::RGB5A1_TO_8I)
{
m_convert.ps[i].RegisterUniform("SBW");
m_convert.ps[i].RegisterUniform("DBW");
m_convert.ps[i].RegisterUniform("PSM");
m_convert.ps[i].RegisterUniform("ScaleFactor");
}
else if (static_cast<ShaderConvert>(i) == ShaderConvert::YUV)
@@ -1594,12 +1595,13 @@ void GSDeviceOGL::ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 off
{
CommitClear(sTex, false);
const ShaderConvert shader = ShaderConvert::RGBA_TO_8I;
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
GLProgram& prog = m_convert.ps[static_cast<int>(shader)];
prog.Bind();
prog.Uniform1ui(0, SBW);
prog.Uniform1ui(1, DBW);
prog.Uniform1f(2, sScale);
prog.Uniform1ui(2, SPSM);
prog.Uniform1f(3, sScale);
OMSetDepthStencilState(m_convert.dss);
OMSetBlendState(false);
@@ -2424,7 +2426,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
const GSVector4 dRect(config.colclip_update_area);
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(colclip_rt);
g_gs_device->SetColorClipTexture(nullptr);
@@ -2444,6 +2446,14 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
config.colclip_update_area = config.drawarea;
colclip_rt = CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false);
if (!colclip_rt)
{
Console.Warning("GL: Failed to allocate ColorClip render target, aborting draw.");
return;
}
OMSetRenderTargets(colclip_rt, config.ds, nullptr);
g_gs_device->SetColorClipTexture(colclip_rt);
@@ -2451,6 +2461,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
const GSVector4 dRect = GSVector4((config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertOnly) ? GSVector4i::loadh(rtsize) : config.drawarea);
const GSVector4 sRect = dRect / GSVector4(rtsize.x, rtsize.y).xyxy();
StretchRect(config.rt, sRect, colclip_rt, dRect, ShaderConvert::COLCLIP_INIT, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
}
}
@@ -2462,6 +2473,11 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
break; // No setup
case GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking:
primid_texture = InitPrimDateTexture(colclip_rt ? colclip_rt : config.rt, config.drawarea, config.datm);
if (!primid_texture)
{
Console.WriteLn("GL: Failed to allocate DATE image, aborting draw.");
return;
}
break;
case GSHWDrawConfig::DestinationAlphaMode::StencilOne:
if (m_features.texture_barrier)
@@ -2489,12 +2505,17 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
if (config.require_one_barrier && !m_features.texture_barrier)
{
// Requires a copy of the RT
// Requires a copy of the RT.
draw_rt_clone = CreateTexture(rtsize.x, rtsize.y, 1, colclip_rt ? GSTexture::Format::ColorClip : GSTexture::Format::Color, true);
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}",
config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
if (draw_rt_clone)
{
GL_PUSH("GL: Copy RT to temp texture {%d,%d %dx%d}",
config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
CopyRect(colclip_rt ? colclip_rt : config.rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
}
else
Console.Warning("GL: Failed to allocate temp texture for RT copy.");
}
IASetVertexBuffer(config.verts, config.nverts);
@@ -2563,7 +2584,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
if (check_barrier && ((config.tex && (config.tex == config.ds || config.tex == config.rt)) || ((psel.ps.IsFeedbackLoop() || psel.ps.blend_c == 1) && GLState::rt == config.rt)))
{
// Ensure all depth writes are finished before sampling
GL_INS("Texture barrier to flush depth or rt before reading");
GL_INS("GL: Texture barrier to flush depth or rt before reading");
glTextureBarrier();
}
// additional non-pipeline config stuff
@@ -2710,7 +2731,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
const GSVector4 dRect(config.colclip_update_area);
const GSVector4 sRect = dRect / GSVector4(size.x, size.y).xyxy();
StretchRect(colclip_rt, sRect, config.rt, dRect, ShaderConvert::COLCLIP_RESOLVE, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
Recycle(colclip_rt);
g_gs_device->SetColorClipTexture(nullptr);

View File

@@ -1491,7 +1491,7 @@ __ri void GSDrawScanline::CDrawScanline(int pixels, int left, int top, const GSV
case 2: break;
}
if(!(sel.fpsm == 1 && sel.abc == 1))
if (!(sel.fpsm == 1 && sel.abc == 1))
{
switch(sel.abc)
{

View File

@@ -562,7 +562,7 @@ L("loop");
L("step");
// if(steps <= 0) break;
// if (steps <= 0) break;
if (!m_sel.edge)
{
@@ -768,7 +768,7 @@ void GSDrawScanlineCodeGenerator::Init()
cvttps2dq(xym6, vt);
// s = vti.xxxx() + m_local.d[skip].s;
// t = vti.yyyy(); if(!sprite) t += m_local.d[skip].t;
// t = vti.yyyy(); if (!sprite) t += m_local.d[skip].t;
pshufd(s, xym6, _MM_SHUFFLE(0, 0, 0, 0));
pshufd(t, xym6, _MM_SHUFFLE(1, 1, 1, 1));
@@ -925,7 +925,7 @@ void GSDrawScanlineCodeGenerator::Step()
// GSVector4i stq = m_local.d4.stq;
// s += stq.xxxx();
// if(!sprite) t += st.yyyy();
// if (!sprite) t += st.yyyy();
broadcasti128(stq, _rip_local_d(stq));
@@ -2096,7 +2096,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
clamp16(_ga, tmp);
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
@@ -2109,7 +2109,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
case TFX_DECAL:
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
// GSVector4i ga = iip ? gaf : m_local.c.ga;
@@ -2139,7 +2139,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
case TFX_HIGHLIGHT2:
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
@@ -2990,8 +2990,8 @@ void GSDrawScanlineCodeGenerator::WritePixel(const XYm& src_, const AddressReg&
{
if (fast)
{
// if(fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
// if(fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
// if (fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
// if (fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
test(mask, 0x0000000f << shift);
je("@f");
@@ -3020,10 +3020,10 @@ void GSDrawScanlineCodeGenerator::WritePixel(const XYm& src_, const AddressReg&
}
else
{
// if(fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
// if(fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
// if(fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
// if(fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
// if (fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
// if (fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
// if (fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
// if (fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
test(mask, 0x00000003 << shift);
je("@f");

View File

@@ -158,7 +158,7 @@ void GSDrawScanlineCodeGenerator::Generate()
Label exit;
armAsm->Bind(&m_step_label);
// if(steps <= 0) break;
// if (steps <= 0) break;
if (!m_sel.edge)
{
@@ -332,7 +332,7 @@ void GSDrawScanlineCodeGenerator::Init()
armAsm->Fcvtzs(v6.V4S(), v4.V4S());
// s = vti.xxxx() + m_local.d[skip].s;
// t = vti.yyyy(); if(!sprite) t += m_local.d[skip].t;
// t = vti.yyyy(); if (!sprite) t += m_local.d[skip].t;
armAsm->Dup(_temp_s.V4S(), v6.V4S(), 0);
armAsm->Dup(_temp_t.V4S(), v6.V4S(), 1);
@@ -485,7 +485,7 @@ void GSDrawScanlineCodeGenerator::Step()
// GSVector4i stq = m_local.d4.stq;
// s += stq.xxxx();
// if(!sprite) t += stq.yyyy();
// if (!sprite) t += stq.yyyy();
armAsm->Dup(_vscratch.V4S(), _d4_stq.V4S(), 0);
if (m_sel.prim != GS_SPRITE_CLASS || m_sel.mmin)
@@ -1394,7 +1394,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
modulate16(v6, _temp_ga, 1);
clamp16(v6, v3);
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
@@ -1407,7 +1407,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
case TFX_DECAL:
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
@@ -1435,7 +1435,7 @@ void GSDrawScanlineCodeGenerator::AlphaTFX()
case TFX_HIGHLIGHT2:
// if(!tcc) gat = gat.mix16(ga.srl16(7));
// if (!tcc) gat = gat.mix16(ga.srl16(7));
if (!m_sel.tcc)
{
@@ -2158,8 +2158,8 @@ void GSDrawScanlineCodeGenerator::WritePixel(const VRegister& src, const Registe
{
if (fast)
{
// if(fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
// if(fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
// if (fzm & 0x0f) GSVector4i::storel(&vm16[addr + 0], fs);
// if (fzm & 0xf0) GSVector4i::storeh(&vm16[addr + 8], fs);
Label skip_low, skip_high;
armAsm->Lsl(_wscratch, addr, 1); // *2
@@ -2177,10 +2177,10 @@ void GSDrawScanlineCodeGenerator::WritePixel(const VRegister& src, const Registe
}
else
{
// if(fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
// if(fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
// if(fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
// if(fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
// if (fzm & 0x03) WritePixel(fpsm, &vm16[addr + 0], fs.extract32<0>());
// if (fzm & 0x0c) WritePixel(fpsm, &vm16[addr + 2], fs.extract32<1>());
// if (fzm & 0x30) WritePixel(fpsm, &vm16[addr + 8], fs.extract32<2>());
// if (fzm & 0xc0) WritePixel(fpsm, &vm16[addr + 10], fs.extract32<3>());
Label skip_0, skip_1, skip_2, skip_3;

View File

@@ -444,9 +444,9 @@ void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const u16* index)
m1 = (y0011 == y1221).mask() & 7;
// if(i == 0) => y0 < y1 < y2
// if(i == 1) => y0 == y1 < y2
// if(i == 4) => y0 < y1 == y2
// if (i == 0) => y0 < y1 < y2
// if (i == 1) => y0 == y1 < y2
// if (i == 4) => y0 < y1 == y2
if (m1 == 7) // y0 == y1 == y2
return;
@@ -623,9 +623,9 @@ void GSRasterizer::DrawTriangle(const GSVertexSW* vertex, const u16* index)
m1 = (y0011 == y1221).mask() & 7;
// if(i == 0) => y0 < y1 < y2
// if(i == 1) => y0 == y1 < y2
// if(i == 4) => y0 < y1 == y2
// if (i == 0) => y0 < y1 < y2
// if (i == 1) => y0 == y1 < y2
// if (i == 4) => y0 < y1 == y2
if (m1 == 7)
return; // y0 == y1 == y2

View File

@@ -94,7 +94,7 @@ void GSRendererSW::VSync(u32 field, bool registers_written, bool idle_frame)
m_tc->IncAge();
m_draw_transfers.clear();
// if((m_perfmon.GetFrame() & 255) == 0) m_rl->PrintStats();
// if ((m_perfmon.GetFrame() & 255) == 0) m_rl->PrintStats();
}
GSTexture* GSRendererSW::GetOutput(int i, float& scale, int& y_offset)

View File

@@ -515,7 +515,7 @@ void GSSetupPrimCodeGenerator::Color()
pshufd(xym1, xym0, _MM_SHUFFLE(1, 0, 3, 2));
punpcklwd(xym0, xym1);
// if(!tme) c = c.srl16(7);
// if (!tme) c = c.srl16(7);
if (m_sel.tfx == TFX_NONE)
{

View File

@@ -322,7 +322,7 @@ void GSSetupPrimCodeGenerator::Color()
armAsm->Ext(v1.V16B(), v0.V16B(), v0.V16B(), 8);
armAsm->Zip1(v0.V8H(), v0.V8H(), v1.V8H());
// if(!tme) c = c.srl16(7);
// if (!tme) c = c.srl16(7);
if (m_sel.tfx == TFX_NONE)
armAsm->Ushr(v0.V8H(), v0.V8H(), 7);

View File

@@ -2059,6 +2059,12 @@ bool GSDeviceVK::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
return false;
}
if (!CreateNullTexture())
{
Host::ReportErrorAsync("GS", "Failed to create dummy texture");
return false;
}
{
std::optional<std::string> shader = ReadShaderSource("shaders/vulkan/tfx.glsl");
if (!shader.has_value())
@@ -2070,12 +2076,6 @@ bool GSDeviceVK::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
m_tfx_source = std::move(*shader);
}
if (!CreateNullTexture())
{
Host::ReportErrorAsync("GS", "Failed to create dummy texture");
return false;
}
if (!CreatePipelineLayouts())
{
Host::ReportErrorAsync("GS", "Failed to create pipeline layouts");
@@ -3158,15 +3158,16 @@ void GSDeviceVK::ConvertToIndexedTexture(
{
u32 SBW;
u32 DBW;
u32 pad1[2];
u32 PSM;
u32 pad1[1];
float ScaleFactor;
float pad2[3];
};
const Uniforms uniforms = {SBW, DBW, {}, sScale, {}};
const Uniforms uniforms = {SBW, DBW, SPSM, {}, sScale, {}};
SetUtilityPushConstants(&uniforms, sizeof(uniforms));
const ShaderConvert shader = ShaderConvert::RGBA_TO_8I;
const ShaderConvert shader = ((SPSM & 0xE) == 0) ? ShaderConvert::RGBA_TO_8I : ShaderConvert::RGB5A1_TO_8I;
const GSVector4 dRect(0, 0, dTex->GetWidth(), dTex->GetHeight());
DoStretchRect(static_cast<GSTextureVK*>(sTex), GSVector4::zero(), static_cast<GSTextureVK*>(dTex), dRect,
m_convert[static_cast<int>(shader)], false, true);
@@ -5291,8 +5292,12 @@ void GSDeviceVK::SetPipeline(VkPipeline pipeline)
void GSDeviceVK::SetInitialState(VkCommandBuffer cmdbuf)
{
const VkDeviceSize buffer_offset = 0;
vkCmdBindVertexBuffers(cmdbuf, 0, 1, m_vertex_stream_buffer.GetBufferPtr(), &buffer_offset);
VkBuffer buffer = *m_vertex_stream_buffer.GetBufferPtr();
if (buffer != VK_NULL_HANDLE)
{
constexpr VkDeviceSize buffer_offset = 0;
vkCmdBindVertexBuffers(cmdbuf, 0, 1, &buffer, &buffer_offset);
}
}
__ri void GSDeviceVK::ApplyBaseState(u32 flags, VkCommandBuffer cmdbuf)
@@ -5625,7 +5630,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
date_image = SetupPrimitiveTrackingDATE(config);
if (!date_image)
{
Console.WriteLn("Failed to allocate DATE image, aborting draw.");
Console.WriteLn("VK: Failed to allocate DATE image, aborting draw.");
return;
}
@@ -5726,12 +5731,14 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
{
EndRenderPass();
GL_PUSH("Copy RT to temp texture for fbmask {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
GL_PUSH("VK: Copy RT to temp texture for fbmask {%d,%d %dx%d}", config.drawarea.left, config.drawarea.top,
config.drawarea.width(), config.drawarea.height());
CopyRect(draw_rt, draw_rt_clone, config.drawarea, config.drawarea.left, config.drawarea.top);
PSSetShaderResource(2, draw_rt_clone, true);
}
else
Console.Warning("VK: Failed to allocate temp texture for RT copy.");
}
// Switch to colclip target for colclip hw rendering
@@ -5744,7 +5751,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
colclip_rt = static_cast<GSTextureVK*>(CreateRenderTarget(rtsize.x, rtsize.y, GSTexture::Format::ColorClip, false));
if (!colclip_rt)
{
Console.WriteLn("Failed to allocate ColorClip render target, aborting draw.");
Console.Warning("VK: Failed to allocate ColorClip render target, aborting draw.");
if (date_image)
Recycle(date_image);

View File

@@ -379,8 +379,8 @@ void GSDumpReplayer::RenderUI()
do \
{ \
text_size = font->CalcTextSizeA(font->FontSize, std::numeric_limits<float>::max(), -1.0f, (text), nullptr, nullptr); \
dl->AddText(font, font->FontSize, ImVec2(margin + shadow_offset, position_y + shadow_offset), IM_COL32(0, 0, 0, 100), (text)); \
dl->AddText(font, font->FontSize, ImVec2(margin, position_y), color, (text)); \
dl->AddText(font, font->FontSize, ImVec2(GSConfig.OsdPerformancePos == OsdOverlayPos::TopLeft ? ImGuiManager::GetWindowWidth() - margin - text_size.x + shadow_offset : margin + shadow_offset, position_y + shadow_offset), IM_COL32(0, 0, 0, 100), (text)); \
dl->AddText(font, font->FontSize, ImVec2(GSConfig.OsdPerformancePos == OsdOverlayPos::TopLeft ? ImGuiManager::GetWindowWidth() - margin - text_size.x : margin, position_y), color, (text)); \
position_y += text_size.y + spacing; \
} while (0)

View File

@@ -91,42 +91,98 @@ static std::recursive_mutex s_mutex;
static GameList::CacheMap s_cache_map;
static std::FILE* s_cache_write_stream = nullptr;
const char* GameList::EntryTypeToString(EntryType type)
const char* GameList::EntryTypeToString(EntryType type, bool translate)
{
static std::array<const char*, static_cast<int>(EntryType::Count)> names = {{"PS2Disc", "PS1Disc", "ELF"}};
return names[static_cast<int>(type)];
static constexpr std::array<const char*, static_cast<int>(EntryType::Count)> names = {
TRANSLATE_NOOP("GameList", "PS2 Disc"),
TRANSLATE_NOOP("GameList", "PS1 Disc"),
TRANSLATE_NOOP("GameList", "ELF"),
TRANSLATE_NOOP("GameList", "Invalid"),
};
const char* name = names.at(static_cast<int>(type));
if (translate)
name = TRANSLATE("GameList", name);
return name;
}
const char* GameList::EntryTypeToDisplayString(EntryType type)
const char* GameList::RegionToString(Region region, bool translate)
{
static std::array<const char*, static_cast<int>(EntryType::Count)> names = {{TRANSLATE("GameList", "PS2 Disc"), TRANSLATE("GameList", "PS1 Disc"), TRANSLATE("GameList", "ELF")}};
return names[static_cast<int>(type)];
static constexpr std::array<const char*, static_cast<int>(Region::Count)> names = {
TRANSLATE_NOOP("GameList", "NTSC-B"),
TRANSLATE_NOOP("GameList", "NTSC-C"),
TRANSLATE_NOOP("GameList", "NTSC-HK"),
TRANSLATE_NOOP("GameList", "NTSC-J"),
TRANSLATE_NOOP("GameList", "NTSC-K"),
TRANSLATE_NOOP("GameList", "NTSC-T"),
TRANSLATE_NOOP("GameList", "NTSC-U"),
TRANSLATE_NOOP("GameList", "Other"),
TRANSLATE_NOOP("GameList", "PAL-A"),
TRANSLATE_NOOP("GameList", "PAL-AF"),
TRANSLATE_NOOP("GameList", "PAL-AU"),
TRANSLATE_NOOP("GameList", "PAL-BE"),
TRANSLATE_NOOP("GameList", "PAL-E"),
TRANSLATE_NOOP("GameList", "PAL-F"),
TRANSLATE_NOOP("GameList", "PAL-FI"),
TRANSLATE_NOOP("GameList", "PAL-G"),
TRANSLATE_NOOP("GameList", "PAL-GR"),
TRANSLATE_NOOP("GameList", "PAL-I"),
TRANSLATE_NOOP("GameList", "PAL-IN"),
TRANSLATE_NOOP("GameList", "PAL-M"),
TRANSLATE_NOOP("GameList", "PAL-NL"),
TRANSLATE_NOOP("GameList", "PAL-NO"),
TRANSLATE_NOOP("GameList", "PAL-P"),
TRANSLATE_NOOP("GameList", "PAL-PL"),
TRANSLATE_NOOP("GameList", "PAL-R"),
TRANSLATE_NOOP("GameList", "PAL-S"),
TRANSLATE_NOOP("GameList", "PAL-SC"),
TRANSLATE_NOOP("GameList", "PAL-SW"),
TRANSLATE_NOOP("GameList", "PAL-SWI"),
TRANSLATE_NOOP("GameList", "PAL-UK"),
};
const char* name = names.at(static_cast<int>(region));
if (translate)
name = TRANSLATE("GameList", name);
return name;
}
const char* GameList::RegionToString(Region region)
const char* GameList::EntryCompatibilityRatingToString(CompatibilityRating rating, bool translate)
{
static std::array<const char*, static_cast<int>(Region::Count)> names = {{"NTSC-B", "NTSC-C", "NTSC-HK", "NTSC-J", "NTSC-K", "NTSC-T",
"NTSC-U", TRANSLATE("GameList", "Other"), "PAL-A", "PAL-AF", "PAL-AU", "PAL-BE", "PAL-E", "PAL-F", "PAL-FI", "PAL-G", "PAL-GR", "PAL-I", "PAL-IN", "PAL-M",
"PAL-NL", "PAL-NO", "PAL-P", "PAL-PL", "PAL-R", "PAL-S", "PAL-SC", "PAL-SW", "PAL-SWI", "PAL-UK"}};
return names[static_cast<int>(region)];
}
const char* GameList::EntryCompatibilityRatingToString(CompatibilityRating rating)
{
// clang-format off
const char* name = "";
switch (rating)
{
case CompatibilityRating::Unknown: return TRANSLATE("GameList", "Unknown");
case CompatibilityRating::Nothing: return TRANSLATE("GameList", "Nothing");
case CompatibilityRating::Intro: return TRANSLATE("GameList", "Intro");
case CompatibilityRating::Menu: return TRANSLATE("GameList", "Menu");
case CompatibilityRating::InGame: return TRANSLATE("GameList", "In-Game");
case CompatibilityRating::Playable: return TRANSLATE("GameList", "Playable");
case CompatibilityRating::Perfect: return TRANSLATE("GameList", "Perfect");
default: return "";
case CompatibilityRating::Unknown:
name = TRANSLATE_NOOP("GameList", "Unknown");
break;
case CompatibilityRating::Nothing:
name = TRANSLATE_NOOP("GameList", "Nothing");
break;
case CompatibilityRating::Intro:
name = TRANSLATE_NOOP("GameList", "Intro");
break;
case CompatibilityRating::Menu:
name = TRANSLATE_NOOP("GameList", "Menu");
break;
case CompatibilityRating::InGame:
name = TRANSLATE_NOOP("GameList", "In-Game");
break;
case CompatibilityRating::Playable:
name = TRANSLATE_NOOP("GameList", "Playable");
break;
case CompatibilityRating::Perfect:
name = TRANSLATE_NOOP("GameList", "Perfect");
break;
default:
return "";
}
// clang-format on
if (translate)
name = TRANSLATE("GameList", name);
return name;
}
bool GameList::IsScannableFilename(const std::string_view path)
@@ -591,15 +647,18 @@ void GameList::ScanDirectory(const char* path, bool recursive, bool only_cache,
Console.WriteLn("Scanning %s%s", path, recursive ? " (recursively)" : "");
progress->PushState();
progress->SetStatusText(fmt::format(
recursive ? TRANSLATE_FS("GameList", "Scanning directory {} (recursively)...") :
TRANSLATE_FS("GameList", "Scanning directory {}..."),
path).c_str());
if (recursive)
progress->SetStatusText(
fmt::format(TRANSLATE_FS("GameList", "Scanning directory {} (recursively)..."), path).c_str());
else
progress->SetStatusText(
fmt::format(TRANSLATE_FS("GameList", "Scanning directory {}..."), path).c_str());
FileSystem::FindResultsArray files;
FileSystem::FindFiles(path, "*",
recursive ? (FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES | FILESYSTEM_FIND_RECURSIVE) :
(FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES),
(FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES),
&files, progress);
u32 files_scanned = 0;
@@ -622,7 +681,7 @@ void GameList::ScanDirectory(const char* path, bool recursive, bool only_cache,
}
const std::string_view filename = Path::GetFileName(ffd.FileName);
progress->SetStatusText(fmt::format(TRANSLATE_FS("GameList","Scanning {}..."), filename.data()).c_str());
progress->SetStatusText(fmt::format(TRANSLATE_FS("GameList", "Scanning {}..."), filename.data()).c_str());
ScanFile(std::move(ffd.FileName), ffd.ModificationTime, lock, played_time_map, custom_attributes_ini);
progress->SetProgressValue(files_scanned);
}
@@ -1300,7 +1359,7 @@ bool GameList::DownloadCovers(const std::vector<std::string>& url_templates, boo
continue;
}
progress->SetStatusText(fmt::format(TRANSLATE_FS("GameList","Downloading cover for {0} [{1}]..."), entry->title, entry->serial).c_str());
progress->SetStatusText(fmt::format(TRANSLATE_FS("GameList", "Downloading cover for {0} [{1}]..."), entry->title, entry->serial).c_str());
}
// we could actually do a few in parallel here...

View File

@@ -104,10 +104,9 @@ namespace GameList
__fi bool IsDisc() const { return (type == EntryType::PS1Disc || type == EntryType::PS2Disc); }
};
const char* EntryTypeToString(EntryType type);
const char* EntryTypeToDisplayString(EntryType type);
const char* RegionToString(Region region);
const char* EntryCompatibilityRatingToString(CompatibilityRating rating);
const char* EntryTypeToString(EntryType type, bool translate);
const char* RegionToString(Region region, bool translate);
const char* EntryCompatibilityRatingToString(CompatibilityRating rating, bool translate);
/// Fills in boot parameters (iso or elf) based on the game list entry.
void FillBootParametersForEntry(VMBootParameters* params, const Entry* entry);

View File

@@ -10,9 +10,9 @@
#define ipumsk( src ) ( (src) & 0xff )
#define ipucase( src ) case ipumsk(src)
#define IPU_INT_TO( cycles ) if(!(cpuRegs.interrupt & (1<<4))) CPU_INT( DMAC_TO_IPU, cycles )
#define IPU_INT_TO( cycles ) if (!(cpuRegs.interrupt & (1<<4))) CPU_INT( DMAC_TO_IPU, cycles )
#define IPU_INT_FROM( cycles ) CPU_INT( DMAC_FROM_IPU, cycles )
#define IPU_INT_PROCESS( cycles ) if(!(cpuRegs.interrupt & (1 << IPU_PROCESS))) CPU_INT( IPU_PROCESS, cycles )
#define IPU_INT_PROCESS( cycles ) if (!(cpuRegs.interrupt & (1 << IPU_PROCESS))) CPU_INT( IPU_PROCESS, cycles )
//
// Bitfield Structures
//

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