Compare commits

...

172 Commits

Author SHA1 Message Date
TheLastRar 38ee1e1e22 GS/DX: Specify shader model directly instead of via feature level 2026-05-11 22:29:45 +02:00
PCSX2 Bot 2b02a5dc78 [ci skip] PAD: Update to latest controller database. 2026-05-11 13:30:19 -04:00
descawed dead00eb62 GameDB: Enable Instant DMA Hack for SLPM-74405 to fix hang 2026-05-10 19:07:21 +02:00
TJnotJT 4fa2b8e45d GS/HW: Fixes/improvements to early scissor/bbox test. 2026-05-09 13:48:42 +02:00
refractionpcsx2 fc90973509 GS/HW/COLCLIP: Check tex mapping is enabled when checking for recursion 2026-05-09 13:47:58 +02:00
Immersion95 ff9176f83e GameDB: fixes wrong title for SLPM-65496 - Hyper Street Fighter II - The Anniversary Edition 2026-05-09 13:46:48 +02:00
refractionpcsx2 63d3dd9978 GS/TC: Update dirty target linked to source when dirty overlaps the read 2026-05-09 13:46:25 +02:00
JordanTheToaster b704c6caaa GameDB: Pump It Up Exceed Fixes 2026-05-08 18:56:51 +02:00
lightningterror a64465681c GS/HW: Disable texture shuffle if there's no tex. 2026-05-08 18:29:05 +02:00
refractionpcsx2 539357436c Build: Clean up a few warnings 2026-05-08 18:17:31 +02:00
refractionpcsx2 22cb6b0c9c GS/HW: Remove zero clear from GSUploadQueue, use transfer_type instead 2026-05-08 18:15:18 +02:00
PCSX2 Bot 81df4e5def [ci skip] Qt: Update Base Translation. 2026-05-07 02:15:53 +02:00
Ziemas a3f3e8733d GS: fix build with libstdc++ 16 2026-05-06 18:05:51 -04:00
SternXD 6fc84f76bb FullscreenUI: Fix RA login state, and add dismiss dialog 2026-05-06 20:55:44 +02:00
TJnotJT 0949f193b8 GS/SW: Adjust bounds in assertion to present false positive.
Account for the fact that bottom/right coordinates are exclusive.
2026-05-06 20:46:51 +02:00
TJnotJT 5f3dc1a76e GS/SW: Early exit optimization for multithreaded horizontal lines. 2026-05-06 20:46:51 +02:00
TJnotJT 9afea55bb6 GS/SW: Adjust bbox to account for AA1 and points/line rounding. 2026-05-06 20:46:51 +02:00
TJnotJT 433614ae85 GS: Adjust primitive bbox in vertex kick to account for AA1. 2026-05-06 20:46:51 +02:00
TJnotJT 00c85c4a8f GS/TC: Use temporary source on invalid TEX0. 2026-05-06 19:18:04 +02:00
PCSX2 Bot f9885315bd [ci skip] Qt: Update Base Translation. 2026-05-06 11:59:56 +02:00
TheLastRar 26563dbae2 GS/HW: Clamp large UVs in shader anisotropic filtering 2026-05-06 11:59:32 +02:00
Ty 53e3838c1d Qt: Add MainWindowMaximized to ini for human readable maximized override 2026-05-05 16:01:35 -04:00
Ty 4509d11daf Qt: Add MainWindowFullscreen to ini for human readable fullscreen override 2026-05-05 16:01:35 -04:00
JordanTheToaster 37d5bf33e8 Deps: Update SDL3 to v3.4.8 2026-05-05 20:01:47 +02:00
PCSX2 Bot 76842401ee [ci skip] PAD: Update to latest controller database. 2026-05-04 23:33:20 +02:00
PCSX2 Bot bf9d38e86a [ci skip] Qt: Update Base Translation. 2026-05-03 21:08:21 -04:00
Vishrut Sachan 7de2aad05a Qt: Fix Big Picture Mode mnemonic shortcut lost after state change 2026-05-03 19:41:23 -04:00
Florin9doi 7d11e1f963 USB: Support for Olympus storage devices
Also the commands were incorrectly handled as file R/W
operations when the host did not provide unique tags,
causing f.buf to be overwritten with file content
2026-05-03 19:38:07 -04:00
TellowKrinkle 452e239eb4 GS:MTL: Fix AA1 depth clears 2026-05-03 23:51:30 +02:00
TJnotJT 8b82fbb449 GS/HW: Add constant buffer dumping. 2026-05-03 18:05:35 +02:00
lightningterror de84c41757 GS: Check if current tex is valid before resizing. 2026-05-03 15:25:58 +02:00
PCSX2 Bot 3000e113e2 [ci skip] Qt: Update Base Translation. 2026-05-02 05:39:03 +02:00
refractionpcsx2 c5d6b28be4 GS/HW: Correct buffered rect size of corrected EE->GS transfers 2026-05-02 05:38:48 +02:00
chaoticgd c0dfb8cfa0 Debugger: Call QWidget::update instead of QWidget::repaint 2026-05-01 20:47:40 +02:00
lightningterror f9feca4f4d GS/DX11/GL: Further cleanup to the copy behavior and some features checks. 2026-05-01 20:35:30 +02:00
lightningterror 4fa9c4e382 GS/HW: Check if alpha second pass copies are feedback loops. 2026-05-01 20:35:30 +02:00
lightningterror 93f1fcbe88 GS/HW: Sync rt copy behaviour across renderers. 2026-05-01 20:35:30 +02:00
TJnotJT 3d71e310c0 GSRunner: Add -debugdevice command line parameter. 2026-04-30 02:21:35 +02:00
TJnotJT 02d0f613ba GS/HW: Fix brackets in texture shuffle detection. 2026-04-30 02:03:44 +02:00
PCSX2 Bot 3091407e9e [ci skip] Qt: Update Base Translation. 2026-04-29 22:53:37 +02:00
Ziemas 70f6169eff StackWalker: Fix bugs.
Fixes incorrect stack tracing in cases where we are stoppen on certain instructions.
2026-04-28 19:58:38 -04:00
Ziemas a1a3cd9d1b DebugData: Remove stack getters
They're not used and the naming is confused, we can readd these if we
actually want to use them.
2026-04-28 19:57:48 -04:00
Ziemas 86c5d2ae2a DebugInterface: Allow stack tracing any IOP thread 2026-04-28 19:57:48 -04:00
Ziemas d759055231 DebugInterface: Enable stack tracing any EE thread 2026-04-28 19:57:48 -04:00
Ziemas c6474852d5 DebugData: Add function for getting register state 2026-04-28 19:57:48 -04:00
Ziemas a2ac576711 DebugData: Add struct for the saved thread context 2026-04-28 19:57:48 -04:00
Ziemas 1b6924a033 DebugData: Rename EE sleep state to match IOP 2026-04-28 19:57:48 -04:00
Ziemas 8e5e053b81 DebugData: Fix EE thread struct 2026-04-28 19:57:48 -04:00
TheLastRar 6891511a1d GS/HW: Reject malformed UVs in shader anisotropic filtering 2026-04-29 00:14:51 +02:00
chaoticgd c186f8d366 Qt: Fix crash when closing OSD font picker dialog 2026-04-28 12:09:23 -04:00
KamFretoZ eed53d19a0 Qt: Move Cheevos Account Box to the top 2026-04-28 03:33:16 +02:00
PCSX2 Bot abb218c5cf [ci skip] PAD: Update to latest controller database. 2026-04-27 18:30:02 +02:00
PCSX2 Bot 249ac51827 [ci skip] Qt: Update Base Translation. 2026-04-27 02:33:55 +02:00
jasaaved 3da22f126e Qt: Fix Fullscreen not on the correct display
Replace setPosition with setGeometry. This makes sure when rendering to main window, it stays on the current display the main window is currently positioned at.
2026-04-26 16:17:09 -04:00
Ty a509350646 FullscreenUI: Use Host::TranslateTo(C)String directly for non-string literals 2026-04-26 16:13:13 -04:00
KamFretoZ bd486f1729 Qt: Add -datapath launch argument 2026-04-26 16:13:04 -04:00
lightningterror f7ef43b155 GS/HW: Match TEXA behavior on shuffles between renderers. 2026-04-26 21:07:44 +02:00
lightningterror 282129030f GS/HW: Exclude shuffles for dst no rgb blend and no rt check. 2026-04-26 21:07:44 +02:00
lightningterror 5734403ffc GS/HW: Several barrier fixes to sw blend and barrier date.
- Accumulation blend: Require 32 bit RT is only when texture barriers/multidraw fb copies are on/supported.

- Barrier DATE:
Always use barrier date if texture barrier/multidraw fb copies are supported.
Check if texture barriers/multidraw fb copies are supported before enabling barrier date for AA1.
2026-04-26 21:07:44 +02:00
lightningterror 8d4d9ce026 GS/HW: Allow Date barrier when texture barriers/multidraw fb copies are disabled. 2026-04-26 21:07:44 +02:00
lightningterror 390e3994ad GS/HW: Clean up date stencil temp ds texture creation.
Add barrier fallback method.
2026-04-26 21:07:44 +02:00
Pyra Drake 6c41c125d8 GameDB: Fixes for SLES-52674 & SLES-52563
The two 2005 releases, like their 2004 versions, have a cross-save feature allowing you to manage team in TCM and play matches in FIFA. This has been made available via memcardFilters for FolderMC users.
The name for SLES-52674 has also been changed from its German name to its English name as it is PAL-M5.
2026-04-26 20:52:51 +02:00
TellowKrinkle 83da1b6479 GS:MTL: AA1 Support 2026-04-26 13:06:57 +02:00
lightningterror 226b4d25dc GS/HW: More AA1 fixes and optimizations.
Do not enable AA1 if we aren't drawing to the RT.
Check if RT is written for IsCoverageAlphaSupported().
2026-04-26 13:05:39 +02:00
SternXD 27736ef47f Achievements: Block debugger in hardcore mode when using RAIntegration 2026-04-25 22:27:23 +02:00
TJnotJT f95b2ce24d GS/HW: Reorganize AA1 setup and fix some performance bugs.
Separate depth feedback setup it is not duplicated in both AA1 and alpha test setup.

Try to optimize out depth feedback in AA1 if triangle interiors are discarded.

Fix barriers not being properly enabled for AA1 triangles (was only activating if depth test was used).
2026-04-25 22:26:09 +02:00
chaoticgd f1d83f8c65 Qt: Automatically reflow settings check boxes 2026-04-24 13:32:24 +02:00
lightningterror 84c0cd8890 GS: Fix AA1 coverage regression on sw and cleanup. 2026-04-24 13:09:54 +02:00
lightningterror 971382f11e GS/DX12/Debug: Enable dx12 support for debug purposes on Haswell. 2026-04-24 01:30:59 +02:00
TellowKrinkle ddf6fe3264 GS: Add helper to check if devices support feedback loops 2026-04-24 01:19:27 +02:00
TellowKrinkle e5f0c99c76 GS: Remove depth feedback none option
Depth feedback doesn't get used most of the time anyways
2026-04-24 01:19:27 +02:00
TellowKrinkle af81d8b7da GS:MTL: Faster fbfetch depth feedback 2026-04-24 01:19:27 +02:00
TellowKrinkle 8f23e31ae4 GS:MTL: Implement depth feedback 2026-04-24 01:19:27 +02:00
TellowKrinkle 3737b1e06a GS: Move DS as RT texture creation to GSDevice 2026-04-24 01:19:27 +02:00
JordanTheToaster de848fe468 GameDB: Various fixes 2026-04-23 22:01:58 +02:00
TheLastRar ce2a859ad1 GS/HW: Use shader anisotropic filtering
Metal port by @TellowKrinkle

Co-Authored-By: TellowKrinkle <tellowkrinkle@gmail.com>
2026-04-23 18:19:57 +02:00
TJnotJT 8cfd583605 GS/HW: Use correct draw functions in backend passes.
Fixes broken primid and blend multipass draws.

Regression from AA1 changes to draw functions.
2026-04-23 02:32:33 +02:00
chaoticgd 8477679096 Qt: Make sure the game list table view cover column remains hidden 2026-04-22 15:37:01 +02:00
TJnotJT d0ee5b859a GS/VK: Fix flat specifier in VK shader. 2026-04-21 23:28:00 +02:00
lightningterror 16f2c262a3 GS/DX11: Clean up pre binding and srv conflict unbinding.
Move conflict check inside OMSetRenderTargets, it's easier to track and gets rid of duplicate code.

Move shader resource binding after rtv/dsv binding, easier to track and manage srv conflicts.

Get rid of shader resource pre binding, while it may work it's more of a headache to track so many states and things can go wrong easily, so just get rid of it, especially with shader binding after rtv/dsv binding.
2026-04-21 19:31:49 +02:00
lightningterror e8c750ee88 GS/DX11: Make sure we commit a clear for read only dsv too. 2026-04-21 19:31:49 +02:00
lightningterror 20bbb99516 GS/HW: Fix shader compile errors and warnings from AA1 on GL. 2026-04-21 02:20:13 +02:00
chaoticgd d9e0cd55c7 Hotkeys: Check if the memory card is busy before resetting 2026-04-20 19:43:55 -04:00
Mrlinkwii 9c64627b07 OSD : add OSD message for HW AA1 2026-04-20 19:49:00 +02:00
lightningterror 3cbc7f3f09 GS/DX11: Properly null out rtv/dsv during CAS.
This way we ensure the current states are also updated.
2026-04-20 19:10:31 +02:00
PCSX2 Bot 38bcdf65e3 [ci skip] PAD: Update to latest controller database. 2026-04-20 19:09:41 +02:00
TJnotJT 2ae8f1f23f GS/HW: Support HW AA1 for lines/triangles.
Credits: concept by TellowKrinkle.
2026-04-20 11:16:27 +02:00
jasaaved ed796ee3db Qt: Fix Exclusive Fullscreen Mode Saving to Config
Add a variable to keep track if the window was in exclusive fullscreen. This helps prevent saving geometry to config which is for windows rendered separate from main.

The variable is set back to false when render window is released.
2026-04-18 09:59:21 -04:00
jasaaved b1962d22b0 Qt: Fix main window not being hidden when using exclusive fullscreen with rendering to main
Fixed an issue where enabling both render‑to‑main and exclusive fullscreen caused the main window to remain visible when switching from windowed to fullscreen. This occurred because shouldHideMainWindow() relied solely on isRenderingFullscreen() to detect fullscreen state, but exclusive fullscreen is controlled by the GS thread and never sets Qt’s WindowFullScreen flag. The fix adds an additional check for isExclusiveFullscreen().
2026-04-18 09:59:21 -04:00
TJnotJT 3722d392d8 GS/TC: Remove debug code. 2026-04-18 13:30:19 +02:00
TheLastRar bda58fb0c1 GHActions: Check msbuild compile succeeds 2026-04-18 02:08:04 -05:00
SternXD 6f1f4e81d0 Qt: Add missing winwil include path 2026-04-18 02:10:53 +02:00
KamFretoZ 928bf313df Qt/Shortcut: Use WIL instead of WRL for shortcut COM initialization 2026-04-17 23:43:11 +02:00
KamFretoZ 7b2fa803de Qt: Add Icon Selection and Preview to the Shortcut Creator 2026-04-17 23:43:11 +02:00
TellowKrinkle 2dbae3bec9 Misc: Fix GCC arm linux build 2026-04-17 21:19:28 +02:00
TellowKrinkle fa26937885 CMake: Disable Wattributes on gcc 2026-04-17 21:19:28 +02:00
TellowKrinkle c610d4d2d4 Common: Fix arm64 linux build 2026-04-17 21:19:28 +02:00
TellowKrinkle 2f9d7a2901 Deps: Fix build on Xcode 26.4 2026-04-17 21:19:28 +02:00
TellowKrinkle 640a30a25b Deps: Don't remove downloaded files while building
That way we don't need to redownload if a deps build fails partway though and is restarted
2026-04-17 21:19:28 +02:00
refractionpcsx2 bf94ee1c8e GS: Simplify Overlaps check 2026-04-17 21:13:30 +02:00
refractionpcsx2 1fa3c6aa4a GS: Move new Draw Buffering to a UI option 2026-04-17 21:13:30 +02:00
refractionpcsx2 76c401b0fc GS: Implement draw buffering 2026-04-17 21:13:30 +02:00
Pyra Drake 1249846e87 GameDB: Fix name of SLES-54961
It was of low quality.
2026-04-17 20:51:36 +02:00
TJnotJT 09fcc4d60e GS/TC: Break LookupTarget() into 3 functions.
Separate draw lookup from frame lookup. Put common code in another processing function.
2026-04-17 20:17:46 +02:00
KamFretoZ fa9c99a948 Redump: Update Database 2026-04-17 19:46:48 +02:00
TheLastRar f85b20eb00 GS/GL: Initialise stencil ref/mask during device creation 2026-04-17 11:46:24 +02:00
lightningterror 420f4177c9 GS/GL/DX11: Don't bind source tex on shader resource if it's tex is fb with no barrier.
Texture will be copied, the copy will be used as a shader resource. Avoids useless binds.
2026-04-15 21:53:40 +02:00
TellowKrinkle 4f5bde2cef GS:MTL: 32K texture support for M5+ 2026-04-15 21:52:24 +02:00
TellowKrinkle 601b0e60ea GS:MTL: Move texture size calculation to dedicated function 2026-04-15 21:52:24 +02:00
lightningterror a2e354c629 GS/GL: Better handle shader resource null. 2026-04-15 21:51:20 +02:00
lightningterror 241a929748 GS/DX11: Better handle shader resource null. 2026-04-15 21:51:20 +02:00
SternXD 1bf80dbabd FullscreenUI: Add missing icons to settings
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-15 21:00:48 +02:00
SternXD e6e9408f95 FullscreenUI: Reduce nav selection opacity from 100% to 70%
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-15 21:00:48 +02:00
SternXD 1c01f8486d FullscreenUI: Add Preview/Reset buttons to Achievement Sounds
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-15 21:00:48 +02:00
SternXD 8700ae00b5 FullscreenUI: center about version under banner
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-15 21:00:48 +02:00
SternXD 427d53d3c4 FullscreenUI: Add configurable gamepad glyph style
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-15 21:00:48 +02:00
SternXD b1a588cc50 FullscreenUI: Fix clipped summary text
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-15 21:00:48 +02:00
SternXD 19738064f6 FullscreenUI: Reduce summary text opacity
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-15 21:00:48 +02:00
SternXD 0eb4441dac FullscreenUI: Add text shadows for improved readability
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-15 21:00:48 +02:00
SternXD fee5ab8e99 FullscreenUI: Align toggles with text
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-15 21:00:48 +02:00
SternXD 6477a2d62e FullscreenUI: Add rounded corners
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-15 21:00:48 +02:00
TJnotJT c26c2236c5 GS/TC: Fix alpha write masking check in target update.
Make sure we detect when FB mask is such that only alpha is written. Avoid incorrectly updating RGB to a target when we don't need it and possibly nuking other depth targets in the process.
2026-04-15 20:58:08 +02:00
TJnotJT f3496e3858 GS/HW: Set valid flags if display target has exact match with recent transfer. 2026-04-15 20:56:23 +02:00
JordanTheToaster 177318b353 GameDB: Various fixes 2026-04-15 16:36:21 +02:00
KamFretoZ 93695ce623 Achievements: Formatting Cleanup 2026-04-15 16:05:13 +02:00
KamFretoZ cc8292753f Achievement: Fix default custom sound effect behavior
Achievements: Preview custom sounds directly instead of using/opening the system's default audio player.
2026-04-15 16:05:13 +02:00
lightningterror 87319a2d2f GS/DX12: Replace the in render pass member check with function check.
Consitency.
2026-04-15 13:08:12 +02:00
lightningterror bf5be8ed4f GS/DX12: Fix render pass optimization not being properly hit.
The depth target render pass optimization wasn't being hit properly, so let's synch it with the other renderers.
2026-04-15 13:08:12 +02:00
github-actions[bot] 0fc1b66a9b Qt: Update Base Translation (#14297)
Daily update of base translation sources.

Co-authored-by: PCSX2 Bot <PCSX2Bot@users.noreply.github.com>
2026-04-13 21:35:31 -04:00
lightningterror cb63269d9e GS: Fix a bunch of compiler warnings.
Type comparisons, unused variables, missing return value.
2026-04-14 00:01:19 +02:00
lightningterror 903e859433 FSUI: Fix unused variable compiler warning. 2026-04-14 00:01:19 +02:00
chaoticgd ceb53a1626 Debugger: Merge redundant memory interfaces 2026-04-13 15:48:41 -04:00
Ty d23ba14335 GameList: Replace [ and ] with '{{' and '}}' to fix custom attributes 2026-04-13 15:43:25 -04:00
dependabot[bot] 71cdad8808 GHActions: Update CI dependencies
[ci skip]

Bumps the ci-deps group with 3 updates:
[peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request),
[flatpak/flatpak-github-actions](https://github.com/flatpak/flatpak-github-actions)
and
[softprops/action-gh-release](https://github.com/softprops/action-gh-release).

Updates `peter-evans/create-pull-request` from 8.1.0 to 8.1.1
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/peter-evans/create-pull-request/releases">peter-evans/create-pull-request's
releases</a>.</em></p>
<blockquote>
<h2>Create Pull Request v8.1.1</h2>
<h2>What's Changed</h2>
<ul>
<li>build(deps-dev): bump the npm group with 2 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4305">peter-evans/create-pull-request#4305</a></li>
<li>build(deps): bump minimatch by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4311">peter-evans/create-pull-request#4311</a></li>
<li>build(deps): bump the github-actions group with 2 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4316">peter-evans/create-pull-request#4316</a></li>
<li>build(deps): bump <code>@​tootallnate/once</code> and
jest-environment-jsdom by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4323">peter-evans/create-pull-request#4323</a></li>
<li>build(deps-dev): bump undici from 6.23.0 to 6.24.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4328">peter-evans/create-pull-request#4328</a></li>
<li>build(deps-dev): bump flatted from 3.3.1 to 3.4.2 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4334">peter-evans/create-pull-request#4334</a></li>
<li>build(deps): bump picomatch by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4339">peter-evans/create-pull-request#4339</a></li>
<li>build(deps-dev): bump handlebars from 4.7.8 to 4.7.9 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4344">peter-evans/create-pull-request#4344</a></li>
<li>build(deps-dev): bump the npm group with 3 updates by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4349">peter-evans/create-pull-request#4349</a></li>
<li>fix: retry post-creation API calls on 422 eventual consistency
errors by <a
href="https://github.com/peter-evans"><code>@​peter-evans</code></a> in
<a
href="https://redirect.github.com/peter-evans/create-pull-request/pull/4356">peter-evans/create-pull-request#4356</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/peter-evans/create-pull-request/compare/v8.1.0...v8.1.1">https://github.com/peter-evans/create-pull-request/compare/v8.1.0...v8.1.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/5f6978faf089d4d20b00c7766989d076bb2fc7f1"><code>5f6978f</code></a>
fix: retry post-creation API calls on 422 eventual consistency errors
(<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4356">#4356</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/d32e88dac789dcc7906e7d26f69f24116fa9c97d"><code>d32e88d</code></a>
build(deps-dev): bump the npm group with 3 updates (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4349">#4349</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/8170bccad11c0df62542c04dcaefe36d342dfd39"><code>8170bcc</code></a>
build(deps-dev): bump handlebars from 4.7.8 to 4.7.9 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4344">#4344</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/00418193b417f888dbf1d993c5c0d31d27fdc7de"><code>0041819</code></a>
build(deps): bump picomatch (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4339">#4339</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/b993918c8536b6d44706130734d5456879762b27"><code>b993918</code></a>
build(deps-dev): bump flatted from 3.3.1 to 3.4.2 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4334">#4334</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/36d7c8468b48f9c2f8f29e260e82f10d4b90d2bd"><code>36d7c84</code></a>
build(deps-dev): bump undici from 6.23.0 to 6.24.0 (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4328">#4328</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/a45d1fb447fcaf601166e405fd4f335cde1a8aa8"><code>a45d1fb</code></a>
build(deps): bump <code>@​tootallnate/once</code> and
jest-environment-jsdom (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4323">#4323</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/3499eb61835cc0015c0b786e203d74b1e8f55e43"><code>3499eb6</code></a>
build(deps): bump the github-actions group with 2 updates (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4316">#4316</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/3f3b473b8c148f5a7520efb4d1f9a70eea3d9d1f"><code>3f3b473</code></a>
build(deps): bump minimatch (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4311">#4311</a>)</li>
<li><a
href="https://github.com/peter-evans/create-pull-request/commit/6699836a213cf8b28c4f0408a404a6ac79d4458a"><code>6699836</code></a>
build(deps-dev): bump the npm group with 2 updates (<a
href="https://redirect.github.com/peter-evans/create-pull-request/issues/4305">#4305</a>)</li>
<li>See full diff in <a
href="https://github.com/peter-evans/create-pull-request/compare/c0f553fe549906ede9cf27b5156039d195d2ece0...5f6978faf089d4d20b00c7766989d076bb2fc7f1">compare
view</a></li>
</ul>
</details>
<br />

Updates `flatpak/flatpak-github-actions` from 6.6 to 6.7
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/flatpak/flatpak-github-actions/releases">flatpak/flatpak-github-actions's
releases</a>.</em></p>
<blockquote>
<h2>v6.7</h2>
<ul>
<li>Bump action to node 24</li>
<li>Add the git commit as the ostree commit subject</li>
<li>Allow configurable build/repo/state dirs</li>
<li>Add keep-build-dirs flag</li>
<li>Update action dependencies</li>
<li>Improvements to contributing docs</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/flatpak/flatpak-github-actions/commit/401fe28a8384095fc1531b9d320b292f0ee45adb"><code>401fe28</code></a>
flatpak-builder: Add keepBuildDirs flag (<a
href="https://redirect.github.com/flatpak/flatpak-github-actions/issues/229">#229</a>)</li>
<li><a
href="https://github.com/flatpak/flatpak-github-actions/commit/fc05c5ecc19c74ec586bd7a5bc32532ab3f0043f"><code>fc05c5e</code></a>
action: Bump to node 24 (<a
href="https://redirect.github.com/flatpak/flatpak-github-actions/issues/243">#243</a>)</li>
<li><a
href="https://github.com/flatpak/flatpak-github-actions/commit/ce5753fa4123107dee7bb03dd0d360c884baf222"><code>ce5753f</code></a>
Some doc improvements (<a
href="https://redirect.github.com/flatpak/flatpak-github-actions/issues/245">#245</a>)</li>
<li><a
href="https://github.com/flatpak/flatpak-github-actions/commit/fef33cbb5c2d1a311753adfa02239b91fb237077"><code>fef33cb</code></a>
Update dependencies (<a
href="https://redirect.github.com/flatpak/flatpak-github-actions/issues/244">#244</a>)</li>
<li><a
href="https://github.com/flatpak/flatpak-github-actions/commit/0a631396999e4243489a8a6ecf54fcb9f0575078"><code>0a63139</code></a>
feat(flatpak-builder): Allow configurable build/repo/state dirs (<a
href="https://redirect.github.com/flatpak/flatpak-github-actions/issues/237">#237</a>)</li>
<li><a
href="https://github.com/flatpak/flatpak-github-actions/commit/ad1b66ed726a37baa034681da3009761063ec360"><code>ad1b66e</code></a>
flatpak-builder: Add the git commit as the ostree commit subject</li>
<li>See full diff in <a
href="https://github.com/flatpak/flatpak-github-actions/compare/92ae9851ad316786193b1fd3f40c4b51eb5cb101...401fe28a8384095fc1531b9d320b292f0ee45adb">compare
view</a></li>
</ul>
</details>
<br />

Updates `softprops/action-gh-release` from 2.6.1 to 3.0.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/releases">softprops/action-gh-release's
releases</a>.</em></p>
<blockquote>
<h2>v3.0.0</h2>
<p><code>3.0.0</code> is a major release that moves the action runtime
from Node 20 to Node 24.
Use <code>v3</code> on GitHub-hosted runners and self-hosted fleets that
already support the
Node 24 Actions runtime. If you still need the last Node 20-compatible
line, stay on
<code>v2.6.2</code>.</p>
<h2>What's Changed</h2>
<h3>Other Changes 🔄</h3>
<ul>
<li>Move the action runtime and bundle target to Node 24</li>
<li>Update <code>@types/node</code> to the Node 24 line and allow future
Dependabot updates</li>
<li>Keep the floating major tag on <code>v3</code>; <code>v2</code>
remains pinned to the latest <code>2.x</code> release</li>
</ul>
<h2>v2.6.2</h2>
<!-- raw HTML omitted -->
<h2>What's Changed</h2>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore(deps): bump picomatch from 4.0.3 to 4.0.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/775">softprops/action-gh-release#775</a></li>
<li>chore(deps): bump brace-expansion from 5.0.4 to 5.0.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/777">softprops/action-gh-release#777</a></li>
<li>chore(deps): bump vite from 8.0.0 to 8.0.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/781">softprops/action-gh-release#781</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/softprops/action-gh-release/compare/v2...v2.6.2">https://github.com/softprops/action-gh-release/compare/v2...v2.6.2</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md">softprops/action-gh-release's
changelog</a>.</em></p>
<blockquote>
<h2>3.0.0</h2>
<p><code>3.0.0</code> is a major release that moves the action runtime
from Node 20 to Node 24.
Use <code>v3</code> on GitHub-hosted runners and self-hosted fleets that
already support the
Node 24 Actions runtime. If you still need the last Node 20-compatible
line, stay on
<code>v2.6.2</code>.</p>
<h2>What's Changed</h2>
<h3>Other Changes 🔄</h3>
<ul>
<li>Move the action runtime and bundle target to Node 24</li>
<li>Update <code>@types/node</code> to the Node 24 line and allow future
Dependabot updates</li>
<li>Keep the floating major tag on <code>v3</code>; <code>v2</code>
remains pinned to the latest <code>2.x</code> release</li>
</ul>
<h2>2.6.2</h2>
<h2>What's Changed</h2>
<h3>Other Changes 🔄</h3>
<ul>
<li>chore(deps): bump picomatch from 4.0.3 to 4.0.4 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/775">softprops/action-gh-release#775</a></li>
<li>chore(deps): bump brace-expansion from 5.0.4 to 5.0.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/777">softprops/action-gh-release#777</a></li>
<li>chore(deps): bump vite from 8.0.0 to 8.0.5 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a>[bot]
in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/781">softprops/action-gh-release#781</a></li>
</ul>
<h2>2.6.1</h2>
<p><code>2.6.1</code> is a patch release focused on restoring linked
discussion thread creation when
<code>discussion_category_name</code> is set. It fixes
<code>[#764](https://github.com/softprops/action-gh-release/issues/764)</code>,
where the draft-first publish flow
stopped carrying the discussion category through the final publish
step.</p>
<p>If you still hit an issue after upgrading, please open a report with
the bug template and include a minimal repro or sanitized workflow
snippet where possible.</p>
<h2>What's Changed</h2>
<h3>Bug fixes 🐛</h3>
<ul>
<li>fix: preserve discussion category on publish by <a
href="https://github.com/chenrui333"><code>@​chenrui333</code></a> in <a
href="https://redirect.github.com/softprops/action-gh-release/pull/765">softprops/action-gh-release#765</a></li>
</ul>
<h2>2.6.0</h2>
<p><code>2.6.0</code> is a minor release centered on
<code>previous_tag</code> support for
<code>generate_release_notes</code>,
which lets workflows pin GitHub's comparison base explicitly instead of
relying on the default range.
It also includes the recent concurrent asset upload recovery fix, a
<code>working_directory</code> docs sync,
a checked-bundle freshness guard for maintainers, and clearer
immutable-prerelease guidance where
GitHub platform behavior imposes constraints on how prerelease asset
uploads can be published.</p>
<p>If you still hit an issue after upgrading, please open a report with
the bug template and include a minimal repro or sanitized workflow
snippet where possible.</p>
<h2>What's Changed</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/softprops/action-gh-release/commit/b4309332981a82ec1c5618f44dd2e27cc8bfbfda"><code>b430933</code></a>
release: cut v3.0.0 for Node 24 upgrade (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/670">#670</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/c2e35e05a74208bafbfcbdae5ebc9da7236e980f"><code>c2e35e0</code></a>
chore(deps): bump the npm group across 1 directory with 7 updates (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/783">#783</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/3bb12739c298aeb8a4eeaf626c5b8d85266b0e65"><code>3bb1273</code></a>
release 2.6.2</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/c34030fec99b0db0f2f22ce7806c445dddb6e224"><code>c34030f</code></a>
chore: bump node to 24.14.1</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/8975bd05c0630603edb0dca2fc7544bf1c77f600"><code>8975bd0</code></a>
chore(deps): bump vite from 8.0.0 to 8.0.5 (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/781">#781</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/f71937f44d5662ac6eb861431746174a7b46a7b6"><code>f71937f</code></a>
chore(deps): bump brace-expansion from 5.0.4 to 5.0.5 (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/777">#777</a>)</li>
<li><a
href="https://github.com/softprops/action-gh-release/commit/3f0d239d58d5c226738ec0a08d0465b548dc026f"><code>3f0d239</code></a>
chore(deps): bump picomatch from 4.0.3 to 4.0.4 (<a
href="https://redirect.github.com/softprops/action-gh-release/issues/775">#775</a>)</li>
<li>See full diff in <a
href="https://github.com/softprops/action-gh-release/compare/153bb8e04406b158c6c84fc1615b65b24149a1fe...b4309332981a82ec1c5618f44dd2e27cc8bfbfda">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 15:42:22 -04:00
PCSX2 Bot 2ca5ec169f [ci skip] PAD: Update to latest controller database. 2026-04-13 18:24:26 +02:00
SternXD f28adb9c30 Resources: Fix gradient on RetroAchievements icon
This logo (svg version) was originally done by @fffathur before he had a GitHub account. He recently touched up the file to fix some issues with the gradients and make it match the original much better.

Co-authored-by: fffathur <132241318+fffathur@users.noreply.github.com>
2026-04-13 17:22:03 +02:00
SternXD f1891d530b Qt: Fix achievement login hang before main window init
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-13 17:22:03 +02:00
SternXD 285dc0070f Qt: Add RetroAchievements to Setup Wizard
Signed-off-by: SternXD <stern@sidestore.io>
2026-04-13 17:22:03 +02:00
PCSX2 Bot 6d0fbed646 [ci skip] Qt: Update Base Translation. 2026-04-13 17:21:41 +02:00
JordanTheToaster 7164e30809 Deps: Update Linux/Mac OS ffmpeg to 8.1 2026-04-13 16:13:50 +02:00
JordanTheToaster 0cb7045412 3rdparty: Update Vulkan-Headers to v1.4.348 2026-04-13 16:13:50 +02:00
JordanTheToaster 5d9655f0eb 3rdparty: Update soundtouch to v2.4.1 2026-04-13 16:13:50 +02:00
JordanTheToaster 603687389f 3rdparty: Update ImGui to v1.92.7 2026-04-13 16:13:50 +02:00
JordanTheToaster a6d4a67581 Deps: Update libjpegturbo to 3.1.4.1 2026-04-13 16:13:50 +02:00
JordanTheToaster a5dc31b62d Deps: Update agilitysdk to 1.619.1 2026-04-13 16:13:50 +02:00
JordanTheToaster 9d4731db18 Deps: Update harfbuzz to 14.0.0 2026-04-13 16:13:50 +02:00
JordanTheToaster 07fadaba75 Deps: Update freetype to 2.14.3 2026-04-13 16:13:50 +02:00
JordanTheToaster b5036aa87b Deps: Update libpng to v1.6.56 2026-04-13 16:13:50 +02:00
TellowKrinkle 4c42672971 GHActions:Linux: Don't build or bundle FreeType/HarfBuzz 2026-04-12 19:45:32 +02:00
TellowKrinkle 4abafa8ba8 FSUI: Disable SVGinOT support
We use COLRv0 fonts now
2026-04-12 19:45:32 +02:00
TellowKrinkle b366775f4f Formatting: Remove trailing whitespace from GHActions yaml 2026-04-12 19:45:32 +02:00
TellowKrinkle 33a5c4d83e FSUI: Switch emoji font to COLRv0 Twemoji 17.0.2 2026-04-12 19:45:32 +02:00
TJnotJT fce3be8544 GS/HW: Disable HPO/even sprite position on texture shuffles.
Quad conversion in texture shuffles is already aligned and not intended to interact with upscaling coord fixes.
2026-04-12 19:38:14 +02:00
TJnotJT 06616ec98e GS: Refactor texture shuffle detection and quad conversion. 2026-04-11 08:16:04 +02:00
TJnotJT 26bd916e37 GS: Add utility functions for vertices/quads. 2026-04-11 08:16:04 +02:00
PCSX2 Bot ba8804ead6 [ci skip] Qt: Update Base Translation. 2026-04-09 10:53:57 +02:00
Ty d37550fccb Qt: Make the SettingWidget default match the settings interface default 2026-04-08 10:42:25 -04:00
TellowKrinkle c1aa19c306 GS: Clean up feedback shader flags
No more checking 3 different flags to decide one thing
2026-04-08 10:42:36 +02:00
TellowKrinkle 95b50e7f81 GS: Clean trailing whitespace from shaders 2026-04-08 10:42:36 +02:00
TellowKrinkle 2be7f168ce GS:MTL: Use ATST/AFAIL enums 2026-04-08 10:42:36 +02:00
TellowKrinkle 3b6d5057fd GS: Use fmt for draw config dump 2026-04-08 10:42:36 +02:00
TellowKrinkle b854de9eea GS: Keep private stuff out of headers where possible 2026-04-08 10:42:36 +02:00
TellowKrinkle 38bd7b0402 GS: Move shader enums to dedicated file 2026-04-08 10:42:36 +02:00
PCSX2 Bot acb29963ba [ci skip] Qt: Update Base Translation. 2026-04-08 05:51:07 +02:00
TJnotJT 9022072de8 GS/HW: Separate DrawPrims() into functions. 2026-04-07 17:42:46 +02:00
TJnotJT 08d3cc32f4 GS: Ignore CRTC outputs with negative sizes. 2026-04-07 16:20:27 +02:00
lightningterror 629e7ffa2f GS/GL: Use memory barrier when texture barrier isn't supported.
Only in Force Enabled mode as it's not guaranteed to work, otherwise use multidraw fb copy.
Also added nv texture barrier fallback when regular texture barrier isn't supported.
2026-04-07 16:10:45 +02:00
PCSX2 Bot c648313edb [ci skip] PAD: Update to latest controller database. 2026-04-06 18:20:37 +02:00
lightningterror dc6c4d7e4e GS/DX11: Rename caching states. 2026-04-06 04:29:56 +02:00
lightningterror 2fb8a48418 GS/GL: Properly clear fbo states.
Fixes crashes in Renderdoc when re launching OpenGL again.
2026-04-05 10:29:28 +02:00
JordanTheToaster ce472dde8b Deps: Update SDL3 to v3.4.4 2026-04-05 04:12:52 +02:00
lightningterror f56d3b5f2f GS/GL: Drop requirement for GLAD_GL_ARB_draw_buffers_blend.
Currently we don't use hw blend on individual render targets
so we can revert to old behavior while keeping compatibility
with older drivers.
2026-04-05 04:12:39 +02:00
181 changed files with 16125 additions and 10561 deletions
@@ -17,7 +17,7 @@ jobs:
run: ./.github/workflows/scripts/common/update_base_translation.sh
- name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1
with:
title: "Qt: Update Base Translation"
commit-message: "[ci skip] Qt: Update Base Translation."
@@ -19,7 +19,7 @@ jobs:
mv ./game_controller_db.txt ${{github.workspace}}/bin/resources/game_controller_db.txt
- name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1
with:
title: "PAD: Update to latest controller database"
commit-message: "[ci skip] PAD: Update to latest controller database."
+4 -4
View File
@@ -93,7 +93,7 @@ jobs:
- name: Build Flatpak (beta)
if: ${{ inputs.stableBuild == false || inputs.stableBuild == 'false' }}
uses: flatpak/flatpak-github-actions/flatpak-builder@92ae9851ad316786193b1fd3f40c4b51eb5cb101
uses: flatpak/flatpak-github-actions/flatpak-builder@401fe28a8384095fc1531b9d320b292f0ee45adb
with:
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
upload-artifact: false
@@ -109,7 +109,7 @@ jobs:
- name: Build Flatpak (stable)
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
uses: flatpak/flatpak-github-actions/flatpak-builder@92ae9851ad316786193b1fd3f40c4b51eb5cb101
uses: flatpak/flatpak-github-actions/flatpak-builder@401fe28a8384095fc1531b9d320b292f0ee45adb
with:
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
upload-artifact: false
@@ -129,7 +129,7 @@ jobs:
- name: Push to Flathub (beta)
if: ${{ inputs.publish == true && (inputs.stableBuild == false || inputs.stableBuild == 'false') }}
uses: flatpak/flatpak-github-actions/flat-manager@92ae9851ad316786193b1fd3f40c4b51eb5cb101
uses: flatpak/flatpak-github-actions/flat-manager@401fe28a8384095fc1531b9d320b292f0ee45adb
with:
flat-manager-url: https://hub.flathub.org/
repository: beta
@@ -138,7 +138,7 @@ jobs:
- name: Push to Flathub (stable)
if: ${{ inputs.publish == true && (inputs.stableBuild == true || inputs.stableBuild == 'true') }}
uses: flatpak/flatpak-github-actions/flat-manager@92ae9851ad316786193b1fd3f40c4b51eb5cb101
uses: flatpak/flatpak-github-actions/flat-manager@401fe28a8384095fc1531b9d320b292f0ee45adb
with:
flat-manager-url: https://hub.flathub.org/
repository: stable
+2 -2
View File
@@ -68,7 +68,7 @@ jobs:
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
- name: Create a GitHub Release (Manual)
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda
if: steps.tag_version.outputs.new_tag && github.event_name == 'workflow_dispatch'
with:
body_path: ./release-notes.md
@@ -77,7 +77,7 @@ jobs:
tag_name: ${{ steps.tag_version.outputs.new_tag }}
- name: Create a GitHub Release (Push)
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda
if: steps.tag_version.outputs.new_tag && github.event_name != 'workflow_dispatch'
with:
body_path: ./release-notes.md
@@ -43,8 +43,6 @@ STRIP=strip
declare -a MANUAL_LIBS=(
"libshaderc_shared.so.1"
"libharfbuzz.so.0"
"libfreetype.so.6"
)
set -e
@@ -21,15 +21,13 @@ fi
QT=6.11.0
QTAPNG=1.3.0
FFMPEG=8.0
FREETYPE=2.14.1
HARFBUZZ=13.0.0
FFMPEG=8.1
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
LIBJPEGTURBO=3.1.3
LIBPNG=1.6.55
LIBJPEGTURBO=3.1.4.1
LIBPNG=1.6.56
LIBWEBP=1.6.0
NVENC=13.0.19.0
SDL=SDL3-3.4.2
SDL=SDL3-3.4.8
LZ4=1.10.0
VULKAN=1.4.328.1
ZSTD=1.5.7
@@ -57,15 +55,13 @@ cfb1993d7a10848965b01b9cf33a54b8a4ba4e5e3a6d28d59483e73f10d9fc76 qttools-everyw
e710e6e760f92922b86e4dd68f6bbe94ef6510919519d1b0068e874b5ad84d37 qtwayland-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
207f96964dc9475b13c1f66565bf145d2658089d65b4cf786d351da2857fc269 harfbuzz-$HARFBUZZ.tar.gz
b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz
96e5c2d7f2c482a60d5804da48a2eb9a0db0719b2c65dcc169fbfdcf37f3a45d libbacktrace-$LIBBACKTRACE.tar.gz
075920b826834ac4ddf97661cc73491047855859affd671d52079c6867c1c6c0 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
d925722864837ad5ae2a82070d4b2e0603dc72af44bd457c3962298258b8e82d libpng-$LIBPNG.tar.xz
ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 libpng-$LIBPNG.tar.xz
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
ef39a2e3f9a8a78296c40da701967dd1b0d0d6e267e483863ce70f8a03b4050c $SDL.tar.gz
017c06f75ffed25f6cda9b5369ec6da0ac35a6616adf7abe4222516a0237f37a libpng-$LIBPNG-apng.patch.gz
e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba $SDL.tar.gz
9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 libpng-$LIBPNG-apng.patch.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
13da39edb3a40ed9713ae390ca89faa2f1202c9dda869ef306a8d4383e242bee nv-codec-headers-$NVENC.tar.gz
c465aa56757e7746ac707f582b6e2d51546569a4a2488c1172fb543aa5fdfc2c vulkan-sdk-$VULKAN.tar.gz
@@ -83,8 +79,6 @@ EOF
if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then
curl -L \
-O "https://sourceforge.net/projects/freetype/files/freetype2/$FREETYPE/freetype-$FREETYPE.tar.xz" \
-O "https://github.com/harfbuzz/harfbuzz/archive/$HARFBUZZ/harfbuzz-$HARFBUZZ.tar.gz" \
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE/libbacktrace-$LIBBACKTRACE.tar.gz" \
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
@@ -158,7 +152,7 @@ cd ..
echo "Building libpng..."
rm -fr "libpng-$LIBPNG"
tar xf "libpng-$LIBPNG.tar.xz"
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
gzip -kd -f "libpng-$LIBPNG-apng.patch.gz"
cd "libpng-$LIBPNG"
patch -p1 < "../libpng-$LIBPNG-apng.patch"
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja
@@ -206,35 +200,6 @@ cmake --build build --parallel
ninja -C build install
cd ..
echo "Building FreeType without HarfBuzz..."
rm -fr "freetype-$FREETYPE"
tar xf "freetype-$FREETYPE.tar.xz"
cd "freetype-$FREETYPE"
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_DISABLE_HARFBUZZ=TRUE -B build -G Ninja
cmake --build build --parallel
ninja -C build install
cd ..
echo "Building HarfBuzz..."
rm -fr "harfbuzz-$HARFBUZZ"
tar xf "harfbuzz-$HARFBUZZ.tar.gz"
cd "harfbuzz-$HARFBUZZ"
# Add an SOVERSION to match system harfbuzz
sed -i 's/PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE)/PROPERTIES VISIBILITY_INLINES_HIDDEN TRUE SOVERSION 0)/g' CMakeLists.txt
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_HAVE_FREETYPE=ON -B build -G Ninja
cmake --build build --parallel
ninja -C build install
cd ..
echo "Building FreeType with HarfBuzz..."
rm -fr "freetype-$FREETYPE"
tar xf "freetype-$FREETYPE.tar.xz"
cd "freetype-$FREETYPE"
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_REQUIRE_HARFBUZZ=TRUE -B build -G Ninja
cmake --build build --parallel
ninja -C build install
cd ..
echo "Building SDL..."
rm -fr "$SDL"
tar xf "$SDL.tar.gz"
@@ -347,7 +312,7 @@ echo "Building PlutoSVG..."
rm -fr "plutosvg-$PLUTOSVG"
tar xf "plutosvg-$PLUTOSVG.tar.gz"
cd "plutosvg-$PLUTOSVG"
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build -G Ninja
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=OFF -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build -G Ninja
cmake --build build --parallel
ninja -C build install
cd ..
@@ -87,7 +87,7 @@ cd ..
echo "Building libpng..."
rm -fr "libpng-$LIBPNG"
tar xf "libpng-$LIBPNG.tar.xz"
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
gzip -kd -f "libpng-$LIBPNG-apng.patch.gz"
cd "libpng-$LIBPNG"
patch -p1 < "../libpng-$LIBPNG-apng.patch"
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_STATIC=OFF -DPNG_SHARED=ON -DPNG_TOOLS=OFF -B build -G Ninja
@@ -14,8 +14,8 @@
"sources": [
{
"type": "archive",
"url": "https://libsdl.org/release/SDL3-3.4.2.tar.gz",
"sha256": "ef39a2e3f9a8a78296c40da701967dd1b0d0d6e267e483863ce70f8a03b4050c"
"url": "https://libsdl.org/release/SDL3-3.4.8.tar.gz",
"sha256": "e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba"
}
],
"cleanup": [
@@ -14,21 +14,21 @@
"sources": [
{
"type": "archive",
"url": "https://downloads.sourceforge.net/project/libpng/libpng16/1.6.55/libpng-1.6.55.tar.xz",
"sha256": "d925722864837ad5ae2a82070d4b2e0603dc72af44bd457c3962298258b8e82d"
"url": "https://downloads.sourceforge.net/project/libpng/libpng16/1.6.56/libpng-1.6.56.tar.xz",
"sha256": "f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18"
},
{
"type": "file",
"url": "https://download.sourceforge.net/libpng-apng/libpng-1.6.55-apng.patch.gz",
"dest-filename": "libpng-1.6.55-apng.patch.gz",
"sha256": "017c06f75ffed25f6cda9b5369ec6da0ac35a6616adf7abe4222516a0237f37a"
"url": "https://download.sourceforge.net/libpng-apng/libpng-1.6.56-apng.patch.gz",
"dest-filename": "libpng-1.6.56-apng.patch.gz",
"sha256": "9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8"
},
{
"type": "shell",
"commands":
[
"gunzip -f libpng-1.6.55-apng.patch.gz",
"patch -p1 < \"libpng-1.6.55-apng.patch\""
"gunzip -f libpng-1.6.56-apng.patch.gz",
"patch -p1 < \"libpng-1.6.56-apng.patch\""
]
}
],
@@ -46,15 +46,15 @@ fi
QT=6.11.0
QTAPNG=1.3.0
FREETYPE=2.14.1
HARFBUZZ=13.0.0
SDL=SDL3-3.4.2
FREETYPE=2.14.3
SDL=SDL3-3.4.8
HARFBUZZ=14.0.0
ZSTD=1.5.7
LZ4=1.10.0
LIBPNG=1.6.55
LIBJPEGTURBO=3.1.3
LIBPNG=1.6.56
LIBJPEGTURBO=3.1.4.1
LIBWEBP=1.6.0
FFMPEG=8.0
FFMPEG=8.1
MOLTENVK=1.4.1
KDDOCKWIDGETS=2.4.0
PLUTOVG=1.3.2
@@ -92,16 +92,16 @@ cfb1993d7a10848965b01b9cf33a54b8a4ba4e5e3a6d28d59483e73f10d9fc76 qttools-everyw
54f48b2fe4316892ff930195f170a5385644acc7393505f3155c066b8e1ffe56 qttranslations-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
207f96964dc9475b13c1f66565bf145d2658089d65b4cf786d351da2857fc269 harfbuzz-$HARFBUZZ.tar.gz
ef39a2e3f9a8a78296c40da701967dd1b0d0d6e267e483863ce70f8a03b4050c $SDL.tar.gz
36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f freetype-$FREETYPE.tar.xz
e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba $SDL.tar.gz
f29db9470e0ca5cef484e04e27baeec233aa428e8fdabe9e51b0f706c0809d24 harfbuzz-$HARFBUZZ.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
d925722864837ad5ae2a82070d4b2e0603dc72af44bd457c3962298258b8e82d libpng-$LIBPNG.tar.xz
f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 libpng-$LIBPNG.tar.xz
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
017c06f75ffed25f6cda9b5369ec6da0ac35a6616adf7abe4222516a0237f37a libpng-$LIBPNG-apng.patch.gz
075920b826834ac4ddf97661cc73491047855859affd671d52079c6867c1c6c0 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 libpng-$LIBPNG-apng.patch.gz
ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c MoltenVK-$MOLTENVK.tar.gz
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
@@ -218,7 +218,7 @@ cd ..
echo "Installing libpng..."
rm -fr "libpng-$LIBPNG"
tar xf "libpng-$LIBPNG.tar.xz"
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
gzip -kd -f "libpng-$LIBPNG-apng.patch.gz"
cd "libpng-$LIBPNG"
patch -p1 < "../libpng-$LIBPNG-apng.patch"
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_X64" -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_FRAMEWORK=OFF -B build
@@ -270,7 +270,7 @@ echo "Building HarfBuzz..."
rm -fr "harfbuzz-$HARFBUZZ"
tar xf "harfbuzz-$HARFBUZZ.tar.gz"
cd "harfbuzz-$HARFBUZZ"
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -B build
cmake "${CMAKE_COMMON[@]}" "$CMAKE_ARCH_UNIVERSAL" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_BUILD_GPU=OFF -B build
cmake --build build --parallel
cmake --install build
cd ..
@@ -301,6 +301,8 @@ cd "qtbase-everywhere-src-$QT"
# Patch Qt to support macOS 11
patch -p1 < "$SCRIPTDIR/qt-macos11compat.patch"
# Backport fix build on Xcode 26.4 (https://codereview.qt-project.org/c/qt/qtbase/+/724619)
patch -p1 < "$SCRIPTDIR/qt110-xcode264.patch"
# since we don't have a direct reference to QtSvg, it doesn't deployed directly from the main binary
# (only indirectly from iconengines), and the libqsvg.dylib imageformat plugin does not get deployed.
@@ -23,15 +23,15 @@ fi
QT=6.11.0
QTAPNG=1.3.0
FREETYPE=2.14.1
HARFBUZZ=13.0.0
SDL=SDL3-3.4.2
FREETYPE=2.14.3
SDL=SDL3-3.4.8
HARFBUZZ=14.0.0
ZSTD=1.5.7
LZ4=1.10.0
LIBPNG=1.6.55
LIBJPEGTURBO=3.1.3
LIBPNG=1.6.56
LIBJPEGTURBO=3.1.4.1
LIBWEBP=1.6.0
FFMPEG=8.0
FFMPEG=8.1
MOLTENVK=1.4.1
KDDOCKWIDGETS=2.4.0
PLUTOVG=1.3.2
@@ -68,16 +68,16 @@ cfb1993d7a10848965b01b9cf33a54b8a4ba4e5e3a6d28d59483e73f10d9fc76 qttools-everyw
54f48b2fe4316892ff930195f170a5385644acc7393505f3155c066b8e1ffe56 qttranslations-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
207f96964dc9475b13c1f66565bf145d2658089d65b4cf786d351da2857fc269 harfbuzz-$HARFBUZZ.tar.gz
ef39a2e3f9a8a78296c40da701967dd1b0d0d6e267e483863ce70f8a03b4050c $SDL.tar.gz
36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f freetype-$FREETYPE.tar.xz
e9fff7467fb60f037e6708da18b25560649e4c63edc2a69bb871b960d9cbfbba $SDL.tar.gz
f29db9470e0ca5cef484e04e27baeec233aa428e8fdabe9e51b0f706c0809d24 harfbuzz-$HARFBUZZ.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
d925722864837ad5ae2a82070d4b2e0603dc72af44bd457c3962298258b8e82d libpng-$LIBPNG.tar.xz
f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 libpng-$LIBPNG.tar.xz
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
017c06f75ffed25f6cda9b5369ec6da0ac35a6616adf7abe4222516a0237f37a libpng-$LIBPNG-apng.patch.gz
075920b826834ac4ddf97661cc73491047855859affd671d52079c6867c1c6c0 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 libpng-$LIBPNG-apng.patch.gz
ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
@@ -170,7 +170,7 @@ cd ..
echo "Installing libpng..."
rm -fr "libpng-$LIBPNG"
tar xf "libpng-$LIBPNG.tar.xz"
gunzip -d -f "libpng-$LIBPNG-apng.patch.gz"
gzip -kd -f "libpng-$LIBPNG-apng.patch.gz"
cd "libpng-$LIBPNG"
patch -p1 < "../libpng-$LIBPNG-apng.patch"
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DPNG_TESTS=OFF -DPNG_FRAMEWORK=OFF -B build
@@ -211,7 +211,7 @@ echo "Building HarfBuzz..."
rm -fr "harfbuzz-$HARFBUZZ"
tar xf "harfbuzz-$HARFBUZZ.tar.gz"
cd "harfbuzz-$HARFBUZZ"
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -B build
cmake "${CMAKE_COMMON[@]}" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_BUILD_GPU=OFF -B build
make -C build "-j$NPROCS"
make -C build install
cd ..
@@ -244,6 +244,8 @@ cd "qtbase-everywhere-src-$QT"
# Patch Qt to support macOS 11
patch -p1 < "$SCRIPTDIR/qt-macos11compat.patch"
# Backport fix build on Xcode 26.4 (https://codereview.qt-project.org/c/qt/qtbase/+/724619)
patch -p1 < "$SCRIPTDIR/qt110-xcode264.patch"
# since we don't have a direct reference to QtSvg, it doesn't deployed directly from the main binary
# (only indirectly from iconengines), and the libqsvg.dylib imageformat plugin does not get deployed.
@@ -0,0 +1,25 @@
diff --git a/src/corelib/thread/qyieldcpu.h b/src/corelib/thread/qyieldcpu.h
index ab710ea..954c49a 100644
--- a/src/corelib/thread/qyieldcpu.h
+++ b/src/corelib/thread/qyieldcpu.h
@@ -33,7 +33,9 @@
noexcept
#endif
{
-#if __has_builtin(__yield)
+#if __has_builtin(__builtin_arm_yield)
+ __builtin_arm_yield();
+#elif __has_builtin(__yield)
__yield(); // Generic
#elif defined(_YIELD_PROCESSOR) && defined(Q_CC_MSVC)
_YIELD_PROCESSOR(); // Generic; MSVC's <atomic>
@@ -47,9 +49,6 @@
_mm_pause();
#elif defined(Q_PROCESSOR_X86)
__asm__("pause"); // hopefully asm() works in this compiler
-
-#elif __has_builtin(__builtin_arm_yield)
- __builtin_arm_yield();
#elif defined(Q_PROCESSOR_ARM) && Q_PROCESSOR_ARM >= 7 && defined(Q_CC_GNU)
__asm__("yield"); // this works everywhere
@@ -58,12 +58,12 @@ set QT=6.11.0
set QTMINOR=6.11
set QTAPNG=1.3.0
set FREETYPE=2.14.1
set HARFBUZZ=13.0.0
set LIBJPEGTURBO=3.1.3
set LIBPNG=1655
set LIBPNGLONG=1.6.55
set SDL=SDL3-3.4.2
set FREETYPE=2.14.3
set HARFBUZZ=14.0.0
set SDL=SDL3-3.4.8
set LIBJPEGTURBO=3.1.4.1
set LIBPNG=1656
set LIBPNGLONG=1.6.56
set LZ4=1.10.0
set WEBP=1.6.0
set ZLIB=1.3.2
@@ -79,7 +79,7 @@ set SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
set SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
set SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
set AGILITYSDK=1.618.5
set AGILITYSDK=1.619.1
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 590d5ae246c85fa14d6458a36ff75a11236acfe8987c2475090aab1770acbdf8 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 5dfb3c0cb84d2c935c1716b3b86358ca496fb9216676e7e28fee1357fb4a050e || goto error
@@ -88,20 +88,20 @@ call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/off
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" f9c4fd4fd73dff51e9043d2825b04361b678f63798ed798021ef47f1ff0bfccf || goto error
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 174d9e53402e1bf9ec7277e22ec199ba3e55a6be2c0740cb18c0ee9850fc8c34 || goto error
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip a448a8abc3f9ae8eef19ef3ce247370957c1fada5d58a01b5e281e792f40fa61 || goto error
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1655.zip aa45ef52ff7a4e61f34af866b3254b0b243ddc42fe2adb823b0843d2a57c2e86 || goto error
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 075920b826834ac4ddf97661cc73491047855859affd671d52079c6867c1c6c0 || goto error
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download e61b31ab26358b946e767ed7eb7f4bb2e507da1cfefeb7a8861ace7fd5c899a1 || goto error
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip f4b86f4d107bc4f0b005c97d6cde43e548a125ee2810fa00d41844b46b6fe16a || goto error
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1656.zip 1ccf023c5f4ee1a7b75c5624f53acede5066f79b2fb14ddffaa28369adf9baac || goto error
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 || goto error
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 4954d436c95c42aa258d4eb3fb95f8ecc5d7a3dc411f0f41ac2692d34b9b9e9c || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 506206e02f90c1f37e048eacaf9e8a3a7dc682fd27783eb0ff15a7d2dcc9c2af || goto error
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://github.com/madler/zlib/releases/download/v%ZLIB%/zlib%ZLIBSHORT%.zip" e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 || goto error
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 4fe4e48f28aa80171b2166d45c0976ab0f21eecedb52cd4c3ef73b5afb48fac9 || goto error
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
call :downloadfile: "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" 0027fc24f947c48dbded13ada7d280be221eb651644e23a8a476f0f1f0a079dd || goto error
call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" 9073a264301e93183844026239c9081717d52d13fb71aae68a0555c576b8de44 || goto error
call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 30054b74abdf0ba35bf2cb435b6e49fcb6d62a8e78a240a018c36aa60dba765f || goto error
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 3ac59c8216d367ab7858684d39c8faf872a64150aeb139335f4e083c5f79dde0 || goto error
@@ -171,7 +171,7 @@ echo Building HarfBuzz...
rmdir /S /Q "harfbuzz-%HARFBUZZ%"
%SEVENZIP% x "-x^!harfbuzz-%HARFBUZZ%\README" "harfbuzz-%HARFBUZZ%.zip" || goto error
cd "harfbuzz-%HARFBUZZ%" || goto error
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -B build -G Ninja || goto error
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_BUILD_GPU=OFF -B build -G Ninja || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error
@@ -75,12 +75,12 @@ set LIBOPUS=1.6.1
set LIBSVTAV1=4.0.1
set LIBX264=b35605ace3ddf7c1a5d67a2eb553f034aef41d55
set FREETYPE=2.14.1
set HARFBUZZ=13.0.0
set LIBJPEGTURBO=3.1.3
set LIBPNG=1655
set LIBPNGLONG=1.6.55
set SDL=SDL3-3.4.2
set FREETYPE=2.14.3
set HARFBUZZ=14.0.0
set SDL=SDL3-3.4.8
set LIBJPEGTURBO=3.1.4.1
set LIBPNG=1656
set LIBPNGLONG=1.6.56
set LZ4=1.10.0
set WEBP=1.6.0
set ZLIB=1.3.2
@@ -96,7 +96,7 @@ set SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
set SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
set SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
set AGILITYSDK=1.619.0
set AGILITYSDK=1.619.1
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 590d5ae246c85fa14d6458a36ff75a11236acfe8987c2475090aab1770acbdf8 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 5dfb3c0cb84d2c935c1716b3b86358ca496fb9216676e7e28fee1357fb4a050e || goto error
@@ -115,20 +115,20 @@ call :downloadfile "opus-%LIBOPUS%.tar.gz" "https://downloads.xiph.org/releases/
call :downloadfile "SVT-AV1-v%LIBSVTAV1%.zip" "https://gitlab.com/AOMediaCodec/SVT-AV1/-/archive/v%LIBSVTAV1%/SVT-AV1-v%LIBSVTAV1%.zip" bfafad9af17f87fff75e44ca9b2c10cdd83c576047c3e96229285a8a64c81afc || goto error
call :downloadfile "x264-%LIBX264%.zip" "https://code.videolan.org/videolan/x264/-/archive/%LIBX264%.zip" d95d059eff81cc565165cd058b66e208f0cc9874106a8fe94a811a66cf8a85a2 || goto error
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 174d9e53402e1bf9ec7277e22ec199ba3e55a6be2c0740cb18c0ee9850fc8c34 || goto error
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip a448a8abc3f9ae8eef19ef3ce247370957c1fada5d58a01b5e281e792f40fa61 || goto error
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1655.zip aa45ef52ff7a4e61f34af866b3254b0b243ddc42fe2adb823b0843d2a57c2e86 || goto error
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 017c06f75ffed25f6cda9b5369ec6da0ac35a6616adf7abe4222516a0237f37a || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 075920b826834ac4ddf97661cc73491047855859affd671d52079c6867c1c6c0 || goto error
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download e61b31ab26358b946e767ed7eb7f4bb2e507da1cfefeb7a8861ace7fd5c899a1 || goto error
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip f4b86f4d107bc4f0b005c97d6cde43e548a125ee2810fa00d41844b46b6fe16a || goto error
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1656.zip 1ccf023c5f4ee1a7b75c5624f53acede5066f79b2fb14ddffaa28369adf9baac || goto error
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 || goto error
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 4954d436c95c42aa258d4eb3fb95f8ecc5d7a3dc411f0f41ac2692d34b9b9e9c || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 506206e02f90c1f37e048eacaf9e8a3a7dc682fd27783eb0ff15a7d2dcc9c2af || goto error
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://github.com/madler/zlib/releases/download/v%ZLIB%/zlib%ZLIBSHORT%.zip" e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 || goto error
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 4fe4e48f28aa80171b2166d45c0976ab0f21eecedb52cd4c3ef73b5afb48fac9 || goto error
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" d5edab9a0c4d1b78ba6fe55b425eeef9fefba7d2a101e889d70fd21d481e6cb1 || goto error
call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" 9073a264301e93183844026239c9081717d52d13fb71aae68a0555c576b8de44 || goto error
call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 30054b74abdf0ba35bf2cb435b6e49fcb6d62a8e78a240a018c36aa60dba765f || goto error
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 3ac59c8216d367ab7858684d39c8faf872a64150aeb139335f4e083c5f79dde0 || goto error
@@ -330,7 +330,7 @@ echo Building HarfBuzz...
rmdir /S /Q "harfbuzz-%HARFBUZZ%"
%SEVENZIP% x "-x^!harfbuzz-%HARFBUZZ%\README" "harfbuzz-%HARFBUZZ%.zip" || goto error
cd "harfbuzz-%HARFBUZZ%" || goto error
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -B build -G Ninja || goto error
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_BUILD_GPU=OFF -B build -G Ninja || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error
+9 -9
View File
@@ -63,10 +63,10 @@ jobs:
shell: pwsh
run: |
[string[]] $clang_cl = &clang-cl.exe --version
$version = [Regex]::Match($clang_cl[0], "(\d+\.\d+\.\d+)")
$path = $clang_cl[3].TrimStart("InstalledDir: ").TrimEnd("\bin")
$output = @"
<Project>
<PropertyGroup>
@@ -75,9 +75,9 @@ jobs:
</PropertyGroup>
</Project>
"@
Write-Host $output
$output | Out-File Directory.build.props
# actions/checkout elides tags, fetch them primarily for releases
@@ -150,10 +150,10 @@ jobs:
cmake --build build --config Release || exit /b
cmake --install build --config Release || exit /b
) else (
msbuild "PCSX2_qt.sln" /m /v:m /p:Configuration="${{ inputs.configuration }}" /p:Platform="${{ inputs.platform }}"
msbuild "PCSX2_qt.sln" /m /v:m /p:Configuration="${{ inputs.configuration }}" /p:Platform="${{ inputs.platform }}" || exit /b
)
REM We can use Segoe UI Emoji so we don't need to bundle this
del bin\resources\fonts\NotoColorEmoji*
del bin\resources\fonts\Twemoji*
- name: Run Tests
if: inputs.configuration == 'CMake'
@@ -186,9 +186,9 @@ jobs:
shell: pwsh
run: |
mkdir -Force symbols
Get-ChildItem -Path ./bin -Recurse -File | Where-Object {
($_.Extension -eq ".exe" -or $_.Extension -eq ".pdb") -and ($_.Name -notmatch "updater")
} | ForEach-Object {
Get-ChildItem -Path ./bin -Recurse -File | Where-Object {
($_.Extension -eq ".exe" -or $_.Extension -eq ".pdb") -and ($_.Name -notmatch "updater")
} | ForEach-Object {
& dump_syms $_.FullName >> symbols/pcsx2-qt.bpsym
}
Get-ChildItem -Path ./bin -Recurse -Filter "*.pdb" | ForEach-Object {
+165
View File
@@ -39,6 +39,171 @@ HOW TO UPDATE?
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
- Please report any issue!
-----------------------------------------------------------------------
VERSION 1.92.7 (Released 2026-04-02)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.7
Breaking Changes:
- Separator: fixed a legacy quirk where `Separator()` was submitting a zero-height
item for layout purpose, even though it draws a 1-pixel separator.
The fix could affect code e.g. computing height from multiple widgets in order to
allocate vertical space for a footer or multi-line status bar. (#2657, #9263)
The "Console" example had such a bug:
float footer_height = style.ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
BeginChild("ScrollingRegion", { 0, -footer_height });
Should be:
float footer_height = style.ItemSpacing.y + style.SeparatorSize + ImGui::GetFrameHeightWithSpacing();
BeginChild("ScrollingRegion", { 0, -footer_height });
When such idiom was used and assuming zero-height Separator, it is likely that
in 1.92.7 the resulting window will have unexpected 1 pixel scrolling range.
- Multi-Select: renamed `ImGuiMultiSelectFlags_SelectOnClick` to `ImGuiMultiSelectFlags_SelectOnAuto`.
Kept inline redirection enum (will obsolete).
- Combo(), ListBox(): commented out legacy signatures which were obsoleted in 1.90
(Nov 2023), when the getter callback type was changed from:
bool (*getter)(void* user_data, int idx, const char** out_text)
To:
const char* (*getter)(void* user_data, int idx)
Other Changes:
- TreeNode:
- Moved `TreeNodeGetOpen()` helper to public API. I was hesitant to make this public
because I intend to provide a more generic and feature-full version, but in the meanwhile
this will do. (#3823, #9251, #7553, #6754, #5423, #2958, #2079, #1947, #1131, #722)
- In 'Demo->Property Editor' demonstrate a way to perform tree clipping by fast-forwarding
through non-visible chunks. (#3823, #9251, #6990, #6042)
Using SetNextItemStorageID() + TreeNodeGetOpen() makes this notably easier than
it was prior to 1.91.
- InputText:
- Shift+Enter in multi-line editor always adds a new line, regardless of
`ImGuiInputTextFlags_CtrlEnterForNewLine` being set or not. (#9239)
- Reworked `io.ConfigInputTextEnterKeepActive` mode so that pressing Enter will
deactivate/reactivate the item in order for e.g. `IsItemDeactivatedAfterEdit()`
signals to be emitted the same way regardless of that setting. (#9001, #9115)
- Fixed a glitch when using `ImGuiInputTextFlags_ElideLeft` where the local x offset
would be incorrect during the deactivation frame. (#9298)
- Fixed a crash introduced in 1.92.6 when handling `ImGuiInputTextFlags_CallbackResize`
in certain situations. (#9174)
- Fixed selection highlight Y1 offset being very slightly off (since 1.92.3). (#9311) [@v-ein]
- InputTextMultiline: fixed an issue introduced in 1.92.3 where line count calculated
for vertical scrollbar range would be +1 when the widget is inactive, word-wrap is
disabled and the text buffer ends with '\n'. Fixed a similar issue related to clipping
large amount of text.
- InputTextMultiline: avoid going through reactivation code and fixed losing revert value
when activating scrollbar.
- InputTextMultiline: fixed an issue where edit buffer wouldn't be reapplied to back
buffer on the `IsItemDeactivatedAfterEdit()` frame. This could create issues when
using the idiom of not applying edits before `IsItemDeactivatedAfterEdit()`.
(#9308, #8915, #8273)
- Tables:
- Allow reordering columns by dragging them in the context menu. (#9312)
- Context menu now presents columns in display order. (#9312)
- Fixed and clarified the behavior of using `TableSetupScrollFreeze()` with columns>1,
and where some of the columns within that range were Hidable.
- Before: `TableSetupScrollFreeze(N, 0)`: include the N left-most visible columns as
part of the scroll freeze. So if you intentionally hide columns <N, the scroll
freeze area would start covering the subsequent/following columns (N+1) etc.
- After: `TableSetupScrollFreeze(N, 0)`: include the N left-most columns (regardless of visibility),
as part of the scroll freeze. So if you intentionally hide columns <N, the scroll
freeze area will cover less columns.
- This is generally more sane and logical.
- Fixed dragging a header to reorder outside of visible bounds (due to horizontal scrolling)
from losing active id.
- Angled Headers: angled section for column being reordered via the regular headers
stays highlighted during reordering.
- Style:
- Fonts: fixed an issue introduced in 1.92.6 where `style.FontBaseSize` would be
cleared during the first frame if no fonts was explicitly added before.
- Border sizes are now scaled (and rounded) by `ScaleAllSizes()`.
- When using large values with `ScallAllSizes()`, the following items thickness
are scaled to integer amounts:
- `InputText()` caret/cursor thickness. (#7031)
- `CloseButton()` thickness.
- `TextLink()` underline thickness.
- `ColorButton()` border thickness.
- `Separator()` thickness, via scaling newly added `style.SeparatorSize`. (#2657, #9263)
- Nav:
- Popups: Shift+F10 or Menu key can now open popups menus when using
`BeginPopupContextItem()`, `BeginPopupContextWindow()` or `OpenPopupOnItemClick()`.
(#8803, #9270) [@exelix11, @ocornut]
- Changed Gamepad mapping for "Activate with Text Input" action: (#8803, #787)
- Previously: press North button (PS4/PS5 triangle, Switch X, Xbox Y).
- Now: long press (hold) Activate button (PS4/PS5 cross, Switch B, Xbox A) for ~0.60 secs.
This is rarely used, somehow easier to discover, and frees a button for other uses.
See updated Gamepad Control Sheets: https://www.dearimgui.com/controls_sheets
- Short Gamepad Activation press on InputText() always activate with Text Input mode.
- Popups: pressing North button (PS4/PS5 triangle, SwitchX, Xbox Y) also open popups menus.
- Multi-Select:
- Added `ImGuiMultiSelectFlags_SelectOnClickAlways` mode (rarely used).
This prevents Drag and Drop of multiple items, but it allows to start a new Box-Selection
from inside an existing selection (Excel style). (#9307, #1861)
- Clipper:
- Clear `DisplayStart`/`DisplayEnd` fields when `Step()` returns false.
- Added `UserIndex` helper storage. This is solely a convenience for cases where
you may want to carry an index around.
- Always pulls current context on `ImGuiListClipper::Begin()`, consistent with public
API design, and avoids issues with clipper instances outliving contexts. (#9324, #5856)
- Scrollbar:
- Implemented a custom tweak to extend hit-testing bounding box when window is sitting
at the edge of a viewport (e.g. fullscreen or docked window), so that e.g. mouse the
mouse at the extreme of the screen will reach the scrollbar. (#9276)
- Fixed an issue which could lead initial click to move the current scroll by a pixel.
- Button:
- Moved `ImGuiButtonFlags_AllowOverlap` from imgui_internal.h to imgui.h,
as a convenience for when using e.g. `InvisibleButton()`.
- Focus: fixed fallback "Debug" window temporarily taking focus and setting `io.WantCaptureKeyboard`
for one frame on e.g. application boot if no other windows are submitted. (#9243)
- DrawList:
- PathArcTo(): fixed erroneous segment count for pathologically small arcs on large
circles. (#9331, #9313) [@thedmd, @epajarre]
- Memory:
- Discard/GC of ImDrawList buffers for unused windows favor restoring them to
~Size*1.05 instead of Capacity when awakening again. Facilitate releasing ImDrawList
buffers after unusual usage spike. (#9303)
- Fixed `GetForegroundDrawList()`/`GetBackgroundDrawList()` per-viewport buffers not being
collected when unused for `io.ConfigMemoryCompactTimer` amount of time. (#9303)
- Demo: fixed `IMGUI_DEMO_MARKER` locations for examples applets. (#9261, #3689) [@pthom]
- Misc: added missing ImVec2/ImVec4 operators. (#9339, #8258) [@dkosmari, @ArashPartow]
- Internals:
- ButtonBehavior: fixed internal/low-level `ImGuiButtonFlags_PressedOnRelease`
(as well as equivalent `ImGuiSelectableFlags_SelectOnRelease` for Selectable) from
not taking current active id. `ImGuiButtonFlags_NoHoldingActiveID` allows that.
This was only used internally by MenuItem().
- Backends:
- DirectX9, OpenGL2, OpenGL3, Metal, SDLGPU3, SDLRenderer2, SDLRenderer3: fixed easy-to-fix
issues in code assuming ImTextureID_Invalid is always defined to 0. (#9295, #9310)
- GLFW: mouse cursor is properly restored if changed by user app/code while using
`glfwSetInputMode(..., GLFW_CURSOR_DISABLED)` or `ImGuiConfigFlags_NoMouseCursorChange`.
Amend optimization done in 1.92.6.
- SDLGPU3: removed unnecessary call to `SDL_WaitForGPUIdle()` when releasing
vertex/index buffers. (#9262) [@jaenis]
- WebGPU: fixed version check for Emscripten 5.0.0+.
- WebGPU: removed support for Emscripten <4.0.10. (#9281) [@ypujante]
- WebGPU: added support for WGVK native backend via `IMGUI_IMPL_WEBGPU_BACKEND_WGVK`,
using SPIRV shaders if WGSL is not available. (#9316, #9246, #9257) [@r-lyeh]
(WGVK is a lightweight alternative to Dawn or WGPU for native applications,
which is easier to build/setup, see: https://github.com/manuel5975p/WGVK)
- Examples:
- Emscripten: added `tabindex=-1` to canvas in our shell_minimal.htm. Without it,
the canvas was not focusable in the DOM, which in turn make some backends
(e.g. pongasoft/emscripten-glfw) not receive focus loss events. (#9259) [@pthom]
- Emscripten: fixed minor rendering issues with our HTML shell. (#9281) [@ypujante]
- hidden small blue outline when canvas is focused on Chrome.
- hidden scrollbar in Firefox.
- Vulkan: added `ImGui_ImplVulkan_PipelineInfo::ExtraDynamicStates[]` to allow specifying
extra dynamic states to add when creating the VkPipeline. (#9211) [@DziubanMaciej]
- Vulkan: `ImGui_ImplVulkan_AddTexture()` skips updating descriptor_set if failing
to allocate one. (#8677) [@micb25]
- WebGPU: fixed undefined behaviors in example code for requesting adapter
and device. (#9246, #9256) [@r-lyeh]
- SDL2+WebGPU: fixed hi-dpi handling. (#9300) [@ypujante]
- GLFW/SDL2/SDL3+WebGPU: added support for WGVK. (#9316, #9246, #9257) [@r-lyeh, @ocornut]
- GLFW/SDL2/SDL3+WebGPU: removed support for Emscripten <4.0.10. (#9281) [@ypujante]
-----------------------------------------------------------------------
VERSION 1.92.6 (2026-02-17)
-----------------------------------------------------------------------
+1 -1
View File
@@ -93,7 +93,7 @@
// - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions.
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
//---- Use stb_truetype to build and rasterize the font atlas (default)
+57 -33
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.6
// dear imgui, v1.92.7
// (headers)
// Help:
@@ -20,7 +20,7 @@
// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui
// - Issues & support ........... https://github.com/ocornut/imgui/issues
// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps)
// - Web version of the Demo .... https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html (w/ source code browser)
// - Web version of the Demo .... https://pthom.github.io/imgui_explorer (w/ source code browser)
// For FIRST-TIME users having issues compiling/linking/running:
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
@@ -29,8 +29,8 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.92.6"
#define IMGUI_VERSION_NUM 19261
#define IMGUI_VERSION "1.92.7"
#define IMGUI_VERSION_NUM 19270
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
@@ -340,7 +340,9 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
typedef ImU64 ImTextureID; // Default: store up to 64-bits (any pointer or integer). A majority of backends are ok with that.
#endif
// Define this if you need 0 to be a valid ImTextureID for your backend.
// Define this if you need to change the invalid value for your backend.
// - If your backend is using ImTextureID to store an index/offset and you need 0 to be valid, You can add '#define ImTextureID_Invalid ((ImTextureID)-1)' in your imconfig.h file.
// - From 2026/03/12 to 2026/03/19 we experimented with changing to default to -1, but I worried it would cause too many issues in third-party code so it was reverted.
#ifndef ImTextureID_Invalid
#define ImTextureID_Invalid ((ImTextureID)0)
#endif
@@ -756,6 +758,7 @@ namespace ImGui
IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header.
IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state.
IMGUI_API void SetNextItemStorageID(ImGuiID storage_id); // set id to use for open/close storage (default to same as item id).
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id); // retrieve tree node open/close state.
// Widgets: Selectables
// - A selectable highlights when hovered, and can display another color when selected.
@@ -911,7 +914,7 @@ namespace ImGui
// The context menu can also be made available in columns body using ImGuiTableFlags_ContextMenuInBody.
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in
// some advanced use cases (e.g. adding custom widgets in header row).
// - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled.
// - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled. When freezing columns you would usually also use ImGuiTableColumnFlags_NoHide on them.
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_id = 0);
IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
@@ -998,7 +1001,7 @@ namespace ImGui
IMGUI_API void SetNavCursorVisible(bool visible); // alter visibility of keyboard/gamepad cursor. by default: show when using an arrow key, hide when clicking with mouse.
// Overlapping mode
IMGUI_API void SetNextItemAllowOverlap(); // allow next item to be overlapped by a subsequent item. Useful with invisible buttons, selectable, treenode covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this.
IMGUI_API void SetNextItemAllowOverlap(); // allow next item to be overlapped by a subsequent item. Typically useful with InvisibleButton(), Selectable(), TreeNode() covering an area where subsequent items may need to be added. Note that both Selectable() and TreeNode() have dedicated flags doing this.
// Item/Widgets Utilities and Query Functions
// - Most of the functions are referring to the previous Item that has been submitted.
@@ -1258,7 +1261,7 @@ enum ImGuiInputTextFlags_
ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider using IsItemDeactivatedAfterEdit() instead!
ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode, validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter).
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode: validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter). Note that Shift+Enter always enter a new line either way.
// Other options
ImGuiInputTextFlags_ReadOnly = 1 << 9, // Read-only mode
@@ -1300,13 +1303,13 @@ enum ImGuiTreeNodeFlags_
ImGuiTreeNodeFlags_None = 0,
ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected
ImGuiTreeNodeFlags_Framed = 1 << 1, // Draw frame with background (e.g. for CollapsingHeader)
ImGuiTreeNodeFlags_AllowOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one
ImGuiTreeNodeFlags_AllowOverlap = 1 << 2, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap().
ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack
ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes)
ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open
ImGuiTreeNodeFlags_OpenOnDoubleClick = 1 << 6, // Open on double-click instead of simple click (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined.
ImGuiTreeNodeFlags_OpenOnArrow = 1 << 7, // Open when clicking on the arrow part (default for multi-select unless any _OpenOnXXX behavior is set explicitly). Both behaviors may be combined.
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes). Note: will always open a tree/id scope and return true. If you never use that scope, add ImGuiTreeNodeFlags_NoTreePushOnOpen.
ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow. IMPORTANT: node can still be marked open/close if you don't set the _Leaf flag!
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding() before the node.
ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line without using AllowOverlap mode.
@@ -1360,7 +1363,7 @@ enum ImGuiSelectableFlags_
ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Frame will span all columns of its container table (text will still fit in current column)
ImGuiSelectableFlags_AllowDoubleClick = 1 << 2, // Generate press events on double clicks too
ImGuiSelectableFlags_Disabled = 1 << 3, // Cannot be selected, display grayed out text
ImGuiSelectableFlags_AllowOverlap = 1 << 4, // (WIP) Hit testing to allow subsequent widgets to overlap this one
ImGuiSelectableFlags_AllowOverlap = 1 << 4, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap().
ImGuiSelectableFlags_Highlight = 1 << 5, // Make the item be displayed as if it is hovered
ImGuiSelectableFlags_SelectOnNav = 1 << 6, // Auto-select when moved into, unless Ctrl is held. Automatic when in a BeginMultiSelect() block.
@@ -1615,10 +1618,10 @@ enum ImGuiKey : int
// // XBOX | SWITCH | PLAYSTA. | -> ACTION
ImGuiKey_GamepadStart, // Menu | + | Options |
ImGuiKey_GamepadBack, // View | - | Share |
ImGuiKey_GamepadFaceLeft, // X | Y | Square | Tap: Toggle Menu. Hold: Windowing mode (Focus/Move/Resize windows)
ImGuiKey_GamepadFaceLeft, // X | Y | Square | Toggle Menu. Hold for Windowing mode (Focus/Move/Resize windows)
ImGuiKey_GamepadFaceRight, // B | A | Circle | Cancel / Close / Exit
ImGuiKey_GamepadFaceUp, // Y | X | Triangle | Text Input / On-screen Keyboard
ImGuiKey_GamepadFaceDown, // A | B | Cross | Activate / Open / Toggle / Tweak
ImGuiKey_GamepadFaceUp, // Y | X | Triangle | Open Context Menu
ImGuiKey_GamepadFaceDown, // A | B | Cross | Activate / Open / Toggle. Hold for 0.60f to Activate in Text Input mode (e.g. wired to an on-screen keyboard).
ImGuiKey_GamepadDpadLeft, // D-pad Left | " | " | Move / Tweak / Resize Window (in Windowing mode)
ImGuiKey_GamepadDpadRight, // D-pad Right | " | " | Move / Tweak / Resize Window (in Windowing mode)
ImGuiKey_GamepadDpadUp, // D-pad Up | " | " | Move / Tweak / Resize Window (in Windowing mode)
@@ -1700,6 +1703,7 @@ enum ImGuiInputFlags_
};
// Configuration flags stored in io.ConfigFlags. Set by user/application.
// Note that nowadays most of our configuration options are in other ImGuiIO fields, e.g. io.ConfigWindowsMoveFromTitleBarOnly.
enum ImGuiConfigFlags_
{
ImGuiConfigFlags_None = 0,
@@ -1709,10 +1713,9 @@ enum ImGuiConfigFlags_
ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct backend to not alter mouse cursor shape and visibility. Use if the backend cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead.
ImGuiConfigFlags_NoKeyboard = 1 << 6, // Instruct dear imgui to disable keyboard inputs and interactions. This is done by ignoring keyboard events and clearing existing states.
// User storage (to allow your backend/engine to communicate to code that may be shared between multiple projects. Those flags are NOT used by core Dear ImGui)
// [Unused] User storage (to allow your backend/engine to communicate to code that may be shared between multiple projects. Those flags are NOT used by core Dear ImGui)
ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware.
ImGuiConfigFlags_IsTouchScreen = 1 << 21, // Application is using a touch screen instead of a mouse.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // [moved/renamed in 1.91.4] -> use bool io.ConfigNavMoveSetMousePos
ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // [moved/renamed in 1.91.4] -> use bool io.ConfigNavCaptureKeyboard
@@ -1851,6 +1854,7 @@ enum ImGuiStyleVar_
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
ImGuiStyleVar_SeparatorSize, // float SeparatorSize
ImGuiStyleVar_SeparatorTextBorderSize, // float SeparatorTextBorderSize
ImGuiStyleVar_SeparatorTextAlign, // ImVec2 SeparatorTextAlign
ImGuiStyleVar_SeparatorTextPadding, // ImVec2 SeparatorTextPadding
@@ -1866,6 +1870,7 @@ enum ImGuiButtonFlags_
ImGuiButtonFlags_MouseButtonMiddle = 1 << 2, // React on center mouse button
ImGuiButtonFlags_MouseButtonMask_ = ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle, // [Internal]
ImGuiButtonFlags_EnableNav = 1 << 3, // InvisibleButton(): do not disable navigation/tabbing. Otherwise disabled by default.
ImGuiButtonFlags_AllowOverlap = 1 << 12, // Hit testing will allow subsequent widgets to overlap this one. Require previous frame HoveredId to match before being usable. Shortcut to calling SetNextItemAllowOverlap().
};
// Flags for ColorEdit3() / ColorEdit4() / ColorPicker3() / ColorPicker4() / ColorButton()
@@ -2025,11 +2030,11 @@ enum ImGuiTableFlags_
// Features
ImGuiTableFlags_None = 0,
ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns.
ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers)
ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row. (Need calling TableSetupColumn() + TableHeadersRow() to display headers, or using ImGuiTableFlags_ContextMenuInBody to access context-menu without headers).
ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu.
ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate.
ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width, visibility and sort settings in the .ini file.
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow().
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will also display table context menu. By default it is available in TableHeadersRow().
// Decorations
ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually)
ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows.
@@ -2330,6 +2335,7 @@ struct ImGuiStyle
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
float SeparatorSize; // Thickness of border in Separator()
float SeparatorTextBorderSize; // Thickness of border in SeparatorText()
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
@@ -2354,7 +2360,7 @@ struct ImGuiStyle
ImGuiHoveredFlags HoverFlagsForTooltipNav; // Default flags when using IsItemHovered(ImGuiHoveredFlags_ForTooltip) or BeginItemTooltip()/SetItemTooltip() while using keyboard/gamepad.
// [Internal]
float _MainScale; // FIXME-WIP: Reference scale, as applied by ScaleAllSizes().
float _MainScale; // FIXME-WIP: Reference scale, as applied by ScaleAllSizes(). PLEASE DO NOT USE THIS FOR NOW.
float _NextFrameFontSizeBase; // FIXME: Temporary hack until we finish remaining work.
// Functions
@@ -2425,7 +2431,7 @@ struct ImGuiIO
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only).
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only).
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
@@ -2850,15 +2856,16 @@ enum ImGuiListClipperFlags_
// - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc.
struct ImGuiListClipper
{
ImGuiContext* Ctx; // Parent UI context
int DisplayStart; // First item to display, updated by each call to Step()
int DisplayEnd; // End of items to display (exclusive)
int UserIndex; // Helper storage for user convenience/code. Optional, and otherwise unused if you don't use it.
int ItemsCount; // [Internal] Number of items
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
ImGuiListClipperFlags Flags; // [Internal] Flags, currently not yet well exposed.
double StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
double StartSeekOffsetY; // [Internal] Account for frozen rows in a table and initial loss of precision in very large windows.
ImGuiContext* Ctx; // [Internal] Parent UI context
void* TempData; // [Internal] Internal data
ImGuiListClipperFlags Flags; // [Internal] Flags, currently not yet well exposed.
// items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step, and you can call SeekCursorForItem() manually if you need)
// items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
@@ -2889,17 +2896,18 @@ struct ImGuiListClipper
// - It is important that we are keeping those disabled by default so they don't leak in user space.
// - This is in order to allow user enabling implicit cast operators between ImVec2/ImVec4 and their own types (using IM_VEC2_CLASS_EXTRA in imconfig.h)
// - Add '#define IMGUI_DEFINE_MATH_OPERATORS' before including this file (or in imconfig.h) to access courtesy maths operators for ImVec2 and ImVec4.
// - We intentionally provide ImVec2*float but not float*ImVec2: this is rare enough and we want to reduce the surface for possible user mistake.
#ifdef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS_IMPLEMENTED
IM_MSVC_RUNTIME_CHECKS_OFF
// ImVec2 operators
inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
inline ImVec2 operator*(const float lhs, const ImVec2& rhs) { return ImVec2(lhs * rhs.x, lhs * rhs.y); }
inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
inline ImVec2 operator-(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x - rhs.x, lhs.y - rhs.y); }
inline ImVec2 operator*(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
inline ImVec2 operator/(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x / rhs.x, lhs.y / rhs.y); }
inline ImVec2 operator+(const ImVec2& lhs) { return lhs; }
inline ImVec2 operator-(const ImVec2& lhs) { return ImVec2(-lhs.x, -lhs.y); }
inline ImVec2& operator*=(ImVec2& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; return lhs; }
inline ImVec2& operator/=(ImVec2& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; return lhs; }
@@ -2911,12 +2919,20 @@ inline bool operator==(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x =
inline bool operator!=(const ImVec2& lhs, const ImVec2& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y; }
// ImVec4 operators
inline ImVec4 operator*(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x * rhs, lhs.y * rhs, lhs.z * rhs, lhs.w * rhs); }
inline ImVec4 operator*(const float lhs, const ImVec4& rhs) { return ImVec4(lhs * rhs.x, lhs * rhs.y, lhs * rhs.z, lhs * rhs.w); }
inline ImVec4 operator/(const ImVec4& lhs, const float rhs) { return ImVec4(lhs.x / rhs, lhs.y / rhs, lhs.z / rhs, lhs.w / rhs); }
inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
inline ImVec4 operator/(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x / rhs.x, lhs.y / rhs.y, lhs.z / rhs.z, lhs.w / rhs.w); }
inline ImVec4 operator+(const ImVec4& lhs) { return lhs; }
inline ImVec4 operator-(const ImVec4& lhs) { return ImVec4(-lhs.x, -lhs.y, -lhs.z, -lhs.w); }
inline ImVec4& operator*=(ImVec4& lhs, const float rhs) { lhs.x *= rhs; lhs.y *= rhs; lhs.z *= rhs; lhs.w *= rhs; return lhs; }
inline ImVec4& operator/=(ImVec4& lhs, const float rhs) { lhs.x /= rhs; lhs.y /= rhs; lhs.z /= rhs; lhs.w /= rhs; return lhs; }
inline ImVec4& operator+=(ImVec4& lhs, const ImVec4& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; lhs.w += rhs.w; return lhs; }
inline ImVec4& operator-=(ImVec4& lhs, const ImVec4& rhs) { lhs.x -= rhs.x; lhs.y -= rhs.y; lhs.z -= rhs.z; lhs.w -= rhs.w; return lhs; }
inline ImVec4& operator*=(ImVec4& lhs, const ImVec4& rhs) { lhs.x *= rhs.x; lhs.y *= rhs.y; lhs.z *= rhs.z; lhs.w *= rhs.w; return lhs; }
inline ImVec4& operator/=(ImVec4& lhs, const ImVec4& rhs) { lhs.x /= rhs.x; lhs.y /= rhs.y; lhs.z /= rhs.z; lhs.w /= rhs.w; return lhs; }
inline bool operator==(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z && lhs.w == rhs.w; }
inline bool operator!=(const ImVec4& lhs, const ImVec4& rhs) { return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z || lhs.w != rhs.w; }
IM_MSVC_RUNTIME_CHECKS_RESTORE
@@ -3018,16 +3034,23 @@ enum ImGuiMultiSelectFlags_
ImGuiMultiSelectFlags_NoAutoClearOnReselect = 1 << 5, // Disable clearing selection when clicking/selecting an already selected item.
ImGuiMultiSelectFlags_BoxSelect1d = 1 << 6, // Enable box-selection with same width and same x pos items (e.g. full row Selectable()). Box-selection works better with little bit of spacing between items hit-box in order to be able to aim at empty space.
ImGuiMultiSelectFlags_BoxSelect2d = 1 << 7, // Enable box-selection with varying width or varying x pos items support (e.g. different width labels, or 2D layout/grid). This is slower: alters clipping logic so that e.g. horizontal movements will update selection of normally clipped items.
ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting near edges of scope.
ImGuiMultiSelectFlags_BoxSelectNoScroll = 1 << 8, // Disable scrolling when box-selecting and moving mouse near edges of scope.
ImGuiMultiSelectFlags_ClearOnEscape = 1 << 9, // Clear selection when pressing Escape while scope is focused.
ImGuiMultiSelectFlags_ClearOnClickVoid = 1 << 10, // Clear selection when clicking on empty location within scope.
ImGuiMultiSelectFlags_ScopeWindow = 1 << 11, // Scope for _BoxSelect and _ClearOnClickVoid is whole window (Default). Use if BeginMultiSelect() covers a whole window or used a single time in same window.
ImGuiMultiSelectFlags_ScopeRect = 1 << 12, // Scope for _BoxSelect and _ClearOnClickVoid is rectangle encompassing BeginMultiSelect()/EndMultiSelect(). Use if BeginMultiSelect() is called multiple times in same window.
ImGuiMultiSelectFlags_SelectOnClick = 1 << 13, // Apply selection on mouse down when clicking on unselected item. (Default)
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 14, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection.
ImGuiMultiSelectFlags_SelectOnAuto = 1 << 13, // Apply selection on mouse down when clicking on unselected item, on mouse up when clicking on selected item. (Default)
ImGuiMultiSelectFlags_SelectOnClickAlways = 1 << 14, // Apply selection on mouse down when clicking on any items. Prevents Drag and Drop from being used on multiple-selection, but allows e.g. BoxSelect to always reselect even when clicking inside an existing selection. (Excel style behavior)
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 15, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection.
//ImGuiMultiSelectFlags_RangeSelect2d = 1 << 15, // Shift+Selection uses 2d geometry instead of linear sequence, so possible to use Shift+up/down to select vertically in grid. Analogous to what BoxSelect does.
ImGuiMultiSelectFlags_NavWrapX = 1 << 16, // [Temporary] Enable navigation wrapping on X axis. Provided as a convenience because we don't have a design for the general Nav API for this yet. When the more general feature be public we may obsolete this flag in favor of new one.
ImGuiMultiSelectFlags_NoSelectOnRightClick = 1 << 17, // Disable default right-click processing, which selects item on mouse down, and is designed for context-menus.
ImGuiMultiSelectFlags_SelectOnMask_ = ImGuiMultiSelectFlags_SelectOnAuto | ImGuiMultiSelectFlags_SelectOnClickAlways | ImGuiMultiSelectFlags_SelectOnClickRelease,
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiMultiSelectFlags_SelectOnClick = ImGuiMultiSelectFlags_SelectOnAuto, // RENAMED in 1.92.6
#endif
};
// Main IO structure returned by BeginMultiSelect()/EndMultiSelect().
@@ -3641,7 +3664,7 @@ enum ImFontAtlasFlags_
// - Call Build() + GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data.
// - Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture in a format natural to your graphics API.
// Common pitfalls:
// - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the
// - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persists up until the
// atlas is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data.
// - Important: By default, AddFontFromMemoryTTF() takes ownership of the data. Even though we are not writing to it, we will free the pointer on destruction.
// You can set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed,
@@ -3853,7 +3876,7 @@ struct ImFont
ImFontAtlas* OwnerAtlas; // 4-8 // What we have been loaded into.
ImFontFlags Flags; // 4 // Font flags.
float CurrentRasterizerDensity; // Current rasterizer density. This is a varying state of the font.
float LineHeight; // 4 // Line Height
float LineHeight; // 4 // Line Height
// [Internal] Members: Cold ~24-52 bytes
// Conceptually Sources[] is the list of font sources merged to create this font.
@@ -3904,8 +3927,10 @@ inline ImTextureID ImTextureRef::GetTexID() const
// Using an indirection to avoid patching ImDrawCmd after a SetTexID() call (but this could be an alternative solution too)
inline ImTextureID ImDrawCmd::GetTexID() const
{
// If you are getting this assert: A renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92)
// must iterate and handle ImTextureData requests stored in ImDrawData::Textures[].
// If you are getting this assert with ImTextureID_Invalid == 0 and your ImTextureID is used to store an index or an offset:
// - You can add '#define ImTextureID_Invalid ((ImTextureID)-1)' in your imconfig.h file.
// If you are getting this assert with a renderer backend with support for ImGuiBackendFlags_RendererHasTextures (1.92+):
// - You must correctly iterate and handle ImTextureData requests stored in ImDrawData::Textures[]. See docs/BACKENDS.md.
ImTextureID tex_id = TexRef._TexData ? TexRef._TexData->TexID : TexRef._TexID; // == TexRef.GetTexID() above.
if (TexRef._TexData != NULL)
IM_ASSERT(tex_id != ImTextureID_Invalid && "ImDrawCmd is referring to ImTextureData that wasn't uploaded to graphics system. Backend must call ImTextureData::SetTexID() after handling ImTextureStatus_WantCreate request!");
@@ -4049,12 +4074,11 @@ namespace ImGui
IMGUI_API ImVec2 GetContentRegionMax(); // Content boundaries max (e.g. window boundaries including scrolling, or current column boundaries). You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
IMGUI_API ImVec2 GetWindowContentRegionMin(); // Content boundaries min for the window (roughly (0,0)-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
IMGUI_API ImVec2 GetWindowContentRegionMax(); // Content boundaries max for the window (roughly (0,0)+Size-Scroll), in window-local coordinates. You should never need this. Always use GetCursorScreenPos() and GetContentRegionAvail()!
// OBSOLETED in 1.90.0 (from September 2023)
IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1);
IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1);
// Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE)
// OBSOLETED in 1.90.0 (from September 2023)
//IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1); // Getter signature changed. See 2023/09/15 and 2026/02/27 commits.
//IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1); // Getter signature changed. See 2023/09/15 and 2026/02/27 commits.
//inline bool BeginChild(const char* str_id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(str_id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
//inline bool BeginChild(ImGuiID id, const ImVec2& size_arg, bool borders, ImGuiWindowFlags window_flags) { return BeginChild(id, size_arg, borders ? ImGuiChildFlags_Borders : ImGuiChildFlags_None, window_flags); } // Unnecessary as true == ImGuiChildFlags_Borders
//inline bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0) { return BeginChild(id, size, ImGuiChildFlags_FrameStyle, flags); }
+33 -16
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.6
// dear imgui, v1.92.7
// (internal structures/api)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
@@ -534,7 +534,7 @@ inline float ImLinearSweep(float current, float target, float speed) { if (cu
inline float ImLinearRemapClamp(float s0, float s1, float d0, float d1, float x) { return ImSaturate((x - s0) / (s1 - s0)) * (d1 - d0) + d0; }
inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); }
inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; }
inline float ImExponentialMovingAverage(float avg, float sample, int n){ avg -= avg / n; avg += sample / n; return avg; }
inline float ImExponentialMovingAverage(float avg, float sample, int n){ avg -= avg / (float)n; avg += sample / (float)n; return avg; }
IM_MSVC_RUNTIME_CHECKS_RESTORE
// Helpers: Geometry
@@ -1023,7 +1023,7 @@ enum ImGuiInputTextFlagsPrivate_
{
// [Internal]
ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline()
ImGuiInputTextFlags_MergedItem = 1 << 27, // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
ImGuiInputTextFlags_TempInput = 1 << 27, // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
ImGuiInputTextFlags_LocalizeDecimalPoint= 1 << 28, // For internal use by InputScalar() and TempInputScalar()
};
@@ -1033,12 +1033,11 @@ enum ImGuiButtonFlagsPrivate_
ImGuiButtonFlags_PressedOnClick = 1 << 4, // return true on click (mouse down event)
ImGuiButtonFlags_PressedOnClickRelease = 1 << 5, // [Default] return true on click + release on same item <-- this is what the majority of Button are using
ImGuiButtonFlags_PressedOnClickReleaseAnywhere = 1 << 6, // return true on click + release even if the release event is not done while hovering the item
ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release)
ImGuiButtonFlags_PressedOnRelease = 1 << 7, // return true on release (default requires click+release). Prior to 2026/03/20 this implied ImGuiButtonFlags_NoHoldingActiveId but they are separate now.
ImGuiButtonFlags_PressedOnDoubleClick = 1 << 8, // return true on double-click (default requires click+release)
ImGuiButtonFlags_PressedOnDragDropHold = 1 << 9, // return true when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers)
//ImGuiButtonFlags_Repeat = 1 << 10, // hold to repeat -> use ImGuiItemFlags_ButtonRepeat instead.
ImGuiButtonFlags_FlattenChildren = 1 << 11, // allow interactions even if a child window is overlapping
ImGuiButtonFlags_AllowOverlap = 1 << 12, // require previous frame HoveredId to either match id or be null before being usable.
//ImGuiButtonFlags_DontClosePopups = 1 << 13, // disable automatically closing parent popup on press
//ImGuiButtonFlags_Disabled = 1 << 14, // disable interactions -> use BeginDisabled() or ImGuiItemFlags_Disabled
ImGuiButtonFlags_AlignTextBaseLine = 1 << 15, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine
@@ -1246,7 +1245,8 @@ struct IMGUI_API ImGuiInputTextState
bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
bool CursorCenterY; // set when we want scrolling to be centered over the cursor position (while resizing a word-wrapping field)
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
bool Edited; // edited this frame
bool EditedBefore; // edited since activated
bool EditedThisFrame; // edited this frame
bool WantReloadUserBuf; // force a reload of user buf so it may be modified externally. may be automatic in future version.
ImS8 LastMoveDirectionLR; // ImGuiDir_Left or ImGuiDir_Right. track last movement direction so when cursor cross over a word-wrapping boundaries we can display it on either line depending on last move.s
int ReloadSelectionStart;
@@ -1259,6 +1259,7 @@ struct IMGUI_API ImGuiInputTextState
void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation
void OnCharPressed(unsigned int c);
float GetPreferredOffsetX() const;
const char* GetText() { return TextA.Data ? TextA.Data : ""; }
// Cursor & Selection
void CursorAnimReset();
@@ -1508,8 +1509,8 @@ typedef ImBitArray<ImGuiKey_NamedKey_COUNT, -ImGuiKey_NamedKey_BEGIN> ImBitAr
#define ImGuiKey_NavGamepadTweakFast ImGuiKey_GamepadR1
#define ImGuiKey_NavGamepadActivate (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceRight : ImGuiKey_GamepadFaceDown)
#define ImGuiKey_NavGamepadCancel (g.IO.ConfigNavSwapGamepadButtons ? ImGuiKey_GamepadFaceDown : ImGuiKey_GamepadFaceRight)
#define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft
#define ImGuiKey_NavGamepadInput ImGuiKey_GamepadFaceUp
#define ImGuiKey_NavGamepadMenu ImGuiKey_GamepadFaceLeft // Toggle menu layer. Hold to enable Windowing.
#define ImGuiKey_NavGamepadContextMenu ImGuiKey_GamepadFaceUp // Open context menu (same as Shift+F10)
enum ImGuiInputEventType
{
@@ -1958,7 +1959,7 @@ struct IMGUI_API ImGuiMultiSelectState
// Every instance of ImGuiViewport is in fact a ImGuiViewportP.
struct ImGuiViewportP : public ImGuiViewport
{
int BgFgDrawListsLastFrame[2]; // Last frame number the background (0) and foreground (1) draw lists were used
float BgFgDrawListsLastTimeActive[2]; // Last frame number the background (0) and foreground (1) draw lists were used
ImDrawList* BgFgDrawLists[2]; // Convenience background (0) and foreground (1) draw lists. We use them to draw software mouser cursor when io.MouseDrawCursor is set and to draw most debug overlays.
ImDrawData DrawDataP;
ImDrawDataBuilder DrawDataBuilder; // Temporary data while building final ImDrawData
@@ -1972,7 +1973,7 @@ struct ImGuiViewportP : public ImGuiViewport
ImVec2 BuildWorkInsetMin; // Work Area inset accumulator for current frame, to become next frame's WorkInset
ImVec2 BuildWorkInsetMax; // "
ImGuiViewportP() { BgFgDrawListsLastFrame[0] = BgFgDrawListsLastFrame[1] = -1; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; }
ImGuiViewportP() { BgFgDrawListsLastTimeActive[0] = BgFgDrawListsLastTimeActive[1] = -1.0f; BgFgDrawLists[0] = BgFgDrawLists[1] = NULL; }
~ImGuiViewportP() { if (BgFgDrawLists[0]) IM_DELETE(BgFgDrawLists[0]); if (BgFgDrawLists[1]) IM_DELETE(BgFgDrawLists[1]); }
// Calculate work rect pos/size given a set of offset (we have 1 pair of offset for rect locked from last frame data, and 1 pair for currently building rect)
@@ -2182,6 +2183,8 @@ struct ImGuiContextHook
ImGuiContextHook() { memset((void*)this, 0, sizeof(*this)); }
};
typedef void (*ImGuiDemoMarkerCallback)(const char* file, int line, const char* section);
//-----------------------------------------------------------------------------
// [SECTION] ImGuiContext (main Dear ImGui context)
//-----------------------------------------------------------------------------
@@ -2323,6 +2326,7 @@ struct ImGuiContext
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope)
ImGuiNavLayer NavLayer; // Focused layer (main scrolling layer, or menu/title bar layer)
ImGuiItemFlags NavIdItemFlags;
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItemByID()
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
@@ -2330,6 +2334,8 @@ struct ImGuiContext
ImVector<ImGuiFocusScopeData> NavFocusRoute; // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
ImGuiID NavHighlightActivatedId;
float NavHighlightActivatedTimer;
ImGuiID NavOpenContextMenuItemId;
ImGuiID NavOpenContextMenuWindowId;
ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame.
ImGuiActivateFlags NavNextActivateFlags;
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Gamepad
@@ -2459,6 +2465,7 @@ struct ImGuiContext
ImGuiInputTextDeactivatedState InputTextDeactivatedState;
ImFontBaked InputTextPasswordFontBackupBaked;
ImFontFlags InputTextPasswordFontBackupFlags;
ImGuiID InputTextReactivateId; // ID of InputText to reactivate on next frame (for io.ConfigInputTextEnterKeepActive behavior)
ImGuiID TempInputId; // Temporary text input when using Ctrl+Click on a slider, etc.
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
int BeginMenuDepth;
@@ -2504,8 +2511,11 @@ struct ImGuiContext
ImVector<ImGuiSettingsHandler> SettingsHandlers; // List of .ini settings handlers
ImChunkStream<ImGuiWindowSettings> SettingsWindows; // ImGuiWindow .ini settings entries
ImChunkStream<ImGuiTableSettings> SettingsTables; // ImGuiTable .ini settings entries
// Hooks
ImVector<ImGuiContextHook> Hooks; // Hooks for extensions (e.g. test engine)
ImGuiID HookIdNext; // Next available HookId
ImGuiDemoMarkerCallback DemoMarkerCallback;
// Localization
const char* LocalizationTable[ImGuiLocKey_COUNT];
@@ -3035,8 +3045,9 @@ struct IMGUI_API ImGuiTable
ImGuiTableColumnIdx ResizedColumn; // Index of column being resized. Reset when InstanceCurrent==0.
ImGuiTableColumnIdx LastResizedColumn; // Index of column being resized from previous frame.
ImGuiTableColumnIdx HeldHeaderColumn; // Index of column header being held.
ImGuiTableColumnIdx LastHeldHeaderColumn; // Index of column header being held from previous frame.
ImGuiTableColumnIdx ReorderColumn; // Index of column being reordered. (not cleared)
ImGuiTableColumnIdx ReorderColumnDir; // -1 or +1
ImGuiTableColumnIdx ReorderColumnDstOrder; // Requested display order of column being reordered.
ImGuiTableColumnIdx LeftMostEnabledColumn; // Index of left-most non-hidden column.
ImGuiTableColumnIdx RightMostEnabledColumn; // Index of right-most non-hidden column.
ImGuiTableColumnIdx LeftMostStretchedColumn; // Index of left-most stretched column.
@@ -3325,6 +3336,8 @@ namespace ImGui
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
IMGUI_API ImGuiMouseButton GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags);
IMGUI_API bool IsPopupOpenRequestForItem(ImGuiPopupFlags flags, ImGuiID id);
IMGUI_API bool IsPopupOpenRequestForWindow(ImGuiPopupFlags flags);
// Tooltips
IMGUI_API bool BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
@@ -3549,6 +3562,7 @@ namespace ImGui
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
IMGUI_API void TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
IMGUI_API void TableQueueSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
IMGUI_API void TableRemove(ImGuiTable* table);
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
@@ -3638,6 +3652,7 @@ namespace ImGui
IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
IMGUI_API ImGuiID GetWindowResizeCornerID(ImGuiWindow* window, int n); // 0..3: corners
IMGUI_API ImGuiID GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir);
IMGUI_API void ExtendHitBoxWhenNearViewportEdge(ImGuiWindow* window, ImRect* bb, float threshold, ImGuiAxis axis);
// Widgets low-level behaviors
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);
@@ -3650,15 +3665,14 @@ namespace ImGui
IMGUI_API void TreeNodeDrawLineToChildNode(const ImVec2& target_pos);
IMGUI_API void TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data);
IMGUI_API void TreePushOverrideID(ImGuiID id);
IMGUI_API bool TreeNodeGetOpen(ImGuiID storage_id);
IMGUI_API void TreeNodeSetOpen(ImGuiID storage_id, bool open);
IMGUI_API bool TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags); // Return open state. Consume previous SetNextItemOpen() data, if any. May return true when logging.
// Template functions are instantiated in imgui_widgets.cpp for a finite number of types.
// To use them externally (for custom widget) you may need an "extern template" statement in your code in order to link to existing instances and silence Clang warnings (see #2036).
// e.g. " extern template IMGUI_API float RoundScalarWithFormatT<float, float>(const char* format, ImGuiDataType data_type, float v); "
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size);
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_size);
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API float ScaleRatioFromValueT(ImGuiDataType data_type, T v, T v_min, T v_max, float logarithmic_zero_epsilon, float zero_deadzone_size);
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API T ScaleValueFromRatioT(ImGuiDataType data_type, float t, T v_min, T v_max, float logarithmic_zero_epsilon, float zero_deadzone_size);
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool DragBehaviorT(ImGuiDataType data_type, T* v, float v_speed, T v_min, T v_max, const char* format, ImGuiSliderFlags flags);
template<typename T, typename SIGNED_T, typename FLOAT_T> IMGUI_API bool SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_type, T* v, T v_min, T v_max, const char* format, ImGuiSliderFlags flags, ImRect* out_grab_bb);
template<typename T> IMGUI_API T RoundScalarWithFormatT(const char* format, ImGuiDataType data_type, T v);
@@ -3676,7 +3690,7 @@ namespace ImGui
// InputText
IMGUI_API bool InputTextEx(const char* label, const char* hint, char* buf, int buf_size, const ImVec2& size_arg, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API void InputTextDeactivateHook(ImGuiID id);
IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags);
IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return g.ActiveId == id && g.TempInputId == id; }
inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active
@@ -3712,6 +3726,9 @@ namespace ImGui
IMGUI_API bool BeginErrorTooltip();
IMGUI_API void EndErrorTooltip();
// Demo Doc Marker for e.g. imgui_explorer
IMGUI_API void DemoMarker(const char* file, int line, const char* section);
// Debug Tools
IMGUI_API void DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size); // size >= 0 : alloc, size = -1 : free
IMGUI_API void DebugDrawCursorPos(ImU32 col = IM_COL32(255, 0, 0, 255));
@@ -3731,7 +3748,7 @@ namespace ImGui
IMGUI_API void DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, const ImDrawList* draw_list, const char* label);
IMGUI_API void DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, const ImDrawList* draw_list, const ImDrawCmd* draw_cmd, bool show_mesh, bool show_aabb);
IMGUI_API void DebugNodeFont(ImFont* font);
IMGUI_API void DebugNodeFontGlyphesForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask);
IMGUI_API void DebugNodeFontGlyphsForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask);
IMGUI_API void DebugNodeFontGlyph(ImFont* font, const ImFontGlyph* glyph);
IMGUI_API void DebugNodeTexture(ImTextureData* tex, int int_id, const ImFontAtlasRect* highlight_rect = NULL); // ID used to facilitate persisting the "current" texture.
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
+166 -53
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.6
// dear imgui, v1.92.7
// (main code and documentation)
// Help:
@@ -20,7 +20,7 @@
// - Software using Dear ImGui https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui
// - Issues & support ........... https://github.com/ocornut/imgui/issues
// - Test Engine & Automation ... https://github.com/ocornut/imgui_test_engine (test suite, test engine to automate your apps)
// - Web version of the Demo .... https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html (w/ source code browser)
// - Web version of the Demo .... https://pthom.github.io/imgui_explorer (w/ source code browser)
// For FIRST-TIME users having issues compiling/linking/running:
// please post in https://github.com/ocornut/imgui/discussions if you cannot find a solution in resources above.
@@ -167,6 +167,7 @@ CODE
- Home, End Scroll to top, scroll to bottom.
- Alt Toggle between scrolling layer and menu layer.
- Ctrl+Tab then Ctrl+Arrows Move window. Hold Shift to resize instead of moving.
- Menu or Shift+F10 Open context menu.
- Output when ImGuiConfigFlags_NavEnableKeyboard set,
- io.WantCaptureKeyboard flag is set when keyboard is claimed.
- io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
@@ -207,7 +208,7 @@ CODE
The UI can be highly dynamic, there are no construction or destruction steps, less superfluous
data retention on your side, less state duplication, less state synchronization, fewer bugs.
- Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features.
Or browse https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html for interactive web version.
Or browse pthom's online imgui_explorer: https://pthom.github.io/imgui_explorer for a web version w/ source code browser.
- The library is designed to be built from sources. Avoid pre-compiled binaries and packaged versions. See imconfig.h to configure your build.
- Dear ImGui is an implementation of the IMGUI paradigm (immediate-mode graphical user interface, a term coined by Casey Muratori).
You can learn about IMGUI principles at http://www.johno.se/book/imgui.html, http://mollyrocket.com/861 & more links in Wiki.
@@ -394,6 +395,19 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2026/03/19 (1.92.7) - MultiSelect: renamed ImGuiMultiSelectFlags_SelectOnClick to ImGuiMultiSelectFlags_SelectOnAuto.
- 2026/02/26 (1.92.7) - Separator: fixed a legacy quirk where Separator() was submitting a zero-height item for layout purpose, even though it draws a 1-pixel separator.
The fix could affect code e.g. computing height from multiple widgets in order to allocate vertical space for a footer or multi-line status bar. (#2657, #9263)
The "Console" example had such a bug:
float footer_height = style.ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
BeginChild("ScrollingRegion", { 0, -footer_height });
Should be:
float footer_height = style.ItemSpacing.y + style.SeparatorSize + ImGui::GetFrameHeightWithSpacing();
BeginChild("ScrollingRegion", { 0, -footer_height });
When such idiom was used and assuming zero-height Separator, it is likely that in 1.92.7 the resulting window will have unexpected 1 pixel scrolling range.
- 2026/02/23 (1.92.7) - Commented out legacy signature for Combo(), ListBox(), signatures which were obsoleted in 1.90 (Nov 2023), when the getter callback type was changed.
- Old getter type: bool (*getter)(void* user_data, int idx, const char** out_text) // Set label + return bool. False replaced label with placeholder.
- New getter type: const char* (*getter)(void* user_data, int idx) // Return label or NULL/empty label if missing
- 2026/01/08 (1.92.6) - Commented out legacy names obsoleted in 1.90 (Sept 2023): 'BeginChildFrame()' --> 'BeginChild()' with 'ImGuiChildFlags_FrameStyle'. 'EndChildFrame()' --> 'EndChild()'. 'ShowStackToolWindow()' --> 'ShowIDStackToolWindow()'. 'IM_OFFSETOF()' --> 'offsetof()'.
- 2026/01/07 (1.92.6) - Popups: changed compile-time 'ImGuiPopupFlags popup_flags = 1' default value to be '= 0' for BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick(). Default value has same meaning before and after.
- Refer to GitHub topic #9157 if you have any question.
@@ -1098,6 +1112,8 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
- Run the examples/ applications and explore them.
- Read Getting Started (https://github.com/ocornut/imgui/wiki/Getting-Started) guide.
- See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
- See pthom's online imgui_explorer (https://pthom.github.io/imgui_explorer) which is a web
version of the demo with a source code browser.
- The demo covers most features of Dear ImGui, so you can read the code and see its output.
- See documentation and comments at the top of imgui.cpp + effectively imgui.h.
- 20+ standalone example applications using e.g. OpenGL/DirectX are provided in the
@@ -1134,10 +1150,10 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
----------
Q: About the ID Stack system..
- Why is my widget not reacting when I click on it?
- How can I have widgets with an empty label?
- How can I have multiple widgets with the same label?
- How can I have multiple windows with the same label?
- How can I have multiple widgets with the same label? (using ## or PushID)
- How can I have widgets with an empty label? (using ##)
- How can I make a label dynamic? (using ###)
- General description of the label and ID Stack system.
Q: How can I display an image? What is ImTextureID, how does it work?
Q: How can I use my own math types instead of ImVec2?
Q: How can I interact with standard C++ types (such as std::string and std::vector)?
@@ -1294,6 +1310,7 @@ static const float FONT_DEFAULT_SIZE_BASE = 20.0f;
static const float NAV_WINDOWING_HIGHLIGHT_DELAY = 0.20f; // Time before the highlight and screen dimming starts fading in
static const float NAV_WINDOWING_LIST_APPEAR_DELAY = 0.15f; // Time before the window list starts to appear
static const float NAV_ACTIVATE_HIGHLIGHT_TIMER = 0.10f; // Time to highlight an item activated by a shortcut.
static const float NAV_ACTIVATE_INPUT_WITH_GAMEPAD_DELAY = 0.60f; // Time to hold activation button (e.g. FaceDown) to turn the activation into a text input.
static const float WINDOWS_RESIZE_FROM_EDGES_FEEDBACK_TIMER = 0.04f; // Reduce visual noise by only highlighting the border after a certain time.
static const float WINDOWS_MOUSE_WHEEL_SCROLL_LOCK_TIMER = 0.70f; // Lock scrolled window (so it doesn't pick child windows that are scrolling through) for a certain time, unless mouse moved.
@@ -1340,6 +1357,7 @@ static void NavUpdateWindowing();
static void NavUpdateWindowingApplyFocus(ImGuiWindow* window);
static void NavUpdateWindowingOverlay();
static void NavUpdateCancelRequest();
static void NavUpdateContextMenuRequest();
static void NavUpdateCreateMoveRequest();
static void NavUpdateCreateTabbingRequest();
static float NavUpdatePageUpPageDown();
@@ -1494,7 +1512,8 @@ ImGuiStyle::ImGuiStyle()
ColorButtonPosition = ImGuiDir_Right; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
SelectableTextAlign = ImVec2(0.0f,0.0f);// Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
SeparatorTextBorderSize = 3.0f; // Thickness of border in SeparatorText()
SeparatorSize = 1.0f; // Thickness of border in Separator().
SeparatorTextBorderSize = 3.0f; // Thickness of border in SeparatorText().
SeparatorTextAlign = ImVec2(0.0f,0.5f);// Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
SeparatorTextPadding = ImVec2(20.0f,3.f);// Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area or monitors by at least this amount. Only applies to regular windows.
@@ -1529,11 +1548,15 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
_MainScale *= scale_factor;
WindowPadding = ImTrunc(WindowPadding * scale_factor);
WindowRounding = ImTrunc(WindowRounding * scale_factor);
WindowBorderSize = ImTrunc(WindowBorderSize * scale_factor);
WindowMinSize = ImTrunc(WindowMinSize * scale_factor);
WindowBorderHoverPadding = ImTrunc(WindowBorderHoverPadding * scale_factor);
ChildRounding = ImTrunc(ChildRounding * scale_factor);
ChildBorderSize = ImTrunc(ChildBorderSize * scale_factor);
PopupRounding = ImTrunc(PopupRounding * scale_factor);
PopupBorderSize = ImTrunc(PopupBorderSize * scale_factor);
FramePadding = ImTrunc(FramePadding * scale_factor);
FrameBorderSize = ImTrunc(FrameBorderSize * scale_factor);
FrameRounding = ImTrunc(FrameRounding * scale_factor);
ItemSpacing = ImTrunc(ItemSpacing * scale_factor);
ItemInnerSpacing = ImTrunc(ItemInnerSpacing * scale_factor);
@@ -1550,16 +1573,21 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
ImageRounding = ImTrunc(ImageRounding * scale_factor);
ImageBorderSize = ImTrunc(ImageBorderSize * scale_factor);
TabRounding = ImTrunc(TabRounding * scale_factor);
TabBorderSize = ImTrunc(TabBorderSize * scale_factor);
TabMinWidthBase = ImTrunc(TabMinWidthBase * scale_factor);
TabMinWidthShrink = ImTrunc(TabMinWidthShrink * scale_factor);
TabCloseButtonMinWidthSelected = (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor) : TabCloseButtonMinWidthSelected;
TabCloseButtonMinWidthUnselected = (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor) : TabCloseButtonMinWidthUnselected;
TabBarBorderSize = ImTrunc(TabBarBorderSize * scale_factor);
TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor);
TreeLinesSize = ImTrunc(TreeLinesSize * scale_factor);
TreeLinesRounding = ImTrunc(TreeLinesRounding * scale_factor);
DragDropTargetRounding = ImTrunc(DragDropTargetRounding * scale_factor);
DragDropTargetBorderSize = ImTrunc(DragDropTargetBorderSize * scale_factor);
DragDropTargetPadding = ImTrunc(DragDropTargetPadding * scale_factor);
ColorMarkerSize = ImTrunc(ColorMarkerSize * scale_factor);
SeparatorSize = ImTrunc(SeparatorSize * scale_factor);
SeparatorTextBorderSize = ImTrunc(SeparatorTextBorderSize * scale_factor);
SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor);
DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor);
DisplaySafeAreaPadding = ImTrunc(DisplaySafeAreaPadding * scale_factor);
@@ -3242,8 +3270,7 @@ ImGuiListClipper::~ImGuiListClipper()
void ImGuiListClipper::Begin(int items_count, float items_height)
{
if (Ctx == NULL)
Ctx = ImGui::GetCurrentContext();
Ctx = ImGui::GetCurrentContext();
ImGuiContext& g = *Ctx;
ImGuiWindow* window = g.CurrentWindow;
@@ -3289,6 +3316,7 @@ void ImGuiListClipper::End()
}
TempData = NULL;
}
DisplayStart = DisplayEnd = ItemsCount; // Clear this so code which may be reused past last Step() won't trip on a non-empty range.
ItemsCount = -1;
}
@@ -3493,7 +3521,7 @@ bool ImGuiListClipper::Step()
return ret;
}
// Generic helper, equivalent to old ImGui::CalcListClipping() but statelesss
// Generic helper, equivalent to old ImGui::CalcListClipping() but stateless
void ImGui::CalcClipRectVisibleItemsY(const ImRect& clip_rect, const ImVec2& pos, float items_height, int* out_visible_start, int* out_visible_end)
{
*out_visible_start = ImMax((int)((clip_rect.Min.y - pos.y) / items_height), 0);
@@ -3622,6 +3650,7 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] =
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesRounding)}, // ImGuiStyleVar_TreeLinesRounding
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorSize)}, // ImGuiStyleVar_SeparatorSize
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextBorderSize)}, // ImGuiStyleVar_SeparatorTextBorderSize
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextAlign) }, // ImGuiStyleVar_SeparatorTextAlign
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorTextPadding) }, // ImGuiStyleVar_SeparatorTextPadding
@@ -4185,6 +4214,8 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
NavWindow = NULL;
NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavLayer = ImGuiNavLayer_Main;
NavIdItemFlags = ImGuiItemFlags_None;
NavOpenContextMenuItemId = NavOpenContextMenuWindowId = 0;
NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavHighlightActivatedId = 0;
@@ -4254,6 +4285,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
MouseStationaryTimer = 0.0f;
InputTextPasswordFontBackupFlags = ImFontFlags_None;
InputTextReactivateId = 0;
TempInputId = 0;
memset(&DataTypeZeroValue, 0, sizeof(DataTypeZeroValue));
BeginMenuDepth = BeginComboDepth = 0;
@@ -4281,6 +4313,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
SettingsLoaded = false;
SettingsDirtyTimer = 0.0f;
HookIdNext = 0;
DemoMarkerCallback = NULL;
memset(LocalizationTable, 0, sizeof(LocalizationTable));
@@ -4596,11 +4629,12 @@ void ImGui::GcCompactTransientMiscBuffers()
// Not freed:
// - ImGuiWindow, ImGuiWindowSettings, Name, StateStorage, ColumnsStorage (may hold useful data)
// This should have no noticeable visual effect. When the window reappear however, expect new allocation/buffer growth/copy cost.
// FIXME: Consider exposing of elaborating GC policy, e.g. being able to trim excessive ImDrawList gaps. (#9303)
void ImGui::GcCompactTransientWindowBuffers(ImGuiWindow* window)
{
window->MemoryCompacted = true;
window->MemoryDrawListIdxCapacity = window->DrawList->IdxBuffer.Capacity;
window->MemoryDrawListVtxCapacity = window->DrawList->VtxBuffer.Capacity;
window->MemoryDrawListIdxCapacity = ImMin((int)(window->DrawList->IdxBuffer.Size * 1.05f), window->DrawList->IdxBuffer.Capacity);
window->MemoryDrawListVtxCapacity = ImMin((int)(window->DrawList->VtxBuffer.Size * 1.05f), window->DrawList->VtxBuffer.Capacity);
window->IDStack.clear();
window->DrawList->_ClearFreeMemory();
window->DC.ChildWindows.clear();
@@ -5050,6 +5084,13 @@ void ImGui::MemFree(void* ptr)
return (*GImAllocatorFreeFunc)(ptr, GImAllocatorUserData);
}
void ImGui::DemoMarker(const char* file, int line, const char* section)
{
ImGuiContext& g = *GImGui;
if (g.DemoMarkerCallback != NULL)
g.DemoMarkerCallback(file, line, section);
}
// We record the number of allocation in recent frames, as a way to audit/sanitize our guiding principles of "no allocations on idle/repeating frames"
void ImGui::DebugAllocHook(ImGuiDebugAllocInfo* info, int frame_count, void* ptr, size_t size)
{
@@ -5153,12 +5194,12 @@ static ImDrawList* GetViewportBgFgDrawList(ImGuiViewportP* viewport, size_t draw
}
// Our ImDrawList system requires that there is always a command
if (viewport->BgFgDrawListsLastFrame[drawlist_no] != g.FrameCount)
if (viewport->BgFgDrawListsLastTimeActive[drawlist_no] != (float)g.Time)
{
draw_list->_ResetForNewFrame();
draw_list->PushTexture(g.IO.Fonts->TexRef);
draw_list->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size, false);
viewport->BgFgDrawListsLastFrame[drawlist_no] = g.FrameCount;
viewport->BgFgDrawListsLastTimeActive[drawlist_no] = (float)g.Time;
}
return draw_list;
}
@@ -5523,7 +5564,7 @@ void ImGui::NewFrame()
// As a result, custom widget using ButtonBehavior() _without_ ItemAdd() need to call KeepAliveID() themselves.
if (g.ActiveId != 0 && g.ActiveIdIsAlive != g.ActiveId && g.ActiveIdPreviousFrame == g.ActiveId)
{
IMGUI_DEBUG_LOG_ACTIVEID("NewFrame(): ClearActiveID() because it isn't marked alive anymore!\n");
IMGUI_DEBUG_LOG_ACTIVEID("NewFrame(): ClearActiveID() 0x%08X because it isn't marked alive anymore!\n", g.ActiveId);
ClearActiveID();
}
@@ -5537,6 +5578,8 @@ void ImGui::NewFrame()
g.ActiveIdIsJustActivated = false;
if (g.TempInputId != 0 && g.ActiveId != g.TempInputId)
g.TempInputId = 0;
if (g.InputTextReactivateId != 0 && g.InputTextReactivateId != g.DeactivatedItemData.ID)
g.InputTextReactivateId = 0;
if (g.ActiveId == 0)
{
g.ActiveIdUsingNavDirMask = 0x00;
@@ -5619,7 +5662,8 @@ void ImGui::NewFrame()
// Mark all windows as not visible and compact unused memory.
IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size);
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
const bool gc_all = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f);
const float memory_compact_start_time = gc_all ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
for (ImGuiWindow* window : g.Windows)
{
window->WasActive = window->Active;
@@ -5629,7 +5673,7 @@ void ImGui::NewFrame()
window->BeginCount = 0;
// Garbage collect transient buffers of recently unused windows
if (!window->WasActive && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
if ((!window->WasActive || gc_all) && !window->MemoryCompacted && window->LastTimeActive < memory_compact_start_time)
GcCompactTransientWindowBuffers(window);
}
@@ -5851,7 +5895,7 @@ static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32
ImDrawList* draw_list = window->RootWindow->DrawList;
if (draw_list->CmdBuffer.Size == 0)
draw_list->AddDrawCmd();
draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect.Max + ImVec2(1, 1), false); // FIXME: Need to stricty ensure ImDrawCmd are not merged (ElemCount==6 checks below will verify that)
draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect.Max + ImVec2(1, 1), false); // FIXME: Need to strictly ensure ImDrawCmd are not merged (ElemCount==6 checks below will verify that)
draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col);
ImDrawCmd cmd = draw_list->CmdBuffer.back();
IM_ASSERT(cmd.ElemCount == 6);
@@ -5947,10 +5991,14 @@ void ImGui::EndFrame()
}
g.WantTextInputNextFrame = ime_data->WantTextInput ? 1 : 0;
// Hide implicit/fallback "Debug" window if it hasn't been used
// Hide and unfocus implicit/fallback "Debug" window if it hasn't been used
g.WithinFrameScopeWithImplicitWindow = false;
if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed)
if (g.CurrentWindow && g.CurrentWindow->IsFallbackWindow && g.CurrentWindow->WriteAccessed == false)
{
g.CurrentWindow->Active = false;
if (g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow)
FocusWindow(NULL);
}
End();
// Update navigation: Ctrl+Tab, wrap-around requests
@@ -6037,7 +6085,7 @@ void ImGui::Render()
for (ImGuiViewportP* viewport : g.Viewports)
{
InitViewportDrawData(viewport);
if (viewport->BgFgDrawLists[0] != NULL)
if (viewport->BgFgDrawLists[0] != NULL && viewport->BgFgDrawListsLastTimeActive[0] == (float)g.Time)
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetBackgroundDrawList(viewport));
}
@@ -6069,7 +6117,7 @@ void ImGui::Render()
FlattenDrawDataIntoSingleLayer(&viewport->DrawDataBuilder);
// Add foreground ImDrawList (for each active viewport)
if (viewport->BgFgDrawLists[1] != NULL)
if (viewport->BgFgDrawLists[1] != NULL && viewport->BgFgDrawListsLastTimeActive[1] == (float)g.Time)
AddDrawListToDrawDataEx(&viewport->DrawDataP, viewport->DrawDataBuilder.Layers[0], GetForegroundDrawList(viewport));
// We call _PopUnusedDrawCmd() last thing, as RenderDimmedBackgrounds() rely on a valid command being there (especially in docking branch).
@@ -10029,11 +10077,12 @@ static void UpdateAliasKey(ImGuiKey key, bool v, float analog_value)
// [Internal] Do not use directly
static ImGuiKeyChord GetMergedModsFromKeys()
{
// Bypass IsKeyDown() for the unlikely case where user used a ImGuiInputFlags_LockXXXX on those.
ImGuiKeyChord mods = 0;
if (ImGui::IsKeyDown(ImGuiMod_Ctrl)) { mods |= ImGuiMod_Ctrl; }
if (ImGui::IsKeyDown(ImGuiMod_Shift)) { mods |= ImGuiMod_Shift; }
if (ImGui::IsKeyDown(ImGuiMod_Alt)) { mods |= ImGuiMod_Alt; }
if (ImGui::IsKeyDown(ImGuiMod_Super)) { mods |= ImGuiMod_Super; }
if (ImGui::GetKeyData(ImGuiMod_Ctrl)->Down) { mods |= ImGuiMod_Ctrl; }
if (ImGui::GetKeyData(ImGuiMod_Shift)->Down) { mods |= ImGuiMod_Shift; }
if (ImGui::GetKeyData(ImGuiMod_Alt)->Down) { mods |= ImGuiMod_Alt; }
if (ImGui::GetKeyData(ImGuiMod_Super)->Down) { mods |= ImGuiMod_Super; }
return mods;
}
@@ -11059,6 +11108,8 @@ bool ImGui::ErrorLog(const char* msg)
return g.IO.ConfigErrorRecoveryEnableAssert;
}
// Display an error tooltip when same ID as HoveredId was submitted multiple times.
// See code in ItemHoverable() for an explanation of why we associate this error to HoveredId + code drawing of rectangles over individual items instances.
void ImGui::ErrorCheckEndFrameFinalizeErrorTooltip()
{
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
@@ -12242,15 +12293,15 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
// - Each popups may contain child windows, which is why we compare ->RootWindow!
// Window -> Popup1 -> Popup1_Child -> Popup2 -> Popup2_Child
// We step through every popup from bottom to top to validate their position relative to reference window.
bool ref_window_is_descendent_of_popup = false;
bool ref_window_is_descendant_of_popup = false;
for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++)
if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window)
if (IsWindowWithinBeginStackOf(ref_window, popup_window))
{
ref_window_is_descendent_of_popup = true;
ref_window_is_descendant_of_popup = true;
break;
}
if (!ref_window_is_descendent_of_popup)
if (!ref_window_is_descendant_of_popup)
break;
}
}
@@ -12454,17 +12505,40 @@ ImGuiMouseButton ImGui::GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags)
return ImGuiMouseButton_Right; // Default == 1
}
bool ImGui::IsPopupOpenRequestForItem(ImGuiPopupFlags popup_flags, ImGuiID id)
{
ImGuiContext& g = *GImGui;
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
return true;
if (g.NavOpenContextMenuItemId == id && (IsItemFocused() || id == g.CurrentWindow->MoveId))
return true;
return false;
}
bool ImGui::IsPopupOpenRequestForWindow(ImGuiPopupFlags popup_flags)
{
ImGuiContext& g = *GImGui;
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
return true;
if (g.NavOpenContextMenuWindowId && g.CurrentWindow->ID)
if (IsWindowChildOf(g.NavWindow, g.CurrentWindow, false)) // This enable ordering to be used to disambiguate item vs window (#8803)
return true;
return false;
}
// Helper to open a popup if mouse button is released over the item
// - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup()
void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
if (IsPopupOpenRequestForItem(popup_flags, g.LastItemData.ID))
{
ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
OpenPopupEx(id, popup_flags);
}
}
@@ -12491,10 +12565,9 @@ bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flag
ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems)
return false;
ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItem ID. Using LastItem ID as a Popup ID won't conflict!
IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item)
if (IsPopupOpenRequestForItem(popup_flags, g.LastItemData.ID))
OpenPopupEx(id, popup_flags);
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
}
@@ -12506,10 +12579,8 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, ImGuiPopupFlags popup_fl
if (!str_id)
str_id = "window_context";
ImGuiID id = window->GetID(str_id);
ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
OpenPopupEx(id, popup_flags);
if (IsPopupOpenRequestForWindow(popup_flags))
OpenPopupEx(id, popup_flags);
return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
}
@@ -13033,6 +13104,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
window->NavLastIds[nav_layer] = id;
if (g.LastItemData.ID == id)
window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
g.NavIdItemFlags = (g.LastItemData.ID == id) ? g.LastItemData.ItemFlags : ImGuiItemFlags_None;
if (id == g.ActiveIdIsAlive)
g.NavIdIsAlive = true;
@@ -13302,6 +13374,7 @@ static void ImGui::NavProcessItem()
SetNavFocusScope(g.CurrentFocusScopeId); // Will set g.NavFocusScopeId AND store g.NavFocusScopePath
g.NavFocusScopeId = g.CurrentFocusScopeId;
g.NavIdIsAlive = true;
g.NavIdItemFlags = item_flags;
if (g.LastItemData.ItemFlags & ImGuiItemFlags_HasSelectionUserData)
{
IM_ASSERT(g.NextItemData.SelectionUserData != ImGuiSelectionUserData_Invalid);
@@ -13686,6 +13759,7 @@ static void ImGui::NavUpdate()
// Process NavCancel input (to close a popup, get back to parent, clear focus)
NavUpdateCancelRequest();
NavUpdateContextMenuRequest();
// Process manual activation request
g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0;
@@ -13694,21 +13768,25 @@ static void ImGui::NavUpdate()
{
const bool activate_down = (nav_keyboard_active && IsKeyDown(ImGuiKey_Space, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_NoOwner));
const bool activate_pressed = activate_down && ((nav_keyboard_active && IsKeyPressed(ImGuiKey_Space, 0, ImGuiKeyOwner_NoOwner)) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, 0, ImGuiKeyOwner_NoOwner)));
const bool input_down = (nav_keyboard_active && (IsKeyDown(ImGuiKey_Enter, ImGuiKeyOwner_NoOwner) || IsKeyDown(ImGuiKey_KeypadEnter, ImGuiKeyOwner_NoOwner))) || (nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadInput, ImGuiKeyOwner_NoOwner));
const bool input_pressed = input_down && ((nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, 0, ImGuiKeyOwner_NoOwner) || IsKeyPressed(ImGuiKey_KeypadEnter, 0, ImGuiKeyOwner_NoOwner))) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadInput, 0, ImGuiKeyOwner_NoOwner)));
const bool input_pressed_keyboard = nav_keyboard_active && (IsKeyPressed(ImGuiKey_Enter, 0, ImGuiKeyOwner_NoOwner) || IsKeyPressed(ImGuiKey_KeypadEnter, 0, ImGuiKeyOwner_NoOwner));
bool input_pressed_gamepad = false;
if (activate_down && nav_gamepad_active && IsKeyDown(ImGuiKey_NavGamepadActivate, ImGuiKeyOwner_NoOwner) && (g.NavIdItemFlags & ImGuiItemFlags_Inputable)) // requires ImGuiItemFlags_Inputable to avoid retriggering regular buttons.
if (GetKeyData(ImGuiKey_NavGamepadActivate)->DownDurationPrev < NAV_ACTIVATE_INPUT_WITH_GAMEPAD_DELAY && GetKeyData(ImGuiKey_NavGamepadActivate)->DownDuration >= NAV_ACTIVATE_INPUT_WITH_GAMEPAD_DELAY)
input_pressed_gamepad = true;
if (g.ActiveId == 0 && activate_pressed)
{
g.NavActivateId = g.NavId;
g.NavActivateFlags = ImGuiActivateFlags_PreferTweak;
}
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && input_pressed)
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (input_pressed_keyboard || input_pressed_gamepad))
{
g.NavActivateId = g.NavId;
g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
}
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_down || input_down))
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_down || input_pressed_keyboard || input_pressed_gamepad)) // FIXME-NAV: Unsure why input_pressed_xxx (migrated from input_down which was already dubious)
g.NavActivateDownId = g.NavId;
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_pressed || input_pressed))
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_pressed || input_pressed_keyboard || input_pressed_gamepad))
{
g.NavActivatePressedId = g.NavId;
NavHighlightActivated(g.NavId);
@@ -14170,6 +14248,31 @@ static void ImGui::NavUpdateCancelRequest()
}
}
static void ImGui::NavUpdateContextMenuRequest()
{
ImGuiContext& g = *GImGui;
g.NavOpenContextMenuItemId = g.NavOpenContextMenuWindowId = 0;
const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
const bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
if ((!nav_keyboard_active && !nav_gamepad_active) || g.NavWindow == NULL)
return;
bool request = false;
request |= nav_keyboard_active && (IsKeyReleased(ImGuiKey_Menu, ImGuiKeyOwner_NoOwner) || (IsKeyPressed(ImGuiKey_F10, ImGuiInputFlags_None, ImGuiKeyOwner_NoOwner) && g.IO.KeyMods == ImGuiMod_Shift));
request |= nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadContextMenu, ImGuiInputFlags_None, ImGuiKeyOwner_NoOwner);
if (!request)
return;
g.NavOpenContextMenuItemId = g.NavId;
g.NavOpenContextMenuWindowId = g.NavWindow->ID;
// Allow triggering for Begin()..BeginPopupContextItem(). A possible alternative would be to use g.NavLayer == ImGuiNavLayer_Menu.
if (g.NavId == g.NavWindow->GetID("#CLOSE") || g.NavId == g.NavWindow->GetID("#COLLAPSE"))
g.NavOpenContextMenuItemId = g.NavWindow->MoveId;
g.NavInputSource = ImGuiInputSource_Keyboard;
SetNavCursorVisibleAfterMove();
}
// Handle PageUp/PageDown/Home/End keys
// Called from NavUpdateCreateMoveRequest() which will use our output to create a move request
// FIXME-NAV: This doesn't work properly with NavFlattened siblings as we use NavWindow rectangle for reference
@@ -14716,7 +14819,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags)
// Magic fallback to handle items with no assigned ID, e.g. Text(), Image()
// We build a throwaway ID based on current ID stack + relative AABB of items in window.
// THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING/RESIZINGG OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
// THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING/RESIZING OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
// We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
// Rely on keeping other window->LastItemXXX fields intact.
source_id = g.LastItemData.ID = window->GetIDFromRectangle(g.LastItemData.Rect);
@@ -14830,14 +14933,14 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s
// Store in heap
g.DragDropPayloadBufHeap.resize((int)data_size);
payload.Data = g.DragDropPayloadBufHeap.Data;
memcpy(payload.Data, data, data_size);
memcpy(payload.Data, data, (size_t)(int)data_size);
}
else if (data_size > 0)
{
// Store locally
memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal));
payload.Data = g.DragDropPayloadBufLocal;
memcpy(payload.Data, data, data_size);
memcpy(payload.Data, data, (size_t)(int)data_size);
}
else
{
@@ -15717,6 +15820,7 @@ static void ImGui::UpdateViewportsNewFrame()
main_viewport->FramebufferScale = g.IO.DisplayFramebufferScale;
IM_ASSERT(main_viewport->FramebufferScale.x > 0.0f && main_viewport->FramebufferScale.y > 0.0f);
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer;
for (ImGuiViewportP* viewport : g.Viewports)
{
// Lock down space taken by menu bars and status bars
@@ -15725,6 +15829,14 @@ static void ImGui::UpdateViewportsNewFrame()
viewport->WorkInsetMax = viewport->BuildWorkInsetMax;
viewport->BuildWorkInsetMin = viewport->BuildWorkInsetMax = ImVec2(0.0f, 0.0f);
viewport->UpdateWorkRect();
// Garbage collect transient buffers of recently BG/FG drawlists
for (int n = 0; n < IM_COUNTOF(viewport->BgFgDrawLists); n++)
if (viewport->BgFgDrawListsLastTimeActive[n] < memory_compact_start_time && viewport->BgFgDrawLists[n] != NULL)
{
IM_DELETE(viewport->BgFgDrawLists[n]);
viewport->BgFgDrawLists[n] = NULL;
}
}
}
@@ -16763,6 +16875,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
{
ImGuiDebugAllocInfo* info = &g.DebugAllocInfo;
Text("%d current allocations", info->TotalAllocCount - info->TotalFreeCount);
Text("Releasing selected unused buffers after: %.2f secs", g.IO.ConfigMemoryCompactTimer);
if (SmallButton("GC now")) { g.GcCompactAll = true; }
Text("Recent frames with allocations:");
int buf_size = IM_COUNTOF(info->LastEntriesBuf);
@@ -17332,7 +17445,7 @@ void ImGui::DebugNodeFont(ImFont* font)
src_n, src->Name, src->OversampleH, oversample_h, src->OversampleV, oversample_v, src->PixelSnapH, src->GlyphOffset.x, src->GlyphOffset.y);
}
DebugNodeFontGlyphesForSrcMask(font, baked, ~0);
DebugNodeFontGlyphsForSrcMask(font, baked, ~0);
TreePop();
}
PopID();
@@ -17341,7 +17454,7 @@ void ImGui::DebugNodeFont(ImFont* font)
Unindent();
}
void ImGui::DebugNodeFontGlyphesForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask)
void ImGui::DebugNodeFontGlyphsForSrcMask(ImFont* font, ImFontBaked* baked, int src_mask)
{
ImDrawList* draw_list = GetWindowDrawList();
const ImU32 glyph_col = GetColorU32(ImGuiCol_Text);
@@ -18112,7 +18225,7 @@ void ImGui::DebugNodeColumns(ImGuiOldColumns*) {}
void ImGui::DebugNodeDrawList(ImGuiWindow*, ImGuiViewportP*, const ImDrawList*, const char*) {}
void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList*, const ImDrawList*, const ImDrawCmd*, bool, bool) {}
void ImGui::DebugNodeFont(ImFont*) {}
void ImGui::DebugNodeFontGlyphesForSrcMask(ImFont*, ImFontBaked*, int) {}
void ImGui::DebugNodeFontGlyphsForSrcMask(ImFont*, ImFontBaked*, int) {}
void ImGui::DebugNodeStorage(ImGuiStorage*, const char*) {}
void ImGui::DebugNodeTabBar(ImGuiTabBar*, const char*) {}
void ImGui::DebugNodeWindow(ImGuiWindow*, const char*) {}
+369 -228
View File
File diff suppressed because it is too large Load Diff
+7 -5
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.6
// dear imgui, v1.92.7
// (drawing and font code)
/*
@@ -1312,7 +1312,7 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa
{
const float arc_length = ImAbs(a_max - a_min);
const int circle_segment_count = _CalcCircleAutoSegmentCount(radius);
const int arc_segment_count = ImMax((int)ImCeil(circle_segment_count * arc_length / (IM_PI * 2.0f)), (int)(2.0f * IM_PI / arc_length));
const int arc_segment_count = ImMax((int)ImCeil(circle_segment_count * arc_length / (IM_PI * 2.0f)), 1);
_PathArcToN(center, radius, a_min, a_max, arc_segment_count);
}
}
@@ -3205,7 +3205,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels,
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
if (font_cfg.Name[0] == '\0')
{
// Store a short copy of filename into into the font name for convenience
// Store a short copy of filename into the font name for convenience
const char* p;
for (p = filename + ImStrlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {}
ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "%s", p);
@@ -3213,7 +3213,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels,
return AddFontFromMemoryTTF(data, (int)data_size, size_pixels, &font_cfg, glyph_ranges);
}
// NB: Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build().
// NB: Transfer ownership of 'font_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build().
ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
{
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
@@ -3260,7 +3260,9 @@ void ImFontAtlasBuildNotifySetFont(ImFontAtlas* atlas, ImFont* old_font, ImFont*
shared_data->Font = new_font;
if (ImGuiContext* ctx = shared_data->Context)
{
if (ctx->FrameCount == 0 && old_font == NULL) // While this should work either way, we save ourselves the bother / debugging confusion of running ImGui code so early when it is not needed.
// While this should work either way, we save ourselves the bother / debugging confusion of running ImGui code so early when it is not needed.
// Also fixes erroneously rewriting style.FontSizeBase during init if adding default fonts.
if (old_font == NULL && ctx->Font == NULL && ctx->FontSizeBase == 0.0f)
continue;
if (ctx->IO.FontDefault == old_font)
+133 -64
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.6
// dear imgui, v1.92.7
// (tables and columns code)
/*
@@ -585,7 +585,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->IsSettingsDirty = true; // Records itself into .ini file even when in default state (#7934)
table->InstanceInteracted = -1;
table->ContextPopupColumn = -1;
table->ReorderColumn = table->ResizedColumn = table->LastResizedColumn = -1;
table->ReorderColumn = table->ReorderColumnDstOrder = table->ResizedColumn = table->LastResizedColumn = -1;
table->AutoFitSingleColumn = -1;
table->HoveredColumnBody = table->HoveredColumnBorder = -1;
for (int n = 0; n < columns_count; n++)
@@ -699,25 +699,23 @@ void ImGui::TableBeginApplyRequests(ImGuiTable* table)
}
// Handle reordering request
// Note: we don't clear ReorderColumn after handling the request (FIXME: clarify why or add a test).
//// Note: we don't clear ReorderColumn after handling the request (FIXME: clarify why or add a test).
if (table->InstanceCurrent == 0)
{
if (table->HeldHeaderColumn == -1 && table->ReorderColumn != -1)
table->ReorderColumn = -1;
table->LastHeldHeaderColumn = table->HeldHeaderColumn;
table->HeldHeaderColumn = -1;
if (table->ReorderColumn != -1 && table->ReorderColumnDir != 0)
if (table->ReorderColumn != -1 && table->ReorderColumnDstOrder != -1)
{
// We need to handle reordering across hidden columns.
// In the configuration below, moving C to the right of E will lead to:
// ... C [D] E ---> ... [D] E C (Column name/index)
// ... 2 3 4 ... 2 3 4 (Display order)
IM_ASSERT(table->ReorderColumnDir == -1 || table->ReorderColumnDir == +1);
IM_ASSERT(table->Flags & ImGuiTableFlags_Reorderable);
ImGuiTableColumn* src_column = &table->Columns[table->ReorderColumn];
ImGuiTableColumn* dst_column = &table->Columns[(table->ReorderColumnDir < 0) ? src_column->PrevEnabledColumn : src_column->NextEnabledColumn];
TableSetColumnDisplayOrder(table, table->ReorderColumn, dst_column->DisplayOrder);
table->ReorderColumnDir = 0;
TableSetColumnDisplayOrder(table, table->ReorderColumn, table->ReorderColumnDstOrder);
table->ReorderColumnDstOrder = -1;
}
// Release
ImGuiContext& g = *GImGui;
if (g.ActiveId == 0) // FIXME: Need to revisit. See 38f5e5a.
table->ReorderColumn = -1;
//if (table->HeldHeaderColumn == -1 && table->ReorderColumn != -1)
// table->ReorderColumn = -1;
}
// Handle display order reset request
@@ -730,8 +728,7 @@ void ImGui::TableBeginApplyRequests(ImGuiTable* table)
}
}
// Note that TableSetupScrollFreeze() enforce a display order range for frozen columns.
// So reordering a column across the frozen column barrier is illegal and will be undone.
// Apply immediately. See TableQueueSetColumnDisplayOrder() for additional checks/constraints.
void ImGui::TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order)
{
IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount);
@@ -755,6 +752,39 @@ void ImGui::TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_
table->IsSettingsDirty = true;
}
static int TableGetMaxDisplayOrderAllowed(ImGuiTable* table, int src_order, int dst_order)
{
dst_order = ImClamp(dst_order, 0, table->ColumnsCount - 1);
if (src_order == dst_order)
return dst_order;
// Cannot cross over the frozen column limit when interactively reordering.
// TableSetupScrollFreeze() enforce a display order range for frozen columns. Reordering across the frozen column barrier is illegal and will be undone.
if (table->FreezeColumnsRequest > 0)
dst_order = (src_order < table->FreezeColumnsRequest) ? ImMin(dst_order, (int)table->FreezeColumnsRequest - 1) : ImMax(dst_order, (int)table->FreezeColumnsRequest);
// Cannot cross over a column with the ImGuiTableColumnFlags_NoReorder flag.
int reorder_dir = (src_order < dst_order) ? +1 : -1;
for (int order_n = src_order; (src_order < dst_order && order_n <= dst_order) || (dst_order < src_order && order_n >= dst_order); order_n += reorder_dir)
if (table->Columns[table->DisplayOrderToIndex[order_n]].Flags & ImGuiTableColumnFlags_NoReorder)
{
dst_order = (order_n == src_order) ? src_order : order_n - reorder_dir;
break;
}
return dst_order;
}
// Reorder requested by user interaction.
void ImGui::TableQueueSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order)
{
const int src_order = table->Columns[column_n].DisplayOrder;
table->ReorderColumn = (ImGuiTableColumnIdx)column_n;
table->ReorderColumnDstOrder = (ImGuiTableColumnIdx)-1;
dst_order = TableGetMaxDisplayOrderAllowed(table, src_order, dst_order);
if (dst_order != src_order)
table->ReorderColumnDstOrder = (ImGuiTableColumnIdx)dst_order;
}
// Adjust flags: default width mode + stretch columns are not allowed when auto extending
static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags flags_in)
{
@@ -1062,7 +1092,6 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column
// Process columns in their visible orders as we are comparing the visible order and adjusting host_clip_rect while looping.
int visible_n = 0;
bool has_at_least_one_column_requesting_output = false;
bool offset_x_frozen = (table->FreezeColumnsCount > 0);
float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1;
@@ -1077,7 +1106,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Initial nav layer: using FreezeRowsCount, NOT FreezeRowsRequest, so Header line changes layer when frozen
column->NavLayerCurrent = (ImS8)(table->FreezeRowsCount > 0 ? ImGuiNavLayer_Menu : (ImGuiNavLayer)table->NavLayer);
if (offset_x_frozen && table->FreezeColumnsCount == visible_n)
if (offset_x_frozen && table->FreezeColumnsCount == order_n)
{
offset_x += work_rect.Min.x - table->OuterRect.Min.x;
offset_x_frozen = false;
@@ -1197,11 +1226,10 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
column->CannotSkipItemsQueue >>= 1;
}
if (visible_n < table->FreezeColumnsCount)
if (order_n < table->FreezeColumnsCount)
host_clip_rect.Min.x = ImClamp(column->MaxX + TABLE_BORDER_SIZE, host_clip_rect.Min.x, host_clip_rect.Max.x);
offset_x += column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
visible_n++;
}
// In case the table is visible (e.g. decorations) but all columns clipped, we keep a column visible.
@@ -1282,7 +1310,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// [Part 13] Setup inner window decoration size (for scrolling / nav tracking to properly take account of frozen rows/columns)
if (table->FreezeColumnsRequest > 0)
table->InnerWindow->DecoInnerSizeX1 = table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsRequest - 1]].MaxX - table->OuterRect.Min.x;
table->InnerWindow->DecoInnerSizeX1 = table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsRequest - 1]].MaxX - table->OuterRect.Min.x; // FIXME-FROZEN
if (table->FreezeRowsRequest > 0)
table->InnerWindow->DecoInnerSizeY1 = table_instance->LastFrozenHeight;
table_instance->LastFrozenHeight = 0.0f;
@@ -1674,18 +1702,6 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows)
table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0;
table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0;
table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b
// Ensure frozen columns are ordered in their section. We still allow multiple frozen columns to be reordered.
// FIXME-TABLE: This work for preserving 2143 into 21|43. How about 4321 turning into 21|43? (preserve relative order in each section)
for (int column_n = 0; column_n < table->FreezeColumnsRequest; column_n++)
{
int order_n = table->DisplayOrderToIndex[column_n];
if (order_n != column_n && order_n >= table->FreezeColumnsRequest)
{
ImSwap(table->Columns[table->DisplayOrderToIndex[order_n]].DisplayOrder, table->Columns[table->DisplayOrderToIndex[column_n]].DisplayOrder);
ImSwap(table->DisplayOrderToIndex[order_n], table->DisplayOrderToIndex[column_n]);
}
}
}
//-----------------------------------------------------------------------------
@@ -3121,7 +3137,7 @@ void ImGui::TableHeadersRow()
const int columns_count = TableGetColumnCount();
for (int column_n = 0; column_n < columns_count; column_n++)
{
if (!TableSetColumnIndex(column_n))
if (!TableSetColumnIndex(column_n) && table->LastHeldHeaderColumn != column_n)
continue;
// Push an id to allow empty/unnamed headers. This is also idiomatic as it ensure there is a consistent ID path to access columns (for e.g. automation)
@@ -3224,21 +3240,19 @@ void ImGui::TableHeader(const char* label)
// FIXME-TABLE: Scroll request while reordering a column and it lands out of the scrolling zone.
if (held && (table->Flags & ImGuiTableFlags_Reorderable) && IsMouseDragging(0) && !g.DragDropActive)
{
// While moving a column it will jump on the other side of the mouse, so we also test for MouseDelta.x
table->ReorderColumn = (ImGuiTableColumnIdx)column_n;
// - While moving a column it will jump on the other side of the mouse, so we also test for MouseDelta.x
// - We need to handle reordering across hidden columns.
// In the configuration below, moving C to the right of E will lead to:
// ... C [D] E ---> ... [D] E C (Column name/index)
// ... 2 3 4 ... 2 3 4 (Display order)
// - The other constraints are enforced by TableQueueSetColumnDisplayOrder() which might early out.
table->InstanceInteracted = table->InstanceCurrent;
// We don't reorder: through the frozen<>unfrozen line, or through a column that is marked with ImGuiTableColumnFlags_NoReorder.
if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < cell_r.Min.x)
if (ImGuiTableColumn* prev_column = (column->PrevEnabledColumn != -1) ? &table->Columns[column->PrevEnabledColumn] : NULL)
if (!((column->Flags | prev_column->Flags) & ImGuiTableColumnFlags_NoReorder))
if ((column->IndexWithinEnabledSet < table->FreezeColumnsRequest) == (prev_column->IndexWithinEnabledSet < table->FreezeColumnsRequest))
table->ReorderColumnDir = -1;
TableQueueSetColumnDisplayOrder(table, column_n, prev_column->DisplayOrder);
if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > cell_r.Max.x)
if (ImGuiTableColumn* next_column = (column->NextEnabledColumn != -1) ? &table->Columns[column->NextEnabledColumn] : NULL)
if (!((column->Flags | next_column->Flags) & ImGuiTableColumnFlags_NoReorder))
if ((column->IndexWithinEnabledSet < table->FreezeColumnsRequest) == (next_column->IndexWithinEnabledSet < table->FreezeColumnsRequest))
table->ReorderColumnDir = +1;
TableQueueSetColumnDisplayOrder(table, column_n, next_column->DisplayOrder);
}
// Sort order arrow
@@ -3277,7 +3291,7 @@ void ImGui::TableHeader(const char* label)
SetItemTooltip("%.*s", (int)(label_end - label), label);
// We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
if (IsMouseReleased(1) && IsItemHovered())
if (IsPopupOpenRequestForItem(ImGuiPopupFlags_None, id))
TableOpenContextMenu(column_n);
}
@@ -3294,7 +3308,7 @@ void ImGui::TableAngledHeadersRow()
// Which column needs highlight?
const ImGuiID row_id = GetID("##AngledHeaders");
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
int highlight_column_n = table->HighlightColumnHeader;
int highlight_column_n = (table->LastHeldHeaderColumn != -1) ? table->LastHeldHeaderColumn : table->HighlightColumnHeader;
if (highlight_column_n == -1 && table->HoveredColumnBody != -1)
if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive)))
highlight_column_n = table->HoveredColumnBody;
@@ -3348,13 +3362,14 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); // vector from bottom-left to top-left, and from bottom-right to top-right
// Declare row, override and draw our own background
// FIXME-TABLE: Generally broken when overlapping frozen columns limit.
TableNextRow(ImGuiTableRowFlags_Headers, row_height);
TableNextColumn();
const ImRect row_r(table->WorkRect.Min.x, table->BgClipRect.Min.y, table->WorkRect.Max.x, table->RowPosY2);
table->DrawSplitter->SetCurrentChannel(draw_list, TABLE_DRAW_CHANNEL_BG0);
float clip_rect_min_x = table->BgClipRect.Min.x;
if (table->FreezeColumnsCount > 0)
clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->FreezeColumnsCount - 1].MaxX);
clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsCount - 1]].MaxX);
TableSetBgColor(ImGuiTableBgTarget_RowBg0, 0); // Cancel
PushClipRect(table->BgClipRect.Min, table->BgClipRect.Max, false); // Span all columns
draw_list->AddRectFilled(ImVec2(table->BgClipRect.Min.x, row_r.Min.y), ImVec2(table->BgClipRect.Max.x, row_r.Max.y), GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color.
@@ -3490,6 +3505,36 @@ bool ImGui::TableBeginContextMenuPopup(ImGuiTable* table)
return false;
}
// FIXME: Copied from MenuItem() for the purpose of being able to pass _SelectOnRelease (#9312)
static bool MenuItemForColumnReorder(const char* label, bool selected, bool enabled)
{
using namespace ImGui;
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
ImVec2 label_size = CalcTextSize(label, NULL, true);
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f);
float min_w = offsets->DeclColumns(0.0f, label_size.x, 0.0f, checkmark_w); // Feedback for next frame
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
ImGuiID id = GetID(label);
ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SpanAvailWidth;
if (g.ActiveId == id)
selectable_flags |= ImGuiSelectableFlags_Highlight; // Stays highlighted while dragging.
const bool has_been_moved = (g.ActiveId == id) && g.ActiveIdHasBeenEditedBefore; // But disable toggling once moved.
BeginDisabled(!enabled); // Don't use ImGuiSelectableFlags_Disabled so that Check mark is also affected.
bool ret = Selectable(label, false, selectable_flags, ImVec2(min_w, label_size.y)) && !has_been_moved; // Can't use IsMouseDragging(0) as button is released already.
if ((g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) && selected)
RenderCheckMark(window->DrawList, text_pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
EndDisabled();
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
return ret;
}
// Output context menu into current window (generally a popup)
// FIXME-TABLE: Ideally this should be writable by the user. Full programmatic access to that data?
// Sections to display are pulled from 'flags_for_section_to_display', which is typically == table->Flags.
@@ -3506,17 +3551,17 @@ void ImGui::TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags
return;
bool want_separator = false;
const int column_n = (table->ContextPopupColumn >= 0 && table->ContextPopupColumn < table->ColumnsCount) ? table->ContextPopupColumn : -1;
ImGuiTableColumn* column = (column_n != -1) ? &table->Columns[column_n] : NULL;
const int context_column_n = (table->ContextPopupColumn >= 0 && table->ContextPopupColumn < table->ColumnsCount) ? table->ContextPopupColumn : -1;
ImGuiTableColumn* context_column = (context_column_n != -1) ? &table->Columns[context_column_n] : NULL;
// Sizing
if (flags_for_section_to_display & ImGuiTableFlags_Resizable)
{
if (column != NULL)
if (context_column != NULL)
{
const bool can_resize = !(column->Flags & ImGuiTableColumnFlags_NoResize) && column->IsEnabled;
const bool can_resize = !(context_column->Flags & ImGuiTableColumnFlags_NoResize) && context_column->IsEnabled;
if (MenuItem(LocalizeGetMsg(ImGuiLocKey_TableSizeOne), NULL, false, can_resize)) // "###SizeOne"
TableSetColumnWidthAutoSingle(table, column_n);
TableSetColumnWidthAutoSingle(table, context_column_n);
}
const char* size_all_desc;
@@ -3565,23 +3610,47 @@ void ImGui::TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags
Separator();
want_separator = true;
// While reordering: we calculate min/max allowed range once here so we can avoid a O(N log N) in the loop (because the query itself does a sweep scan).
// This assume that reordering constraints output a single range, otherwise would need to either call TableGetMaxDisplayOrderAllowed() for each item below, or cache this once per frame into columns.
const bool is_reordering = (g.ActiveId != 0 && g.ActiveIdWindow == g.CurrentWindow && table->ReorderColumn != -1 && g.ActiveIdHasBeenEditedBefore); // FIXME: This is a bit of a hack.
const int reorder_src_order = is_reordering ? table->Columns[table->ReorderColumn].DisplayOrder : -1;
const int reorder_min_order = is_reordering ? TableGetMaxDisplayOrderAllowed(table, reorder_src_order, 0) : 0;
const int reorder_max_order = is_reordering ? TableGetMaxDisplayOrderAllowed(table, reorder_src_order, table->ColumnsCount - 1) : table->ColumnsCount - 1;
PushItemFlag(ImGuiItemFlags_AutoClosePopups, false);
for (int other_column_n = 0; other_column_n < table->ColumnsCount; other_column_n++)
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{
ImGuiTableColumn* other_column = &table->Columns[other_column_n];
if (other_column->Flags & ImGuiTableColumnFlags_Disabled)
const int column_n = table->DisplayOrderToIndex[order_n];
ImGuiTableColumn* column = &table->Columns[column_n];
if (column->Flags & ImGuiTableColumnFlags_Disabled)
continue;
const char* name = TableGetColumnName(table, other_column_n);
const char* name = TableGetColumnName(table, column_n);
if (name == NULL || name[0] == 0)
name = "<Unknown>";
// Make sure we can't hide the last active column
bool menu_item_active = (other_column->Flags & ImGuiTableColumnFlags_NoHide) ? false : true;
if (other_column->IsUserEnabled && table->ColumnsEnabledCount <= 1)
menu_item_active = false;
if (MenuItem(name, NULL, other_column->IsUserEnabled, menu_item_active))
other_column->IsUserEnabledNextFrame = !other_column->IsUserEnabled;
bool menu_item_enabled = (column->Flags & ImGuiTableColumnFlags_NoHide) ? false : true;
if (column->IsUserEnabled && table->ColumnsEnabledCount <= 1)
menu_item_enabled = false;
if (is_reordering && (column->DisplayOrder < reorder_min_order || column->DisplayOrder > reorder_max_order))
menu_item_enabled = false;
if (MenuItemForColumnReorder(name, column->IsUserEnabled, menu_item_enabled))
column->IsUserEnabledNextFrame = !column->IsUserEnabled;
// Drag to reorder
// FIXME: It is currently not possible to reorder columns marked with ImGuiTableColumnFlags_NoHide.
if (IsItemActive() && IsMouseDragging(0) && g.ActiveIdSource == ImGuiInputSource_Mouse && (table->Flags & ImGuiTableFlags_Reorderable))
{
g.ActiveIdHasBeenEditedBefore = true; // Disable toggle in MenuItemForColumnReorder() + start dimming to display allowed reorder targets.
table->ReorderColumn = (ImGuiTableColumnIdx)column_n;
if (!IsItemHovered())
{
int reorder_dir = (g.IO.MousePos.y < (g.LastItemData.Rect.Min.y + g.LastItemData.Rect.Max.y) * 0.5f) ? -1 : +1;
float reorder_amount = (reorder_dir < 0 ? g.LastItemData.Rect.Min.y - g.IO.MousePos.y : g.IO.MousePos.y - g.LastItemData.Rect.Max.y) / g.LastItemData.Rect.GetHeight();
int dst_order = column->DisplayOrder + (int)ImCeil(reorder_amount) * reorder_dir; // Estimated target order, will be validated and clamped.
TableQueueSetColumnDisplayOrder(table, column_n, dst_order);
}
}
}
PopItemFlag();
}
@@ -4051,7 +4120,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
BulletText("CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f", table->CellPaddingX, table->CellSpacingX1, table->CellSpacingX2, table->OuterPaddingX);
BulletText("HoveredColumnBody: %d, HoveredColumnBorder: %d", table->HoveredColumnBody, table->HoveredColumnBorder);
BulletText("ResizedColumn: %d, ReorderColumn: %d, HeldHeaderColumn: %d", table->ResizedColumn, table->ReorderColumn, table->HeldHeaderColumn);
BulletText("ResizedColumn: %d, HeldHeaderColumn: %d, ReorderColumn: %d", table->LastResizedColumn, table->LastHeldHeaderColumn, table->ReorderColumn);
for (int n = 0; n < table->InstanceCurrent + 1; n++)
{
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, n);
+268 -240
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.6
// dear imgui, v1.92.7
// (widgets code)
/*
@@ -653,6 +653,14 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
FocusWindow(window, ImGuiFocusRequestFlags_RestoreFocusedChild); // Still need to focus and bring to front, but try to avoid losing NavId when navigating a child
}
}
if (flags & ImGuiButtonFlags_PressedOnRelease)
{
// FIXME: Traditionally ImGuiButtonFlags_PressedOnRelease never took ActiveId. Adding it in 2026-03-20 since ImGuiButtonFlags_NoHoldingActiveId can always be added.
// We don't yet perform an explicit ClearActiveID() to reduce scope of change, but this possibility could be investigated.
if (!(flags & ImGuiButtonFlags_NoHoldingActiveId))
SetActiveID(id, window); // Hold on ID
g.ActiveIdMouseButton = (ImS8)mouse_button_clicked;
}
}
if (flags & ImGuiButtonFlags_PressedOnRelease)
{
@@ -919,7 +927,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)
const ImU32 cross_col = GetColorU32(ImGuiCol_Text);
const ImVec2 cross_center = bb.GetCenter() - ImVec2(0.5f, 0.5f);
const float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
const float cross_thickness = 1.0f; // FIXME-DPI
const float cross_thickness = 1.0f * (float)(int)g.Style._MainScale; // FIXME-DPI
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, +cross_extent), cross_center + ImVec2(-cross_extent, -cross_extent), cross_col, cross_thickness);
window->DrawList->AddLine(cross_center + ImVec2(+cross_extent, -cross_extent), cross_center + ImVec2(-cross_extent, +cross_extent), cross_col, cross_thickness);
@@ -974,6 +982,16 @@ ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis)
return ImRect(ImMax(outer_rect.Min.x, outer_rect.Max.x - border_size - scrollbar_size), inner_rect.Min.y + border_top, outer_rect.Max.x - border_size, inner_rect.Max.y - border_size);
}
void ImGui::ExtendHitBoxWhenNearViewportEdge(ImGuiWindow* window, ImRect* bb, float threshold, ImGuiAxis axis)
{
ImRect window_rect = window->RootWindow->Rect();
ImRect viewport_rect = window->Viewport->GetMainRect();
if (window_rect.Min[axis] == viewport_rect.Min[axis] && bb->Min[axis] > window_rect.Min[axis] && bb->Min[axis] - threshold <= window_rect.Min[axis])
bb->Min[axis] = window_rect.Min[axis];
if (window_rect.Max[axis] == viewport_rect.Max[axis] && bb->Max[axis] < window_rect.Max[axis] && bb->Max[axis] + threshold >= window_rect.Max[axis])
bb->Max[axis] = window_rect.Max[axis];
}
void ImGui::Scrollbar(ImGuiAxis axis)
{
ImGuiContext& g = *GImGui;
@@ -1032,14 +1050,18 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS6
IM_ASSERT(ImMax(size_contents_v, size_visible_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.
const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_visible_v), (ImS64)1);
const float grab_h_minsize = ImMin(bb.GetSize()[axis], style.GrabMinSize);
const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_visible_v / (float)win_size_v), grab_h_minsize, scrollbar_size_v);
const float grab_h_pixels = (float)(int)ImClamp(scrollbar_size_v * ((float)size_visible_v / (float)win_size_v), grab_h_minsize, scrollbar_size_v);
const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
// As a special thing, we allow scrollbar near the edge of a screen/viewport to be reachable with mouse at the extreme edge (#9276)
ImRect bb_hit = bb_frame;
ExtendHitBoxWhenNearViewportEdge(window, &bb_hit, g.Style.WindowBorderSize, (ImGuiAxis)(axis ^ 1));
// Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
bool held = false;
bool hovered = false;
ItemAdd(bb_frame, id, NULL, ImGuiItemFlags_NoNav);
ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
ButtonBehavior(bb_hit, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_visible_v);
float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);
@@ -1529,7 +1551,7 @@ bool ImGui::TextLink(const char* label)
}
float line_y = bb.Max.y + ImFloor(g.FontBaked->Descent * g.FontBakedScale * 0.20f);
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf)); // FIXME-TEXT: Underline mode // FIXME-DPI
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf), 1.0f * (float)(int)g.Style._MainScale); // FIXME-TEXT: Underline mode // FIXME-DPI
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
RenderText(bb.Min, label, label_end);
@@ -1664,9 +1686,13 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags, float thickness)
// We don't provide our width to the layout so that it doesn't get feed back into AutoFit
// FIXME: This prevents ->CursorMaxPos based bounding box evaluation from working (e.g. TableEndCell)
const float thickness_for_layout = (thickness == 1.0f) ? 0.0f : thickness; // FIXME: See 1.70/1.71 Separator() change: makes legacy 1-px separator not affect layout yet. Should change.
// Between 1.71 and 1.92.7, we maintained a hack where a 1.0f thin Separator() would not impact layout.
// This was mostly chosen to allow backward compatibility with user's code assuming zero-height when calculating height for layout (e.g. bottom alignment of a status bar).
// In order to handle scaling we need to scale separator thickness and it would not makes sense to have a disparity depending on height.
////float thickness_for_layout = (thickness == 1.0f) ? 0.0f : thickness; // FIXME: See 1.70/1.71 Separator() change: makes legacy 1-px separator not affect layout yet. Should change.
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness));
ItemSize(ImVec2(0.0f, thickness_for_layout));
ItemSize(ImVec2(0.0f, thickness));
if (ItemAdd(bb, 0))
{
@@ -1692,14 +1718,13 @@ void ImGui::Separator()
return;
// Those flags should eventually be configurable by the user
// FIXME: We cannot g.Style.SeparatorTextBorderSize for thickness as it relates to SeparatorText() which is a decorated separator, not defaulting to 1.0f.
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
// Only applies to legacy Columns() api as they relied on Separator() a lot.
if (window->DC.CurrentColumns)
flags |= ImGuiSeparatorFlags_SpanAllColumns;
SeparatorEx(flags, 1.0f);
SeparatorEx(flags, g.Style.SeparatorSize);
}
void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w)
@@ -2202,30 +2227,6 @@ bool ImGui::Combo(const char* label, int* current_item, const char* items_separa
return value_changed;
}
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
struct ImGuiGetNameFromIndexOldToNewCallbackData { void* UserData; bool (*OldCallback)(void*, int, const char**); };
static const char* ImGuiGetNameFromIndexOldToNewCallback(void* user_data, int idx)
{
ImGuiGetNameFromIndexOldToNewCallbackData* data = (ImGuiGetNameFromIndexOldToNewCallbackData*)user_data;
const char* s = NULL;
data->OldCallback(data->UserData, idx, &s);
return s;
}
bool ImGui::ListBox(const char* label, int* current_item, bool (*old_getter)(void*, int, const char**), void* user_data, int items_count, int height_in_items)
{
ImGuiGetNameFromIndexOldToNewCallbackData old_to_new_data = { user_data, old_getter };
return ListBox(label, current_item, ImGuiGetNameFromIndexOldToNewCallback, &old_to_new_data, items_count, height_in_items);
}
bool ImGui::Combo(const char* label, int* current_item, bool (*old_getter)(void*, int, const char**), void* user_data, int items_count, int popup_max_height_in_items)
{
ImGuiGetNameFromIndexOldToNewCallbackData old_to_new_data = { user_data, old_getter };
return Combo(label, current_item, ImGuiGetNameFromIndexOldToNewCallback, &old_to_new_data, items_count, popup_max_height_in_items);
}
#endif
//-------------------------------------------------------------------------
// [SECTION] Data Type and Data Formatting Helpers [Internal]
//-------------------------------------------------------------------------
@@ -2585,9 +2586,9 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
// Convert to parametric space, apply delta, convert back
float v_old_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
float v_old_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
float v_new_parametric = v_old_parametric + g.DragCurrentAccum;
v_cur = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new_parametric, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
v_cur = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new_parametric, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
v_old_ref_for_accum_remainder = v_old_parametric;
}
else
@@ -2604,7 +2605,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
if (is_logarithmic)
{
// Convert to parametric space, apply delta, convert back
float v_new_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
float v_new_parametric = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_cur, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
g.DragCurrentAccum -= (float)(v_new_parametric - v_old_ref_for_accum_remainder);
}
else
@@ -2680,6 +2681,20 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v
return false;
}
// Only clamp Ctrl+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
static bool TempInputIsClampEnabled(ImGuiSliderFlags flags, ImGuiDataType data_type, const void* p_min, const void* p_max)
{
if ((flags & ImGuiSliderFlags_ClampOnInput) && (p_min != NULL || p_max != NULL))
{
const int clamp_range_dir = (p_min != NULL && p_max != NULL) ? ImGui::DataTypeCompare(data_type, p_min, p_max) : 0; // -1 when *p_min < *p_max, == 0 when *p_min == *p_max
if (p_min == NULL || p_max == NULL || clamp_range_dir < 0)
return true;
if (clamp_range_dir == 0)
return ImGui::DataTypeIsZero(data_type, p_min) ? ((flags & ImGuiSliderFlags_ClampZeroRange) != 0) : true;
}
return false;
}
// Note: p_data, p_min and p_max are _pointers_ to a memory address holding the data. For a Drag widget, p_min and p_max are optional.
// Read code of e.g. DragFloat(), DragInt() etc. or examples in 'Demo->Widgets->Data Types' to understand how to use this function directly.
bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, ImGuiSliderFlags flags)
@@ -2745,16 +2760,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
if (temp_input_is_active)
{
// Only clamp Ctrl+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
bool clamp_enabled = false;
if ((flags & ImGuiSliderFlags_ClampOnInput) && (p_min != NULL || p_max != NULL))
{
const int clamp_range_dir = (p_min != NULL && p_max != NULL) ? DataTypeCompare(data_type, p_min, p_max) : 0; // -1 when *p_min < *p_max, == 0 when *p_min == *p_max
if (p_min == NULL || p_max == NULL || clamp_range_dir < 0)
clamp_enabled = true;
else if (clamp_range_dir == 0)
clamp_enabled = DataTypeIsZero(data_type, p_min) ? ((flags & ImGuiSliderFlags_ClampZeroRange) != 0) : true;
}
const bool clamp_enabled = TempInputIsClampEnabled(flags, data_type, p_min, p_max);
return TempInputScalar(frame_bb, id, label, data_type, p_data, format, clamp_enabled ? p_min : NULL, clamp_enabled ? p_max : NULL);
}
@@ -2954,14 +2960,14 @@ bool ImGui::DragIntRange2(const char* label, int* v_current_min, int* v_current_
// Convert a value v in the output space of a slider into a parametric position on the slider itself (the logical opposite of ScaleValueFromRatioT)
template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, TYPE v_max, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
{
if (v_min == v_max)
return 0.0f;
IM_UNUSED(data_type);
const TYPE v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min);
if (is_logarithmic)
if (logarithmic_zero_epsilon > 0.0f) // == is_logarithmic from caller
{
bool flipped = v_max < v_min;
@@ -3011,7 +3017,7 @@ float ImGui::ScaleRatioFromValueT(ImGuiDataType data_type, TYPE v, TYPE v_min, T
// Convert a parametric position on a slider into a value v in the output space (the logical opposite of ScaleRatioFromValueT)
template<typename TYPE, typename SIGNEDTYPE, typename FLOATTYPE>
TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, bool is_logarithmic, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, TYPE v_max, float logarithmic_zero_epsilon, float zero_deadzone_halfsize)
{
// We special-case the extents because otherwise our logarithmic fudging can lead to "mathematically correct"
// but non-intuitive behaviors like a fully-left slider not actually reaching the minimum value. Also generally simpler.
@@ -3021,7 +3027,7 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T
return v_max;
TYPE result = (TYPE)0;
if (is_logarithmic)
if (logarithmic_zero_epsilon > 0.0f) // == is_logarithmic from caller
{
// Fudge min/max to avoid getting silly results close to zero
FLOATTYPE v_min_fudged = (ImAbs((FLOATTYPE)v_min) < logarithmic_zero_epsilon) ? ((v_min < 0.0f) ? -logarithmic_zero_epsilon : logarithmic_zero_epsilon) : (FLOATTYPE)v_min;
@@ -3126,7 +3132,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
const float mouse_abs_pos = g.IO.MousePos[axis];
if (g.ActiveIdIsJustActivated)
{
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
if (axis == ImGuiAxis_Y)
grab_t = 1.0f - grab_t;
const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
@@ -3181,7 +3187,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
}
else if (g.SliderCurrentAccumDirty)
{
clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits
{
@@ -3195,10 +3201,10 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
clicked_t = ImSaturate(clicked_t + delta);
// Calculate what our "new" clicked_t will be, and thus how far we actually moved the slider, and subtract this from the accumulator
TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
if (is_floating_point && !(flags & ImGuiSliderFlags_NoRoundToFormat))
v_new = RoundScalarWithFormatT<TYPE>(format, data_type, v_new);
float new_clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
float new_clicked_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, v_new, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
if (delta > 0)
g.SliderCurrentAccum -= ImMin(new_clicked_t - old_clicked_t, delta);
@@ -3216,7 +3222,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
if (set_new_value)
{
TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
TYPE v_new = ScaleValueFromRatioT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, clicked_t, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
// Round to user desired precision based on format string
if (is_floating_point && !(flags & ImGuiSliderFlags_NoRoundToFormat))
@@ -3238,7 +3244,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
else
{
// Output grab position so it can be displayed by the caller
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, is_logarithmic, logarithmic_zero_epsilon, zero_deadzone_halfsize);
float grab_t = ScaleRatioFromValueT<TYPE, SIGNEDTYPE, FLOATTYPE>(data_type, *v, v_min, v_max, logarithmic_zero_epsilon, zero_deadzone_halfsize);
if (axis == ImGuiAxis_Y)
grab_t = 1.0f - grab_t;
const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
@@ -3346,7 +3352,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
if (temp_input_is_active)
{
// Only clamp Ctrl+Click input when ImGuiSliderFlags_ClampOnInput is set (generally via ImGuiSliderFlags_AlwaysClamp)
const bool clamp_enabled = (flags & ImGuiSliderFlags_ClampOnInput) != 0;
const bool clamp_enabled = (flags & ImGuiSliderFlags_ClampOnInput) != 0; // Don't use TempInputIsClampEnabled()
return TempInputScalar(frame_bb, id, label, data_type, p_data, format, clamp_enabled ? p_min : NULL, clamp_enabled ? p_max : NULL);
}
@@ -3688,27 +3694,33 @@ int ImParseFormatPrecision(const char* fmt, int default_precision)
}
// Create text input in place of another active widget (e.g. used when doing a Ctrl+Click on drag/slider widgets)
// - This must be submitted right after the item it is overlaying.
// FIXME: Facilitate using this in variety of other situations.
// FIXME: Among other things, setting ImGuiItemFlags_AllowDuplicateId in LastItemData is currently correct but
// the expected relationship between TempInputXXX functions and LastItemData is a little fishy.
bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, int buf_size, ImGuiInputTextFlags flags)
bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
{
// On the first frame, g.TempInputTextId == 0, then on subsequent frames it becomes == id.
// We clear ActiveID on the first frame to allow the InputText() taking it back.
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const bool init = (g.TempInputId != id);
if (init)
ClearActiveID();
g.CurrentWindow->DC.CursorPos = bb.Min;
g.LastItemData.ItemFlags |= ImGuiItemFlags_AllowDuplicateId;
bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_MergedItem);
ImVec2 backup_pos = window->DC.CursorPos;
window->DC.CursorPos = bb.Min;
g.LastItemData.ItemFlags |= ImGuiItemFlags_AllowDuplicateId; // Using ImGuiInputTextFlags_MergedItem above will skip ItemAdd() so we poke here.
bool value_changed = InputTextEx(label, NULL, buf, (int)buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_TempInput | ImGuiInputTextFlags_AutoSelectAll, callback, user_data);
KeepAliveID(id); // Not done because of ImGuiInputTextFlags_TempInput
if (init)
{
// First frame we started displaying the InputText widget, we expect it to take the active id.
IM_ASSERT(g.ActiveId == id);
g.TempInputId = g.ActiveId;
}
if (g.ActiveId != id)
g.TempInputId = 0;
window->DC.CursorPos = backup_pos;
return value_changed;
}
@@ -3731,29 +3743,28 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
g.LastItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited; // Because TempInputText() uses ImGuiInputTextFlags_MergedItem it doesn't submit a new item, so we poke LastItemData.
bool value_changed = false;
if (TempInputText(bb, id, label, data_buf, IM_COUNTOF(data_buf), flags))
if (!TempInputText(bb, id, label, data_buf, IM_COUNTOF(data_buf), flags))
return false;
// Backup old value
size_t data_type_size = type_info->Size;
ImGuiDataTypeStorage data_backup;
memcpy(&data_backup, p_data, data_type_size);
// Apply new value (or operations) then clamp
DataTypeApplyFromText(data_buf, data_type, p_data, format, NULL);
if (p_clamp_min || p_clamp_max)
{
// Backup old value
size_t data_type_size = type_info->Size;
ImGuiDataTypeStorage data_backup;
memcpy(&data_backup, p_data, data_type_size);
// Apply new value (or operations) then clamp
DataTypeApplyFromText(data_buf, data_type, p_data, format, NULL);
if (p_clamp_min || p_clamp_max)
{
if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
ImSwap(p_clamp_min, p_clamp_max);
DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max);
}
// Only mark as edited if new value is different
g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
if (value_changed)
MarkItemEdited(id);
if (p_clamp_min && p_clamp_max && DataTypeCompare(data_type, p_clamp_min, p_clamp_max) > 0)
ImSwap(p_clamp_min, p_clamp_max);
DataTypeClamp(data_type, p_data, p_clamp_min, p_clamp_max);
}
// Only mark as edited if new value is different
g.LastItemData.ItemFlags &= ~ImGuiItemFlags_NoMarkEdited;
bool value_changed = memcmp(&data_backup, p_data, data_type_size) != 0;
if (value_changed)
MarkItemEdited(id);
return value_changed;
}
@@ -3792,24 +3803,30 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
g.NextItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited;
flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
bool value_changed = false;
if (p_step == NULL)
const bool has_step_buttons = (p_step != NULL);
const float button_size = has_step_buttons ? GetFrameHeight() : 0.0f;
bool ret;
if (has_step_buttons)
{
if (InputText(label, buf, IM_COUNTOF(buf), flags))
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
}
else
{
const float button_size = GetFrameHeight();
// With Step Buttons
BeginGroup(); // The only purpose of the group here is to allow the caller to query item data e.g. IsItemActive()
PushID(label);
SetNextItemWidth(ImMax(1.0f, CalcItemWidth() - (button_size + style.ItemInnerSpacing.x) * 2));
if (InputText("", buf, IM_COUNTOF(buf), flags)) // PushId(label) + "" gives us the expected ID from outside point of view
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
ret = InputText("", buf, IM_COUNTOF(buf), flags); // PushID(label) + "" gives us the expected ID from outside point of view
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable);
}
else
{
// Without Step Buttons
ret = InputText(label, buf, IM_COUNTOF(buf), flags);
}
// Step buttons
// Apply
bool value_changed = ret ? DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL) : false;
// Step buttons
if (has_step_buttons)
{
const ImVec2 backup_frame_padding = style.FramePadding;
style.FramePadding.x = style.FramePadding.y;
if (flags & ImGuiInputTextFlags_ReadOnly)
@@ -4167,7 +4184,7 @@ static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
char* dst = obj->TextA.Data + pos;
char* src = obj->TextA.Data + pos + n;
memmove(dst, src, obj->TextLen - n - pos + 1);
obj->Edited = true;
obj->EditedBefore = obj->EditedThisFrame = true;
obj->TextLen -= n;
}
@@ -4197,7 +4214,7 @@ static int STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const cha
memmove(text + pos + new_text_len, text + pos, (size_t)(text_len - pos));
memcpy(text + pos, new_text, (size_t)new_text_len);
obj->Edited = true;
obj->EditedBefore = obj->EditedThisFrame = true;
obj->TextLen += new_text_len;
obj->TextA[obj->TextLen] = '\0';
@@ -4399,6 +4416,7 @@ void ImGui::PopPasswordFont()
// Return false to discard a character.
static bool InputTextFilterCharacter(ImGuiContext* ctx, ImGuiInputTextState* state, unsigned int* p_char, ImGuiInputTextCallback callback, void* user_data, bool input_source_is_clipboard)
{
IM_ASSERT(state != NULL);
unsigned int c = *p_char;
ImGuiInputTextFlags flags = state->Flags;
@@ -4584,6 +4602,7 @@ static int InputTextLineIndexBuild(ImGuiInputTextFlags flags, ImGuiTextIndex* li
ImGuiContext& g = *GImGui;
int size = 0;
const char* s;
bool trailing_line_already_counted = false;
if (flags & ImGuiInputTextFlags_WordWrap)
{
for (s = buf; s < buf_end; s = (*s == '\n') ? s + 1 : s)
@@ -4604,6 +4623,7 @@ static int InputTextLineIndexBuild(ImGuiInputTextFlags flags, ImGuiTextIndex* li
}
else
{
// Inactive path: we don't know buf_end ahead of time.
const char* s_eol;
for (s = buf; ; s = s_eol + 1)
{
@@ -4612,6 +4632,7 @@ static int InputTextLineIndexBuild(ImGuiInputTextFlags flags, ImGuiTextIndex* li
if ((s_eol = strchr(s, '\n')) != NULL)
continue;
s += strlen(s);
trailing_line_already_counted = true;
break;
}
}
@@ -4622,11 +4643,8 @@ static int InputTextLineIndexBuild(ImGuiInputTextFlags flags, ImGuiTextIndex* li
line_index->Offsets.push_back(0);
size++;
}
if (buf_end > buf && buf_end[-1] == '\n' && size <= max_output_buffer_size)
{
if (buf_end > buf && buf_end[-1] == '\n' && !trailing_line_already_counted && size++ <= max_output_buffer_size)
line_index->Offsets.push_back((int)(buf_end - buf));
size++;
}
return size;
}
@@ -4727,12 +4745,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
draw_window->DC.NavLayersActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it.
draw_window->DC.CursorPos += style.FramePadding;
inner_size.x -= draw_window->ScrollbarSizes.x;
// FIXME: Could this be a ImGuiChildFlags to affect the SetLastItemDataForWindow() call?
g.LastItemData.ID = id;
g.LastItemData.ItemFlags = item_data_backup.ItemFlags;
g.LastItemData.StatusFlags = item_data_backup.StatusFlags;
}
else
{
// Support for internal ImGuiInputTextFlags_MergedItem flag, which could be redesigned as an ItemFlags if needed (with test performed in ItemAdd)
ItemSize(total_bb, style.FramePadding.y);
if (!(flags & ImGuiInputTextFlags_MergedItem))
if (!(flags & ImGuiInputTextFlags_TempInput))
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
return false;
}
@@ -4763,11 +4786,13 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_wordwrap)
wrap_width = ImMax(1.0f, GetContentRegionAvail().x + (draw_window->ScrollbarY ? 0.0f : -g.Style.ScrollbarSize));
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard)));
const bool user_clicked = hovered && io.MouseClicked[0];
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
const bool input_requested_by_nav = (g.ActiveId != id) && (g.NavActivateId == id);
const bool input_requested_by_reactivate = (g.InputTextReactivateId == id); // for io.ConfigInputTextEnterKeepActive
const bool input_requested_by_user = (user_clicked) || (g.ActiveId == 0 && (flags & ImGuiInputTextFlags_TempInput));
const ImGuiID scrollbar_id = (is_multiline && state != NULL) ? GetWindowScrollbarID(draw_window, ImGuiAxis_Y) : 0;
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == scrollbar_id;
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == scrollbar_id;
bool clear_active_id = false;
bool select_all = false;
@@ -4775,8 +4800,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const bool init_reload_from_user_buf = (state != NULL && state->WantReloadUserBuf);
const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state.
const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav);
const bool init_state = (init_make_active || user_scroll_active);
const bool init_make_active = (input_requested_by_user || input_requested_by_nav || input_requested_by_reactivate || user_scroll_finish);
if (init_reload_from_user_buf)
{
int new_len = (int)ImStrlen(buf);
@@ -4789,7 +4813,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->Stb->select_start = state->ReloadSelectionStart;
state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd; // will be clamped to bounds below
}
else if ((init_state && g.ActiveId != id) || init_changed_specs)
else if ((init_make_active && g.ActiveId != id) || init_changed_specs)
{
// Access state even if we don't own it yet.
state = &g.InputTextState;
@@ -4802,8 +4826,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode)
const int buf_len = (int)ImStrlen(buf);
IM_ASSERT(((buf_len + 1 <= buf_size) || (buf_len == 0 && buf_size == 0)) && "Is your input buffer properly zero-terminated?");
state->TextToRevertTo.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
memcpy(state->TextToRevertTo.Data, buf, buf_len + 1);
if (!user_scroll_finish)
{
state->TextToRevertTo.resize(buf_len + 1); // UTF-8. we use +1 to make sure that .Data is always pointing to at least an empty string.
memcpy(state->TextToRevertTo.Data, buf, buf_len + 1);
}
// Preserve cursor position and undo/redo stack if we come back to same widget
// FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
@@ -4814,6 +4841,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Start edition
state->ID = id;
state->TextLen = buf_len;
state->EditedBefore = false;
if (!is_readonly)
{
state->TextA.resize(buf_size + 1); // we use +1 to make sure that .Data is always pointing to at least an empty string.
@@ -4899,7 +4927,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ClearActiveID();
// Release focus when we click outside
if (g.ActiveId == id && io.MouseClicked[0] && !init_state && !init_make_active) //-V560
if (g.ActiveId == id && io.MouseClicked[0] && !init_make_active) //-V560
clear_active_id = true;
// Lock the decision of whether we are going to take the path displaying the cursor or selection
@@ -4929,7 +4957,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (g.ActiveId == id)
{
IM_ASSERT(state != NULL);
state->Edited = false;
state->EditedThisFrame = false;
state->BufCapacity = buf_size;
state->Flags = flags;
state->WrapWidth = wrap_width;
@@ -5070,7 +5098,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0;
const bool is_enter = Shortcut(ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiKey_KeypadEnter, f_repeat, id);
const bool is_ctrl_enter = Shortcut(ImGuiMod_Ctrl | ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_KeypadEnter, f_repeat, id);
const bool is_gamepad_validate = nav_gamepad_active && (IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false));
const bool is_shift_enter = Shortcut(ImGuiMod_Shift | ImGuiKey_Enter, f_repeat, id) || Shortcut(ImGuiMod_Shift | ImGuiKey_KeypadEnter, f_repeat, id);
const bool is_gamepad_validate = nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadActivate, false);
const bool is_cancel = Shortcut(ImGuiKey_Escape, f_repeat, id) || (nav_gamepad_active && Shortcut(ImGuiKey_NavGamepadCancel, f_repeat, id));
// FIXME: Should use more Shortcut() and reduce IsKeyPressed()+SetKeyOwner(), but requires modifiers combination to be taken account of.
@@ -5104,17 +5133,20 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
}
else if (is_enter || is_ctrl_enter || is_gamepad_validate)
else if (is_enter || is_ctrl_enter || is_shift_enter || is_gamepad_validate)
{
// Determine if we turn Enter into a \n character
bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
if (!is_multiline || is_gamepad_validate || (ctrl_enter_for_new_line != is_ctrl_enter))
bool is_new_line = is_multiline && !is_gamepad_validate && (is_shift_enter || (is_enter && !ctrl_enter_for_new_line) || (is_ctrl_enter && ctrl_enter_for_new_line));
if (!is_new_line)
{
validated = true;
validated = clear_active_id = true;
if (io.ConfigInputTextEnterKeepActive && !is_multiline)
{
// Queue reactivation, so that e.g. IsItemDeactivatedAfterEdit() will work. (#9001)
state->SelectAll(); // No need to scroll
else
clear_active_id = true;
g.InputTextReactivateId = id; // Mark for reactivation on next frame
}
}
else if (!is_readonly)
{
@@ -5210,7 +5242,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
render_selection |= state->HasSelection() && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
}
// Process callbacks and apply result back to user's buffer.
// Process revert and user callbacks
const char* apply_new_text = NULL;
int apply_new_text_length = 0;
if (g.ActiveId == id)
@@ -5240,110 +5272,99 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
}
// FIXME-OPT: We always reapply the live buffer back to the input buffer before clearing ActiveId,
// even though strictly speaking it wasn't modified on this frame. Should mark dirty state from the stb_textedit callbacks.
// If we do that, need to ensure that as special case, 'validated == true' also writes back.
// This also allows the user to use InputText() without maintaining any user-side storage.
// (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object
// unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize).
const bool apply_edit_back_to_user_buffer = true;// !revert_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);
if (apply_edit_back_to_user_buffer)
// User callback
if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0)
{
// Apply current edited text immediately.
// Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer
IM_ASSERT(callback != NULL);
// User callback
if ((flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackEdit | ImGuiInputTextFlags_CallbackAlways)) != 0)
// The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.
ImGuiInputTextFlags event_flag = 0;
ImGuiKey event_key = ImGuiKey_None;
if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && Shortcut(ImGuiKey_Tab, 0, id))
{
IM_ASSERT(callback != NULL);
// The reason we specify the usage semantic (Completion/History) is that Completion needs to disable keyboard TABBING at the moment.
ImGuiInputTextFlags event_flag = 0;
ImGuiKey event_key = ImGuiKey_None;
if ((flags & ImGuiInputTextFlags_CallbackCompletion) != 0 && Shortcut(ImGuiKey_Tab, 0, id))
{
event_flag = ImGuiInputTextFlags_CallbackCompletion;
event_key = ImGuiKey_Tab;
}
else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressed(ImGuiKey_UpArrow))
{
event_flag = ImGuiInputTextFlags_CallbackHistory;
event_key = ImGuiKey_UpArrow;
}
else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressed(ImGuiKey_DownArrow))
{
event_flag = ImGuiInputTextFlags_CallbackHistory;
event_key = ImGuiKey_DownArrow;
}
else if ((flags & ImGuiInputTextFlags_CallbackEdit) && state->Edited)
{
event_flag = ImGuiInputTextFlags_CallbackEdit;
}
else if (flags & ImGuiInputTextFlags_CallbackAlways)
{
event_flag = ImGuiInputTextFlags_CallbackAlways;
}
if (event_flag)
{
ImGuiInputTextCallbackData callback_data;
callback_data.Ctx = &g;
callback_data.ID = id;
callback_data.Flags = flags;
callback_data.EventFlag = event_flag;
callback_data.EventActivated = (g.ActiveId == state->ID && g.ActiveIdIsJustActivated);
callback_data.UserData = callback_user_data;
// FIXME-OPT: Undo stack reconcile needs a backup of the data until we rework API, see #7925
char* callback_buf = is_readonly ? buf : state->TextA.Data;
IM_ASSERT(callback_buf == state->TextSrc);
state->CallbackTextBackup.resize(state->TextLen + 1);
memcpy(state->CallbackTextBackup.Data, callback_buf, state->TextLen + 1);
callback_data.EventKey = event_key;
callback_data.Buf = callback_buf;
callback_data.BufTextLen = state->TextLen;
callback_data.BufSize = state->BufCapacity;
callback_data.BufDirty = false;
callback_data.CursorPos = state->Stb->cursor;
callback_data.SelectionStart = state->Stb->select_start;
callback_data.SelectionEnd = state->Stb->select_end;
// Call user code
callback(&callback_data);
// Read back what user may have modified
callback_buf = is_readonly ? buf : state->TextA.Data; // Pointer may have been invalidated by a resize callback
IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields
IM_ASSERT(callback_data.BufSize == state->BufCapacity);
IM_ASSERT(callback_data.Flags == flags);
if (callback_data.BufDirty || callback_data.CursorPos != state->Stb->cursor)
state->CursorFollow = true;
state->Stb->cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen);
state->Stb->select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen);
state->Stb->select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen);
if (callback_data.BufDirty)
{
// Callback may update buffer and thus set buf_dirty even in read-only mode.
IM_ASSERT(callback_data.BufTextLen == (int)ImStrlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
InputTextReconcileUndoState(state, state->CallbackTextBackup.Data, state->CallbackTextBackup.Size - 1, callback_data.Buf, callback_data.BufTextLen);
state->TextLen = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
state->CursorAnimReset();
}
}
event_flag = ImGuiInputTextFlags_CallbackCompletion;
event_key = ImGuiKey_Tab;
}
else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressed(ImGuiKey_UpArrow))
{
event_flag = ImGuiInputTextFlags_CallbackHistory;
event_key = ImGuiKey_UpArrow;
}
else if ((flags & ImGuiInputTextFlags_CallbackHistory) != 0 && IsKeyPressed(ImGuiKey_DownArrow))
{
event_flag = ImGuiInputTextFlags_CallbackHistory;
event_key = ImGuiKey_DownArrow;
}
else if ((flags & ImGuiInputTextFlags_CallbackEdit) && state->EditedThisFrame)
{
event_flag = ImGuiInputTextFlags_CallbackEdit;
}
else if (flags & ImGuiInputTextFlags_CallbackAlways)
{
event_flag = ImGuiInputTextFlags_CallbackAlways;
}
// Will copy result string if modified
if (!is_readonly && strcmp(state->TextSrc, buf) != 0)
if (event_flag)
{
apply_new_text = state->TextSrc;
apply_new_text_length = state->TextLen;
value_changed = true;
ImGuiInputTextCallbackData callback_data;
callback_data.Ctx = &g;
callback_data.ID = id;
callback_data.Flags = flags;
callback_data.EventFlag = event_flag;
callback_data.EventActivated = (g.ActiveId == state->ID && g.ActiveIdIsJustActivated);
callback_data.UserData = callback_user_data;
// FIXME-OPT: Undo stack reconcile needs a backup of the data until we rework API, see #7925
char* callback_buf = is_readonly ? buf : state->TextA.Data;
IM_ASSERT(callback_buf == state->TextSrc);
state->CallbackTextBackup.resize(state->TextLen + 1);
memcpy(state->CallbackTextBackup.Data, callback_buf, state->TextLen + 1);
callback_data.EventKey = event_key;
callback_data.Buf = callback_buf;
callback_data.BufTextLen = state->TextLen;
callback_data.BufSize = state->BufCapacity;
callback_data.BufDirty = false;
callback_data.CursorPos = state->Stb->cursor;
callback_data.SelectionStart = state->Stb->select_start;
callback_data.SelectionEnd = state->Stb->select_end;
// Call user code
callback(&callback_data);
// Read back what user may have modified
callback_buf = is_readonly ? buf : state->TextA.Data; // Pointer may have been invalidated by a resize callback
IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields
IM_ASSERT(callback_data.BufSize == state->BufCapacity);
IM_ASSERT(callback_data.Flags == flags);
if (callback_data.BufDirty || callback_data.CursorPos != state->Stb->cursor)
state->CursorFollow = true;
state->Stb->cursor = ImClamp(callback_data.CursorPos, 0, callback_data.BufTextLen);
state->Stb->select_start = ImClamp(callback_data.SelectionStart, 0, callback_data.BufTextLen);
state->Stb->select_end = ImClamp(callback_data.SelectionEnd, 0, callback_data.BufTextLen);
if (callback_data.BufDirty)
{
// Callback may update buffer and thus set buf_dirty even in read-only mode.
IM_ASSERT(callback_data.BufTextLen == (int)ImStrlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
InputTextReconcileUndoState(state, state->CallbackTextBackup.Data, state->CallbackTextBackup.Size - 1, callback_data.Buf, callback_data.BufTextLen);
state->TextLen = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
state->CursorAnimReset();
}
}
}
// Will copy result string if modified.
// FIXME-OPT: Could mark dirty state from the stb_textedit callbacks
if (!is_readonly && strcmp(state->TextSrc, buf) != 0)
{
apply_new_text = state->TextSrc;
apply_new_text_length = state->TextLen;
value_changed = true;
}
}
// Handle reapplying final data on deactivation (see InputTextDeactivateHook() for details)
// This is used when e.g. losing focus or tabbing out into another InputText() which may already be using the temp buffer.
if (g.InputTextDeactivatedState.ID == id)
{
if (g.ActiveId != id && IsItemDeactivatedAfterEdit() && !is_readonly && strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0)
@@ -5356,12 +5377,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
g.InputTextDeactivatedState.ID = 0;
}
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
// Write back result to user buffer. This can currently only happen when (g.ActiveId == id) or when just deactivated.
// - As soon as the InputText() is active, our stored in-widget value gets priority over any underlying modification of the user buffer.
// - Make sure we always reapply the live buffer back to the input/user buffer before clearing ActiveId, even thought strictly speaking
// it was not modified on this frame. This allows the user to use InputText() without maintaining any user-side storage.
// (PS: if you use this property together with ImGuiInputTextFlags_CallbackResize, you are at the risk of recreating a temporary
// allocated/string object every frame. Which in the grand scheme of scheme is nothing, but isn't dear imgui vibe).
if (apply_new_text != NULL)
{
//// We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size
//// of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used
//// without any storage on user's side.
IM_ASSERT(apply_new_text_length >= 0);
if (is_resizable)
{
@@ -5370,7 +5393,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
callback_data.ID = id;
callback_data.Flags = flags;
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
callback_data.EventActivated = (g.ActiveId == state->ID && g.ActiveIdIsJustActivated);
callback_data.EventActivated = (state != NULL && g.ActiveId == state->ID && g.ActiveIdIsJustActivated);
callback_data.Buf = buf;
callback_data.BufTextLen = apply_new_text_length;
callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
@@ -5530,7 +5553,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (render_selection)
{
const ImU32 bg_color = GetColorU32(ImGuiCol_TextSelectedBg, render_cursor ? 1.0f : 0.6f); // FIXME: current code flow mandate that render_cursor is always true here, we are leaving the transparent one for tests.
const float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME: those offsets should be part of the style? they don't play so well with multi-line selection.
const float bg_offy_up = is_multiline ? 0.0f : -1.0f; // FIXME-DPI: those offsets should be part of the style? they don't play so well with multi-line selection.
const float bg_offy_dn = is_multiline ? 0.0f : 2.0f;
const float bg_eol_width = IM_TRUNC(g.FontBaked->GetCharAdvance((ImWchar)' ') * 0.50f); // So we can see selected empty lines
@@ -5559,7 +5582,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
rect.Min.y = draw_pos.y - draw_scroll.y + line_n * g.FontSize;
rect.Max.x = rect.Min.x + rect_width;
rect.Max.y = rect.Min.y + bg_offy_dn + g.FontSize;
rect.Min.y -= bg_offy_up;
rect.Min.y += bg_offy_up;
rect.ClipWith(clip_rect);
draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color);
}
@@ -5567,7 +5590,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
}
// Find render position for right alignment (single-line only)
if (g.ActiveId != id && flags & ImGuiInputTextFlags_ElideLeft)
if (g.ActiveId != id && (flags & ImGuiInputTextFlags_ElideLeft) && !render_cursor && !render_selection)
draw_pos.x = ImMin(draw_pos.x, frame_bb.Max.x - CalcTextSize(buf_display, NULL).x - style.FramePadding.x);
//draw_scroll.x = state->Scroll.x; // Preserve scroll when inactive?
@@ -5588,7 +5611,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f); // FIXME-DPI: Cursor thickness (#7031)
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f * (float)(int)style._MainScale); // FIXME-DPI: Cursor thickness (#7031)
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
// This is required for some backends (SDL3) to start emitting character/text inputs.
@@ -6446,7 +6469,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
if (g.Style.FrameBorderSize > 0.0f)
RenderFrameBorder(bb.Min, bb.Max, rounding);
else
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color buttons are often in need of some sort of border // FIXME-DPI
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding, 0, 1.0f * (float)(int)g.Style._MainScale); // Color buttons are often in need of some sort of border // FIXME-DPI
}
// Drag and Drop Source
@@ -6726,6 +6749,8 @@ bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char
return TreeNodeBehavior(id, flags, label, label_end);
}
// The reason those two functions are not yet in public API is because I would like to design a more feature-full and generic API for this.
// They are otherwise function (cc: #3823, #9251, #7553, #6754, #5423, #2958, #2079, #1947, #1131, #722)
bool ImGui::TreeNodeGetOpen(ImGuiID storage_id)
{
ImGuiContext& g = *GImGui;
@@ -6733,15 +6758,16 @@ bool ImGui::TreeNodeGetOpen(ImGuiID storage_id)
return storage->GetInt(storage_id, 0) != 0;
}
void ImGui::TreeNodeSetOpen(ImGuiID storage_id, bool open)
void ImGui::TreeNodeSetOpen(ImGuiID storage_id, bool is_open)
{
ImGuiContext& g = *GImGui;
ImGuiStorage* storage = g.CurrentWindow->DC.StateStorage;
storage->SetInt(storage_id, open ? 1 : 0);
storage->SetInt(storage_id, is_open ? 1 : 0);
}
bool ImGui::TreeNodeUpdateNextOpen(ImGuiID storage_id, ImGuiTreeNodeFlags flags)
{
// Leaf node always open a new tree/id scope. If you never use it, add ImGuiTreeNodeFlags_NoTreePushOnOpen.
if (flags & ImGuiTreeNodeFlags_Leaf)
return true;
@@ -8165,10 +8191,13 @@ void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags
{
ImGuiButtonFlags button_flags = *p_button_flags;
button_flags |= ImGuiButtonFlags_NoHoveredOnFocus;
if ((!selected || (g.ActiveId == id && g.ActiveIdHasBeenPressedBefore)) && !(ms->Flags & ImGuiMultiSelectFlags_SelectOnClickRelease))
button_flags = (button_flags | ImGuiButtonFlags_PressedOnClick) & ~ImGuiButtonFlags_PressedOnClickRelease;
else
button_flags &= ~(ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnClickRelease);
if (ms->Flags & ImGuiMultiSelectFlags_SelectOnClickAlways)
button_flags |= ImGuiButtonFlags_PressedOnClick;
else if (ms->Flags & ImGuiMultiSelectFlags_SelectOnClickRelease)
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
else // ImGuiMultiSelectFlags_SelectOnAuto
button_flags |= (!selected || (g.ActiveId == id && g.ActiveIdHasBeenPressedBefore)) ? ImGuiButtonFlags_PressedOnClick : ImGuiButtonFlags_PressedOnClickRelease;
*p_button_flags = button_flags;
}
}
@@ -8288,7 +8317,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
// Box-select
ImGuiInputSource input_source = (g.NavJustMovedToId == id || g.NavActivateId == id) ? g.NavInputSource : ImGuiInputSource_Mouse;
if (flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
if (selected == false && !g.BoxSelectState.IsActive && !g.BoxSelectState.IsStarting && input_source == ImGuiInputSource_Mouse && g.IO.MouseClickedCount[0] == 1)
if (!g.BoxSelectState.IsActive && !g.BoxSelectState.IsStarting && input_source == ImGuiInputSource_Mouse && g.IO.MouseClickedCount[0] == 1)
BoxSelectPreStartDrag(ms->BoxSelectId, item_data);
//----------------------------------------------------------------------------------------
@@ -9232,11 +9261,12 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
PushID(label);
if (!enabled)
BeginDisabled();
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
bool pressed;
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_NoAutoClosePopups;
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
{
// Menu inside a horizontal menu bar
@@ -9244,9 +9274,8 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
// For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin()
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f);
PushStyleVarX(ImGuiStyleVar_ItemSpacing, style.ItemSpacing.x * 2.0f);
float w = label_size.x;
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, pos.y + window->DC.CurrLineTextBaseOffset);
pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, label_size.y));
pressed = Selectable("", menu_is_open, selectable_flags, label_size);
LogSetNextTextDecoration("[", "]");
RenderText(text_pos, label);
PopStyleVar();
@@ -9260,7 +9289,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.)
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f);
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
float min_w = offsets->DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
ImVec2 text_pos(window->DC.CursorPos.x, pos.y + window->DC.CurrLineTextBaseOffset);
pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
@@ -9445,17 +9474,16 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
BeginDisabled();
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SetNavIdOnHover;
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SetNavIdOnHover;
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
{
// Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
// Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark.
float w = label_size.x;
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * 0.5f);
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
PushStyleVarX(ImGuiStyleVar_ItemSpacing, style.ItemSpacing.x * 2.0f);
pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f));
pressed = Selectable("", selected, selectable_flags, ImVec2(label_size.x, 0.0f));
PopStyleVar();
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
RenderText(text_pos, label);
@@ -9469,7 +9497,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f;
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f);
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
float min_w = offsets->DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
ImVec2 text_pos(pos.x, pos.y + window->DC.CurrLineTextBaseOffset);
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
@@ -10545,7 +10573,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// Click to Select a tab
// Allow the close button to overlap
ImGuiButtonFlags button_flags = ((is_tab_button ? ImGuiButtonFlags_PressedOnClickRelease : ImGuiButtonFlags_PressedOnClick) | ImGuiButtonFlags_AllowOverlap);
ImGuiButtonFlags button_flags = ((ImGuiButtonFlags)(is_tab_button ? ImGuiButtonFlags_PressedOnClickRelease : ImGuiButtonFlags_PressedOnClick) | ImGuiButtonFlags_AllowOverlap);
if (g.DragDropActive)
button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
bool hovered, held, pressed;
+2 -2
View File
@@ -315,7 +315,7 @@ static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0
if (node->y > min_y) {
// raise min_y higher.
// we've accounted for all waste up to min_y,
// but we'll now add more waste for everything we've visted
// but we'll now add more waste for everything we've visited
waste_area += visited_width * (node->y - min_y);
min_y = node->y;
// the first time through, visited_width might be reduced
@@ -470,7 +470,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i
// insert the new node into the right starting point, and
// let 'cur' point to the remaining nodes needing to be
// stiched back in
// stitched back in
cur = *res.prev_link;
if (cur->x < res.x) {
+1 -1
View File
@@ -886,7 +886,7 @@ STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, fl
// xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap
STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff);
// the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel
// the same as stbtt_GetCodepointBitmap, but you can specify a subpixel
// shift for the character
STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint);
-1032
View File
File diff suppressed because it is too large Load Diff
+74
View File
@@ -0,0 +1,74 @@
# SoundTouch library
## About
SoundTouch is an open-source audio processing library that allows changing the sound tempo, pitch and playback rate parameters independently from each other:
* Change **tempo** while maintaining the original pitch
* Change **pitch** while maintaining the original tempo
* Change **playback rate** that affects both tempo and pitch at the
same time
* Change any combination of tempo/pitch/rate
Visit [SoundTouch website](https://www.surina.net/soundtouch) and see the [README file](https://www.surina.net/soundtouch/readme.html) for more information and audio examples.
## Version
**The latest stable release in Git is 2.4.1**
See the [README file for change history](https://soundtouch.surina.net/README.html#changehistory)
[![latest packaged version(s)](https://repology.org/badge/latest-versions/soundtouch.svg)](https://repology.org/project/soundtouch/versions)
## Example
Use SoundStretch example app for modifying wav audio files, for example as follows:
```
soundstretch my_original_file.wav output_file.wav -tempo=+15 -pitch=-3
```
See the [README file](https://soundtouch.surina.net/README.html) for more usage examples and instructions how to build the software.
Ready [SoundStretch application executables](https://www.surina.net/soundtouch/download.html) are available for download for Windows and Mac OS.
## Language & Platforms
SoundTouch is written in C++ and compiles in virtually any platform:
* Windows
* Mac OS
* Linux & Unices (including also Raspberry, Beaglebone, Yocto etc embedded Linux flavors)
* Android
* iOS
* embedded systems
The source code package includes dynamic library import modules for C#, Java and Pascal/Delphi languages.
## Tarballs
Source code release tarballs:
* https://www.surina.net/soundtouch/soundtouch-2.4.1.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.4.0.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.3.3.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.3.2.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.3.1.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.3.0.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.2.0.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.1.2.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.1.1.tar.gz
* https://www.surina.net/soundtouch/soundtouch-2.0.0.tar.gz
## License
SoundTouch is released under LGPL v2.1:
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
See [LGPL v2.1 full license text ](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html) for details.
--
Also commercial license free of GPL limitations available upon request
+2 -2
View File
@@ -72,10 +72,10 @@ namespace soundtouch
{
/// Soundtouch library version string
#define SOUNDTOUCH_VERSION "2.4.0"
#define SOUNDTOUCH_VERSION "2.4.1"
/// SoundTouch library version id
#define SOUNDTOUCH_VERSION_ID (20400)
#define SOUNDTOUCH_VERSION_ID (20401)
//
// Available setting IDs for the 'setSetting' & 'get_setting' functions:
+1 -1
View File
@@ -220,7 +220,7 @@ void WavInFile::init()
}
// sanity check for format parameters
if ((header.format.channel_number < 1) || (header.format.channel_number > 9) ||
if ((header.format.channel_number < 1) || (header.format.channel_number > 32) ||
(header.format.sample_rate < 4000) || (header.format.sample_rate > 192000) ||
(header.format.byte_per_sample < 1) || (header.format.byte_per_sample > 320) ||
(header.format.bits_per_sample < 8) || (header.format.bits_per_sample > 32))
+1 -1
View File
@@ -165,7 +165,7 @@ uint FIRFilter::evaluateFilterMulti(SAMPLETYPE *dest, const SAMPLETYPE *src, uin
for (j = 0; j < end; j += numChannels)
{
const SAMPLETYPE *ptr;
LONG_SAMPLETYPE sums[16];
LONG_SAMPLETYPE sums[SOUNDTOUCH_MAX_CHANNELS];
uint c;
int i;
+1 -2
View File
@@ -136,10 +136,9 @@ int PeakFinder::findGround(const float *data, int peakpos, int direction) const
// proceeds to direction defined in 'direction'
int PeakFinder::findCrossingLevel(const float *data, float level, int peakpos, int direction) const
{
float peaklevel;
int pos;
peaklevel = data[peakpos];
[[maybe_unused]] float peaklevel = data[peakpos];
assert(peaklevel >= level);
pos = peakpos;
while ((pos >= minPos) && (pos + direction < maxPos))
+1 -1
View File
@@ -220,7 +220,7 @@ void FIRFilterSSE::setCoefficients(const float *coeffs, uint newLength, uint uRe
filterCoeffsUnalign = new float[2 * newLength + 4];
filterCoeffsAlign = (float *)SOUNDTOUCH_ALIGN_POINTER_16(filterCoeffsUnalign);
const float scale = ::pow(0.5, (int)resultDivFactor);
const float scale = static_cast<float>(::pow(0.5, (int)resultDivFactor));
// rearrange the filter coefficients for sse routines
for (auto i = 0U; i < newLength; i ++)
File diff suppressed because it is too large Load Diff
+59 -25
View File
@@ -17558,7 +17558,7 @@ SLES-51257:
name: "The Sims"
name-sort: "Sims, The"
region: "PAL-M8"
compat: 3
compat: 5
speedHacks:
mtvu: 0 # Fixes bad graphics due to bad T-Bit handling.
SLES-51258:
@@ -17719,7 +17719,7 @@ SLES-51315:
compat: 5
SLES-51316:
name: "Grand Theft Auto - Vice City"
region: "PAL-E"
region: "PAL-A"
SLES-51317:
name: "Minority Report - Le Futur vous Rattrape"
region: "PAL-F"
@@ -20719,7 +20719,7 @@ SLES-52558:
name: "Crimson Sea 2"
region: "PAL-G"
SLES-52559:
name: "FIFA 2005"
name: "FIFA Football 2005"
region: "PAL-E"
gameFixes:
- GIFFIFOHack # Partially fixes graphical issues also needs EE cycle rate + 3.
@@ -20728,9 +20728,10 @@ SLES-52559:
gsHWFixes:
halfPixelOffset: 2 # Fixes misaligned bloom and edge garbage.
nativeScaling: 1 # Fixes misaligned bloom.
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLES-52560:
name: "FIFA 2005"
name: "FIFA Football 2005"
region: "PAL-G"
gameFixes:
- GIFFIFOHack # Partially fixes graphical issues also needs EE cycle rate + 3.
@@ -20739,9 +20740,10 @@ SLES-52560:
gsHWFixes:
halfPixelOffset: 2 # Fixes misaligned bloom and edge garbage.
nativeScaling: 1 # Fixes misaligned bloom.
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLES-52561:
name: "FIFA 2005"
name: "FIFA Football 2005"
region: "PAL-P-S"
gameFixes:
- GIFFIFOHack # Partially fixes graphical issues also needs EE cycle rate + 3.
@@ -20750,9 +20752,10 @@ SLES-52561:
gsHWFixes:
halfPixelOffset: 2 # Fixes misaligned bloom and edge garbage.
nativeScaling: 1 # Fixes misaligned bloom.
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLES-52562:
name: "FIFA 2005"
name: "FIFA Football 2005"
region: "PAL-I"
gameFixes:
- GIFFIFOHack # Partially fixes graphical issues also needs EE cycle rate + 3.
@@ -20761,7 +20764,8 @@ SLES-52562:
gsHWFixes:
halfPixelOffset: 2 # Fixes misaligned bloom and edge garbage.
nativeScaling: 1 # Fixes misaligned bloom.
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLES-52563:
name: "FIFA Football 2005"
region: "PAL-M6"
@@ -20772,7 +20776,11 @@ SLES-52563:
gsHWFixes:
halfPixelOffset: 2 # Fixes misaligned bloom and edge garbage.
nativeScaling: 1 # Fixes misaligned bloom.
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
memcardFilters: # Football Fusion with Total Club Manager 2005
- "SLES-52674"
- "SLES-52563"
SLES-52567:
name: "Catwoman"
region: "PAL-M7"
@@ -21167,10 +21175,13 @@ SLES-52673:
name: "NHL 2005"
region: "PAL-M5"
SLES-52674:
name: "Fussball Manager 2005"
name: "Total Club Manager 2005"
region: "PAL-M5"
clampModes:
vu1ClampMode: 3 # Fixes 3D rendering.
memcardFilters: # Football Fusion with Total Club Manager 2005
- "SLES-52674"
- "SLES-52563"
SLES-52675:
name: "Hugo - Cannon Cruise"
region: "PAL-Unk"
@@ -21839,28 +21850,32 @@ SLES-52909:
gameFixes:
- EETimingHack # Fixes graphical corruption.
gsHWFixes:
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLES-52910:
name: "UEFA Champions League 2005"
name: "UEFA Champions League 2004-2005"
region: "PAL-F-G"
gameFixes:
- EETimingHack # Fixes graphical corruption.
gsHWFixes:
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLES-52911:
name: "UEFA Champions League 2005"
name: "UEFA Champions League 2004-2005"
region: "PAL-I-S"
gameFixes:
- EETimingHack # Fixes graphical corruption.
gsHWFixes:
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLES-52912:
name: "UEFA Champions League 2005"
name: "UEFA Champions League 2004-2005"
region: "PAL-E-DU"
gameFixes:
- EETimingHack # Fixes graphical corruption.
gsHWFixes:
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLES-52913:
name: "Suikoden IV"
region: "PAL-M5"
@@ -27045,6 +27060,9 @@ SLES-54522:
SLES-54527:
name: "DreamWorks & Aardman Flushed Away"
region: "PAL-M5"
gsHWFixes:
halfPixelOffset: 5 # Fixes post alignment.
nativeScaling: 2 # Fixes post effects.
SLES-54532:
name: "Home Alone"
region: "PAL-PL-P"
@@ -28404,7 +28422,7 @@ SLES-54960:
name: "Godzilla - Unleashed"
region: "PAL-M5"
SLES-54961:
name: "World series of poker 2008"
name: "World Series of Poker 2008 - Battle for the Bracelets"
region: "PAL-E"
SLES-54962:
name: "Guitar Hero III - Legends of Rock"
@@ -31951,6 +31969,9 @@ SLKA-25176:
name: "펌프 잇 업 익시드"
name-en: "Pump It Up - Exceed"
region: "NTSC-K"
gsHWFixes:
cpuSpriteRenderBW: 4 # Fixes graphical corruption in musical notes.
cpuSpriteRenderLevel: 2 # Needed for above.
SLKA-25180:
name: "스플린터 셀 - 판도라 투머로우"
name-en: "Tom Clancy's Splinter Cell - Pandora Tomorrow"
@@ -32125,7 +32146,8 @@ SLKA-25209:
gsHWFixes:
halfPixelOffset: 2 # Fixes misaligned bloom and edge garbage.
nativeScaling: 1 # Fixes misaligned bloom.
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLKA-25210:
name: "서머 히트 비치 발리볼" # Undumped on ReDump as of 2025-08-28
name-en: "Summer Heat Beach Volleyball"
@@ -44020,7 +44042,7 @@ SLPM-65495:
SLPM-65496:
name: "ハイパーストリートファイターⅡ アニバーサリーエディション"
name-sort: "はいぱーすとりーとふぁいたー2 あにばーさりーえでぃしょん"
name-en: "Hyper Street Fighter"
name-en: "Hyper Street Fighter II - The Anniversary Edition"
region: "NTSC-J"
SLPM-65497:
name: "ワールドサッカーウイニングイレブン7 インターナショナル プレミアムパッケージ supported by アディダス"
@@ -54487,6 +54509,7 @@ SLPM-74405:
region: "NTSC-J"
gameFixes:
- EETimingHack # Stops crash after intro movie.
- InstantDMAHack # Stops hang when entering Sword Select screen.
SLPM-74406:
name: "WRC WORLD RALLY CHAMPIONSHIP [PlayStation2 the Best]"
name-sort: "WRC ~わーるど らりー ちゃんぴおんしっぷ~ [PlayStation2 the Best]"
@@ -69652,7 +69675,7 @@ SLUS-21050:
getSkipCount: "GSC_BurnoutGames"
beforeDraw: "OI_BurnoutGames"
SLUS-21051:
name: "FIFA 2005"
name: "FIFA Soccer 2005"
region: "NTSC-U"
compat: 5
gameFixes:
@@ -69662,7 +69685,8 @@ SLUS-21051:
gsHWFixes:
halfPixelOffset: 2 # Fixes misaligned bloom and edge garbage.
nativeScaling: 1 # Fixes misaligned bloom.
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLUS-21052:
name: "Disney/Pixar Monsters, Inc."
region: "NTSC-U"
@@ -70095,6 +70119,9 @@ SLUS-21131:
name: "Pump It Up - Exceed"
region: "NTSC-U"
compat: 5
gsHWFixes:
cpuSpriteRenderBW: 4 # Fixes graphical corruption in musical notes.
cpuSpriteRenderLevel: 2 # Needed for above.
SLUS-21132:
name: "Stella Deus - The Gate of Eternity"
region: "NTSC-U"
@@ -72499,6 +72526,9 @@ SLUS-21484:
name: "DreamWorks & Aardman Flushed Away"
region: "NTSC-U"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes post alignment.
nativeScaling: 2 # Fixes post effects.
SLUS-21485:
name: "Backyard Sports - Basketball 2007"
region: "NTSC-U"
@@ -75569,7 +75599,8 @@ SLUS-29127:
gsHWFixes:
halfPixelOffset: 2 # Fixes misaligned bloom and edge garbage.
nativeScaling: 1 # Fixes misaligned bloom.
mipmap: 0 # Currently totally breaks player uniform rendering if mipmapping is enabled.
cpuSpriteRenderBW: 2 # Fixes player outfit rendering.
cpuSpriteRenderLevel: 2 # Needed for above.
SLUS-29129:
name: "25 to Life [Public Beta Vol.1.0]"
region: "NTSC-U"
@@ -75930,6 +75961,9 @@ SLUS-29196:
SLUS-29197:
name: "DreamWorks & Aardman Flushed Away [Demo]"
region: "NTSC-U"
gsHWFixes:
halfPixelOffset: 5 # Fixes post alignment.
nativeScaling: 2 # Fixes post effects.
SLUS-29198:
name: "Guitar Hero II [Demo]"
region: "NTSC-U"
File diff suppressed because it is too large Load Diff
@@ -1,93 +0,0 @@
Copyright 2021 Google Inc. All Rights Reserved.
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
"Font Software" 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.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" 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.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & 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 "AS IS", 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.
Binary file not shown.
@@ -0,0 +1,50 @@
## License for the Code
Copyright 2016-2018, Mozilla Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
## License for the Visual Design
The Emoji art in the twe-svg.zip archive comes from [Twemoji](https://twitter.github.io/twemoji),
and is used and redistributed under the CC-BY-4.0 [license terms](https://github.com/twitter/twemoji#license)
offered by the Twemoji project.
### Creative Commons Attribution 4.0 International (CC BY 4.0)
https://creativecommons.org/licenses/by/4.0/legalcode
or for the human readable summary: https://creativecommons.org/licenses/by/4.0/
#### You are free to:
**Share** — copy and redistribute the material in any medium or format
**Adapt** — remix, transform, and build upon the material for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
#### Under the following terms:
**Attribution** — You must give appropriate credit, provide a link to the license,
and indicate if changes were made.
You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
**No additional restrictions** — You may not apply legal terms or **technological measures**
that legally restrict others from doing anything the license permits.
#### Notices:
You do not have to comply with the license for elements of the material in the public domain
or where your use is permitted by an applicable exception or limitation. No warranties are given.
The license may not give you all of the permissions necessary for your intended use.
For example, other rights such as publicity, privacy, or moral rights may limit how you use the material.
Binary file not shown.
+94 -78
View File
@@ -48,7 +48,7 @@
03000000c82d00002038000000000000,8BitDo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000751000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000851000000000000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000360000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000361000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000660000000000000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000960000000000000,8BitDo Pro 3,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
@@ -75,7 +75,9 @@
03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001130000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001230000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001330000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001260000000000000,8BitDo Ultimate 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b17,paddle2:b16,paddle3:b2,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001b30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001c30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
@@ -83,8 +85,6 @@
03000000c82d00001530000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001630000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001730000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001130000000000000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001330000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000121000000000000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
@@ -125,7 +125,7 @@
03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000050b00000579000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000050b00000679000000000000,ASUS ROG Kunai 3,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,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
030000006a0e00001140000000000000,Atari CX Wireless Controller,a:b0,leftx:a0,lefty:a1,platform:Windows,
030000006a0e00001140000000000000,Atari CX Controller,a:b0,leftx:a0,lefty:a1,platform:Windows,
03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows,
03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
03000000380800001889000000000000,AtGames Legends Gamer Pro,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b14,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
@@ -140,6 +140,8 @@
03000000ad1b000001f9000000000000,BB 070,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,
03000000d62000002a79000000000000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
03000000bc2000005250000000000000,Beitong G3,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:b9,rightx:a3,righty:a4,start:b15,x:b3,y:b4,platform:Windows,
030000000d0500000208000000000000,Belkin Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
030000000d0500000308000000000000,Belkin Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows,
03000000bc2000006012000000000000,Betop 2126F,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,
03000000bc2000000055000000000000,Betop BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000790000000700000000000000,Betop 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:a4,start:b9,x:b3,y:b0,platform:Windows,
@@ -176,6 +178,7 @@
030000001a1c00000001000000000000,Datel Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000451300000830000000000000,Defender Game Racer X7,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000791d00000103000000000000,Dual Box Wii,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000151a00006222000000000000,Dual Plus PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,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,
030000004f040000070f000000000000,Dual Power,a:b8,b:b9,back:b4,dpdown:b1,dpleft:b2,dpright:b3,dpup:b0,leftshoulder:b13,leftstick:b6,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b12,rightstick:b7,righttrigger:b15,start:b5,x:b10,y:b11,platform:Windows,
030000004f04000012b3000000000000,Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
@@ -190,7 +193,7 @@
03000095090000010000000000000000,Elecom JC-U609,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows,
0300004112000000e500000000000000,Elecom JC-U909Z,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows,
03000041120000001050000000000000,Elecom JC-U911,a:b1,b:b2,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,start:b0,x:b4,y:b5,platform:Windows,
030000006e0500000520000000000000,Elecom P301U PlayStation Controller Adapter,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
030000006e0500000520000000000000,Elecom P301U PlayStation Adapter,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
03000000250900000218000000000000,Elecom 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,
03000000411200004450000000000000,Elecom U1012,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
030000006e0500000320000000000000,Elecom U3613M,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Windows,
@@ -226,11 +229,11 @@
03000000b40400001224000000000000,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:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows,
0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
03000000790000004618000000000000,GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000260900002625000000000000,GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,
03000000341a000005f7000000000000,GameCube Controller,a:b2,b:b3,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b1,y:b0,platform:Windows,
03000000430b00000500000000000000,GameCube Controller,a:b0,b:b2,dpdown:b10,dpleft:b8,dpright:b9,dpup:b11,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a3,rightx:a5,righty:a2,start:b7,x:b1,y:b3,platform:Windows,
03000000790000004718000000000000,GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000790000004618000000000000,GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
030000008f0e00000d31000000000000,Gamepad 3 Turbo,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,
03000000ac0500003d03000000000000,GameSir G3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000ac0500005b05000000000000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -344,7 +347,7 @@
030000000d0f0000dc00000000000000,Horipad Switch,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,
03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows,
03000000242e0000ff0b000000000000,Hyperkin N64 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:a3,start:b9,platform:Windows,
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,
03000000790000004e95000000000000,Hyperkin N64 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,
@@ -373,11 +376,13 @@
030000007e0500000720000000000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
03000000250900000017000000000000,Joypad Adapter,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,
03000000bd12000003c0000000000000,Joypad Alpha Shock,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000008b0100002301000000000000,Joytech JS-112,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a2,lefty:a3,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a0,righty:a1,start:b9,x:b0,y:b1,platform:Windows,
03000000ff1100004033000000000000,JPD FFB,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:a2,start:b15,x:b3,y:b0,platform:Windows,
03000000242f00002d00000000000000,JYS Adapter,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,
03000000242f00008a00000000000000,JYS Adapter,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,
03000000c4100000c082000000000000,KADE,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:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000828200000180000000000000,Keio,a:b4,b:b5,back:b8,leftshoulder:b2,lefttrigger:b3,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b1,platform:Windows,
03000000c4ac00001c80000000000000,KidzPlay Adventure PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000790000000200000000000000,King PS3 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:a4,start:b9,x:b3,y:b0,platform:Windows,
03000000bd12000001e0000000000000,Leadership,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:Windows,
030000006f0e00000103000000000000,Logic3,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,
@@ -421,19 +426,19 @@
03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
030000002a0600001024000000000000,Matricom,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
030000008f0e00001330000000000000,Mayflash Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,
030000008f0e00001330000000000000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,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:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000790000004318000000000000,Mayflash GameCube Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
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,
03000000242f0000f400000000000000,Mayflash N64 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,
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,
03000000790000007918000000000000,Mayflash N64 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,
0300000025090000e803000000000000,Mayflash Wii Classic Adapter,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:a5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
03000000790000000318000000000000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Windows,
@@ -475,27 +480,25 @@
03000000eb0300000000000000000000,NeGcon Adapter,a:a2,b:b13,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,lefttrigger:a4,leftx:a1,righttrigger:b11,start:b3,x:a3,y:b12,platform:Windows,
0300000038070000efbe000000000000,NEO SE,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:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
0300000092120000474e000000000000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Windows,
03000000921200004b46000000000000,NES 2 port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
03000000921200004b46000000000000,NES Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
03000000790000004518000000000000,NEXILUX GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000790000004518000000000000,NEXiLUX GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Windows,
03000000050b00000045000000000000,Nexus,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Windows,
03000000152000000182000000000000,NGDS,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:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
03000000ec110000e1a7000000000000,Nintendo Switch,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000007e0500006920000000000000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Windows,
030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000000d0500000208000000000000,Nostromo N40,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
030000000d0500000308000000000000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Windows,
030000007e0500007320000000000000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Windows,
030000007e0500001920000000000000,NSO N64 Controller,+rightx:b8,+righty:b2,-rightx:b3,-righty:b7,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Windows,
030000007e0500001720000000000000,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:Windows,
03000000550900001472000000000000,NVIDIA Controller,a:b11,b:b10,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b5,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b4,righttrigger:a5,rightx:a3,righty:a6,start:b3,x:b9,y:b8,platform:Windows,
03000000550900001072000000000000,NVIDIA Shield,a:b9,b:b8,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b3,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b2,righttrigger:a4,rightx:a2,righty:a5,start:b0,x:b7,y:b6,platform:Windows,
030000005509000000b4000000000000,NVIDIA Virtual,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:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000120c00000288000000000000,Nyko Air Flo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
030000004b120000014d000000000000,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:Windows,
030000004b120000014d000000000000,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:Windows,
03000000d62000001d57000000000000,Nyko Airflo 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,
03000000120c00000288000000000000,Nyko Airflo Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000791d00000900000000000000,Nyko Playpad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000782300000a10000000000000,Onlive Controller,a:b15,b:b14,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b11,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b13,y:b12,platform:Windows,
030000000d0f00000401000000000000,Onyx,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,
@@ -516,8 +519,8 @@
03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,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:Windows,
03000000dd62000016a7000000000000,PowerA Fusion 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:Windows,
03000000d620000013a7000000000000,PowerA 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:Windows,
03000000d62000003340000000000000,PowerA OPS Pro 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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000d62000002640000000000000,PowerA OPS 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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000d62000002640000000000000,PowerA OPS 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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000d62000003340000000000000,PowerA OPS Pro 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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000d62000006dca000000000000,PowerA Pro Ex,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,
0300000062060000d570000000000000,PowerA PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d620000014a7000000000000,PowerA Spectra 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:Windows,
@@ -535,7 +538,6 @@
03000000250900008888000000000000,PS2 Controller,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,
030000006b1400000303000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000009d0d00001330000000000000,PS2 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000151a00006222000000000000,PS2 Dual Plus Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,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,
03000000120a00000100000000000000,PS3 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:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000120c00001307000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000120c00001cf1000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -603,7 +605,7 @@
030000009b2800006300000000000000,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:Windows,
030000009b2800006400000000000000,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:Windows,
030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows,
030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows,
030000009b2800004400000000000000,Raphnet PlayStation Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows,
030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
030000009b2800000500000000000000,Raphnet Saturn Adapter 2.0,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
030000009b2800000300000000000000,Raphnet SNES Adapter,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
@@ -631,7 +633,7 @@
03000000321500000910000000000000,Razer Raiju UE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000321500000011000000000000,Razer Raion PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
03000000321500000009000000000000,Razer Serval,+lefty:+a2,-lefty:-a1,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,leftx:a0,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000921200004547000000000000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows,
03000000921200004547000000000000,Retro Bit Sega Genesis Adapter,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b6,x:b3,y:b4,platform:Windows,
03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
03000000830500006020000000000000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000632500007805000000000000,Retro Fighters Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -652,6 +654,7 @@
030000006f0e00001e01000000000000,Rock Candy 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,
030000006f0e00002801000000000000,Rock Candy 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,
030000006f0e00002f01000000000000,Rock Candy 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,
03000000830500000052000000000000,Rockfire CosmoVoyager,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b10,leftshoulder:b6,lefttrigger:b7,misc1:b11,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
03000000830500007030000000000000,Rockfire Space Ranger,a:b0,b:b1,back:b5,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b9,righttrigger:b8,start:b2,x:b3,y:b4,platform:Windows,
03000000050b0000e318000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
03000000050b0000e518000000000000,ROG Chakram,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
@@ -680,6 +683,7 @@
03000000a306000020f6000000000000,Saitek PS2700 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:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000300f00001101000000000000,Saitek Rumble,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
03000000e804000000a0000000000000,Samsung EIGP20,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000bd12000010d1000000000000,Sanwa 4Button,a:b0,b:b1,x:b2,y:b3,dpup:-a1,dpdown:+a1,dpleft:-a0,dpright:+a0,platform:Windows,
03000000c01100000252000000000000,Sanwa Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
03000000c01100004350000000000000,Sanwa Micro Grip P3,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,x:b3,y:b2,platform:Windows,
03000000411200004550000000000000,Sanwa Micro Grip Pro,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a1,righty:a2,start:b9,x:b1,y:b3,platform:Windows,
@@ -688,6 +692,7 @@
03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Windows,
030000009d0d00001130000000000000,Sanwa PlayStation Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000830500006120000000000000,Sanwa Smart Grip II,a:b0,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,x:b1,y:b3,platform:Windows,
03000000630600000201000000000000,Sanwa Virtua Grip,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,x:b0,y:b1,platform:Windows,
03000000c01100000051000000000000,Satechi 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:a5,start:b11,x:b3,y:b4,platform:Windows,
030000004f04000028b3000000000000,Score A,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:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000952e00002577000000000000,Scuf PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
@@ -710,12 +715,12 @@
030000008f0e00000910000000000000,Sony DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
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,
03000000d9040000160f000000000000,Sony PlayStation Adapter,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: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,
03000000d9040000160f000000000000,Sony PlayStation Controller Adapter,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:Windows,
03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
030000004c0500003713000000000000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
@@ -753,21 +758,24 @@
030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
030000004f04000023b3000000000000,Thrustmaster Dual Trigger PlayStation 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:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f0400000ed0000000000000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000008d0000000000000,Thrustmaster Ferrari 150 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,
030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
030000004f04000003d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000003d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:-a3,leftx:a0,lefty:a1,paddle1:b6,paddle2:b7,rightshoulder:b5,rightstick:b11,righttrigger:-a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000008d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,paddle1:b7,paddle2:b6,rightshoulder:b5,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000009d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000011000000200000000000000,ThundeRobot G30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000666600000288000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,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,
03000000666600000488000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,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,
030000004f04000007d0000000000000,TMini,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,
03000000571d00002100000000000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Windows,
03000000571d00002000000000000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000571d00002100000000000000,Tomee NES Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Windows,
03000000571d00002000000000000000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000d62000006000000000000000,Tournament 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,
03000000c01100000055000000000000,Tronsmart,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,
03000000d60600002a00000000000000,Trust 850F,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,x:b3,y:b4,platform:Windows,
030000005f140000c501000000000000,Trust Gamepad,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,
03000000b80500000210000000000000,Trust Gamepad,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,
030000005f1400002a01000000000000,Trust Predator GM1200,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,x:b3,y:b4,platform:Windows,
030000004f04000087b6000000000000,TWCS Throttle,dpdown:b8,dpleft:b9,dpright:b7,dpup:b6,leftstick:b5,lefttrigger:-a5,leftx:a0,lefty:a1,righttrigger:+a5,platform:Windows,
03000000411200000450000000000000,Twin Shock,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows,
03000000d90400000200000000000000,TwinShock PS2 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:Windows,
@@ -812,7 +820,7 @@
03000000c62400000053000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000c6240000fdfa000000000000,Xbox 360 Controller,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,
03000000380700002847000000000000,Xbox 360 Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e040000a102000000000000,Xbox 360 Wireless Receiver,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:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e040000a102000000000000,Xbox 360 Receiver,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:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e0400000a0b000000000000,Xbox Adaptive Controller,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:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000120c00001088000000000000,Xbox Controller,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,
@@ -952,7 +960,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000151900004000000001000000,Flydigi Vader 2,a:b14,b:b15,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Mac OS X,
03000000b40400001124000001040000,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:Mac OS X,
03000000b40400001224000003030000,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:Mac OS X,
03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
03000000790000004618000000010000,GameCube Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
03000000ac0500001a06000002020000,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:Mac OS X,
03000000373500000411000023000000,GameSir X4A Xbox 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:Mac OS X,
03000000ad1b000001f9000000000000,Gamestop BB070 X360 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,
@@ -985,8 +993,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000000d0f00006600000000000000,Horipad FPS Plus 4,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:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f0000ee00000000010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f0000c100000072050000,Horipad 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:Mac OS X,
030000000d0f0000f600000000010000,Horipad Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000242e0000ff0b000000010000,Hyperkin N64 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:a3,start:b9,platform:Mac OS X,
03000000790000004e95000000010000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X,
03000000790000004e95000000010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Mac OS X,
03000000830500006020000000000000,iBuffalo Super Famicom Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,
03000000ef0500000300000000020000,InterAct AxisPad,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Mac OS X,
03000000fd0500000030000010010000,Interact GoPad,a:b3,b:b4,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Mac OS X,
@@ -1002,6 +1011,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006d04000018c2000000000000,Logitech F510,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:Mac OS X,
030000006d04000019c2000005030000,Logitech F710,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:Mac OS X,
030000006d0400001fc2000000000000,Logitech F710,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,
030000006d0400001ac2000004000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000006d04000018c2000000010000,Logitech RumblePad 2,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:Mac OS X,
03000000380700005032000000010000,Mad Catz PS3 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,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:Mac OS X,
@@ -1009,7 +1019,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
0300000049190000020400001b010000,Manba One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,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:Mac OS X,
03000000790000000600000007010000,Marvo GT-004,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:Mac OS X,
030000008f0e00001330000011010000,Mayflash Controller Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X,
030000008f0e00001330000011010000,Mayflash Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X,
03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000242f00007300000000020000,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:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X,
@@ -1030,7 +1040,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c62400002b89000000010000,MOGA XP5A Plus,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:Mac OS X,
03000000853200008906000000010000,Nacon Revolution X Unlimited,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:Mac OS X,
03000000632500007505000000020000,NeoGeo mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000921200004b46000003020000,NES 2-port Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X,
03000000921200004b46000003020000,NES Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Mac OS X,
030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000ec110000e1a7000001010000,Nintendo Switch,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:Mac OS X,
030000007e0500006920000001010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Mac OS X,
@@ -1046,10 +1056,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
03000000100800000300000006010000,PlayStation Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,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,
03000000d620000011a7000010050000,PowerA 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,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000d62000006dca000000010000,PowerA Pro Ex,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:Mac OS X,
03000000100800000300000006010000,PS2 Adapter,a:b2,b:b1,back:b8,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
030000004c0500006802000072050000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
@@ -1078,7 +1088,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
0300000032150000030a000000000000,Razer Wildcat,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,
03000000632500008005000000010000,Redgear,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:Mac OS X,
03000000632500002305000000010000,Redragon Saturn,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:Mac OS X,
03000000921200004547000000020000,Retro Bit Sega Genesis Controller Adapter,a:b0,b:b2,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,lefttrigger:b14,rightshoulder:b10,righttrigger:b4,start:b12,x:b6,y:b8,platform:Mac OS X,
03000000921200004547000000020000,Retro Bit Sega Genesis Adapter,a:b0,b:b2,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,lefttrigger:b14,rightshoulder:b10,righttrigger:b4,start:b12,x:b6,y:b8,platform:Mac OS X,
03000000790000001100000000000000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000790000001100000005010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000830500006020000000010000,Retro Controller,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b8,righttrigger:b9,start:b7,x:b2,y:b3,platform:Mac OS X,
@@ -1112,7 +1122,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000381000003114000000000000,SteelSeries Stratus Duo,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,
03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,
03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,
030000000d0f0000f600000000010000,Switch Hori Pad,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:Mac OS X,
03000000457500002211000000010000,SZMY Power PC Gamepad,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:Mac OS X,
03000000e40a00000307000001000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X,
03000000e40a00000207000001000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X,
@@ -1123,10 +1132,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,
030000004f0400000ed0000000020000,Thrustmaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,
03000000571d00002100000021000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Mac OS X,
03000000571d00002100000021000000,Tomee NES Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Mac OS X,
03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000571d00002000000021000000,Tomee SNES Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000bd12000015d0000000000000,Tomee SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000571d00002000000021000000,Tomee SNES Controller Adapter,a:b0,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X,
030000005f140000c501000000020000,Trust Gamepad,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:Mac OS X,
03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,
03000000632500002605000000010000,Uberwith Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
@@ -1233,6 +1242,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000260000011010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000631000010010000,8BitDo Ultimate,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,
03000000c82d00000631000014010000,8BitDo Ultimate,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,
03000000c82d00000760000011010000,8BitDo Ultimate,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00001130000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001230000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001330000011010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00000a31000014010000,8BitDo Ultimate 2C,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,
03000000c82d00001d30000011010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -1240,12 +1255,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001130000011010000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00000631000010010000,8BitDo Ultimate Wireless,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,
03000000c82d00000631000014010000,8BitDo Ultimate Wireless,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,
03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00001230000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001330000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
@@ -1275,7 +1284,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
03000000050b00000579000011010000,ASUS ROG Kunai 3,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:b36,paddle1:b52,paddle2:b53,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000050b00000679000000010000,ASUS ROG Kunai 3,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:b21,paddle1:b22,paddle2:b23,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000006a0e00001140000010010000,Atari CX Wireless Controller,a:b0,leftx:a0,lefty:a1,platform:Linux,
030000006a0e00001140000010010000,Atari CX Controller,a:b0,leftx:a0,lefty:a1,platform:Linux,
03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
03000000503200000110000011010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
05000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
@@ -1297,6 +1306,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c31100000791000011010000,Be1 GC101 Controller 1.03,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,
030000005e0400008e02000003030000,Be1 GC101 Xbox 360,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,
03000000bc2000004d50000011010000,Beitong A1T2 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000000d0500000308000010010000,Belkin Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
05000000bc2000000055000001000000,Betop AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
030000006b1400000209000011010000,Bigben,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,
@@ -1328,6 +1338,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,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,
06000000d73700000124000000000000,Flydigi Vader 5 Pro,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,misc2:b12,misc3:b13,misc4:b14,misc5:b19,paddle1:b15,paddle2:b17,paddle3:b16,paddle4:b18,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000373500000b10000019010000,GameSir Cyclone 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -1338,7 +1349,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
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,
03000000373500000410000044010000,GameSir T4 Kaleid,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
03000000373500000410000044010000,GameSir T4 Kaleid,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,
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,
03000000373500009410000010010000,GameSir Tegenaria Lite,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger: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,
@@ -1397,8 +1408,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000000d0f00006700000001010000,Horipad One,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,
030000000d0f0000ab01000011010000,Horipad Steam,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,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000000d0f00009601000091000000,Horipad Steam,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,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000000d0f0000f600000001000000,Horipad Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
050000000d0f0000f600000001000000,Horipad Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000341a000005f7000010010000,HuiJia GameCube Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux,
03000000242e0000ff0b000011010000,Hyperkin N64 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:a3,start:b9,platform:Linux,
03000000242e00006a38000010010000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Linux,
@@ -1433,6 +1444,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000bd12000003c0000010010000,Joypad Alpha Shock,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,
03000000242f00002d00000011010000,JYS Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000242f00008a00000011010000,JYS Adapter,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:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,
03000000314100001935000000010000,LeadJoy Xeno Plus,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:a4,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e00000103000000020000,Logic3 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,
030000006d040000d1ca000000000000,Logitech Chillstream,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,
030000006d040000d1ca000011010000,Logitech Chillstream,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,
@@ -1445,8 +1457,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006d0400001fc2000005030000,Logitech F710,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,
030000006d04000018c2000010010000,Logitech RumblePad 2,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,
030000006d04000019c2000010010000,Logitech RumblePad 2,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,
030000006d04000011c2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,
030000006d0400000ac2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux,
030000006d04000011c2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,
05000000380700006652000025010000,Mad Catz CTRLR,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,
03000000380700008532000010010000,Mad Catz Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000380700005032000011010000,Mad Catz Fightpad Pro PS3,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,
@@ -1464,7 +1476,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000380700003847000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000120c00000500000000010000,Manta DualShock 2,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:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
030000008f0e00001330000010010000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
030000008f0e00001330000010010000,Mayflash Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
03000000790000004318000010010000,Mayflash GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000242f00007300000011010000,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:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,
@@ -1519,20 +1531,22 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000f70600000100000000010000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Linux,
030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006b1400000906000014010000,Nacon Asymmetric PS4 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
0300000085320000030c000011010000,Nacon GC100,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000853200000706000012010000,Nacon GC100,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000006b140000010c000010010000,Nacon GC400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
05000000853200000503000000010000,Nacon MGX Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
0300000085320000180d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
0300000085320000160d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux,
03000000790000004518000010010000,Nexilux GameCube Controller Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000790000004518000010010000,NEXiLUX GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,righttrigger:b6,start:b9,x:b3,y:b0,platform:Linux,
060000007e0500003713000000000000,Nintendo 3DS,a:b0,b:b1,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
03000000790000004618000010010000,Nintendo GameCube Controller Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux,
03000000790000004618000010010000,Nintendo GameCube Adapter,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a5~,righty:a2~,start:b9,x:b2,y:b3,platform:Linux,
03000000ec110000e1a7000010010000,Nintendo Switch,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,
030000007e0500006920000011010000,Nintendo Switch 2 Pro Controller,a:b0,b:b1,back:b14,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b12,leftstick:b15,lefttrigger:b13,leftx:a0,lefty:a1~,misc1:b17,misc2:b20,paddle1:b18,paddle2:b19,rightshoulder:b4,rightstick:b7,righttrigger:b5,rightx:a2,righty:a3~,start:b6,x:b2,y:b3,platform:Linux,
060000004e696e74656e646f20537700,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,misc1:b4,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
@@ -1548,7 +1562,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000010000000100000003000000,Nintendo Wii Remote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
050000005a1d00000218000003000000,Nokia GC 5000,a: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,
030000000d0500000308000010010000,Nostromo N45,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
030000007e0500007320000011010000,NSO GameCube Controller,a:b1,b:b3,dpdown:b8,dpleft:b10,dpright:b9,dpup:b11,guide:b16,leftshoulder:b13,lefttrigger:b12,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b4,rightx:a2,righty:a3~,start:b6,x:b0,y:b2,platform:Linux,
030000007e0500001920000011810000,NSO N64 Controller,+rightx:b2,+righty:b3,-rightx:b4,-righty:b10,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b5,rightshoulder:b7,righttrigger:b9,start:b11,platform:Linux,
050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux,
@@ -1560,8 +1573,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000550900001472000011010000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
05000000550900001472000001000000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
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:Linux,
03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
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:Linux,
03000000451300000830000010010000,Nyko CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
19000000010000000100000001010000,ODROID Go 2,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
19000000010000000200000011000000,ODROID Go 2,a:b1,b:b0,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b12,leftshoulder:b4,leftstick:b14,lefttrigger:b13,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b16,start:b17,x:b2,y:b3,platform:Linux,
05000000362800000100000002010000,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:Linux,
@@ -1606,7 +1619,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000d62000000b20000001010000,PowerA 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,
03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,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,
030000006d040000d2ca000011010000,Precision 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,
03000000250900000017000010010000,PS/SS/N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux,
03000000250900000017000010010000,PS SS N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux,
03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000120c0000160e000011010000,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:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -1658,8 +1671,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000009b2800000300000001010000,Raphnet 4nes4snes,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,
030000009b2800004200000001010000,Raphnet Dual NES Adapter,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux,
0300132d9b2800006500000000000000,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,
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,
030000009b2800006500000000000000,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,
030000009b2800006500000001010000,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,
03000000401700007f05000001010000,Raphnet GC and N64 Adapter,a:b5,b:b3,back:b8,dpdown:b10,dpleft:b12,dpright:b11,dpup:b9,leftshoulder:b6,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:-a5,rightx:a2,righty:a3,start:b1,x:b4,y:b2,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,
030000009b2800003c00000001010000,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,
@@ -1725,29 +1739,17 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000632500007505000010010000,ShanWan Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000bc2000000055000010010000,ShanWan Gamepad,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,
03000000341a00000908000010010000,SL6566,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,
03000000250900000500000000010000,SmartJoy 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:Linux,
030000004b2900000430000011000000,Snakebyte 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,
03000000790000002601000011010000,SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
050000004c050000cc09000001000000,Sony DualShock 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000666600006706000000010000,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:Linux,
03000000d9040000160f000000010000,Sony PlayStation Adapter,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:Linux,
030000004c050000da0c000011010000,Sony PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000d9040000160f000000010000,Sony PlayStation Controller Adapter,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:Linux,
03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
030000004c0500003713000011010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000250900000500000000010000,Sony PS2 pad with SmartJoy 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:Linux,
030000005e0400008e02000073050000,Speedlink Torid,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,
030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,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,
03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800004211000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,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,
05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000512000010010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux,
03000000de2800000512000011010000,Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux,
03000000de280000ff11000001000000,Steam Virtual Gamepad,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,
050000004e696d6275732b0000000000,SteelSeries Nimbus Plus,a:b0,b:b1,back:b10,guide:b11,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Linux,
03000000381000003014000075010000,SteelSeries Stratus Duo,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,
@@ -1765,7 +1767,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000008f0e00001431000010010000,SZMY Power PS3,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,
03000000e40a00000307000011010000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux,
03000000e40a00000207000011010000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux,
03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,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:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux,
03000000ba2200000701000001010000,Technology Innovation PlayStation Adapter,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:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux,
03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
@@ -1795,12 +1797,26 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000f00600000300000003000000,TRBot Virtual Joypad,a:b11,b:b12,back:b15,dpdown:b6,dpleft:b3,dpright:b4,dpup:b5,leftshoulder:b17,leftstick:b21,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b22,righttrigger:a2,rightx:a3,righty:a4,start:b16,x:b13,y:b14,platform:Linux,
030000005f140000c501000010010000,Trust Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
06000000f51000000870000003010000,Turtle Beach Recon,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,
03000000100800000100000010010000,Twin PS2 Adapter,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:Linux,
03000000f51000001370000000010000,Turtle Beach ReactR,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
03000000f51000001370000000000000,Turtle Beach ReactR,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
03000000100800000100000010010000,Twin PlayStation Adapter,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:Linux,
03000000c0160000e105000010010000,Ultimate Atari Fight Stick,a:b1,b:b2,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b8,x:b0,y:b3,platform:Linux,
03000000151900005678000010010000,Uniplay U6,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000100800000300000010010000,USB Gamepad,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:Linux,
03000000790000000600000007010000,USB Gamepad,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:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,
03000000790000001100000000010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,
03000000de2800000112000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000112000011010000,Valve Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de2800000211000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000211000011010000,Valve Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de2800004211000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800004211000011010000,Valve Steam Controller,a:b2,b:b3,back:b10,dpdown:b18,dpleft:b19,dpright:b20,dpup:b17,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b16,paddle2:b15,rightshoulder:b7,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de280000fc11000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,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,
05000000de2800000212000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
05000000de2800000511000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
05000000de2800000611000001000000,Valve Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000512000010010000,Valve Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux,
03000000de2800000512000011010000,Valve Steam Deck,a:b3,b:b4,back:b11,dpdown:b17,dpleft:b18,dpright:b19,dpup:b16,guide:b13,leftshoulder:b7,leftstick:b14,lefttrigger:a9,leftx:a0,lefty:a1,misc1:b2,paddle1:b21,paddle2:b20,paddle3:b23,paddle4:b22,rightshoulder:b8,rightstick:b15,righttrigger:a8,rightx:a2,righty:a3,start:b12,x:b5,y:b6,platform:Linux,
03000000790000001a18000011010000,Venom PS4 Arcade Joystick,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,
03000000790000001b18000011010000,Venom PS4 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e00000302000011010000,Victrix Pro Fightstick PS4,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,touchpad:b13,x:b0,y:b3,platform:Linux,
@@ -1829,6 +1845,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000d102000002010000,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,
030000005e040000ea02000000000000,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,
030000005e040000ea02000001030000,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,
050000005e040000200b000013050000,Xbox One 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 One 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,
050000005e040000200b000023050000,Xbox One 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 One 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,
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,
@@ -1866,10 +1886,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
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,
060000005e040000120b000011050000,Xbox Series X 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,
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,
050000005e040000200b000023050000,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,
03000000450c00002043000010010000,XEOX SL6556 BK,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,
05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,
03000000c0160000e105000001010000,XinMo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,
+10 -102
View File
@@ -1,106 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
height="275"
width="570"
version="1.1"
viewBox="0 0 150.81249 72.760419"
id="svg4"
sodipodi:docname="RetroAchievements_logo_square.svg"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
inkscape:export-filename="RetroAchievements_logo_square.png"
inkscape:export-xdpi="960"
inkscape:export-ydpi="960"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs4">
<linearGradient
id="linearGradient6"
inkscape:collect="always">
<stop
style="stop-color:#ca9800;stop-opacity:1;"
offset="0.5"
id="stop6" />
<stop
style="stop-color:#ffe080;stop-opacity:1;"
offset="1"
id="stop7" />
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 570 275">
<defs>
<linearGradient id="a" x1="217.45" y1="974.97" x2="217.45" y2="950.13" gradientTransform="matrix(8.48 0 0 -8.33 -1680.66 8153.87)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#89b4ee"/>
<stop offset=".32" stop-color="#1066dd"/>
</linearGradient>
<linearGradient
id="linearGradient4"
inkscape:collect="always">
<stop
style="stop-color:#87b6f8;stop-opacity:1;"
offset="0"
id="stop4" />
<stop
style="stop-color:#0f65dd;stop-opacity:1;"
offset="0.50065017"
id="stop5" />
<linearGradient id="b" x1="245.24" y1="976.59" x2="245.24" y2="948.51" gradientTransform="matrix(8.48 0 0 -8.33 -1686.3 8153.87)" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#e5cd83"/>
<stop offset=".32" stop-color="#cc9a00"/>
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4"
id="linearGradient5"
x1="229.8"
y1="-556.42499"
x2="229.8"
y2="-531.58502"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient6"
id="linearGradient7"
x1="257.58826"
y1="-529.96503"
x2="257.58826"
y2="-558.04498"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-0.66412404)" />
</defs>
<sodipodi:namedview
id="namedview4"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
showguides="true"
inkscape:zoom="0.54074219"
inkscape:cx="213.59532"
inkscape:cy="218.21859"
inkscape:window-width="1536"
inkscape:window-height="898"
inkscape:window-x="-6"
inkscape:window-y="-6"
inkscape:window-maximized="1"
inkscape:current-layer="svg4" />
<g
transform="matrix(5.6312119,0,0,5.6312119,-392.00615,-696.01846)"
id="g4">
<g
transform="matrix(0.35278,0,0,-0.35278,-4.3083,326.78)"
id="g3">
<g
aria-label="RA"
style="font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal"
transform="matrix(1.1293,0,0,-1.1092,-28.246,-45.784)"
id="g2">
<path
style="font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;fill:url(#linearGradient5)"
d="m 217.38,-553.59 h 11.73 q 1.89,0 3.12,1.14 1.26,1.14 1.26,3.45 0,0.99 -0.33,1.86 -0.33,0.84 -0.93,1.47 -0.57,0.63 -1.38,0.99 -0.81,0.36 -1.74,0.36 h -0.99 l 8.55,15.03 h -4.29 l -5.94,-10.29 v 10.29 h -3.99 v -19.17 h 6.51 q 0.24,0 0.36,-0.18 0.15,-0.18 0.15,-0.39 0,-0.21 -0.15,-0.36 -0.12,-0.18 -0.36,-0.18 h -7.59 v 20.28 h -3.99 z m 12.66,10.26 q 0.87,-0.06 1.68,-0.51 0.84,-0.45 1.47,-1.2 0.63,-0.75 1.02,-1.74 0.39,-1.02 0.39,-2.22 0,-1.23 -0.39,-2.28 -0.39,-1.05 -1.11,-1.8 -0.72,-0.75 -1.74,-1.17 -0.99,-0.42 -2.25,-0.42 h -11.73 v -4.05 h 11.73 q 1.98,0 3.72,0.75 1.74,0.75 3.03,2.07 1.29,1.32 2.01,3.09 0.75,1.77 0.75,3.81 0,2.58 -0.87,4.47 -0.87,1.86 -2.37,3 l 6.84,12.24 h -4.08 z"
id="path1" />
<path
style="font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;fill:url(#linearGradient7)"
d="m 253.50413,-532.8 h 12.45 l -7.62,-21.15 q -0.09,-0.3 -0.54,-0.54 -0.45,-0.24 -0.87,-0.24 -0.48,0 -0.9,0.24 -0.39,0.24 -0.48,0.54 l -8.67,24.66 h -3.99 l 9.27,-26.16 q 0.21,-0.63 0.6,-1.2 0.39,-0.6 0.96,-1.05 0.6,-0.48 1.38,-0.75 0.81,-0.27 1.83,-0.27 1.02,0 1.8,0.27 0.78,0.27 1.35,0.75 0.6,0.45 0.99,1.05 0.39,0.57 0.63,1.2 l 9.27,26.16 h -17.46 z m 0,-1.08 v -1.14 l -1.92,5.73 h -3.63 l 8.25,-23.91 q 0.06,-0.18 0.27,-0.3 0.24,-0.15 0.45,-0.15 0.21,0 0.45,0.15 0.24,0.12 0.3,0.3 l 6.84,19.32 z m 3.42,-11.13 -2.4,7.56 h 4.89 z"
id="path2" />
</g>
</g>
</g>
<path d="M57.83 57.67h99.46c10.68 0 19.5 3.16 26.45 9.49 7.12 6.33 10.68 15.91 10.68 28.73 0 5.5-.93 10.66-2.8 15.49-1.87 4.66-4.49 8.74-7.89 12.24-3.22 3.5-7.12 6.25-11.7 8.24-4.58 2-9.5 3-14.75 3h-8.39l72.5 125.17h-36.38l-50.37-85.7v85.7h-33.83V100.4h55.2c1.36 0 2.37-.5 3.05-1.5.85-1 1.27-2.08 1.27-3.25s-.42-2.17-1.27-3c-.68-1-1.7-1.5-3.05-1.5H91.65v168.9H57.82V57.67Zm107.34 85.45c4.92-.33 9.67-1.75 14.24-4.25 4.75-2.5 8.9-5.83 12.46-9.99s6.44-8.99 8.65-14.49c2.2-5.66 3.31-11.83 3.31-18.49 0-6.83-1.1-13.16-3.31-18.99-2.2-5.83-5.34-10.83-9.41-14.99s-8.99-7.41-14.75-9.74c-5.6-2.33-11.96-3.5-19.08-3.5H57.83V14.95h99.46c11.19 0 21.71 2.08 31.54 6.25s18.4 9.91 25.69 17.24 12.97 15.91 17.04 25.73c4.24 9.83 6.36 20.4 6.36 31.73q0 21.48-7.38 37.23c-4.92 10.33-11.62 18.66-20.1 24.98l58 101.94h-34.59z" style="fill:url(#a)"/>
<path d="M364.13 230.82H469.7L405.09 54.68c-.51-1.67-2.03-3.16-4.58-4.5s-5-2-7.38-2c-2.71 0-5.26.67-7.63 2-2.2 1.33-3.56 2.83-4.07 4.5l-73.51 205.37h-33.83l78.6-217.87c1.19-3.5 2.88-6.83 5.09-9.99 2.2-3.33 4.92-6.25 8.14-8.74 3.39-2.67 7.29-4.75 11.7-6.25 4.58-1.5 9.75-2.25 15.52-2.25s10.85.75 15.26 2.25 8.22 3.58 11.45 6.25c3.39 2.5 6.19 5.41 8.39 8.74 2.2 3.16 3.99 6.5 5.34 9.99l78.6 217.87H364.13zm0-9v-9.49l-16.28 47.72h-30.78l69.95-199.13c.34-1 1.1-1.83 2.29-2.5 1.36-.83 2.63-1.25 3.82-1.25s2.46.42 3.82 1.25c1.36.67 2.2 1.5 2.54 2.5l58 160.9zm29-92.69-20.35 62.96h41.46z" style="fill:url(#b)"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

+333 -59
View File
@@ -32,6 +32,7 @@
#define AFAIL_ZB_ONLY 2
#define AFAIL_RGB_ONLY 3
#define AFAIL_RGB_ONLY_DSB 4
#define AFAIL_RGB_ONLY_SW_Z 5
#endif
#ifndef PS_ATST_NONE
@@ -42,6 +43,13 @@
#define PS_ATST_NOTEQUAL 4
#endif
#ifndef PS_AA1_NONE
#define PS_AA1_NONE 0
#define PS_AA1_LINE 1
#define PS_AA1_TRIANGLE 2
#define PS_AA1_TRIANGLE_SW_Z 3
#endif
#ifndef PS_FST
#define PS_IIP 0
#define PS_FST 0
@@ -93,7 +101,6 @@
#define PS_DITHER_ADJUST 0
#define PS_ZCLAMP 0
#define PS_ZFLOOR 0
#define PS_ZWRITE 0
#define PS_SCANMSK 0
#define PS_AUTOMATIC_LOD 0
#define PS_MANUAL_LOD 0
@@ -102,15 +109,28 @@
#define PS_NO_COLOR1 0
#define PS_DATE 0
#define PS_TEX_IS_FB 0
#define PS_COLOR_FEEDBACK 0
#define PS_DEPTH_FEEDBACK 0
#define PS_AA1 0
#define PS_ABE 0
#endif
#ifndef VS_EXPAND_NONE
#define VS_EXPAND_NONE 0
#define VS_EXPAND_POINT 1
#define VS_EXPAND_LINE 2
#define VS_EXPAND_SPRITE 3
#define VS_EXPAND_LINE_AA1 4
#define VS_EXPAND_TRIANGLE_AA1 5
#endif
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
#define AFAIL_NEEDS_RT (PS_AFAIL == AFAIL_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
#define AFAIL_NEEDS_DEPTH (PS_AFAIL == AFAIL_FB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
#define NEEDS_RT_FOR_AFAIL (PS_AFAIL == AFAIL_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
#define NEEDS_DEPTH_FOR_AFAIL (PS_AFAIL == AFAIL_FB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
#define NEEDS_DEPTH_FOR_ZTST (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
#define NEEDS_DEPTH_FOR_AA1 (PS_AA1 == PS_AA1_TRIANGLE_SW_Z)
#define SW_DEPTH (NEEDS_DEPTH_FOR_AFAIL || NEEDS_DEPTH_FOR_ZTST || NEEDS_DEPTH_FOR_AA1)
#define ZWRITE (PS_ZFLOOR || PS_ZCLAMP || SW_DEPTH)
struct VS_INPUT
{
@@ -134,6 +154,9 @@ struct VS_OUTPUT
#else
nointerpolation float4 c : COLOR0;
#endif
float inv_cov : COLOR1; // We use the inverse to make it simpler to interpolate.
nointerpolation uint interior : COLOR2; // 1 for triangle interior; 0 for edge;
};
struct PS_INPUT
@@ -146,6 +169,8 @@ struct PS_INPUT
#else
nointerpolation float4 c : COLOR0;
#endif
float inv_cov : COLOR1; // We use the inverse to make it simpler to interpolate.
nointerpolation uint interior : COLOR2; // 1 for triangle interior; 0 for edge;
#if (PS_DATE >= 1 && PS_DATE <= 3) || GS_FORWARD_PRIMID
uint primid : SV_PrimitiveID;
#endif
@@ -168,16 +193,16 @@ struct PS_OUTPUT
#endif
#endif
#endif
#if PS_ZWRITE
#if ZWRITE
// In DX12 we do depth feedback loops with a color copy.
#if PS_DEPTH_FEEDBACK && PS_NO_COLOR1 && DX12
#if SW_DEPTH && PS_NO_COLOR1 && DX12
#if NUM_RTS > 0
float depth_color : SV_Target1;
#else
float depth_color : SV_Target0;
#endif
#endif
#if PS_HAS_CONSERVATIVE_DEPTH && !PS_DEPTH_FEEDBACK
#if PS_HAS_CONSERVATIVE_DEPTH && !SW_DEPTH
float depth : SV_DepthLessEqual;
#else
float depth : SV_Depth;
@@ -219,6 +244,155 @@ cbuffer cb1
float RcpScaleFactor;
};
#if (PS_AUTOMATIC_LOD != 1) && (PS_MANUAL_LOD == 1)
float manual_lod(float uv_w)
{
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
float K = LODParams.x;
float L = LODParams.y;
float bias = LODParams.z;
float max_lod = LODParams.w;
float gs_lod = K - log2(abs(uv_w)) * L;
// FIXME max useful ?
//return max(min(gs_lod, max_lod) - bias, 0.0f);
return min(gs_lod, max_lod) - bias;
}
#endif
#if PS_ANISOTROPIC_FILTERING > 1
float4 sample_c_af(float2 uv, float uv_w)
{
// HW sampler will reject bad UVs, match that here.
uv = any(isnan(uv) | isinf(uv)) ? float2(0, 0) : uv;
// Large floating point values risk NaN/Inf values.
// Above this value floats lose decimal precision, so seems a resonable limit for UVs.
uv = clamp(uv, -8388608.0f, 8388608.0f);
// Below taken from https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#7.18.11%20LOD%20Calculations
// With guidance from https://pema.dev/2025/05/09/mipmaps-too-much-detail/
float2 sz;
Texture.GetDimensions(sz.x, sz.y);
float2 dX = ddx(uv) * sz;
float2 dY = ddy(uv) * sz;
// Calculate Ellipse Transform
bool d_zero = length(dX) == 0 || length(dY) == 0;
bool d_par = (dX.x * dY.y - dY.x * dX.y) == 0;
bool d_per = dot(dX, dY) == 0;
bool d_inf_nan = any(isinf(dX) | isinf(dY) | isnan(dX) | isnan(dY));
if (!(d_zero || d_par || d_per || d_inf_nan))
{
float A = dX.y * dX.y + dY.y * dY.y;
float B = -2 * (dX.x * dX.y + dY.x * dY.y);
float C = dX.x * dX.x + dY.x * dY.x;
float f = (dX.x * dY.y - dY.x * dX.y);
float F = f * f;
float p = A - C;
float q = A + C;
float t = sqrt(p * p + B * B);
float2 new_dX = float2(
sqrt(F * (t + p) / (t * (q + t))),
sqrt(F * (t - p) / (t * (q + t))) * sign(B)
);
float2 new_dY = float2(
sqrt(F * (t - p) / (t * (q - t))) * -sign(B),
sqrt(F * (t + p) / (t * (q - t)))
);
d_inf_nan = any(isinf(new_dX) | isinf(new_dY) | isnan(new_dX) | isnan(new_dY));
if (!d_inf_nan)
{
dX = new_dX;
dY = new_dY;
}
}
// Compute AF values
float squared_length_x = dX.x * dX.x + dX.y * dX.y;
float squared_length_y = dY.x * dY.x + dY.y * dY.y;
float determinant = abs(dX.x * dY.y - dX.y * dY.x);
bool is_major_x = squared_length_x > squared_length_y;
float squared_length_major = is_major_x ? squared_length_x : squared_length_y;
float length_major = sqrt(squared_length_major);
float aniso_ratio;
float length_lod;
float2 aniso_line;
if (length_major <= 1.0f)
{
// A zero length_major would result in NaN Lod and break sampling.
// A small length_major would result in aniso_ratio getting clamped to 1.
// Perform isotropic filtering instead.
aniso_ratio = 1.0f;
length_lod = length_major;
aniso_line = float2(0, 0);
}
else
{
float norm_major = 1.0f / length_major;
float2 aniso_line_dir = float2(
(is_major_x ? dX.x : dY.x) * norm_major,
(is_major_x ? dX.y : dY.y) * norm_major
);
aniso_ratio = squared_length_major / determinant;
// Calculate the minor length of the ellipse for Lod, while also clamping the ratio of anisotropy.
if (aniso_ratio > PS_ANISOTROPIC_FILTERING)
{
// ratio is clamped - Lod is based on ratio (preserves area)
aniso_ratio = PS_ANISOTROPIC_FILTERING;
length_lod = length_major / PS_ANISOTROPIC_FILTERING;
}
else
{
// ratio not clamped - Lod is based on area
length_lod = determinant / length_major;
}
// clamp to top Lod
if (length_lod < 1.0f)
aniso_ratio = max(1.0f, aniso_ratio * length_lod);
aniso_ratio = round(aniso_ratio);
aniso_line = aniso_line_dir * 0.5f * length_major * (1.0f / sz);
}
#if PS_AUTOMATIC_LOD == 1
float lod = log2(length_lod);
#elif PS_MANUAL_LOD == 1
float lod = manual_lod(uv_w);
#else
float lod = 0; // No Lod
#endif
float4 colour;
if (aniso_ratio == 1.0f)
colour = Texture.SampleLevel(TextureSampler, uv, lod);
else
{
float4 num = float4(0, 0, 0, 0);
for (int i = 0; i < aniso_ratio; i++)
{
float2 d = -aniso_line + (0.5f + i) * (2.0f * aniso_line) / aniso_ratio;
float2 uv_sample = uv + d;
float4 sample_colour = Texture.SampleLevel(TextureSampler, uv_sample, lod);
num += sample_colour;
}
colour = num / aniso_ratio;
}
return colour;
}
#endif
float4 sample_c(float2 uv, float uv_w, int2 xy)
{
#if PS_TEX_IS_FB == 1
@@ -251,21 +425,12 @@ float4 sample_c(float2 uv, float uv_w, int2 xy)
#endif
#endif
#if PS_AUTOMATIC_LOD == 1
#if PS_ANISOTROPIC_FILTERING > 1
return sample_c_af(uv, uv_w);
#elif PS_AUTOMATIC_LOD == 1
return Texture.Sample(TextureSampler, uv);
#elif PS_MANUAL_LOD == 1
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
float K = LODParams.x;
float L = LODParams.y;
float bias = LODParams.z;
float max_lod = LODParams.w;
float gs_lod = K - log2(abs(uv_w)) * L;
// FIXME max useful ?
//float lod = max(min(gs_lod, max_lod) - bias, 0.0f);
float lod = min(gs_lod, max_lod) - bias;
return Texture.SampleLevel(TextureSampler, uv, lod);
return Texture.SampleLevel(TextureSampler, uv, manual_lod(uv_w));
#else
return Texture.SampleLevel(TextureSampler, uv, 0); // No lod
#endif
@@ -1067,19 +1232,24 @@ PS_OUTPUT ps_main(PS_INPUT input)
input.p.z = floor(input.p.z * exp2(32.0f)) * exp2(-32.0f);
#endif
#if PS_DEPTH_FEEDBACK && (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
#if PS_ZTST == ZTST_GEQUAL
if (input.p.z < DepthTexture.Load(int3(input.p.xy, 0)).r)
discard;
#elif PS_ZTST == ZTST_GREATER
if (input.p.z <= DepthTexture.Load(int3(input.p.xy, 0)).r)
discard;
#endif
#endif // PS_ZTST
#if PS_ZTST == ZTST_GEQUAL
if (input.p.z < DepthTexture.Load(int3(input.p.xy, 0)).r)
discard;
#elif PS_ZTST == ZTST_GREATER
if (input.p.z <= DepthTexture.Load(int3(input.p.xy, 0)).r)
discard;
#endif
float4 C = ps_color(input);
#if PS_FIXED_ONE_A
#if PS_AA1
float cov = clamp(1.0f - abs(input.inv_cov), 0.0f, 1.0f);
#if PS_ABE
if (floor(C.a) == 128.0f) // The coverage is only used if the fragment alpha is 128.
C.a = 128.0f * cov;
#else
C.a = 128.0f * cov;
#endif
#elif PS_FIXED_ONE_A
// AA (Fixed one) will output a coverage of 1.0 as alpha
C.a = 128.0f;
#endif
@@ -1212,10 +1382,7 @@ PS_OUTPUT ps_main(PS_INPUT input)
uint4 denorm_c = uint4(C);
uint2 denorm_TA = uint2(float2(TA.xy) * 255.0f + 0.5f);
C.rb = (float2)float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5));
if (denorm_c.a & 0x80u)
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u));
else
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u));
C.ga = (float2)float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u));
}
else if (PS_SHUFFLE_ACROSS)
{
@@ -1257,19 +1424,17 @@ PS_OUTPUT ps_main(PS_INPUT input)
#endif
// Alpha test with feedback
#if (PS_AFAIL == AFAIL_FB_ONLY) && PS_DEPTH_FEEDBACK && PS_ZWRITE
#if PS_AFAIL == AFAIL_FB_ONLY
if (!atst_pass)
input.p.z = DepthTexture.Load(int3(input.p.xy, 0)).r;
#elif (PS_AFAIL == AFAIL_ZB_ONLY) && PS_COLOR_FEEDBACK
#elif PS_AFAIL == AFAIL_ZB_ONLY
if (!atst_pass)
output.c0 = RtTexture.Load(int3(input.p.xy, 0));
#elif (PS_AFAIL == AFAIL_RGB_ONLY)
#elif PS_AFAIL == AFAIL_RGB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z
if (!atst_pass)
{
#if PS_COLOR_FEEDBACK
output.c0.a = RtTexture.Load(int3(input.p.xy, 0)).a;
#endif
#if PS_DEPTH_FEEDBACK && PS_ZWRITE
output.c0.a = RtTexture.Load(int3(input.p.xy, 0)).a;
#if PS_AFAIL == AFAIL_RGB_ONLY_SW_Z
input.p.z = DepthTexture.Load(int3(input.p.xy, 0)).r;
#endif
}
@@ -1283,8 +1448,13 @@ PS_OUTPUT ps_main(PS_INPUT input)
input.p.z = min(input.p.z, MaxDepthPS);
#endif
#if PS_ZWRITE
#if PS_DEPTH_FEEDBACK && PS_NO_COLOR1 && DX12
#if PS_AA1 == PS_AA1_TRIANGLE_SW_Z
if (!bool(input.interior))
input.p.z = DepthTexture.Load(int3(input.p.xy, 0)).r; // No depth update for triangle edges.
#endif
#if ZWRITE
#if SW_DEPTH && PS_NO_COLOR1 && DX12
// Output color clone for feedback as well as real depth.
output.depth_color = input.p.z;
#endif
@@ -1314,7 +1484,19 @@ cbuffer cb0
float2 TextureOffset;
float2 PointSize;
uint MaxDepth;
uint BaseVertex; // Only used in DX11.
uint _cb0_pad0;
};
#ifdef DX12
cbuffer cb2 : register(b2)
#else
cbuffer cb2
#endif
{
uint BaseVertex;
uint BaseIndex;
uint _cb2_pad0;
uint _cb2_pad1;
};
VS_OUTPUT vs_main(VS_INPUT input)
@@ -1366,10 +1548,14 @@ VS_OUTPUT vs_main(VS_INPUT input)
output.c = input.c;
output.t.z = input.f.r;
// Silence compiler warnings; should be optimized out when not needed.
output.inv_cov = 0.0f;
output.interior = 0;
return output;
}
#if VS_EXPAND != 0
#if VS_EXPAND != VS_EXPAND_NONE
struct VS_RAW_INPUT
{
@@ -1383,14 +1569,19 @@ struct VS_RAW_INPUT
};
StructuredBuffer<VS_RAW_INPUT> vertices : register(t0);
StructuredBuffer<uint> IndexBuffer : register(t5);
uint load_index(uint _i)
{
uint i = _i + BaseIndex;
// i is even => load lower 16 bits; i odd => load upper 16 bits.
uint shift = (i & 1u) << 4u;
return (IndexBuffer.Load(i >> 1u) >> shift) & 0xFFFFu;
}
VS_INPUT load_vertex(uint index)
{
#ifdef DX12
VS_RAW_INPUT raw = vertices.Load(index);
#else
VS_RAW_INPUT raw = vertices.Load(BaseVertex + index);
#endif
VS_INPUT vert;
vert.st = raw.ST;
@@ -1405,7 +1596,7 @@ VS_INPUT load_vertex(uint index)
VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
{
#if VS_EXPAND == 1 // Point
#if VS_EXPAND == VS_EXPAND_POINT
VS_OUTPUT vtx = vs_main(load_vertex(vid >> 2));
@@ -1414,7 +1605,13 @@ VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
return vtx;
#elif VS_EXPAND == 2 // Line
#elif (VS_EXPAND == VS_EXPAND_LINE) || (VS_EXPAND == VS_EXPAND_LINE_AA1)
// The difference between EXPAND_LINE and EXPAND_LINE_AA1
// is that EXPAND_LINE expands in the perpendicular direction while
// EXPAND_LINE_AA1 expands in the Y direction for shallow lines (X dominant)
// and the X direction for steep lines (Y dominant).
// EXPAND_LINE_AA1 also adds coverage to the output.
uint vid_base = vid >> 2;
bool is_bottom = vid & 2;
@@ -1423,20 +1620,31 @@ VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
VS_OUTPUT vtx = vs_main(load_vertex(vid_base));
VS_OUTPUT other = vs_main(load_vertex(vid_other));
float2 line_vector = normalize(vtx.p.xy - other.p.xy);
float2 line_normal = float2(line_vector.y, -line_vector.x);
float2 line_width = (line_normal * PointSize) / 2;
// line_normal is inverted for bottom point
float2 offset = (is_bottom ^ is_right) ? line_width : -line_width;
// Use bottom minus top for delta regardless of which vertex we are expanding.
float2 line_delta = is_bottom ? (vtx.p.xy - other.p.xy) : (other.p.xy - vtx.p.xy);
float2 line_vector = normalize(line_delta);
#if VS_EXPAND == VS_EXPAND_LINE
float2 line_expand = float2(line_vector.y, -line_vector.x);
#elif VS_EXPAND == VS_EXPAND_LINE_AA1
// Expand in y direction for shallow lines and x direction for steep lines.
line_delta /= VertexScale;
float2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? float2(0.0f, 2.0f) : float2(2.0f, 0.0f);
#endif
float2 line_width = (line_expand * PointSize) / 2;
float2 offset = is_right ? line_width : -line_width;
vtx.p.xy += offset;
#if VS_EXPAND == VS_EXPAND_LINE_AA1
vtx.inv_cov = is_right ? 1.0f : -1.0f;
#endif
// Lines will be run as (0 1 2) (1 2 3)
// This means that both triangles will have a point based off the top line point as their first point
// So we don't have to do anything for !IIP
return vtx;
#elif VS_EXPAND == 3 // Sprite
#elif VS_EXPAND == VS_EXPAND_SPRITE
// Sprite points are always in pairs
uint vid_base = vid >> 1;
@@ -1459,6 +1667,72 @@ VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
return vtx;
#elif VS_EXPAND == VS_EXPAND_TRIANGLE_AA1
// Triangles with AA1 are expanded as follows:
// - Vertices 0-2: Interior of triangle (1 triangle).
// - Vertices 3-8: First edge expanded (2 triangles).
// - Vertices 9-14: Second edge expanded (2 triangles).
// - Vertices 15-20: Third edge expanded (2 triangles).
uint prim_id = vid / 21;
uint prim_offset = vid - 21 * prim_id; // range: 0-20
bool interior = prim_offset < 3;
VS_OUTPUT vtx;
if (interior)
{
vtx = vs_main(load_vertex(load_index(3 * prim_id + prim_offset)));
vtx.inv_cov = 0.0f; // Full coverage
vtx.interior = 1;
}
else
{
// Vertex indices for this edge. We need all 3 for determining exterior/interior.
uint prim_offset_edges = prim_offset - 3; // range: 0-17
uint i0 = prim_offset_edges / 6;
uint i1 = (i0 >= 2) ? i0 - 2 : i0 + 1;
uint i2 = (i0 >= 1) ? i0 - 1 : i0 + 2;
uint edge_offset = prim_offset_edges - 6 * i0; // range: 0-5
// Note: order of top/bottom, inside/outside order is arbitrary,
// as long as it assembles into two triangles forming a quad.
bool is_bottom = (2 <= edge_offset) && (edge_offset <= 4);
bool is_outside = edge_offset & 1;
vtx = vs_main(load_vertex(load_index(3 * prim_id + i0)));
VS_OUTPUT other = vs_main(load_vertex(load_index(3 * prim_id + i1)));
VS_OUTPUT opposite = vs_main(load_vertex(load_index(3 * prim_id + i2)));
// Similar expansion to line AA1 except instead of expanding on both sides of
// the line we expand on on the side towards the outside of the triangle.
float2 line_delta = vtx.p.xy - other.p.xy;
float2 line_normal = normalize(float2(line_delta.y, -line_delta.x));
float2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? float2(0.0f, 2.0f) : float2(2.0f, 0.0f);
if ((dot(line_expand, line_normal) >= 0.0f) == (dot(opposite.p.xy - vtx.p.xy, line_normal) >= 0.0f))
{
// Expand direction point towards the interior so flip it.
line_expand = -line_expand;
}
float2 line_width = (line_expand * PointSize) / 2;
if (is_bottom)
vtx = other;
if (is_outside)
{
vtx.p.xy += line_width;
vtx.inv_cov = 1.0f; // No coverage
}
else
{
vtx.inv_cov = 0.0f; // Full coverage
}
vtx.interior = 0;
}
return vtx;
#endif
}
+13 -13
View File
@@ -271,7 +271,7 @@ void ps_convert_rgb5a1_8i()
// 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
@@ -279,7 +279,7 @@ void ps_convert_rgb5a1_8i()
uvec2 subcolumn = (pos & uvec2(0u, 1u));
column.x -= (column.x / 128u) * 64u;
column.y += (column.y / 32u) * 32u;
// Deal with swizzling differences
if ((PSM & 0x8u) != 0u) // PSMCT16S
{
@@ -288,18 +288,18 @@ void ps_convert_rgb5a1_8i()
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32u;
}
if ((pos.x & 64u) != 0u)
{
column.x -= 32u;
}
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
{
column.x ^= 16u;
column.x ^= 16u;
column.y ^= 8u;
}
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
{
column.x ^= 32u;
@@ -313,20 +313,20 @@ void ps_convert_rgb5a1_8i()
column.y -= 16u;
column.x += 32u;
}
if ((pos.x & 96u) != 0u)
{
uint multi = (pos.x & 96u) / 32u;
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96u);
}
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
{
column.x ^= 16u;
column.x ^= 16u;
column.y ^= 8u;
}
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
{
column.x ^= 32u;
@@ -334,7 +334,7 @@ void ps_convert_rgb5a1_8i()
}
}
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;
@@ -353,13 +353,13 @@ void ps_convert_rgb5a1_8i()
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;
SV_Target0 = vec4(float(((green << 5) | red) & 0xFFu) / 255.0f);
}
else
+2 -2
View File
@@ -181,10 +181,10 @@ void ps_main4()
// compared to the new centre line and the high line (with some threshold of about 25 color steps), then reconstruct.
vec3 mhln = hn.rgb - ln.rgb;
vec3 mchn = hn.rgb - cn.rgb;
mhln = max(mhln, -mhln) - motion_thr;
mchn = max(mchn, -mchn) - motion_thr;
float mhln_max = max(max(mhln.x, mhln.y), mhln.z);
float mchn_max = max(max(mchn.x, mchn.y), mchn.z);
+1 -1
View File
@@ -293,7 +293,7 @@ vec3 Bloom(vec2 pos)
vec3 e = Horz5(pos, 2.0);
float wa = BloomScan(pos,-2.0);
float wb = BloomScan(pos,-1.0);
float wb = BloomScan(pos,-1.0);
float wc = BloomScan(pos, 0.0);
float wd = BloomScan(pos, 1.0);
float we = BloomScan(pos, 2.0);
+207 -49
View File
@@ -22,6 +22,7 @@
#define AFAIL_ZB_ONLY 2
#define AFAIL_RGB_ONLY 3
#define AFAIL_RGB_ONLY_DSB 4
#define AFAIL_RGB_ONLY_SW_Z 5
#endif
#ifndef PS_ATST_NONE
@@ -32,6 +33,13 @@
#define PS_ATST_NOTEQUAL 4
#endif
#ifndef PS_AA1_NONE
#define PS_AA1_NONE 0
#define PS_AA1_LINE 1
#define PS_AA1_TRIANGLE 2
#define PS_AA1_TRIANGLE_SW_Z 3
#endif
// TEX_COORD_DEBUG output the uv coordinate as color. It is useful
// to detect bad sampling due to upscaling
//#define TEX_COORD_DEBUG
@@ -46,13 +54,15 @@
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
#define PS_PRIMID_INIT (PS_DATE == 1 || PS_DATE == 2)
#define NEEDS_RT_EARLY (PS_TEX_IS_FB == 1 || PS_DATE >= 5)
#define NEEDS_RT_FOR_AFAIL (PS_AFAIL == PS_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
#define NEEDS_DEPTH_FOR_AFAIL (PS_AFAIL == AFAIL_FB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
#define NEEDS_RT_FOR_AFAIL (PS_AFAIL == PS_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
#define NEEDS_DEPTH_FOR_AFAIL (PS_AFAIL == AFAIL_FB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
#define NEEDS_DEPTH_FOR_ZTST (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
#define NEEDS_DEPTH_FOR_AA1 (PS_AA1 == PS_AA1_TRIANGLE_SW_Z)
#define NEEDS_RT (NEEDS_RT_EARLY || NEEDS_RT_FOR_AFAIL || (!PS_PRIMID_INIT && (PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW)) || PS_COLOR_FEEDBACK)
#define NEEDS_TEX (PS_TFX != 4)
#define NEEDS_DEPTH (PS_DEPTH_FEEDBACK && (NEEDS_DEPTH_FOR_AFAIL || NEEDS_DEPTH_FOR_ZTST))
#define SW_DEPTH (NEEDS_DEPTH_FOR_AFAIL || NEEDS_DEPTH_FOR_ZTST || NEEDS_DEPTH_FOR_AA1)
#define ZWRITE (SW_DEPTH || PS_ZCLAMP || PS_ZFLOOR)
layout(std140, binding = 0) uniform cb21
{
@@ -95,6 +105,9 @@ in SHADER
#else
flat vec4 c;
#endif
float inv_cov; // We use the inverse to make it simpler to interpolate.
flat uint interior; // 1 for triangle interior; 0 for edge;
} PSin;
#define TARGET_0_QUALIFIER out
@@ -124,7 +137,7 @@ in SHADER
// Depth feedback mode 2 is for depth as color.
// Use FB fetch for the feedback if it's available.
#if NEEDS_DEPTH && PS_NO_COLOR1 && (DEPTH_FEEDBACK_SUPPORT == 2)
#if SW_DEPTH && PS_NO_COLOR1 && (DEPTH_FEEDBACK_SUPPORT == 2)
#if HAS_FRAMEBUFFER_FETCH
layout(location = 1) inout float SV_Target1;
#else
@@ -148,11 +161,11 @@ layout(binding = 3) uniform sampler2D img_prim_min;
// Depth feedback mode 1 binds depth buffer directly as a texture.
// Depth feedback mode 2 (depth as color) can use FB fetch for the feedback,
// in which case we don't need to explicitly bind depth as a texture.
#if (DEPTH_FEEDBACK_SUPPORT == 1 || (DEPTH_FEEDBACK_SUPPORT == 2 && !HAS_FRAMEBUFFER_FETCH)) && NEEDS_DEPTH
#if (DEPTH_FEEDBACK_SUPPORT == 1 || (DEPTH_FEEDBACK_SUPPORT == 2 && !HAS_FRAMEBUFFER_FETCH)) && SW_DEPTH
layout(binding = 4) uniform sampler2D DepthSampler;
#endif
#if PS_ZWRITE && PS_HAS_CONSERVATIVE_DEPTH && !NEEDS_DEPTH
#if ZWRITE && PS_HAS_CONSERVATIVE_DEPTH && !SW_DEPTH
layout(depth_less) out float gl_FragDepth;
#endif
@@ -169,7 +182,7 @@ vec4 sample_from_rt()
vec4 sample_from_depth()
{
#if !NEEDS_DEPTH
#if !SW_DEPTH
return vec4(0.0);
#elif HAS_FRAMEBUFFER_FETCH && (DEPTH_FEEDBACK_SUPPORT == 2)
return SV_Target1;
@@ -180,6 +193,154 @@ vec4 sample_from_depth()
#if NEEDS_TEX
#if (PS_AUTOMATIC_LOD != 1) && (PS_MANUAL_LOD == 1)
float manual_lod(float uv_w)
{
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
float K = LODParams.x;
float L = LODParams.y;
float bias = LODParams.z;
float max_lod = LODParams.w;
float gs_lod = K - log2(abs(uv_w)) * L;
// FIXME max useful ?
//return max(min(gs_lod, max_lod) - bias, 0.0f);
return min(gs_lod, max_lod) - bias;
}
#endif
#if PS_ANISOTROPIC_FILTERING > 1
vec4 sample_c_af(vec2 uv, float uv_w)
{
// HW sampler will reject bad UVs, match that here.
uv = (any(isnan(uv)) || any(isinf(uv))) ? vec2(0, 0) : uv;
// Large floating point values risk NaN/Inf values.
// Above this value floats lose decimal precision, so seems a resonable limit for UVs.
uv = clamp(uv, -8388608.0f, 8388608.0f);
// Below taken from https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#7.18.11%20LOD%20Calculations
// With guidance from https://pema.dev/2025/05/09/mipmaps-too-much-detail/
vec2 sz = textureSize(TextureSampler, 0);
vec2 dX = dFdx(uv) * sz;
vec2 dY = dFdy(uv) * sz;
// Calculate Ellipse Transform
bool d_zero = length(dX) == 0 || length(dY) == 0;
bool d_par = (dX.x * dY.y - dY.x * dX.y) == 0;
bool d_per = dot(dX, dY) == 0;
bool d_inf_nan = any(isinf(dX)) || any(isinf(dY)) || any(isnan(dX)) || any(isnan(dY));
if (!(d_zero || d_par || d_per || d_inf_nan))
{
float A = dX.y * dX.y + dY.y * dY.y;
float B = -2 * (dX.x * dX.y + dY.x * dY.y);
float C = dX.x * dX.x + dY.x * dY.x;
float f = (dX.x * dY.y - dY.x * dX.y);
float F = f * f;
float p = A - C;
float q = A + C;
float t = sqrt(p * p + B * B);
vec2 new_dX = vec2(
sqrt(F * (t + p) / (t * (q + t))),
sqrt(F * (t - p) / (t * (q + t))) * sign(B)
);
vec2 new_dY = vec2(
sqrt(F * (t - p) / (t * (q - t))) * -sign(B),
sqrt(F * (t + p) / (t * (q - t)))
);
d_inf_nan = any(isinf(new_dX)) || any(isinf(new_dY)) || any(isnan(new_dX)) || any(isnan(new_dY));
if (!d_inf_nan)
{
dX = new_dX;
dY = new_dY;
}
}
// Compute AF values
float squared_length_x = dX.x * dX.x + dX.y * dX.y;
float squared_length_y = dY.x * dY.x + dY.y * dY.y;
float determinant = abs(dX.x * dY.y - dX.y * dY.x);
bool is_major_x = squared_length_x > squared_length_y;
float squared_length_major = is_major_x ? squared_length_x : squared_length_y;
float length_major = sqrt(squared_length_major);
float aniso_ratio;
float length_lod;
vec2 aniso_line;
if (length_major <= 1.0f)
{
// A zero length_major would result in NaN Lod and break sampling.
// A small length_major would result in aniso_ratio getting clamped to 1.
// Perform isotropic filtering instead.
aniso_ratio = 1.0f;
length_lod = length_major;
aniso_line = vec2(0, 0);
}
else
{
float norm_major = 1.0f / length_major;
vec2 aniso_line_dir = vec2(
(is_major_x ? dX.x : dY.x) * norm_major,
(is_major_x ? dX.y : dY.y) * norm_major
);
aniso_ratio = squared_length_major / determinant;
// Calculate the minor length of the ellipse for Lod, while also clamping the ratio of anisotropy.
if (aniso_ratio > PS_ANISOTROPIC_FILTERING)
{
// ratio is clamped - Lod is based on ratio (preserves area)
aniso_ratio = PS_ANISOTROPIC_FILTERING;
length_lod = length_major / PS_ANISOTROPIC_FILTERING;
}
else
{
// ratio not clamped - Lod is based on area
length_lod = determinant / length_major;
}
// clamp to top Lod
if (length_lod < 1.0f)
aniso_ratio = max(1.0f, aniso_ratio * length_lod);
aniso_ratio = round(aniso_ratio);
aniso_line = aniso_line_dir * 0.5f * length_major * (1.0f / sz);
}
#if PS_AUTOMATIC_LOD == 1
float lod = log2(length_lod);
#elif PS_MANUAL_LOD == 1
float lod = manual_lod(uv_w);
#else
float lod = 0; // No Lod
#endif
vec4 colour;
if (aniso_ratio == 1.0f)
colour = textureLod(TextureSampler, uv, lod);
else
{
vec4 num = vec4(0, 0, 0, 0);
for (int i = 0; i < aniso_ratio; i++)
{
vec2 d = -aniso_line + (0.5f + i) * (2.0f * aniso_line) / aniso_ratio;
vec2 uv_sample = uv + d;
vec4 sample_colour = textureLod(TextureSampler, uv_sample, lod);
num += sample_colour;
}
colour = num / aniso_ratio;
}
return colour;
}
#endif
vec4 sample_c(vec2 uv)
{
#if PS_TEX_IS_FB == 1
@@ -203,21 +364,12 @@ vec4 sample_c(vec2 uv)
#endif
#endif
#if PS_AUTOMATIC_LOD == 1
#if PS_ANISOTROPIC_FILTERING > 1
return sample_c_af(uv, PSin.t_float.w);
#elif PS_AUTOMATIC_LOD == 1
return texture(TextureSampler, uv);
#elif PS_MANUAL_LOD == 1
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
float K = LODParams.x;
float L = LODParams.y;
float bias = LODParams.z;
float max_lod = LODParams.w;
float gs_lod = K - log2(abs(PSin.t_float.w)) * L;
// FIXME max useful ?
//float lod = max(min(gs_lod, max_lod) - bias, 0.0f);
float lod = min(gs_lod, max_lod) - bias;
return textureLod(TextureSampler, uv, lod);
return textureLod(TextureSampler, uv, manual_lod(PSin.t_float.w));
#else
return textureLod(TextureSampler, uv, 0.0f); // No lod
#endif
@@ -331,8 +483,8 @@ uvec4 sample_4_index(vec4 uv)
c.y = sample_c(uv.zy).a;
c.z = sample_c(uv.xw).a;
c.w = sample_c(uv.zw).a;
#if PS_RTA_SRC_CORRECTION
#if PS_RTA_SRC_CORRECTION
uvec4 i = uvec4(round(c * 128.25f)); // Denormalize value
#else
uvec4 i = uvec4(c * 255.5f); // Denormalize value
@@ -760,10 +912,10 @@ vec4 ps_color()
T.b = float((denorm_c_before.g << 1) & 0xF8u);
T.a = float(denorm_c_before.g & 0x80u);
#endif
T.a = ((T.a >= 127.5f) ? TA.y : ((PS_AEM == 0 || any(bvec3(ivec3(T.rgb) & ivec3(0xF8)))) ? TA.x : 0.0f)) * 255.0f;
#endif
vec4 C = tfx(T, PSin.c);
fog(C, PSin.t_float.z);
@@ -894,7 +1046,7 @@ float As = As_rgba.a;
RT.a = float(denorm_rt.g & 0x80u);
#endif
#endif
// Let the compiler do its jobs !
#if PS_COLCLIP_HW == 1
vec3 Cd = trunc(RT.rgb * 65535.0f);
@@ -1040,15 +1192,13 @@ void ps_main()
input_z = floor(input_z * exp2(32.0f)) * exp2(-32.0f);
#endif
#if NEEDS_DEPTH && (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
#if PS_ZTST == ZTST_GEQUAL
if (input_z < sample_from_depth().r)
discard;
#elif PS_ZTST == ZTST_GREATER
if (input_z <= sample_from_depth().r)
discard;
#endif
#endif // PS_ZTST
#if PS_ZTST == ZTST_GEQUAL
if (input_z < sample_from_depth().r)
discard;
#elif PS_ZTST == ZTST_GREATER
if (input_z <= sample_from_depth().r)
discard;
#endif
#if PS_SCANMSK & 2
// fail depth test on prohibited lines
@@ -1099,7 +1249,15 @@ void ps_main()
vec4 C = ps_color();
#if PS_FIXED_ONE_A
#if PS_AA1
float cov = clamp(1.0f - abs(PSin.inv_cov), 0.0f, 1.0f);
#if PS_ABE
if (floor(C.a) == 128.0f) // The coverage is only used if the fragment alpha is 128.
C.a = 128.0f * cov;
#else
C.a = 128.0f * cov;
#endif
#elif PS_FIXED_ONE_A
// AA (Fixed one) will output a coverage of 1.0 as alpha
C.a = 128.0f;
#endif
@@ -1170,12 +1328,9 @@ void ps_main()
#elif PS_READ16_SRC
uvec4 denorm_c = uvec4(C);
uvec2 denorm_TA = uvec2(vec2(TA.xy) * 255.0f + 0.5f);
C.rb = vec2(float((denorm_c.r >> 3) | (((denorm_c.g >> 3) & 0x7u) << 5)));
if (bool(denorm_c.a & 0x80u))
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.y & 0x80u)));
else
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u)));
C.ga = vec2(float((denorm_c.g >> 6) | ((denorm_c.b >> 3) << 2) | (denorm_TA.x & 0x80u)));
#elif PS_SHUFFLE_ACROSS
#if(PS_PROCESS_BA == SHUFFLE_READWRITE && PS_PROCESS_RG == SHUFFLE_READWRITE)
C.br = C.rb;
@@ -1213,21 +1368,19 @@ void ps_main()
#else
C.rgb = C.rgb / 255.0f;
#endif
// Alpha test with feedback
#if (PS_AFAIL == AFAIL_FB_ONLY) && NEEDS_DEPTH && PS_ZWRITE
#if PS_AFAIL == AFAIL_FB_ONLY
if (!atst_pass)
input_z = sample_from_depth().r;
#elif (PS_AFAIL == AFAIL_ZB_ONLY) && NEEDS_RT
#elif PS_AFAIL == AFAIL_ZB_ONLY
if (!atst_pass)
C = sample_from_rt();
#elif (PS_AFAIL == AFAIL_RGB_ONLY)
#elif (PS_AFAIL == AFAIL_RGB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
if (!atst_pass)
{
#if NEEDS_RT
C.a = sample_from_rt().a;
#endif
#if NEEDS_DEPTH && PS_ZWRITE
#if PS_AFAIL == AFAIL_RGB_ONLY_SW_Z
input_z = sample_from_depth().r;
#endif
}
@@ -1246,8 +1399,13 @@ void ps_main()
input_z = min(input_z, MaxDepthPS);
#endif
#if PS_ZWRITE
#if NEEDS_DEPTH && PS_NO_COLOR1 && (DEPTH_FEEDBACK_SUPPORT == 2)
#if PS_AA1 == PS_AA1_TRIANGLE_SW_Z
if (!bool(PSin.interior))
input_z = sample_from_depth().r; // No depth update for triangle edges.
#endif
#if ZWRITE
#if SW_DEPTH && PS_NO_COLOR1 && (DEPTH_FEEDBACK_SUPPORT == 2)
// Depth as color write. For depth as color feedback we write to both
// color copy and real depth to avoid having to copy back to real depth.
// Warning: do not write SV_Target1 until the end since the value might
+116 -10
View File
@@ -18,6 +18,15 @@ layout(std140, binding = 1) uniform cb20
#ifdef VERTEX_SHADER
#ifndef VS_EXPAND_NONE
#define VS_EXPAND_NONE 0
#define VS_EXPAND_POINT 1
#define VS_EXPAND_LINE 2
#define VS_EXPAND_SPRITE 3
#define VS_EXPAND_LINE_AA1 4
#define VS_EXPAND_TRIANGLE_AA1 5
#endif
out SHADER
{
vec4 t_float;
@@ -27,11 +36,13 @@ out SHADER
#else
flat vec4 c;
#endif
float inv_cov; // We use the inverse to make it simpler to interpolate.
flat uint interior; // 1 for triangle interior; 0 for edge.
} VSout;
const float exp_min32 = exp2(-32.0f);
#if VS_EXPAND == 0
#if VS_EXPAND == VS_EXPAND_NONE
layout(location = 0) in vec2 i_st;
layout(location = 2) in vec4 i_c;
@@ -98,10 +109,23 @@ struct RawVertex
uint FOG;
};
layout(std140, binding = 4) uniform cb22
{
uint BaseVertex;
uint BaseIndex;
uint pad_cb22_0;
uint pad_cb22_1;
};
layout(std140, binding = 2) readonly buffer VertexBuffer {
RawVertex vertex_buffer[];
};
// Warning: use std430 instead of std140 so that the ints are tightly packed.
layout(std430, binding = 3) readonly buffer IndexBuffer {
uint index_buffer[];
};
struct ProcessedVertex
{
vec4 p;
@@ -110,9 +134,17 @@ struct ProcessedVertex
vec4 c;
};
uint load_index(uint _i)
{
uint i = _i + BaseIndex;
// i is even => load lower 16 bits; i odd => load upper 16 bits.
uint shift = (i & 1u) << 4u;
return (index_buffer[i >> 1u] >> shift) & 0xFFFFu;
}
ProcessedVertex load_vertex(uint index)
{
RawVertex rvtx = vertex_buffer[index];
RawVertex rvtx = vertex_buffer[BaseVertex + index];
vec2 i_st = rvtx.ST;
vec4 i_c = vec4(uvec4(bitfieldExtract(rvtx.RGBA, 0, 8), bitfieldExtract(rvtx.RGBA, 8, 8),
@@ -156,14 +188,14 @@ void main()
uint vid = uint(gl_VertexID);
#if VS_EXPAND == 1 // Point
#if VS_EXPAND == VS_EXPAND_POINT
vtx = load_vertex(vid >> 2);
vtx.p.x += ((vid & 1u) != 0u) ? PointSize.x : 0.0f;
vtx.p.y += ((vid & 2u) != 0u) ? PointSize.y : 0.0f;
#elif VS_EXPAND == 2 // Line
#elif (VS_EXPAND == VS_EXPAND_LINE) || (VS_EXPAND == VS_EXPAND_LINE_AA1)
uint vid_base = vid >> 2;
bool is_bottom = (vid & 2u) != 0u;
@@ -172,18 +204,29 @@ void main()
vtx = load_vertex(vid_base);
ProcessedVertex other = load_vertex(vid_other);
vec2 line_vector = normalize(vtx.p.xy - other.p.xy);
vec2 line_normal = vec2(line_vector.y, -line_vector.x);
vec2 line_width = (line_normal * PointSize) / 2;
// line_normal is inverted for bottom point
vec2 offset = ((uint(is_bottom) ^ uint(is_right)) != 0u) ? line_width : -line_width;
// Use bottom minus top for delta regardless of which vertex we are expanding.
vec2 line_delta = is_bottom ? (vtx.p.xy - other.p.xy) : (other.p.xy - vtx.p.xy);
vec2 line_vector = normalize(line_delta);
#if VS_EXPAND == VS_EXPAND_LINE
vec2 line_expand = vec2(line_vector.y, -line_vector.x);
#elif VS_EXPAND == VS_EXPAND_LINE_AA1
// Expand in y direction for shallow lines and x direction for steep lines.
line_delta /= VertexScale;
vec2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? vec2(0.0f, 2.0f) : vec2(2.0f, 0.0f);
#endif
vec2 line_width = (line_expand * PointSize) / 2;
vec2 offset = is_right ? line_width : -line_width;
vtx.p.xy += offset;
#if VS_EXPAND == VS_EXPAND_LINE_AA1
VSout.inv_cov = is_right ? 1.0f : -1.0f;
#endif
// Lines will be run as (0 1 2) (1 2 3)
// This means that both triangles will have a point based off the top line point as their first point
// So we don't have to do anything for !IIP
#elif VS_EXPAND == 3 // Sprite
#elif VS_EXPAND == VS_EXPAND_SPRITE
// Sprite points are always in pairs
uint vid_base = vid >> 1;
@@ -204,6 +247,69 @@ void main()
vtx.t_float.y = is_bottom ? lt.t_float.y : vtx.t_float.y;
vtx.t_int.yw = is_bottom ? lt.t_int.yw : vtx.t_int.yw;
#elif VS_EXPAND == VS_EXPAND_TRIANGLE_AA1
// Triangles with AA1 are expanded as follows:
// - Vertices 0-2: Interior of triangle (1 triangle).
// - Vertices 3-8: First edge expanded (2 triangles).
// - Vertices 9-14: Second edge expanded (2 triangles).
// - Vertices 15-20: Third edge expanded (2 triangles).
uint prim_id = vid / 21;
uint prim_offset = vid - 21 * prim_id; // range: 0-20
bool interior = prim_offset < 3;
if (interior)
{
vtx = load_vertex(load_index(3 * prim_id + prim_offset));
VSout.inv_cov = 0.0f; // Full coverage
VSout.interior = 1;
}
else
{
// Vertex indices for this edge. We need all 3 for determining exterior/interior.
uint prim_offset_edges = prim_offset - 3; // range: 0-17
uint i0 = prim_offset_edges / 6;
uint i1 = (i0 >= 2) ? i0 - 2 : i0 + 1;
uint i2 = (i0 >= 1) ? i0 - 1 : i0 + 2;
uint edge_offset = prim_offset_edges - 6 * i0; // range: 0-5
// Note: order of top/bottom, inside/outside order is arbitrary,
// as long as it assembles into two triangles forming a quad.
bool is_bottom = (2 <= edge_offset) && (edge_offset <= 4);
bool is_outside = (edge_offset & 1) != 0;
vtx = load_vertex(load_index(3 * prim_id + i0));
ProcessedVertex other = load_vertex(load_index(3 * prim_id + i1));
ProcessedVertex opposite = load_vertex(load_index(3 * prim_id + i2));
// Similar expansion to line AA1 except instead of expanding on both sides of
// the line we expand on on the side towards the outside of the triangle.
vec2 line_delta = vtx.p.xy - other.p.xy;
vec2 line_normal = normalize(vec2(line_delta.y, -line_delta.x));
vec2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? vec2(0.0f, 2.0f) : vec2(2.0f, 0.0f);
if ((dot(line_expand, line_normal) >= 0.0f) == (dot(opposite.p.xy - vtx.p.xy, line_normal) >= 0.0f))
{
// Expand direction point towards the interior so flip it.
line_expand = -line_expand;
}
vec2 line_width = (line_expand * PointSize) / 2;
if (is_bottom)
vtx = other;
if (is_outside)
{
vtx.p.xy += line_width;
VSout.inv_cov = 1.0f; // No coverage
}
else
{
VSout.inv_cov = 0.0f; // Full coverage
}
VSout.interior = 0;
}
#endif
gl_Position = vtx.p;
+13 -13
View File
@@ -347,7 +347,7 @@ void ps_convert_rgb5a1_8i()
// 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
@@ -355,7 +355,7 @@ void ps_convert_rgb5a1_8i()
uvec2 subcolumn = (pos & uvec2(0u, 1u));
column.x -= (column.x / 128u) * 64u;
column.y += (column.y / 32u) * 32u;
// Deal with swizzling differences
if ((PSM & 0x8u) != 0u) // PSMCT16S
{
@@ -364,18 +364,18 @@ void ps_convert_rgb5a1_8i()
column.y += 32u; // 4 columns high times 4 to get bottom 4 blocks
column.x &= ~32u;
}
if ((pos.x & 64u) != 0u)
{
column.x -= 32u;
}
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
{
column.x ^= 16u;
column.x ^= 16u;
column.y ^= 8u;
}
if ((PSM & 0x30u) != 0u) // PSMZ16S - Untested but hopefully ok if anything uses it.
{
column.x ^= 32u;
@@ -389,20 +389,20 @@ void ps_convert_rgb5a1_8i()
column.y -= 16u;
column.x += 32u;
}
if ((pos.x & 96u) != 0u)
{
uint multi = (pos.x & 96u) / 32u;
column.y += 16u * multi; // 4 columns high times 4 to get bottom 4 blocks
column.x -= (pos.x & 96u);
}
if (((pos.x & 16u) != 0u) != ((pos.y & 16u) != 0u))
{
column.x ^= 16u;
column.x ^= 16u;
column.y ^= 8u;
}
if ((PSM & 0x30u) != 0u) // PSMZ16 - Untested but hopefully ok if anything uses it.
{
column.x ^= 32u;
@@ -410,7 +410,7 @@ void ps_convert_rgb5a1_8i()
}
}
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;
@@ -429,13 +429,13 @@ void ps_convert_rgb5a1_8i()
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;
o_col0 = vec4(float(((green << 5) | red) & 0xFFu) / 255.0f);
}
else
+2 -2
View File
@@ -202,10 +202,10 @@ void ps_main4()
// compared to the new centre line and the high line (with some threshold of about 25 color steps), then reconstruct.
vec3 mhln = hn.rgb - ln.rgb;
vec3 mchn = hn.rgb - cn.rgb;
mhln = max(mhln, -mhln) - motion_thr;
mchn = max(mchn, -mchn) - motion_thr;
float mhln_max = max(max(mhln.x, mhln.y), mhln.z);
float mchn_max = max(max(mchn.x, mchn.y), mchn.z);
+1 -1
View File
@@ -264,7 +264,7 @@ vec3 Bloom(vec2 pos)
vec3 e = Horz5(pos, 2.0);
float wa = BloomScan(pos,-2.0);
float wb = BloomScan(pos,-1.0);
float wb = BloomScan(pos,-1.0);
float wc = BloomScan(pos, 0.0);
float wd = BloomScan(pos, 1.0);
float we = BloomScan(pos, 2.0);
+320 -56
View File
@@ -7,6 +7,15 @@
#if defined(VERTEX_SHADER)
#ifndef VS_EXPAND_NONE
#define VS_EXPAND_NONE 0
#define VS_EXPAND_POINT 1
#define VS_EXPAND_LINE 2
#define VS_EXPAND_SPRITE 3
#define VS_EXPAND_LINE_AA1 4
#define VS_EXPAND_TRIANGLE_AA1 5
#endif
layout(std140, set = 0, binding = 0) uniform cb0
{
vec2 VertexScale;
@@ -28,9 +37,12 @@ layout(location = 0) out VSOutput
#else
flat vec4 c;
#endif
float inv_cov; // We use the inverse to make it simpler to interpolate.
flat uint interior; // 1 for triangle interior; 0 for edge;
} vsOut;
#if VS_EXPAND == 0
#if VS_EXPAND == VS_EXPAND_NONE
layout(location = 0) in vec2 a_st;
layout(location = 1) in uvec4 a_c;
@@ -99,10 +111,23 @@ struct RawVertex
uint FOG;
};
layout(push_constant) uniform cb2
{
uint BaseVertex;
uint BaseIndex;
uint pad_cb2_0;
uint pad_cb2_1;
};
layout(std140, set = 0, binding = 2) readonly buffer VertexBuffer {
RawVertex vertex_buffer[];
};
// Warning: use std430 instead of std140 so that the ints are tightly packed.
layout(std430, set = 0, binding = 3) readonly buffer IndexBuffer {
uint index_buffer[];
};
struct ProcessedVertex
{
vec4 p;
@@ -111,9 +136,17 @@ struct ProcessedVertex
vec4 c;
};
uint load_index(uint _i)
{
uint i = _i + BaseIndex;
// i is even => load lower 16 bits; i odd => load upper 16 bits.
uint shift = (i & 1u) << 4u;
return (index_buffer[i >> 1u] >> shift) & 0xFFFFu;
}
ProcessedVertex load_vertex(uint index)
{
RawVertex rvtx = vertex_buffer[index];
RawVertex rvtx = vertex_buffer[BaseVertex + index];
vec2 a_st = rvtx.ST;
uvec4 a_c = uvec4(bitfieldExtract(rvtx.RGBA, 0, 8), bitfieldExtract(rvtx.RGBA, 8, 8),
@@ -161,36 +194,47 @@ void main()
ProcessedVertex vtx;
uint vid = uint(gl_VertexIndex);
#if VS_EXPAND == 1 // Point
#if VS_EXPAND == VS_EXPAND_POINT
vtx = load_vertex(vid >> 2);
vtx.p.x += ((vid & 1u) != 0u) ? PointSize.x : 0.0f;
vtx.p.x += ((vid & 1u) != 0u) ? PointSize.x : 0.0f;
vtx.p.y += ((vid & 2u) != 0u) ? PointSize.y : 0.0f;
#elif VS_EXPAND == 2 // Line
#elif (VS_EXPAND == VS_EXPAND_LINE) || (VS_EXPAND == VS_EXPAND_LINE_AA1)
uint vid_base = vid >> 2;
bool is_bottom = (vid & 2u) != 0u;
bool is_right = (vid & 1u) != 0u;
uint vid_other = is_bottom ? vid_base - 1 : vid_base + 1;
vtx = load_vertex(vid_base);
ProcessedVertex other = load_vertex(vid_other);
vec2 line_vector = normalize(vtx.p.xy - other.p.xy);
vec2 line_normal = vec2(line_vector.y, -line_vector.x);
vec2 line_width = (line_normal * PointSize) / 2;
// line_normal is inverted for bottom point
vec2 offset = ((uint(is_bottom) ^ uint(is_right)) != 0u) ? line_width : -line_width;
// Use bottom minus top for delta regardless of which vertex we are expanding.
vec2 line_delta = is_bottom ? (vtx.p.xy - other.p.xy) : (other.p.xy - vtx.p.xy);
vec2 line_vector = normalize(line_delta);
#if VS_EXPAND == VS_EXPAND_LINE
vec2 line_expand = vec2(line_vector.y, -line_vector.x);
#elif VS_EXPAND == VS_EXPAND_LINE_AA1
// Expand in y direction for shallow lines and x direction for steep lines.
line_delta /= VertexScale;
vec2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? vec2(0.0f, 2.0f) : vec2(2.0f, 0.0f);
#endif
vec2 line_width = (line_expand * PointSize) / 2;
vec2 offset = is_right ? line_width : -line_width;
vtx.p.xy += offset;
#if VS_EXPAND == VS_EXPAND_LINE_AA1
vsOut.inv_cov = is_right ? 1.0f : -1.0f;
#endif
// Lines will be run as (0 1 2) (1 2 3)
// This means that both triangles will have a point based off the top line point as their first point
// So we don't have to do anything for !IIP
#elif VS_EXPAND == 3 // Sprite
#elif VS_EXPAND == VS_EXPAND_SPRITE
// Sprite points are always in pairs
uint vid_base = vid >> 1;
@@ -211,6 +255,69 @@ void main()
vtx.t.y = is_bottom ? lt.t.y : vtx.t.y;
vtx.ti.yw = is_bottom ? lt.ti.yw : vtx.ti.yw;
#elif VS_EXPAND == VS_EXPAND_TRIANGLE_AA1
// Triangles with AA1 are expanded as follows:
// - Vertices 0-2: Interior of triangle (1 triangle).
// - Vertices 3-8: First edge expanded (2 triangles).
// - Vertices 9-14: Second edge expanded (2 triangles).
// - Vertices 15-20: Third edge expanded (2 triangles).
uint prim_id = vid / 21;
uint prim_offset = vid - 21 * prim_id; // range: 0-20
bool interior = prim_offset < 3;
if (interior)
{
vtx = load_vertex(load_index(3 * prim_id + prim_offset));
vsOut.inv_cov = 0.0f; // Full coverage
vsOut.interior = 1;
}
else
{
// Vertex indices for this edge. We need all 3 for determining exterior/interior.
uint prim_offset_edges = prim_offset - 3; // range: 0-17
uint i0 = prim_offset_edges / 6;
uint i1 = (i0 >= 2) ? i0 - 2 : i0 + 1;
uint i2 = (i0 >= 1) ? i0 - 1 : i0 + 2;
uint edge_offset = prim_offset_edges - 6 * i0; // range: 0-5
// Note: order of top/bottom, inside/outside order is arbitrary,
// as long as it assembles into two triangles forming a quad.
bool is_bottom = (2 <= edge_offset) && (edge_offset <= 4);
bool is_outside = (edge_offset & 1) != 0;
vtx = load_vertex(load_index(3 * prim_id + i0));
ProcessedVertex other = load_vertex(load_index(3 * prim_id + i1));
ProcessedVertex opposite = load_vertex(load_index(3 * prim_id + i2));
// Similar expansion to line AA1 except instead of expanding on both sides of
// the line we expand on on the side towards the outside of the triangle.
vec2 line_delta = vtx.p.xy - other.p.xy;
vec2 line_normal = normalize(vec2(line_delta.y, -line_delta.x));
vec2 line_expand = abs(line_delta.x) >= abs(line_delta.y) ? vec2(0.0f, 2.0f) : vec2(2.0f, 0.0f);
if ((dot(line_expand, line_normal) >= 0.0f) == (dot(opposite.p.xy - vtx.p.xy, line_normal) >= 0.0f))
{
// Expand direction point towards the interior so flip it.
line_expand = -line_expand;
}
vec2 line_width = (line_expand * PointSize) / 2;
if (is_bottom)
vtx = other;
if (is_outside)
{
vtx.p.xy += line_width;
vsOut.inv_cov = 1.0f; // No coverage
}
else
{
vsOut.inv_cov = 0.0f; // Full coverage
}
vsOut.interior = 0;
}
#endif
gl_Position = vtx.p;
@@ -256,6 +363,7 @@ void main()
#define AFAIL_ZB_ONLY 2
#define AFAIL_RGB_ONLY 3
#define AFAIL_RGB_ONLY_DSB 4
#define AFAIL_RGB_ONLY_SW_Z 5
#endif
#ifndef PS_ATST_NONE
@@ -266,6 +374,13 @@ void main()
#define PS_ATST_NOTEQUAL 4
#endif
#ifndef PS_AA1_NONE
#define PS_AA1_NONE 0
#define PS_AA1_LINE 1
#define PS_AA1_TRIANGLE 2
#define PS_AA1_TRIANGLE_SW_Z 3
#endif
#ifndef PS_FST
#define PS_FST 0
#define PS_WMS 0
@@ -310,7 +425,6 @@ void main()
#define PS_DITHER_ADJUST 0
#define PS_ZCLAMP 0
#define PS_ZFLOOR 0
#define PS_ZWRITE 0
#define PS_SCANMSK 0
#define PS_AUTOMATIC_LOD 0
#define PS_MANUAL_LOD 0
@@ -319,19 +433,19 @@ void main()
#define PS_NO_COLOR1 0
#define PS_DATE 0
#define PS_TEX_IS_FB 0
#define PS_COLOR_FEEDBACK 0
#define PS_DEPTH_FEEDBACK 0
#endif
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
#define AFAIL_NEEDS_RT (PS_AFAIL == AFAIL_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
#define AFAIL_NEEDS_DEPTH (PS_AFAIL == AFAIL_FB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
#define AFAIL_NEEDS_RT (PS_AFAIL == AFAIL_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
#define AFAIL_NEEDS_DEPTH (PS_AFAIL == AFAIL_FB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
#define ZTST_NEEDS_DEPTH (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
#define AA1_NEEDS_DEPTH (PS_AA1 == PS_AA1_TRIANGLE_SW_Z)
#define PS_FEEDBACK_LOOP_IS_NEEDED_RT (PS_TEX_IS_FB == 1 || AFAIL_NEEDS_RT || PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW || (PS_DATE >= 5) || PS_COLOR_FEEDBACK)
#define PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH (PS_DEPTH_FEEDBACK && (AFAIL_NEEDS_DEPTH || ZTST_NEEDS_DEPTH))
#define PS_FEEDBACK_LOOP_IS_NEEDED_RT (PS_TEX_IS_FB == 1 || AFAIL_NEEDS_RT || PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW || (PS_DATE >= 5))
#define PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH (AFAIL_NEEDS_DEPTH || ZTST_NEEDS_DEPTH || AA1_NEEDS_DEPTH)
#define ZWRITE (PS_ZCLAMP || PS_ZFLOOR || PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH)
#define NEEDS_TEX (PS_TFX != 4)
@@ -366,6 +480,8 @@ layout(location = 0) in VSOutput
#else
flat vec4 c;
#endif
float inv_cov; // We use the inverse to make it simpler to interpolate.
flat uint interior; // 1 for triangle interior; 0 for edge;
} vsIn;
#if !PS_NO_COLOR && !PS_NO_COLOR1
@@ -411,12 +527,160 @@ layout(set = 1, binding = 1) uniform texture2D Palette;
layout(set = 1, binding = 3) uniform texture2D PrimMinTexture;
#endif
#if PS_ZWRITE && !PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
#if ZWRITE && !PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
layout(depth_less) out float gl_FragDepth;
#endif
#if NEEDS_TEX
#if (PS_AUTOMATIC_LOD != 1) && (PS_MANUAL_LOD == 1)
float manual_lod(float uv_w)
{
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
float K = LODParams.x;
float L = LODParams.y;
float bias = LODParams.z;
float max_lod = LODParams.w;
float gs_lod = K - log2(abs(uv_w)) * L;
// FIXME max useful ?
//return max(min(gs_lod, max_lod) - bias, 0.0f);
return min(gs_lod, max_lod) - bias;
}
#endif
#if PS_ANISOTROPIC_FILTERING > 1
vec4 sample_c_af(vec2 uv, float uv_w)
{
// HW sampler will reject bad UVs, match that here.
uv = (any(isnan(uv)) || any(isinf(uv))) ? vec2(0, 0) : uv;
// Large floating point values risk NaN/Inf values.
// Above this value floats lose decimal precision, so seems a resonable limit for UVs.
uv = clamp(uv, -8388608.0f, 8388608.0f);
// Below taken from https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#7.18.11%20LOD%20Calculations
// With guidance from https://pema.dev/2025/05/09/mipmaps-too-much-detail/
vec2 sz = textureSize(Texture, 0);
vec2 dX = dFdx(uv) * sz;
vec2 dY = dFdy(uv) * sz;
// Calculate Ellipse Transform
bool d_zero = length(dX) == 0 || length(dY) == 0;
bool d_par = (dX.x * dY.y - dY.x * dX.y) == 0;
bool d_per = dot(dX, dY) == 0;
bool d_inf_nan = any(isinf(dX)) || any(isinf(dY)) || any(isnan(dX)) || any(isnan(dY));
if (!(d_zero || d_par || d_per || d_inf_nan))
{
float A = dX.y * dX.y + dY.y * dY.y;
float B = -2 * (dX.x * dX.y + dY.x * dY.y);
float C = dX.x * dX.x + dY.x * dY.x;
float f = (dX.x * dY.y - dY.x * dX.y);
float F = f * f;
float p = A - C;
float q = A + C;
float t = sqrt(p * p + B * B);
vec2 new_dX = vec2(
sqrt(F * (t + p) / (t * (q + t))),
sqrt(F * (t - p) / (t * (q + t))) * sign(B)
);
vec2 new_dY = vec2(
sqrt(F * (t - p) / (t * (q - t))) * -sign(B),
sqrt(F * (t + p) / (t * (q - t)))
);
d_inf_nan = any(isinf(new_dX)) || any(isinf(new_dY)) || any(isnan(new_dX)) || any(isnan(new_dY));
if (!d_inf_nan)
{
dX = new_dX;
dY = new_dY;
}
}
// Compute AF values
float squared_length_x = dX.x * dX.x + dX.y * dX.y;
float squared_length_y = dY.x * dY.x + dY.y * dY.y;
float determinant = abs(dX.x * dY.y - dX.y * dY.x);
bool is_major_x = squared_length_x > squared_length_y;
float squared_length_major = is_major_x ? squared_length_x : squared_length_y;
float length_major = sqrt(squared_length_major);
float aniso_ratio;
float length_lod;
vec2 aniso_line;
if (length_major <= 1.0f)
{
// A zero length_major would result in NaN Lod and break sampling.
// A small length_major would result in aniso_ratio getting clamped to 1.
// Perform isotropic filtering instead.
aniso_ratio = 1.0f;
length_lod = length_major;
aniso_line = vec2(0, 0);
}
else
{
float norm_major = 1.0f / length_major;
vec2 aniso_line_dir = vec2(
(is_major_x ? dX.x : dY.x) * norm_major,
(is_major_x ? dX.y : dY.y) * norm_major
);
aniso_ratio = squared_length_major / determinant;
// Calculate the minor length of the ellipse for Lod, while also clamping the ratio of anisotropy.
if (aniso_ratio > PS_ANISOTROPIC_FILTERING)
{
// ratio is clamped - Lod is based on ratio (preserves area)
aniso_ratio = PS_ANISOTROPIC_FILTERING;
length_lod = length_major / PS_ANISOTROPIC_FILTERING;
}
else
{
// ratio not clamped - Lod is based on area
length_lod = determinant / length_major;
}
// clamp to top Lod
if (length_lod < 1.0f)
aniso_ratio = max(1.0f, aniso_ratio * length_lod);
aniso_ratio = round(aniso_ratio);
aniso_line = aniso_line_dir * 0.5f * length_major * (1.0f / sz);
}
#if PS_AUTOMATIC_LOD == 1
float lod = log2(length_lod);
#elif PS_MANUAL_LOD == 1
float lod = manual_lod(uv_w);
#else
float lod = 0; // No Lod
#endif
vec4 colour;
if (aniso_ratio == 1.0f)
colour = textureLod(Texture, uv, lod);
else
{
vec4 num = vec4(0, 0, 0, 0);
for (int i = 0; i < aniso_ratio; i++)
{
vec2 d = -aniso_line + (0.5f + i) * (2.0f * aniso_line) / aniso_ratio;
vec2 uv_sample = uv + d;
vec4 sample_colour = textureLod(Texture, uv_sample, lod);
num += sample_colour;
}
colour = num / aniso_ratio;
}
return colour;
}
#endif
vec4 sample_c(vec2 uv)
{
#if PS_TEX_IS_FB
@@ -440,21 +704,12 @@ vec4 sample_c(vec2 uv)
#endif
#endif
#if PS_AUTOMATIC_LOD == 1
#if PS_ANISOTROPIC_FILTERING > 1
return sample_c_af(uv, vsIn.t.w);
#elif PS_AUTOMATIC_LOD == 1
return texture(Texture, uv);
#elif PS_MANUAL_LOD == 1
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
float K = LODParams.x;
float L = LODParams.y;
float bias = LODParams.z;
float max_lod = LODParams.w;
float gs_lod = K - log2(abs(vsIn.t.w)) * L;
// FIXME max useful ?
//float lod = max(min(gs_lod, max_lod) - bias, 0.0f);
float lod = min(gs_lod, max_lod) - bias;
return textureLod(Texture, uv, lod);
return textureLod(Texture, uv, manual_lod(vsIn.t.w));
#else
return textureLod(Texture, uv, 0); // No lod
#endif
@@ -575,7 +830,7 @@ uvec4 sample_4_index(vec4 uv)
c.w = sample_c(uv.zw).a;
// Denormalize value
#if PS_RTA_SRC_CORRECTION
uvec4 i = uvec4(round(c * 128.25f));
#else
@@ -1010,10 +1265,10 @@ vec4 ps_color()
T.b = float((denorm_c_before.g << 1) & 0xF8u);
T.a = float(denorm_c_before.g & 0x80u);
#endif
T.a = ((T.a >= 127.5f) ? TA.y : ((PS_AEM == 0 || any(bvec3(ivec3(T.rgb) & ivec3(0xF8)))) ? TA.x : 0.0f)) * 255.0f;
#endif
vec4 C = tfx(T, vsIn.c);
C = fog(C, vsIn.t.z);
@@ -1045,7 +1300,7 @@ void ps_dither(inout vec3 C, float As)
#endif
float value = DitherMatrix[fpos.y & 3][fpos.x & 3];
// The idea here is we add on the dither amount adjusted by the alpha before it goes to the hw blend
// so after the alpha blend the resulting value should be the same as (Cs - Cd) * As + Cd + Dither.
#if PS_DITHER_ADJUST
@@ -1057,7 +1312,7 @@ void ps_dither(inout vec3 C, float As)
value *= Alpha > 0.0f ? min(1.0f / Alpha, 1.0f) : 1.0f;
#endif
#if PS_ROUND_INV
C -= value;
#else
@@ -1131,7 +1386,7 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
#else
float Ad = trunc(RT.a * 255.0f + 0.1f) / 128.0f;
#endif
#if PS_SHUFFLE && PS_FEEDBACK_LOOP_IS_NEEDED_RT
uvec4 denorm_rt = uvec4(RT);
#if (PS_PROCESS_BA & SHUFFLE_WRITE)
@@ -1291,15 +1546,13 @@ void main()
input_z = floor(input_z * exp2(32.0f)) * exp2(-32.0f);
#endif
#if PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH && (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
#if PS_ZTST == ZTST_GEQUAL
if (input_z < sample_from_depth().r)
discard;
#elif PS_ZTST == ZTST_GREATER
if (input_z <= sample_from_depth().r)
discard;
#endif
#endif // PS_ZTST
#if PS_ZTST == ZTST_GEQUAL
if (input_z < sample_from_depth().r)
discard;
#elif PS_ZTST == ZTST_GREATER
if (input_z <= sample_from_depth().r)
discard;
#endif
#if PS_SCANMSK & 2
// fail depth test on prohibited lines
@@ -1349,7 +1602,15 @@ void main()
vec4 C = ps_color();
#if PS_FIXED_ONE_A
#if PS_AA1
float cov = clamp(1.0f - abs(vsIn.inv_cov), 0.0f, 1.0f);
#if PS_ABE
if (floor(C.a) == 128.0f) // The coverage is only used if the fragment alpha is 128.
C.a = 128.0f * cov;
#else
C.a = 128.0f * cov;
#endif
#elif PS_FIXED_ONE_A
// AA (Fixed one) will output a coverage of 1.0 as alpha
C.a = 128.0f;
#endif
@@ -1466,19 +1727,17 @@ void main()
#endif
// Alpha test with feedback
#if (PS_AFAIL == AFAIL_FB_ONLY) && PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH && PS_ZWRITE
#if PS_AFAIL == AFAIL_FB_ONLY
if (!atst_pass)
input_z = sample_from_depth().r;
#elif (PS_AFAIL == AFAIL_ZB_ONLY) && PS_FEEDBACK_LOOP_IS_NEEDED_RT
#elif PS_AFAIL == AFAIL_ZB_ONLY
if (!atst_pass)
o_col0 = sample_from_rt();
#elif (PS_AFAIL == AFAIL_RGB_ONLY)
#elif (PS_AFAIL == AFAIL_RGB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY_SW_Z)
if (!atst_pass)
{
#if PS_FEEDBACK_LOOP_IS_NEEDED_RT
o_col0.a = sample_from_rt().a;
#endif
#if PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH && PS_ZWRITE
#if PS_AFAIL == AFAIL_RGB_ONLY_SW_Z
input_z = sample_from_depth().r;
#endif
}
@@ -1489,7 +1748,12 @@ void main()
input_z = min(input_z, MaxDepthPS);
#endif
#if PS_ZWRITE
#if PS_AA1 == PS_AA1_TRIANGLE_SW_Z
if (!bool(vsIn.interior))
input_z = sample_from_depth().r; // No depth update for triangle edges.
#endif
#if ZWRITE
gl_FragDepth = input_z;
#endif
#endif // PS_DATE
+3
View File
@@ -247,6 +247,9 @@ if (MSVC)
else()
set(DEFAULT_WARNINGS -Wall -Wextra -Wno-unused-function -Wno-unused-parameter -Wno-missing-field-initializers)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
list(APPEND DEFAULT_WARNINGS -Wno-attributes)
endif()
if (USE_PGO_GENERATE OR USE_PGO_OPTIMIZE)
add_compile_options("-fprofile-dir=${CMAKE_SOURCE_DIR}/profile")
+1 -1
View File
@@ -18,7 +18,7 @@ find_package(Zstd 1.5.5 REQUIRED)
find_package(LZ4 REQUIRED)
find_package(WebP REQUIRED) # v1.3.2, spews an error on Linux because no pkg-config.
find_package(SDL3 3.2.6 REQUIRED)
find_package(Freetype 2.12 REQUIRED)
find_package(Freetype 2.10 REQUIRED) # 2.10 is the first with COLRv0 support, which we need for rendering emoji
find_package(plutovg 1.1.0 REQUIRED)
find_package(plutosvg 0.0.7 REQUIRED)
find_package(ryml REQUIRED)
-5
View File
@@ -226,11 +226,6 @@ namespace PageFaultHandler
#ifdef ARCH_ARM64
void HostSys::FlushInstructionCache(void* address, u32 size)
{
__builtin___clear_cache(reinterpret_cast<char*>(address), reinterpret_cast<char*>(address) + size);
}
[[maybe_unused]] static bool IsStoreInstruction(const void* ptr)
{
u32 bits;
+12
View File
@@ -3,6 +3,8 @@
#include "MemoryInterface.h"
#include <bit>
template <MemoryAccessType Value>
Value MemoryInterface::Read(u32 address, bool* valid)
{
@@ -24,6 +26,10 @@ Value MemoryInterface::Read(u32 address, bool* valid)
.hi = static_cast<s64>(value.hi),
};
}
else if constexpr (std::is_same_v<Value, float>)
return std::bit_cast<float>(Read32(address, valid));
else if constexpr (std::is_same_v<Value, double>)
return std::bit_cast<double>(Read64(address, valid));
else
return Value(0);
}
@@ -48,6 +54,10 @@ bool MemoryInterface::Write(u32 address, Value value)
unsigned_value.hi = static_cast<u64>(value.hi);
return Write128(address, unsigned_value);
}
else if constexpr (std::is_same_v<Value, float>)
return Write32(address, std::bit_cast<u32>(value));
else if constexpr (std::is_same_v<Value, double>)
return Write64(address, std::bit_cast<u64>(value));
else
return false;
}
@@ -135,4 +145,6 @@ EXPLICITLY_INSTANTIATE_TEMPLATES(u64)
EXPLICITLY_INSTANTIATE_TEMPLATES(s64)
EXPLICITLY_INSTANTIATE_TEMPLATES(u128)
EXPLICITLY_INSTANTIATE_TEMPLATES(s128)
EXPLICITLY_INSTANTIATE_TEMPLATES(float)
EXPLICITLY_INSTANTIATE_TEMPLATES(double)
#undef EXPLICITLY_INSTANTIATE_TEMPLATES
+4 -1
View File
@@ -12,12 +12,15 @@ concept MemoryAccessType = std::is_same_v<Value, u8> || std::is_same_v<Value, s8
std::is_same_v<Value, u16> || std::is_same_v<Value, s16> ||
std::is_same_v<Value, u32> || std::is_same_v<Value, s32> ||
std::is_same_v<Value, u64> || std::is_same_v<Value, s64> ||
std::is_same_v<Value, u128> || std::is_same_v<Value, s128>;
std::is_same_v<Value, u128> || std::is_same_v<Value, s128> ||
std::is_same_v<Value, float> || std::is_same_v<Value, double>;
/// Interface for reading/writing guest memory.
class MemoryInterface
{
public:
virtual ~MemoryInterface() {}
virtual u8 Read8(u32 address, bool* valid = nullptr) = 0;
virtual u16 Read16(u32 address, bool* valid = nullptr) = 0;
virtual u32 Read32(u32 address, bool* valid = nullptr) = 0;
+6
View File
@@ -799,6 +799,12 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
s_perf_enable = true;
continue;
}
else if (CHECK_ARG("-debugdevice"))
{
Console.WriteLn("Enable debug device");
s_settings_interface.SetBoolValue("EmuCore/GS", "UseDebugDevice", true);
continue;
}
else if (CHECK_ARG("--"))
{
no_more_args = true;
+4 -5
View File
@@ -450,7 +450,7 @@ void DebuggerWindow::onStepInto()
cpu->resumeCpu();
});
repaint();
update();
}
void DebuggerWindow::onStepOver()
@@ -500,7 +500,7 @@ void DebuggerWindow::onStepOver()
cpu->resumeCpu();
});
this->repaint();
update();
}
void DebuggerWindow::onStepOut()
@@ -525,8 +525,7 @@ void DebuggerWindow::onStepOut()
cpu->getPC(),
cpu->getRegister(0, 31),
cpu->getRegister(0, 29),
thread->EntryPoint(),
thread->StackTop());
thread->EntryPoint());
break;
}
}
@@ -541,7 +540,7 @@ void DebuggerWindow::onStepOut()
cpu->resumeCpu();
});
this->repaint();
update();
}
void DebuggerWindow::changeEvent(QEvent* event)
+20 -20
View File
@@ -86,7 +86,7 @@ bool DisassemblyView::fromJson(const JsonValueWrapper& json)
if (show_instruction_bytes != json.value().MemberEnd() && show_instruction_bytes->value.IsBool())
m_showInstructionBytes = show_instruction_bytes->value.GetBool();
repaint();
update();
return true;
}
@@ -204,7 +204,7 @@ void DisassemblyView::contextRestoreInstruction()
{
u32 address = start + i * 4;
if (original_instructions[i].has_value())
cpu->write32(address, *original_instructions[i]);
cpu->Write32(address, *original_instructions[i]);
}
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
});
@@ -222,7 +222,7 @@ void DisassemblyView::contextRunToCursor()
void DisassemblyView::contextJumpToCursor()
{
cpu().setPc(m_selectedAddressStart);
this->repaint();
update();
}
void DisassemblyView::contextToggleBreakpoint()
@@ -332,11 +332,11 @@ void DisassemblyView::contextStubFunction()
const QPointer<DisassemblyView> view(this);
Host::RunOnCPUThread([view, address, cpu = &cpu()] {
const u32 first_instruction = cpu->read32(address);
const u32 second_instruction = cpu->read32(address + 4);
const u32 first_instruction = cpu->Read32(address);
const u32 second_instruction = cpu->Read32(address + 4);
cpu->write32(address, 0x03E00008); // jr ra
cpu->write32(address + 4, 0x00000000); // nop
cpu->Write32(address, 0x03E00008); // jr ra
cpu->Write32(address + 4, 0x00000000); // nop
QtHost::RunOnUIThread([view, address, first_instruction, second_instruction]() {
if (!view)
@@ -364,8 +364,8 @@ void DisassemblyView::contextRestoreFunction()
m_stubbedFunctions.erase(stub);
Host::RunOnCPUThread([address, cpu = &cpu(), first_instruction, second_instruction] {
cpu->write32(address, first_instruction);
cpu->write32(address + 4, second_instruction);
cpu->Write32(address, first_instruction);
cpu->Write32(address + 4, second_instruction);
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
});
}
@@ -378,7 +378,7 @@ void DisassemblyView::contextRestoreFunction()
void DisassemblyView::contextShowInstructionBytes()
{
m_showInstructionBytes = !m_showInstructionBytes;
this->repaint();
update();
}
QString DisassemblyView::GetLineDisasm(u32 address)
@@ -610,7 +610,7 @@ void DisassemblyView::mousePressEvent(QMouseEvent* event)
m_selectedAddressEnd = selectedAddress;
}
}
this->repaint();
update();
}
}
@@ -637,7 +637,7 @@ void DisassemblyView::wheelEvent(QWheelEvent* event)
{
m_visibleStart -= 4;
}
this->repaint();
update();
}
void DisassemblyView::keyPressEvent(QKeyEvent* event)
@@ -709,7 +709,7 @@ void DisassemblyView::keyPressEvent(QKeyEvent* event)
break;
}
this->repaint();
update();
}
void DisassemblyView::openContextMenu(QPoint pos)
@@ -919,7 +919,7 @@ inline QString DisassemblyView::DisassemblyStringFromAddress(u32 address, QFont
if (showOpcode)
{
const u32 opcode = cpu().read32(address);
const u32 opcode = cpu().Read32(address);
lineString = lineString.arg(QtUtils::FilledQStringFromValue(opcode, 16));
}
@@ -989,7 +989,7 @@ QString DisassemblyView::FetchSelectionInfo(SelectionInfo selInfo)
}
else // INSTRUCTIONHEX
{
infoBlock += FilledQStringFromValue(cpu().read32(i), 16);
infoBlock += FilledQStringFromValue(cpu().Read32(i), 16);
}
}
return infoBlock;
@@ -1014,9 +1014,9 @@ void DisassemblyView::gotoAddress(u32 address, bool should_set_focus)
m_selectedAddressStart = destAddress;
m_selectedAddressEnd = destAddress;
this->repaint();
update();
if (should_set_focus)
this->setFocus();
setFocus();
}
void DisassemblyView::toggleBreakpoint(u32 address)
@@ -1034,7 +1034,7 @@ void DisassemblyView::toggleBreakpoint(u32 address)
QtHost::RunOnUIThread([view, cpu]() {
BreakpointModel::getInstance(*cpu)->refreshData();
if (view)
view->repaint();
view->update();
});
});
}
@@ -1050,8 +1050,8 @@ void DisassemblyView::setInstructions(u32 start, u32 end, u32 value)
for (u32 i = 0; i < count; i++)
{
const u32 address = start + i * 4;
original_instructions.emplace_back(cpu->read32(address));
cpu->write32(address, value);
original_instructions.emplace_back(cpu->Read32(address));
cpu->Write32(address, value);
}
QtHost::RunOnUIThread([view, start, count, original_instructions = std::move(original_instructions)]() {
+4 -45
View File
@@ -27,7 +27,6 @@ MemorySearchView::MemorySearchView(const DebuggerViewParameters& parameters)
: DebuggerView(parameters, MONOSPACE_FONT)
{
m_ui.setupUi(this);
this->repaint();
m_ui.listSearchResults->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_ui.btnSearch, &QPushButton::clicked, this, &MemorySearchView::onSearchButtonClicked);
@@ -112,46 +111,6 @@ void MemorySearchView::onListSearchResultsContextMenu(QPoint pos)
menu->popup(m_ui.listSearchResults->viewport()->mapToGlobal(pos));
}
template <typename T>
T readValueAtAddress(DebugInterface* cpu, u32 addr);
template <>
float readValueAtAddress<float>(DebugInterface* cpu, u32 addr)
{
return std::bit_cast<float>(cpu->read32(addr));
}
template <>
double readValueAtAddress<double>(DebugInterface* cpu, u32 addr)
{
return std::bit_cast<double>(cpu->read64(addr));
}
template <typename T>
T readValueAtAddress(DebugInterface* cpu, u32 addr)
{
T val = 0;
switch (sizeof(T))
{
case sizeof(u8):
val = cpu->read8(addr);
break;
case sizeof(u16):
val = cpu->read16(addr);
break;
case sizeof(u32):
{
val = cpu->read32(addr);
break;
}
case sizeof(u64):
{
val = cpu->read64(addr);
break;
}
}
return val;
}
template <typename T>
static bool memoryValueComparator(SearchComparison searchComparison, T searchValue, T readValue)
{
@@ -294,7 +253,7 @@ void searchWorker(DebugInterface* cpu, std::vector<SearchResult>& searchResults,
if (!cpu->isValidAddress(addr))
continue;
T readValue = readValueAtAddress<T>(cpu, addr);
T readValue = cpu->Read<T>(addr);
if (handleSearchComparison(searchComparison, addr, nullptr, searchValue, readValue))
{
searchResults.push_back(MemorySearchView::SearchResult(addr, QVariant::fromValue(readValue), searchType));
@@ -308,7 +267,7 @@ void searchWorker(DebugInterface* cpu, std::vector<SearchResult>& searchResults,
if (!cpu->isValidAddress(addr))
return true;
const auto readValue = readValueAtAddress<T>(cpu, addr);
const auto readValue = cpu->Read<T>(addr);
const bool doesMatch = handleSearchComparison(searchComparison, addr, &searchResult, searchValue, readValue);
if (doesMatch)
@@ -325,7 +284,7 @@ static bool compareByteArrayAtAddress(DebugInterface* cpu, SearchComparison sear
const bool isNotOperator = searchComparison == SearchComparison::NotEquals;
for (qsizetype i = 0; i < value.length(); i++)
{
const char nextByte = cpu->read8(addr + i);
const char nextByte = cpu->Read8(addr + i);
switch (searchComparison)
{
case SearchComparison::Equals:
@@ -383,7 +342,7 @@ static QByteArray readArrayAtAddress(DebugInterface* cpu, u32 address, u32 lengt
QByteArray readArray;
for (u32 i = address; i < address + length; i++)
{
readArray.append(cpu->read8(i));
readArray.append(cpu->Read8(i));
}
return readArray;
}
+28 -28
View File
@@ -119,7 +119,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
{
case MemoryViewType::BYTE:
{
const u8 val = static_cast<u8>(cpu.read8(thisSegmentsStart, valid));
const u8 val = cpu.Read8(thisSegmentsStart, &valid);
if (penDefault && val == 0)
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "??");
@@ -127,7 +127,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
}
case MemoryViewType::BYTEHW:
{
const u16 val = convertEndian<u16>(static_cast<u16>(cpu.read16(thisSegmentsStart, valid)));
const u16 val = convertEndian<u16>(cpu.Read16(thisSegmentsStart, &valid));
if (penDefault && val == 0)
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "????");
@@ -135,7 +135,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
}
case MemoryViewType::WORD:
{
const u32 val = convertEndian<u32>(cpu.read32(thisSegmentsStart, valid));
const u32 val = convertEndian<u32>(cpu.Read32(thisSegmentsStart, &valid));
if (penDefault && val == 0)
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "????????");
@@ -143,7 +143,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
}
case MemoryViewType::DWORD:
{
const u64 val = convertEndian<u64>(cpu.read64(thisSegmentsStart, valid));
const u64 val = convertEndian<u64>(cpu.Read64(thisSegmentsStart, &valid));
if (penDefault && val == 0)
painter.setPen(QColor::fromRgb(145, 145, 155)); // ZERO BYTE COLOUR
painter.drawText(valX, y + (rowHeight * i), valid ? FilledQStringFromValue(val, 16) : "????????????????");
@@ -151,7 +151,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
}
case MemoryViewType::FLOAT:
{
const u32 intVal = convertEndian<u32>(cpu.read32(thisSegmentsStart, valid));
const u32 intVal = convertEndian<u32>(cpu.Read32(thisSegmentsStart, &valid));
float val = 0.0;
std::memcpy(&val, &intVal, sizeof(val));
if (penDefault && val == 0.0)
@@ -177,7 +177,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
painter.setPen(palette.text().color());
bool valid;
const u8 value = cpu.read8(currentRowAddress + j, valid);
const u8 value = cpu.Read8(currentRowAddress + j, &valid);
if (valid)
{
QChar curChar = QChar::fromLatin1(value);
@@ -258,19 +258,19 @@ u128 MemoryViewTable::GetSelectedSegment(DebugInterface& cpu)
switch (displayType)
{
case MemoryViewType::BYTE:
val.lo = cpu.read8(selectedAddress);
val.lo = cpu.Read8(selectedAddress);
break;
case MemoryViewType::BYTEHW:
val.lo = convertEndian(static_cast<u16>(cpu.read16(selectedAddress & ~1)));
val.lo = convertEndian(static_cast<u16>(cpu.Read16(selectedAddress & ~1)));
break;
case MemoryViewType::WORD:
val.lo = convertEndian(cpu.read32(selectedAddress & ~3));
val.lo = convertEndian(cpu.Read32(selectedAddress & ~3));
break;
case MemoryViewType::DWORD:
val._u64[0] = convertEndian(cpu.read64(selectedAddress & ~7));
val._u64[0] = convertEndian(cpu.Read64(selectedAddress & ~7));
break;
case MemoryViewType::FLOAT:
val.lo = convertEndian(cpu.read32(selectedAddress & ~3));
val.lo = convertEndian(cpu.Read32(selectedAddress & ~3));
break;
}
return val;
@@ -279,13 +279,13 @@ u128 MemoryViewTable::GetSelectedSegment(DebugInterface& cpu)
void MemoryViewTable::InsertIntoSelectedHexView(u8 value, DebugInterface& cpu)
{
const u8 mask = selectedNibbleHI ? 0x0f : 0xf0;
u8 curVal = cpu.read8(selectedAddress) & mask;
u8 curVal = cpu.Read8(selectedAddress) & mask;
u8 newVal = value << (selectedNibbleHI ? 4 : 0);
curVal |= newVal;
const QPointer<MemoryViewTable> table(this);
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = curVal] {
cpu.write8(address, val);
cpu.Write8(address, val);
QtHost::RunOnUIThread([table] {
if (!table)
@@ -323,7 +323,7 @@ bool MemoryViewTable::InsertFloatIntoSelectedHexView(DebugInterface& cpu)
const QPointer<MemoryViewTable> table(this);
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = newIntVal] {
cpu.write32(address, val);
cpu.Write32(address, val);
QtHost::RunOnUIThread([table] {
if (!table)
@@ -360,7 +360,7 @@ void MemoryViewTable::InsertAtCurrentSelection(const QString& text, DebugInterfa
const QPointer<MemoryViewTable> table(this);
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = newIntVal] {
cpu.write32(address, val);
cpu.Write32(address, val);
QtHost::RunOnUIThread([table] {
if (!table)
@@ -384,7 +384,7 @@ void MemoryViewTable::InsertAtCurrentSelection(const QString& text, DebugInterfa
u32 currAddr = address;
for (int i = 0; i < input.size(); i++)
{
cpu.write8(currAddr, input[i]);
cpu.Write8(currAddr, input[i]);
currAddr = nextAddress(currAddr, address, display_type, little_endian);
}
@@ -552,7 +552,7 @@ bool MemoryViewTable::KeyPress(int key, QChar keychar, DebugInterface& cpu)
{
const QPointer<MemoryViewTable> table(this);
Host::RunOnCPUThread([table, address = selectedAddress, &cpu, val = keychar.toLatin1()] {
cpu.write8(address, val);
cpu.Write8(address, val);
QtHost::RunOnUIThread([table, address]() {
if (!table)
@@ -572,7 +572,7 @@ bool MemoryViewTable::KeyPress(int key, QChar keychar, DebugInterface& cpu)
{
const QPointer<MemoryViewTable> table(this);
Host::RunOnCPUThread([table, address = selectedAddress, &cpu] {
cpu.write8(address, 0);
cpu.Write8(address, 0);
QtHost::RunOnUIThread([table] {
if (!table)
@@ -741,7 +741,7 @@ bool MemoryView::fromJson(const JsonValueWrapper& json)
if (little_endian != json.value().MemberEnd() && little_endian->value.IsBool())
m_table.SetLittleEndian(little_endian->value.GetBool());
repaint();
update();
return true;
}
@@ -764,7 +764,7 @@ void MemoryView::mousePressEvent(QMouseEvent* event)
return;
m_table.SelectAt(event->pos());
repaint();
update();
}
void MemoryView::openContextMenu(QPoint pos)
@@ -859,13 +859,13 @@ void MemoryView::openContextMenu(QPoint pos)
menu->popup(this->mapToGlobal(pos));
this->repaint();
update();
return;
}
void MemoryView::contextCopyByte()
{
QApplication::clipboard()->setText(QString::number(cpu().read8(m_table.selectedAddress), 16).toUpper());
QApplication::clipboard()->setText(QString::number(cpu().Read8(m_table.selectedAddress), 16).toUpper());
}
void MemoryView::contextCopySegment()
@@ -885,7 +885,7 @@ void MemoryView::contextCopySegment()
void MemoryView::contextCopyCharacter()
{
QApplication::clipboard()->setText(QChar::fromLatin1(cpu().read8(m_table.selectedAddress)).toUpper());
QApplication::clipboard()->setText(QChar::fromLatin1(cpu().Read8(m_table.selectedAddress)).toUpper());
}
void MemoryView::contextPaste()
@@ -913,7 +913,7 @@ void MemoryView::contextGoToAddress()
void MemoryView::contextFollowAddress()
{
bool valid;
u32 address = cpu().read32(m_table.selectedAddress & ~3, valid);
u32 address = cpu().Read32(m_table.selectedAddress & ~3, &valid);
if (!valid)
return;
@@ -934,7 +934,7 @@ void MemoryView::wheelEvent(QWheelEvent* event)
{
m_table.UpdateStartAddress(m_table.startAddress - 0x10);
}
this->repaint();
update();
}
void MemoryView::keyPressEvent(QKeyEvent* event)
@@ -954,7 +954,7 @@ void MemoryView::keyPressEvent(QKeyEvent* event)
break;
}
}
this->repaint();
update();
DebuggerView::broadcastEvent(DebuggerEvents::VMUpdate());
}
@@ -962,8 +962,8 @@ void MemoryView::gotoAddress(u32 address)
{
m_table.UpdateStartAddress(address & ~0xF);
m_table.selectedAddress = address;
this->repaint();
this->setFocus();
update();
setFocus();
}
#include "moc_MemoryView.cpp"
+7 -6
View File
@@ -36,7 +36,7 @@ RegisterView::RegisterView(const DebuggerViewParameters& parameters)
ui.registerTabs->addTab(cpu().getRegisterCategoryName(i));
}
connect(ui.registerTabs, &QTabBar::currentChanged, [this]() { this->repaint(); });
connect(ui.registerTabs, &QTabBar::currentChanged, [this]() { update(); });
receiveEvent<DebuggerEvents::Refresh>([this](const DebuggerEvents::Refresh& event) -> bool {
update();
@@ -69,7 +69,7 @@ bool RegisterView::fromJson(const JsonValueWrapper& json)
if (show_fpr_float != json.value().MemberEnd() && show_fpr_float->value.IsBool())
m_showFPRFloat = show_fpr_float->value.GetBool();
repaint();
update();
return true;
}
@@ -209,7 +209,8 @@ void RegisterView::mousePressEvent(QMouseEvent* event)
}
}
}
this->repaint();
update();
}
void RegisterView::wheelEvent(QWheelEvent* event)
@@ -223,7 +224,7 @@ void RegisterView::wheelEvent(QWheelEvent* event)
m_rowStart -= 1;
}
this->repaint();
update();
}
void RegisterView::mouseDoubleClickEvent(QMouseEvent* event)
@@ -259,7 +260,7 @@ void RegisterView::customMenuRequested(QPoint pos)
action->setChecked(m_showFPRFloat);
connect(action, &QAction::triggered, this, [this]() {
m_showFPRFloat = !m_showFPRFloat;
repaint();
update();
});
menu->addSeparator();
@@ -272,7 +273,7 @@ void RegisterView::customMenuRequested(QPoint pos)
action->setChecked(m_showVU0FFloat);
connect(action, &QAction::triggered, this, [this]() {
m_showVU0FFloat = !m_showVU0FFloat;
repaint();
update();
});
menu->addSeparator();
+1 -2
View File
@@ -111,8 +111,7 @@ void StackModel::refreshData()
{
if (thread->Status() == ThreadStatus::THS_RUN)
{
m_stackFrames = MipsStackWalk::Walk(&m_cpu, m_cpu.getPC(), m_cpu.getRegister(0, 31), m_cpu.getRegister(0, 29),
thread->EntryPoint(), thread->StackTop());
m_stackFrames = m_cpu.StackTrace(*thread);
break;
}
}
@@ -60,7 +60,7 @@ u8 SymbolTreeLocation::read8(DebugInterface& cpu) const
return cpu.getRegister(EECAT_GPR, address)._u8[0];
break;
case MEMORY:
return (u8)cpu.read8(address);
return cpu.Read8(address);
default:
{
}
@@ -77,7 +77,7 @@ u16 SymbolTreeLocation::read16(DebugInterface& cpu) const
return cpu.getRegister(EECAT_GPR, address)._u16[0];
break;
case MEMORY:
return (u16)cpu.read16(address);
return cpu.Read16(address);
default:
{
}
@@ -94,7 +94,7 @@ u32 SymbolTreeLocation::read32(DebugInterface& cpu) const
return cpu.getRegister(EECAT_GPR, address)._u32[0];
break;
case MEMORY:
return cpu.read32(address);
return cpu.Read32(address);
default:
{
}
@@ -111,7 +111,7 @@ u64 SymbolTreeLocation::read64(DebugInterface& cpu) const
return cpu.getRegister(EECAT_GPR, address)._u64[0];
break;
case MEMORY:
return cpu.read64(address);
return cpu.Read64(address);
default:
{
}
@@ -128,7 +128,7 @@ u128 SymbolTreeLocation::read128(DebugInterface& cpu) const
return cpu.getRegister(EECAT_GPR, address);
break;
case MEMORY:
return cpu.read128(address);
return cpu.Read128(address);
default:
{
}
@@ -145,7 +145,7 @@ void SymbolTreeLocation::write8(u8 value, DebugInterface& cpu) const
cpu.setRegister(0, address, u128::From32(value));
break;
case MEMORY:
cpu.write8(address, value);
cpu.Write8(address, value);
break;
default:
{
@@ -162,7 +162,7 @@ void SymbolTreeLocation::write16(u16 value, DebugInterface& cpu) const
cpu.setRegister(0, address, u128::From32(value));
break;
case MEMORY:
cpu.write16(address, value);
cpu.Write16(address, value);
break;
default:
{
@@ -179,7 +179,7 @@ void SymbolTreeLocation::write32(u32 value, DebugInterface& cpu) const
cpu.setRegister(0, address, u128::From32(value));
break;
case MEMORY:
cpu.write32(address, value);
cpu.Write32(address, value);
break;
default:
{
@@ -196,7 +196,7 @@ void SymbolTreeLocation::write64(u64 value, DebugInterface& cpu) const
cpu.setRegister(0, address, u128::From64(value));
break;
case MEMORY:
cpu.write64(address, value);
cpu.Write64(address, value);
break;
default:
{
@@ -213,7 +213,7 @@ void SymbolTreeLocation::write128(u128 value, DebugInterface& cpu) const
cpu.setRegister(0, address, value);
break;
case MEMORY:
cpu.write128(address, value);
cpu.Write128(address, value);
break;
default:
{
-2
View File
@@ -71,8 +71,6 @@ private:
//: Refers to a Thread Wait State in the Debugger.
{WaitState::NONE, tr("NONE")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::WAKEUP_REQ, tr("WAKEUP REQUEST")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::SEMA, tr("SEMAPHORE")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::SLEEP, tr("SLEEP")},
+8 -5
View File
@@ -294,11 +294,6 @@ void GameListWidget::initialize()
if (Host::ContainsBaseSettingValue("GameListTableView", "HeaderState"))
{
loadTableHeaderState();
// Enforce at least one column is visible immediately after loading.
// This handles cases where a config (perhaps from an older version) has 0 columns and
// no games are visible to be changed (such as per-game config) or played as you can't click on any.
// Will automatically repair a broken header state from config (PCSX2.ini) file.
ensureMinimumOneColumnVisible();
}
else
{
@@ -811,6 +806,14 @@ void GameListWidget::loadTableHeaderState()
QSignalBlocker blocker(header);
header->restoreState(QByteArray::fromBase64(QByteArray::fromStdString(state_setting)));
header->setSectionHidden(GameListModel::Column_Cover, true);
// Enforce at least one column is visible immediately after loading.
// This handles cases where a config (perhaps from an older version) has 0 columns and
// no games are visible to be changed (such as per-game config) or played as you can't click on any.
// Will automatically repair a broken header state from config (PCSX2.ini) file.
ensureMinimumOneColumnVisible();
}
void GameListWidget::ensureMinimumOneColumnVisible()
+46 -6
View File
@@ -399,8 +399,8 @@ void MainWindow::connectSignals()
m_ui.actionEnableVerboseLogging->setChecked(true);
m_ui.actionEnableVerboseLogging->setEnabled(false);
#endif
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableEEConsoleLogging, "Logging", "EnableEEConsole", true);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableIOPConsoleLogging, "Logging", "EnableIOPConsole", true);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableEEConsoleLogging, "Logging", "EnableEEConsole", false);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableIOPConsoleLogging, "Logging", "EnableIOPConsole", false);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableLogWindow, "Logging", "EnableLogWindow", false);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableFileLogging, "Logging", "EnableFileLogging", true);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableLogTimestamps, "Logging", "EnableTimestamps", true);
@@ -873,6 +873,26 @@ void MainWindow::saveStateToConfig()
changed = true;
}
if (Host::ContainsBaseSettingValue("UI", "MainWindowMaximized"))
{
const bool maximized = Host::GetBaseBoolSettingValue("UI", "MainWindowMaximized");
if (maximized != isMaximized())
{
Host::SetBaseBoolSettingValue("UI", "MainWindowMaximized", isMaximized());
changed = true;
}
}
if (Host::ContainsBaseSettingValue("UI", "MainWindowFullscreen"))
{
const bool fullscreen = Host::GetBaseBoolSettingValue("UI", "MainWindowFullscreen");
if (fullscreen != isFullScreen())
{
Host::SetBaseBoolSettingValue("UI", "MainWindowFullscreen", isFullScreen());
changed = true;
}
}
if (changed)
Host::CommitBaseSettingChanges();
}
@@ -901,6 +921,24 @@ void MainWindow::restoreStateFromConfig()
m_ui.actionViewStatusBar->setChecked(!m_ui.statusBar->isHidden());
}
}
{
if (Host::ContainsBaseSettingValue("UI", "MainWindowMaximized"))
{
const bool maximized = Host::GetBaseBoolSettingValue("UI", "MainWindowMaximized");
if (maximized)
showMaximized();
}
}
{
if (Host::ContainsBaseSettingValue("UI", "MainWindowFullscreen"))
{
const bool fullscreen = Host::GetBaseBoolSettingValue("UI", "MainWindowFullscreen");
if (fullscreen)
showFullScreen();
}
}
}
void MainWindow::updateEmulationActions(bool starting, bool running, bool stopping)
@@ -1114,7 +1152,7 @@ bool MainWindow::shouldHideMainWindow() const
{
// NOTE: We can't use isRenderingToMain() here, because this happens post-fullscreen-switch.
return (Host::GetBoolSettingValue("UI", "HideMainWindowWhenRunning", false) && !g_emu_thread->shouldRenderToMain()) ||
(g_emu_thread->shouldRenderToMain() && (isRenderingFullscreen() || m_is_temporarily_windowed)) ||
(g_emu_thread->shouldRenderToMain() && (isRenderingFullscreen() || g_emu_thread->isExclusiveFullscreen() || m_is_temporarily_windowed)) ||
Host::InNoGUIMode();
}
@@ -1714,7 +1752,7 @@ void MainWindow::onStartFullscreenUITriggered()
void MainWindow::onFullscreenUIStateChange(bool running)
{
m_ui.actionStartFullscreenUI->setText(running ? tr("Stop Big Picture Mode") : tr("Start Big Picture Mode"));
m_ui.actionStartFullscreenUI->setText(running ? tr("Stop Big Picture Mode") : tr("Start Big Picture &Mode"));
m_ui.actionToolbarStartFullscreenUI->setText(running ? tr("Exit Big Picture", "In Toolbar") : tr("Big Picture", "In Toolbar"));
}
@@ -2538,6 +2576,7 @@ std::optional<WindowInfo> MainWindow::acquireRenderWindow(bool recreate_window,
return std::nullopt;
}
m_display_is_exclusive_fullscreen = g_emu_thread->isExclusiveFullscreen();
g_emu_thread->connectDisplaySignals(m_display_surface);
updateWindowTitle();
@@ -2582,7 +2621,7 @@ void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main)
#ifdef DISPLAY_SURFACE_WINDOW
if (isVisible() && g_emu_thread->shouldRenderToMain())
m_display_surface->setPosition(screen()->availableGeometry().topLeft());
m_display_surface->setGeometry(screen()->geometry());
else
restoreDisplayWindowGeometryFromConfig();
@@ -2709,6 +2748,7 @@ void MainWindow::releaseRenderWindow()
// Now we can safely destroy the display window.
destroyDisplayWidget(true);
m_display_created = false;
m_display_is_exclusive_fullscreen = false;
m_ui.actionViewSystemDisplay->setEnabled(false);
m_ui.actionFullscreen->setEnabled(false);
@@ -2719,7 +2759,7 @@ void MainWindow::destroyDisplayWidget(bool show_game_list)
if (!m_display_surface)
return;
if (!m_display_surface->isFullScreen() && !isRenderingToMain())
if (!(m_display_surface->isFullScreen() || m_display_is_exclusive_fullscreen) && !isRenderingToMain())
saveDisplayWindowGeometryToConfig();
if (isRenderingToMain())
+1
View File
@@ -317,6 +317,7 @@ private:
QMenu* m_settings_toolbar_menu = nullptr;
bool m_display_created = false;
bool m_display_is_exclusive_fullscreen = false;
bool m_relative_mouse_mode = false;
bool m_hide_mouse_cursor = false;
bool m_was_paused_on_surface_loss = false;
+9 -2
View File
@@ -2086,7 +2086,8 @@ void QtHost::PrintCommandLineHelp(const std::string_view progname)
std::fprintf(stderr, " -version: Displays version information and exits.\n");
std::fprintf(stderr, " -batch: Enables batch mode (exits after shutting down).\n");
std::fprintf(stderr, " -nogui: Hides main window while running (implies batch mode).\n");
std::fprintf(stderr, " -portable: Force enable portable mode to store data in local PCSX2 path instead of the default configuration path.\n");
std::fprintf(stderr, " -portable: Force enable portable mode to store data in local PCSX2 path instead of the default configuration path. Overrides '-datapath'.\n");
std::fprintf(stderr, " -datapath <path>: Specify the directory to be used for all application data.\n");
std::fprintf(stderr, " -elf <file>: Overrides the boot ELF with the specified filename.\n");
std::fprintf(stderr, " -gameargs <string>: passes the specified quoted space-delimited string of launch arguments.\n");
std::fprintf(stderr, " -disc <path>: Uses the specified host DVD drive as a source.\n");
@@ -2165,6 +2166,12 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
EmuConfig.IsPortableMode = true;
continue;
}
else if (CHECK_ARG_PARAM(QStringLiteral("-datapath")))
{
std::string path = (++it)->toStdString();
EmuConfig.CustomDataPath = path;
continue;
}
else if (CHECK_ARG(QStringLiteral("-fastboot")))
{
AutoBoot(autoboot)->fast_boot = true;
@@ -2297,7 +2304,7 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
Console.Warning("Skipping autoboot due to no boot parameters.");
autoboot.reset();
}
if(autoboot && autoboot->start_turbo.value_or(false) && autoboot->start_unlimited.value_or(false))
{
Console.Warning("Both turbo and unlimited frame limit modes requested. Using unlimited.");
+15 -26
View File
@@ -23,6 +23,7 @@
#include <QtWidgets/QSpinBox>
#include "common/FileSystem.h"
#include "common/HostSys.h"
#include "common/Path.h"
#include "pcsx2/Config.h"
@@ -1261,8 +1262,8 @@ namespace SettingWidgetBinder
widget->connect(widget, &QLineEdit::editingFinished, widget, std::move(value_changed));
}
static inline void BindWidgetToFileSetting(SettingsInterface* sif, QLineEdit* widget, QAbstractButton* browse_button,
QAbstractButton* open_button, QAbstractButton* reset_button, std::string section, std::string key, std::string default_value,
static inline void BindWidgetToAudioFileSetting(SettingsInterface* sif, QLineEdit* widget, QAbstractButton* browse_button,
QAbstractButton* preview_button, QAbstractButton* reset_button, std::string section, std::string key, std::string default_value,
const QString& filter, bool allow_pergame = false, bool use_relative = true)
{
using Accessor = SettingAccessor<QLineEdit>;
@@ -1296,40 +1297,25 @@ namespace SettingWidgetBinder
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), relative_path.c_str());
}
else
{
Host::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.c_str());
}
if (!FileSystem::FileExists(new_value.c_str()))
{
QMessageBox::critical(QtUtils::GetRootWidget(widget), qApp->translate("SettingWidgetBinder", "Error"),
qApp->translate("SettingWidgetBinder", "File cannot be found."));
}
Host::CommitBaseSettingChanges();
return;
}
else
{
QMessageBox::critical(QtUtils::GetRootWidget(widget), qApp->translate("SettingWidgetBinder", "Error"),
qApp->translate("SettingWidgetBinder", "File path cannot be empty."));
}
Host::RemoveBaseSettingValue(section.c_str(), key.c_str());
// reset to old value
std::string current_path(Host::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str()));
if (current_path.empty())
current_path = default_value;
else if (use_relative && !Path::IsAbsolute(current_path))
current_path = Path::Canonicalize(Path::Combine(EmuFolders::DataRoot, current_path));
widget->setText(QString::fromStdString(current_path));
};
if (browse_button)
{
QObject::connect(browse_button, &QAbstractButton::clicked, browse_button, [widget, key, value_changed, filter]() {
const QString path(QDir::toNativeSeparators(QFileDialog::getOpenFileName(QtUtils::GetRootWidget(widget),
qApp->translate("SettingWidgetBinder", "Select File"), QString(), filter)));
qApp->translate("SettingWidgetBinder", "Select Audio File"), QString(), filter)));
if (path.isEmpty())
return;
@@ -1337,19 +1323,22 @@ namespace SettingWidgetBinder
value_changed();
});
}
if (open_button)
if (preview_button)
{
QObject::connect(open_button, &QAbstractButton::clicked, open_button, [widget]() {
QString path(Accessor::getStringValue(widget));
if (!path.isEmpty())
QtUtils::OpenURL(QtUtils::GetRootWidget(widget), QUrl::fromLocalFile(path));
QObject::connect(preview_button, &QAbstractButton::clicked, preview_button, [widget, default_value = std::move(default_value)]() {
const QByteArray path = widget->text().toUtf8();
Common::PlaySoundAsync(
(path.isEmpty()
? default_value
: path.constData()).c_str()
);
});
}
if (reset_button)
{
QObject::connect(
reset_button, &QAbstractButton::clicked, reset_button, [widget, default_value = std::move(default_value), value_changed]() {
widget->setText(QString::fromStdString(default_value));
reset_button, &QAbstractButton::clicked, reset_button, [widget, value_changed]() {
widget->clear();
value_changed();
});
}
+7 -5
View File
@@ -52,12 +52,14 @@ void AchievementLoginDialog::loginClicked()
const bool result = Achievements::Login(username.c_str(), password.c_str(), &error);
const QString message = QString::fromStdString(error.GetDescription());
QtHost::RunOnUIThread([dialog, result, message = std::move(message)]() {
if (!dialog)
return;
QMetaObject::invokeMethod(
qApp, [dialog, result, message = std::move(message)]() {
if (!dialog)
return;
dialog->processLoginResult(result, message);
});
dialog->processLoginResult(result, message);
},
Qt::QueuedConnection);
});
}
@@ -17,7 +17,10 @@
#include <QtCore/QDateTime>
#include <QtWidgets/QMessageBox>
const char* AchievementSettingsWidget::AUDIO_FILE_FILTER = QT_TRANSLATE_NOOP("AchievementSettingsWidget", "WAV Audio Files (*.wav)");
static constexpr const char* AUDIO_FILE_FILTER = QT_TRANSLATE_NOOP("AchievementSettingsWidget", "WAV Audio Files (*.wav)");
static constexpr const char* DEFAULT_INFO_SOUND_NAME = "sounds/achievements/message.wav";
static constexpr const char* DEFAULT_UNLOCK_SOUND_NAME = "sounds/achievements/unlock.wav";
static constexpr const char* DEFAULT_LBSUBMIT_SOUND_NAME = "sounds/achievements/lbsubmit.wav";
AchievementSettingsWidget::AchievementSettingsWidget(SettingsWindow* settings_dialog, QWidget* parent)
: SettingsWidget(settings_dialog, parent)
@@ -44,9 +47,9 @@ AchievementSettingsWidget::AchievementSettingsWidget(SettingsWindow* settings_di
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.achievementNotificationsDuration, "Achievements", "NotificationsDuration", Pcsx2Config::AchievementsOptions::DEFAULT_NOTIFICATION_DURATION);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.leaderboardNotificationsDuration, "Achievements", "LeaderboardsDuration", Pcsx2Config::AchievementsOptions::DEFAULT_LEADERBOARD_DURATION);
SettingWidgetBinder::BindWidgetToFileSetting(sif, m_ui.notificationSoundPath, m_ui.notificationSoundBrowse, m_ui.notificationSoundOpen, m_ui.notificationSoundReset, "Achievements", "InfoSoundName", Path::Combine(EmuFolders::Resources, EmuConfig.Achievements.DEFAULT_INFO_SOUND_NAME), qApp->translate("AchievementSettingsWidget", AUDIO_FILE_FILTER), true, false);
SettingWidgetBinder::BindWidgetToFileSetting(sif, m_ui.unlockSoundPath, m_ui.unlockSoundBrowse, m_ui.unlockSoundOpen, m_ui.unlockSoundReset, "Achievements", "UnlockSoundName", Path::Combine(EmuFolders::Resources, EmuConfig.Achievements.DEFAULT_UNLOCK_SOUND_NAME), qApp->translate("AchievementSettingsWidget", AUDIO_FILE_FILTER), true, false);
SettingWidgetBinder::BindWidgetToFileSetting(sif, m_ui.lbSoundPath, m_ui.lbSoundBrowse, m_ui.lbSoundOpen, m_ui.lbSoundReset, "Achievements", "LBSubmitSoundName", Path::Combine(EmuFolders::Resources, EmuConfig.Achievements.DEFAULT_LBSUBMIT_SOUND_NAME), qApp->translate("AchievementSettingsWidget", AUDIO_FILE_FILTER), true, false);
SettingWidgetBinder::BindWidgetToAudioFileSetting(sif, m_ui.notificationSoundPath, m_ui.notificationSoundBrowse, m_ui.notificationSoundOpen, m_ui.notificationSoundReset, "Achievements", "InfoSoundName", Path::Combine(EmuFolders::Resources, DEFAULT_INFO_SOUND_NAME), qApp->translate("AchievementSettingsWidget", AUDIO_FILE_FILTER), true, false);
SettingWidgetBinder::BindWidgetToAudioFileSetting(sif, m_ui.unlockSoundPath, m_ui.unlockSoundBrowse, m_ui.unlockSoundOpen, m_ui.unlockSoundReset, "Achievements", "UnlockSoundName", Path::Combine(EmuFolders::Resources, DEFAULT_UNLOCK_SOUND_NAME), qApp->translate("AchievementSettingsWidget", AUDIO_FILE_FILTER), true, false);
SettingWidgetBinder::BindWidgetToAudioFileSetting(sif, m_ui.lbSoundPath, m_ui.lbSoundBrowse, m_ui.lbSoundOpen, m_ui.lbSoundReset, "Achievements", "LBSubmitSoundName", Path::Combine(EmuFolders::Resources, DEFAULT_LBSUBMIT_SOUND_NAME), qApp->translate("AchievementSettingsWidget", AUDIO_FILE_FILTER), true, false);
dialog()->registerWidgetHelp(m_ui.enable, tr("Enable Achievements"), tr("Unchecked"), tr("When enabled and logged in, PCSX2 will scan for achievements on startup."));
dialog()->registerWidgetHelp(m_ui.hardcoreMode, tr("Enable Hardcore Mode"), tr("Unchecked"), tr("\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions."));
@@ -117,6 +120,10 @@ void AchievementSettingsWidget::updateEnableState()
const bool info = enabled && sound && dialog()->getEffectiveBoolValue("Achievements", "InfoSound", true);
const bool unlock = enabled && sound && dialog()->getEffectiveBoolValue("Achievements", "UnlockSound", true);
const bool lbsound = enabled && sound && dialog()->getEffectiveBoolValue("Achievements", "LBSubmitSound", true);
m_ui.viewProfile->setEnabled(enabled);
m_ui.loginButton->setEnabled(enabled);
m_ui.hardcoreMode->setEnabled(enabled);
m_ui.achievementNotifications->setEnabled(enabled);
m_ui.leaderboardNotifications->setEnabled(enabled);
@@ -26,7 +26,6 @@ private Q_SLOTS:
private:
void updateLoginState();
static const char* AUDIO_FILE_FILTER;
Ui::AchievementSettingsWidget m_ui;
};
+128 -106
View File
@@ -11,13 +11,118 @@
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="loginBox">
<property name="title">
<string>Account</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0">
<item>
<layout class="QGridLayout" name="acccountLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="enable">
<property name="text">
<string>Enable Achievements</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="loginStatus">
<property name="text">
<string>Username:
Login token generated at:</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
</property>
<property name="buddy">
<cstring>viewProfile</cstring>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="achievementButtons">
<item>
<widget class="QPushButton" name="viewProfile">
<property name="text">
<string>View Profile...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="loginButton">
<property name="text">
<string>Login...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gameInfoBox">
<property name="minimumSize">
<size>
<width>0</width>
<height>75</height>
</size>
</property>
<property name="title">
<string>Game Info</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="gameInfo">
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
</property>
<property name="buddy">
<cstring>viewProfile</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="rcheevosDisclaimer">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;PCSX2 uses RetroAchievements as an achievement database and for tracking progress. To use achievements, please sign up for an account at &lt;a href=&quot;https://retroachievements.org/&quot;&gt;retroachievements.org&lt;/a&gt;.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;To view the achievement list in-game, press the hotkey for &lt;span style=&quot; font-weight:600;&quot;&gt;Open Pause Menu&lt;/span&gt; and select &lt;span style=&quot; font-weight:600;&quot;&gt;Achievements&lt;/span&gt; from the menu.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::TextFormat::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>8</number>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
<property name="buddy">
<cstring>enable</cstring>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="settingsBox">
<property name="title">
<string>Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="2" column="0">
<item row="1" column="1">
<widget class="QCheckBox" name="unofficialAchievements">
<property name="text">
<string>Test Unofficial Achievements</string>
@@ -25,23 +130,16 @@
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="hardcoreMode">
<widget class="QCheckBox" name="spectatorMode">
<property name="text">
<string>Enable Hardcore Mode</string>
<string>Enable Spectator Mode</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="enable">
<widget class="QCheckBox" name="hardcoreMode">
<property name="text">
<string>Enable Achievements</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="spectatorMode">
<property name="text">
<string>Enable Spectator Mode</string>
<string>Enable Hardcore Mode</string>
</property>
</widget>
</item>
@@ -316,10 +414,18 @@
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="5" column="0">
<widget class="QLineEdit" name="lbSoundPath"/>
<widget class="QLineEdit" name="lbSoundPath">
<property name="placeholderText">
<string>Default Sound Effect</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLineEdit" name="notificationSoundPath"/>
<widget class="QLineEdit" name="notificationSoundPath">
<property name="placeholderText">
<string>Default Sound Effect</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="unlockSoundBrowse">
@@ -350,7 +456,11 @@
</widget>
</item>
<item row="3" column="0">
<widget class="QLineEdit" name="unlockSoundPath"/>
<widget class="QLineEdit" name="unlockSoundPath">
<property name="placeholderText">
<string>Default Sound Effect</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="lbSoundBrowse">
@@ -411,94 +521,6 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="loginBox">
<property name="title">
<string>Account</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<item>
<widget class="QLabel" name="loginStatus">
<property name="text">
<string>Username:
Login token generated at:</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="buddy">
<cstring>viewProfile</cstring>
</property>
<property name="textInteractionFlags">
<set>Qt::TextBrowserInteraction</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="achievementButtons">
<item>
<widget class="QPushButton" name="viewProfile">
<property name="text">
<string>View Profile...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="loginButton">
<property name="text">
<string>Login...</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gameInfoBox">
<property name="minimumSize">
<size>
<width>0</width>
<height>75</height>
</size>
</property>
<property name="title">
<string>Game Info</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QLabel" name="gameInfo">
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="textInteractionFlags">
<set>Qt::TextBrowserInteraction</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="rcheevosDisclaimer">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;PCSX2 uses RetroAchievements as an achievement database and for tracking progress. To use achievements, please sign up for an account at &lt;a href=&quot;https://retroachievements.org/&quot;&gt;retroachievements.org&lt;/a&gt;.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;To view the achievement list in-game, press the hotkey for &lt;span style=&quot; font-weight:600;&quot;&gt;Open Pause Menu&lt;/span&gt; and select &lt;span style=&quot; font-weight:600;&quot;&gt;Achievements&lt;/span&gt; from the menu.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::TextFormat::RichText</enum>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>8</number>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@@ -516,9 +538,11 @@ Login token generated at:</string>
</widget>
<tabstops>
<tabstop>enable</tabstop>
<tabstop>viewProfile</tabstop>
<tabstop>loginButton</tabstop>
<tabstop>hardcoreMode</tabstop>
<tabstop>encoreMode</tabstop>
<tabstop>spectatorMode</tabstop>
<tabstop>encoreMode</tabstop>
<tabstop>unofficialAchievements</tabstop>
<tabstop>achievementNotifications</tabstop>
<tabstop>achievementNotificationsDuration</tabstop>
@@ -544,8 +568,6 @@ Login token generated at:</string>
<tabstop>lbSoundBrowse</tabstop>
<tabstop>lbSoundOpen</tabstop>
<tabstop>lbSoundReset</tabstop>
<tabstop>viewProfile</tabstop>
<tabstop>loginButton</tabstop>
</tabstops>
<resources>
<include location="../resources/resources.qrc"/>
+6 -18
View File
@@ -70,23 +70,9 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
std::clamp(Host::GetBaseIntSettingValue("EmuCore/Speedhacks", "EECycleRate", DEFAULT_EE_CYCLE_RATE) - MINIMUM_EE_CYCLE_RATE,
0, MAXIMUM_EE_CYCLE_RATE - MINIMUM_EE_CYCLE_RATE))));
// Disable cheats, use the cheats panel instead (move fastcvd up in its spot).
const int count = m_ui.systemSettingsLayout->count();
for (int i = 0; i < count; i++)
{
QLayoutItem* item = m_ui.systemSettingsLayout->itemAt(i);
if (item && item->widget() == m_ui.cheats)
{
int row, col, rowSpan, colSpan;
m_ui.systemSettingsLayout->getItemPosition(i, &row, &col, &rowSpan, &colSpan);
delete m_ui.systemSettingsLayout->takeAt(i);
m_ui.systemSettingsLayout->removeWidget(m_ui.fastCDVD);
m_ui.systemSettingsLayout->addWidget(m_ui.fastCDVD, row, col);
delete m_ui.cheats;
m_ui.cheats = nullptr;
break;
}
}
// Disable cheats, use the cheats panel instead
m_ui.systemSettingsLayout->removeWidget(m_ui.cheats);
m_ui.cheats->hide();
}
else
{
@@ -96,9 +82,11 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
// Allow for FastCDVD for per-game settings only
m_ui.systemSettingsLayout->removeWidget(m_ui.fastCDVD);
m_ui.fastCDVD->deleteLater();
m_ui.fastCDVD->hide();
}
reflowCheckBoxes(m_ui.systemSettingsLayout);
const std::optional<int> cycle_rate =
dialog()->getIntValue("EmuCore/Speedhacks", "EECycleRate", sif ? std::nullopt : std::optional<int>(DEFAULT_EE_CYCLE_RATE));
m_ui.eeCycleRate->setCurrentIndex(cycle_rate.has_value() ? (std::clamp(cycle_rate.value(), MINIMUM_EE_CYCLE_RATE, MAXIMUM_EE_CYCLE_RATE) + (0 - MINIMUM_EE_CYCLE_RATE) + static_cast<int>(dialog()->isPerGameSettings())) : 0);
@@ -270,7 +270,14 @@
</widget>
</item>
<item row="7" column="0" colspan="2">
<layout class="QGridLayout" name="hwFixesLayout">
<layout class="QGridLayout" name="hwFixesLayout">
<item row="4" column="1">
<widget class="QCheckBox" name="drawBuffering">
<property name="text">
<string>Draw Buffering</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="estimateTextureRegion">
<property name="text">
@@ -65,6 +65,13 @@
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="hwAA1">
<property name="text">
<string>AA1</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="enableHWFixes">
<property name="text">
<string>Manual Hardware Renderer Fixes</string>
@@ -235,6 +242,7 @@
<tabstop>blending</tabstop>
<tabstop>mipmapping</tabstop>
<tabstop>accurateAlphaTest</tabstop>
<tabstop>hwAA1</tabstop>
<tabstop>enableHWFixes</tabstop>
</tabstops>
<resources/>
@@ -112,6 +112,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_hw.dithering, "EmuCore/GS", "dithering_ps2", 2);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.mipmapping, "EmuCore/GS", "hw_mipmap", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.accurateAlphaTest, "EmuCore/GS", "HWAccurateAlphaTest", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.hwAA1, "EmuCore/GS", "HWAA1", false);
SettingWidgetBinder::BindWidgetToIntSetting(
sif, m_hw.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_hw.enableHWFixes, "EmuCore/GS", "UserHacks", false);
@@ -152,6 +153,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
sif, m_fixes.limit24BitDepth, "EmuCore/GS", "UserHacks_Limit24BitDepth", static_cast<int>(GSLimit24BitDepth::Disabled));
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.readTCOnClose, "EmuCore/GS", "UserHacks_ReadTCOnClose", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.estimateTextureRegion, "EmuCore/GS", "UserHacks_EstimateTextureRegion", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.drawBuffering, "EmuCore/GS", "UserHacks_DrawBuffering", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.gpuPaletteConversion, "EmuCore/GS", "paltex", false);
connect(m_fixes.cpuSpriteRenderBW, &QComboBox::currentIndexChanged, this,
&GraphicsSettingsWidget::onCPUSpriteRenderBWChanged);
@@ -491,6 +493,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
dialog()->registerWidgetHelp(
m_hw.accurateAlphaTest, tr("Accurate Alpha Test"), tr("Unchecked"), tr("Enables accurate alpha testing, which some games require to render correctly. This may require more draw calls and result in a speed penalty."));
dialog()->registerWidgetHelp(
m_hw.hwAA1, tr("AA1"), tr("Unchecked"), tr("Enables AA1 (PS2 antialiasing), which some games require to render correctly. This may result in a heavy performance penalty."));
dialog()->registerWidgetHelp(
m_hw.textureFiltering, tr("Texture Filtering"), tr("Bilinear (PS2)"),
tr("Changes what filtering algorithm is used to map textures to surfaces.<br> "
@@ -610,6 +615,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
dialog()->registerWidgetHelp(m_fixes.estimateTextureRegion, tr("Estimate Texture Region"), tr("Unchecked"),
tr("Attempts to reduce the texture size when games do not set it themselves (e.g. Snowblind games)."));
dialog()->registerWidgetHelp(m_fixes.drawBuffering, tr("Draw Buffering"), tr("Unchecked"),
tr("Attempts to reduce draw calls in games which do heavy context switching for blending purposes."));
}
// Upscaling Fixes tab
+1 -5
View File
@@ -184,10 +184,6 @@ void OSDSettingsWidget::onBrowseOsdFontPathClicked()
saveOsdFontPathSetting(QDir::toNativeSeparators(selected));
});
connect(m_font_picker, &QObject::destroyed, this, [this]() {
m_font_picker = nullptr;
});
m_font_picker->show();
}
@@ -313,4 +309,4 @@ void OSDSettingsWidget::onDeselectAllClicked()
m_ui.warnAboutUnsafeSettings->setChecked(true);
}
#include "moc_OSDSettingsWidget.cpp"
#include "moc_OSDSettingsWidget.cpp"
+26
View File
@@ -3,6 +3,7 @@
#include "SettingsWidget.h"
#include <QtWidgets/QGridLayout>
#include <QtWidgets/QScrollArea>
#include <QtWidgets/QScrollBar>
#include <QtWidgets/QTabBar>
@@ -115,4 +116,29 @@ void SettingsWidget::updateTabMargins(QScrollArea* scroll_area)
}
}
void SettingsWidget::reflowCheckBoxes(QGridLayout* layout)
{
std::vector<QWidget*> widgets;
for (int row = 0; row < layout->rowCount(); row++)
{
for (int column = 0; column < layout->columnCount(); column++)
{
QLayoutItem* item = layout->itemAtPosition(row, column);
if (item && item->widget())
{
widgets.push_back(item->widget());
layout->removeWidget(item->widget());
}
}
}
for (size_t i = 0; i < widgets.size(); i++)
{
int row = static_cast<int>(i / 2);
int column = static_cast<int>(i % 2);
layout->addWidget(widgets[i], row, column);
}
}
#include "moc_SettingsWidget.cpp"
+5
View File
@@ -7,6 +7,7 @@
#include <QtWidgets/QWidget>
class QGridLayout;
class QScrollArea;
class QTabWidget;
@@ -45,6 +46,10 @@ protected:
QWidget* addTab(QString name, QWidget* contents, bool custom_margins = false);
void setTabVisible(QWidget* tab, bool is_visible, QWidget* switch_to = nullptr);
// Rearrange the checkboxes in a group so that there aren't any gaps. To be
// used if checkboxes have been hidden programmatically.
void reflowCheckBoxes(QGridLayout* layout);
private:
void updateTabMargins(QScrollArea* scroll_area);
+94 -2
View File
@@ -1,17 +1,18 @@
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
#include "pcsx2/Achievements.h"
#include "pcsx2/SIO/Pad/Pad.h"
#include "QtHost.h"
#include "QtUtils.h"
#include "SettingWidgetBinder.h"
#include "Settings/AchievementLoginDialog.h"
#include "Settings/BIOSSettingsWidget.h"
#include "Settings/ControllerSettingWidgetBinder.h"
#include "Settings/InterfaceSettingsWidget.h"
#include "SetupWizardDialog.h"
#include <QtCore/QLocale>
#include <QtWidgets/QMessageBox>
#include "common/StringUtil.h"
SetupWizardDialog::SetupWizardDialog()
{
@@ -109,6 +110,10 @@ void SetupWizardDialog::pageChangedTo(int page)
resizeDirectoryListColumns();
break;
case Page_RetroAchievements:
refreshRetroAchievementsLoginState();
break;
default:
break;
}
@@ -160,6 +165,7 @@ void SetupWizardDialog::setupUi()
m_page_labels[Page_BIOS] = m_ui.labelBIOS;
m_page_labels[Page_GameList] = m_ui.labelGameList;
m_page_labels[Page_Controller] = m_ui.labelController;
m_page_labels[Page_RetroAchievements] = m_ui.labelRetroAchievements;
m_page_labels[Page_Complete] = m_ui.labelComplete;
connect(m_ui.back, &QPushButton::clicked, this, &SetupWizardDialog::previousPage);
@@ -170,6 +176,7 @@ void SetupWizardDialog::setupUi()
setupBIOSPage();
setupGameListPage();
setupControllerPage();
setupRetroAchievementsPage();
}
void SetupWizardDialog::setupLanguagePage()
@@ -407,6 +414,91 @@ void SetupWizardDialog::setupControllerPage()
g_emu_thread->enumerateInputDevices();
}
void SetupWizardDialog::setupRetroAchievementsPage()
{
const QString base_path(QtHost::GetResourcesBasePath());
QtUtils::SetScalableIcon(m_ui.raLogo, QIcon(QStringLiteral("%1/icons/ra-icon.svg").arg(base_path)), QSize(56, 56));
if (Achievements::IsUsingRAIntegration())
{
m_ui.raIntegrationLabel->setVisible(true);
m_ui.raContentWidget->setVisible(false);
return;
}
SettingWidgetBinder::BindWidgetToBoolSetting(
nullptr, m_ui.raEnableAchievements, "Achievements", "Enabled", false);
SettingWidgetBinder::BindWidgetToBoolSetting(
nullptr, m_ui.raHardcoreMode, "Achievements", "ChallengeMode", false);
connect(m_ui.raLoginButton, &QPushButton::clicked, this, &SetupWizardDialog::onRetroAchievementsLoginLogoutPressed);
connect(m_ui.raViewProfileButton, &QPushButton::clicked, this, &SetupWizardDialog::onRetroAchievementsViewProfilePressed);
refreshRetroAchievementsLoginState();
}
void SetupWizardDialog::refreshRetroAchievementsLoginState()
{
const std::string username(Host::GetBaseStringSettingValue("Achievements", "Username"));
const bool logged_in = !username.empty();
if (logged_in)
{
const u64 login_unix_timestamp =
StringUtil::FromChars<u64>(Host::GetBaseStringSettingValue("Achievements", "LoginTimestamp", "0")).value_or(0);
const QDateTime login_timestamp(QDateTime::fromSecsSinceEpoch(static_cast<qint64>(login_unix_timestamp)));
m_ui.raLoginStatus->setText(tr("Username: %1\nLogin token generated on %2.")
.arg(QString::fromStdString(username))
.arg(login_timestamp.toString(Qt::TextDate)));
m_ui.raLoginButton->setText(tr("Logout"));
}
else
{
m_ui.raLoginStatus->setText(tr("Not Logged In."));
m_ui.raLoginButton->setText(tr("Login..."));
}
m_ui.raViewProfileButton->setEnabled(logged_in);
}
void SetupWizardDialog::onRetroAchievementsLoginLogoutPressed()
{
if (!Host::GetBaseStringSettingValue("Achievements", "Username").empty())
{
Host::RunOnCPUThread([]() { Achievements::Logout(); }, true);
refreshRetroAchievementsLoginState();
return;
}
AchievementLoginDialog login(this, Achievements::LoginRequestReason::UserInitiated);
if (login.exec() != 0)
return;
refreshRetroAchievementsLoginState();
// Login can enable achievements, keep the checkbox state in sync.
if (!m_ui.raEnableAchievements->isChecked() &&
Host::GetBaseBoolSettingValue("Achievements", "Enabled", false))
{
QSignalBlocker sb(m_ui.raEnableAchievements);
m_ui.raEnableAchievements->setChecked(true);
}
if (!m_ui.raHardcoreMode->isChecked() &&
Host::GetBaseBoolSettingValue("Achievements", "ChallengeMode", false))
{
QSignalBlocker sb(m_ui.raHardcoreMode);
m_ui.raHardcoreMode->setChecked(true);
}
}
void SetupWizardDialog::onRetroAchievementsViewProfilePressed()
{
const std::string username(Host::GetBaseStringSettingValue("Achievements", "Username"));
if (username.empty())
return;
const QByteArray encoded_username(QUrl::toPercentEncoding(QString::fromStdString(username)));
QtUtils::OpenURL(this, QUrl(QStringLiteral("https://retroachievements.org/user/%1").arg(QString::fromUtf8(encoded_username))));
}
void SetupWizardDialog::openAutomaticMappingMenu(u32 port, QLabel* update_label)
{
QMenu menu(this);
+5
View File
@@ -42,6 +42,8 @@ private Q_SLOTS:
void onInputDevicesEnumerated(const QList<QPair<QString, QString>>& devices);
void onInputDeviceConnected(const QString& identifier, const QString& device_name);
void onInputDeviceDisconnected(const QString& identifier);
void onRetroAchievementsLoginLogoutPressed();
void onRetroAchievementsViewProfilePressed();
protected:
void resizeEvent(QResizeEvent* event);
@@ -53,6 +55,7 @@ private:
Page_BIOS,
Page_GameList,
Page_Controller,
Page_RetroAchievements,
Page_Complete,
Page_Count,
};
@@ -62,6 +65,8 @@ private:
void setupBIOSPage();
void setupGameListPage();
void setupControllerPage();
void setupRetroAchievementsPage();
void refreshRetroAchievementsLoginState();
void pageChangedTo(int page);
void updatePageLabels(int prev_page);
+259 -2
View File
@@ -91,6 +91,13 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelRetroAchievements">
<property name="text">
<string>RetroAchievements</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="labelComplete">
<property name="text">
@@ -118,12 +125,12 @@
<item row="0" column="1">
<widget class="QStackedWidget" name="pages">
<property name="currentIndex">
<number>3</number>
<number>4</number>
</property>
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>10</number>
<number>4</number>
</property>
<property name="leftMargin">
<number>0</number>
@@ -628,6 +635,256 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="pageRetroAchievements">
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="spacing">
<number>4</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_12">
<item>
<widget class="QLabel" name="raLogo">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>56</width>
<height>56</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>56</width>
<height>56</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="raSectionLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>14</pointsize>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>RetroAchievements</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_11">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="raIntroLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;justify&quot;&gt;PCSX2 supports RetroAchievements, a service that adds achievements, leaderboards, and extra challenges to classic games.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Sign in below to link your account and start earning achievements in supported titles, or create a free account at &lt;a href=&quot;https://retroachievements.org/createaccount.php&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#27bf73;&quot;&gt;retroachievements.org/createaccount.php&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p align=&quot;justify&quot;&gt;Using RetroAchievements is completely optional and not required to use PCSX2.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::TextFormat::RichText</enum>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="margin">
<number>2</number>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="raIntegrationLabel">
<property name="visible">
<bool>false</bool>
</property>
<property name="text">
<string>RAIntegration is being used, built-in RetroAchievements support is disabled.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="raContentWidget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_9">
<property name="spacing">
<number>4</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="raSettingsBox">
<property name="title">
<string/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<widget class="QCheckBox" name="raEnableAchievements">
<property name="text">
<string>Enable Achievements</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="raHardcoreMode">
<property name="text">
<string>Enable Hardcore Mode</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="raAccountBox">
<property name="title">
<string>Account</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_7" stretch="1,0,0,0">
<item>
<widget class="QLabel" name="raLoginStatus">
<property name="text">
<string>Not Logged In.</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::TextBrowserInteraction</set>
</property>
<property name="buddy">
<cstring>raViewProfileButton</cstring>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="raViewProfileButton">
<property name="text">
<string>View Profile...</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="raLoginButton">
<property name="text">
<string>Login...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="raFooterLabel">
<property name="text">
<string>You can customize additional RetroAchievements options later in Settings &gt; Achievements.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_5">
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="leftMargin">
+103 -58
View File
@@ -14,16 +14,10 @@
#include "VMManager.h"
#if defined(_WIN32)
#include "common/RedtapeWindows.h"
#include "common/RedtapeWilCom.h"
#include <shlobj.h>
#include <winnls.h>
#include <shobjidl.h>
#include <objbase.h>
#include <objidl.h>
#include <shlguid.h>
#include <comdef.h>
#include <wrl/client.h>
#endif
ShortcutCreationDialog::ShortcutCreationDialog(QWidget* parent, const QString& title, const QString& path)
@@ -41,10 +35,10 @@ ShortcutCreationDialog::ShortcutCreationDialog(QWidget* parent, const QString& t
m_ui.shortcutStartMenu->setText(tr("Application Launcher"));
#endif
QButtonGroup* buttonGroup = new QButtonGroup(this);
buttonGroup->setExclusive(true);
buttonGroup->addButton(m_ui.fastForwardTurboOption);
buttonGroup->addButton(m_ui.fastForwardUnlimitedOption);
QButtonGroup* speedGroup = new QButtonGroup(this);
speedGroup->setExclusive(true);
speedGroup->addButton(m_ui.fastForwardTurboOption);
speedGroup->addButton(m_ui.fastForwardUnlimitedOption);
m_ui.fastForwardTurboOption->setChecked(true);
connect(m_ui.overrideBootELFButton, &QPushButton::clicked, [&]() {
@@ -75,6 +69,37 @@ ShortcutCreationDialog::ShortcutCreationDialog(QWidget* parent, const QString& t
m_ui.loadStateIndex->setMaximum(VMManager::NUM_SAVE_STATE_SLOTS);
m_ui.iconPreview->setPixmap(QtHost::GetAppIcon().pixmap(m_ui.iconPreview->size()));
m_ui.resetIconButton->setEnabled(false);
connect(m_ui.browseIconButton, &QPushButton::clicked, [&]() {
#if defined(_WIN32)
const QString filter = tr("Icon Files (*.ico);;All Files (*.*)");
#else
const QString filter = tr("Image Files (*.png *.jpg *.svg *.webp);;All Files (*.*)");
#endif
const QString icon_file = QFileDialog::getOpenFileName(this, tr("Select Icon"), QString(), filter);
if (!icon_file.isEmpty())
{
QPixmap pixmap(icon_file);
if (pixmap.isNull())
{
QMessageBox::critical(this, tr("Invalid Icon"), tr("The selected file could not be loaded as an icon."));
return;
}
m_ui.iconPath->setText(Path::ToNativePath(icon_file.toStdString()).c_str());
m_ui.iconPreview->setPixmap(pixmap.scaled(m_ui.iconPreview->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
m_ui.resetIconButton->setEnabled(true);
}
});
connect(m_ui.resetIconButton, &QPushButton::clicked, [&]() {
m_ui.iconPath->clear();
m_ui.iconPreview->setPixmap(QtHost::GetAppIcon().pixmap(m_ui.iconPreview->size()));
m_ui.resetIconButton->setEnabled(false);
});
if (std::getenv("container"))
{
m_ui.portableModeToggle->setEnabled(false);
@@ -107,7 +132,7 @@ ShortcutCreationDialog::ShortcutCreationDialog(QWidget* parent, const QString& t
if (m_ui.loadStateIndexToggle->isChecked())
{
const s32 load_state_index = m_ui.loadStateIndex->value();
if (load_state_index >= 1 && load_state_index <= VMManager::NUM_SAVE_STATE_SLOTS)
if (load_state_index > 0 && load_state_index <= VMManager::NUM_SAVE_STATE_SLOTS)
{
args.push_back("-state");
args.push_back(StringUtil::ToChars(load_state_index));
@@ -135,14 +160,15 @@ ShortcutCreationDialog::ShortcutCreationDialog(QWidget* parent, const QString& t
}
std::string custom_args = m_ui.customArgsInput->text().toStdString();
std::string icon_path = m_ui.iconPath->text().toStdString();
ShortcutCreationDialog::CreateShortcut(title.toStdString(), path.toStdString(), args, custom_args, m_ui.shortcutDesktop->isChecked());
ShortcutCreationDialog::CreateShortcut(title.toStdString(), path.toStdString(), args, custom_args, icon_path, m_ui.shortcutDesktop->isChecked());
accept();
});
}
void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::string game_path, std::vector<std::string> passed_cli_args, std::string custom_args, bool is_desktop)
void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::string game_path, std::vector<std::string> passed_cli_args, std::string custom_args, const std::string icon_path, bool is_desktop)
{
#if defined(_WIN32)
if (name.empty())
@@ -165,10 +191,9 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
// https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath
// https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid
std::string link_file;
if (PWSTR directory; SUCCEEDED(SHGetKnownFolderPath(is_desktop ? FOLDERID_Desktop : FOLDERID_Programs, 0, NULL, &directory)))
if (wil::unique_cotaskmem_string directory; SUCCEEDED(SHGetKnownFolderPath(is_desktop ? FOLDERID_Desktop : FOLDERID_Programs, 0, NULL, &directory)))
{
std::string directory_utf8 = StringUtil::WideStringToUTF8String(directory);
CoTaskMemFree(directory);
std::string directory_utf8 = StringUtil::WideStringToUTF8String(directory.get());
if (is_desktop)
link_file = Path::ToNativePath(fmt::format("{}/{}.lnk", directory_utf8, clean_name));
@@ -186,7 +211,6 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
}
else
{
CoTaskMemFree(directory);
QMessageBox::critical(this, tr("Failed to create shortcut"), is_desktop ? tr("'Desktop' directory not found") : tr("User's 'Start Menu\\Programs' directory not found"), QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
return;
}
@@ -205,7 +229,7 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
if (!lossless)
{
QMessageBox::warning(this, tr("Failed to create shortcut"), tr("File path contains invalid character(s)."), QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
QMessageBox::critical(this, tr("Failed to create shortcut"), tr("File path contains invalid character(s)."), QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
return;
}
@@ -231,23 +255,19 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
return;
}
Microsoft::WRL::ComPtr<IShellLink> pShellLink;
Microsoft::WRL::ComPtr<IPersistFile> pPersistFile;
wil::unique_couninitialize_call co_cleanup;
const auto cleanup = [&](bool return_value, const QString& fail_reason) -> bool {
if (!return_value)
{
Console.ErrorFmt("Failed to create shortcut: {}", fail_reason.toStdString());
QMessageBox::critical(this, tr("Failed to create shortcut"), fail_reason, QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
}
CoUninitialize();
return return_value;
const auto report_error = [&](const QString& reason) {
Console.ErrorFmt("Failed to create shortcut: {}", reason.toStdString());
QMessageBox::critical(this, tr("Failed to create shortcut"), reason, QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
};
res = CoCreateInstance(__uuidof(ShellLink), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pShellLink));
if (FAILED(res))
wil::com_ptr_nothrow<IShellLink> pShellLink = wil::CoCreateInstanceNoThrow<IShellLink>(CLSID_ShellLink);
wil::com_ptr_nothrow<IPersistFile> pPersistFile;
if (!pShellLink)
{
cleanup(false, tr("CoCreateInstance failed"));
report_error(tr("CoCreateInstance failed"));
return;
}
@@ -256,7 +276,7 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
res = pShellLink->SetPath(target_file.c_str());
if (FAILED(res))
{
cleanup(false, tr("SetPath failed (%1)").arg(str_error(res)));
report_error(tr("SetPath failed (%1)").arg(str_error(res)));
return;
}
@@ -265,7 +285,7 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
res = pShellLink->SetWorkingDirectory(working_dir.c_str());
if (FAILED(res))
{
cleanup(false, tr("SetWorkingDirectory failed (%1)").arg(str_error(res)));
report_error(tr("SetWorkingDirectory failed (%1)").arg(str_error(res)));
return;
}
@@ -276,26 +296,40 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
res = pShellLink->SetArguments(target_cli_args.c_str());
if (FAILED(res))
{
cleanup(false, tr("SetArguments failed (%1)").arg(str_error(res)));
report_error(tr("SetArguments failed (%1)").arg(str_error(res)));
return;
}
}
// Set the icon
std::string icon_path = Path::ToNativePath(Path::Combine(Path::GetDirectory(FileSystem::GetProgramPath()), "resources/icons/AppIconLarge.ico"));
const std::wstring w_icon_path = StringUtil::UTF8StringToWideString(icon_path);
std::string final_icon_path;
if (!icon_path.empty())
{
final_icon_path = Path::ToNativePath(icon_path);
if (!FileSystem::FileExists(final_icon_path.c_str()))
{
QMessageBox::critical(this, tr("Failed to create shortcut"), tr("The selected icon file does not exist."), QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
return;
}
}
else
{
final_icon_path = Path::ToNativePath(Path::Combine(Path::GetDirectory(FileSystem::GetProgramPath()), "resources/icons/AppIconLarge.ico"));
}
const std::wstring w_icon_path = StringUtil::UTF8StringToWideString(final_icon_path);
res = pShellLink->SetIconLocation(w_icon_path.c_str(), 0);
if (FAILED(res))
{
cleanup(false, tr("SetIconLocation failed (%1)").arg(str_error(res)));
report_error(tr("SetIconLocation failed (%1)").arg(str_error(res)));
return;
}
// Use the IPersistFile object to save the shell link
res = pShellLink.As(&pPersistFile);
res = pShellLink.query_to(&pPersistFile);
if (FAILED(res))
{
cleanup(false, tr("QueryInterface failed (%1)").arg(str_error(res)));
report_error(tr("QueryInterface failed (%1)").arg(str_error(res)));
return;
}
@@ -304,12 +338,10 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
res = pPersistFile->Save(w_link_file.c_str(), TRUE);
if (FAILED(res))
{
cleanup(false, tr("Failed to save the shortcut (%1)").arg(str_error(res)));
report_error(tr("Failed to save the shortcut (%1)").arg(str_error(res)));
return;
}
cleanup(true, {});
#else
if (name.empty())
@@ -365,25 +397,38 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
return;
}
// Copy PCSX2 icon
std::string icon_dest;
if (xdg_data_home)
icon_dest = fmt::format("{}/icons/hicolor/512x512/apps/", xdg_data_home);
else
icon_dest = fmt::format("{}/.local/share/icons/hicolor/512x512/apps/", home);
std::string icon_name;
if (is_flatpak) // Flatpak
if (!icon_path.empty())
{
executable_path = "flatpak run net.pcsx2.PCSX2";
icon_name = "net.pcsx2.PCSX2";
if (!FileSystem::FileExists(icon_path.c_str()))
{
QMessageBox::critical(this, tr("Failed to create shortcut"), tr("The selected icon file does not exist."), QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
return;
}
icon_name = icon_path;
}
else
{
icon_name = "PCSX2";
std::string icon_path = fmt::format("{}/{}.png", icon_dest, icon_name).c_str();
if (FileSystem::EnsureDirectoryExists(icon_dest.c_str(), true))
FileSystem::CopyFilePath(Path::Combine(EmuFolders::Resources, "icons/AppIconLarge.png").c_str(), icon_path.c_str(), false);
// Copy PCSX2 icon
std::string icon_dest;
if (xdg_data_home)
icon_dest = fmt::format("{}/icons/hicolor/512x512/apps/", xdg_data_home);
else
icon_dest = fmt::format("{}/.local/share/icons/hicolor/512x512/apps/", home);
if (is_flatpak) // Flatpak
{
executable_path = "flatpak run net.pcsx2.PCSX2";
icon_name = "net.pcsx2.PCSX2";
}
else
{
icon_name = "PCSX2";
std::string icon_path_dest = fmt::format("{}/{}.png", icon_dest, icon_name).c_str();
if (FileSystem::EnsureDirectoryExists(icon_dest.c_str(), true))
if (!FileSystem::FileExists(icon_path_dest.c_str()))
FileSystem::CopyFilePath(Path::Combine(EmuFolders::Resources, "icons/AppIconLarge.png").c_str(), icon_path_dest.c_str(), false);
}
}
// Shortcut CmdLine Args
@@ -393,7 +438,7 @@ void ShortcutCreationDialog::CreateShortcut(const std::string name, const std::s
if (!lossless)
{
QMessageBox::warning(this, tr("Failed to create shortcut"), tr("File path contains invalid character(s)."), QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
QMessageBox::critical(this, tr("Failed to create shortcut"), tr("File path contains invalid character(s)."), QMessageBox::StandardButton::Ok, QMessageBox::StandardButton::Ok);
return;
}
+1 -1
View File
@@ -15,7 +15,7 @@ public:
~ShortcutCreationDialog() = default;
/// Create desktop shortcut for games
void CreateShortcut(const std::string name, const std::string game_path, std::vector<std::string> passed_cli_args, std::string custom_args, bool is_desktop);
void CreateShortcut(const std::string name, const std::string game_path, std::vector<std::string> passed_cli_args, std::string custom_args, const std::string icon_path, bool is_desktop);
/// Escapes the given string for use with command line arguments.
/// Returns a bool that indicates whether the escaping operation are lossless or not.
+97 -5
View File
@@ -10,11 +10,11 @@
<x>0</x>
<y>0</y>
<width>500</width>
<height>700</height>
<height>825</height>
</rect>
</property>
<layout class="QGridLayout" name="shortcutLayout">
<item row="4" column="0" colspan="2">
<item row="6" column="0" colspan="2">
<widget class="QGroupBox" name="launchArgsGroup">
<property name="title">
<string/>
@@ -291,7 +291,7 @@
</property>
</widget>
</item>
<item row="6" column="1">
<item row="8" column="1">
<widget class="QDialogButtonBox" name="dialogButtons">
<property name="standardButtons">
<set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
@@ -301,7 +301,7 @@
</property>
</widget>
</item>
<item row="3" column="0">
<item row="5" column="0">
<widget class="QLabel" name="instruction">
<property name="text">
<string>Launch Options</string>
@@ -334,7 +334,7 @@
</layout>
</widget>
</item>
<item row="5" column="0">
<item row="7" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
@@ -347,11 +347,100 @@
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QLabel" name="iconLabel">
<property name="text">
<string>Icon</string>
</property>
<property name="buddy">
<cstring>browseIconButton</cstring>
</property>
</widget>
</item>
<item row="4" column="0" colspan="2">
<widget class="QGroupBox" name="iconGroup">
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="iconLayout">
<item row="1" column="2">
<widget class="QPushButton" name="resetIconButton">
<property name="toolTip">
<string>Reset to default application icon</string>
</property>
<property name="text">
<string>Reset</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="browseIconButton">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="2">
<widget class="QLabel" name="iconPreview">
<property name="minimumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>64</width>
<height>64</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::ContextMenuPolicy::NoContextMenu</enum>
</property>
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
<property name="textInteractionFlags">
<set>Qt::TextInteractionFlag::NoTextInteraction</set>
</property>
<property name="buddy">
<cstring>iconPath</cstring>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="iconPath">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>Default PCSX2 Icon</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>shortcutDesktop</tabstop>
<tabstop>shortcutStartMenu</tabstop>
<tabstop>iconPath</tabstop>
<tabstop>browseIconButton</tabstop>
<tabstop>resetIconButton</tabstop>
<tabstop>portableModeToggle</tabstop>
<tabstop>overrideBootELFToggle</tabstop>
<tabstop>overrideBootELFPath</tabstop>
@@ -360,6 +449,9 @@
<tabstop>gameArgs</tabstop>
<tabstop>bootOptionToggle</tabstop>
<tabstop>bootOptionDropdown</tabstop>
<tabstop>fastForwardOptionToggle</tabstop>
<tabstop>fastForwardTurboOption</tabstop>
<tabstop>fastForwardUnlimitedOption</tabstop>
<tabstop>fullscreenMode</tabstop>
<tabstop>fullscreenModeDropdown</tabstop>
<tabstop>bigPictureModeToggle</tabstop>
+4 -25
View File
@@ -337,10 +337,11 @@ namespace FontNames
{nullptr, "Noto Sans Devanagari"},
};
static constexpr FontLoadInfo Emoji[] = {
{"NotoColorEmoji-Regular.ttf"},
{"Twemoji.Mozilla.ttf"},
{"Seguiemj.ttf"},
// {nullptr, "Apple Color Emoji"}, // Freetype can't properly render Apple Color Emoji.
{nullptr, "Noto Color Emoji"},
{nullptr, "Twemoji Mozilla"},
// {nullptr, "Noto Color Emoji"}, // Noto Color Emoji comes in bitmap, SVG, and COLRv1 variants, none of which are supported
{nullptr, "Noto Emoji"},
};
static constexpr FontLoadInfo Hebrew[] = {
@@ -473,29 +474,7 @@ static std::span<const u8> TryLoadFont(FontSearchContext* ctx, const FontLoadInf
static bool ValidateFont(const FontLoadInfo& info, std::span<const u8> data)
{
if (info.face_name && 0 == strcmp(info.face_name, "Noto Color Emoji"))
{
// Noto Color Emoji comes in bitmap, SVG, and COLRv1 variants.
// We can only render the SVG variant.
if (data.size() < 8)
return false;
u32 magic_be;
u16 num_tables_be;
memcpy(&magic_be, &data[0], sizeof(u32));
memcpy(&num_tables_be, &data[4], sizeof(u16));
if (qFromBigEndian(magic_be) != 0x10000)
return false;
size_t num_tables = qFromBigEndian(num_tables_be);
if (data.size() < num_tables * 16 + 12)
return false;
for (size_t i = 0; i < num_tables; i++)
{
// Check if there's an "SVG " table
if (0 == memcmp(&data[i * 16 + 12], "SVG ", 4))
return true;
}
return false;
}
// We currently don't search for any fonts that might have unsupported versions installed on some OSes
return true;
}
File diff suppressed because it is too large Load Diff
+1
View File
@@ -39,6 +39,7 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DepsIncludeDir)\SDL3</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DepsIncludeDir)\kddockwidgets-qt6</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\fmt\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\winwil\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\lzma\include</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\simpleini\include</AdditionalIncludeDirectories>
+112 -61
View File
@@ -63,6 +63,10 @@ namespace Achievements
static constexpr float LEADERBOARD_STARTED_NOTIFICATION_TIME = 3.0f;
static constexpr float LEADERBOARD_FAILED_NOTIFICATION_TIME = 3.0f;
static constexpr const char* DEFAULT_INFO_SOUND_NAME = "sounds/achievements/message.wav";
static constexpr const char* DEFAULT_UNLOCK_SOUND_NAME = "sounds/achievements/unlock.wav";
static constexpr const char* DEFAULT_LBSUBMIT_SOUND_NAME = "sounds/achievements/lbsubmit.wav";
static constexpr float INDICATOR_FADE_IN_TIME = 0.1f;
static constexpr float INDICATOR_FADE_OUT_TIME = 0.5f;
@@ -455,9 +459,9 @@ bool Achievements::Initialize()
SettingsInterface* secretsInterface = Host::Internal::GetSecretsSettingsLayer();
secretsInterface->SetStringValue("Achievements", "Token", oldToken.c_str());
secretsInterface->Save();
oldToken.clear();
auto baseLock = Host::GetSettingsLock();
SettingsInterface* baseInterface = Host::Internal::GetBaseSettingsLayer();
baseInterface->DeleteValue("Achievements", "Token");
@@ -540,7 +544,7 @@ void Achievements::UpdateNotificationPosition()
{
// Set notification position based on achievement settings
float horizontal_position, vertical_position, direction;
// Determine horizontal alignment
switch (EmuConfig.Achievements.NotificationPosition)
{
@@ -549,13 +553,13 @@ void Achievements::UpdateNotificationPosition()
case OsdOverlayPos::BottomLeft:
horizontal_position = 0.0f; // Left
break;
case OsdOverlayPos::TopCenter:
case OsdOverlayPos::Center:
case OsdOverlayPos::BottomCenter:
horizontal_position = 0.5f; // Center
break;
case OsdOverlayPos::TopRight:
case OsdOverlayPos::CenterRight:
case OsdOverlayPos::BottomRight:
@@ -563,7 +567,7 @@ void Achievements::UpdateNotificationPosition()
horizontal_position = 1.0f; // Right
break;
}
// Determine vertical alignment and stacking direction
switch (EmuConfig.Achievements.NotificationPosition)
{
@@ -573,14 +577,14 @@ void Achievements::UpdateNotificationPosition()
vertical_position = 0.15f; // Top area
direction = 1.0f; // Stack downward
break;
case OsdOverlayPos::CenterLeft:
case OsdOverlayPos::Center:
case OsdOverlayPos::CenterRight:
vertical_position = 0.5f; // Center
direction = 1.0f; // Stack downward
break;
case OsdOverlayPos::BottomLeft:
case OsdOverlayPos::BottomCenter:
case OsdOverlayPos::BottomRight:
@@ -589,7 +593,7 @@ void Achievements::UpdateNotificationPosition()
direction = -1.0f; // Stack upward
break;
}
ImGuiFullscreen::SetNotificationPosition(horizontal_position, vertical_position, direction);
}
@@ -1142,7 +1146,11 @@ void Achievements::DisplayAchievementSummary()
}
if (EmuConfig.Achievements.SoundEffects && EmuConfig.Achievements.InfoSound)
Common::PlaySoundAsync(EmuConfig.Achievements.InfoSoundName.c_str());
Common::PlaySoundAsync(
(EmuConfig.Achievements.InfoSoundName.empty()
? Path::Combine(EmuFolders::Resources, DEFAULT_INFO_SOUND_NAME)
: EmuConfig.Achievements.InfoSoundName).c_str()
);
}
void Achievements::DisplayHardcoreDeferredMessage()
@@ -1194,7 +1202,11 @@ void Achievements::HandleUnlockEvent(const rc_client_event_t* event)
}
if (EmuConfig.Achievements.SoundEffects && EmuConfig.Achievements.UnlockSound)
Common::PlaySoundAsync(EmuConfig.Achievements.UnlockSoundName.c_str());
Common::PlaySoundAsync(
(EmuConfig.Achievements.UnlockSoundName.empty()
? Path::Combine(EmuFolders::Resources, DEFAULT_UNLOCK_SOUND_NAME)
: EmuConfig.Achievements.UnlockSoundName).c_str()
);
}
void Achievements::HandleGameCompleteEvent(const rc_client_event_t* event)
@@ -1315,7 +1327,11 @@ void Achievements::HandleLeaderboardSubmittedEvent(const rc_client_event_t* even
}
if (EmuConfig.Achievements.SoundEffects && EmuConfig.Achievements.LBSubmitSound)
Common::PlaySoundAsync(EmuConfig.Achievements.LBSubmitSoundName.c_str());
Common::PlaySoundAsync(
(EmuConfig.Achievements.LBSubmitSoundName.empty()
? Path::Combine(EmuFolders::Resources, DEFAULT_LBSUBMIT_SOUND_NAME)
: EmuConfig.Achievements.LBSubmitSoundName).c_str()
);
}
void Achievements::HandleLeaderboardScoreboardEvent(const rc_client_event_t* event)
@@ -1524,6 +1540,11 @@ void Achievements::DisableHardcoreMode()
if (RA_HardcoreModeIsActive())
RA_DisableHardcore();
if (s_hardcore_mode && !RA_HardcoreModeIsActive())
{
s_hardcore_mode = false;
Host::OnAchievementsHardcoreModeChanged(false);
}
return;
}
#endif
@@ -1537,6 +1558,18 @@ bool Achievements::ResetHardcoreMode(bool is_booting)
if (!IsActive())
return false;
#ifdef ENABLE_RAINTEGRATION
if (IsUsingRAIntegration())
{
const bool ra_hardcore = (RA_HardcoreModeIsActive() != 0);
if (ra_hardcore == s_hardcore_mode)
return false;
s_hardcore_mode = ra_hardcore;
Host::OnAchievementsHardcoreModeChanged(ra_hardcore);
return true;
}
#endif
const auto lock = GetLock();
// If we're not logged in, don't apply hardcore mode restrictions.
@@ -1833,7 +1866,7 @@ void Achievements::ClientLoginWithPasswordCallback(int result, const char* error
Host::SetBaseStringSettingValue("Achievements", "Username", params->username);
Host::SetBaseStringSettingValue("Achievements", "LoginTimestamp", fmt::format("{}", std::time(nullptr)).c_str());
Host::CommitBaseSettingChanges();
SettingsInterface* secretsInterface = Host::Internal::GetSecretsSettingsLayer();
secretsInterface->SetStringValue("Achievements", "Token", user->token);
secretsInterface->Save();
@@ -2032,7 +2065,7 @@ static ImVec2 CalculateOverlayPosition(const ImGuiIO& io, float padding, Achieve
static ImVec2 AdjustPositionForAlignment(const ImVec2& base_position, const ImVec2& element_size, AchievementOverlayPosition alignment)
{
ImVec2 adjusted = base_position;
// Adjust for horizontal alignment
switch (alignment)
{
@@ -2041,14 +2074,14 @@ static ImVec2 AdjustPositionForAlignment(const ImVec2& base_position, const ImVe
case AchievementOverlayPosition::BottomLeft:
// Left aligned no adjustment needed for x
break;
case AchievementOverlayPosition::TopCenter:
case AchievementOverlayPosition::Center:
case AchievementOverlayPosition::BottomCenter:
// Center aligned offset by half element width
adjusted.x -= element_size.x * 0.5f;
break;
case AchievementOverlayPosition::TopRight:
case AchievementOverlayPosition::CenterRight:
case AchievementOverlayPosition::BottomRight:
@@ -2057,7 +2090,7 @@ static ImVec2 AdjustPositionForAlignment(const ImVec2& base_position, const ImVe
adjusted.x -= element_size.x;
break;
}
// Adjust for vertical alignment
switch (alignment)
{
@@ -2066,14 +2099,14 @@ static ImVec2 AdjustPositionForAlignment(const ImVec2& base_position, const ImVe
case AchievementOverlayPosition::TopRight:
// Top aligned no adjustment needed for y
break;
case AchievementOverlayPosition::CenterLeft:
case AchievementOverlayPosition::Center:
case AchievementOverlayPosition::CenterRight:
// Center aligned offset by half element height
adjusted.y -= element_size.y * 0.5f;
break;
case AchievementOverlayPosition::BottomLeft:
case AchievementOverlayPosition::BottomCenter:
case AchievementOverlayPosition::BottomRight:
@@ -2082,7 +2115,7 @@ static ImVec2 AdjustPositionForAlignment(const ImVec2& base_position, const ImVe
adjusted.y -= element_size.y;
break;
}
return adjusted;
}
@@ -2094,19 +2127,19 @@ static ImVec2 GetStackingDirection(AchievementOverlayPosition alignment)
case AchievementOverlayPosition::TopCenter:
case AchievementOverlayPosition::TopRight:
return ImVec2(0.0f, 1.0f); // Stack downward
case AchievementOverlayPosition::BottomLeft:
case AchievementOverlayPosition::BottomCenter:
case AchievementOverlayPosition::BottomRight:
default:
return ImVec2(0.0f, -1.0f); // Stack upward
case AchievementOverlayPosition::CenterLeft:
return ImVec2(1.0f, 0.0f); // Stack rightward
case AchievementOverlayPosition::CenterRight:
return ImVec2(-1.0f, 0.0f); // Stack leftward
case AchievementOverlayPosition::Center:
return ImVec2(0.0f, -1.0f); // Stack upward for center
}
@@ -2147,7 +2180,7 @@ void Achievements::DrawGameOverlays()
{
dl->AddImage(reinterpret_cast<ImTextureID>(badge->GetNativeHandle()),
current_position, current_position + image_size, ImVec2(0.0f, 0.0f), ImVec2(1.0f, 1.0f), col);
// For horizontal layouts, go horizontally for vertical layouts, stay in the same row
if (std::abs(stack_direction.x) > 0.0f)
{
@@ -2198,7 +2231,7 @@ void Achievements::DrawGameOverlays()
const ImVec2 progress_box_size = ImVec2(image_size.x + text_size.x + spacing + padding * 2.0f, image_size.y + padding * 2.0f);
const ImVec2 stack_direction = GetStackingDirection(EmuConfig.Achievements.OverlayPosition);
const ImVec2 box_position = AdjustPositionForAlignment(position, progress_box_size, EmuConfig.Achievements.OverlayPosition);
const ImVec2 box_min = box_position;
const ImVec2 box_max = box_position + progress_box_size;
const float box_rounding = LayoutScale(1.0f);
@@ -2232,7 +2265,7 @@ void Achievements::DrawGameOverlays()
if (!s_active_leaderboard_trackers.empty() && EmuConfig.Achievements.LBOverlays)
{
const ImVec2 stack_direction = GetStackingDirection(EmuConfig.Achievements.OverlayPosition);
for (auto it = s_active_leaderboard_trackers.begin(); it != s_active_leaderboard_trackers.end();)
{
const LeaderboardTrackerIndicator& indicator = *it;
@@ -2247,7 +2280,7 @@ void Achievements::DrawGameOverlays()
const ImVec2 tracker_box_size = ImVec2(size.x + padding * 2.0f, size.y + padding * 2.0f);
const ImVec2 box_position = AdjustPositionForAlignment(position, tracker_box_size, EmuConfig.Achievements.OverlayPosition);
const ImVec2 box_min = box_position;
const ImVec2 box_max = box_position + tracker_box_size;
const float box_rounding = LayoutScale(1.0f);
@@ -2468,7 +2501,8 @@ void Achievements::DrawAchievementsWindow()
top += GetLineHeight(g_large_font) + spacing;
ImGui::PushFont(g_large_font.first, g_large_font.second);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::PopFont();
const ImRect summary_bb(ImVec2(left, top), ImVec2(right, top + GetLineHeight(g_medium_font)));
@@ -2599,7 +2633,8 @@ void Achievements::DrawAchievementsWindow()
const ImRect text_bb(ImVec2(text_x, bb.Min.y), ImVec2(bb.Max.x - padding, bb.Max.y));
ImGui::PushFont(g_medium_font.first, g_medium_font.second);
ImGui::RenderTextClipped(text_bb.Min, text_bb.Max, subset->title, nullptr, nullptr, ImVec2(0.0f, 0.5f), &text_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
text_bb.Min, text_bb.Max, subset->title, nullptr, nullptr, ImVec2(0.0f, 0.5f), &text_bb);
ImGui::PopFont();
if (ImGui::IsItemClicked() || ImGui::IsItemActivated())
@@ -2688,21 +2723,22 @@ void Achievements::DrawAchievementsWindow()
if (ImGuiFullscreen::IsGamepadInputSource())
{
const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons;
const auto glyphs = ImGuiFullscreen::GetGamepadGlyphs();
if (s_sidebar_has_focus)
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_DPAD_UP_DOWN, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, TRANSLATE_SV("Achievements", "Back to List")),
std::make_pair(circleOK ? ICON_PF_BUTTON_CIRCLE : ICON_PF_BUTTON_CROSS, TRANSLATE_SV("Achievements", "Select")),
std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, TRANSLATE_SV("Achievements", "Back")),
std::make_pair(glyphs.dpad_ud, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(glyphs.dpad_lr, TRANSLATE_SV("Achievements", "Back to List")),
std::make_pair(glyphs.confirm(circleOK), TRANSLATE_SV("Achievements", "Select")),
std::make_pair(glyphs.cancel(circleOK), TRANSLATE_SV("Achievements", "Back")),
});
}
else
{
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(ICON_PF_DPAD_UP_DOWN, TRANSLATE_SV("Achievements", "Change Selection")),
std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, TRANSLATE_SV("Achievements", "Back")),
std::make_pair(glyphs.dpad_lr, TRANSLATE_SV("Achievements", "Navigate Subsets")),
std::make_pair(glyphs.dpad_ud, TRANSLATE_SV("Achievements", "Change Selection")),
std::make_pair(glyphs.cancel(circleOK), TRANSLATE_SV("Achievements", "Back")),
});
}
}
@@ -2878,8 +2914,9 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
ImVec2(points_template_start + ((points_template_size.x - right_icon_size.x) * 0.5f), bb.Min.y), ImVec2(bb.Max.x, midpoint));
ImGui::PushFont(g_large_font.first, g_large_font.second);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, cheevo->title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::RenderTextClipped(lock_bb.Min, lock_bb.Max, right_icon_text, nullptr, &right_icon_size, ImVec2(0.0f, 0.0f), &lock_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, cheevo->title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
lock_bb.Min, lock_bb.Max, right_icon_text, nullptr, &right_icon_size, ImVec2(0.0f, 0.0f), &lock_bb);
ImGui::PopFont();
if (badge_text && badge_icon)
@@ -2905,14 +2942,16 @@ void Achievements::DrawAchievement(const rc_client_achievement_t* cheevo)
{
ImGui::RenderTextWrapped(summary_bb.Min, cheevo->description, cheevo->description + summary_length, summary_wrap_width);
}
ImGui::RenderTextClipped(points_bb.Min, points_bb.Max, text.c_str(), text.end_ptr(), &points_size, ImVec2(0.0f, 0.0f), &points_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
points_bb.Min, points_bb.Max, text.c_str(), text.end_ptr(), &points_size, ImVec2(0.0f, 0.0f), &points_bb);
if (is_unlocked)
{
text.format(TRANSLATE_FS("Achievements", "Unlocked: {}"), FullscreenUI::TimeToPrintableString(cheevo->unlock_time));
const ImRect unlock_bb(summary_bb.Min.x, summary_bb.Max.y + spacing, summary_bb.Max.x, bb.Max.y);
ImGui::RenderTextClipped(unlock_bb.Min, unlock_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &unlock_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
unlock_bb.Min, unlock_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &unlock_bb);
}
else if (is_measured)
{
@@ -3071,7 +3110,8 @@ void Achievements::DrawLeaderboardsWindow()
top += GetLineHeight(g_large_font) + spacing;
ImGui::PushFont(g_large_font.first, g_large_font.second);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
title_bb.Min, title_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::PopFont();
if (is_leaderboard_open)
@@ -3082,7 +3122,7 @@ void Achievements::DrawLeaderboardsWindow()
top += GetLineHeight(g_large_font) + spacing_small;
ImGui::PushFont(g_large_font.first, g_large_font.second);
ImGui::RenderTextClipped(
ImGuiFullscreen::RenderTextClippedWithShadow(
subtitle_bb.Min, subtitle_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &subtitle_bb);
ImGui::PopFont();
@@ -3100,7 +3140,7 @@ void Achievements::DrawLeaderboardsWindow()
top += GetLineHeight(g_medium_font) + spacing_small;
ImGui::PushFont(g_medium_font.first, g_medium_font.second);
ImGui::RenderTextClipped(
ImGuiFullscreen::RenderTextClippedWithShadow(
summary_bb.Min, summary_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &summary_bb);
if (!is_leaderboard_open && !Achievements::IsHardcoreModeActive())
@@ -3108,9 +3148,9 @@ void Achievements::DrawLeaderboardsWindow()
const ImRect hardcore_warning_bb(ImVec2(left, top), ImVec2(right, top + GetLineHeight(g_medium_font)));
top += GetLineHeight(g_medium_font) + spacing_small;
ImGui::RenderTextClipped(hardcore_warning_bb.Min, hardcore_warning_bb.Max,
TRANSLATE("Achievements", "Submitting scores is disabled because hardcore mode is off. Leaderboards are read-only."),
nullptr, nullptr, ImVec2(0.0f, 0.0f), &hardcore_warning_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(hardcore_warning_bb.Min, hardcore_warning_bb.Max,
TRANSLATE("Achievements", "Submitting scores is disabled because hardcore mode is off. Leaderboards are read-only."), nullptr,
nullptr, ImVec2(0.0f, 0.0f), &hardcore_warning_bb);
}
ImGui::PopFont();
@@ -3159,7 +3199,7 @@ void Achievements::DrawLeaderboardsWindow()
const auto render_centered_heading = [&](const char* text, float width) {
const ImRect rect(ImVec2(column_left, bb.Min.y), ImVec2(column_left + width, midpoint));
ImGui::RenderTextClipped(rect.Min, rect.Max, text, nullptr, nullptr, ImVec2(0.5f, 0.0f), &rect);
ImGuiFullscreen::RenderTextClippedWithShadow(rect.Min, rect.Max, text, nullptr, nullptr, ImVec2(0.5f, 0.0f), &rect);
column_left += width + column_spacing;
};
@@ -3168,7 +3208,7 @@ void Achievements::DrawLeaderboardsWindow()
const float name_column_total_width = icon_column_width + column_spacing + name_column_width;
const ImRect user_bb(ImVec2(column_left + icon_column_width + column_spacing, bb.Min.y),
ImVec2(column_left + name_column_total_width, midpoint));
ImGui::RenderTextClipped(
ImGuiFullscreen::RenderTextClippedWithShadow(
user_bb.Min, user_bb.Max, TRANSLATE("Achievements", "Name"), nullptr, nullptr, ImVec2(0.5f, 0.0f), &user_bb);
column_left += name_column_total_width + column_spacing;
@@ -3185,8 +3225,8 @@ void Achievements::DrawLeaderboardsWindow()
const float date_column_width = std::max(bb.Max.x - column_left, 0.0f);
const ImRect date_bb(ImVec2(column_left, bb.Min.y), ImVec2(column_left + date_column_width, midpoint));
ImGui::RenderTextClipped(date_bb.Min, date_bb.Max, TRANSLATE("Achievements", "Date Submitted"), nullptr, nullptr,
ImVec2(0.5f, 0.0f), &date_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
date_bb.Min, date_bb.Max, TRANSLATE("Achievements", "Date Submitted"), nullptr, nullptr, ImVec2(0.5f, 0.0f), &date_bb);
column_left += date_column_width;
ImGui::PopFont();
@@ -3303,10 +3343,11 @@ void Achievements::DrawLeaderboardsWindow()
if (ImGuiFullscreen::IsGamepadInputSource())
{
const bool circleOK = ImGui::GetIO().ConfigNavSwapGamepadButtons;
const auto glyphs = ImGuiFullscreen::GetGamepadGlyphs();
ImGuiFullscreen::SetFullscreenFooterText(std::array{
std::make_pair(ICON_PF_DPAD_LEFT_RIGHT, TRANSLATE_SV("Achievements", "Switch Rankings")),
std::make_pair(ICON_PF_DPAD_UP_DOWN, TRANSLATE_SV("Achievements", "Change Selection")),
std::make_pair(circleOK ? ICON_PF_BUTTON_CROSS : ICON_PF_BUTTON_CIRCLE, TRANSLATE_SV("Achievements", "Back")),
std::make_pair(glyphs.dpad_lr, TRANSLATE_SV("Achievements", "Switch Rankings")),
std::make_pair(glyphs.dpad_ud, TRANSLATE_SV("Achievements", "Change Selection")),
std::make_pair(glyphs.cancel(circleOK), TRANSLATE_SV("Achievements", "Back")),
});
}
else
@@ -3353,7 +3394,8 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(255, 242, 0, 255));
const ImRect rank_bb(ImVec2(column_left, bb.Min.y), ImVec2(column_left + rank_column_width, midpoint));
ImGui::RenderTextClipped(rank_bb.Min, rank_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &rank_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
rank_bb.Min, rank_bb.Max, text.c_str(), text.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &rank_bb);
column_left += rank_column_width + column_spacing;
const ImRect icon_bb(ImVec2(column_left, bb.Min.y), ImVec2(column_left + icon_column_width, bb.Min.y + icon_column_width));
@@ -3383,16 +3425,18 @@ void Achievements::DrawLeaderboardEntry(const rc_client_leaderboard_entry_t& ent
column_left += icon_column_width + column_spacing;
const ImRect user_bb(ImVec2(column_left, bb.Min.y), ImVec2(column_left + name_column_width, midpoint));
ImGui::RenderTextClipped(user_bb.Min, user_bb.Max, entry.user, nullptr, nullptr, ImVec2(0.0f, 0.0f), &user_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(user_bb.Min, user_bb.Max, entry.user, nullptr, nullptr, ImVec2(0.0f, 0.0f), &user_bb);
column_left += name_column_width + column_spacing;
const ImRect score_bb(ImVec2(column_left, bb.Min.y), ImVec2(column_left + time_column_width, midpoint));
ImGui::RenderTextClipped(score_bb.Min, score_bb.Max, entry.display, nullptr, nullptr, ImVec2(0.0f, 0.0f), &score_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
score_bb.Min, score_bb.Max, entry.display, nullptr, nullptr, ImVec2(0.0f, 0.0f), &score_bb);
column_left += time_column_width + column_spacing;
const ImRect time_bb(ImVec2(column_left, bb.Min.y), ImVec2(bb.Max.x, midpoint));
const auto submit_time = FullscreenUI::TimeToPrintableString(entry.submitted);
ImGui::RenderTextClipped(time_bb.Min, time_bb.Max, submit_time.c_str(), submit_time.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &time_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
time_bb.Min, time_bb.Max, submit_time.c_str(), submit_time.end_ptr(), nullptr, ImVec2(0.0f, 0.0f), &time_bb);
if (is_self)
ImGui::PopStyleColor();
@@ -3436,13 +3480,14 @@ void Achievements::DrawLeaderboardListEntry(const rc_client_leaderboard_t* lboar
const ImRect summary_bb(ImVec2(text_start_x, midpoint), bb.Max);
ImGui::PushFont(g_large_font.first, g_large_font.second);
ImGui::RenderTextClipped(title_bb.Min, title_bb.Max, lboard->title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(title_bb.Min, title_bb.Max, lboard->title, nullptr, nullptr, ImVec2(0.0f, 0.0f), &title_bb);
ImGui::PopFont();
if (lboard->description && lboard->description[0] != '\0')
{
ImGui::PushFont(g_medium_font.first, g_medium_font.second);
ImGui::RenderTextClipped(summary_bb.Min, summary_bb.Max, lboard->description, nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb);
ImGuiFullscreen::RenderTextClippedWithShadow(
summary_bb.Min, summary_bb.Max, lboard->description, nullptr, nullptr, ImVec2(0.0f, 0.0f), &summary_bb);
ImGui::PopFont();
}
@@ -3693,7 +3738,13 @@ void Achievements::RAIntegration::RACallbackCausePause()
void Achievements::RAIntegration::RACallbackRebuildMenu()
{
// unused, we build the menu on demand
// Sync hardcore state in case the user changed it via the RA menu.
const bool ra_hardcore = (RA_HardcoreModeIsActive() != 0);
if (ra_hardcore != s_hardcore_mode)
{
s_hardcore_mode = ra_hardcore;
Host::OnAchievementsHardcoreModeChanged(ra_hardcore);
}
}
void Achievements::RAIntegration::RACallbackEstimateTitle(char* buf)
+2 -1
View File
@@ -544,6 +544,7 @@ set(pcsx2GSHeaders
GS/Renderers/Common/GSFastList.h
GS/Renderers/Common/GSFunctionMap.h
GS/Renderers/Common/GSRenderer.h
GS/Renderers/Common/GSShaderEnums.h
GS/Renderers/Common/GSTexture.h
GS/Renderers/Common/GSVertex.h
GS/Renderers/Common/GSVertexTrace.h
@@ -1276,7 +1277,7 @@ function(setup_main_executable target)
if (NOT WIN32 AND "${path}" MATCHES "/dx11/") # Don't include unneccessary stuff
continue()
endif()
if (NOT BUNDLE_EMOJI_FONT AND "${path}" MATCHES "fonts/NotoColorEmoji")
if (NOT BUNDLE_EMOJI_FONT AND "${path}" MATCHES "fonts/Twemoji")
continue()
endif()
pcsx2_resource(${target} ${path} ${CMAKE_SOURCE_DIR}/bin/resources/)
+3 -3
View File
@@ -792,6 +792,7 @@ struct Pcsx2Config
Mipmap : 1,
HWMipmap : 1,
HWAccurateAlphaTest: 1,
HWAA1 : 1,
ManualUserHacks : 1,
UserHacks_AlignSpriteX : 1,
UserHacks_CPUFBConversion : 1,
@@ -804,6 +805,7 @@ struct Pcsx2Config
UserHacks_ForceEvenSpritePosition : 1,
UserHacks_NativePaletteDraw : 1,
UserHacks_EstimateTextureRegion : 1,
UserHacks_DrawBuffering : 1,
FXAA : 1,
ShadeBoost : 1,
DumpGSData : 1,
@@ -1285,9 +1287,6 @@ struct Pcsx2Config
static constexpr u32 MAXIMUM_NOTIFICATION_DURATION = 30;
static constexpr u32 DEFAULT_NOTIFICATION_DURATION = 5;
static constexpr u32 DEFAULT_LEADERBOARD_DURATION = 10;
static constexpr const char* DEFAULT_INFO_SOUND_NAME = "sounds/achievements/message.wav";
static constexpr const char* DEFAULT_UNLOCK_SOUND_NAME = "sounds/achievements/unlock.wav";
static constexpr const char* DEFAULT_LBSUBMIT_SOUND_NAME = "sounds/achievements/lbsubmit.wav";
static const char* OverlayPositionNames[(size_t)AchievementOverlayPosition::MaxCount + 1];
@@ -1404,6 +1403,7 @@ struct Pcsx2Config
std::string CurrentBlockdump;
std::string CurrentIRX;
std::string CurrentGameArgs;
std::string CustomDataPath;
AspectRatioType CurrentAspectRatio = AspectRatioType::RAuto4_3_3_2;
// Fall back aspect ratio for games that have patches (when AspectRatioType::RAuto4_3_3_2) is active.
float CurrentCustomAspectRatio = 0.f;
+1 -1
View File
@@ -876,7 +876,7 @@ static __fi void rcntEndGate(bool isVblank, u64 sCycle)
isVblank ? "vblank" : "hblank", counters[i].mode.GateMode, counters[i].count);
counters[i].count = 0;
counters[i].target &= 0xffff;
counters[i].startCycle = sCycle & ~(counters[i].rate - 1);
counters[i].startCycle = sCycle & ~(static_cast<u64>(counters[i].rate - 1));
break;
}
}
+4 -3
View File
@@ -49,7 +49,8 @@ std::vector<std::unique_ptr<BiosThread>> getIOPThreads()
return {};
}
data.stackTop = iopMemRead32(item + 0x3c);
data.stacMem = iopMemRead32(item + 0x3c);
data.stackSize = iopMemRead32(item + 0x40);
data.status = iopMemRead8(item + 0xc);
data.tid = iopMemRead16(item + 0xa);
data.entrypoint = iopMemRead32(item + 0x38);
@@ -57,9 +58,9 @@ std::vector<std::unique_ptr<BiosThread>> getIOPThreads()
data.waitId = iopMemRead32(item + 0x20);
data.initPriority = iopMemRead16(item + 0xe);
data.SavedSP = iopMemRead32(item + 0x10);
data.regCtx = iopMemRead32(item + 0x10);
data.PC = iopMemRead32(data.SavedSP + 0x8c);
data.PC = iopMemRead32(data.regCtx + 0x8c);
threads.emplace_back(std::make_unique<IOPThread>(data));
+29 -16
View File
@@ -18,26 +18,37 @@ enum class ThreadStatus
THS_DORMANT = 0x10,
};
struct EEInternalCtx
{
u32 sa;
u32 fcsr;
u32 float_thing;
u32 unk;
// gpr excluding $zero
// k0/k1 contains hi, hi1, lo, lo1
u128 gpr[31];
float fpr[32];
};
struct EEInternalThread
{ // internal struct
u32 prev;
u32 next;
int status;
u32 entry;
u32 stack;
u32 resumeAddr; // address to return to when switching
u32 regCtx; // points to the saved regs on stack
u32 gpReg;
short currentPriority;
short initPriority;
short currentPriority;
int waitType;
int semaId;
int wakeupCount;
int attr;
int option;
u32 entry_init;
u32 entry;
int argc;
u32 argstring;
u32 stack_bottom; //FIXME
u32 stackMem;
int stackSize;
u32 root;
u32 heap_base;
@@ -48,8 +59,9 @@ struct IOPInternalThread
{
u32 tid;
u32 PC;
u32 stackTop;
u32 SavedSP;
u32 stacMem;
u32 stackSize;
u32 regCtx;
u32 status;
u32 entrypoint;
u32 waitstate;
@@ -71,14 +83,13 @@ enum class IOPWaitStatus
enum class EEWaitStatus
{
WAIT_NONE = 0,
WAIT_WAKEUP_REQ = 1,
WAIT_SLEEP = 1,
WAIT_SEMA = 2,
};
enum class WaitState
{
NONE,
WAKEUP_REQ,
SEMA,
SLEEP,
DELAY,
@@ -98,8 +109,10 @@ public:
[[nodiscard]] virtual WaitState Wait() const = 0;
[[nodiscard]] virtual u32 WaitId() const = 0;
[[nodiscard]] virtual u32 EntryPoint() const = 0;
[[nodiscard]] virtual u32 StackTop() const = 0;
[[nodiscard]] virtual u32 Priority() const = 0;
// Only call RegCtx on threads that aren't running
[[nodiscard]] virtual u32 RegCtx() const = 0;
};
class EEThread : public BiosThread
@@ -113,7 +126,7 @@ public:
~EEThread() override = default;
[[nodiscard]] u32 TID() const override { return tid; };
[[nodiscard]] u32 PC() const override { return data.entry; };
[[nodiscard]] u32 PC() const override { return data.resumeAddr; };
[[nodiscard]] ThreadStatus Status() const override { return static_cast<ThreadStatus>(data.status); };
[[nodiscard]] WaitState Wait() const override
{
@@ -122,17 +135,17 @@ public:
{
case EEWaitStatus::WAIT_NONE:
return WaitState::NONE;
case EEWaitStatus::WAIT_WAKEUP_REQ:
return WaitState::WAKEUP_REQ;
case EEWaitStatus::WAIT_SLEEP:
return WaitState::SLEEP;
case EEWaitStatus::WAIT_SEMA:
return WaitState::SEMA;
}
return WaitState::NONE;
};
[[nodiscard]] u32 WaitId() const override { return data.semaId; };
[[nodiscard]] u32 EntryPoint() const override { return data.entry_init; };
[[nodiscard]] u32 StackTop() const override { return data.stack; };
[[nodiscard]] u32 EntryPoint() const override { return data.entry; };
[[nodiscard]] u32 Priority() const override { return data.currentPriority; };
[[nodiscard]] u32 RegCtx() const override { return data.regCtx; };
private:
u32 tid;
@@ -175,8 +188,8 @@ public:
};
[[nodiscard]] u32 WaitId() const override { return data.waitId; };
[[nodiscard]] u32 EntryPoint() const override { return data.entrypoint; };
[[nodiscard]] u32 StackTop() const override { return data.stackTop; };
[[nodiscard]] u32 Priority() const override { return data.initPriority; };
[[nodiscard]] u32 RegCtx() const override { return data.regCtx; };
private:
IOPInternalThread data;
+253 -209
View File
@@ -14,6 +14,7 @@
#include "R3000A.h"
#include "IopMem.h"
#include "VMManager.h"
#include "vtlb.h"
#include "common/StringUtil.h"
@@ -74,7 +75,7 @@ char* DebugInterface::stringFromPointer(u32 p)
// Hopefully the checks in isValidAddress() are sufficient.
for (u32 i = 0; i < BUFFER_LEN; i++)
{
char c = read8(p + i);
char c = Read8(p + i);
buf[i] = c;
if (c == 0)
@@ -121,7 +122,7 @@ std::optional<u32> DebugInterface::getStackFrameSize(const ccc::Function& functi
// start of the current function that is in the form of
// "addiu $sp, $sp, frame_size" instead.
u32 instruction = read32(function.address().value);
u32 instruction = Read32(function.address().value);
if ((instruction & 0xffff0000) == 0x27bd0000)
stack_frame_size = -static_cast<s16>(instruction & 0xffff);
@@ -209,167 +210,140 @@ const char* DebugInterface::longCpuName(BreakPointCpu cpu)
return "";
}
//
// R5900DebugInterface
//
// *****************************************************************************
BreakPointCpu R5900DebugInterface::getCpuType()
{
return BREAKPOINT_EE;
}
u32 R5900DebugInterface::read8(u32 address)
static int InvalidReadResult(bool* valid)
{
if (valid)
*valid = false;
return -1;
}
u8 R5900DebugInterface::Read8(u32 address, bool* valid)
{
if (!isValidAddress(address))
return -1;
return static_cast<u8>(InvalidReadResult(valid));
u8 value;
if (!vtlb_memSafeReadBytes(address, &value, sizeof(u8)))
return -1;
if (!vtlb_memSafeReadBytes(address, &value, sizeof(value)))
return static_cast<u8>(InvalidReadResult(valid));
if (valid)
*valid = true;
return value;
}
u32 R5900DebugInterface::read8(u32 address, bool& valid)
u16 R5900DebugInterface::Read16(u32 address, bool* valid)
{
if (!(valid = isValidAddress(address)))
return -1;
u8 value;
if (!(valid = vtlb_memSafeReadBytes(address, &value, sizeof(u8))))
return -1;
return value;
}
u32 R5900DebugInterface::read16(u32 address)
{
if (!isValidAddress(address) || address % 2)
return -1;
if (!isValidAddress(address))
return static_cast<u16>(InvalidReadResult(valid));
u16 value;
if (!vtlb_memSafeReadBytes(address, &value, sizeof(u16)))
return -1;
if (!vtlb_memSafeReadBytes(address, &value, sizeof(value)))
return static_cast<u16>(InvalidReadResult(valid));
return static_cast<u32>(value);
if (valid)
*valid = true;
return value;
}
u32 R5900DebugInterface::read16(u32 address, bool& valid)
u32 R5900DebugInterface::Read32(u32 address, bool* valid)
{
if (!(valid = (isValidAddress(address) || address % 2)))
return -1;
u16 value;
if (!(valid = vtlb_memSafeReadBytes(address, &value, sizeof(u16))))
return -1;
return static_cast<u32>(value);
}
u32 R5900DebugInterface::read32(u32 address)
{
if (!isValidAddress(address) || address % 4)
return -1;
if (!isValidAddress(address))
return static_cast<u32>(InvalidReadResult(valid));
u32 value;
if (!vtlb_memSafeReadBytes(address, &value, sizeof(u32)))
return -1;
if (!vtlb_memSafeReadBytes(address, &value, sizeof(value)))
return static_cast<u32>(InvalidReadResult(valid));
if (valid)
*valid = true;
return value;
}
u32 R5900DebugInterface::read32(u32 address, bool& valid)
u64 R5900DebugInterface::Read64(u32 address, bool* valid)
{
if (!(valid = (isValidAddress(address) || address % 4)))
return -1;
u32 value;
if (!(valid = vtlb_memSafeReadBytes(address, &value, sizeof(u32))))
return -1;
return value;
}
u64 R5900DebugInterface::read64(u32 address)
{
if (!isValidAddress(address) || address % 8)
return -1;
if (!isValidAddress(address))
return static_cast<u64>(InvalidReadResult(valid));
u64 value;
if (!vtlb_memSafeReadBytes(address, &value, sizeof(u64)))
return -1;
if (!vtlb_memSafeReadBytes(address, &value, sizeof(value)))
return static_cast<u64>(InvalidReadResult(valid));
if (valid)
*valid = true;
return value;
}
static u128 InvalidReadResult128(bool* valid)
{
if (valid)
*valid = false;
u128 value;
value.lo = static_cast<u64>(-1);
value.hi = static_cast<u64>(-1);
return value;
}
u128 R5900DebugInterface::Read128(u32 address, bool* valid)
{
if (!isValidAddress(address))
return InvalidReadResult128(valid);
u128 value;
if (!vtlb_memSafeReadBytes(address, &value, sizeof(u128)))
return InvalidReadResult128(valid);
if (valid)
*valid = true;
return value;
}
u64 R5900DebugInterface::read64(u32 address, bool& valid)
bool R5900DebugInterface::ReadBytes(u32 address, void* dest, u32 size)
{
if (!(valid = (isValidAddress(address) || address % 8)))
return -1;
u64 value;
if (!(valid = vtlb_memSafeReadBytes(address, &value, sizeof(u64))))
return -1;
return value;
return vtlb_memSafeReadBytes(address, dest, size);
}
u128 R5900DebugInterface::read128(u32 address)
bool R5900DebugInterface::Write8(u32 address, u8 value)
{
alignas(16) u128 result;
if (!isValidAddress(address) || address % 16)
{
result.hi = result.lo = -1;
return result;
}
if (!vtlb_memSafeReadBytes(address, &result, sizeof(u128)))
{
result.hi = result.lo = -1;
}
return result;
return isValidAddress(address) && vtlb_memSafeWriteBytes(address, &value, sizeof(value));
}
void R5900DebugInterface::write8(u32 address, u8 value)
bool R5900DebugInterface::Write16(u32 address, u16 value)
{
if (!isValidAddress(address))
return;
vtlb_memSafeWriteBytes(address, &value, sizeof(u8));
return isValidAddress(address) && vtlb_memSafeWriteBytes(address, &value, sizeof(value));
}
void R5900DebugInterface::write16(u32 address, u16 value)
bool R5900DebugInterface::Write32(u32 address, u32 value)
{
if (!isValidAddress(address))
return;
vtlb_memSafeWriteBytes(address, &value, sizeof(u16));
return isValidAddress(address) && vtlb_memSafeWriteBytes(address, &value, sizeof(value));
}
void R5900DebugInterface::write32(u32 address, u32 value)
bool R5900DebugInterface::Write64(u32 address, u64 value)
{
if (!isValidAddress(address))
return;
vtlb_memSafeWriteBytes(address, &value, sizeof(u32));
return isValidAddress(address) && vtlb_memSafeWriteBytes(address, &value, sizeof(value));
}
void R5900DebugInterface::write64(u32 address, u64 value)
bool R5900DebugInterface::Write128(u32 address, u128 value)
{
if (!isValidAddress(address))
return;
vtlb_memSafeWriteBytes(address, &value, sizeof(u64));
return isValidAddress(address) && vtlb_memSafeWriteBytes(address, &value, sizeof(value));
}
void R5900DebugInterface::write128(u32 address, u128 value)
bool R5900DebugInterface::WriteBytes(u32 address, void* src, u32 size)
{
if (!isValidAddress(address))
return;
return vtlb_memSafeWriteBytes(address, src, size);
}
vtlb_memSafeWriteBytes(address, &value, sizeof(u128));
bool R5900DebugInterface::CompareBytes(u32 address, void* src, u32 size)
{
return vtlb_memSafeCmpBytes(address, src, size) == 0;
}
int R5900DebugInterface::getRegisterCategoryCount()
@@ -650,7 +624,7 @@ std::string R5900DebugInterface::disasm(u32 address, bool simplify)
{
std::string out;
u32 op = read32(address);
u32 op = Read32(address);
R5900::disR5900Fasm(out, op, address, simplify);
return out;
}
@@ -734,6 +708,23 @@ std::vector<std::unique_ptr<BiosThread>> R5900DebugInterface::GetThreadList() co
return getEEThreads();
}
std::vector<MipsStackWalk::StackFrame> R5900DebugInterface::StackTrace(const BiosThread& thread)
{
if (thread.Status() == ThreadStatus::THS_RUN)
{
return MipsStackWalk::Walk(this, getPC(), getRegister(0, 31), getRegister(0, 29),
thread.EntryPoint());
}
EEInternalCtx* ctx = static_cast<EEInternalCtx*>(PSM(thread.RegCtx()));
u32 pc = thread.PC();
// $zero is not in the array so subtract 1
u32 ra = ctx->gpr[31 - 1]._u32[0];
u32 sp = ctx->gpr[29 - 1]._u32[0];
return MipsStackWalk::Walk(this, pc, ra, sp, thread.EntryPoint());
}
std::vector<IopMod> R5900DebugInterface::GetModuleList() const
{
return {};
@@ -748,106 +739,114 @@ BreakPointCpu R3000DebugInterface::getCpuType()
return BREAKPOINT_IOP;
}
u32 R3000DebugInterface::read8(u32 address)
u8 R3000DebugInterface::Read8(u32 address, bool* valid)
{
if (!isValidAddress(address))
return -1;
return iopMemRead8(address);
return static_cast<u8>(InvalidReadResult(valid));
u8 value = iopMemRead8(address);
if (valid)
*valid = true;
return value;
}
u32 R3000DebugInterface::read8(u32 address, bool& valid)
{
if (!(valid = isValidAddress(address)))
return -1;
return iopMemRead8(address);
}
u32 R3000DebugInterface::read16(u32 address)
u16 R3000DebugInterface::Read16(u32 address, bool* valid)
{
if (!isValidAddress(address))
return -1;
return iopMemRead16(address);
return static_cast<u16>(InvalidReadResult(valid));
u16 value = iopMemRead16(address);
if (valid)
*valid = true;
return value;
}
u32 R3000DebugInterface::read16(u32 address, bool& valid)
{
if (!(valid = isValidAddress(address)))
return -1;
return iopMemRead16(address);
}
u32 R3000DebugInterface::read32(u32 address)
u32 R3000DebugInterface::Read32(u32 address, bool* valid)
{
if (!isValidAddress(address))
return -1;
return iopMemRead32(address);
return static_cast<u32>(InvalidReadResult(valid));
u32 value = iopMemRead32(address);
if (valid)
*valid = true;
return value;
}
u32 R3000DebugInterface::read32(u32 address, bool& valid)
u64 R3000DebugInterface::Read64(u32 address, bool* valid)
{
if (!(valid = isValidAddress(address)))
return -1;
return iopMemRead32(address);
return InvalidReadResult(valid);
}
u64 R3000DebugInterface::read64(u32 address)
u128 R3000DebugInterface::Read128(u32 address, bool* valid)
{
return 0;
return InvalidReadResult128(valid);
}
u64 R3000DebugInterface::read64(u32 address, bool& valid)
bool R3000DebugInterface::ReadBytes(u32 address, void* dest, u32 size)
{
return 0;
return iopMemSafeReadBytes(address, dest, size);
}
u128 R3000DebugInterface::read128(u32 address)
{
return u128::From32(0);
}
void R3000DebugInterface::write8(u32 address, u8 value)
bool R3000DebugInterface::Write8(u32 address, u8 value)
{
if (!isValidAddress(address))
return;
return false;
iopMemWrite8(address, value);
return true;
}
void R3000DebugInterface::write16(u32 address, u16 value)
bool R3000DebugInterface::Write16(u32 address, u16 value)
{
if (!isValidAddress(address))
return;
return false;
iopMemWrite16(address, value);
return true;
}
void R3000DebugInterface::write32(u32 address, u32 value)
bool R3000DebugInterface::Write32(u32 address, u32 value)
{
if (!isValidAddress(address))
return;
return false;
iopMemWrite32(address, value);
return true;
}
void R3000DebugInterface::write64(u32 address, u64 value)
bool R3000DebugInterface::Write64(u32 address, u64 value)
{
if (!isValidAddress(address))
return;
return false;
iopMemWrite32(address + 0, value);
iopMemWrite32(address + 4, value >> 32);
return true;
}
void R3000DebugInterface::write128(u32 address, u128 value)
bool R3000DebugInterface::Write128(u32 address, u128 value)
{
if (!isValidAddress(address))
return;
return false;
iopMemWrite32(address + 0x0, value._u32[0]);
iopMemWrite32(address + 0x4, value._u32[1]);
iopMemWrite32(address + 0x8, value._u32[2]);
iopMemWrite32(address + 0xc, value._u32[3]);
return true;
}
bool R3000DebugInterface::WriteBytes(u32 address, void* src, u32 size)
{
return iopMemSafeWriteBytes(address, src, size);
}
bool R3000DebugInterface::CompareBytes(u32 address, void* src, u32 size)
{
return iopMemSafeCmpBytes(address, src, size) == 0;
}
int R3000DebugInterface::getRegisterCategoryCount()
@@ -1016,7 +1015,7 @@ std::string R3000DebugInterface::disasm(u32 address, bool simplify)
{
std::string out;
u32 op = read32(address);
u32 op = Read32(address);
R5900::disR5900Fasm(out, op, address, simplify);
return out;
}
@@ -1067,95 +1066,140 @@ std::vector<std::unique_ptr<BiosThread>> R3000DebugInterface::GetThreadList() co
return getIOPThreads();
}
std::vector<MipsStackWalk::StackFrame> R3000DebugInterface::StackTrace(const BiosThread& thread)
{
if (thread.Status() == ThreadStatus::THS_RUN)
{
return MipsStackWalk::Walk(this, getPC(), getRegister(0, 31), getRegister(0, 29),
thread.EntryPoint());
}
u32 p = thread.RegCtx();
u32 pc = Read32(p + 0x8c);
u32 ra = Read32(p + 0x7c);
u32 sp = Read32(p + 0x74);
return MipsStackWalk::Walk(this, pc, ra, sp, thread.EntryPoint());
}
std::vector<IopMod> R3000DebugInterface::GetModuleList() const
{
return getIOPModules();
}
// *****************************************************************************
ElfMemoryReader::ElfMemoryReader(const ccc::ElfFile& elf)
: m_elf(elf)
{
}
u32 ElfMemoryReader::read8(u32 address)
u8 ElfMemoryReader::Read8(u32 address, bool* valid)
{
std::optional<u8> result = m_elf.get_object_virtual<u8>(address);
if (!result.has_value())
return 0;
return InvalidReadResult(valid);
if (valid)
*valid = true;
return *result;
}
u32 ElfMemoryReader::read8(u32 address, bool& valid)
{
std::optional<u8> result = m_elf.get_object_virtual<u8>(address);
valid = result.has_value();
if (!valid)
return 0;
return *result;
}
u32 ElfMemoryReader::read16(u32 address)
u16 ElfMemoryReader::Read16(u32 address, bool* valid)
{
std::optional<u16> result = m_elf.get_object_virtual<u16>(address);
if (!result.has_value())
return 0;
return InvalidReadResult(valid);
if (valid)
*valid = true;
return *result;
}
u32 ElfMemoryReader::read16(u32 address, bool& valid)
{
std::optional<u16> result = m_elf.get_object_virtual<u16>(address);
valid = result.has_value();
if (!valid)
return 0;
return *result;
}
u32 ElfMemoryReader::read32(u32 address)
u32 ElfMemoryReader::Read32(u32 address, bool* valid)
{
std::optional<u32> result = m_elf.get_object_virtual<u32>(address);
if (!result.has_value())
return 0;
return InvalidReadResult(valid);
if (valid)
*valid = true;
return *result;
}
u32 ElfMemoryReader::read32(u32 address, bool& valid)
{
std::optional<u32> result = m_elf.get_object_virtual<u32>(address);
valid = result.has_value();
if (!valid)
return 0;
return *result;
}
u64 ElfMemoryReader::read64(u32 address)
u64 ElfMemoryReader::Read64(u32 address, bool* valid)
{
std::optional<u64> result = m_elf.get_object_virtual<u64>(address);
if (!result.has_value())
return 0;
return InvalidReadResult(valid);
if (valid)
*valid = true;
return *result;
}
u64 ElfMemoryReader::read64(u32 address, bool& valid)
u128 ElfMemoryReader::Read128(u32 address, bool* valid)
{
std::optional<u64> result = m_elf.get_object_virtual<u64>(address);
valid = result.has_value();
if (!valid)
return 0;
std::optional<u128> result = m_elf.get_object_virtual<u128>(address);
if (!result.has_value())
return InvalidReadResult128(valid);
if (valid)
*valid = true;
return *result;
}
//
// MipsExpressionFunctions
//
bool ElfMemoryReader::ReadBytes(u32 address, void* dest, u32 size)
{
std::optional<std::span<const u8>> bytes = m_elf.get_virtual(address, size);
if (!bytes.has_value())
return false;
std::memcpy(dest, bytes->data(), size);
return true;
}
bool ElfMemoryReader::Write8(u32 address, u8 value)
{
return false;
}
bool ElfMemoryReader::Write16(u32 address, u16 value)
{
return false;
}
bool ElfMemoryReader::Write32(u32 address, u32 value)
{
return false;
}
bool ElfMemoryReader::Write64(u32 address, u64 value)
{
return false;
}
bool ElfMemoryReader::Write128(u32 address, u128 value)
{
return false;
}
bool ElfMemoryReader::WriteBytes(u32 address, void* src, u32 size)
{
return false;
}
bool ElfMemoryReader::CompareBytes(u32 address, void* src, u32 size)
{
std::optional<std::span<const u8>> bytes = m_elf.get_virtual(address, size);
if (!bytes.has_value())
return false;
return std::memcmp(src, bytes->data(), size) == 0;
}
// *****************************************************************************
MipsExpressionFunctions::MipsExpressionFunctions(
DebugInterface* cpu, const ccc::SymbolDatabase* symbolDatabase, bool shouldEnumerateSymbols)
@@ -1309,7 +1353,7 @@ u64 MipsExpressionFunctions::getReferenceValue(u64 referenceIndex)
return m_cpu->getLO()._u64[0];
if (referenceIndex & REF_INDEX_IS_OPSL)
{
const u32 OP = m_cpu->read32(m_cpu->getPC());
const u32 OP = m_cpu->Read32(m_cpu->getPC());
const R5900::OPCODE& opcode = R5900::GetInstruction(OP);
if (opcode.flags & IS_MEMORY)
{
@@ -1373,16 +1417,16 @@ bool MipsExpressionFunctions::getMemoryValue(u32 address, int size, u64& dest, s
switch (size)
{
case 1:
dest = m_cpu->read8(address);
dest = m_cpu->Read8(address);
break;
case 2:
dest = m_cpu->read16(address);
dest = m_cpu->Read16(address);
break;
case 4:
dest = m_cpu->read32(address);
dest = m_cpu->Read32(address);
break;
case 8:
dest = m_cpu->read64(address);
dest = m_cpu->Read64(address);
break;
}
+53 -58
View File
@@ -7,6 +7,9 @@
#include "ExpressionParser.h"
#include "SymbolGuardian.h"
#include "SymbolImporter.h"
#include "MipsStackWalk.h"
#include "common/MemoryInterface.h"
#include <string>
@@ -38,20 +41,7 @@ inline const std::array<BreakPointCpu, 2> DEBUG_CPUS = {
BREAKPOINT_IOP,
};
class MemoryReader
{
public:
virtual u32 read8(u32 address) = 0;
virtual u32 read8(u32 address, bool& valid) = 0;
virtual u32 read16(u32 address) = 0;
virtual u32 read16(u32 address, bool& valid) = 0;
virtual u32 read32(u32 address) = 0;
virtual u32 read32(u32 address, bool& valid) = 0;
virtual u64 read64(u32 address) = 0;
virtual u64 read64(u32 address, bool& valid) = 0;
};
class DebugInterface : public MemoryReader
class DebugInterface : public MemoryInterface
{
public:
enum RegisterType
@@ -60,13 +50,6 @@ public:
SPECIAL
};
virtual u128 read128(u32 address) = 0;
virtual void write8(u32 address, u8 value) = 0;
virtual void write16(u32 address, u16 value) = 0;
virtual void write32(u32 address, u32 value) = 0;
virtual void write64(u32 address, u64 value) = 0;
virtual void write128(u32 address, u128 value) = 0;
// register stuff
virtual int getRegisterCategoryCount() = 0;
virtual const char* getRegisterCategoryName(int cat) = 0;
@@ -90,6 +73,7 @@ public:
virtual SymbolGuardian& GetSymbolGuardian() const = 0;
virtual SymbolImporter* GetSymbolImporter() const = 0;
virtual std::vector<std::unique_ptr<BiosThread>> GetThreadList() const = 0;
virtual std::vector<MipsStackWalk::StackFrame> StackTrace(const BiosThread& thread) = 0;
virtual std::vector<IopMod> GetModuleList() const = 0;
bool isAlive();
@@ -119,20 +103,21 @@ private:
class R5900DebugInterface : public DebugInterface
{
public:
u32 read8(u32 address) override;
u32 read8(u32 address, bool& valid) override;
u32 read16(u32 address) override;
u32 read16(u32 address, bool& valid) override;
u32 read32(u32 address) override;
u32 read32(u32 address, bool& valid) override;
u64 read64(u32 address) override;
u64 read64(u32 address, bool& valid) override;
u128 read128(u32 address) override;
void write8(u32 address, u8 value) override;
void write16(u32 address, u16 value) override;
void write32(u32 address, u32 value) override;
void write64(u32 address, u64 value) override;
void write128(u32 address, u128 value) override;
u8 Read8(u32 address, bool* valid = nullptr) override;
u16 Read16(u32 address, bool* valid = nullptr) override;
u32 Read32(u32 address, bool* valid = nullptr) override;
u64 Read64(u32 address, bool* valid = nullptr) override;
u128 Read128(u32 address, bool* valid = nullptr) override;
bool ReadBytes(u32 address, void* dest, u32 size) override;
bool Write8(u32 address, u8 value) override;
bool Write16(u32 address, u16 value) override;
bool Write32(u32 address, u32 value) override;
bool Write64(u32 address, u64 value) override;
bool Write128(u32 address, u128 value) override;
bool WriteBytes(u32 address, void* src, u32 size) override;
bool CompareBytes(u32 address, void* src, u32 size) override;
// register stuff
int getRegisterCategoryCount() override;
@@ -152,6 +137,7 @@ public:
SymbolGuardian& GetSymbolGuardian() const override;
SymbolImporter* GetSymbolImporter() const override;
std::vector<std::unique_ptr<BiosThread>> GetThreadList() const override;
std::vector<MipsStackWalk::StackFrame> StackTrace(const BiosThread& thread) override;
std::vector<IopMod> GetModuleList() const override;
std::string disasm(u32 address, bool simplify) override;
@@ -163,20 +149,21 @@ public:
class R3000DebugInterface : public DebugInterface
{
public:
u32 read8(u32 address) override;
u32 read8(u32 address, bool& valid) override;
u32 read16(u32 address) override;
u32 read16(u32 address, bool& valid) override;
u32 read32(u32 address) override;
u32 read32(u32 address, bool& valid) override;
u64 read64(u32 address) override;
u64 read64(u32 address, bool& valid) override;
u128 read128(u32 address) override;
void write8(u32 address, u8 value) override;
void write16(u32 address, u16 value) override;
void write32(u32 address, u32 value) override;
void write64(u32 address, u64 value) override;
void write128(u32 address, u128 value) override;
u8 Read8(u32 address, bool* valid = nullptr) override;
u16 Read16(u32 address, bool* valid = nullptr) override;
u32 Read32(u32 address, bool* valid = nullptr) override;
u64 Read64(u32 address, bool* valid = nullptr) override;
u128 Read128(u32 address, bool* valid = nullptr) override;
bool ReadBytes(u32 address, void* dest, u32 size) override;
bool Write8(u32 address, u8 value) override;
bool Write16(u32 address, u16 value) override;
bool Write32(u32 address, u32 value) override;
bool Write64(u32 address, u64 value) override;
bool Write128(u32 address, u128 value) override;
bool WriteBytes(u32 address, void* src, u32 size) override;
bool CompareBytes(u32 address, void* src, u32 size) override;
// register stuff
int getRegisterCategoryCount() override;
@@ -196,6 +183,7 @@ public:
SymbolGuardian& GetSymbolGuardian() const override;
SymbolImporter* GetSymbolImporter() const override;
std::vector<std::unique_ptr<BiosThread>> GetThreadList() const override;
std::vector<MipsStackWalk::StackFrame> StackTrace(const BiosThread& thread) override;
std::vector<IopMod> GetModuleList() const override;
std::string disasm(u32 address, bool simplify) override;
@@ -205,19 +193,26 @@ public:
};
// Provides access to the loadable segments from the ELF as they are on disk.
class ElfMemoryReader : public MemoryReader
class ElfMemoryReader : public MemoryInterface
{
public:
ElfMemoryReader(const ccc::ElfFile& elf);
u32 read8(u32 address) override;
u32 read8(u32 address, bool& valid) override;
u32 read16(u32 address) override;
u32 read16(u32 address, bool& valid) override;
u32 read32(u32 address) override;
u32 read32(u32 address, bool& valid) override;
u64 read64(u32 address) override;
u64 read64(u32 address, bool& valid) override;
u8 Read8(u32 address, bool* valid = nullptr) override;
u16 Read16(u32 address, bool* valid = nullptr) override;
u32 Read32(u32 address, bool* valid = nullptr) override;
u64 Read64(u32 address, bool* valid = nullptr) override;
u128 Read128(u32 address, bool* valid = nullptr) override;
bool ReadBytes(u32 address, void* dest, u32 size) override;
bool Write8(u32 address, u8 value) override;
bool Write16(u32 address, u16 value) override;
bool Write32(u32 address, u32 value) override;
bool Write64(u32 address, u64 value) override;
bool Write128(u32 address, u128 value) override;
bool WriteBytes(u32 address, void* src, u32 size) override;
bool CompareBytes(u32 address, void* src, u32 size) override;
protected:
const ccc::ElfFile& m_elf;
+5 -5
View File
@@ -23,7 +23,7 @@ static u32 computeHash(u32 address, u32 size)
u32 hash = 0xBACD7814;
while (address < end)
{
hash += r5900Debug.read32(address);
hash += r5900Debug.Read32(address);
address += 4;
}
return hash;
@@ -918,7 +918,7 @@ void DisassemblyData::createLines()
bool inString = false;
while (pos < end)
{
u8 b = r5900Debug.read8(pos++);
u8 b = r5900Debug.Read8(pos++);
if (b >= 0x20 && b <= 0x7F)
{
if (currentLine.size()+1 >= maxChars)
@@ -995,18 +995,18 @@ void DisassemblyData::createLines()
switch (type)
{
case DATATYPE_BYTE:
value = cpu->read8(pos);
value = cpu->Read8(pos);
std::snprintf(buffer,std::size(buffer),"0x%02X",value);
pos++;
break;
case DATATYPE_HALFWORD:
value = cpu->read16(pos);
value = cpu->Read16(pos);
std::snprintf(buffer,std::size(buffer),"0x%04X",value);
pos += 2;
break;
case DATATYPE_WORD:
{
value = cpu->read32(pos);
value = cpu->Read32(pos);
const std::string label = cpu->GetSymbolGuardian().SymbolStartingAtAddress(value).name;
if (!label.empty())
std::snprintf(buffer,std::size(buffer),"%s",label.c_str());

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