Compare commits

..
150 Commits
Author SHA1 Message Date
Connor McLaughlin e8e0f355fc GS/WX: Fix default adapter causing unnecessary GS restarts 2022-03-09 09:14:36 +00:00
Mrlinkwii 3202fd88d2 Gamedb: add VU clamping to 'DT Racer' and update MGS2 hack 2022-03-09 00:10:00 +00:00
RedDevilus 1c66c904ab GameDB: Katamari games
Katamari games have become sensitive again to this hack. It's forcefully disabled for this PR to fix performance and other breaking issues.
2022-03-09 00:08:21 +00:00
lightningterror 784e090081 GS-hw: Improve how we handle blending when output is Cd.
Disable hw blending on Cd output,
Disable rgb write on Cd output.
2022-03-08 23:46:27 +01:00
Connor McLaughlin 2d08d3dc94 GL/Context: Drop GL string logging back to devbuilds 2022-03-08 10:39:50 +01:00
Connor McLaughlin 237b9754c6 Qt: Log graphics driver info on startup 2022-03-08 10:39:50 +01:00
Connor McLaughlin 74bbccdf59 Wx: Log graphics driver info on startup 2022-03-08 10:39:50 +01:00
Connor McLaughlin 062d625901 Vulkan/Context: Allow non-debug device when validation layers unavailable 2022-03-08 10:39:50 +01:00
Connor McLaughlin 3f30c2bda2 VulkanHostDisplay: Improve Vulkan version reporting 2022-03-08 10:39:50 +01:00
PCSX2 Bot 0702692746 PAD: Update to latest controller database. 2022-03-07 17:11:41 +01:00
dependabot[bot] 11a218b1aa Bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-07 14:15:25 +01:00
Connor McLaughlin f4acff1321 Qt: Fix incorrect dropdown value in game properties 2022-03-07 14:14:49 +01:00
Connor McLaughlin a8ee746c39 Qt: Fix live changing game settings not applying 2022-03-07 14:14:49 +01:00
Connor McLaughlin ddd5fc7bf3 VMManager: Fix brief unpause before shutdown 2022-03-07 14:14:04 +01:00
lightningterror 22dfe05287 GS-hw: Optimize blending when ALPHA.A is equal to ALPHA.B.
Set ALPHA A B to 0 (Cs), and ALPHA.C to 0 (As).
2022-03-07 14:13:19 +01:00
refractionpcsx2 fa78e1295a GS: Handle Auto Flush across pages + scissor, add TEXFLUSH
Fixes Jak 3 shadows, partially fixes Beyond Good and Evil water, improves Auto Flush performance hugely (x3 in Jak 2 @ 3x Native)
2022-03-06 03:07:37 +00:00
refractionpcsx2 4a634ca154 GS: Fix compilation of GS SW Int Rasterizer 2022-03-05 16:55:54 +00:00
refractionpcsx2 bd1f5d0888 GS: Adjust Tekken 5 CRC hack for fire effect, fixes sun bleed.
Fixes #2766
2022-03-05 15:55:36 +00:00
Connor McLaughlin 2f028c5f40 Qt: Implement CTRL+C and confirm shutdown 2022-03-04 17:41:28 +00:00
Connor McLaughlin 56c8843406 Qt: Add log options to debug menu 2022-03-04 17:41:28 +00:00
Connor McLaughlin 37c4c596b5 Qt: Fix a few warnings on Linux 2022-03-04 17:41:28 +00:00
Connor McLaughlin 7b0bde4f1f Qt: Move section/key in setting binder
It's passed in by value, so elide the copy.
2022-03-04 17:41:28 +00:00
Connor McLaughlin 5c5c7d64a8 Qt: Remove version check macros
Not needed anymore since we require Qt6 on all platforms.
2022-03-04 17:41:28 +00:00
lightningterror 565189d08c GS-hw: Fix Wunused-variable warning in GSRendererHW. 2022-03-03 22:27:40 +01:00
lightningterror 682580e318 GS-hw: Fix Wsign-compare warnings in GSRendererNew. 2022-03-03 22:27:40 +01:00
lightningterror 74e3d6470a GS-hw: Fix Wunused-but-set-variable warnings in GSTextureCache. 2022-03-03 22:27:40 +01:00
refractionpcsx2 b4e6a715fc EE/JIT: Flush const on LDL/LDR instructions 2022-03-03 16:18:16 +00:00
Mrlinkwii 85f0d44997 Gamedb: add patch for Cars 2022-03-03 11:29:52 +00:00
TellowKrinkle 294855700d GS:OGL: Don't memset C++ objects 2022-03-02 12:10:12 +00:00
TellowKrinkle 099ddfedc7 GS:Mac: Properly init vulkan on main thread 2022-03-02 12:02:15 +00:00
TellowKrinkle d9e2bcef6d GS:Mac: Nicer message send 2022-03-02 12:02:15 +00:00
TellowKrinkle 7a628f1a12 WX: Make texture dump location configurable 2022-03-02 11:58:44 +00:00
Mrlinkwii 75bc680934 GameDB: add 'VUSyncHack' to 'Tiger Woods PGA Tour 2002' and update documentation 2022-03-02 11:36:11 +00:00
Connor McLaughlin 0c98b5ff76 GS/TextureCache: Don't let hash cache memusage go negative 2022-03-01 17:34:59 +00:00
arcum42 11918e5846 Disable warnings on several third party libraries. (#5519) 2022-02-28 21:14:52 -08:00
refractionpcsx2 2c33bf8c6f GUI/Qt: Update VU Sync option in Qt interface 2022-02-28 19:29:53 +00:00
refractionpcsx2 e833a67bb7 VU: Rework VUKickstart in to VUSync, swap behaviour 2022-02-28 19:29:53 +00:00
refractionpcsx2 6dc5087cbd VU: Run sync ahead on small blocks 2022-02-28 19:29:53 +00:00
PCSX2 Bot eabda670ac PAD: Update to latest controller database. 2022-02-28 17:52:52 +01:00
Connor McLaughlin 845e7930d7 microVU: Move VU0 micro flag instance setup to program start
They're only used in micro mode, so no point updating them in a cop2
chain.
2022-02-28 15:07:15 +00:00
Connor McLaughlin d20bfa240d EE: Add COP2 flag hack 2022-02-28 15:07:15 +00:00
Connor McLaughlin ba27a46ac6 GS/TextureCache: Don't count replacements in hash cache budget
Large replacement textures were causing the hash cache to disable
itself. There's plenty of other massive VRAM sinks in PCSX2 that we need
to consider before we can say we're managing VRAM well anyway.
2022-02-28 09:38:12 +00:00
Connor McLaughlin 866e5bd929 GS/TextureReplacements: Disable generated mipmaps on compressed textures
They should be provided in the file.
2022-02-28 09:38:12 +00:00
TellowKrinkle 1beb5517a7 Pad: Fix connection of macOS GameController framework controllers 2022-02-28 09:51:11 +01:00
TheLastRar a12ad1f627 Config: Clang format Pcsx2Config 2022-02-28 09:44:14 +01:00
TheLastRar c18be9dde7 Dependencies: Remove LibXml 2022-02-28 09:44:14 +01:00
TheLastRar 4eba400170 DEV9: Don't enforce MTA requirement
Also CoUninitialize() needs to be called for all successful calls to CoInitialize/Ex(), not just those that return S_OK
2022-02-28 09:44:14 +01:00
TheLastRar dc376ab161 DEV9: Clang format net.cpp 2022-02-28 09:44:14 +01:00
TheLastRar 5ff49a78eb Config: Add DEV9 options to global struct
Additionally switch to using std::string in various locations in DEV9
2022-02-28 09:44:14 +01:00
TheLastRar 6df50992c4 DEV9: Remove old settings/log directory functions 2022-02-28 09:44:14 +01:00
TheLastRar 5d2bcfaa38 DEV9: Fix off by one error on LBA range check 2022-02-28 09:44:14 +01:00
TheLastRar 990d7ad0f7 DEV9: Correct DEV9 include in Tap 2022-02-28 09:44:14 +01:00
TheLastRar 510283cd4d DEV9: Rename DEV9's Config.h to DEV9Config.h 2022-02-28 09:44:14 +01:00
TheLastRar dcc183179a DEV9: Use fs namespace instead of ghc 2022-02-28 09:44:14 +01:00
TheLastRar 30bc9b04c5 DEV9: Use UTF8 strings on windows for AdapterEntry 2022-02-28 09:44:14 +01:00
dependabot[bot] 8aaeb1c7ce Bump actions/setup-node from 2 to 3
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2 to 3.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-28 09:25:18 +01:00
AKuHAK 1984c68516 PCSX2: Add ability to combine CLI options --elf or --irx with --gameargs
Exception: if full path to host: contains spaces, then arguments will be ignored. To avoid this you can use relative paths when possible.
2022-02-28 09:20:01 +01:00
refractionpcsx2 c81c89d6d9 GUI/Qt: Fix startup project for debugger 2022-02-28 07:34:52 +00:00
refractionpcsx2 9ce2405f3f GUI/Qt: Fix loading ELF files from menu 2022-02-28 07:05:15 +00:00
refractionpcsx2 21fba45a3c GameDB: Added patch for PowerDrome US 2022-02-27 15:22:42 +00:00
refractionpcsx2 a0bbdcefb3 GS: Ignore 24bit on DATE and Handle Reversed Color and Z
Clamp Framebuffer width to 1-32
2022-02-27 15:22:42 +00:00
lightningterror 753da789a0 GS-hw: Adjust DATE selection.
Remove fbmask check from DATE,
Enable DATE_BARRIER with one barrier when alpha isn't written and there is no alpha test.
2022-02-26 17:48:27 +01:00
lightningterror cd5ce6e162 GH-workflows: Remove os mentions for auto pad db update.
Not needed anymore.
2022-02-24 14:52:41 +01:00
Connor McLaughlin 5a25cc171d GS: Add texture dumping and replacement system 2022-02-24 10:18:49 +00:00
Connor McLaughlin 32dc68f103 GS: Support BC1/BC2/BC3/BC7 compressed texture formats 2022-02-24 10:18:49 +00:00
Connor McLaughlin 69a500d657 GS: Add Swap() to GSTexture 2022-02-24 10:18:49 +00:00
Connor McLaughlin ed9f34de5f Common/FileSystem: Add EnsureDirectoryExists() 2022-02-24 10:18:49 +00:00
iMineLink d6f1291c0b GS: skip no output draws. 2022-02-24 10:12:59 +00:00
iMineLink 01079f5162 GS: upscale regardless of PCRTC enabling. 2022-02-24 10:12:59 +00:00
RedDevilus 9b0dc287c1 PCSX2-GUI: Rename Interlacing to Deinterlacing
So to sketch what is an annoying issue is that this for years has been wrongly presented to users.
None Interlacing = Interlacing but if used with a no-interlacing patch it will look like progressive but PCSX2 or really the internal PS2 side only detects interlacing mode. Which blows my mind that the user wouldn't be wrong to assume that None Interlacing = Interlacing.
Weave = Interlacing method (saw-tooth)
Bob = Likely the sharpest but can do vertical bouncing.
Blending = A bit blurry but the most consistent and has no bouncing.

I didn't change the code just the visual presentation to the users.

Example in gif format: https://upload.wikimedia.org/wikipedia/de/1/1e/Interlaced_Animation.gif
2022-02-24 00:38:01 +00:00
lightningterror bb92566781 GS-hw: Don't trigger no overlap check for DATE_BARRIER on d3d11.
d3d11 doesn't support DATE_BARRIER, it's better to let the Date one cases handle it as it will be more accurate.
2022-02-23 20:48:00 +01:00
Connor McLaughlin 17b1c664a8 GS: Add option to disable status indicators
Fast forward/pause icons.
2022-02-23 15:45:47 +00:00
Connor McLaughlin 2eaba084c7 GS/TextureCache: Fix target not getting invalidated in some cases
This would happen when there was a source from local memory with the
same pointer as the target.

Fixes sky getting messed up in the Jak 3 menu when the hash cache is
enabled.
2022-02-23 15:45:19 +00:00
arcum42@gmail.com ff75ab73cc Qt: Fix qt compilation on linux. 2022-02-22 19:23:51 +00:00
RedDevilus 3c54593456 Qt: Add themes
Ranging from ColorBlind themes to flashy to pastel. Based on the Fusion factory. 3 Light and 1 Dark extra themes (2 light and 2 dark themes on master) with enough variability and choice.
It's just a placeholder for when other factories are implemented and perhaps even viable for future community-based static or dynamic ones.
2022-02-22 16:13:09 +00:00
RedDevilus 39dfb2e606 Qt: Resize default headersize BIOS
Qt: Resize default headersize BIOS

The first column was too small and visually makes it harder to see what BIOS you have.
2022-02-22 16:13:09 +00:00
PCSX2 Bot 4e7ade8612 pad-windows/unix: Update to latest controller database. 2022-02-21 21:22:07 +01:00
seta-san 664013e7ad Qt: Fix type on graphics panel (#5553) 2022-02-21 19:10:14 +00:00
Connor McLaughlin 9d51c64d92 GS: Support mipmaps in hash cache 2022-02-21 16:50:57 +01:00
Connor McLaughlin ee82c7834d GS: Auto-disable hash cache when it's too large 2022-02-21 16:50:57 +01:00
Connor McLaughlin b389c6e103 GS: Only allocate valid page array when needed 2022-02-21 16:50:57 +01:00
Connor McLaughlin b3a2d3c1e4 GS: Track hash cache memory usage 2022-02-21 16:50:57 +01:00
Connor McLaughlin 5d33af13ca GS: Add full (hash cache) texture preloading option 2022-02-21 16:50:57 +01:00
Connor McLaughlin 6b2a851dec GS/Vulkan: Fix uploading large (>64MB) textures 2022-02-21 16:50:57 +01:00
Connor McLaughlin 3b3072801c GS/OpenGL: Fix uploading large (>16MB) textures 2022-02-21 16:50:57 +01:00
Connor McLaughlin 9ed33d4337 GS/HW: Fix mipmap level not updating on live config change 2022-02-21 16:50:57 +01:00
Mrlinkwii 728b3eb5db Core: remove not needed logging 2022-02-21 10:46:29 +01:00
Connor McLaughlin f73398ea84 GS/Vulkan: Fix warning when compiling RGBA8->RGB5A1 shader
Also gets rid of the program info log length check, since that's been
long removed in glslang.
2022-02-20 14:03:33 +00:00
lightningterror 2b646c2153 GS-hw: Disable dithering if blend mix is enabled.
It breaks stuff since we do a mix of hw/sw.
2022-02-20 02:31:03 +01:00
lightningterror f83692c0df GS-ogl: Remove GL_ARB_get_texture_sub_image.
Not used.
Also remove some not used commented out defines.
2022-02-19 18:08:05 +01:00
lightningterror b8236b1b1c GS-hw: Partially revert #5540
Allow to wrap on colclip.
For real tho, ideal solution is sw blend, doing any clamp/wrap is wrong on blend mix.
2022-02-19 00:38:13 +01:00
lightningterror 1a3d77b2c0 GS-hw: Fix d3d11 depth sample shader.
Also adjust some comments to match updated shader names.
2022-02-18 19:21:01 +01:00
lightningterror 816ee9e545 GS-hw: Prefer sw blend for clr_blend1_2 on ultra blending.
Opengl/Vulkan: Prefer sw blend over hw for clr_blend1_2 on ultra blending, doing hw is less accurate and will introduce rounding issues.

Direct3D11: Prefer sw blend over hw for clr_blend1_2 only when primitives don't overlap.
2022-02-18 19:06:49 +01:00
lightningterror 06766ddb98 GS-hw: Don't wrap on 16bit destination format for blend mix.
Helps Dog's Life blending, we shouldn't wrap as we do more blend math afterward which will be wrong if we wrapped before.
2022-02-18 19:00:54 +01:00
lightningterror 7151848406 GS-hw: Rename alpha_clamp to blend_mix. 2022-02-18 19:00:54 +01:00
Ziemas 45b5347092 SPU2: Don't cap pitch setting on register write.
While 0x3FFF is indeed the highest playable pitch I think that the
register is 16 bits wide and that the cap is enforced by the pitch
counter algorithm.

This fixes the air time ticking sound in Jak X.
2022-02-18 12:32:04 +00:00
Ty Lamontagne 5b6986c230 Core: Export recompiler offsets 2022-02-16 17:51:40 +00:00
Connor McLaughlin de195d9b20 Qt: Add game summary and audio/memcard placeholders 2022-02-16 17:34:53 +01:00
Connor McLaughlin b47552c08f Qt: Add per-game settings UI 2022-02-16 17:34:53 +01:00
Mrlinkwii 48dabd3ca2 QT: Add icon for Hk BIOS. 2022-02-15 20:54:27 +01:00
lockhart 91ac0368e3 GameDB: Add Ratchet & Clank demo and Spider-Man 3 Fixes + several new entries as well as the removal of the virtual-on Ontario program fixes.
This commit fixes several entries from the GameIndex, removes the clamping fixes from Virtual On ontario program which wasn't needed, adds several rounding fixes to Ratchet 1 titles to fix the Hydrodisplacer Behaviour and adds several entries as well.

For Ratchet 1, After having done tests on actual hardware,

the results shows that even real hardware will behave badly on the retail version....

However, the demo does indeed have an issue, so let's fix that.

Also, this fixes an oversight made for Spiderman 3 in the past, now the proper fix is applied.
2022-02-15 12:58:27 +00:00
Connor McLaughlin dfe4bc199f GS/HW: Use integers for depth conversion shaders
Fixes z-fighting in reflections in DBZ BT3, maybe others?
2022-02-15 10:41:37 +01:00
PCSX2 Bot 1630404621 pad-windows/unix: Update to latest controller database. 2022-02-14 21:06:50 +01:00
Mrlinkwii 02c66491e8 Gamedb: add 'VUKickstartHack' to 'Jet Li - Rise to Honor' 2022-02-14 18:29:57 +00:00
refractionpcsx2 d4b1d9abe5 GS-hw: Increase 32->16bit conversion accuracy
Improves Dogs life (no longer goes completely black right away, but has decal problems)
Vastly improves texture quality in Spider-Man 3 when using Framebuffer Conversion to fix the textures
2022-02-14 14:50:21 +00:00
Ty Lamontagne 6ab77be8fc COP2: Move COP2 timing messages to release builds. 2022-02-14 01:52:44 +00:00
RedDevilus 6cf518e7df actions: Add windows category for SDL
Upcoming Qt will feature native support for multiple controllers + remapping for all relevant OSes. This makes the step a bit easier.

Rationale:
Windows has cleaner code (becoming just like OnePad) and no more DS4/DualSense/Switch Pro/... wrapper such as steam or DS4Windows (ryochan7) though will still work if you want it.
Linux will have OnePad legacy remapping.
Mac will have feature parity to some extent.
2022-02-14 01:50:57 +00:00
Mrlinkwii 8f1745bf44 Gamedb: add EETimingHack to 'Obscure 2' and patch to 'Snoopy Vs Red Baron' 2022-02-14 01:50:39 +00:00
lightningterror 38f1ae34ad GS-hw: Prefer sw blend when one barrier is already enabled and prims don't overlap.
More accurate, speed will be the same.
2022-02-13 14:11:51 +01:00
refractionpcsx2 ad415945a6 GS-hw: Apply clamp/wrap when FBMask enabled 2022-02-11 19:33:38 +01:00
Frank Hartung a44fe29b8d CMake: add back HarfBuzz to fix build (#5510)
- pango relies on HarfBuzz & pulls in its headers
2022-02-10 17:56:19 -08:00
RedDevilus c1d96fc876 CI: Label Qt into GUI/Qt
The label has recently been changed into GUI/Qt for more clarity that it touches upon a GUI toolkit just like WX. Also added the 3rdparty for the binary.
2022-02-10 21:04:28 +01:00
Florin9doi 65db50df5d Qt: Add icon for Cn BIOS. 2022-02-10 21:02:55 +01:00
Blackbird88 f009d6f9e7 GameDB: Add missing Gran Turismo demos 2022-02-09 10:56:25 +00:00
Mrlinkwii ed8bd18dfb GameDB: disable mVUFlagHack for Maken Shao 2022-02-09 10:21:52 +00:00
PCSX2 Bot af648334d1 pad-linux: Update to latest controller database. 2022-02-07 17:11:12 +01:00
987123879113 8f4ce02d05 GameDB: Update Bemani game titles and add new entries for Japanese DDR X and SuperNOVA2 2022-02-07 02:52:57 +00:00
C.W. Betts 9b7e87c043 Mark static functions in headers as static inline:
This quiets unused function warnings (-Wunused-function) which is on by default on Xcode.
2022-02-07 02:32:56 +00:00
C.W. Betts cae8e6ae79 Change a couple of includes from angle brackets to quotes:
This makes Xcode happy, as it interprets angled brackets as system headers or headers inside of frameworks.
2022-02-07 02:32:56 +00:00
iMineLink 1a2272ad43 GS: partially revert "c1e5e45431863bc206686c49b8fb4fa2775be9a2".
overwrite the target pitch when an overlapping write is detected
with the write pitch itself.
fixes the broken splashscreen in This is Football 2002.
2022-02-07 02:17:19 +00:00
iMineLink fede91a98b GS: update target pitch on frame lookup.
fix Jurassic Park - Operation Genesis loading disk logo.
2022-02-07 01:42:54 +00:00
Connor McLaughlin 7e8c6fcc9d Wx: Fix live vsync changes not applying 2022-02-07 01:42:40 +00:00
Connor McLaughlin 0ca3167595 Vulkan: Implement adaptive vsync (FIFO-relaxed) 2022-02-07 01:42:40 +00:00
Connor McLaughlin c74cc9bc12 HostDisplay: Fix vsync getting lost on window changes 2022-02-07 01:42:40 +00:00
iMineLink 061fff6f17 cmake: copy resources in build folder. 2022-02-06 16:01:39 +00:00
lightningterror 2aaabdd2ea GS-hw: Cleanup crc stuff.
Merge the following crc lists, gets rid of duplication since code is shared:
BurnoutDominator, BurnoutRevenge, BurnoutTakedown ->BurnoutGames

GetaWay, GetaWayBlackMonday ->GetaWayGames

GT3, GT4, GTConcept, TouristTrophy ->PolyphonyDigitalGames

Yakuza, Yakuza2 -> YakuzaGames

ValkyrieProfile2, StarOcean3, RadiataStories -> TriAceGames

Rename defines Dx_and_OGL to CRC_Partial, Dx_only to CRC_Full, Aggressive to CRC_Aggressive
2022-02-06 16:21:30 +01:00
lightningterror 2f06ed2af8 GS-hw-tc: Remove JackieChanAdv crc hack.
Game seems to work fine currently.
2022-02-06 15:45:49 +01:00
Florin9doiandFlorin9doi 52252de3a6 GameDB: Add missing NTSC-J games (#5491)
Co-authored-by: Florin9doi <Florin9doi@users.noreply.github.com>
2022-02-06 13:58:09 +00:00
Florin9doi ff725980c3 Game DB: Add missing PAL games to GameIndex Correct AFL Football serial
PR #5490
Co-authored-by: Florin9doi <Florin9doi@users.noreply.github.com>
2022-02-06 13:57:12 +00:00
lightningterror d6d420b1f7 QT: Add missing Texture Inside RT option. 2022-02-06 13:17:28 +01:00
TellowKrinkle 977e8a4c54 GS:HW: Fix scale of color → 8 bit converted textures 2022-02-06 05:04:56 +00:00
iMineLink b8188a7954 GS: remove bw equality check in tex in rt.
fixes jak mipmapping.
2022-02-06 04:53:09 +00:00
refractionpcsx2 8ac57db117 GS: Don't process CLUT load condition on invalid PSM 2022-02-05 15:13:48 +00:00
RedDevilus 5cc66e4d36 Qt: Resize Windows + Change Framerate Presets + Lower OSD time
The main window will now correctly display the full Toolbar. Interface Settings will not go out of bounds. The OSD message for cheats and patches has been changed and the overall timing of the static (not dynamic) OSD messages are now 5 seconds instead of 10 seconds which is pretty long. Tested on 1920 x 1080 + 2560 x 1080 on 125% and 150% DPI scaling.
2022-02-05 14:09:34 +00:00
Connor McLaughlin d9d2022096 InputManager: Missing motor bindings are not errors 2022-02-05 14:09:11 +00:00
Connor McLaughlin 1ea38b1981 Qt: Fix current tab resetting when switching renderers 2022-02-05 14:09:11 +00:00
Connor McLaughlin d63a36216f Qt: Fix default values for software mipmap/AA1 2022-02-05 14:09:11 +00:00
s-andro 9ac935ed94 CRC: Gran Turismo 4 [PlayStation 2 Racing Pack] 2022-02-05 09:01:41 +01:00
s-andro 02bb2b7477 GameDB: Gran Turismo 4 [PlayStation 2 Racing Pack] 2022-02-05 09:01:41 +01:00
TheLastRar 9cfce59547 DEV9: Check for null ifa_addr in PCAPGetIfAdapter 2022-02-05 00:51:50 +00:00
lightningterror 99f0d5c685 GS-hw: Properly enable/disable each channel based on fbmask, adjust fbmask detection when to do blending for 16bit/24bit.
Optimization.
2022-02-04 23:28:24 +01:00
lightningterror f84cb1c9cc GS-hw: Optimize fbmask on 16bit format.
Set fbmask to 0 if unused bits are the ones enabling it, they aren't used anyway.
2022-02-04 19:27:08 +01:00
lightningterror ae4733c59d GS-hw: Purge LordOfTheRingsThirdAge crc hack.
Shadows are now rendered correctly on all renderers.
2022-02-04 18:53:28 +01:00
Connor McLaughlin 2629c92a00 GS/Vulkan: Fix HDR resolve to cleared target
Fixes shadows in LOTR: Third Age.
2022-02-04 18:32:53 +01:00
Ty Lamontagne 4ccb922d1a Debugger: Make memory search size depend on platform 2022-02-04 16:52:27 +00:00
Ty Lamontagne 8113e9a168 Debugger: Fix memory search drawing and sizing
Now it should be sized a little better
A little funky on dpis greater than 100%
(sorry wx is not easy to work with)
2022-02-04 16:52:27 +00:00
Ty Lamontagne a632f3c5cb Core: Lighten IOP breakpoint load
standardizeBreakpintAddress calls on the IOP just return the address unmodified. Considering this is called at least once every load / store instruction when there is an IOP OR EE memcheck enabled, it's pretty hot.
2022-02-04 16:52:27 +00:00
Tokman5 e64e2f2c4e Debugger: add register name pattern 2022-02-04 15:34:46 +00:00
RedDevilus f6d49eb5b9 Qt: More sizing + improve hotkeys code
There were other sizing issues with region and CRC that are now have better width. Taking the liberty to organise the hotkeys as it is laid on the GUI-level + adding missing hotkeys. There is still much work to be done.
2022-02-04 02:26:01 +00:00
lightningterror ee4f498a13 GS-hw: Re add alpha c check for clr_blend1_2.
Removed it by accident, nobody saw nothing.
2022-02-03 23:37:01 +01:00
211 changed files with 8507 additions and 3387 deletions
+3 -1
View File
@@ -27,9 +27,11 @@
'GUI/WX':
- 'pcsx2/gui/*'
- 'pcsx2/gui/**/*'
'Qt':
'GUI/Qt':
- 'pcsx2-qt/*'
- 'pcsx2-qt/**/*'
- '3rdparty/Qt/*'
- '3rdparty/Qt/**/*'
'GameDB':
- '**/GameIndex.*'
'Installer | Package':
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Validate GameDB
env:
+1 -1
View File
@@ -105,7 +105,7 @@ jobs:
# echo ${{ github.event.pull_request.title }}
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Checkout Submodules
if: steps.cache-submodules.outputs.cache-hit != 'true'
+1 -1
View File
@@ -86,7 +86,7 @@ jobs:
# echo ${{ github.event.pull_request.title }}
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Checkout Submodules
run: git submodule update --init --recursive -j $(getconf _NPROCESSORS_ONLN)
+2 -2
View File
@@ -9,9 +9,9 @@ jobs:
if: github.repository == 'PCSX2/pcsx2'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- uses: actions/setup-node@v2
- uses: actions/setup-node@v3
with:
node-version: 16
@@ -26,7 +26,7 @@ jobs:
if: github.repository == 'PCSX2/pcsx2'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
# Docs - https://github.com/mathieudutour/github-tag-action
# Workflows cannot trigger other workflows implicitly
@@ -1,6 +1,7 @@
import os
relevant_categories = [
"# Windows",
"# Mac OS X",
"# Linux"
]
@@ -29,7 +29,6 @@ declare -a PCSX2_PACKAGES=(
"libudev-dev"
"libwxgtk3.0-gtk3-dev"
"libx11-xcb-dev"
"libxml2-dev"
"pkg-config"
"portaudio19-dev"
"zlib1g-dev"
@@ -32,7 +32,7 @@ allowed_game_fixes = [
"VIF1StallHack",
"GIFFIFOHack",
"GoemonTlbHack",
"VUKickstartHack",
"VUSyncHack",
"IbitHack",
"VUOverflowHack",
]
+4 -4
View File
@@ -9,7 +9,7 @@ jobs:
if: github.repository == 'PCSX2/pcsx2'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Get Latest DB and Prepare DB File
run: |
@@ -21,9 +21,9 @@ jobs:
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
with:
title: "pad-linux: Update to latest controller database"
commit-message: "pad-linux: Update to latest controller database."
title: "PAD: Update to latest controller database"
commit-message: "PAD: Update to latest controller database."
committer: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
author: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
body: "Weekly automatic update of SDL Controller DB for Linux / Mac OS"
body: "Weekly automatic update of SDL Controller DB"
reviewers: lightningterror
+1 -1
View File
@@ -64,7 +64,7 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Checkout Submodules
run: git submodule update --init --recursive -j $env:NUMBER_OF_PROCESSORS
+2 -2
View File
@@ -10,6 +10,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3rdparty", "3rdparty", "{78
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{2D6F0A62-A247-4CCF-947F-FCD54BE16103}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2-qt", "pcsx2-qt\pcsx2-qt.vcxproj", "{2A016F21-87AE-4154-8271-1F57E91408E9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SoundTouch", "3rdparty\soundtouch\SoundTouch.vcxproj", "{E9B51944-7E6D-4BCD-83F2-7BBD5A46182D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "3rdparty\zlib\zlib.vcxproj", "{2F6C0388-20CB-4242-9F6C-A6EBB6A83F47}"
@@ -46,8 +48,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glad", "3rdparty\glad\glad.
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "imgui", "3rdparty\imgui\imgui.vcxproj", "{88FB34EC-845E-4F21-A552-F1573B9ED167}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pcsx2-qt", "pcsx2-qt\pcsx2-qt.vcxproj", "{2A016F21-87AE-4154-8271-1F57E91408E9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simpleini", "3rdparty\simpleini\simpleini.vcxproj", "{1EC8B3C0-8FB3-46DE-A2E0-A9121203F266}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cubeb", "3rdparty\cubeb\cubeb.vcxproj", "{BF74C473-DC04-44B3-92E8-4145F4E77342}"
Binary file not shown.
File diff suppressed because it is too large Load Diff
+736 -14
View File
@@ -1,6 +1,719 @@
# Game Controller DB for SDL in 2.0.16 format
# Source: https://github.com/gabomdq/SDL_GameControllerDB
# Windows
03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,
03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
03000000d0160000060d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
03000000d0160000070d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
03000000d0160000600a000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
03000000c82d00000031000000000000,8BitDo Adapter,a:b0,b:b1,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:b3,y:b4,platform:Windows,
03000000c82d00000531000000000000,8BitDo Adapter 2,a:b0,b:b1,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:b3,y:b4,platform:Windows,
03000000c82d00000951000000000000,8BitDo Dogbone Modkit,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b11,platform:Windows,
03000000008000000210000000000000,8BitDo F30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
030000003512000011ab000000000000,8BitDo F30 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,
03000000c82d00001028000000000000,8BitDo F30 Arcade Joystick,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d000011ab000000000000,8BitDo F30 Arcade Joystick,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,
03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001038000000000000,8BitDo F30 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:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000090000000000000,8BitDo FC30 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,
03000000c82d00000650000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00005106000000000000,8BitDo M30,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,guide:b2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000151000000000000,8BitDo M30 Modkit,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000310000000000000,8BitDo N30,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,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00002028000000000000,8BitDo N30,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:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00008010000000000000,8BitDo N30,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,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d0000e002000000000000,8BitDo N30,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b6,platform:Windows,
03000000c82d00000451000000000000,8BitDo N30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,start:b11,platform:Windows,
03000000c82d00000190000000000000,8BitDo N30 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,
03000000c82d00001590000000000000,8BitDo N30 Pro 2,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:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00006528000000000000,8BitDo N30 Pro 2,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,
03000000c82d00000290000000000000,8Bitdo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows,
03000000c82d00003038000000000000,8Bitdo N64,+rightx:b9,+righty:b3,-rightx:b4,-righty:b8,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,platform:Windows,
03000000c82d000012ab000000000000,8BitDo NES30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Windows,
03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Windows,
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:a1,rightshoulder:b7,righttrigger:b9,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,
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,
03000000c82d00002867000000000000,8BitDo S30 Modkit,a:b0,b:b1,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b8,lefttrigger:b9,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000130000000000000,8BitDo SF30,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:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000060000000000000,8Bitdo SF30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Windows,
03000000c82d00000061000000000000,8Bitdo SF30 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,
03000000102800000900000000000000,8Bitdo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d000021ab000000000000,8BitDo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00003028000000000000,8Bitdo SFC30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000030000000000000,8BitDo SN30,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001290000000000000,8BitDo SN30,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,
03000000c82d000020ab000000000000,8BitDo SN30,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:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00004028000000000000,8BitDo SN30,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:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00006228000000000000,8BitDo SN30,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,
03000000c82d00000351000000000000,8BitDo SN30 Modkit,a:b1,b:b0,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000160000000000000,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,
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,
03000000c82d00000121000000000000,8BitDo SN30 Pro for Android,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,
03000000c82d00000260000000000000,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,
03000000c82d00000261000000000000,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,
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,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000d81d00000e00000000000000,AC02,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
030000008f0e00001200000000000000,Acme GA02,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:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000c01100000355000000000000,Acrux,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,
03000000fa190000f0ff000000000000,Acteck AGJ 3200,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,
030000006d0400000bc2000000000000,Action,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:a5~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b5,righttrigger:a2~,start:b8,x:b3,y:b4,platform:Windows,
03000000d1180000402c000000000000,ADT1,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a3,rightx:a2,righty:a5,x:b3,y:b4,platform:Windows,
030000006f0e00001301000000000000,Afterglow,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,
030000006f0e00001302000000000000,Afterglow,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,
030000006f0e00001304000000000000,Afterglow,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,
030000006f0e00001413000000000000,Afterglow,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,
030000006f0e00003901000000000000,Afterglow,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,
03000000ab1200000103000000000000,Afterglow,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,
03000000ad1b000000f9000000000000,Afterglow,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,
03000000341a00003608000000000000,Afterglow 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,
030000006f0e00000263000000000000,Afterglow 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,
030000006f0e00001101000000000000,Afterglow 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,
030000006f0e00001401000000000000,Afterglow 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,
030000006f0e00001402000000000000,Afterglow 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,
030000006f0e00001901000000000000,Afterglow 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,
030000006f0e00001a01000000000000,Afterglow 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,
03000000100000008200000000000000,Akishop Customs PS360,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,
030000007c1800000006000000000000,Alienware Dual Compatible 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:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows,
03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows,
03000000120c0000100e000000000000,Armor 3,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,
03000000490b00004406000000000000,ASCII Seamic Controller,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,
03000000869800002500000000000000,Astro C40 TR PS4 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,
03000000a30c00002700000000000000,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,
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,
03000000ef0500000300000000000000,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:Windows,
03000000fd0500000230000000000000,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:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
03000000e4150000103f000000000000,Batarang,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,
03000000d6200000e557000000000000,Batarang 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,
03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,
030000006f0e00003201000000000000,Battlefield 4 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,
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,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,
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,
03000000bc2000006312000000000000,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:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000bc2000006321000000000000,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:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000bc2000006412000000000000,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:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000c01100000555000000000000,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:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000c01100000655000000000000,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:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000790000000700000000000000,Betop 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:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
03000000808300000300000000000000,Betop 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:a2,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
030000006f0e00006401000000000000,BF One,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,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
03000000300f00000202000000000000,Bigben,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:a5,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
030000006b1400000209000000000000,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:Windows,
030000006b1400000055000000000000,Bigben PS3 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,
030000006b1400000103000000000000,Bigben PS3 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:b3,y:b2,platform:Windows,
03000000120c0000200e000000000000,Brook Mars PS4 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,
03000000120c0000210e000000000000,Brook Mars PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d81d00000b00000000000000,Buffalo BSGP1601 Series,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,
030000006d04000042c2000000000000,ChillStream,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000e82000006058000000000000,Cideko AK08b,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,
03000000457500000401000000000000,Cobra,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:Windows,
030000000b0400003365000000000000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
030000004c050000c505000000000000,CronusMax Adapter,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,
03000000d814000007cd000000000000,Cthulhu,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,
03000000d8140000cefa000000000000,Cthulhu,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,
03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,
030000003807000002cb000000000000,Cyborg,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000a306000022f6000000000000,Cyborg V.3 Rumble,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:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000f806000000a3000000000000,DA Leader,a:b7,b:b6,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b8,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:b3,rightx:a2,righty:a3,start:b12,x:b4,y:b5,platform:Windows,
030000001a1c00000001000000000000,Datel,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,
030000007d0400000840000000000000,Destroyer Tiltpad,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,x:b0,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,
03000000c0160000e105000000000000,Dual 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:a3,righty:a4,start:b9,x:b0,y:b3,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,
03000000bd12000002e0000000000000,Dual Vibration Joystick,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,
03000000ff1100003133000000000000,DualForce,a:b2,b:b3,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:b0,y:b1,platform:Windows,
030000008f0e00000910000000000000,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,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,
030000006f0e00003001000000000000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000fc0400000250000000000000,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,
030000006e0500000a20000000000000,Elecom DUX60 MMO,a:b2,b:b3,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b14,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b15,righttrigger:b13,rightx:a3,righty:a4,start:b20,x:b0,y:b1,platform:Windows,
03000000b80500000410000000000000,Elecom Gamepad,a:b2,b:b3,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:b1,platform:Windows,
03000000b80500000610000000000000,Elecom Gamepad,a:b2,b:b3,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:b1,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,
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,
030000006e0500000e20000000000000,Elecom U3912T,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,
030000006e0500000f20000000000000,Elecom U4013S,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,
030000006e0500001320000000000000,Elecom U4113,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,
030000006e0500001020000000000000,Elecom U4113S,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,
030000006e0500000720000000000000,Elecom W01U,a:b2,b:b3,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:a3,start:b9,x:b0,y:b1,platform:Windows,
03000000120c0000f61c000000000000,Elite,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,
03000000430b00000300000000000000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000242f000000b7000000000000,ESM 9110,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows,
03000000101c0000181c000000000000,Essential,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b4,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
030000008f0e00000f31000000000000,EXEQ,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:b3,y:b2,platform:Windows,
03000000341a00000108000000000000,EXEQ RF Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000790000003018000000000000,F300,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,F300 Elite,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,
030000006f0e00008401000000000000,Faceoff Deluxe Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006f0e00008001000000000000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000021000000090000000000000,FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
0300000011040000c600000000000000,FC801,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000852100000201000000000000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700002847000000000000,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,
03000000ad1b000028f0000000000000,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,
03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,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:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000380700001847000000000000,Fightstick,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000380700008031000000000000,Fightstick,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,
03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows,
03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows,
03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows,
03000000b40400001024000000000000,Flydigi Apex,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,
03000000151900004000000000000000,Flydigi Vader 2,a:b11,b:b10,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,leftstick:b1,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b0,righttrigger:b4,rightx:a3,righty:a4,start:b2,x:b9,y:b8,platform:Windows,
03000000b40400001124000000000000,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,paddle1:b4,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows,
03000000b40400001224000000000000,Flydigi Vader 2 Pro,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,paddle1:b15,paddle2:b16,paddle3:b17,paddle4:b18,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows,
03000000ac0500002d02000000000000,G2U,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,
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,
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: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: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,
03000000280400000140000000000000,GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000ac0500003d03000000000000,GameSir,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,
03000000ac0500004d04000000000000,GameSir,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,
030000004c0e00001035000000000000,Gamester,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
030000000d0f00001110000000000000,GameStick Controller,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,
0300000047530000616d000000000000,GameStop,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,
03000000c01100000140000000000000,GameStop PS4 Fun 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,
03000000b62500000100000000000000,Gametel GT004 01,a:b3,b:b0,dpdown:b10,dpleft:b9,dpright:b8,dpup:b11,leftshoulder:b4,rightshoulder:b5,start:b7,x:b1,y:b2,platform:Windows,
030000008f0e00001411000000000000,Gamo2 Divaller PS4 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,
03000000120c0000a857000000000000,Gator Claw,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000c9110000f055000000000000,GC100XF,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000008305000009a0000000000000,Genius,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000008305000031b0000000000000,Genius Maxfire Blaze 3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000451300000010000000000000,Genius Maxfire Grandias 12,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000005c1a00003330000000000000,Genius MaxFire Grandias 12V,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000300f00000b01000000000000,GGE909 Recoil,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:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c283000000000000,Gioteck PlayStation 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,
03000000f025000021c1000000000000,Gioteck 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:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000004f04000026b3000000000000,GP XID,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,
0300000079000000d418000000000000,GPD Win,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,
03000000c6240000025b000000000000,GPX,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,
030000007d0400000540000000000000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000007d0400000340000000000000,Gravis G44011 Xterminator,a:b0,b:b1,back:b10,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:a2,start:b9,x:b3,y:b4,platform:Windows,
030000008f0e00000610000000000000,GreenAsia,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:a5,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
03000000ac0500006b05000000000000,GT2a,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,
03000000341a00000302000000000000,Hama Scorpad,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,
03000000fd0500003902000000000000,Hammerhead,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b2,lefttrigger:b8,rightshoulder:b7,rightstick:b5,righttrigger:b9,start:b10,x:b0,y:b1,platform:Windows,
03000000fd0500002a26000000000000,Hammerhead FX,a:b3,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b0,y:b1,platform:Windows,
03000000fd0500002f26000000000000,Hammerhead FX,a:b4,b:b5,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b1,y:b2,platform:Windows,
030000000d0f00004900000000000000,Hatsune Miku Sho 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,
030000001008000001e1000000000000,Havit HV G60,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b0,platform:Windows,
030000000d0f00000c00000000000000,HEXT,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,
03000000d81400000862000000000000,HitBox Edition Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
03000000632500002605000000000000,HJD X,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,
030000000d0f00000a00000000000000,Hori DOA,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000000d0f00005100000000000000,Hori Fighting,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,
030000000d0f00008600000000000000,Hori Fighting Commander,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,
030000000d0f0000ba00000000000000,Hori Fighting Commander,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,
030000000d0f00008500000000000000,Hori Fighting Commander 2016 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:Windows,
030000000d0f00002500000000000000,Hori Fighting Commander 3,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,
030000000d0f00002d00000000000000,Hori Fighting Commander 3 Pro,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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00005f00000000000000,Hori Fighting Commander 4 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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00005e00000000000000,Hori Fighting Commander 4 PS4,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,x:b0,y:b3,platform:Windows,
030000000d0f00008400000000000000,Hori Fighting Commander 5,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:Windows,
030000000d0f00001000000000000000,Hori Fightstick,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,
030000000f0d00000010000000000000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00003200000000000000,Hori Fightstick 3W,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,
030000000d0f0000c000000000000000,Hori Fightstick 4,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,
030000000d0f00000d00000000000000,Hori Fightstick EX2,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,
030000000d0f00003701000000000000,Hori Fightstick Mini,a:b1,b:b0,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:b3,y:b2,platform:Windows,
030000000d0f00004000000000000000,Hori Fightstick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00008700000000000000,Hori Fightstick mini 4,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,
030000000d0f00008800000000000000,Hori Fightstick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
030000000d0f00002100000000000000,Hori Fightstick V3,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,
030000000d0f00002700000000000000,Hori Fightstick V3,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,
030000000d0f0000a000000000000000,Hori Grip TAC4,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:b13,x:b0,y:b3,platform:Windows,
030000000d0f00000101000000000000,Hori Mini Hatsune Miku FT,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,
030000000d0f00005400000000000000,Hori Pad 3,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,
030000000d0f00000900000000000000,Hori Pad 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,
030000000d0f00004d00000000000000,Hori Pad A,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,
030000000d0f00003801000000000000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Windows,
030000000d0f00009200000000000000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00002301000000000000,Hori PS4 Controller Light,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,
030000000d0f00001100000000000000,Hori Real Arcade Pro 3,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00002600000000000000,Hori Real Arcade Pro 3P,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,
030000000d0f00004b00000000000000,Hori Real Arcade Pro 3W,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,
030000000d0f00006a00000000000000,Hori Real Arcade Pro 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,x:b0,y:b3,platform:Windows,
030000000d0f00006b00000000000000,Hori Real Arcade Pro 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:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00008a00000000000000,Hori Real Arcade Pro 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,x:b0,y:b3,platform:Windows,
030000000d0f00008b00000000000000,Hori Real Arcade Pro 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:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00006f00000000000000,Hori Real Arcade Pro 4 VLX,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:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00007000000000000000,Hori Real Arcade Pro 4 VLX,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00003d00000000000000,Hori Real Arcade Pro N3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b4,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b6,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f0000ae00000000000000,Hori Real Arcade Pro N4,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,
030000000d0f00008c00000000000000,Hori Real Arcade Pro P4,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,
030000000d0f0000aa00000000000000,Hori Real Arcade Pro S,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,
030000000d0f0000d800000000000000,Hori Real Arcade Pro S,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Windows,
030000000d0f00002200000000000000,Hori Real Arcade Pro V3,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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00005b00000000000000,Hori Real Arcade Pro V4,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:Windows,
030000000d0f00005c00000000000000,Hori Real Arcade Pro V4,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,
030000000d0f0000af00000000000000,Hori Real Arcade Pro VHS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00001b00000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000ad1b000002f5000000000000,Hori Real Arcade Pro VX,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b07,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b08,righttrigger:b11,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Windows,
030000000d0f00009c00000000000000,Hori TAC 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:Windows,
030000000d0f0000c900000000000000,Hori Taiko 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,
030000000d0f0000c100000000000000,Horipad,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,
030000000d0f00006400000000000000,Horipad 3TP,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,
030000000d0f00001300000000000000,Horipad 3W,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,
030000000d0f00005500000000000000,Horipad 4 FPS,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,
030000000d0f00006e00000000000000,Horipad 4 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:Windows,
030000000d0f00006600000000000000,Horipad 4 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,x:b0,y:b3,platform:Windows,
030000000d0f00004200000000000000,Horipad 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,
03000000ad1b000001f5000000000000,Horipad EXT2,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,
030000005b1c00002400000000000000,Horipad Mini,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
030000000d0f0000ee00000000000000,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:Windows,
030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:Windows,
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,
030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,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,
03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000005c0a00000285000000000000,iDroidCon,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b6,platform:Windows,
03000000696400006964000000000000,iDroidCon Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000b50700001403000000000000,Impact Black,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
030000006f0e00002401000000000000,Injustice Fightstick PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000830500005130000000000000,InterAct ActionPad,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
03000000fd0500005302000000000000,InterAct ProPad,a:b3,b:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,x:b0,y:b1,platform:Windows,
03000000ac0500002c02000000000000,Ipega Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000491900000204000000000000,Ipega PG9023,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,
03000000491900000304000000000000,Ipega PG9087,+righty:+a5,-righty:-a4,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,start:b11,x:b3,y:b4,platform:Windows,
030000007e0500000620000000000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Windows,
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,
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,
03000000250900000017000000000000,Joypad to 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,
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,
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,
030000006f0e00000104000000000000,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,
030000008f0e00001300000000000000,Logic3,a:b2,b:b1,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:a3,start:b9,x:b3,y:b0,platform:Windows,
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:Windows,
030000006d040000d2ca000000000000,Logitech Cordless Precision,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,
030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,
030000006d04000016c2000000000000,Logitech Dual Action,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,
030000006d0400001dc2000000000000,Logitech F310,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,
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:Windows,
030000006d0400001ec2000000000000,Logitech F510,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,
030000006d04000019c2000000000000,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:Windows,
030000006d0400001fc2000000000000,Logitech F710,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,
030000006d0400001ac2000000000000,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:Windows,
030000006d04000009c2000000000000,Logitech WingMan,a:b0,b:b1,back:b10,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:b8,x:b3,y:b4,platform:Windows,
030000006d0400000ac2000000000000,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:Windows,
03000000380700005645000000000000,Lynx,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,
03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,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,
03000000380700003888000000000000,Mad Catz Arcade Fightstick TE S Plus 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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008532000000000000,Mad Catz Arcade Fightstick TE S 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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700006352000000000000,Mad Catz CTRLR,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,
03000000380700006652000000000000,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000380700005032000000000000,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:Windows,
03000000380700005082000000000000,Mad Catz Fightpad Pro 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,x:b0,y:b3,platform:Windows,
030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000380700008433000000000000,Mad Catz Fightstick TE S 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:Windows,
03000000380700008483000000000000,Mad Catz Fightstick TE S 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,x:b0,y:b3,platform:Windows,
03000000380700008134000000000000,Mad Catz Fightstick TE2 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008184000000000000,Mad Catz Fightstick TE2 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
78696e70757403000000000000000000,Mad Catz Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,
03000000380700006252000000000000,Mad Catz Micro 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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008232000000000000,Mad Catz PlayStation Brawlpad,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:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008731000000000000,Mad Catz PlayStation Fightstick,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:a3,start:b9,x:b0,y:b3,platform:Windows,
030000003807000056a8000000000000,Mad Catz 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,
03000000380700001888000000000000,Mad Catz SFIV Fightstick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000380700008081000000000000,Mad Catz SFV Arcade Fightstick Alpha 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,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
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,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,
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,
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,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,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,
030000008f0e00001030000000000000,Mayflash Sega Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,
0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
03000000790000000018000000000000,Mayflash WiiU Pro Adapter,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,
03000000790000002418000000000000,Mega Drive Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b2,start:b9,x:b3,y:b4,platform:Windows,
0300000079000000ae18000000000000,Mega Drive Controller,a:b0,b:b1,back:b7,dpdown:b14,dpleft:b15,dpright:b13,dpup:b2,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
03000000c0160000990a000000000000,Mega Drive Controller,a:b0,b:b1,leftx:a0,lefty:a1,righttrigger:b2,start:b3,platform:Windows,
030000005e0400002800000000000000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Windows,
030000005e0400000300000000000000,Microsoft SideWinder,a:b0,b:b1,back:b9,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:b8,x:b3,y:b4,platform:Windows,
030000005e0400000700000000000000,Microsoft SideWinder,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,
030000005e0400000e00000000000000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b8,x:b3,y:b4,platform:Windows,
030000005e0400002700000000000000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Windows,
03000000280d00000202000000000000,Miller Lite Cantroller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b5,x:b2,y:b3,platform:Windows,
030000005b1c00002500000000000000,Mini,a:b3,b:b4,back:b7,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b6,x:b0,y:b1,platform:Windows,
03000000ad1b000023f0000000000000,MLG,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a6,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000ad1b00003ef0000000000000,MLG Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000380700006382000000000000,MLG 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,
03000000ffff00000000000000000000,Mocute M053,a:b3,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b11,leftstick:b7,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b6,righttrigger:b4,rightx:a3,righty:a4,start:b8,x:b1,y:b0,platform:Windows,
03000000d6200000e589000000000000,Moga 2,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:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
03000000d62000007162000000000000,Moga Pro,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:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
03000000d6200000ad0d000000000000,Moga Pro,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,
03000000c62400002a89000000000000,Moga XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c62400002b89000000000000,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c62400001a89000000000000,Moga XP5X 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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c62400001b89000000000000,Moga XP5X 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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000efbe0000edfe000000000000,Monect Virtual 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:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Windows,
03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows,
030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000006b1400001106000000000000,Nacon Revolution 3 PS4 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,
030000006b140000100d000000000000,Nacon Revolution Infinity PS4 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,
030000006b140000080d000000000000,Nacon Revolution Unlimited Pro 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,
03000000bd12000001c0000000000000,Nebular,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:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
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,
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,
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,
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,
03000000000f00000100000000000000,NES Controller,a:b1,b:b0,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
03000000571d00002100000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Windows,
03000000921200004346000000000000,NES Controller,a:b0,b:b1,back:b2,leftx:a0,lefty: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,
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,
030000007e0500001920000000000000,Nintendo Switch 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,Nintendo Switch Online Controller,a:b0,b:b1,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: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,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,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,
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,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,rightshoulder:b5,rightstick:a2,righttrigger:b7,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,
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,
030000008916000001fd000000000000,Onza CE,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:a3,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000d62000006d57000000000000,OPP PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
03000000362800000100000000000000,OUYA Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,
03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
03000000790000002201000000000000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000006f0e00008501000000000000,PDP Fightpad Pro,a:b2,b:b3,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:b1,y:b0,platform:Windows,
030000006f0e00000901000000000000,PDP 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:Windows,
03000000e30500009605000000000000,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,
030000004c050000da0c000000000000,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,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,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,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,
030000004c0500003713000000000000,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,
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,
03000000d620000013a7000000000000,PowerA 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:Windows,
030000006d04000084ca000000000000,Precision,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,
03000000d62000009557000000000000,Pro Elite 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,
03000000c62400001a53000000000000,Pro Ex Mini,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,
03000000d62000009f31000000000000,Pro Ex mini 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,
03000000d6200000c757000000000000,Pro Ex mini 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,
03000000120c0000110e000000000000,Pro5,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,
03000000100800000100000000000000,PS1 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,
030000008f0e00007530000000000000,PS1 Controller,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:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000100800000300000000000000,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:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000250900000088000000000000,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,
03000000250900006888000000000000,PS2 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b6,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
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,
03000000666600006706000000000000,PS2 Controller,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,
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,
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,
03000000120c0000f90e000000000000,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,
03000000250900000118000000000000,PS3 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,
03000000250900000218000000000000,PS3 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,
03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,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:b0,y:b3,platform:Windows,
030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows,
030000004f1f00000800000000000000,PS3 Controller,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,
03000000632500007505000000000000,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:b3,y:b0,platform:Windows,
03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,leftshoulder:b10,leftstick:b1,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,
030000008f0e00000300000000000000,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:a5,start:b9,x:b3,y:b0,platform:Windows,
030000008f0e00001431000000000000,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,
03000000ba2200002010000000000000,PS3 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:a5,righty:a2,start:b9,x:b3,y:b2,platform:Windows,
03000000120c00000807000000000000,PS4 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,
03000000120c0000111e000000000000,PS4 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,
03000000120c0000121e000000000000,PS4 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,
03000000120c0000130e000000000000,PS4 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,
03000000120c0000150e000000000000,PS4 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,
03000000120c0000180e000000000000,PS4 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,
03000000120c0000181e000000000000,PS4 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,
03000000120c0000191e000000000000,PS4 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,
03000000120c00001e0e000000000000,PS4 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,
03000000120c0000a957000000000000,PS4 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,
03000000120c0000aa57000000000000,PS4 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,
03000000120c0000f10e000000000000,PS4 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,
03000000120c0000f21c000000000000,PS4 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,
03000000120c0000f31c000000000000,PS4 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,
03000000120c0000f41c000000000000,PS4 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,
03000000120c0000f51c000000000000,PS4 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,
03000000120c0000f70e000000000000,PS4 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,
03000000120e0000120c000000000000,PS4 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,
03000000160e0000120c000000000000,PS4 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,
030000001a1e0000120c000000000000,PS4 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,
030000004c050000a00b000000000000,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,x:b0,y:b3,platform:Windows,
030000004c050000c405000000000000,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,
030000004c050000cc09000000000000,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,x:b0,y:b3,platform:Windows,
030000004c050000e60c000000000000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
03000000830500005020000000000000,PSX,a:b0,b:b1,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:b2,y:b3,platform:Windows,
03000000300f00000111000000000000,Qanba 2,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,
03000000300f00000211000000000000,Qanba 2P,a:b1,b:b0,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,
03000000300f00000011000000000000,Qanba Arcade Stick 1008,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:b10,x:b0,y:b3,platform:Windows,
03000000300f00001611000000000000,Qanba Arcade Stick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
03000000222c00000020000000000000,Qanba Drone Arcade Stick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000300f00001211000000000000,Qanba 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,
03000000300f00001210000000000000,Qanba Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
03000000341a00000104000000000000,Qanba Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,
03000000222c00000223000000000000,Qanba Obsidian Arcade Stick 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:Windows,
03000000222c00000023000000000000,Qanba Obsidian Arcade Stick PS4,a:b1,b:b2,back:b13,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,
030000008a2400006682000000000000,R1 Mobile Controller,a:b3,b:b1,back:b7,leftx:a0,lefty:a1,start:b6,x:b4,y:b0,platform:Windows,
03000000086700006626000000000000,RadioShack,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:a5,start:b9,x:b3,y:b0,platform:Windows,
030000009b2800002300000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows,
030000009b2800006900000000000000,Raphnet 3DO Adapter,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b2,start:b3,platform:Windows,
030000009b2800000800000000000000,Raphnet Dreamcast Adapter,a:b2,b:b1,dpdown:b5,dpleft:b6,dpright:b7,dpup:b4,lefttrigger:a2,leftx:a0,righttrigger:a3,righty:a1,start:b3,x:b10,y:b9,platform:Windows,
030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,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,
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,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,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,
030000009b2800005600000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
030000009b2800005700000000000000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Windows,
030000009b2800001e00000000000000,Raphnet Vectrex Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a1,lefty:a2,x:b2,y:b3,platform:Windows,
030000009b2800002b00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
03000000321500000003000000000000,Razer Hydra,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,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000321500000204000000000000,Razer Panthera 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,
03000000321500000104000000000000,Razer Panthera 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,x:b0,y:b3,platform:Windows,
03000000321500000010000000000000,Razer Raiju,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,
03000000321500000507000000000000,Razer Raiju Mobile,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,
03000000321500000707000000000000,Razer Raiju Mobile,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,
03000000321500000710000000000000,Razer Raiju TE,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,
03000000321500000a10000000000000,Razer Raiju TE,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,
03000000321500000410000000000000,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,
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,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,
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,
03000000bd12000013d0000000000000,Retrolink Sega Saturn Classic Controller,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,lefttrigger:b6,rightshoulder:b2,righttrigger:b7,start:b8,x:b3,y:b4,platform:Windows,
03000000bd12000015d0000000000000,Retrolink Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
0300000000f000000300000000000000,RetroUSB RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
0300000000f00000f100000000000000,RetroUSB Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,
03000000830500000960000000000000,Revenger,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b5,platform:Windows,
030000006b140000010d000000000000,Revolution 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,
030000006b140000020d000000000000,Revolution Pro Controller 2,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,
030000006b140000130d000000000000,Revolution Pro Controller 3,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,
030000006f0e00001f01000000000000,Rock Candy,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,
030000006f0e00004601000000000000,Rock Candy,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,
03000000c6240000fefa000000000000,Rock Candy 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:Windows,
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,
03000000050b00005819000000000000,ROG Chakram Core,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
03000000050b0000181a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
03000000050b00001a1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,platform:Windows,
03000000050b00001c1a000000000000,ROG Chakram X,a:b1,b:b0,leftx:a0,lefty:a1,x:b2,y:b3,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,
030000004f04000001d0000000000000,Rumble Force,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,
030000008916000000fe000000000000,Sabertooth,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,
03000000c6240000045d000000000000,Sabertooth,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,
03000000a30600001af5000000000000,Saitek Cyborg,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000a306000023f6000000000000,Saitek Cyborg V.1 Game,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,
03000000300f00001201000000000000,Saitek Dual Analog,a:b2,b:b3,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:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows,
03000000a30600000cff000000000000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,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:b10,x:b0,y:b1,platform:Windows,
03000000a30600000d5f000000000000,Saitek P2600,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:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,
03000000a30600000dff000000000000,Saitek P2600,a:b1,b:b2,back:b9,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:b8,x:b0,y:b3,platform:Windows,
03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000a306000018f5000000000000,Saitek P3200,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000300f00001001000000000000,Saitek P480 Rumble,a:b2,b:b3,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:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
03000000a30600000901000000000000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b8,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b5,rightx:a3,righty:a2,x:b0,y:b1,platform:Windows,
03000000a30600000b04000000000000,Saitek P990,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:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000a30600002106000000000000,Saitek PS1000 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,
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,
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,
03000000c01100004150000000000000,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:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
03000000c01100004450000000000000,Sanwa Online Grip,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,rightstick:b11,righttrigger:b9,rightx:a3,righty:a2,start:b14,x:b3,y:b4,platform:Windows,
03000000730700000401000000000000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start: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,
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,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,
03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows,
03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows,
03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,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,
03000000b40400000a01000000000000,Sega Saturn Controller,a:b0,b:b1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
030000003b07000004a1000000000000,SFX,a:b0,b:b2,back:b7,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Windows,
03000000120c00001c1e000000000000,SnakeByte 4S PS4 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,
0300000003040000c197000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
03000000571d00002000000000000000,SNES Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
0300000081170000960a000000000000,SNES Controller,a:b4,b:b0,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b5,y:b1,platform:Windows,
03000000811700009d0a000000000000,SNES Controller,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,
030000008b2800000300000000000000,SNES Controller,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,
03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,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,
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,
03000000341a00000908000000000000,Speedlink 6566,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,
03000000380700001722000000000000,Speedlink Competition Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b2,y:b3,platform:Windows,
030000008f0e00000800000000000000,Speedlink Strike FX,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,
03000000c01100000591000000000000,Speedlink Torid,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,
03000000d11800000094000000000000,Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:Windows,
03000000de280000ff11000000000000,Steam Virtual Gamepad,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,
03000000120c0000160e000000000000,Steel Play Metaltech PS4 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,
03000000110100001914000000000000,SteelSeries,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:b6,leftx:a0,lefty:a1,rightstick:b14,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000381000001214000000000000,SteelSeries Free,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000110100003114000000000000,SteelSeries Stratus Duo,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,
03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows,
03000000790000001c18000000000000,STK 7024X,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,
03000000381000003014000000000000,Stratus Duo,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,
03000000381000003114000000000000,Stratus Duo,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,
03000000380700003847000000000000,Street Fighter Fightstick TE,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,start:b7,x:b2,y:b3,platform:Windows,
030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000d620000011a7000000000000,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:Windows,
030000000d0f0000f600000000000000,Switch Hori,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,
03000000457500002211000000000000,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:Windows,
030000004f0400000ab1000000000000,T16000M,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b10,x:b2,y:b3,platform:Windows,
030000000d0f00007b00000000000000,TAC GEAR,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,
03000000d814000001a0000000000000,TE Kitty,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,
03000000fa1900000706000000000000,Team 5,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,
03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,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:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
03000000ba2200000701000000000000,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:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows,
03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,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,x:b3,y:b4,platform:Windows,
03000000790000002601000000000000,TGZ,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:a5,start:b9,x:b3,y:b0,platform:Windows,
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 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,
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,
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,
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,
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,
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,
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,
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,
03000000101c0000171c000000000000,uRage 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:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
030000000b0400003065000000000000,USB 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:a5,start:b9,x:b3,y:b0,platform:Windows,
03000000242f00006e00000000000000,USB Controller,a:b1,b:b4,back:b10,leftshoulder:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,righttrigger:b7,rightx:a2,righty:a5,start:b11,x:b0,y:b3,platform:Windows,
03000000300f00000701000000000000,USB 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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000341a00002308000000000000,USB 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,
03000000666600000188000000000000,USB 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,
03000000666600000288000000000000,USB 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,
030000006b1400000203000000000000,USB 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,
03000000790000000a00000000000000,USB 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,
03000000b404000081c6000000000000,USB 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:a5,start:b9,x:b3,y:b0,platform:Windows,
03000000b50700001503000000000000,USB Controller,a:b2,b:b3,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:a5,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
03000000bd12000012d0000000000000,USB Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000ff1100004133000000000000,USB 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:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000632500002305000000000000,USB Vibration Joystick,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,
03000000790000001a18000000000000,Venom,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,
03000000790000001b18000000000000,Venom Arcade Joystick,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,
030000006f0e00000302000000000000,Victrix PS4 Pro Fightstick,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,
030000006f0e00000702000000000000,Victrix PS4 Pro Fightstick,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,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
0300000034120000adbe000000000000,vJoy Device,a:b0,b:b1,back:b15,dpdown:b6,dpleft:b7,dpright:b8,dpup:b5,guide:b16,leftshoulder:b9,leftstick:b13,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b14,righttrigger:b12,rightx:a3,righty:a4,start:b4,x:b2,y:b3,platform:Windows,
03000000120c0000ab57000000000000,Warrior Joypad JS083,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,
030000007e0500003003000000000000,WiiU Pro,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b6,leftstick:b11,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b12,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
0300000032150000030a000000000000,Wildcat,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,
030000005e040000ff02000000000000,Wired Xbox One 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,
0300000032150000140a000000000000,Wolverine,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,
030000002e160000efbe000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows,
03000000380700001647000000000000,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:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000380700002045000000000000,Xbox 360 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,
03000000380700002644000000000000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a5,start:b8,x:b2,y:b3,platform:Windows,
03000000380700002647000000000000,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,
030000003807000026b7000000000000,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:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000380700003647000000000000,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:a7,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
030000005e0400001907000000000000,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:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e0400008e02000000000000,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:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e0400009102000000000000,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:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000ad1b000000fd000000000000,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,
03000000ad1b000001fd000000000000,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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000ad1b000016f0000000000000,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:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000ad1b00008e02000000000000,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:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
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,
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,
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,
030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows,
03000000300f00008888000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:b13,dpleft:b10,dpright:b11,dpup:b12,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,
03000000380700001645000000000000,Xbox Controller,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,
03000000380700002645000000000000,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:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000380700003645000000000000,Xbox Controller,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,
03000000380700008645000000000000,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,
030000005e0400000202000000000000,Xbox Controller,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,
030000005e0400008502000000000000,Xbox 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,
030000005e0400008702000000000000,Xbox Controller,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:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
030000000d0f00006300000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e0400000c0b000000000000,Xbox One 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,
030000005e040000d102000000000000,Xbox One 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,
030000005e040000dd02000000000000,Xbox One 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,
030000005e040000e002000000000000,Xbox One 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,
030000005e040000e302000000000000,Xbox One 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,
030000005e040000ea02000000000000,Xbox One 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,
030000005e040000fd02000000000000,Xbox One 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,
030000006f0e0000a802000000000000,Xbox One 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,
030000006f0e0000c802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:Windows,
03000000c62400003a54000000000000,Xbox One 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,
030000005e040000130b000000000000,Xbox Series 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:Windows,
03000000341a00000608000000000000,Xeox,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,
03000000450c00002043000000000000,Xeox SL6556BK,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,
030000006f0e00000300000000000000,XGear,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:a5,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000ac0500005b05000000000000,Xiaoji 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,
03000000172700004431000000000000,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:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000786901006e70000000000000,XInput 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:Windows,
xinput,XInput 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:Windows,
03000000790000004f18000000000000,ZDT Android 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,
03000000120c0000101e000000000000,Zeroplus P4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
# Mac OS X
030000008f0e00000300000009010000,2In1 Joystick,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,
03000000c82d00000031000001000000,8BitDo Adapter,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:Mac OS X,
@@ -99,7 +812,7 @@
03000000d62000007162000001000000,Moga Pro 2,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:b6,x:b2,y:b3,platform:Mac OS X,
03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,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,
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,
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,
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,
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,
03000000d620000011a7000000020000,Nintendo Switch Core Plus 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,
@@ -119,7 +832,7 @@
030000004c050000c405000000000000,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,x:b0,y:b3,platform:Mac OS X,
030000004c050000c405000000010000,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,x:b0,y:b3,platform:Mac OS X,
030000004c050000cc09000000010000,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,x:b0,y:b3,platform:Mac OS X,
050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
030000008916000000fd000000000000,Razer Onza TE,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,
03000000321500000204000000010000,Razer Panthera 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:Mac OS X,
03000000321500000104000000010000,Razer Panthera 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,x:b0,y:b3,platform:Mac OS X,
@@ -164,7 +877,7 @@
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,
030000006f0e00000302000025040000,Victrix PS4 Pro Fightstick,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,
030000006f0e00000702000003060000,Victrix PS4 Pro Fightstick,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,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000791d00000103000009010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,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:Mac OS X,
03000000791d00000103000009010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,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:Mac OS X,
050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,
050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,
030000005e0400008e02000000000000,Xbox 360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
@@ -206,8 +919,8 @@
03000000c82d00000190000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Linux,
05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b12,start:b11,leftshoulder:b6,rightshoulder:b7,leftstick:b13,rightstick:b14,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux,
05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,x:b4,y:b3,back:b10,guide:b12,start:b11,leftshoulder:b6,rightshoulder:b7,leftstick:b13,rightstick:b14,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux,
03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,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:b4,y:b3,platform:Linux,
05000000c82d00000061000000010000,8Bitdo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
030000003512000012ab000010010000,8Bitdo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
@@ -254,6 +967,7 @@
05000000503200000210000000000000,Atari 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:b3,y:b2,platform:Linux,
05000000503200000210000045010000,Atari 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:b3,y:b2,platform:Linux,
05000000503200000210000046010000,Atari 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:b3,y:b2,platform:Linux,
05000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,x:b2,y:b3,back:b9,guide:b10,start:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b6,rightstick:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:+a5,righttrigger:-a4,platform:Linux,
03000000120c00000500000010010000,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:Linux,
03000000ef0500000300000000010000,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:Linux,
03000000c62400001b89000011010000,BDA MOGA XP5X 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:Linux,
@@ -275,7 +989,9 @@
030000004f04000004b3000010010000,Dual Power 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:Linux,
030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000c11100000191000011010000,EasySMX,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000242f00009100000000010000,EasySMX ESM-9101,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,
030000006e0500000320000010010000,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:Linux,
030000006e0500000720000010010000,Elecom W01U,a:b2,b:b3,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:a3,start:b9,x:b0,y:b1,platform:Linux,
03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,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:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle4:b17,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:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
@@ -299,6 +1015,7 @@
03000000c9110000f055000011010000,HJC 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,
03000000632500002605000010010000,HJDX,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:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000000d0f00000d00000000010000,Hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,
030000000d0f00006d00000020010000,Hori EDGE 301,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,
030000000d0f00008500000010010000,Hori Fighting Commander,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,
030000000d0f00008600000002010000,Hori Fighting Commander,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,
030000000d0f00005f00000011010000,Hori Fighting Commander 4 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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -408,25 +1125,28 @@
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,
030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
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,
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,
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,
050000004e696d6275732b0000000000,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,
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,
030000007e0500003703000000016800,Nintendo GameCube Controller,a:b0,b:b2,dpdown:b6,dpleft:b4,dpright:b5,dpup:b7,lefttrigger:a4,leftx:a0,lefty:a1~,rightshoulder:b9,righttrigger:a5,rightx:a2,righty:a3~,start:b8,x:b1,y:b3,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,
060000007e0500000620000000000000,Nintendo Switch Combined Joy-Cons,a:b0,b:b1,back:b9,dpdown:b15,dpleft:b16,dpright:b17,dpup:b14,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
060000007e0500000820000000000000,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,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
050000004c69632050726f20436f6e00,Nintendo 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,
050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b9,b:b8,back:b5,leftshoulder:b2,leftstick:b6,leftx:a1,lefty:a0~,rightshoulder:b4,start:b0,x:b7,y:b10,platform:Linux,
050000007e0500000620000001800000,Nintendo Switch Left Joy-Con,a:b16,b:b15,back:b4,leftshoulder:b6,leftstick:b12,leftx:a1,lefty:a0~,rightshoulder:b8,start:b9,x:b14,y:b17,platform:Linux,
050000007e0500001920000001000000,Nintendo Switch 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:Linux,
050000007e0500001720000001000000,Nintendo Switch Online Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
03000000d620000013a7000011010000,Nintendo Switch PowerA 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,
03000000d620000011a7000011010000,Nintendo Switch PowerA Core Plus 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,
030000007e0500000920000011810000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
050000007e0500000920000001000000,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
050000007e0500000920000001800000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0~,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux,
050000007e0500001720000001000000,Nintendo Switch 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:Linux,
050000007e0500000720000001800000,Nintendo Switch Right Joy-Con,a:b1,b:b2,back:b9,leftshoulder:b4,leftstick:b10,leftx:a1~,lefty:a0,rightshoulder:b6,start:b8,x:b0,y:b3,platform:Linux,
050000007e0500003003000001000000,Nintendo Wii Remote 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,
05000000010000000100000003000000,Nintendo Wiimote,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,
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,
030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
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 v01.04,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,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
@@ -438,7 +1158,7 @@
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,
05000000362800000100000003010000,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,
05000000362800000100000004010000,OUYA Controller,a:b0,b:b3,back:b14,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,start:b16,x:b1,y:b2,platform:Linux,
03000000830500005020000010010000,Padix Rockfire PlayStation Brige,a:b0,b:b1,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:b2,y:b3,platform:Linux,
03000000830500005020000010010000,Padix Rockfire PlayStation Bridge,a:b0,b:b1,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:b2,y:b3,platform:Linux,
03000000790000001c18000011010000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000ff1100003133000010010000,PC Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
030000006f0e0000b802000001010000,PDP Afterglow 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,
@@ -471,6 +1191,7 @@
030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000004c0500006802000011010000,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:Linux,
030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000005f1400003102000010010000,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:a3,start:b9,x:b3,y:b0,platform:Linux,
030000006f0e00001402000011010000,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,
030000008f0e00000300000010010000,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:a3,start:b9,x:b3,y:b0,platform:Linux,
050000004c0500006802000000000000,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:Linux,
@@ -493,8 +1214,8 @@
050000004c050000cc09000000010000,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,x:b0,y:b3,platform:Linux,
050000004c050000cc09000000810000,PS4 Controller,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:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
050000004c050000cc09000001800000,PS4 Controller,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:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
030000004c050000e60c000011010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
050000004c050000e60c000000010000,PS5 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,
03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,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,
@@ -603,7 +1324,7 @@
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,x:b0,y:b3,platform:Linux,
030000006f0e00000702000011010000,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,leftstick:b10,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
05000000ac0500003232000001000000,VR Box Controller,a:b0,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:b2,y:b3,platform:Linux,
03000000791d00000103000010010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
0000000058626f782033363020576900,Xbox 360 Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,
030000005e0400001907000000010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400008e02000010010000,Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -636,6 +1357,7 @@
050000005e040000130b000005050000,Xbox Series 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,
050000005e040000130b000009050000,Xbox Series 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,
060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
050000005e040000130b000011050000,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,
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,
03000000ac0500005b05000010010000,Xiaoji 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: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,
+15 -34
View File
@@ -114,15 +114,12 @@ float4 ps_scanlines(PS_INPUT input, int i)
return sample_c(input.t) * saturate(mask[i] + 0.5f);
}
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
uint ps_convert_rgba8_16bits(PS_INPUT input) : SV_Target0
{
float4 c = sample_c(input.t);
uint4 i = sample_c(input.t) * float4(255.5f, 255.5f, 255.5f, 255.5f);
c.a *= 256.0f / 127; // hm, 0.5 won't give us 1.0 if we just multiply with 2
uint4 i = c * float4(0x001f, 0x03e0, 0x7c00, 0x8000);
return (i.x & 0x001f) | (i.y & 0x03e0) | (i.z & 0x7c00) | (i.w & 0x8000);
return ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
}
PS_OUTPUT ps_datm1(PS_INPUT input)
@@ -221,12 +218,8 @@ PS_OUTPUT ps_convert_float32_rgba8(PS_INPUT input)
PS_OUTPUT output;
// Convert a FLOAT32 depth texture into a RGBA color texture
const float4 bitSh = float4(exp2(24.0f), exp2(16.0f), exp2(8.0f), exp2(0.0f));
const float4 bitMsk = float4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
float4 res = frac(float4(sample_c(input.t).rrrr) * bitSh);
output.c = (res - res.xxyz * bitMsk) * 256.0f / 255.0f;
uint d = uint(sample_c(input.t).r * exp2(32.0f));
output.c = float4(uint4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / 255.0f;
return output;
}
@@ -236,21 +229,16 @@ PS_OUTPUT ps_convert_float16_rgb5a1(PS_INPUT input)
PS_OUTPUT output;
// Convert a FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
const float4 bitSh = float4(exp2(32.0f), exp2(27.0f), exp2(22.0f), exp2(17.0f));
const uint4 bitMsk = uint4(0x1F, 0x1F, 0x1F, 0x1);
uint4 color = uint4(float4(sample_c(input.t).rrrr) * bitSh) & bitMsk;
output.c = float4(color) / float4(32.0f, 32.0f, 32.0f, 1.0f);
uint d = uint(sample_c(input.t).r * exp2(32.0f));
output.c = float4(uint4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / float4(32.0f, 32.0f, 32.0f, 1.0f);
return output;
}
float ps_convert_rgba8_float32(PS_INPUT input) : SV_Depth
{
// Convert a RRGBA texture into a float depth texture
// FIXME: I'm afraid of the accuracy
const float4 bitSh = float4(exp2(-32.0f), exp2(-24.0f), exp2(-16.0f), exp2(-8.0f)) * (float4)255.0;
return dot(sample_c(input.t), bitSh);
uint4 c = uint4(sample_c(input.t) * 255.0f + 0.5f);
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
}
float ps_convert_rgba8_float24(PS_INPUT input) : SV_Depth
@@ -258,9 +246,8 @@ float ps_convert_rgba8_float24(PS_INPUT input) : SV_Depth
// Same as above but without the alpha channel (24 bits Z)
// Convert a RRGBA texture into a float depth texture
const float3 bitSh = float3(exp2(-32.0f), exp2(-24.0f), exp2(-16.0f)) * (float3)255.0;
return dot(sample_c(input.t).rgb, bitSh);
uint3 c = uint3(sample_c(input.t).rgb * 255.0f + 0.5f);
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
}
float ps_convert_rgba8_float16(PS_INPUT input) : SV_Depth
@@ -268,21 +255,15 @@ float ps_convert_rgba8_float16(PS_INPUT input) : SV_Depth
// Same as above but without the A/B channels (16 bits Z)
// Convert a RRGBA texture into a float depth texture
// FIXME: I'm afraid of the accuracy
const float2 bitSh = float2(exp2(-32.0f), exp2(-24.0f)) * (float2)255.0;
return dot(sample_c(input.t).rg, bitSh);
uint2 c = uint2(sample_c(input.t).rg * 255.0f + 0.5f);
return float(c.r | (c.g << 8)) * exp2(-32.0f);
}
float ps_convert_rgb5a1_float16(PS_INPUT input) : SV_Depth
{
// Convert a RGB5A1 (saved as RGBA8) color to a 16 bit Z
// FIXME: I'm afraid of the accuracy
const float4 bitSh = float4(exp2(-32.0f), exp2(-27.0f), exp2(-22.0f), exp2(-17.0f));
// Trunc color to drop useless lsb
float4 color = trunc(sample_c(input.t) * (float4)255.0 / float4(8.0f, 8.0f, 8.0f, 128.0f));
return dot(float4(color), bitSh);
uint4 c = uint4(sample_c(input.t) * 255.0f + 0.5f);
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
}
PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
+10 -17
View File
@@ -49,7 +49,7 @@
#define PS_BLEND_B 0
#define PS_BLEND_C 0
#define PS_BLEND_D 0
#define PS_ALPHA_CLAMP 0
#define PS_BLEND_MIX 0
#define PS_PABE 0
#define PS_DITHER 0
#define PS_ZCLAMP 0
@@ -390,26 +390,19 @@ float4 sample_depth(float2 st, float2 pos)
}
else if (PS_DEPTH_FMT == 1)
{
// Based on ps_main11 of convert
// Based on ps_convert_float32_rgba8 of convert
// Convert a FLOAT32 depth texture into a RGBA color texture
const float4 bitSh = float4(exp2(24.0f), exp2(16.0f), exp2(8.0f), exp2(0.0f));
const float4 bitMsk = float4(0.0, 1.0f / 256.0f, 1.0f / 256.0f, 1.0f / 256.0f);
float4 res = frac((float4)fetch_c(uv).r * bitSh);
t = (res - res.xxyz * bitMsk) * 256.0f;
uint d = uint(fetch_c(uv).r * exp2(32.0f));
t = float4(uint4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24)));
}
else if (PS_DEPTH_FMT == 2)
{
// Based on ps_main12 of convert
// Based on ps_convert_float16_rgb5a1 of convert
// Convert a FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
const float4 bitSh = float4(exp2(32.0f), exp2(27.0f), exp2(22.0f), exp2(17.0f));
const uint4 bitMsk = uint4(0x1F, 0x1F, 0x1F, 0x1);
uint4 color = (uint4)((float4)fetch_c(uv).r * bitSh) & bitMsk;
t = (float4)color * float4(8.0f, 8.0f, 8.0f, 128.0f);
uint d = uint(fetch_c(uv).r * exp2(32.0f));
t = float4(uint4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) * float4(8.0f, 8.0f, 8.0f, 128.0f);
}
else if (PS_DEPTH_FMT == 3)
{
@@ -717,14 +710,14 @@ void ps_color_clamp_wrap(inout float3 C)
{
// When dithering the bottom 3 bits become meaningless and cause lines in the picture
// so we need to limit the color depth on dithered items
if (SW_BLEND || PS_DITHER)
if (SW_BLEND || PS_DITHER || PS_FBMASK)
{
// Standard Clamp
if (PS_COLCLIP == 0 && PS_HDR == 0)
C = clamp(C, (float3)0.0f, (float3)255.0f);
// In 16 bits format, only 5 bits of color are used. It impacts shadows computation of Castlevania
if (PS_DFMT == FMT_16)
if (PS_DFMT == FMT_16 && (PS_HDR == 1 || PS_BLEND_MIX == 0))
C = (float3)((int3)C & (int3)0xF8);
else if (PS_COLCLIP == 1 && PS_HDR == 0)
C = (float3)((int3)C & (int3)0xFF);
@@ -756,7 +749,7 @@ void ps_blend(inout float4 Color, float As, float2 pos_xy)
float3 D = (PS_BLEND_D == 0) ? Cs : ((PS_BLEND_D == 1) ? Cd : (float3)0.0f);
// As/Af clamp alpha for Blend mix
if (PS_ALPHA_CLAMP)
if (PS_BLEND_MIX)
C = min(C, (float)1.0f);
Color.rgb = (PS_BLEND_A == PS_BLEND_B) ? D : trunc(((A - B) * C) + D);
+15 -63
View File
@@ -74,47 +74,12 @@ void ps_depth_copy()
#endif
#ifdef ps_convert_rgba8_16bits
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
void ps_convert_rgba8_16bits()
{
// Input Color is RGBA8
// We want to output a pixel on the PSMCT16* format
// A1-BGR5
#if 0
// Note: dot is a good idea from pseudo. However we must be careful about float accuraccy.
// Here a global idea example:
//
// SV_Target1 = dot(round(sample_c() * vec4(31.f, 31.f, 31.f, 1.f)), vec4(1.f, 32.f, 1024.f, 32768.f));
//
// For me this code is more accurate but it will require some tests
vec4 c = sample_c() * 255.0f + 0.5f; // Denormalize value to avoid float precision issue
// shift Red: -3
// shift Green: -3 + 5
// shift Blue: -3 + 10
// shift Alpha: -7 + 15
highp uvec4 i = uvec4(c * vec4(1/8.0f, 4.0f, 128.0f, 256.0f)); // Shift value
// bit field operation requires GL4 HW. Could be nice to merge it with step/mix below
SV_Target1 = (i.r & uint(0x001f)) | (i.g & uint(0x03e0)) | (i.b & uint(0x7c00)) | (i.a & uint(0x8000));
#else
// Old code which is likely wrong.
vec4 c = sample_c();
c.a *= 256.0f / 127.0f; // hm, 0.5 won't give us 1.0 if we just multiply with 2
highp uvec4 i = uvec4(c * vec4(uint(0x001f), uint(0x03e0), uint(0x7c00), uint(0x8000)));
// bit field operation requires GL4 HW.
SV_Target1 = (i.x & uint(0x001f)) | (i.y & uint(0x03e0)) | (i.z & uint(0x7c00)) | (i.w & uint(0x8000));
#endif
highp uvec4 i = uvec4(sample_c() * vec4(255.5f, 255.5f, 255.5f, 255.5f));
SV_Target1 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
}
#endif
@@ -130,12 +95,8 @@ void ps_convert_float32_32bits()
void ps_convert_float32_rgba8()
{
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
const vec4 bitSh = vec4(exp2(24.0f), exp2(16.0f), exp2(8.0f), exp2(0.0f));
const vec4 bitMsk = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
vec4 res = fract(vec4(sample_c().r) * bitSh);
SV_Target0 = (res - res.xxyz * bitMsk) * 256.0f/255.0f;
uint d = uint(sample_c().r * exp2(32.0f));
SV_Target0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
}
#endif
@@ -143,11 +104,8 @@ void ps_convert_float32_rgba8()
void ps_convert_float16_rgb5a1()
{
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
const vec4 bitSh = vec4(exp2(32.0f), exp2(27.0f), exp2(22.0f), exp2(17.0f));
const uvec4 bitMsk = uvec4(0x1F, 0x1F, 0x1F, 0x1);
uvec4 color = uvec4(vec4(sample_c().r) * bitSh) & bitMsk;
SV_Target0 = vec4(color) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
uint d = uint(sample_c().r * exp2(32.0f));
SV_Target0 = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
}
#endif
@@ -155,9 +113,8 @@ void ps_convert_float16_rgb5a1()
void ps_convert_rgba8_float32()
{
// Convert a RRGBA texture into a float depth texture
// FIXME: I'm afraid of the accuracy
const vec4 bitSh = vec4(exp2(-32.0f), exp2(-24.0f), exp2(-16.0f), exp2(-8.0f)) * vec4(255.0);
gl_FragDepth = dot(sample_c(), bitSh);
uvec4 c = uvec4(sample_c() * vec4(255.0f) + vec4(0.5f));
gl_FragDepth = float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
}
#endif
@@ -167,9 +124,8 @@ void ps_convert_rgba8_float24()
// Same as above but without the alpha channel (24 bits Z)
// Convert a RRGBA texture into a float depth texture
// FIXME: I'm afraid of the accuracy
const vec3 bitSh = vec3(exp2(-32.0f), exp2(-24.0f), exp2(-16.0f)) * vec3(255.0);
gl_FragDepth = dot(sample_c().rgb, bitSh);
uvec3 c = uvec3(sample_c().rgb * vec3(255.0f) + vec3(0.5f));
gl_FragDepth = float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
}
#endif
@@ -179,9 +135,8 @@ void ps_convert_rgba8_float16()
// Same as above but without the A/B channels (16 bits Z)
// Convert a RRGBA texture into a float depth texture
// FIXME: I'm afraid of the accuracy
const vec2 bitSh = vec2(exp2(-32.0f), exp2(-24.0f)) * vec2(255.0);
gl_FragDepth = dot(sample_c().rg, bitSh);
uvec2 c = uvec2(sample_c().rg * vec2(255.0f) + vec2(0.5f));
gl_FragDepth = float(c.r | (c.g << 8)) * exp2(-32.0f);
}
#endif
@@ -189,11 +144,8 @@ void ps_convert_rgba8_float16()
void ps_convert_rgb5a1_float16()
{
// Convert a RGB5A1 (saved as RGBA8) color to a 16 bit Z
// FIXME: I'm afraid of the accuracy
const vec4 bitSh = vec4(exp2(-32.0f), exp2(-27.0f), exp2(-22.0f), exp2(-17.0f));
// Trunc color to drop useless lsb
vec4 color = trunc(sample_c() * vec4(255.0f) / vec4(8.0f, 8.0f, 8.0f, 128.0f));
gl_FragDepth = dot(vec4(color), bitSh);
uvec4 c = uvec4(sample_c() * vec4(255.0f) + vec4(0.5f));
gl_FragDepth = float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
}
#endif
+9 -18
View File
@@ -326,25 +326,16 @@ vec4 sample_depth(vec2 st)
#elif PS_DEPTH_FMT == 1
// Based on ps_main11 of convert
// Based on ps_convert_float32_rgba8 of convert
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
const vec4 bitSh = vec4(exp2(24.0f), exp2(16.0f), exp2(8.0f), exp2(0.0f));
const vec4 bitMsk = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
vec4 res = fract(vec4(fetch_c(uv).r) * bitSh);
t = (res - res.xxyz * bitMsk) * 256.0f;
uint d = uint(fetch_c(uv).r * exp2(32.0f));
t = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24)));
#elif PS_DEPTH_FMT == 2
// Based on ps_main12 of convert
// Based on ps_convert_float16_rgb5a1 of convert
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
const vec4 bitSh = vec4(exp2(32.0f), exp2(27.0f), exp2(22.0f), exp2(17.0f));
const uvec4 bitMsk = uvec4(0x1F, 0x1F, 0x1F, 0x1);
uvec4 color = uvec4(vec4(fetch_c(uv).r) * bitSh) & bitMsk;
t = vec4(color) * vec4(8.0f, 8.0f, 8.0f, 128.0f);
uint d = uint(fetch_c(uv).r * exp2(32.0f));
t = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) * vec4(8.0f, 8.0f, 8.0f, 128.0f);
#elif PS_DEPTH_FMT == 3
// Convert a RGBA/RGB5A1 color texture into a RGBA/RGB5A1 color texture
@@ -633,7 +624,7 @@ void ps_color_clamp_wrap(inout vec3 C)
{
// When dithering the bottom 3 bits become meaningless and cause lines in the picture
// so we need to limit the color depth on dithered items
#if SW_BLEND || PS_DITHER
#if SW_BLEND || PS_DITHER || PS_FBMASK
// Correct the Color value based on the output format
#if PS_COLCLIP == 0 && PS_HDR == 0
@@ -647,7 +638,7 @@ void ps_color_clamp_wrap(inout vec3 C)
// Warning: normally blending equation is mult(A, B) = A * B >> 7. GPU have the full accuracy
// GS: Color = 1, Alpha = 255 => output 1
// GPU: Color = 1/255, Alpha = 255/255 * 255/128 => output 1.9921875
#if PS_DFMT == FMT_16
#if PS_DFMT == FMT_16 && (PS_HDR == 1 || PS_BLEND_MIX == 0)
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
C = vec3(ivec3(C) & ivec3(0xF8));
#elif PS_COLCLIP == 1 && PS_HDR == 0
@@ -715,7 +706,7 @@ void ps_blend(inout vec4 Color, float As)
#endif
// As/Af clamp alpha for Blend mix
#if PS_ALPHA_CLAMP
#if PS_BLEND_MIX
C = min(C, float(1.0f));
#endif
+15 -34
View File
@@ -87,15 +87,12 @@ void ps_filter_transparency()
#endif
#ifdef ps_convert_rgba8_16bits
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
void ps_convert_rgba8_16bits()
{
vec4 c = sample_c(v_tex);
uvec4 i = uvec4(sample_c(v_tex) * vec4(255.5f, 255.5f, 255.5f, 255.5f));
c.a *= 256.0f / 127; // hm, 0.5 won't give us 1.0 if we just multiply with 2
uvec4 i = uvec4(c * vec4(0x001f, 0x03e0, 0x7c00, 0x8000));
o_col0 = (i.x & 0x001fu) | (i.y & 0x03e0u) | (i.z & 0x7c00u) | (i.w & 0x8000u);
o_col0 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
}
#endif
@@ -183,12 +180,8 @@ void ps_convert_float32_32bits()
void ps_convert_float32_rgba8()
{
// Convert a vec32 depth texture into a RGBA color texture
const vec4 bitSh = vec4(exp2(24.0f), exp2(16.0f), exp2(8.0f), exp2(0.0f));
const vec4 bitMsk = vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
vec4 res = fract(vec4(sample_c(v_tex).rrrr) * bitSh);
o_col0 = (res - res.xxyz * bitMsk) * 256.0f / 255.0f;
uint d = uint(sample_c(v_tex).r * exp2(32.0f));
o_col0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
}
#endif
@@ -196,11 +189,8 @@ void ps_convert_float32_rgba8()
void ps_convert_float16_rgb5a1()
{
// Convert a vec32 (only 16 lsb) depth into a RGB5A1 color texture
const vec4 bitSh = vec4(exp2(32.0f), exp2(27.0f), exp2(22.0f), exp2(17.0f));
const uvec4 bitMsk = uvec4(0x1F, 0x1F, 0x1F, 0x1);
uvec4 color = uvec4(vec4(sample_c(v_tex).rrrr) * bitSh) & bitMsk;
o_col0 = vec4(color) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
uint d = uint(sample_c(v_tex).r * exp2(32.0f));
o_col0 = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
}
#endif
@@ -208,10 +198,8 @@ void ps_convert_float16_rgb5a1()
void ps_convert_rgba8_float32()
{
// Convert a RRGBA texture into a float depth texture
// FIXME: I'm afraid of the accuracy
const vec4 bitSh = vec4(exp2(-32.0f), exp2(-24.0f), exp2(-16.0f), exp2(-8.0f)) * vec4(255.0);
gl_FragDepth = dot(sample_c(v_tex), bitSh);
uvec4 c = uvec4(sample_c(v_tex) * vec4(255.0f) + vec4(0.5f));
gl_FragDepth = float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
}
#endif
@@ -221,9 +209,8 @@ void ps_convert_rgba8_float24()
// Same as above but without the alpha channel (24 bits Z)
// Convert a RRGBA texture into a float depth texture
const vec3 bitSh = vec3(exp2(-32.0f), exp2(-24.0f), exp2(-16.0f)) * vec3(255.0);
gl_FragDepth = dot(sample_c(v_tex).rgb, bitSh);
uvec3 c = uvec3(sample_c(v_tex).rgb * vec3(255.0f) + vec3(0.5f));
gl_FragDepth = float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
}
#endif
@@ -233,10 +220,8 @@ void ps_convert_rgba8_float16()
// Same as above but without the A/B channels (16 bits Z)
// Convert a RRGBA texture into a float depth texture
// FIXME: I'm afraid of the accuracy
const vec2 bitSh = vec2(exp2(-32.0f), exp2(-24.0f)) * vec2(255.0);
gl_FragDepth = dot(sample_c(v_tex).rg, bitSh);
uvec2 c = uvec2(sample_c(v_tex).rg * vec2(255.0f) + vec2(0.5f));
gl_FragDepth = float(c.r | (c.g << 8)) * exp2(-32.0f);
}
#endif
@@ -244,12 +229,8 @@ void ps_convert_rgba8_float16()
void ps_convert_rgb5a1_float16()
{
// Convert a RGB5A1 (saved as RGBA8) color to a 16 bit Z
// FIXME: I'm afraid of the accuracy
const vec4 bitSh = vec4(exp2(-32.0f), exp2(-27.0f), exp2(-22.0f), exp2(-17.0f));
// Trunc color to drop useless lsb
vec4 color = trunc(sample_c(v_tex) * vec4(255.0f) / vec4(8.0f, 8.0f, 8.0f, 128.0f));
gl_FragDepth = dot(vec4(color), bitSh);
uvec4 c = uvec4(sample_c(v_tex) * vec4(255.0f) + vec4(0.5f));
gl_FragDepth = float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
}
#endif
+9 -16
View File
@@ -650,26 +650,19 @@ vec4 sample_depth(vec2 st, ivec2 pos)
}
#elif (PS_DEPTH_FMT == 1)
{
// Based on ps_main11 of convert
// Based on ps_convert_float32_rgba8 of convert
// Convert a vec32 depth texture into a RGBA color texture
const vec4 bitSh = vec4(exp2(24.0f), exp2(16.0f), exp2(8.0f), exp2(0.0f));
const vec4 bitMsk = vec4(0.0, 1.0f / 256.0f, 1.0f / 256.0f, 1.0f / 256.0f);
vec4 res = fract(vec4(fetch_c(uv).r) * bitSh);
t = (res - res.xxyz * bitMsk) * 256.0f;
uint d = uint(fetch_c(uv).r * exp2(32.0f));
t = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24)));
}
#elif (PS_DEPTH_FMT == 2)
{
// Based on ps_main12 of convert
// Based on ps_convert_float16_rgb5a1 of convert
// Convert a vec32 (only 16 lsb) depth into a RGB5A1 color texture
const vec4 bitSh = vec4(exp2(32.0f), exp2(27.0f), exp2(22.0f), exp2(17.0f));
const uvec4 bitMsk = uvec4(0x1F, 0x1F, 0x1F, 0x1);
uvec4 color = uvec4(vec4(fetch_c(uv).r) * bitSh) & bitMsk;
t = vec4(color) * vec4(8.0f, 8.0f, 8.0f, 128.0f);
uint d = uint(fetch_c(uv).r * exp2(32.0f));
t = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) * vec4(8.0f, 8.0f, 8.0f, 128.0f);
}
#elif (PS_DEPTH_FMT == 3)
{
@@ -966,7 +959,7 @@ void ps_color_clamp_wrap(inout vec3 C)
{
// When dithering the bottom 3 bits become meaningless and cause lines in the picture
// so we need to limit the color depth on dithered items
#if SW_BLEND || PS_DITHER
#if SW_BLEND || PS_DITHER || PS_FBMASK
// Correct the Color value based on the output format
#if PS_COLCLIP == 0 && PS_HDR == 0
@@ -980,7 +973,7 @@ void ps_color_clamp_wrap(inout vec3 C)
// Warning: normally blending equation is mult(A, B) = A * B >> 7. GPU have the full accuracy
// GS: Color = 1, Alpha = 255 => output 1
// GPU: Color = 1/255, Alpha = 255/255 * 255/128 => output 1.9921875
#if PS_DFMT == FMT_16
#if PS_DFMT == FMT_16 && (PS_HDR == 1 || PS_BLEND_MIX == 0)
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
C = vec3(ivec3(C) & ivec3(0xF8));
#elif PS_COLCLIP == 1 && PS_HDR == 0
@@ -1053,7 +1046,7 @@ void ps_blend(inout vec4 Color, float As)
#endif
// As/Af clamp alpha for Blend mix
#if PS_ALPHA_CLAMP
#if PS_BLEND_MIX
C = min(C, 1.0f);
#endif
+181
View File
@@ -0,0 +1,181 @@
# Copyright (c) 2012, Intel Corporation
# Copyright (c) 2019 Sony Interactive Entertainment Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Intel Corporation nor the names of its contributors may
# be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Try to find Harfbuzz include and library directories.
#
# After successful discovery, this will set for inclusion where needed:
# HarfBuzz_INCLUDE_DIRS - containg the HarfBuzz headers
# HarfBuzz_LIBRARIES - containg the HarfBuzz library
#[=======================================================================[.rst:
FindHarfBuzz
--------------
Find HarfBuzz headers and libraries.
Imported Targets
^^^^^^^^^^^^^^^^
``HarfBuzz::HarfBuzz``
The HarfBuzz library, if found.
``HarfBuzz::ICU``
The HarfBuzz ICU library, if found.
Result Variables
^^^^^^^^^^^^^^^^
This will define the following variables in your project:
``HarfBuzz_FOUND``
true if (the requested version of) HarfBuzz is available.
``HarfBuzz_VERSION``
the version of HarfBuzz.
``HarfBuzz_LIBRARIES``
the libraries to link against to use HarfBuzz.
``HarfBuzz_INCLUDE_DIRS``
where to find the HarfBuzz headers.
``HarfBuzz_COMPILE_OPTIONS``
this should be passed to target_compile_options(), if the
target is not used for linking
#]=======================================================================]
find_package(PkgConfig QUIET)
pkg_check_modules(PC_HARFBUZZ QUIET harfbuzz)
set(HarfBuzz_COMPILE_OPTIONS ${PC_HARFBUZZ_CFLAGS_OTHER})
set(HarfBuzz_VERSION ${PC_HARFBUZZ_CFLAGS_VERSION})
find_path(HarfBuzz_INCLUDE_DIR
NAMES hb.h
HINTS ${PC_HARFBUZZ_INCLUDEDIR} ${PC_HARFBUZZ_INCLUDE_DIRS}
PATH_SUFFIXES harfbuzz
)
find_library(HarfBuzz_LIBRARY
NAMES ${HarfBuzz_NAMES} harfbuzz
HINTS ${PC_HARFBUZZ_LIBDIR} ${PC_HARFBUZZ_LIBRARY_DIRS}
)
if (HarfBuzz_INCLUDE_DIR AND NOT HarfBuzz_VERSION)
if (EXISTS "${HarfBuzz_INCLUDE_DIR}/hb-version.h")
file(READ "${HarfBuzz_INCLUDE_DIR}/hb-version.h" _harfbuzz_version_content)
string(REGEX MATCH "#define +HB_VERSION_STRING +\"([0-9]+\\.[0-9]+\\.[0-9]+)\"" _dummy "${_harfbuzz_version_content}")
set(HarfBuzz_VERSION "${CMAKE_MATCH_1}")
endif ()
endif ()
if ("${HarfBuzz_FIND_VERSION}" VERSION_GREATER "${HarfBuzz_VERSION}")
message(FATAL_ERROR "Required version (" ${HarfBuzz_FIND_VERSION} ") is higher than found version (" ${HarfBuzz_VERSION} ")")
endif ()
# Find components
if (HarfBuzz_INCLUDE_DIR AND HarfBuzz_LIBRARY)
set(_HarfBuzz_REQUIRED_LIBS_FOUND ON)
set(HarfBuzz_LIBS_FOUND "HarfBuzz (required): ${HarfBuzz_LIBRARY}")
else ()
set(_HarfBuzz_REQUIRED_LIBS_FOUND OFF)
set(HarfBuzz_LIBS_NOT_FOUND "HarfBuzz (required)")
endif ()
if ("ICU" IN_LIST HarfBuzz_FIND_COMPONENTS)
pkg_check_modules(PC_HARFBUZZ_ICU QUIET harfbuzz-icu)
set(HarfBuzz_ICU_COMPILE_OPTIONS ${PC_HARFBUZZ_ICU_CFLAGS_OTHER})
find_library(HarfBuzz_ICU_LIBRARY
NAMES ${HarfBuzz_ICU_NAMES} harfbuzz-icu
HINTS ${PC_HARFBUZZ_ICU_LIBDIR} ${PC_HARFBUZZ_ICU_LIBRARY_DIRS}
)
if (HarfBuzz_ICU_LIBRARY)
if (HarfBuzz_FIND_REQUIRED_ICU)
list(APPEND HarfBuzz_LIBS_FOUND "ICU (required): ${HarfBuzz_ICU_LIBRARY}")
else ()
list(APPEND HarfBuzz_LIBS_FOUND "ICU (optional): ${HarfBuzz_ICU_LIBRARY}")
endif ()
else ()
if (HarfBuzz_FIND_REQUIRED_ICU)
set(_HarfBuzz_REQUIRED_LIBS_FOUND OFF)
list(APPEND HarfBuzz_LIBS_NOT_FOUND "ICU (required)")
else ()
list(APPEND HarfBuzz_LIBS_NOT_FOUND "ICU (optional)")
endif ()
endif ()
endif ()
if (NOT HarfBuzz_FIND_QUIETLY)
if (HarfBuzz_LIBS_FOUND)
message(STATUS "Found the following HarfBuzz libraries:")
foreach (found ${HarfBuzz_LIBS_FOUND})
message(STATUS " ${found}")
endforeach ()
endif ()
if (HarfBuzz_LIBS_NOT_FOUND)
message(STATUS "The following HarfBuzz libraries were not found:")
foreach (found ${HarfBuzz_LIBS_NOT_FOUND})
message(STATUS " ${found}")
endforeach ()
endif ()
endif ()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(HarfBuzz
FOUND_VAR HarfBuzz_FOUND
REQUIRED_VARS HarfBuzz_INCLUDE_DIR HarfBuzz_LIBRARY _HarfBuzz_REQUIRED_LIBS_FOUND
VERSION_VAR HarfBuzz_VERSION
)
if (HarfBuzz_LIBRARY AND NOT TARGET HarfBuzz::HarfBuzz)
add_library(HarfBuzz::HarfBuzz UNKNOWN IMPORTED GLOBAL)
set_target_properties(HarfBuzz::HarfBuzz PROPERTIES
IMPORTED_LOCATION "${HarfBuzz_LIBRARY}"
INTERFACE_COMPILE_OPTIONS "${HarfBuzz_COMPILE_OPTIONS}"
INTERFACE_INCLUDE_DIRECTORIES "${HarfBuzz_INCLUDE_DIR}"
)
endif ()
if (HarfBuzz_ICU_LIBRARY AND NOT TARGET HarfBuzz::ICU)
add_library(HarfBuzz::ICU UNKNOWN IMPORTED GLOBAL)
set_target_properties(HarfBuzz::ICU PROPERTIES
IMPORTED_LOCATION "${HarfBuzz_ICU_LIBRARY}"
INTERFACE_COMPILE_OPTIONS "${HarfBuzz_ICU_COMPILE_OPTIONS}"
INTERFACE_INCLUDE_DIRECTORIES "${HarfBuzz_INCLUDE_DIR}"
)
endif ()
mark_as_advanced(
HarfBuzz_INCLUDE_DIR
HarfBuzz_LIBRARY
HarfBuzz_ICU_LIBRARY
)
if (HarfBuzz_FOUND)
set(HarfBuzz_LIBRARIES ${HarfBuzz_LIBRARY} ${HarfBuzz_ICU_LIBRARY})
set(HarfBuzz_INCLUDE_DIRS ${HarfBuzz_INCLUDE_DIR})
endif ()
+5 -2
View File
@@ -23,8 +23,6 @@ else()
make_imported_target_if_missing(ALSA::ALSA ALSA)
endif()
find_package(PCAP REQUIRED)
find_package(LibXml2 REQUIRED)
make_imported_target_if_missing(LibXml2::LibXml2 LibXml2)
find_package(Gettext) # translation tool
find_package(LibLZMA REQUIRED)
make_imported_target_if_missing(LibLZMA::LibLZMA LIBLZMA)
@@ -163,6 +161,8 @@ else()
check_lib(GTK3 gtk+-3.0 gtk/gtk.h)
alias_library(GTK::gtk PkgConfig::GTK3)
endif()
## Use pcsx2 package to find module
find_package(HarfBuzz)
endif()
endif()
if(WAYLAND_API)
@@ -248,6 +248,7 @@ if(QT_BUILD)
endif()
add_subdirectory(3rdparty/libchdr/libchdr EXCLUDE_FROM_ALL)
target_compile_options(chdr-static PRIVATE "-w")
if(USE_NATIVE_TOOLS)
add_subdirectory(tools/bin2cpp EXCLUDE_FROM_ALL)
@@ -269,5 +270,7 @@ endif()
if(CUBEB_API)
add_subdirectory(3rdparty/cubeb EXCLUDE_FROM_ALL)
target_compile_options(cubeb PRIVATE "-w")
target_compile_options(speex PRIVATE "-w")
endif()
+9
View File
@@ -565,6 +565,15 @@ bool FileSystem::WriteFileToString(const char* filename, const std::string_view&
return true;
}
bool FileSystem::EnsureDirectoryExists(const char* path, bool recursive)
{
if (FileSystem::DirectoryExists(path))
return true;
// if it fails to create, we're not going to be able to use it anyway
return FileSystem::CreateDirectoryPath(path, recursive);
}
#ifdef _WIN32
static u32 TranslateWin32Attributes(u32 Win32Attributes)
+4
View File
@@ -150,6 +150,10 @@ namespace FileSystem
/// if they do not exist.
bool CreateDirectoryPath(const char* path, bool recursive);
/// Creates a directory if it doesn't already exist.
/// Returns false if it does not exist and creation failed.
bool EnsureDirectoryExists(const char* path, bool recursive);
/// Returns the path to the current executable.
std::string GetProgramPath();
+4 -4
View File
@@ -149,10 +149,10 @@ namespace GL
const char* gl_renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
const char* gl_version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
const char* gl_shading_language_version = reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
Console.WriteLn(Color_Magenta, "GL_VENDOR: %s", gl_vendor);
Console.WriteLn(Color_Magenta, "GL_RENDERER: %s", gl_renderer);
Console.WriteLn(Color_Magenta, "GL_VERSION: %s", gl_version);
Console.WriteLn(Color_Magenta, "GL_SHADING_LANGUAGE_VERSION: %s", gl_shading_language_version);
DevCon.WriteLn(Color_Magenta, "GL_VENDOR: %s", gl_vendor);
DevCon.WriteLn(Color_Magenta, "GL_RENDERER: %s", gl_renderer);
DevCon.WriteLn(Color_Magenta, "GL_VERSION: %s", gl_version);
DevCon.WriteLn(Color_Magenta, "GL_SHADING_LANGUAGE_VERSION: %s", gl_shading_language_version);
DisableBrokenExtensions(gl_vendor, gl_renderer);
+3 -3
View File
@@ -192,20 +192,20 @@ namespace StringUtil
std::vector<std::string> splitOnNewLine(const std::string& str);
/// Converts a wxString to a UTF-8 std::string.
static std::string wxStringToUTF8String(const wxString& str)
static inline std::string wxStringToUTF8String(const wxString& str)
{
const wxScopedCharBuffer buf(str.ToUTF8());
return std::string(buf.data(), buf.length());
}
/// Converts a UTF-8 std::string to a wxString.
static wxString UTF8StringToWxString(const std::string_view& str)
static inline wxString UTF8StringToWxString(const std::string_view& str)
{
return wxString::FromUTF8(str.data(), str.length());
}
/// Converts a UTF-8 std::string to a wxString.
static wxString UTF8StringToWxString(const std::string& str)
static inline wxString UTF8StringToWxString(const std::string& str)
{
return wxString::FromUTF8(str.data(), str.length());
}
+18 -39
View File
@@ -59,41 +59,6 @@ namespace Vulkan
Context::~Context() = default;
bool Context::CheckValidationLayerAvailablility()
{
u32 extension_count = 0;
VkResult res = vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkEnumerateInstanceExtensionProperties failed: ");
return false;
}
std::vector<VkExtensionProperties> extension_list(extension_count);
res = vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, extension_list.data());
pxAssert(res == VK_SUCCESS);
u32 layer_count = 0;
res = vkEnumerateInstanceLayerProperties(&layer_count, nullptr);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkEnumerateInstanceExtensionProperties failed: ");
return false;
}
std::vector<VkLayerProperties> layer_list(layer_count);
res = vkEnumerateInstanceLayerProperties(&layer_count, layer_list.data());
pxAssert(res == VK_SUCCESS);
// Check for both VK_EXT_debug_utils and VK_LAYER_LUNARG_standard_validation
return (std::find_if(extension_list.begin(), extension_list.end(),
[](const auto& it) { return strcmp(it.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0; }) !=
extension_list.end() &&
std::find_if(layer_list.begin(), layer_list.end(), [](const auto& it) {
return strcmp(it.layerName, "VK_LAYER_KHRONOS_validation") == 0;
}) != layer_list.end());
}
VkInstance Context::CreateVulkanInstance(
const WindowInfo* wi, bool enable_debug_utils, bool enable_validation_layer)
{
@@ -291,7 +256,8 @@ namespace Vulkan
}
bool Context::Create(std::string_view gpu_name, const WindowInfo* wi, std::unique_ptr<SwapChain>* out_swap_chain,
bool threaded_presentation, bool enable_debug_utils, bool enable_validation_layer)
VkPresentModeKHR preferred_present_mode, bool threaded_presentation, bool enable_debug_utils,
bool enable_validation_layer)
{
pxAssertMsg(!g_vulkan_context, "Has no current context");
@@ -305,8 +271,20 @@ namespace Vulkan
VkInstance instance = CreateVulkanInstance(wi, enable_debug_utils, enable_validation_layer);
if (instance == VK_NULL_HANDLE)
{
Vulkan::UnloadVulkanLibrary();
return false;
if (enable_debug_utils || enable_validation_layer)
{
// Try again without the validation layer.
enable_debug_utils = false;
enable_validation_layer = false;
instance = CreateVulkanInstance(wi, enable_debug_utils, enable_validation_layer);
if (instance == VK_NULL_HANDLE)
{
Vulkan::UnloadVulkanLibrary();
return false;
}
Console.Error("Vulkan validation/debug layers requested but are unavailable. Creating non-debug device.");
}
}
if (!Vulkan::LoadVulkanInstanceFunctions(instance))
@@ -370,7 +348,7 @@ namespace Vulkan
if (!g_vulkan_context->CreateDevice(surface, enable_validation_layer, nullptr, 0, nullptr, 0, nullptr) ||
!g_vulkan_context->CreateAllocator() || !g_vulkan_context->CreateGlobalDescriptorPool() ||
!g_vulkan_context->CreateCommandBuffers() || !g_vulkan_context->CreateTextureStreamBuffer() ||
(enable_surface && (*out_swap_chain = SwapChain::Create(wi_copy, surface, true)) == nullptr))
(enable_surface && (*out_swap_chain = SwapChain::Create(wi_copy, surface, preferred_present_mode)) == nullptr))
{
// Since we are destroying the instance, we're also responsible for destroying the surface.
if (surface != VK_NULL_HANDLE)
@@ -485,6 +463,7 @@ namespace Vulkan
m_device_features.largePoints = available_features.largePoints;
m_device_features.wideLines = available_features.wideLines;
m_device_features.fragmentStoresAndAtomics = available_features.fragmentStoresAndAtomics;
m_device_features.textureCompressionBC = available_features.textureCompressionBC;
return true;
}
+2 -4
View File
@@ -55,9 +55,6 @@ namespace Vulkan
~Context();
// Determines if the Vulkan validation layer is available on the system.
static bool CheckValidationLayerAvailablility();
// Helper method to create a Vulkan instance.
static VkInstance CreateVulkanInstance(
const WindowInfo* wi, bool enable_debug_utils, bool enable_validation_layer);
@@ -70,7 +67,8 @@ namespace Vulkan
// Creates a new context and sets it up as global.
static bool Create(std::string_view gpu_name, const WindowInfo* wi, std::unique_ptr<SwapChain>* out_swap_chain,
bool threaded_presentation, bool enable_debug_utils, bool enable_validation_layer);
VkPresentModeKHR preferred_present_mode, bool threaded_presentation, bool enable_debug_utils,
bool enable_validation_layer);
// Destroys context.
static void Destroy();
+2 -4
View File
@@ -107,13 +107,11 @@ namespace Vulkan::ShaderCompiler
glslang::GlslangToSpv(*intermediate, out_code, &logger);
// Write out messages
// Temporary: skip if it contains "Warning, version 450 is not yet complete; most version-specific
// features are present, but some are missing."
if (std::strlen(shader->getInfoLog()) > 108)
if (std::strlen(shader->getInfoLog()) > 0)
Console.Warning("Shader info log: %s", shader->getInfoLog());
if (std::strlen(shader->getInfoDebugLog()) > 0)
Console.Warning("Shader debug info log: %s", shader->getInfoDebugLog());
if (std::strlen(program->getInfoLog()) > 25)
if (std::strlen(program->getInfoLog()) > 0)
Console.Warning("Program info log: %s", program->getInfoLog());
if (std::strlen(program->getInfoDebugLog()) > 0)
Console.Warning("Program debug info log: %s", program->getInfoDebugLog());
+65 -27
View File
@@ -28,9 +28,39 @@
#if defined(__APPLE__)
#include <objc/message.h>
#include <dispatch/dispatch.h>
#ifdef __i386__
typedef float CGFloat;
#else
typedef double CGFloat;
#endif
template <typename Ret, typename Self, typename... Args>
Ret msgsend(Self self, const char* sel, Args... args)
{
void (*fn)(void) = objc_msgSend;
#ifdef __i386__
if (std::is_same<Ret, float>::value || std::is_same<Ret, double>::value || std::is_same<Ret, long double>::value)
fn = objc_msgSend_fpret;
#endif
#ifdef __x86_64__
if (std::is_same<Ret, long double>::value)
fn = objc_msgSend_fpret;
#endif
return reinterpret_cast<Ret(*)(Self, SEL, Args...)>(fn)(self, sel_getUid(sel), args...);
}
static bool CreateMetalLayer(WindowInfo* wi)
{
// if (![NSThread isMainThread])
if (!msgsend<BOOL, Class>(objc_getClass("NSThread"), "isMainThread"))
{
__block bool ret;
dispatch_sync(dispatch_get_main_queue(), ^{ ret = CreateMetalLayer(wi); });
return ret;
}
id view = reinterpret_cast<id>(wi->window_handle);
Class clsCAMetalLayer = objc_getClass("CAMetalLayer");
@@ -41,7 +71,7 @@ static bool CreateMetalLayer(WindowInfo* wi)
}
// [CAMetalLayer layer]
id layer = reinterpret_cast<id (*)(Class, SEL)>(objc_msgSend)(objc_getClass("CAMetalLayer"), sel_getUid("layer"));
id layer = msgsend<id, Class>(clsCAMetalLayer, "layer");
if (!layer)
{
Console.Error("Failed to create Metal layer.");
@@ -49,19 +79,19 @@ static bool CreateMetalLayer(WindowInfo* wi)
}
// [view setWantsLayer:YES]
reinterpret_cast<void (*)(id, SEL, BOOL)>(objc_msgSend)(view, sel_getUid("setWantsLayer:"), YES);
msgsend<void, id, BOOL>(view, "setWantsLayer:", YES);
// [view setLayer:layer]
reinterpret_cast<void (*)(id, SEL, id)>(objc_msgSend)(view, sel_getUid("setLayer:"), layer);
msgsend<void, id, id>(view, "setLayer:", layer);
// NSScreen* screen = [NSScreen mainScreen]
id screen = reinterpret_cast<id (*)(Class, SEL)>(objc_msgSend)(objc_getClass("NSScreen"), sel_getUid("mainScreen"));
id screen = msgsend<id, Class>(objc_getClass("NSScreen"), "mainScreen");
// CGFloat factor = [screen backingScaleFactor]
double factor = reinterpret_cast<double (*)(id, SEL)>(objc_msgSend)(screen, sel_getUid("backingScaleFactor"));
CGFloat factor = msgsend<CGFloat, id>(screen, "backingScaleFactor");
// layer.contentsScale = factor
reinterpret_cast<void (*)(id, SEL, double)>(objc_msgSend)(layer, sel_getUid("setContentsScale:"), factor);
msgsend<void, id, CGFloat>(layer, "setContentsScale:", factor);
// Store the layer pointer, that way MoltenVK doesn't call [NSView layer] outside the main thread.
wi->surface_handle = layer;
@@ -85,10 +115,10 @@ static void DestroyMetalLayer(WindowInfo* wi)
namespace Vulkan
{
SwapChain::SwapChain(const WindowInfo& wi, VkSurfaceKHR surface, bool vsync)
SwapChain::SwapChain(const WindowInfo& wi, VkSurfaceKHR surface, VkPresentModeKHR preferred_present_mode)
: m_window_info(wi)
, m_surface(surface)
, m_vsync_enabled(vsync)
, m_preferred_present_mode(preferred_present_mode)
{
}
@@ -465,9 +495,10 @@ namespace Vulkan
return {};
}
std::unique_ptr<SwapChain> SwapChain::Create(const WindowInfo& wi, VkSurfaceKHR surface, bool vsync)
std::unique_ptr<SwapChain> SwapChain::Create(const WindowInfo& wi, VkSurfaceKHR surface,
VkPresentModeKHR preferred_present_mode)
{
std::unique_ptr<SwapChain> swap_chain = std::make_unique<SwapChain>(wi, surface, vsync);
std::unique_ptr<SwapChain> swap_chain = std::make_unique<SwapChain>(wi, surface, preferred_present_mode);
if (!swap_chain->CreateSwapChain() || !swap_chain->SetupSwapChainImages() || !swap_chain->CreateSemaphores())
return nullptr;
@@ -537,29 +568,33 @@ namespace Vulkan
return it != present_modes.end();
};
// If vsync is enabled, use VK_PRESENT_MODE_FIFO_KHR.
// This check should not fail with conforming drivers, as the FIFO present mode is mandated by
// the specification (VK_KHR_swapchain). In case it isn't though, fall through to any other mode.
if (m_vsync_enabled && CheckForMode(VK_PRESENT_MODE_FIFO_KHR))
// Use preferred mode if available.
if (CheckForMode(m_preferred_present_mode))
{
m_present_mode = VK_PRESENT_MODE_FIFO_KHR;
m_present_mode = m_preferred_present_mode;
return true;
}
// Prefer screen-tearing, if possible, for lowest latency.
if (CheckForMode(VK_PRESENT_MODE_IMMEDIATE_KHR))
{
m_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
return true;
}
// Use optimized-vsync above vsync.
if (CheckForMode(VK_PRESENT_MODE_MAILBOX_KHR))
// Prefer mailbox over fifo for adaptive vsync/no-vsync.
if ((m_preferred_present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR ||
m_preferred_present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR) &&
CheckForMode(VK_PRESENT_MODE_MAILBOX_KHR))
{
m_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
return true;
}
// Fallback to FIFO if we're using any kind of vsync.
if (m_preferred_present_mode == VK_PRESENT_MODE_FIFO_KHR || m_preferred_present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR)
{
// This should never fail, FIFO is mandated.
if (CheckForMode(VK_PRESENT_MODE_FIFO_KHR))
{
m_present_mode = VK_PRESENT_MODE_FIFO_KHR;
return true;
}
}
// Fall back to whatever is available.
m_present_mode = present_modes[0];
return true;
@@ -581,6 +616,9 @@ namespace Vulkan
if (!SelectSurfaceFormat() || !SelectPresentMode())
return false;
DevCon.WriteLn("(SwapChain) Preferred present mode: %s, selected: %s",
Util::PresentModeToString(m_preferred_present_mode), Util::PresentModeToString(m_present_mode));
// Select number of images in swap chain, we prefer one buffer in the background to work on
u32 image_count = std::max(surface_capabilities.minImageCount + 1u, 2u);
@@ -771,13 +809,13 @@ namespace Vulkan
return true;
}
bool SwapChain::SetVSync(bool enabled)
bool SwapChain::SetVSync(VkPresentModeKHR preferred_mode)
{
if (m_vsync_enabled == enabled)
if (m_preferred_present_mode == preferred_mode)
return true;
// Recreate the swap chain with the new present mode.
m_vsync_enabled = enabled;
m_preferred_present_mode = preferred_mode;
return RecreateSwapChain();
}
+12 -5
View File
@@ -27,7 +27,7 @@ namespace Vulkan
class SwapChain
{
public:
SwapChain(const WindowInfo& wi, VkSurfaceKHR surface, bool vsync);
SwapChain(const WindowInfo& wi, VkSurfaceKHR surface, VkPresentModeKHR preferred_present_mode);
~SwapChain();
// Creates a vulkan-renderable surface for the specified window handle.
@@ -47,12 +47,13 @@ namespace Vulkan
VkInstance instance, VkPhysicalDevice physical_device, const WindowInfo& wi);
// Create a new swap chain from a pre-existing surface.
static std::unique_ptr<SwapChain> Create(const WindowInfo& wi, VkSurfaceKHR surface, bool vsync);
static std::unique_ptr<SwapChain> Create(const WindowInfo& wi, VkSurfaceKHR surface,
VkPresentModeKHR preferred_present_mode);
__fi VkSurfaceKHR GetSurface() const { return m_surface; }
__fi VkSurfaceFormatKHR GetSurfaceFormat() const { return m_surface_format; }
__fi VkFormat GetTextureFormat() const { return m_surface_format.format; }
__fi bool IsVSyncEnabled() const { return m_vsync_enabled; }
__fi VkPresentModeKHR GetPreferredPresentMode() const { return m_preferred_present_mode; }
__fi VkSwapchainKHR GetSwapChain() const { return m_swap_chain; }
__fi const WindowInfo& GetWindowInfo() const { return m_window_info; }
__fi u32 GetWidth() const { return m_window_info.surface_width; }
@@ -74,7 +75,13 @@ namespace Vulkan
bool RecreateSwapChain();
// Change vsync enabled state. This may fail as it causes a swapchain recreation.
bool SetVSync(bool enabled);
bool SetVSync(VkPresentModeKHR preferred_mode);
// Returns true if the current present mode is synchronizing (adaptive or hard).
bool IsPresentModeSynchronizing() const
{
return (m_present_mode == VK_PRESENT_MODE_FIFO_KHR || m_present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR);
}
private:
bool SelectSurfaceFormat();
@@ -102,6 +109,7 @@ namespace Vulkan
VkSurfaceKHR m_surface = VK_NULL_HANDLE;
VkSurfaceFormatKHR m_surface_format = {};
VkPresentModeKHR m_preferred_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
VkPresentModeKHR m_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
VkRenderPass m_load_render_pass = VK_NULL_HANDLE;
@@ -113,6 +121,5 @@ namespace Vulkan
VkSwapchainKHR m_swap_chain = VK_NULL_HANDLE;
std::vector<SwapChainImage> m_images;
u32 m_current_image = 0;
bool m_vsync_enabled = false;
};
} // namespace Vulkan
+27
View File
@@ -352,6 +352,33 @@ namespace Vulkan
}
}
const char* PresentModeToString(VkPresentModeKHR mode)
{
switch (mode)
{
case VK_PRESENT_MODE_IMMEDIATE_KHR:
return "VK_PRESENT_MODE_IMMEDIATE_KHR";
case VK_PRESENT_MODE_MAILBOX_KHR:
return "VK_PRESENT_MODE_MAILBOX_KHR";
case VK_PRESENT_MODE_FIFO_KHR:
return "VK_PRESENT_MODE_FIFO_KHR";
case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
return "VK_PRESENT_MODE_FIFO_RELAXED_KHR";
case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR:
return "VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR";
case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR:
return "VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR";
default:
return "UNKNOWN_VK_PRESENT_MODE";
}
}
void LogVulkanResult(const char* func_name, VkResult res, const char* msg, ...)
{
std::va_list ap;
+1
View File
@@ -53,6 +53,7 @@ namespace Vulkan
void AddPointerToChain(void* head, const void* ptr);
const char* VkResultToString(VkResult res);
const char* PresentModeToString(VkPresentModeKHR mode);
void LogVulkanResult(const char* func_name, VkResult res, const char* msg, ...) /*printflike(4, 5)*/;
#define LOG_VULKAN_ERROR(res, ...) ::Vulkan::Util::LogVulkanResult(__func__, res, __VA_ARGS__)
+9
View File
@@ -39,6 +39,9 @@ target_sources(pcsx2-qt PRIVATE
Settings/AdvancedSystemSettingsWidget.cpp
Settings/AdvancedSystemSettingsWidget.h
Settings/AdvancedSystemSettingsWidget.ui
Settings/AudioSettingsWidget.cpp
Settings/AudioSettingsWidget.h
Settings/AudioSettingsWidget.ui
Settings/BIOSSettingsWidget.cpp
Settings/BIOSSettingsWidget.h
Settings/BIOSSettingsWidget.ui
@@ -61,6 +64,9 @@ target_sources(pcsx2-qt PRIVATE
Settings/GameListSettingsWidget.cpp
Settings/GameListSettingsWidget.h
Settings/GameListSettingsWidget.ui
Settings/GameSummaryWidget.cpp
Settings/GameSummaryWidget.h
Settings/GameSummaryWidget.ui
Settings/GraphicsSettingsWidget.cpp
Settings/GraphicsSettingsWidget.h
Settings/GraphicsSettingsWidget.ui
@@ -74,6 +80,9 @@ target_sources(pcsx2-qt PRIVATE
Settings/InterfaceSettingsWidget.cpp
Settings/InterfaceSettingsWidget.h
Settings/InterfaceSettingsWidget.ui
Settings/MemoryCardSettingsWidget.cpp
Settings/MemoryCardSettingsWidget.h
Settings/MemoryCardSettingsWidget.ui
Settings/SettingsDialog.cpp
Settings/SettingsDialog.h
Settings/SettingsDialog.ui
+1 -6
View File
@@ -49,12 +49,7 @@ DisplayWidget::~DisplayWidget() = default;
qreal DisplayWidget::devicePixelRatioFromScreen() const
{
QScreen* screen_for_ratio;
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
screen_for_ratio = windowHandle()->screen();
#else
screen_for_ratio = screen();
#endif
const QScreen* screen_for_ratio = screen();
if (!screen_for_ratio)
screen_for_ratio = QGuiApplication::primaryScreen();
+34 -6
View File
@@ -16,6 +16,7 @@
#include "PrecompiledHeader.h"
#include <QtWidgets/QApplication>
#include <QtWidgets/QMessageBox>
#include "common/Assertions.h"
#include "common/Console.h"
@@ -137,12 +138,16 @@ void EmuThread::setVMPaused(bool paused)
VMManager::SetPaused(paused);
}
void EmuThread::shutdownVM(bool allow_save_to_state /* = true */, bool blocking /* = false */)
bool EmuThread::shutdownVM(bool allow_confirm /* = true */, bool allow_save_to_state /* = true */, bool blocking /* = false */)
{
if (!isOnEmuThread())
{
QMetaObject::invokeMethod(this, "shutdownVM", Qt::QueuedConnection, Q_ARG(bool, allow_save_to_state),
Q_ARG(bool, blocking));
// only confirm on UI thread because we need to display a msgbox
if (allow_confirm && g_main_window && !g_main_window->confirmShutdown())
return false;
QMetaObject::invokeMethod(this, "shutdownVM", Qt::QueuedConnection, Q_ARG(bool, false),
Q_ARG(bool, allow_save_to_state), Q_ARG(bool, blocking));
if (blocking)
{
@@ -151,16 +156,17 @@ void EmuThread::shutdownVM(bool allow_save_to_state /* = true */, bool blocking
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
}
return;
return true;
}
const VMState state = VMManager::GetState();
if (state == VMState::Paused)
m_event_loop->quit();
else if (state != VMState::Running)
return;
return true;
VMManager::SetState(VMState::Stopping);
return true;
}
void EmuThread::loadState(const QString& filename)
@@ -285,6 +291,9 @@ void EmuThread::executeVM()
destroyVM();
m_event_loop->processEvents(QEventLoop::AllEvents);
return;
default:
continue;
}
}
}
@@ -365,6 +374,22 @@ void EmuThread::applySettings()
VMManager::ApplySettings();
}
void EmuThread::reloadGameSettings()
{
if (!isOnEmuThread())
{
QMetaObject::invokeMethod(this, &EmuThread::reloadGameSettings, Qt::QueuedConnection);
return;
}
// this will skip applying settings when they're not active
if (VMManager::ReloadGameSettings())
{
// none of these settings below are per-game.. for now. but in case they are in the future.
checkForSettingChanges();
}
}
void EmuThread::checkForSettingChanges()
{
if (VMManager::HasValidVM())
@@ -607,6 +632,9 @@ HostDisplay* EmuThread::acquireHostDisplay(HostDisplay::RenderAPI api)
g_gs_window_info = s_host_display->GetWindowInfo();
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", HostDisplay::RenderAPIToString(s_host_display->GetRenderAPI()));
Console.Indent().WriteLn(s_host_display->GetDriverInfo());
return s_host_display.get();
}
@@ -738,7 +766,7 @@ ScopedVMPause::ScopedVMPause(bool was_paused)
ScopedVMPause::~ScopedVMPause()
{
if (m_was_paused)
if (!m_was_paused)
g_emu_thread->setVMPaused(false);
}
+2 -1
View File
@@ -57,7 +57,7 @@ public Q_SLOTS:
void startVM(std::shared_ptr<VMBootParameters> boot_params);
void resetVM();
void setVMPaused(bool paused);
void shutdownVM(bool allow_save_to_state = true, bool blocking = false);
bool shutdownVM(bool allow_confirm = true, bool allow_save_to_state = true, bool blocking = false);
void loadState(const QString& filename);
void loadStateFromSlot(qint32 slot);
void saveState(const QString& filename);
@@ -65,6 +65,7 @@ public Q_SLOTS:
void toggleFullscreen();
void setFullscreen(bool fullscreen);
void applySettings();
void reloadGameSettings();
void toggleSoftwareRendering();
void switchRenderer(GSRendererType renderer);
void changeDisc(const QString& path);
+2 -2
View File
@@ -324,9 +324,9 @@ void GameListWidget::resizeTableViewColumnsToFit()
80, // code
-1, // title
-1, // file title
50, // crc
60, // crc
80, // size
50, // region
60, // region
100 // compatibility
});
}
+1 -5
View File
@@ -17,6 +17,7 @@
#include <QtWidgets/QApplication>
#include <cstdlib>
#include <csignal>
#include "MainWindow.h"
#include "EmuThread.h"
@@ -184,13 +185,9 @@ static bool ParseCommandLineOptions(int argc, char* argv[], std::shared_ptr<VMBo
int main(int argc, char* argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
#endif
QApplication app(argc, argv);
std::shared_ptr<VMBootParameters> autoboot;
@@ -216,7 +213,6 @@ int main(int argc, char* argv[])
const int result = app.exec();
EmuThread::stop();
QtHost::Shutdown();
return result;
}
+266 -125
View File
@@ -16,6 +16,7 @@
#include "PrecompiledHeader.h"
#include <QtCore/QDateTime>
#include <QtGui/QCloseEvent>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QProgressBar>
@@ -39,12 +40,13 @@
#include "Settings/ControllerSettingsDialog.h"
#include "Settings/GameListSettingsWidget.h"
#include "Settings/InterfaceSettingsWidget.h"
#include "SettingWidgetBinder.h"
#include "svnrev.h"
static constexpr char DISC_IMAGE_FILTER[] = QT_TRANSLATE_NOOP(
"MainWindow", "All File Types (*.bin *.iso *.cue *.chd *.cso *.elf *.irx *.m3u);;Single-Track Raw Images (*.bin "
"*.iso);;Cue Sheets (*.cue);;MAME CHD Images (*.chd);;CSO Images (*.cso);;"
"ELF Executables (*.elf);;IRX Executables (*.irx);;Playlists (*.m3u)");
static constexpr char DISC_IMAGE_FILTER[] =
QT_TRANSLATE_NOOP("MainWindow", "All File Types (*.bin *.iso *.cue *.chd *.cso *.elf *.irx *.m3u);;Single-Track Raw Images (*.bin "
"*.iso);;Cue Sheets (*.cue);;MAME CHD Images (*.chd);;CSO Images (*.cso);;"
"ELF Executables (*.elf);;IRX Executables (*.irx);;Playlists (*.m3u)");
const char* MainWindow::DEFAULT_THEME_NAME = "darkfusion";
@@ -106,8 +108,7 @@ void MainWindow::setupAdditionalUi()
for (u32 scale = 0; scale <= 10; scale++)
{
QAction* action =
m_ui.menuWindowSize->addAction((scale == 0) ? tr("Internal Resolution") : tr("%1x Scale").arg(scale));
QAction* action = m_ui.menuWindowSize->addAction((scale == 0) ? tr("Internal Resolution") : tr("%1x Scale").arg(scale));
connect(action, &QAction::triggered, [scale]() { g_emu_thread->requestDisplaySize(static_cast<float>(scale)); });
}
@@ -120,10 +121,8 @@ void MainWindow::connectSignals()
connect(m_ui.actionStartBios, &QAction::triggered, this, &MainWindow::onStartBIOSActionTriggered);
connect(m_ui.actionChangeDisc, &QAction::triggered, [this] { m_ui.menuChangeDisc->exec(QCursor::pos()); });
connect(m_ui.actionChangeDiscFromFile, &QAction::triggered, this, &MainWindow::onChangeDiscFromFileActionTriggered);
connect(m_ui.actionChangeDiscFromDevice, &QAction::triggered, this,
&MainWindow::onChangeDiscFromDeviceActionTriggered);
connect(m_ui.actionChangeDiscFromGameList, &QAction::triggered, this,
&MainWindow::onChangeDiscFromGameListActionTriggered);
connect(m_ui.actionChangeDiscFromDevice, &QAction::triggered, this, &MainWindow::onChangeDiscFromDeviceActionTriggered);
connect(m_ui.actionChangeDiscFromGameList, &QAction::triggered, this, &MainWindow::onChangeDiscFromGameListActionTriggered);
connect(m_ui.menuChangeDisc, &QMenu::aboutToShow, this, &MainWindow::onChangeDiscMenuAboutToShow);
connect(m_ui.menuChangeDisc, &QMenu::aboutToHide, this, &MainWindow::onChangeDiscMenuAboutToHide);
connect(m_ui.actionPowerOff, &QAction::triggered, []() { g_emu_thread->shutdownVM(); });
@@ -132,29 +131,20 @@ void MainWindow::connectSignals()
connect(m_ui.actionExit, &QAction::triggered, this, &MainWindow::close);
connect(m_ui.menuLoadState, &QMenu::aboutToShow, this, &MainWindow::onLoadStateMenuAboutToShow);
connect(m_ui.menuSaveState, &QMenu::aboutToShow, this, &MainWindow::onSaveStateMenuAboutToShow);
connect(m_ui.actionSettings, &QAction::triggered, [this]() { doSettings(SettingsDialog::Category::Count); });
connect(m_ui.actionInterfaceSettings, &QAction::triggered,
[this]() { doSettings(SettingsDialog::Category::InterfaceSettings); });
connect(m_ui.actionGameListSettings, &QAction::triggered,
[this]() { doSettings(SettingsDialog::Category::GameListSettings); });
connect(m_ui.actionEmulationSettings, &QAction::triggered,
[this]() { doSettings(SettingsDialog::Category::EmulationSettings); });
connect(m_ui.actionBIOSSettings, &QAction::triggered,
[this]() { doSettings(SettingsDialog::Category::BIOSSettings); });
connect(m_ui.actionSystemSettings, &QAction::triggered,
[this]() { doSettings(SettingsDialog::Category::SystemSettings); });
connect(m_ui.actionGraphicsSettings, &QAction::triggered,
[this]() { doSettings(SettingsDialog::Category::GraphicsSettings); });
connect(m_ui.actionAudioSettings, &QAction::triggered,
[this]() { doSettings(SettingsDialog::Category::AudioSettings); });
connect(m_ui.actionMemoryCardSettings, &QAction::triggered,
[this]() { doSettings(SettingsDialog::Category::MemoryCardSettings); });
connect(m_ui.actionControllerSettings, &QAction::triggered,
[this]() { doControllerSettings(ControllerSettingsDialog::Category::GlobalSettings); });
connect(m_ui.actionHotkeySettings, &QAction::triggered,
[this]() { doControllerSettings(ControllerSettingsDialog::Category::HotkeySettings); });
connect(m_ui.actionAddGameDirectory, &QAction::triggered,
[this]() { getSettingsDialog()->getGameListSettingsWidget()->addSearchDirectory(this); });
connect(m_ui.actionSettings, &QAction::triggered, [this]() { doSettings(); });
connect(m_ui.actionInterfaceSettings, &QAction::triggered, [this]() { doSettings("Interface"); });
connect(m_ui.actionGameListSettings, &QAction::triggered, [this]() { doSettings("Game List"); });
connect(m_ui.actionEmulationSettings, &QAction::triggered, [this]() { doSettings("Emulation"); });
connect(m_ui.actionBIOSSettings, &QAction::triggered, [this]() { doSettings("BIOS"); });
connect(m_ui.actionSystemSettings, &QAction::triggered, [this]() { doSettings("System"); });
connect(m_ui.actionGraphicsSettings, &QAction::triggered, [this]() { doSettings("Graphics"); });
connect(m_ui.actionAudioSettings, &QAction::triggered, [this]() { doSettings("Audio"); });
connect(m_ui.actionMemoryCardSettings, &QAction::triggered, [this]() { doSettings("Memory Card"); });
connect(
m_ui.actionControllerSettings, &QAction::triggered, [this]() { doControllerSettings(ControllerSettingsDialog::Category::GlobalSettings); });
connect(m_ui.actionHotkeySettings, &QAction::triggered, [this]() { doControllerSettings(ControllerSettingsDialog::Category::HotkeySettings); });
connect(
m_ui.actionAddGameDirectory, &QAction::triggered, [this]() { getSettingsDialog()->getGameListSettingsWidget()->addSearchDirectory(this); });
connect(m_ui.actionScanForNewGames, &QAction::triggered, [this]() { refreshGameList(false); });
connect(m_ui.actionRescanAllGames, &QAction::triggered, [this]() { refreshGameList(true); });
connect(m_ui.actionViewToolbar, &QAction::toggled, this, &MainWindow::onViewToolbarActionToggled);
@@ -180,26 +170,37 @@ void MainWindow::connectSignals()
if (isShowingGameList())
m_game_list_widget->gridZoomOut();
});
connect(m_ui.actionGridViewRefreshCovers, &QAction::triggered, m_game_list_widget,
&GameListWidget::refreshGridCovers);
connect(m_ui.actionGridViewRefreshCovers, &QAction::triggered, m_game_list_widget, &GameListWidget::refreshGridCovers);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableSystemConsole, "Logging", "EnableSystemConsole", false);
connect(m_ui.actionEnableSystemConsole, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
#ifndef PCSX2_DEVBUILD
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableVerboseLogging, "Logging", "EnableVerbose", false);
connect(m_ui.actionEnableVerboseLogging, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
#else
// Dev builds always have verbose logging.
m_ui.actionEnableVerboseLogging->setChecked(true);
m_ui.actionEnableVerboseLogging->setEnabled(false);
#endif
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableEEConsoleLogging, "Logging", "EnableEEConsole", false);
connect(m_ui.actionEnableEEConsoleLogging, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionEnableIOPConsoleLogging, "Logging", "EnableIOPConsole", false);
connect(m_ui.actionEnableIOPConsoleLogging, &QAction::triggered, this, &MainWindow::onLoggingOptionChanged);
// These need to be queued connections to stop crashing due to menus opening/closing and switching focus.
connect(m_game_list_widget, &GameListWidget::refreshProgress, this, &MainWindow::onGameListRefreshProgress);
connect(m_game_list_widget, &GameListWidget::refreshComplete, this, &MainWindow::onGameListRefreshComplete);
connect(m_game_list_widget, &GameListWidget::selectionChanged, this, &MainWindow::onGameListSelectionChanged,
Qt::QueuedConnection);
connect(m_game_list_widget, &GameListWidget::entryActivated, this, &MainWindow::onGameListEntryActivated,
Qt::QueuedConnection);
connect(m_game_list_widget, &GameListWidget::entryContextMenuRequested, this,
&MainWindow::onGameListEntryContextMenuRequested, Qt::QueuedConnection);
connect(m_game_list_widget, &GameListWidget::selectionChanged, this, &MainWindow::onGameListSelectionChanged, Qt::QueuedConnection);
connect(m_game_list_widget, &GameListWidget::entryActivated, this, &MainWindow::onGameListEntryActivated, Qt::QueuedConnection);
connect(
m_game_list_widget, &GameListWidget::entryContextMenuRequested, this, &MainWindow::onGameListEntryContextMenuRequested, Qt::QueuedConnection);
}
void MainWindow::connectVMThreadSignals(EmuThread* thread)
{
connect(thread, &EmuThread::onCreateDisplayRequested, this, &MainWindow::createDisplay, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onUpdateDisplayRequested, this, &MainWindow::updateDisplay, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onDestroyDisplayRequested, this, &MainWindow::destroyDisplay,
Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onDestroyDisplayRequested, this, &MainWindow::destroyDisplay, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onResizeDisplayRequested, this, &MainWindow::displayResizeRequested);
connect(thread, &EmuThread::onVMStarting, this, &MainWindow::onVMStarting);
connect(thread, &EmuThread::onVMStarted, this, &MainWindow::onVMStarted);
@@ -221,16 +222,15 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
GSRendererType::OGL, GSRendererType::VK, GSRendererType::SW, GSRendererType::Null};
for (GSRendererType renderer : renderers)
{
connect(
m_ui.menuDebugSwitchRenderer->addAction(QString::fromUtf8(Pcsx2Config::GSOptions::GetRendererName(renderer))),
&QAction::triggered, [renderer] { g_emu_thread->switchRenderer(renderer); });
connect(m_ui.menuDebugSwitchRenderer->addAction(QString::fromUtf8(Pcsx2Config::GSOptions::GetRendererName(renderer))), &QAction::triggered,
[renderer] { g_emu_thread->switchRenderer(renderer); });
}
}
void MainWindow::recreate()
{
if (m_vm_valid)
g_emu_thread->shutdownVM(true, true);
g_emu_thread->shutdownVM(false, true, true);
close();
g_main_window = nullptr;
@@ -252,6 +252,113 @@ void MainWindow::setStyleFromSettings()
qApp->setStyleSheet(QString());
qApp->setStyle(QStyleFactory::create("Fusion"));
}
else if (theme == "UntouchedLagoon")
{
// Custom pallete by RedDevilus, Tame (Light/Washed out) Green as main color and Grayish Blue as complimentary.
// Alternative white theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor black(25, 25, 25);
const QColor teal(0, 128, 128);
const QColor tameTeal(160, 190, 185);
const QColor grayBlue(160, 180, 190);
QPalette standardPalette;
standardPalette.setColor(QPalette::Window, tameTeal);
standardPalette.setColor(QPalette::WindowText, black);
standardPalette.setColor(QPalette::Base, grayBlue);
standardPalette.setColor(QPalette::AlternateBase, tameTeal);
standardPalette.setColor(QPalette::ToolTipBase, tameTeal);
standardPalette.setColor(QPalette::ToolTipText, grayBlue);
standardPalette.setColor(QPalette::Text, black);
standardPalette.setColor(QPalette::Button, tameTeal);
standardPalette.setColor(QPalette::ButtonText, Qt::white);
standardPalette.setColor(QPalette::Link, tameTeal);
standardPalette.setColor(QPalette::Highlight, teal);
standardPalette.setColor(QPalette::HighlightedText, Qt::white);
standardPalette.setColor(QPalette::Active, QPalette::Button, tameTeal.darker());
standardPalette.setColor(QPalette::Disabled, QPalette::ButtonText, Qt::white);
standardPalette.setColor(QPalette::Disabled, QPalette::WindowText, Qt::white);
standardPalette.setColor(QPalette::Disabled, QPalette::Text, Qt::white);
standardPalette.setColor(QPalette::Disabled, QPalette::Light, tameTeal);
qApp->setPalette(standardPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "BabyPastel")
{
// Custom pallete by RedDevilus, Blue as main color and blue as complimentary.
// Alternative light theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor gray(150, 150, 150);
const QColor black(25, 25, 25);
const QColor pink(255, 174, 201);
const QColor brightPink(255, 230, 255);
const QColor congoPink(255, 127, 121);
const QColor blue(221, 225, 239);
QPalette standardPalette;
standardPalette.setColor(QPalette::Window, pink);
standardPalette.setColor(QPalette::WindowText, black);
standardPalette.setColor(QPalette::Base, brightPink);
standardPalette.setColor(QPalette::AlternateBase, blue);
standardPalette.setColor(QPalette::ToolTipBase, pink);
standardPalette.setColor(QPalette::ToolTipText, brightPink);
standardPalette.setColor(QPalette::Text, black);
standardPalette.setColor(QPalette::Button, pink);
standardPalette.setColor(QPalette::ButtonText, black);
standardPalette.setColor(QPalette::Link, congoPink);
standardPalette.setColor(QPalette::Highlight, congoPink);
standardPalette.setColor(QPalette::HighlightedText, black);
standardPalette.setColor(QPalette::Active, QPalette::Button, pink);
standardPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
standardPalette.setColor(QPalette::Disabled, QPalette::WindowText, congoPink);
standardPalette.setColor(QPalette::Disabled, QPalette::Text, blue);
standardPalette.setColor(QPalette::Disabled, QPalette::Light, gray);
qApp->setPalette(standardPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "PCSX2Blue")
{
// Custom pallete by RedDevilus, White as main color and Blue as complimentary.
// Alternative light theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor black(25, 25, 25);
const QColor darkBlue(73, 97, 177);
const QColor blue(106, 156, 255);
const QColor lightBlue(130, 155, 241);
QPalette standardPalette;
standardPalette.setColor(QPalette::Window, lightBlue);
standardPalette.setColor(QPalette::WindowText, black);
standardPalette.setColor(QPalette::Base, darkBlue);
standardPalette.setColor(QPalette::AlternateBase, lightBlue);
standardPalette.setColor(QPalette::ToolTipBase, lightBlue);
standardPalette.setColor(QPalette::ToolTipText, Qt::white);
standardPalette.setColor(QPalette::Text, Qt::white);
standardPalette.setColor(QPalette::Button, blue);
standardPalette.setColor(QPalette::ButtonText, Qt::white);
standardPalette.setColor(QPalette::Link, blue);
standardPalette.setColor(QPalette::Highlight, Qt::white);
standardPalette.setColor(QPalette::HighlightedText, black);
standardPalette.setColor(QPalette::Active, QPalette::Button, blue.darker());
standardPalette.setColor(QPalette::Disabled, QPalette::ButtonText, darkBlue);
standardPalette.setColor(QPalette::Disabled, QPalette::WindowText, darkBlue);
standardPalette.setColor(QPalette::Disabled, QPalette::Text, black);
standardPalette.setColor(QPalette::Disabled, QPalette::Light, darkBlue);
qApp->setPalette(standardPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "darkfusion")
{
// adapted from https://gist.github.com/QuantumCD/6245215
@@ -292,7 +399,6 @@ void MainWindow::setStyleFromSettings()
// adapted from https://gist.github.com/QuantumCD/6245215
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor lighterGray(75, 75, 75);
const QColor darkGray(53, 53, 53);
const QColor gray(128, 128, 128);
const QColor black(25, 25, 25);
@@ -323,6 +429,40 @@ void MainWindow::setStyleFromSettings()
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "ScarletDevilRed")
{
// Custom pallete by RedDevilus, Red as main color and Purple as complimentary.
// Alternative dark theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor darkRed(80, 45, 69);
const QColor purplishRed(120, 45, 69);
const QColor brightRed(200, 45, 69);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, darkRed);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, purplishRed);
darkPalette.setColor(QPalette::AlternateBase, darkRed);
darkPalette.setColor(QPalette::ToolTipBase, darkRed);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, darkRed);
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, darkRed);
darkPalette.setColor(QPalette::Highlight, brightRed);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, purplishRed.darker());
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, brightRed);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, brightRed);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, brightRed);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, darkRed);
qApp->setPalette(darkPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else
{
qApp->setPalette(QApplication::style()->standardPalette());
@@ -336,7 +476,7 @@ void MainWindow::setIconThemeFromSettings()
const std::string theme(QtHost::GetBaseStringSettingValue("UI", "Theme", DEFAULT_THEME_NAME));
QString icon_theme;
if (theme == "darkfusion" || theme == "darkfusionblue")
if (theme == "darkfusion" || theme == "darkfusionblue" || theme == "dualtoneOrangeBlue" || theme == "ScarletDevilRed")
icon_theme = QStringLiteral("white");
else
icon_theme = QStringLiteral("black");
@@ -462,10 +602,7 @@ void MainWindow::clearProgressBar()
m_ui.statusBar->removeWidget(m_status_progress_widget);
}
bool MainWindow::isShowingGameList() const
{
return m_ui.mainContainer->currentIndex() == 0;
}
bool MainWindow::isShowingGameList() const { return m_ui.mainContainer->currentIndex() == 0; }
void MainWindow::switchToGameListView()
{
@@ -498,25 +635,32 @@ void MainWindow::switchToEmulationView()
m_display_widget->setFocus();
}
void MainWindow::refreshGameList(bool invalidate_cache)
void MainWindow::refreshGameList(bool invalidate_cache) { m_game_list_widget->refresh(invalidate_cache); }
void MainWindow::invalidateSaveStateCache() { m_save_states_invalidated = true; }
void MainWindow::reportError(const QString& title, const QString& message) { QMessageBox::critical(this, title, message); }
bool MainWindow::confirmShutdown()
{
m_game_list_widget->refresh(invalidate_cache);
if (!m_vm_valid || !QtHost::GetBaseBoolSettingValue("UI", "ConfirmShutdown", true))
return true;
ScopedVMPause pauser(m_vm_paused);
return (QMessageBox::question(g_main_window, tr("Confirm Shutdown"),
tr("Are you sure you want to shut down the virtual machine?\n\nAll unsaved progress will be lost.")) == QMessageBox::Yes);
}
void MainWindow::invalidateSaveStateCache()
void MainWindow::requestExit()
{
m_save_states_invalidated = true;
if (!g_emu_thread->shutdownVM(true, true, false))
return;
close();
}
void MainWindow::reportError(const QString& title, const QString& message)
{
QMessageBox::critical(this, title, message);
}
void Host::InvalidateSaveStateCache()
{
QMetaObject::invokeMethod(g_main_window, &MainWindow::invalidateSaveStateCache, Qt::QueuedConnection);
}
void Host::InvalidateSaveStateCache() { QMetaObject::invokeMethod(g_main_window, &MainWindow::invalidateSaveStateCache, Qt::QueuedConnection); }
void MainWindow::onGameListRefreshProgress(const QString& status, int current, int total)
{
@@ -524,10 +668,7 @@ void MainWindow::onGameListRefreshProgress(const QString& status, int current, i
setProgressBar(current, total);
}
void MainWindow::onGameListRefreshComplete()
{
clearProgressBar();
}
void MainWindow::onGameListRefreshComplete() { clearProgressBar(); }
void MainWindow::onGameListSelectionChanged()
{
@@ -555,8 +696,7 @@ void MainWindow::onGameListEntryActivated()
}
// only resume if the option is enabled, and we have one for this game
const bool resume =
(VMManager::ShouldSaveResumeState() && VMManager::HasSaveStateInSlot(entry->serial.c_str(), entry->crc, -1));
const bool resume = (VMManager::ShouldSaveResumeState() && VMManager::HasSaveStateInSlot(entry->serial.c_str(), entry->crc, -1));
startGameListEntry(entry, resume ? std::optional<s32>(-1) : std::optional<s32>(), std::nullopt);
}
@@ -570,7 +710,9 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
if (entry)
{
QAction* action = menu.addAction(tr("Properties..."));
// connect(action, &QAction::triggered, [this, entry]() { GamePropertiesDialog::showForEntry(entry, this); });
action->setEnabled(!entry->serial.empty());
if (action->isEnabled())
connect(action, &QAction::triggered, [entry]() { SettingsDialog::openGamePropertiesDialog(entry, entry->crc); });
action = menu.addAction(tr("Open Containing Directory..."));
connect(action, &QAction::triggered, [this, entry]() {
@@ -608,8 +750,7 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
}
menu.addSeparator();
populateLoadStateMenu(&menu, QString::fromStdString(entry->path), QString::fromStdString(entry->serial),
entry->crc);
populateLoadStateMenu(&menu, QString::fromStdString(entry->path), QString::fromStdString(entry->serial), entry->crc);
}
else
{
@@ -632,8 +773,8 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
void MainWindow::onStartFileActionTriggered()
{
QString filename = QDir::toNativeSeparators(
QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr));
QString filename =
QDir::toNativeSeparators(QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr));
if (filename.isEmpty())
return;
@@ -653,18 +794,14 @@ void MainWindow::onChangeDiscFromFileActionTriggered()
{
ScopedVMPause pauser(m_vm_paused);
QString filename =
QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr);
QString filename = QFileDialog::getOpenFileName(this, tr("Select Disc Image"), QString(), tr(DISC_IMAGE_FILTER), nullptr);
if (filename.isEmpty())
return;
g_emu_thread->changeDisc(filename);
}
void MainWindow::onChangeDiscFromGameListActionTriggered()
{
switchToGameListView();
}
void MainWindow::onChangeDiscFromGameListActionTriggered() { switchToGameListView(); }
void MainWindow::onChangeDiscFromDeviceActionTriggered()
{
@@ -676,9 +813,7 @@ void MainWindow::onChangeDiscMenuAboutToShow()
// TODO: This is where we would populate the playlist if there is one.
}
void MainWindow::onChangeDiscMenuAboutToHide()
{
}
void MainWindow::onChangeDiscMenuAboutToHide() {}
void MainWindow::onLoadStateMenuAboutToShow()
{
@@ -732,22 +867,29 @@ void MainWindow::onViewGamePropertiesActionTriggered()
{
if (!m_vm_valid)
return;
// prefer to use a game list entry, if we have one, that way the summary is populated
if (!m_current_disc_path.isEmpty())
{
auto lock = GameList::GetLock();
const GameList::Entry* entry = GameList::GetEntryForPath(m_current_disc_path.toUtf8().constData());
if (entry)
{
SettingsDialog::openGamePropertiesDialog(entry, entry->crc);
return;
}
}
// open properties for the current running file (isn't in the game list)
if (m_current_game_crc != 0)
SettingsDialog::openGamePropertiesDialog(nullptr, m_current_game_crc);
}
void MainWindow::onGitHubRepositoryActionTriggered()
{
QtUtils::OpenURL(this, AboutDialog::getGitHubRepositoryUrl());
}
void MainWindow::onGitHubRepositoryActionTriggered() { QtUtils::OpenURL(this, AboutDialog::getGitHubRepositoryUrl()); }
void MainWindow::onSupportForumsActionTriggered()
{
QtUtils::OpenURL(this, AboutDialog::getSupportForumsUrl());
}
void MainWindow::onSupportForumsActionTriggered() { QtUtils::OpenURL(this, AboutDialog::getSupportForumsUrl()); }
void MainWindow::onDiscordServerActionTriggered()
{
QtUtils::OpenURL(this, AboutDialog::getDiscordServerUrl());
}
void MainWindow::onDiscordServerActionTriggered() { QtUtils::OpenURL(this, AboutDialog::getDiscordServerUrl()); }
void MainWindow::onAboutActionTriggered()
{
@@ -755,9 +897,7 @@ void MainWindow::onAboutActionTriggered()
about.exec();
}
void MainWindow::onCheckForUpdatesActionTriggered()
{
}
void MainWindow::onCheckForUpdatesActionTriggered() {}
void MainWindow::onToolsOpenDataDirectoryTriggered()
{
@@ -776,7 +916,12 @@ void MainWindow::onThemeChangedFromSettings()
{
// reopen the settings dialog after recreating
onThemeChanged();
g_main_window->doSettings(SettingsDialog::Category::InterfaceSettings);
g_main_window->doSettings();
}
void MainWindow::onLoggingOptionChanged()
{
QtHost::UpdateLogging();
}
void MainWindow::onVMStarting()
@@ -841,7 +986,12 @@ void MainWindow::onGameChanged(const QString& path, const QString& serial, const
void MainWindow::closeEvent(QCloseEvent* event)
{
g_emu_thread->shutdownVM(true, true);
if (!g_emu_thread->shutdownVM(true, true, true))
{
event->ignore();
return;
}
saveStateToConfig();
QMainWindow::closeEvent(event);
}
@@ -905,9 +1055,8 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
return nullptr;
}
if (!host_display->CreateRenderDevice(wi.value(), Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""),
Host::GetBoolSettingValue("EmuCore/GS", "ThreadedPresentation", false),
Host::GetBoolSettingValue("EmuCore/GS", "UseDebugDevice", false)))
if (!host_display->CreateRenderDevice(wi.value(), Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""), EmuConfig.GetEffectiveVsyncMode(),
Host::GetBoolSettingValue("EmuCore/GS", "ThreadedPresentation", false), Host::GetBoolSettingValue("EmuCore/GS", "UseDebugDevice", false)))
{
QMessageBox::critical(this, tr("Error"), tr("Failed to create host display device context."));
destroyDisplayWidget();
@@ -1042,10 +1191,7 @@ void MainWindow::displayResizeRequested(qint32 width, qint32 height)
resize(QSize(std::max<qint32>(width, 1), std::max<qint32>(height + extra_height, 1)));
}
void MainWindow::destroyDisplay()
{
destroyDisplayWidget();
}
void MainWindow::destroyDisplay() { destroyDisplayWidget(); }
void MainWindow::focusDisplayWidget()
{
@@ -1127,14 +1273,14 @@ SettingsDialog* MainWindow::getSettingsDialog()
if (!m_settings_dialog)
{
m_settings_dialog = new SettingsDialog(this);
connect(m_settings_dialog->getInterfaceSettingsWidget(), &InterfaceSettingsWidget::themeChanged, this,
&MainWindow::onThemeChangedFromSettings);
connect(
m_settings_dialog->getInterfaceSettingsWidget(), &InterfaceSettingsWidget::themeChanged, this, &MainWindow::onThemeChangedFromSettings);
}
return m_settings_dialog;
}
void MainWindow::doSettings(SettingsDialog::Category category)
void MainWindow::doSettings(const char* category /* = nullptr */)
{
SettingsDialog* dlg = getSettingsDialog();
if (!dlg->isVisible())
@@ -1143,7 +1289,7 @@ void MainWindow::doSettings(SettingsDialog::Category category)
dlg->show();
}
if (category != SettingsDialog::Category::Count)
if (category)
dlg->setCategory(category);
}
@@ -1168,8 +1314,7 @@ void MainWindow::doControllerSettings(ControllerSettingsDialog::Category categor
dlg->setCategory(category);
}
void MainWindow::startGameListEntry(const GameList::Entry* entry, std::optional<s32> save_slot,
std::optional<bool> fast_boot)
void MainWindow::startGameListEntry(const GameList::Entry* entry, std::optional<s32> save_slot, std::optional<bool> fast_boot)
{
std::shared_ptr<VMBootParameters> params = std::make_shared<VMBootParameters>();
params->fast_boot = fast_boot;
@@ -1193,15 +1338,13 @@ void MainWindow::startGameListEntry(const GameList::Entry* entry, std::optional<
void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
{
const QString filename(QFileDialog::getOpenFileName(this, tr("Select Cover Image"), QString(),
tr("All Cover Image Types (*.jpg *.jpeg *.png)")));
const QString filename(QFileDialog::getOpenFileName(this, tr("Select Cover Image"), QString(), tr("All Cover Image Types (*.jpg *.jpeg *.png)")));
if (filename.isEmpty())
return;
if (!GameList::GetCoverImagePathForEntry(entry).empty())
{
if (QMessageBox::question(this, tr("Cover Already Exists"),
tr("A cover image for this game already exists, do you wish to replace it?"),
if (QMessageBox::question(this, tr("Cover Already Exists"), tr("A cover image for this game already exists, do you wish to replace it?"),
QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)
{
return;
@@ -1276,8 +1419,7 @@ void MainWindow::populateLoadStateMenu(QMenu* menu, const QString& filename, con
QAction* action = menu->addAction(is_right_click_menu ? tr("Load State File...") : tr("Load From File..."));
connect(action, &QAction::triggered, [this, filename]() {
const QString path(
QFileDialog::getOpenFileName(this, tr("Select Save State File"), QString(), tr("Save States (*.p2s)")));
const QString path(QFileDialog::getOpenFileName(this, tr("Select Save State File"), QString(), tr("Save States (*.p2s)")));
if (path.isEmpty())
return;
@@ -1328,8 +1470,7 @@ void MainWindow::populateSaveStateMenu(QMenu* menu, const QString& serial, quint
return;
connect(menu->addAction(tr("Save To File...")), &QAction::triggered, [this]() {
const QString path(
QFileDialog::getSaveFileName(this, tr("Select Save State File"), QString(), tr("Save States (*.p2s)")));
const QString path(QFileDialog::getSaveFileName(this, tr("Select Save State File"), QString(), tr("Save States (*.p2s)")));
if (path.isEmpty())
return;
@@ -1350,7 +1491,7 @@ void MainWindow::populateSaveStateMenu(QMenu* menu, const QString& serial, quint
timestamp = tr("Empty");
QString title(tr("Save Slot %1 (%2)").arg(i).arg(timestamp));
connect(menu->addAction(title), &QAction::triggered, [this, i]() { g_emu_thread->saveStateToSlot(i); });
connect(menu->addAction(title), &QAction::triggered, [i]() { g_emu_thread->saveStateToSlot(i); });
}
}
+5 -2
View File
@@ -54,6 +54,8 @@ public Q_SLOTS:
void refreshGameList(bool invalidate_cache);
void invalidateSaveStateCache();
void reportError(const QString& title, const QString& message);
bool confirmShutdown();
void requestExit();
private Q_SLOTS:
DisplayWidget* createDisplay(bool fullscreen, bool render_to_main);
@@ -92,6 +94,7 @@ private Q_SLOTS:
void onToolsOpenDataDirectoryTriggered();
void onThemeChanged();
void onThemeChangedFromSettings();
void onLoggingOptionChanged();
void onVMStarting();
void onVMStarted();
@@ -104,7 +107,7 @@ private Q_SLOTS:
void recreate();
protected:
void closeEvent(QCloseEvent* event);
void closeEvent(QCloseEvent* event) override;
private:
enum : s32
@@ -136,7 +139,7 @@ private:
void setDisplayFullscreen(const std::string& fullscreen_mode);
SettingsDialog* getSettingsDialog();
void doSettings(SettingsDialog::Category category = SettingsDialog::Category::Count);
void doSettings(const char* category = nullptr);
ControllerSettingsDialog* getControllerSettingsDialog();
void doControllerSettings(ControllerSettingsDialog::Category category = ControllerSettingsDialog::Category::Count);
+174 -106
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>700</height>
<width>950</width>
<height>640</height>
</rect>
</property>
<property name="acceptDrops">
@@ -32,7 +32,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<width>950</width>
<height>22</height>
</rect>
</property>
@@ -45,7 +45,8 @@
<string>Change Disc</string>
</property>
<property name="icon">
<iconset theme="dvd-line"/>
<iconset theme="dvd-line">
<normaloff>.</normaloff>.</iconset>
</property>
<actiongroup name="actionGroupChangeDiscSubImages"/>
<addaction name="actionChangeDiscFromFile"/>
@@ -59,7 +60,8 @@
<string>Cheats</string>
</property>
<property name="icon">
<iconset theme="flask-line"/>
<iconset theme="flask-line">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
<widget class="QMenu" name="menuLoadState">
@@ -67,7 +69,8 @@
<string>Load State</string>
</property>
<property name="icon">
<iconset theme="folder-open-line"/>
<iconset theme="folder-open-line">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
<widget class="QMenu" name="menuSaveState">
@@ -75,7 +78,8 @@
<string>Save State</string>
</property>
<property name="icon">
<iconset theme="save-3-line"/>
<iconset theme="save-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
<addaction name="actionStartFile"/>
@@ -141,6 +145,11 @@
<addaction name="menuDebugSwitchRenderer"/>
<addaction name="separator"/>
<addaction name="actionReloadPatches"/>
<addaction name="separator"/>
<addaction name="actionEnableSystemConsole"/>
<addaction name="actionEnableVerboseLogging"/>
<addaction name="actionEnableEEConsoleLogging"/>
<addaction name="actionEnableIOPConsoleLogging"/>
</widget>
<widget class="QMenu" name="menu_View">
<property name="title">
@@ -151,7 +160,8 @@
<string>&amp;Window Size</string>
</property>
<property name="icon">
<iconset theme="window-2-line"/>
<iconset theme="window-2-line">
<normaloff>.</normaloff>.</iconset>
</property>
</widget>
<addaction name="actionViewToolbar"/>
@@ -185,8 +195,11 @@
<addaction name="menuHelp"/>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="visible">
<bool>true</bool>
</property>
<property name="windowTitle">
<string>toolBar</string>
<string>Toolbar</string>
</property>
<property name="iconSize">
<size>
@@ -203,9 +216,6 @@
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<property name="visible">
<bool>false</bool>
</property>
<addaction name="actionStartFile"/>
<addaction name="actionStartDisc"/>
<addaction name="actionStartBios"/>
@@ -227,143 +237,160 @@
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionStartFile">
<property name="icon">
<iconset theme="file-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Start &amp;File...</string>
</property>
<property name="icon">
<iconset theme="file-line"/>
</property>
</action>
<action name="actionStartDisc">
<property name="icon">
<iconset theme="disc-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Start &amp;Disc...</string>
</property>
<property name="icon">
<iconset theme="disc-line"/>
</property>
</action>
<action name="actionStartBios">
<property name="icon">
<iconset theme="hard-drive-2-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Start &amp;BIOS</string>
</property>
<property name="icon">
<iconset theme="hard-drive-2-line"/>
</property>
</action>
<action name="actionScanForNewGames">
<property name="icon">
<iconset theme="file-search-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Scan For New Games</string>
</property>
<property name="icon">
<iconset theme="file-search-line"/>
</property>
</action>
<action name="actionRescanAllGames">
<property name="icon">
<iconset theme="refresh-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Rescan All Games</string>
</property>
<property name="icon">
<iconset theme="refresh-line"/>
</property>
</action>
<action name="actionPowerOff">
<property name="icon">
<iconset theme="shut-down-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Shut &amp;Down</string>
</property>
<property name="icon">
<iconset theme="shut-down-line"/>
</property>
</action>
<action name="actionReset">
<property name="icon">
<iconset theme="restart-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Reset</string>
</property>
<property name="icon">
<iconset theme="restart-line"/>
</property>
</action>
<action name="actionPause">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset theme="pause-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Pause</string>
</property>
<property name="icon">
<iconset theme="pause-line"/>
</property>
</action>
<action name="actionLoadState">
<property name="icon">
<iconset theme="folder-open-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Load State</string>
</property>
<property name="icon">
<iconset theme="folder-open-line"/>
</property>
</action>
<action name="actionSaveState">
<property name="icon">
<iconset theme="save-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Save State</string>
</property>
<property name="icon">
<iconset theme="save-3-line"/>
</property>
</action>
<action name="actionExit">
<property name="icon">
<iconset theme="door-open-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>E&amp;xit</string>
</property>
<property name="icon">
<iconset theme="door-open-line"/>
</property>
</action>
<action name="actionBIOSSettings">
<property name="icon">
<iconset theme="hard-drive-2-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;BIOS</string>
</property>
<property name="icon">
<iconset theme="hard-drive-2-line"/>
</property>
</action>
<action name="actionSystemSettings">
<property name="icon">
<iconset theme="artboard-2-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>System</string>
</property>
<property name="icon">
<iconset theme="artboard-2-line"/>
</property>
</action>
<action name="actionEmulationSettings">
<property name="icon">
<iconset theme="dashboard-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Emulation</string>
</property>
<property name="icon">
<iconset theme="dashboard-line"/>
</property>
</action>
<action name="actionControllerSettings">
<property name="icon">
<iconset theme="gamepad-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Controllers</string>
</property>
<property name="icon">
<iconset theme="gamepad-line"/>
</property>
</action>
<action name="actionHotkeySettings">
<property name="icon">
<iconset theme="keyboard-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Hotkeys</string>
</property>
<property name="icon">
<iconset theme="keyboard-line"/>
</property>
</action>
<action name="actionGraphicsSettings">
<property name="icon">
<iconset theme="brush-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Graphics</string>
</property>
<property name="icon">
<iconset theme="brush-line"/>
</property>
</action>
<action name="actionPostProcessingSettings">
<property name="text">
@@ -371,12 +398,13 @@
</property>
</action>
<action name="actionFullscreen">
<property name="icon">
<iconset theme="fullscreen-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Fullscreen</string>
</property>
<property name="icon">
<iconset theme="fullscreen-line"/>
</property>
</action>
<action name="actionResolution_Scale">
<property name="text">
@@ -400,7 +428,8 @@
</action>
<action name="actionCheckForUpdates">
<property name="icon">
<iconset theme="download-2-line"/>
<iconset theme="download-2-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Check for &amp;Updates...</string>
@@ -421,60 +450,67 @@
</property>
</action>
<action name="actionChangeDisc">
<property name="icon">
<iconset theme="dvd-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Change Disc...</string>
</property>
<property name="icon">
<iconset theme="dvd-line"/>
</property>
</action>
<action name="actionCheats">
<property name="icon">
<iconset theme="flask-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Cheats...</string>
</property>
<property name="icon">
<iconset theme="flask-line"/>
</property>
</action>
<action name="actionAudioSettings">
<property name="icon">
<iconset theme="volume-up-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Audio</string>
</property>
<property name="icon">
<iconset theme="volume-up-line"/>
</property>
</action>
<action name="actionGameListSettings">
<property name="icon">
<iconset theme="folder-settings-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Game List</string>
</property>
<property name="icon">
<iconset theme="folder-settings-line"/>
</property>
</action>
<action name="actionInterfaceSettings">
<property name="icon">
<iconset theme="settings-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Interface</string>
</property>
<property name="icon">
<iconset theme="settings-3-line"/>
</property>
</action>
<action name="actionAddGameDirectory">
<property name="icon">
<iconset theme="folder-add-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Add Game Directory...</string>
</property>
<property name="icon">
<iconset theme="folder-add-line"/>
</property>
</action>
<action name="actionSettings">
<property name="icon">
<iconset theme="settings-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Settings...</string>
</property>
<property name="icon">
<iconset theme="settings-3-line"/>
</property>
</action>
<action name="actionChangeDiscFromFile">
<property name="text">
@@ -502,20 +538,22 @@
</property>
</action>
<action name="actionScreenshot">
<property name="icon">
<iconset theme="screenshot-2-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Screenshot</string>
</property>
<property name="icon">
<iconset theme="screenshot-2-line"/>
</property>
</action>
<action name="actionMemoryCardSettings">
<property name="icon">
<iconset theme="sd-card-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Memory Cards</string>
</property>
<property name="icon">
<iconset theme="sd-card-line"/>
</property>
</action>
<action name="actionViewToolbar">
<property name="checkable">
@@ -551,42 +589,46 @@
</property>
</action>
<action name="actionViewGameList">
<property name="icon">
<iconset theme="list-check">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Game &amp;List</string>
</property>
<property name="icon">
<iconset theme="list-check"/>
</property>
</action>
<action name="actionViewSystemDisplay">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset theme="tv-2-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>System &amp;Display</string>
</property>
<property name="icon">
<iconset theme="tv-2-line"/>
</property>
</action>
<action name="actionViewGameProperties">
<property name="enabled">
<bool>false</bool>
</property>
<property name="icon">
<iconset theme="file-settings-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Game &amp;Properties</string>
</property>
<property name="icon">
<iconset theme="file-settings-line"/>
</property>
</action>
<action name="actionViewGameGrid">
<property name="icon">
<iconset theme="function-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Game &amp;Grid</string>
</property>
<property name="icon">
<iconset theme="function-line"/>
</property>
</action>
<action name="actionGridViewShowTitles">
<property name="checkable">
@@ -640,6 +682,32 @@
<string>Reload Cheats/Patches</string>
</property>
</action>
<action name="actionEnableSystemConsole">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Enable System Console</string>
</property>
</action>
<action name="actionEnableVerboseLogging">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Enable Verbose Logging</string>
</property>
</action>
<action name="actionEnableEEConsoleLogging">
<property name="text">
<string>Enable EE Console Logging</string>
</property>
</action>
<action name="actionEnableIOPConsoleLogging">
<property name="text">
<string>Enable IOP Console Logging</string>
</property>
</action>
</widget>
<resources>
<include location="resources/resources.qrc"/>
+92 -22
View File
@@ -15,6 +15,15 @@
#include "PrecompiledHeader.h"
#include <csignal>
#include <QtCore/QTimer>
#include <QtWidgets/QMessageBox>
#ifdef _WIN32
#include "common/RedtapeWindows.h"
#endif
#include "common/Assertions.h"
#include "common/Console.h"
#include "common/FileSystem.h"
@@ -26,9 +35,6 @@
#include "pcsx2/HostSettings.h"
#include "pcsx2/PAD/Host/PAD.h"
#include <QtCore/QTimer>
#include <QtWidgets/QMessageBox>
#include "EmuThread.h"
#include "GameList/GameListWidget.h"
#include "MainWindow.h"
@@ -42,11 +48,15 @@ static constexpr u32 SETTINGS_SAVE_DELAY = 1000;
//////////////////////////////////////////////////////////////////////////
// Local function declarations
//////////////////////////////////////////////////////////////////////////
namespace QtHost {
static void InitializeWxRubbish();
static bool InitializeConfig();
static void HookSignals();
static bool SetCriticalFolders();
static void SetDefaultConfig();
static void QueueSettingsSave();
static void SaveSettings();
}
//////////////////////////////////////////////////////////////////////////
// Local variable declarations
@@ -72,12 +82,21 @@ bool QtHost::Initialize()
return false;
}
HookSignals();
return true;
}
void QtHost::Shutdown() {}
void QtHost::Shutdown()
{
EmuThread::stop();
if (g_main_window)
{
g_main_window->close();
delete g_main_window;
}
}
static bool SetCriticalFolders()
bool QtHost::SetCriticalFolders()
{
std::string program_path(FileSystem::GetProgramPath());
EmuFolders::AppRoot = wxDirName(wxFileName(StringUtil::UTF8StringToWxString(program_path)));
@@ -110,7 +129,7 @@ void QtHost::UpdateFolders()
EmuFolders::EnsureFoldersExist();
}
bool InitializeConfig()
bool QtHost::InitializeConfig()
{
if (!SetCriticalFolders())
return false;
@@ -138,7 +157,7 @@ bool InitializeConfig()
return true;
}
void SetDefaultConfig()
void QtHost::SetDefaultConfig()
{
EmuConfig = Pcsx2Config();
EmuFolders::SetDefaults();
@@ -247,7 +266,7 @@ void QtHost::RemoveBaseSettingValue(const char* section, const char* key)
QueueSettingsSave();
}
void SaveSettings()
void QtHost::SaveSettings()
{
pxAssertRel(!g_emu_thread->isOnEmuThread(), "Saving should happen on the UI thread.");
@@ -261,7 +280,7 @@ void SaveSettings()
s_settings_save_timer.release();
}
void QueueSettingsSave()
void QtHost::QueueSettingsSave()
{
if (s_settings_save_timer)
return;
@@ -338,9 +357,38 @@ void PatchesVerboseReset()
// FIXME
}
static void SignalHandler(int signal)
{
// First try the normal (graceful) shutdown/exit.
static bool graceful_shutdown_attempted = false;
if (!graceful_shutdown_attempted && g_main_window)
{
std::fprintf(stderr, "Received CTRL+C, attempting graceful shutdown. Press CTRL+C again to force.\n");
graceful_shutdown_attempted = true;
// This could be a bit risky invoking from a signal handler... hopefully it's okay.
QMetaObject::invokeMethod(g_main_window, &MainWindow::requestExit, Qt::QueuedConnection);
return;
}
std::signal(signal, SIG_DFL);
// MacOS is missing std::quick_exit() despite it being C++11...
#ifndef __APPLE__
std::quick_exit(1);
#else
_Exit(1);
#endif
}
void QtHost::HookSignals()
{
std::signal(SIGINT, SignalHandler);
std::signal(SIGTERM, SignalHandler);
}
// Replacement for Console so we actually get output to our console window on Windows.
#ifdef _WIN32
#include "common/RedtapeWindows.h"
static bool s_debugger_attached = false;
static bool s_console_handle_set = false;
@@ -433,24 +481,32 @@ static const IConsoleWriter ConsoleWriter_WinQt =
ConsoleWinQt_Newline,
ConsoleWinQt_SetTitle,
};
static BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
{
Console.WriteLn("Handler %u", dwCtrlType);
if (dwCtrlType != CTRL_C_EVENT)
return FALSE;
SignalHandler(SIGTERM);
return TRUE;
}
#endif
void QtHost::UpdateLogging()
{
// TODO: Make this an actual option.
bool console_logging_enabled = false;
const bool system_console_enabled = QtHost::GetBaseBoolSettingValue("Logging", "EnableSystemConsole", false);
#if defined(_DEBUG) || defined(PCSX2_DEVBUILD)
console_logging_enabled = true;
#endif
const bool any_logging_sinks = system_console_enabled;
DevConWriterEnabled = any_logging_sinks && QtHost::GetBaseBoolSettingValue("Logging", "EnableVerbose", false);
SysConsole.eeConsole.Enabled = any_logging_sinks && QtHost::GetBaseBoolSettingValue("Logging", "EnableEEConsole", true);
SysConsole.iopConsole.Enabled = any_logging_sinks && QtHost::GetBaseBoolSettingValue("Logging", "EnableIOPConsole", true);
DevConWriterEnabled = console_logging_enabled;
SysConsole.eeConsole.Enabled = console_logging_enabled;
SysConsole.iopConsole.Enabled = console_logging_enabled;
if (console_logging_enabled)
{
#ifdef _WIN32
if (system_console_enabled)
{
s_debugger_attached = IsDebuggerPresent();
if (!s_console_handle_set)
{
@@ -471,17 +527,31 @@ void QtHost::UpdateLogging()
}
if (!s_console_handle && !s_debugger_attached)
{
Console_SetActiveHandler(ConsoleWriter_Null);
SetConsoleCtrlHandler(ConsoleCtrlHandler, FALSE);
}
else
{
Console_SetActiveHandler(ConsoleWriter_WinQt);
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
}
}
else
{
Console_SetActiveHandler(ConsoleWriter_Null);
SetConsoleCtrlHandler(ConsoleCtrlHandler, FALSE);
}
#else
if (system_console_enabled)
{
Console_SetActiveHandler(ConsoleWriter_Stdout);
#endif
}
else
{
Console_SetActiveHandler(ConsoleWriter_Null);
}
#endif
}
#include <wx/module.h>
@@ -491,7 +561,7 @@ extern "C" HINSTANCE wxGetInstance();
extern void wxSetInstance(HINSTANCE hInst);
#endif
void InitializeWxRubbish()
void QtHost::InitializeWxRubbish()
{
wxLog::DoCreateOnDemand();
wxLog::GetActiveTarget();
-4
View File
@@ -20,11 +20,7 @@
#include <QtGui/QDesktopServices>
#include <QtGui/QKeyEvent>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QtGui/QAction>
#else
#include <QtWidgets/QAction>
#endif
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDialog>
+498 -145
View File
@@ -14,16 +14,12 @@
*/
#pragma once
#include <QtCore/QtCore>
#include <optional>
#include <type_traits>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QtCore/QtCore>
#include <QtGui/QAction>
#else
#include <QtWidgets/QAction>
#endif
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDoubleSpinBox>
@@ -33,6 +29,7 @@
#include "EmuThread.h"
#include "QtHost.h"
#include "Settings/SettingsDialog.h"
namespace SettingWidgetBinder
{
@@ -41,15 +38,27 @@ namespace SettingWidgetBinder
{
static bool getBoolValue(const T* widget);
static void setBoolValue(T* widget, bool value);
static void makeNullableBool(T* widget, bool globalValue);
static std::optional<bool> getNullableBoolValue(const T* widget);
static void setNullableBoolValue(T* widget, std::optional<bool> value);
static int getIntValue(const T* widget);
static void setIntValue(T* widget, int value);
static void setIntValue(T* widget, bool nullable, int value);
static void makeNullableInt(T* widget, int globalValue);
static std::optional<int> getNullableIntValue(const T* widget);
static void setNullableIntValue(T* widget, std::optional<int> value);
static int getFloatValue(const T* widget);
static void setFloatValue(T* widget, int value);
static void makeNullableFloat(T* widget, float globalValue);
static std::optional<float> getNullableFloatValue(const T* widget);
static void setNullableFloatValue(T* widget, std::optional<float> value);
static QString getStringValue(const T* widget);
static void setStringValue(T* widget, const QString& value);
static void makeNullableString(T* widget, const QString& globalValue);
static std::optional<QString> getNullableStringValue(const T* widget);
static void setNullableFloatValue(T* widget, std::optional<QString> value);
template <typename F>
static void connectValueChanged(T* widget, F func);
@@ -59,19 +68,28 @@ namespace SettingWidgetBinder
struct SettingAccessor<QLineEdit>
{
static bool getBoolValue(const QLineEdit* widget) { return widget->text().toInt() != 0; }
static void setBoolValue(QLineEdit* widget, bool value)
{
widget->setText(value ? QStringLiteral("1") : QStringLiteral("0"));
}
static void setBoolValue(QLineEdit* widget, bool value) { widget->setText(value ? QStringLiteral("1") : QStringLiteral("0")); }
static void makeNullableBool(QLineEdit* widget, bool globalValue) { widget->setEnabled(false); }
static std::optional<bool> getNullableBoolValue(const QLineEdit* widget) { return getBoolValue(widget); }
static void setNullableBoolValue(QLineEdit* widget, std::optional<bool> value) { setBoolValue(widget, value.value_or(false)); }
static int getIntValue(const QLineEdit* widget) { return widget->text().toInt(); }
static void setIntValue(QLineEdit* widget, int value) { widget->setText(QString::number(value)); }
static void makeNullableInt(QLineEdit* widget, int globalValue) { widget->setEnabled(false); }
static std::optional<int> getNullableIntValue(const QLineEdit* widget) { return getIntValue(widget); }
static void setNullableIntValue(QLineEdit* widget, std::optional<int> value) { setIntValue(widget, value.value_or(0)); }
static float getFloatValue(const QLineEdit* widget) { return widget->text().toFloat(); }
static void setFloatValue(QLineEdit* widget, float value) { widget->setText(QString::number(value)); }
static void makeNullableFloat(QLineEdit* widget, float globalValue) { widget->setEnabled(false); }
static std::optional<float> getNullableFloatValue(const QLineEdit* widget) { return getFloatValue(widget); }
static void setNullableFloatValue(QLineEdit* widget, std::optional<float> value) { setFloatValue(widget, value.value_or(0.0f)); }
static QString getStringValue(const QLineEdit* widget) { return widget->text(); }
static void setStringValue(QLineEdit* widget, const QString& value) { widget->setText(value); }
static void makeNullableString(QLineEdit* widget, const QString& globalValue) { widget->setEnabled(false); }
static std::optional<QString> getNullableStringValue(const QLineEdit* widget) { return getStringValue(widget); }
static void setNullableStringValue(QLineEdit* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
template <typename F>
static void connectValueChanged(QLineEdit* widget, F func)
@@ -83,29 +101,58 @@ namespace SettingWidgetBinder
template <>
struct SettingAccessor<QComboBox>
{
static bool isNullValue(const QComboBox* widget) { return (widget->currentIndex() == 0); }
static bool getBoolValue(const QComboBox* widget) { return widget->currentIndex() > 0; }
static void setBoolValue(QComboBox* widget, bool value) { widget->setCurrentIndex(value ? 1 : 0); }
static void makeNullableBool(QComboBox* widget, bool globalValue)
{
widget->insertItem(0, globalValue ? qApp->translate("SettingsDialog", "Use Global Setting [Enabled]") :
qApp->translate("SettingsDialog", "Use Global Setting [Disabled]"));
}
static int getIntValue(const QComboBox* widget) { return widget->currentIndex(); }
static void setIntValue(QComboBox* widget, int value) { widget->setCurrentIndex(value); }
static void makeNullableInt(QComboBox* widget, int globalValue)
{
widget->insertItem(0, qApp->translate("SettingsDialog", "Use Global Setting [%1]")
.arg((globalValue >= 0 && globalValue < widget->count()) ? widget->itemText(globalValue) : QString()));
}
static std::optional<int> getNullableIntValue(const QComboBox* widget)
{
return isNullValue(widget) ? std::nullopt : std::optional<int>(widget->currentIndex() - 1);
}
static void setNullableIntValue(QComboBox* widget, std::optional<int> value)
{
widget->setCurrentIndex(value.has_value() ? (value.value() + 1) : 0);
}
static float getFloatValue(const QComboBox* widget) { return static_cast<float>(widget->currentIndex()); }
static void setFloatValue(QComboBox* widget, float value) { widget->setCurrentIndex(static_cast<int>(value)); }
static void makeNullableFloat(QComboBox* widget, float globalValue)
{
widget->insertItem(0,
qApp->translate("SettingsDialog", "Use Global Setting [%1]")
.arg((globalValue >= 0.0f && static_cast<int>(globalValue) < widget->count()) ? widget->itemText(static_cast<int>(globalValue)) :
QString()));
}
static std::optional<float> getNullableFloatValue(const QComboBox* widget)
{
return isNullValue(widget) ? std::nullopt : std::optional<float>(static_cast<float>(widget->currentIndex() + 1));
}
static void setNullableFloatValue(QComboBox* widget, std::optional<float> value)
{
widget->setCurrentIndex(value.has_value() ? static_cast<int>(value.value() + 1.0f) : 0);
}
static QString getStringValue(const QComboBox* widget)
{
const QVariant currentData(widget->currentData());
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (currentData.type() == QVariant::String)
return currentData.toString();
#else
if (currentData.metaType().id() == QMetaType::QString)
return currentData.toString();
#endif
return widget->currentText();
}
static void setStringValue(QComboBox* widget, const QString& value)
{
const int index = widget->findData(value);
@@ -117,6 +164,15 @@ namespace SettingWidgetBinder
widget->setCurrentText(value);
}
static void makeNullableString(QComboBox* widget, const QString& globalValue) { makeNullableInt(widget, widget->findData(globalValue)); }
static std::optional<QString> getNullableStringValue(const QComboBox* widget)
{
return isNullValue(widget) ? std::nullopt : std::optional<QString>(getStringValue(widget));
}
static void setNullableStringValue(QComboBox* widget, std::optional<QString> value)
{
isNullValue(widget) ? widget->setCurrentIndex(0) : setStringValue(widget, value.value());
}
template <typename F>
static void connectValueChanged(QComboBox* widget, F func)
@@ -130,18 +186,53 @@ namespace SettingWidgetBinder
{
static bool getBoolValue(const QCheckBox* widget) { return widget->isChecked(); }
static void setBoolValue(QCheckBox* widget, bool value) { widget->setChecked(value); }
static void makeNullableBool(QCheckBox* widget, bool globalValue) { widget->setTristate(true); }
static std::optional<bool> getNullableBoolValue(const QCheckBox* widget)
{
return (widget->checkState() == Qt::PartiallyChecked) ? std::nullopt : std::optional<bool>(widget->isChecked());
}
static void setNullableBoolValue(QCheckBox* widget, std::optional<bool> value)
{
widget->setCheckState(value.has_value() ? (value.value() ? Qt::Checked : Qt::Unchecked) : Qt::PartiallyChecked);
}
static int getIntValue(const QCheckBox* widget) { return widget->isChecked() ? 1 : 0; }
static void setIntValue(QCheckBox* widget, int value) { widget->setChecked(value != 0); }
static void makeNullableInt(QCheckBox* widget, int globalValue) { widget->setTristate(true); }
static std::optional<int> getNullableIntValue(const QCheckBox* widget)
{
return (widget->checkState() == Qt::PartiallyChecked) ? std::nullopt : std::optional<int>(widget->isChecked() ? 1 : 0);
}
static void setNullableIntValue(QCheckBox* widget, std::optional<int> value)
{
widget->setCheckState(value.has_value() ? ((value.value() != 0) ? Qt::Checked : Qt::Unchecked) : Qt::PartiallyChecked);
}
static float getFloatValue(const QCheckBox* widget) { return widget->isChecked() ? 1.0f : 0.0f; }
static void setFloatValue(QCheckBox* widget, float value) { widget->setChecked(value != 0.0f); }
static QString getStringValue(const QCheckBox* widget)
static void makeNullableFloat(QCheckBox* widget, float globalValue) { widget->setTristate(true); }
static std::optional<float> getNullableFloatValue(const QCheckBox* widget)
{
return widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0");
return (widget->checkState() == Qt::PartiallyChecked) ? std::nullopt : std::optional<float>(widget->isChecked() ? 1.0f : 0.0f);
}
static void setNullableFloatValue(QCheckBox* widget, std::optional<float> value)
{
widget->setCheckState(value.has_value() ? ((value.value() != 0.0f) ? Qt::Checked : Qt::Unchecked) : Qt::PartiallyChecked);
}
static QString getStringValue(const QCheckBox* widget) { return widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"); }
static void setStringValue(QCheckBox* widget, const QString& value) { widget->setChecked(value.toInt() != 0); }
static void makeNullableString(QCheckBox* widget, const QString& globalValue) { widget->setTristate(true); }
static std::optional<QString> getNullableStringValue(const QCheckBox* widget)
{
return (widget->checkState() == Qt::PartiallyChecked) ?
std::nullopt :
std::optional<QString>(widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"));
}
static void setNullableStringValue(QCheckBox* widget, std::optional<QString> value)
{
widget->setCheckState(value.has_value() ? ((value->toInt() != 0) ? Qt::Checked : Qt::Unchecked) : Qt::PartiallyChecked);
}
template <typename F>
static void connectValueChanged(QCheckBox* widget, F func)
@@ -155,15 +246,27 @@ namespace SettingWidgetBinder
{
static bool getBoolValue(const QSlider* widget) { return widget->value() > 0; }
static void setBoolValue(QSlider* widget, bool value) { widget->setValue(value ? 1 : 0); }
static void makeNullableBool(QSlider* widget, bool globalSetting) { widget->setEnabled(false); }
static std::optional<bool> getNullableBoolValue(const QSlider* widget) { return getBoolValue(widget); }
static void setNullableBoolValue(QSlider* widget, std::optional<bool> value) { setBoolValue(widget, value.value_or(false)); }
static int getIntValue(const QSlider* widget) { return widget->value(); }
static void setIntValue(QSlider* widget, int value) { widget->setValue(value); }
static void makeNullableInt(QSlider* widget, int globalValue) { widget->setEnabled(false); }
static std::optional<int> getNullableIntValue(const QSlider* widget) { return getIntValue(widget); }
static void setNullableIntValue(QSlider* widget, std::optional<int> value) { setIntValue(widget, value.value_or(0)); }
static float getFloatValue(const QSlider* widget) { return static_cast<float>(widget->value()); }
static void setFloatValue(QSlider* widget, float value) { widget->setValue(static_cast<int>(value)); }
static void makeNullableFloat(QSlider* widget, float globalValue) { widget->setEnabled(false); }
static std::optional<float> getNullableFloatValue(const QSlider* widget) { return getFloatValue(widget); }
static void setNullableFloatValue(QSlider* widget, std::optional<float> value) { setFloatValue(widget, value.value_or(0.0f)); }
static QString getStringValue(const QSlider* widget) { return QString::number(widget->value()); }
static void setStringValue(QSlider* widget, const QString& value) { widget->setValue(value.toInt()); }
static void makeNullableString(QSlider* widget, const QString& globalValue) { widget->setEnabled(false); }
static std::optional<QString> getNullableStringValue(const QSlider* widget) { return getStringValue(widget); }
static void setNullableStringValue(QSlider* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
template <typename F>
static void connectValueChanged(QSlider* widget, F func)
@@ -177,15 +280,27 @@ namespace SettingWidgetBinder
{
static bool getBoolValue(const QSpinBox* widget) { return widget->value() > 0; }
static void setBoolValue(QSpinBox* widget, bool value) { widget->setValue(value ? 1 : 0); }
static void makeNullableBool(QSpinBox* widget, bool globalSetting) { widget->setEnabled(false); }
static std::optional<bool> getNullableBoolValue(const QSpinBox* widget) { return getBoolValue(widget); }
static void setNullableBoolValue(QSpinBox* widget, std::optional<bool> value) { setBoolValue(widget, value.value_or(false)); }
static int getIntValue(const QSpinBox* widget) { return widget->value(); }
static void setIntValue(QSpinBox* widget, int value) { widget->setValue(value); }
static void makeNullableInt(QSpinBox* widget, int globalValue) { widget->setEnabled(false); }
static std::optional<int> getNullableIntValue(const QSpinBox* widget) { return getIntValue(widget); }
static void setNullableIntValue(QSpinBox* widget, std::optional<int> value) { setIntValue(widget, value.value_or(0)); }
static float getFloatValue(const QSpinBox* widget) { return static_cast<float>(widget->value()); }
static void setFloatValue(QSpinBox* widget, float value) { widget->setValue(static_cast<int>(value)); }
static void makeNullableFloat(QSpinBox* widget, float globalValue) { widget->setEnabled(false); }
static std::optional<float> getNullableFloatValue(const QSpinBox* widget) { return getFloatValue(widget); }
static void setNullableFloatValue(QSpinBox* widget, std::optional<float> value) { setFloatValue(widget, value.value_or(0.0f)); }
static QString getStringValue(const QSpinBox* widget) { return QString::number(widget->value()); }
static void setStringValue(QSpinBox* widget, const QString& value) { widget->setValue(value.toInt()); }
static void makeNullableString(QSpinBox* widget, const QString& globalValue) { widget->setEnabled(false); }
static std::optional<QString> getNullableStringValue(const QSpinBox* widget) { return getStringValue(widget); }
static void setNullableStringValue(QSpinBox* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
template <typename F>
static void connectValueChanged(QSpinBox* widget, F func)
@@ -199,15 +314,30 @@ namespace SettingWidgetBinder
{
static bool getBoolValue(const QDoubleSpinBox* widget) { return widget->value() > 0.0; }
static void setBoolValue(QDoubleSpinBox* widget, bool value) { widget->setValue(value ? 1.0 : 0.0); }
static void makeNullableBool(QDoubleSpinBox* widget, bool globalSetting) { widget->setEnabled(false); }
static std::optional<bool> getNullableBoolValue(const QDoubleSpinBox* widget) { return getBoolValue(widget); }
static void setNullableBoolValue(QDoubleSpinBox* widget, std::optional<bool> value) { setBoolValue(widget, value.value_or(false)); }
static int getIntValue(const QDoubleSpinBox* widget) { return static_cast<int>(widget->value()); }
static void setIntValue(QDoubleSpinBox* widget, int value) { widget->setValue(static_cast<double>(value)); }
static void makeNullableInt(QDoubleSpinBox* widget, int globalValue) { widget->setEnabled(false); }
static std::optional<int> getNullableIntValue(const QDoubleSpinBox* widget) { return getIntValue(widget); }
static void setNullableIntValue(QDoubleSpinBox* widget, std::optional<int> value) { setIntValue(widget, value.value_or(0)); }
static float getFloatValue(const QDoubleSpinBox* widget) { return static_cast<float>(widget->value()); }
static void setFloatValue(QDoubleSpinBox* widget, float value) { widget->setValue(static_cast<double>(value)); }
static void makeNullableFloat(QDoubleSpinBox* widget, float globalValue) { widget->setEnabled(false); }
static std::optional<float> getNullableFloatValue(const QDoubleSpinBox* widget) { return getFloatValue(widget); }
static void setNullableFloatValue(QDoubleSpinBox* widget, std::optional<float> value) { setFloatValue(widget, value.value_or(0.0f)); }
static QString getStringValue(const QDoubleSpinBox* widget) { return QString::number(widget->value()); }
static void setStringValue(QDoubleSpinBox* widget, const QString& value) { widget->setValue(value.toDouble()); }
static void makeNullableString(QDoubleSpinBox* widget, const QString& globalValue) { widget->setEnabled(false); }
static std::optional<QString> getNullableStringValue(const QDoubleSpinBox* widget) { return getStringValue(widget); }
static void setNullableStringValue(QDoubleSpinBox* widget, std::optional<QString> value)
{
setStringValue(widget, value.value_or(QString()));
}
template <typename F>
static void connectValueChanged(QDoubleSpinBox* widget, F func)
@@ -221,18 +351,27 @@ namespace SettingWidgetBinder
{
static bool getBoolValue(const QAction* widget) { return widget->isChecked(); }
static void setBoolValue(QAction* widget, bool value) { widget->setChecked(value); }
static void makeNullableBool(QAction* widget, bool globalSetting) { widget->setEnabled(false); }
static std::optional<bool> getNullableBoolValue(const QAction* widget) { return getBoolValue(widget); }
static void setNullableBoolValue(QAction* widget, std::optional<bool> value) { setBoolValue(widget, value.value_or(false)); }
static int getIntValue(const QAction* widget) { return widget->isChecked() ? 1 : 0; }
static void setIntValue(QAction* widget, int value) { widget->setChecked(value != 0); }
static void makeNullableInt(QAction* widget, int globalValue) { widget->setEnabled(false); }
static std::optional<int> getNullableIntValue(const QAction* widget) { return getIntValue(widget); }
static void setNullableIntValue(QAction* widget, std::optional<int> value) { setIntValue(widget, value.value_or(0)); }
static float getFloatValue(const QAction* widget) { return widget->isChecked() ? 1.0f : 0.0f; }
static void setFloatValue(QAction* widget, float value) { widget->setChecked(value != 0.0f); }
static void makeNullableFloat(QAction* widget, float globalValue) { widget->setEnabled(false); }
static std::optional<float> getNullableFloatValue(const QAction* widget) { return getFloatValue(widget); }
static void setNullableFloatValue(QAction* widget, std::optional<float> value) { setFloatValue(widget, value.value_or(0.0f)); }
static QString getStringValue(const QAction* widget)
{
return widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0");
}
static QString getStringValue(const QAction* widget) { return widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"); }
static void setStringValue(QAction* widget, const QString& value) { widget->setChecked(value.toInt() != 0); }
static void makeNullableString(QAction* widget, const QString& globalValue) { widget->setEnabled(false); }
static std::optional<QString> getNullableStringValue(const QAction* widget) { return getStringValue(widget); }
static void setNullableStringValue(QAction* widget, std::optional<QString> value) { setStringValue(widget, value.value_or(QString())); }
template <typename F>
static void connectValueChanged(QAction* widget, F func)
@@ -244,153 +383,334 @@ namespace SettingWidgetBinder
/// Binds a widget's value to a setting, updating it when the value changes.
template <typename WidgetType>
static void BindWidgetToBoolSetting(WidgetType* widget, std::string section, std::string key, bool default_value)
static void BindWidgetToBoolSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, bool default_value)
{
using Accessor = SettingAccessor<WidgetType>;
bool value = QtHost::GetBaseBoolSettingValue(section.c_str(), key.c_str(), default_value);
const bool value = QtHost::GetBaseBoolSettingValue(section.c_str(), key.c_str(), default_value);
Accessor::setBoolValue(widget, value);
if (sif)
{
Accessor::makeNullableBool(widget, value);
Accessor::connectValueChanged(widget, [widget, section, key]() {
const bool new_value = Accessor::getBoolValue(widget);
QtHost::SetBaseBoolSettingValue(section.c_str(), key.c_str(), new_value);
g_emu_thread->applySettings();
});
}
template <typename WidgetType>
static void BindWidgetToIntSetting(WidgetType* widget, std::string section, std::string key, int default_value, int option_offset = 0)
{
using Accessor = SettingAccessor<WidgetType>;
s32 value = QtHost::GetBaseIntSettingValue(section.c_str(), key.c_str(), static_cast<s32>(default_value)) - option_offset;
Accessor::setIntValue(widget, static_cast<int>(value));
Accessor::connectValueChanged(widget, [widget, section, key, option_offset]() {
const int new_value = Accessor::getIntValue(widget);
QtHost::SetBaseIntSettingValue(section.c_str(), key.c_str(), new_value + option_offset);
g_emu_thread->applySettings();
});
}
template <typename WidgetType>
static void BindWidgetToFloatSetting(WidgetType* widget, std::string section, std::string key, float default_value)
{
using Accessor = SettingAccessor<WidgetType>;
float value = QtHost::GetBaseFloatSettingValue(section.c_str(), key.c_str(), default_value);
Accessor::setFloatValue(widget, value);
Accessor::connectValueChanged(widget, [widget, section, key]() {
const float new_value = Accessor::getFloatValue(widget);
QtHost::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
g_emu_thread->applySettings();
});
}
template <typename WidgetType>
static void BindWidgetToNormalizedSetting(WidgetType* widget, std::string section, std::string key, float range,
float default_value)
{
using Accessor = SettingAccessor<WidgetType>;
float value = QtHost::GetBaseFloatSettingValue(section.c_str(), key.c_str(), default_value);
Accessor::setIntValue(widget, static_cast<int>(value * range));
Accessor::connectValueChanged(widget, [widget, section, key, range]() {
const float new_value = (static_cast<float>(Accessor::getIntValue(widget)) / range);
QtHost::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
g_emu_thread->applySettings();
});
}
template <typename WidgetType>
static void BindWidgetToStringSetting(WidgetType* widget, std::string section, std::string key,
std::string default_value = std::string())
{
using Accessor = SettingAccessor<WidgetType>;
std::string value = QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str());
Accessor::setStringValue(widget, QString::fromStdString(value));
Accessor::connectValueChanged(widget, [widget, section, key]() {
const QString new_value = Accessor::getStringValue(widget);
if (!new_value.isEmpty())
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.toUtf8().constData());
bool sif_value;
if (sif->GetBoolValue(section.c_str(), key.c_str(), &sif_value))
Accessor::setNullableBoolValue(widget, sif_value);
else
QtHost::RemoveBaseSettingValue(section.c_str(), key.c_str());
Accessor::setNullableBoolValue(widget, std::nullopt);
g_emu_thread->applySettings();
});
}
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key)]() {
if (std::optional<bool> new_value = Accessor::getNullableBoolValue(widget); new_value.has_value())
sif->SetBoolValue(section.c_str(), key.c_str(), new_value.value());
else
sif->DeleteValue(section.c_str(), key.c_str());
template <typename WidgetType, typename DataType>
static void BindWidgetToEnumSetting(WidgetType* widget, std::string section, std::string key,
std::optional<DataType> (*from_string_function)(const char* str),
const char* (*to_string_function)(DataType value), DataType default_value)
{
using Accessor = SettingAccessor<WidgetType>;
using UnderlyingType = std::underlying_type_t<DataType>;
// TODO: Clean this up?
const std::string old_setting_string_value =
QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), to_string_function(default_value));
const std::optional<DataType> old_setting_value = from_string_function(old_setting_string_value.c_str());
if (old_setting_value.has_value())
Accessor::setIntValue(widget, static_cast<int>(static_cast<UnderlyingType>(old_setting_value.value())));
sif->Save();
g_emu_thread->reloadGameSettings();
});
}
else
Accessor::setIntValue(widget, static_cast<int>(static_cast<UnderlyingType>(default_value)));
{
Accessor::setBoolValue(widget, value);
Accessor::connectValueChanged(widget, [widget, section, key, to_string_function]() {
const DataType value = static_cast<DataType>(static_cast<UnderlyingType>(Accessor::getIntValue(widget)));
const char* string_value = to_string_function(value);
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), string_value);
g_emu_thread->applySettings();
});
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const bool new_value = Accessor::getBoolValue(widget);
QtHost::SetBaseBoolSettingValue(section.c_str(), key.c_str(), new_value);
g_emu_thread->applySettings();
});
}
}
template <typename WidgetType>
static void BindWidgetToIntSetting(
SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, int default_value, int option_offset = 0)
{
using Accessor = SettingAccessor<WidgetType>;
const s32 value = QtHost::GetBaseIntSettingValue(section.c_str(), key.c_str(), static_cast<s32>(default_value)) - option_offset;
if (sif)
{
Accessor::makeNullableInt(widget, value);
int sif_value;
if (sif->GetIntValue(section.c_str(), key.c_str(), &sif_value))
Accessor::setNullableIntValue(widget, sif_value);
else
Accessor::setNullableIntValue(widget, std::nullopt);
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key), option_offset]() {
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
sif->SetIntValue(section.c_str(), key.c_str(), new_value.value() + option_offset);
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
g_emu_thread->reloadGameSettings();
});
}
else
{
Accessor::setIntValue(widget, static_cast<int>(value));
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), option_offset]() {
const int new_value = Accessor::getIntValue(widget);
QtHost::SetBaseIntSettingValue(section.c_str(), key.c_str(), new_value + option_offset);
g_emu_thread->applySettings();
});
}
}
template <typename WidgetType>
static void BindWidgetToFloatSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, float default_value)
{
using Accessor = SettingAccessor<WidgetType>;
const float value = QtHost::GetBaseFloatSettingValue(section.c_str(), key.c_str(), default_value);
if (sif)
{
Accessor::makeNullableFloat(widget, value);
float sif_value;
if (sif->GetFloatValue(section.c_str(), key.c_str(), &sif_value))
Accessor::setNullableFloatValue(widget, sif_value);
else
Accessor::setNullableFloatValue(widget, std::nullopt);
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key)]() {
if (std::optional<float> new_value = Accessor::getNullableFloatValue(widget); new_value.has_value())
sif->SetFloatValue(section.c_str(), key.c_str(), new_value.value());
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
g_emu_thread->reloadGameSettings();
});
}
else
{
Accessor::setFloatValue(widget, value);
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const float new_value = Accessor::getFloatValue(widget);
QtHost::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
g_emu_thread->applySettings();
});
}
}
template <typename WidgetType>
static void BindWidgetToNormalizedSetting(
SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, float range, float default_value)
{
using Accessor = SettingAccessor<WidgetType>;
const float value = QtHost::GetBaseFloatSettingValue(section.c_str(), key.c_str(), default_value);
if (sif)
{
Accessor::makeNullableInt(widget, static_cast<int>(value * range));
float sif_value;
if (sif->GetFloatValue(section.c_str(), key.c_str(), &sif_value))
Accessor::setNullableIntValue(widget, static_cast<int>(sif_value * range));
else
Accessor::setNullableIntValue(widget, std::nullopt);
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key), range]() {
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
sif->SetFloatValue(section.c_str(), key.c_str(), static_cast<float>(new_value.value()) / range);
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
g_emu_thread->reloadGameSettings();
});
}
else
{
Accessor::setIntValue(widget, static_cast<int>(value * range));
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), range]() {
const float new_value = (static_cast<float>(Accessor::getIntValue(widget)) / range);
QtHost::SetBaseFloatSettingValue(section.c_str(), key.c_str(), new_value);
g_emu_thread->applySettings();
});
}
}
template <typename WidgetType>
static void BindWidgetToStringSetting(
SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, std::string default_value = std::string())
{
using Accessor = SettingAccessor<WidgetType>;
const QString value(QString::fromStdString(QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value.c_str())));
if (sif)
{
Accessor::makeNullableString(widget, value);
std::string sif_value;
if (sif->GetStringValue(section.c_str(), key.c_str(), &sif_value))
Accessor::setNullableStringValue(widget, QString::fromStdString(sif_value));
else
Accessor::setNullableStringValue(widget, std::nullopt);
Accessor::connectValueChanged(widget, [widget, sif, section = std::move(section), key = std::move(key)]() {
if (std::optional<QString> new_value = Accessor::getNullableStringValue(widget); new_value.has_value())
sif->SetStringValue(section.c_str(), key.c_str(), new_value->toUtf8().constData());
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
g_emu_thread->reloadGameSettings();
});
}
else
{
Accessor::setStringValue(widget, value);
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key)]() {
const QString new_value = Accessor::getStringValue(widget);
if (!new_value.isEmpty())
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), new_value.toUtf8().constData());
else
QtHost::RemoveBaseSettingValue(section.c_str(), key.c_str());
g_emu_thread->applySettings();
});
}
}
template <typename WidgetType, typename DataType>
static void BindWidgetToEnumSetting(WidgetType* widget, std::string section, std::string key, const char** enum_names,
DataType default_value)
static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key,
std::optional<DataType> (*from_string_function)(const char* str), const char* (*to_string_function)(DataType value), DataType default_value)
{
using Accessor = SettingAccessor<WidgetType>;
using UnderlyingType = std::underlying_type_t<DataType>;
const std::string old_setting_string_value = QtHost::GetBaseStringSettingValue(
section.c_str(), key.c_str(), enum_names[static_cast<UnderlyingType>(default_value)]);
const std::string value(QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), to_string_function(default_value)));
const std::optional<DataType> typed_value = from_string_function(value.c_str());
if (sif)
{
Accessor::makeNullableInt(widget, typed_value.has_value() ? static_cast<int>(static_cast<UnderlyingType>(typed_value.value())) : 0);
std::string sif_value;
if (sif->GetStringValue(section.c_str(), key.c_str(), &sif_value))
{
const std::optional<DataType> old_setting_value = from_string_function(sif_value.c_str());
if (old_setting_value.has_value())
Accessor::setNullableIntValue(widget, static_cast<int>(static_cast<UnderlyingType>(old_setting_value.value())));
else
Accessor::setNullableIntValue(widget, std::nullopt);
}
else
{
Accessor::setNullableIntValue(widget, std::nullopt);
}
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key), to_string_function]() {
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
{
const char* string_value = to_string_function(static_cast<DataType>(static_cast<UnderlyingType>(new_value.value())));
sif->SetStringValue(section.c_str(), key.c_str(), string_value);
}
else
{
sif->DeleteValue(section.c_str(), key.c_str());
}
sif->Save();
g_emu_thread->reloadGameSettings();
});
}
else
{
if (typed_value.has_value())
Accessor::setIntValue(widget, static_cast<int>(static_cast<UnderlyingType>(typed_value.value())));
else
Accessor::setIntValue(widget, static_cast<int>(static_cast<UnderlyingType>(default_value)));
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), to_string_function]() {
const DataType value = static_cast<DataType>(static_cast<UnderlyingType>(Accessor::getIntValue(widget)));
const char* string_value = to_string_function(value);
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), string_value);
g_emu_thread->applySettings();
});
}
}
template <typename WidgetType, typename DataType>
static void BindWidgetToEnumSetting(
SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, const char** enum_names, DataType default_value)
{
using Accessor = SettingAccessor<WidgetType>;
using UnderlyingType = std::underlying_type_t<DataType>;
const std::string value(
QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), enum_names[static_cast<UnderlyingType>(default_value)]));
UnderlyingType enum_index = static_cast<UnderlyingType>(default_value);
for (UnderlyingType i = 0; enum_names[i] != nullptr; i++)
{
if (old_setting_string_value == enum_names[i])
if (value == enum_names[i])
{
enum_index = i;
break;
}
}
Accessor::setIntValue(widget, static_cast<int>(enum_index));
Accessor::connectValueChanged(widget, [widget, section, key, enum_names]() {
const UnderlyingType value = static_cast<UnderlyingType>(Accessor::getIntValue(widget));
const char* string_value = enum_names[value];
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), string_value);
g_emu_thread->applySettings();
});
if (sif)
{
Accessor::makeNullableInt(widget, static_cast<int>(enum_index));
std::string sif_value;
std::optional<int> sif_int_value;
if (sif->GetStringValue(section.c_str(), key.c_str(), &sif_value))
{
for (UnderlyingType i = 0; enum_names[i] != nullptr; i++)
{
if (sif_value == enum_names[i])
{
sif_int_value = static_cast<int>(i);
break;
}
}
}
Accessor::setNullableIntValue(widget, sif_int_value);
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key), enum_names]() {
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
sif->SetStringValue(section.c_str(), key.c_str(), enum_names[new_value.value()]);
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
g_emu_thread->reloadGameSettings();
});
}
else
{
Accessor::setIntValue(widget, static_cast<int>(enum_index));
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), enum_names]() {
const UnderlyingType value = static_cast<UnderlyingType>(Accessor::getIntValue(widget));
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), enum_names[value]);
g_emu_thread->applySettings();
});
}
}
template <typename WidgetType>
static void BindWidgetToEnumSetting(WidgetType* widget, std::string section, std::string key, const char** enum_names,
static void BindWidgetToEnumSetting(SettingsInterface* sif, WidgetType* widget, std::string section, std::string key, const char** enum_names,
const char** enum_values, const char* default_value)
{
using Accessor = SettingAccessor<WidgetType>;
const std::string old_setting_string_value =
QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value);
const std::string value = QtHost::GetBaseStringSettingValue(section.c_str(), key.c_str(), default_value);
for (int i = 0; enum_names[i] != nullptr; i++)
widget->addItem(QString::fromUtf8(enum_names[i]));
@@ -398,20 +718,53 @@ namespace SettingWidgetBinder
int enum_index = -1;
for (int i = 0; enum_values[i] != nullptr; i++)
{
if (old_setting_string_value == enum_values[i])
if (value == enum_values[i])
{
enum_index = i;
break;
}
}
if (enum_index >= 0)
Accessor::setIntValue(widget, enum_index);
Accessor::connectValueChanged(widget, [widget, section, key, enum_values]() {
const int value = Accessor::getIntValue(widget);
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), enum_values[value]);
g_emu_thread->applySettings();
});
if (sif)
{
Accessor::makeNullableInt(widget, enum_index);
std::string sif_value;
std::optional<int> sif_int_value;
if (sif->GetStringValue(section.c_str(), key.c_str(), &sif_value))
{
for (int i = 0; enum_values[i] != nullptr; i++)
{
if (value == enum_values[i])
{
sif_int_value = i;
break;
}
}
}
Accessor::setNullableIntValue(widget, sif_int_value);
Accessor::connectValueChanged(widget, [sif, widget, section = std::move(section), key = std::move(key), enum_names]() {
if (std::optional<int> new_value = Accessor::getNullableIntValue(widget); new_value.has_value())
sif->SetStringValue(section.c_str(), key.c_str(), enum_names[new_value.value()]);
else
sif->DeleteValue(section.c_str(), key.c_str());
sif->Save();
g_emu_thread->reloadGameSettings();
});
}
else
{
if (enum_index >= 0)
Accessor::setIntValue(widget, enum_index);
Accessor::connectValueChanged(widget, [widget, section = std::move(section), key = std::move(key), enum_values]() {
const int value = Accessor::getIntValue(widget);
QtHost::SetBaseStringSettingValue(section.c_str(), key.c_str(), enum_values[value]);
g_emu_thread->applySettings();
});
}
}
} // namespace SettingWidgetBinder
@@ -24,27 +24,29 @@
#include "SettingWidgetBinder.h"
#include "SettingsDialog.h"
AdvancedSystemSettingsWidget::AdvancedSystemSettingsWidget(QWidget* parent, SettingsDialog* dialog)
AdvancedSystemSettingsWidget::AdvancedSystemSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
{
SettingsInterface* sif = dialog->getSettingsInterface();
m_ui.setupUi(this);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.eeRecompiler, "EmuCore/CPU/Recompiler", "EnableEE", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.eeCache, "EmuCore/CPU/Recompiler", "EnableEECache", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.eeINTCSpinDetection, "EmuCore/Speedhacks", "IntcStat", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.eeWaitLoopDetection, "EmuCore/Speedhacks", "WaitLoop", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.eeRecompiler, "EmuCore/CPU/Recompiler", "EnableEE", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.eeCache, "EmuCore/CPU/Recompiler", "EnableEECache", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.eeINTCSpinDetection, "EmuCore/Speedhacks", "IntcStat", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.eeWaitLoopDetection, "EmuCore/Speedhacks", "WaitLoop", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.vu0Recompiler, "EmuCore/CPU/Recompiler", "EnableVU0", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.vu1Recompiler, "EmuCore/CPU/Recompiler", "EnableVU1", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.vuFlagHack, "EmuCore/Speedhacks", "vuFlagHack", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vu0Recompiler, "EmuCore/CPU/Recompiler", "EnableVU0", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vu1Recompiler, "EmuCore/CPU/Recompiler", "EnableVU1", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.vuFlagHack, "EmuCore/Speedhacks", "vuFlagHack", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.iopRecompiler, "EmuCore/CPU/Recompiler", "EnableIOP", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.iopRecompiler, "EmuCore/CPU/Recompiler", "EnableIOP", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.gameFixes, "", "EnableGameFixes", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.patches, "EmuCore", "EnablePatches", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gameFixes, "", "EnableGameFixes", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.patches, "EmuCore", "EnablePatches", true);
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.ntscFrameRate, "EmuCore/GS", "FramerateNTSC", 59.94f);
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.palFrameRate, "EmuCore/GS", "FrameratePAL", 50.00f);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.ntscFrameRate, "EmuCore/GS", "FramerateNTSC", 59.94f);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.palFrameRate, "EmuCore/GS", "FrameratePAL", 50.00f);
}
AdvancedSystemSettingsWidget::~AdvancedSystemSettingsWidget() = default;
@@ -26,7 +26,7 @@ class AdvancedSystemSettingsWidget : public QWidget
Q_OBJECT
public:
AdvancedSystemSettingsWidget(QWidget* parent, SettingsDialog* dialog);
AdvancedSystemSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~AdvancedSystemSettingsWidget();
private:
+35
View File
@@ -0,0 +1,35 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include <QtWidgets/QMessageBox>
#include <algorithm>
#include "AudioSettingsWidget.h"
#include "EmuThread.h"
#include "QtUtils.h"
#include "SettingWidgetBinder.h"
#include "SettingsDialog.h"
AudioSettingsWidget::AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
{
// SettingsInterface* sif = dialog->getSettingsInterface();
m_ui.setupUi(this);
}
AudioSettingsWidget::~AudioSettingsWidget() = default;
+34
View File
@@ -0,0 +1,34 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QtWidgets/QWidget>
#include "ui_AudioSettingsWidget.h"
class SettingsDialog;
class AudioSettingsWidget : public QWidget
{
Q_OBJECT
public:
AudioSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~AudioSettingsWidget();
private:
Ui::AudioSettingsWidget m_ui;
};
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AudioSettingsWidget</class>
<widget class="QWidget" name="AudioSettingsWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
</widget>
<resources/>
<connections/>
</ui>
+12 -4
View File
@@ -26,12 +26,14 @@
#include "SettingWidgetBinder.h"
#include "SettingsDialog.h"
BIOSSettingsWidget::BIOSSettingsWidget(QWidget* parent, SettingsDialog* dialog)
BIOSSettingsWidget::BIOSSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
{
SettingsInterface* sif = dialog->getSettingsInterface();
m_ui.setupUi(this);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.fastBoot, "EmuCore", "EnableFastBoot", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fastBoot, "EmuCore", "EnableFastBoot", true);
dialog->registerWidgetHelp(m_ui.fastBoot, tr("Fast Boot"), tr("Unchecked"),
tr("Patches the BIOS to skip the console's boot animation."));
@@ -124,9 +126,15 @@ void BIOSSettingsWidget::listRefreshed(const QVector<BIOSInfo>& items)
item->setIcon(0, QIcon(QStringLiteral(":/icons/flag-eu.png")));
break;
case 5: // HK
case 6: // Free
case 7: // China
item->setIcon(0, QIcon(QStringLiteral(":/icons/flag-cn.png")));
break;
case 5: // HK
item->setIcon(0, QIcon(QStringLiteral(":/icons/flag-hk.png")));
break;
case 6: // Free
case 0: // T10K
case 1: // Test
default:
+1 -1
View File
@@ -42,7 +42,7 @@ class BIOSSettingsWidget : public QWidget
Q_OBJECT
public:
BIOSSettingsWidget(QWidget* parent, SettingsDialog* dialog);
BIOSSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~BIOSSettingsWidget();
private Q_SLOTS:
+6
View File
@@ -108,6 +108,12 @@
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<attribute name="headerMinimumSectionSize">
<number>250</number>
</attribute>
<attribute name="headerDefaultSectionSize">
<number>250</number>
</attribute>
<column>
<property name="text">
<string>Filename</string>
@@ -38,7 +38,7 @@ ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSett
populateControllerTypes();
onTypeChanged();
SettingWidgetBinder::BindWidgetToStringSetting(m_ui.controllerType, m_config_section, "Type", "None");
SettingWidgetBinder::BindWidgetToStringSetting(nullptr, m_ui.controllerType, m_config_section, "Type", "None");
connect(m_ui.controllerType, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&ControllerBindingWidget::onTypeChanged);
}
@@ -26,9 +26,9 @@ ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent,
{
m_ui.setupUi(this);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.enableSDLSource, "InputSources", "SDL", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.enableSDLEnhancedMode, "InputSources", "SDLControllerEnhancedMode", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.enableXInputSource, "InputSources", "XInput", false);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.enableSDLSource, "InputSources", "SDL", true);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.enableSDLEnhancedMode, "InputSources", "SDLControllerEnhancedMode", false);
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.enableXInputSource, "InputSources", "XInput", false);
connect(m_ui.enableSDLSource, &QCheckBox::stateChanged, this, &ControllerGlobalSettingsWidget::updateSDLOptionsEnabled);
updateSDLOptionsEnabled();
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>880</width>
<height>712</height>
<width>900</width>
<height>500</height>
</rect>
</property>
<property name="windowTitle">
@@ -54,7 +54,7 @@
<item>
<widget class="QCheckBox" name="enableSDLEnhancedMode">
<property name="text">
<string>Dualshock 4 / Dualsense Enhanced Mode</string>
<string>DualShock 4 / DualSense Enhanced Mode</string>
</property>
</widget>
</item>
+125 -96
View File
@@ -15,6 +15,7 @@
#include "PrecompiledHeader.h"
#include <QtWidgets/QInputDialog>
#include <QtWidgets/QMessageBox>
#include <limits>
@@ -25,90 +26,45 @@
static constexpr u32 DEFAULT_FRAME_LATENCY = 2;
static void FillComboBoxWithEmulationSpeeds(QComboBox* cb)
{
cb->addItem(qApp->translate("GeneralSettingsWidget", "Unlimited"), QVariant(0.0f));
static const int speeds[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 125, 150, 175,
200, 250, 300, 350, 400, 450, 500, 600, 700, 800, 900, 1000};
for (const int speed : speeds)
{
cb->addItem(qApp->translate("EmulationSettingsWidget", "%1% [%2 FPS (NTSC) / %3 FPS (PAL)]")
.arg(speed)
.arg((60 * speed) / 100)
.arg((50 * speed) / 100),
QVariant(static_cast<float>(speed) / 100.0f));
}
}
EmulationSettingsWidget::EmulationSettingsWidget(QWidget* parent, SettingsDialog* dialog)
EmulationSettingsWidget::EmulationSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
, m_dialog(dialog)
{
SettingsInterface* sif = dialog->getSettingsInterface();
m_ui.setupUi(this);
FillComboBoxWithEmulationSpeeds(m_ui.normalSpeed);
if (const int index =
m_ui.normalSpeed->findData(QVariant(QtHost::GetBaseFloatSettingValue("Framerate", "NominalScalar", 1.0f)));
index >= 0)
{
m_ui.normalSpeed->setCurrentIndex(index);
}
connect(m_ui.normalSpeed, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&EmulationSettingsWidget::onNormalSpeedIndexChanged);
FillComboBoxWithEmulationSpeeds(m_ui.fastForwardSpeed);
initializeSpeedCombo(m_ui.normalSpeed, "Framerate", "NominalScalar", 1.0f);
initializeSpeedCombo(m_ui.fastForwardSpeed, "Framerate", "TurboScalar", 2.0f);
initializeSpeedCombo(m_ui.slowMotionSpeed, "Framerate", "SlomoScalar", 0.5f);
if (const int index =
m_ui.fastForwardSpeed->findData(QVariant(QtHost::GetBaseFloatSettingValue("Framerate", "TurboScalar", 2.0f)));
index >= 0)
{
m_ui.fastForwardSpeed->setCurrentIndex(index);
}
connect(m_ui.fastForwardSpeed, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&EmulationSettingsWidget::onFastForwardSpeedIndexChanged);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.speedLimiter, "EmuCore/GS", "FrameLimitEnable", true);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.maxFrameLatency, "EmuCore/GS", "VsyncQueueSize", DEFAULT_FRAME_LATENCY);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.syncToHostRefreshRate, "EmuCore/GS", "SyncToHostRefreshRate", false);
connect(m_ui.optimalFramePacing, &QCheckBox::stateChanged, this, &EmulationSettingsWidget::onOptimalFramePacingChanged);
m_ui.optimalFramePacing->setTristate(dialog->isPerGameSettings());
FillComboBoxWithEmulationSpeeds(m_ui.slowMotionSpeed);
if (const int index =
m_ui.slowMotionSpeed->findData(QVariant(QtHost::GetBaseFloatSettingValue("Framerate", "SlomoScalar", 0.5f)));
index >= 0)
{
m_ui.slowMotionSpeed->setCurrentIndex(index);
}
connect(m_ui.slowMotionSpeed, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&EmulationSettingsWidget::onSlowMotionSpeedIndexChanged);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.cheats, "EmuCore", "EnableCheats", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.widescreenPatches, "EmuCore", "EnableWideScreenPatches", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.perGameSettings, "EmuCore", "EnablePerGameSettings", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.hostFilesystem, "EmuCore", "HostFs", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.speedLimiter, "EmuCore/GS", "FrameLimitEnable", true);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.maxFrameLatency, "EmuCore/GS", "VsyncQueueSize", DEFAULT_FRAME_LATENCY);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.syncToHostRefreshRate, "EmuCore/GS", "SyncToHostRefreshRate",
false);
connect(m_ui.optimalFramePacing, &QCheckBox::toggled, this, &EmulationSettingsWidget::onOptimalFramePacingChanged);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.cheats, "EmuCore", "EnableCheats", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.widescreenPatches, "EmuCore", "EnableWideScreenPatches", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.perGameSettings, "EmuCore", "EnablePerGameSettings", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.hostFilesystem, "EmuCore", "HostFs", false);
dialog->registerWidgetHelp(
m_ui.normalSpeed, tr("Normal Speed"), "100%",
dialog->registerWidgetHelp(m_ui.normalSpeed, tr("Normal Speed"), "100%",
tr("Sets the target emulation speed. It is not guaranteed that this speed will be reached, "
"and if not, the emulator will run as fast as it can manage."));
dialog->registerWidgetHelp(
m_ui.fastForwardSpeed, tr("Fast Forward Speed"), tr("User Preference"),
dialog->registerWidgetHelp(m_ui.fastForwardSpeed, tr("Fast Forward Speed"), tr("User Preference"),
tr("Sets the fast forward speed. This speed will be used when the fast forward hotkey is pressed/toggled."));
dialog->registerWidgetHelp(
m_ui.slowMotionSpeed, tr("Slow Motion Speed"), tr("User Preference"),
dialog->registerWidgetHelp(m_ui.slowMotionSpeed, tr("Slow Motion Speed"), tr("User Preference"),
tr("Sets the slow motion speed. This speed will be used when the slow motion hotkey is pressed/toggled."));
dialog->registerWidgetHelp(
m_ui.syncToHostRefreshRate, tr("Sync To Host Refresh Rate"), tr("Unchecked"),
dialog->registerWidgetHelp(m_ui.syncToHostRefreshRate, tr("Sync To Host Refresh Rate"), tr("Unchecked"),
tr("Adjusts the emulation speed so the console's refresh rate matches the host's refresh rate when both VSync and "
"Audio Resampling settings are enabled. This results in the smoothest animations possible, at the cost of "
"potentially increasing the emulation speed by less than 1%. Sync To Host Refresh Rate will not take effect if "
"the console's refresh rate is too far from the host's refresh rate. Users with variable refresh rate displays "
"should disable this option."));
dialog->registerWidgetHelp(m_ui.cheats, tr("Enable Cheats"), tr("Unchecked"),
tr("Automatically loads and applies cheats on game start."));
dialog->registerWidgetHelp(
m_ui.perGameSettings, tr("Enable Per-Game Settings"), tr("Checked"),
dialog->registerWidgetHelp(m_ui.cheats, tr("Enable Cheats"), tr("Unchecked"), tr("Automatically loads and applies cheats on game start."));
dialog->registerWidgetHelp(m_ui.perGameSettings, tr("Enable Per-Game Settings"), tr("Checked"),
tr("When enabled, per-game settings will be applied, and incompatible enhancements will be disabled. You should "
"leave this option enabled except when testing enhancements with incompatible games."));
@@ -117,49 +73,122 @@ EmulationSettingsWidget::EmulationSettingsWidget(QWidget* parent, SettingsDialog
EmulationSettingsWidget::~EmulationSettingsWidget() = default;
void EmulationSettingsWidget::onNormalSpeedIndexChanged(int index)
void EmulationSettingsWidget::initializeSpeedCombo(QComboBox* cb, const char* section, const char* key, float default_value)
{
bool okay;
const float value = m_ui.normalSpeed->currentData().toFloat(&okay);
QtHost::SetBaseFloatSettingValue("Framerate", "NominalScalar", okay ? value : 1.0f);
g_emu_thread->applySettings();
float value = QtHost::GetBaseFloatSettingValue(section, key, default_value);
if (m_dialog->isPerGameSettings())
{
cb->addItem(tr("Use Global Setting [%1%]").arg(value * 100.0f, 0, 'f', 0));
if (!m_dialog->getSettingsInterface()->GetFloatValue(key, section, &value))
{
// set to something without data
value = -1.0f;
cb->setCurrentIndex(0);
}
}
static const int speeds[] = {1, 10, 25, 50, 75, 90, 100, 110, 120, 150, 175, 200, 300, 400, 500, 1000};
for (const int speed : speeds)
{
cb->addItem(tr("%1% [%2 FPS (NTSC) / %3 FPS (PAL)]")
.arg(speed)
.arg((60 * speed) / 100)
.arg((50 * speed) / 100),
QVariant(static_cast<float>(speed) / 100.0f));
}
cb->addItem(tr("Unlimited"), QVariant(0.0f));
const int custom_index = cb->count();
cb->addItem(tr("Custom"));
if (const int index = cb->findData(QVariant(value)); index >= 0)
{
cb->setCurrentIndex(index);
}
else if (value > 0.0f)
{
cb->setItemText(custom_index, tr("Custom [%1% / %2 FPS (NTSC) / %3 FPS (PAL)]")
.arg(value * 100)
.arg(60 * value)
.arg(50 * value));
cb->setCurrentIndex(custom_index);
}
connect(cb, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
[this, cb, section, key](int index) { handleSpeedComboChange(cb, section, key); });
}
void EmulationSettingsWidget::onFastForwardSpeedIndexChanged(int index)
void EmulationSettingsWidget::handleSpeedComboChange(QComboBox* cb, const char* section, const char* key)
{
bool okay;
const float value = m_ui.fastForwardSpeed->currentData().toFloat(&okay);
QtHost::SetBaseFloatSettingValue("Framerate", "TurboScalar", okay ? value : 1.0f);
g_emu_thread->applySettings();
const int custom_index = cb->count() - 1;
const int current_index = cb->currentIndex();
std::optional<float> new_value;
if (current_index == custom_index)
{
bool ok = false;
const double custom_value = QInputDialog::getDouble(
QtUtils::GetRootWidget(this), tr("Custom Speed"), tr("Enter Custom Speed"), cb->currentData().toFloat(), 0.0f, 5000.0f, 1, &ok);
if (!ok)
{
// we need to set back to the old value
float value = m_dialog->getEffectiveFloatValue(section, key, 1.0f);
QSignalBlocker sb(cb);
if (m_dialog->isPerGameSettings() && !m_dialog->getSettingsInterface()->GetFloatValue(section, key, &value))
cb->setCurrentIndex(0);
else if (const int index = cb->findData(QVariant(value)); index >= 0)
cb->setCurrentIndex(index);
return;
}
cb->setItemText(custom_index, tr("Custom [%1% / %2 FPS (NTSC) / %3 FPS (PAL)]")
.arg(custom_value)
.arg((60 * custom_value) / 100)
.arg((50 * custom_value) / 100));
new_value = static_cast<float>(custom_value / 100.0);
}
else if (current_index > 0 || !m_dialog->isPerGameSettings())
{
new_value = cb->currentData().toFloat();
}
m_dialog->setFloatSettingValue(section, key, new_value);
}
void EmulationSettingsWidget::onSlowMotionSpeedIndexChanged(int index)
{
bool okay;
const float value = m_ui.slowMotionSpeed->currentData().toFloat(&okay);
QtHost::SetBaseFloatSettingValue("Framerate", "SlomoScalar", okay ? value : 1.0f);
g_emu_thread->applySettings();
}
void EmulationSettingsWidget::onOptimalFramePacingChanged(bool checked)
void EmulationSettingsWidget::onOptimalFramePacingChanged()
{
const QSignalBlocker sb(m_ui.maxFrameLatency);
m_ui.maxFrameLatency->setValue(DEFAULT_FRAME_LATENCY);
m_ui.maxFrameLatency->setEnabled(!checked);
QtHost::SetBaseIntSettingValue("EmuCore/GS", "VsyncQueueSize", checked ? 0 : DEFAULT_FRAME_LATENCY);
g_emu_thread->applySettings();
std::optional<int> value;
if (m_ui.optimalFramePacing->checkState() != Qt::PartiallyChecked)
value = m_ui.optimalFramePacing->isChecked() ? 0 : DEFAULT_FRAME_LATENCY;
m_ui.maxFrameLatency->setValue(DEFAULT_FRAME_LATENCY);
m_ui.maxFrameLatency->setEnabled(!m_dialog->isPerGameSettings() && !m_ui.optimalFramePacing->isChecked());
m_dialog->setIntSettingValue("EmuCore/GS", "VsyncQueueSize", value);
}
void EmulationSettingsWidget::updateOptimalFramePacing()
{
const int value = QtHost::GetBaseIntSettingValue("EmuCore/GS", "VsyncQueueSize", DEFAULT_FRAME_LATENCY);
const bool optimal = (value == 0);
const QSignalBlocker sb(m_ui.optimalFramePacing);
m_ui.optimalFramePacing->setChecked(optimal);
const QSignalBlocker sb2(m_ui.maxFrameLatency);
m_ui.maxFrameLatency->setEnabled(!optimal);
int value = m_dialog->getEffectiveIntValue("EmuCore/GS", "VsyncQueueSize", DEFAULT_FRAME_LATENCY);
bool optimal = (value == 0);
if (m_dialog->isPerGameSettings() && !m_dialog->getSettingsInterface()->GetIntValue("EmuCore/GS", "VsyncQueueSize", &value))
{
m_ui.optimalFramePacing->setCheckState(Qt::PartiallyChecked);
m_ui.maxFrameLatency->setEnabled(false);
}
else
{
m_ui.optimalFramePacing->setChecked(optimal);
m_ui.maxFrameLatency->setEnabled(!optimal);
}
m_ui.maxFrameLatency->setValue(optimal ? DEFAULT_FRAME_LATENCY : value);
}
+6 -5
View File
@@ -26,17 +26,18 @@ class EmulationSettingsWidget : public QWidget
Q_OBJECT
public:
EmulationSettingsWidget(QWidget* parent, SettingsDialog* dialog);
EmulationSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~EmulationSettingsWidget();
private Q_SLOTS:
void onNormalSpeedIndexChanged(int index);
void onFastForwardSpeedIndexChanged(int index);
void onSlowMotionSpeedIndexChanged(int index);
void onOptimalFramePacingChanged(bool checked);
void onOptimalFramePacingChanged();
private:
void initializeSpeedCombo(QComboBox* cb, const char* section, const char* key, float default_value);
void handleSpeedComboChange(QComboBox* cb, const char* section, const char* key);
void updateOptimalFramePacing();
SettingsDialog* m_dialog;
Ui::EmulationSettingsWidget m_ui;
};
+1 -1
View File
@@ -75,7 +75,7 @@
<item>
<widget class="QGroupBox" name="basicGroupBox">
<property name="title">
<string>Frame Pacing/Latency Control</string>
<string>Frame Pacing / Latency Control</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
+19 -17
View File
@@ -24,27 +24,29 @@
#include "SettingWidgetBinder.h"
#include "SettingsDialog.h"
GameFixSettingsWidget::GameFixSettingsWidget(QWidget* parent, SettingsDialog* dialog)
GameFixSettingsWidget::GameFixSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
{
SettingsInterface* sif = dialog->getSettingsInterface();
m_ui.setupUi(this);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.FpuMulHack, "EmuCore/Gamefixes", "FpuMulHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.FpuNegDivHack, "EmuCore/Gamefixes", "FpuNegDivHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.GoemonTlbHack, "EmuCore/Gamefixes", "GoemonTlbHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.SoftwareRendererFMVHack, "EmuCore/Gamefixes", "SoftwareRendererFMVHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.SkipMPEGHack, "EmuCore/Gamefixes", "SkipMPEGHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.OPHFlagHack, "EmuCore/Gamefixes", "OPHFlagHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.EETimingHack, "EmuCore/Gamefixes", "EETimingHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.DMABusyHack, "EmuCore/Gamefixes", "DMABusyHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.GIFFIFOHack, "EmuCore/Gamefixes", "GIFFIFOHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.VIFFIFOHack, "EmuCore/Gamefixes", "VIFFIFOHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.VIF1StallHack, "EmuCore/Gamefixes", "VIF1StallHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.VuAddSubHack, "EmuCore/Gamefixes", "VuAddSubHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.IbitHack, "EmuCore/Gamefixes", "IbitHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.VUKickstartHack, "EmuCore/Gamefixes", "VUKickstartHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.VUOverflowHack, "EmuCore/Gamefixes", "VUOverflowHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.XgKickHack, "EmuCore/Gamefixes", "XgKickHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.FpuMulHack, "EmuCore/Gamefixes", "FpuMulHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.FpuNegDivHack, "EmuCore/Gamefixes", "FpuNegDivHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.GoemonTlbHack, "EmuCore/Gamefixes", "GoemonTlbHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.SoftwareRendererFMVHack, "EmuCore/Gamefixes", "SoftwareRendererFMVHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.SkipMPEGHack, "EmuCore/Gamefixes", "SkipMPEGHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.OPHFlagHack, "EmuCore/Gamefixes", "OPHFlagHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.EETimingHack, "EmuCore/Gamefixes", "EETimingHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.DMABusyHack, "EmuCore/Gamefixes", "DMABusyHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.GIFFIFOHack, "EmuCore/Gamefixes", "GIFFIFOHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VIFFIFOHack, "EmuCore/Gamefixes", "VIFFIFOHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VIF1StallHack, "EmuCore/Gamefixes", "VIF1StallHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VuAddSubHack, "EmuCore/Gamefixes", "VuAddSubHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.IbitHack, "EmuCore/Gamefixes", "IbitHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VUSyncHack, "EmuCore/Gamefixes", "VUSyncHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.VUOverflowHack, "EmuCore/Gamefixes", "VUOverflowHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.XgKickHack, "EmuCore/Gamefixes", "XgKickHack", false);
}
GameFixSettingsWidget::~GameFixSettingsWidget() = default;
+1 -1
View File
@@ -26,7 +26,7 @@ class GameFixSettingsWidget : public QWidget
Q_OBJECT
public:
GameFixSettingsWidget(QWidget* parent, SettingsDialog* dialog);
GameFixSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~GameFixSettingsWidget();
private:
+2 -2
View File
@@ -128,9 +128,9 @@
</widget>
</item>
<item>
<widget class="QCheckBox" name="VUKickstartHack">
<widget class="QCheckBox" name="VUSyncHack">
<property name="text">
<string>VU Kickstart Hack (Run Ahead)</string>
<string>VU Sync (Run Behind, M-Bit games)</string>
</property>
</widget>
</item>
+2 -2
View File
@@ -31,7 +31,7 @@
#include "QtHost.h"
#include "QtUtils.h"
GameListSettingsWidget::GameListSettingsWidget(QWidget* parent, SettingsDialog* dialog)
GameListSettingsWidget::GameListSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
{
m_ui.setupUi(this);
@@ -102,7 +102,7 @@ void GameListSettingsWidget::addPathToTable(const std::string& path, bool recurs
m_ui.searchDirectoryList->setCellWidget(row, 1, cb);
cb->setChecked(recursive);
connect(cb, &QCheckBox::stateChanged, [this, item](int state) {
connect(cb, &QCheckBox::stateChanged, [item](int state) {
const std::string path(item->text().toStdString());
if (state == Qt::Checked)
{
+1 -1
View File
@@ -28,7 +28,7 @@ class GameListSettingsWidget : public QWidget
Q_OBJECT
public:
GameListSettingsWidget(QWidget* parent, SettingsDialog* dialog);
GameListSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~GameListSettingsWidget();
bool addExcludedPath(const std::string& path);
+41
View File
@@ -0,0 +1,41 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "common/StringUtil.h"
#include "Frontend/GameList.h"
#include "GameSummaryWidget.h"
GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent)
{
m_ui.setupUi(this);
populateUi(entry);
}
GameSummaryWidget::~GameSummaryWidget() = default;
void GameSummaryWidget::populateUi(const GameList::Entry* entry)
{
m_ui.title->setText(QString::fromStdString(entry->title));
m_ui.path->setText(QString::fromStdString(entry->path));
m_ui.serial->setText(QString::fromStdString(entry->serial));
m_ui.crc->setText(QString::fromStdString(StringUtil::StdStringFromFormat("%08X", entry->crc)));
m_ui.type->setCurrentIndex(static_cast<int>(entry->type));
m_ui.region->setCurrentIndex(static_cast<int>(entry->region));
m_ui.compatibility->setCurrentIndex(static_cast<int>(entry->compatibility_rating));
}
+41
View File
@@ -0,0 +1,41 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QtWidgets/QWidget>
#include "ui_GameSummaryWidget.h"
namespace GameList
{
struct Entry;
}
class SettingsDialog;
class GameSummaryWidget : public QWidget
{
Q_OBJECT
public:
GameSummaryWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent);
~GameSummaryWidget();
private:
void populateUi(const GameList::Entry* entry);
Ui::GameSummaryWidget m_ui;
};
+278
View File
@@ -0,0 +1,278 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GameSummaryWidget</class>
<widget class="QWidget" name="GameSummaryWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>692</width>
<height>562</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<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 row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Title:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="title">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Path:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="path">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Serial:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="serial">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_36">
<property name="text">
<string>CRC:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="crc">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Region:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="region">
<property name="enabled">
<bool>false</bool>
</property>
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>NTSC-U/C (US/Canada)</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/flag-us.png</normaloff>:/icons/flag-us.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>NTSC-J (Japan)</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/flag-jp.png</normaloff>:/icons/flag-jp.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>PAL (Europe/Australia)</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/flag-eu.png</normaloff>:/icons/flag-eu.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>Other</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/flag-other.png</normaloff>:/icons/flag-other.png</iconset>
</property>
</item>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Compatibility:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="1">
<widget class="QComboBox" name="compatibility">
<property name="enabled">
<bool>false</bool>
</property>
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>Unknown</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/star-0.png</normaloff>:/icons/star-0.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>Not Bootable</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/star-1.png</normaloff>:/icons/star-1.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>Reaches Intro</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/star-2.png</normaloff>:/icons/star-2.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>Reaches Menu</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/star-3.png</normaloff>:/icons/star-3.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>In-Game</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/star-4.png</normaloff>:/icons/star-4.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>Perfect</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/star-5.png</normaloff>:/icons/star-5.png</iconset>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Type:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="type">
<property name="enabled">
<bool>false</bool>
</property>
<property name="editable">
<bool>true</bool>
</property>
<item>
<property name="text">
<string>PS2 Disc</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/media-optical-24.png</normaloff>:/icons/media-optical-24.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>PS1 Disc</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/media-optical-24.png</normaloff>:/icons/media-optical-24.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>ELF (PS2 Executable)</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/applications-system-24.png</normaloff>:/icons/applications-system-24.png</iconset>
</property>
</item>
<item>
<property name="text">
<string>Playlist</string>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/icons/address-book-new-22.png</normaloff>:/icons/address-book-new-22.png</iconset>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../resources/resources.qrc"/>
</resources>
<connections/>
</ui>
+190 -129
View File
@@ -54,69 +54,66 @@ static constexpr RendererInfo s_renderer_info[] = {
};
static const char* s_anisotropic_filtering_entries[] = {QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "Off (Default)"),
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "2x"),
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "4x"),
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "8x"),
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "16x"),
nullptr};
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "2x"), QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "4x"),
QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "8x"), QT_TRANSLATE_NOOP("GraphicsSettingsWidget", "16x"), nullptr};
static const char* s_anisotropic_filtering_values[] = {"1", "2", "4", "8", "16", nullptr};
static constexpr int DEFAULT_INTERLACE_MODE = 7;
GraphicsSettingsWidget::GraphicsSettingsWidget(QWidget* parent, SettingsDialog* dialog)
GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
, m_dialog(dialog)
{
SettingsInterface* sif = dialog->getSettingsInterface();
m_ui.setupUi(this);
//////////////////////////////////////////////////////////////////////////
// Global Settings
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToStringSetting(m_ui.adapter, "EmuCore/GS", "Adapter");
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.vsync, "EmuCore/GS", "VsyncEnable", 0);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.enableHWFixes, "EmuCore/GS", "UserHacks", false);
SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.adapter, "EmuCore/GS", "Adapter");
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vsync, "EmuCore/GS", "VsyncEnable", 0);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableHWFixes, "EmuCore/GS", "UserHacks", false);
//////////////////////////////////////////////////////////////////////////
// Game Display Settings
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToEnumSetting(m_ui.aspectRatio, "EmuCore/GS", "AspectRatio",
Pcsx2Config::GSOptions::AspectRatioNames, AspectRatioType::R4_3);
SettingWidgetBinder::BindWidgetToEnumSetting(m_ui.fmvAspectRatio, "EmuCore/GS", "FMVAspectRatioSwitch",
Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames,
FMVAspectRatioSwitchType::Off);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.interlacing, "EmuCore/GS", "interlace", DEFAULT_INTERLACE_MODE);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.bilinearFiltering, "EmuCore/GS", "LinearPresent", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.integerScaling, "EmuCore/GS", "IntegerScaling", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.internalResolutionScreenshots, "EmuCore/GS",
"InternalResolutionScreenshots", false);
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.zoom, "EmuCore/GS", "Zoom", 100.0f);
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.stretchY, "EmuCore/GS", "StretchY", 100.0f);
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.offsetX, "EmuCore/GS", "OffsetX", 0.0f);
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.offsetY, "EmuCore/GS", "OffsetY", 0.0f);
SettingWidgetBinder::BindWidgetToEnumSetting(
sif, m_ui.aspectRatio, "EmuCore/GS", "AspectRatio", Pcsx2Config::GSOptions::AspectRatioNames, AspectRatioType::R4_3);
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.fmvAspectRatio, "EmuCore/GS", "FMVAspectRatioSwitch",
Pcsx2Config::GSOptions::FMVAspectRatioSwitchNames, FMVAspectRatioSwitchType::Off);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.interlacing, "EmuCore/GS", "interlace", DEFAULT_INTERLACE_MODE);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.bilinearFiltering, "EmuCore/GS", "LinearPresent", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.integerScaling, "EmuCore/GS", "IntegerScaling", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.internalResolutionScreenshots, "EmuCore/GS", "InternalResolutionScreenshots", false);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.zoom, "EmuCore/GS", "Zoom", 100.0f);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.stretchY, "EmuCore/GS", "StretchY", 100.0f);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.offsetX, "EmuCore/GS", "OffsetX", 0.0f);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.offsetY, "EmuCore/GS", "OffsetY", 0.0f);
connect(m_ui.integerScaling, &QCheckBox::stateChanged, this, &GraphicsSettingsWidget::onIntegerScalingChanged);
onIntegerScalingChanged();
connect(m_ui.fullscreenModes, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onFullscreenModeChanged);
connect(m_ui.fullscreenModes, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onFullscreenModeChanged);
//////////////////////////////////////////////////////////////////////////
// OSD Settings
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToFloatSetting(m_ui.osdScale, "EmuCore/GS", "OsdScale", 100.0f);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowMessages, "EmuCore/GS", "OsdShowMessages", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowSpeed, "EmuCore/GS", "OsdShowSpeed", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowFPS, "EmuCore/GS", "OsdShowFPS", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowCPU, "EmuCore/GS", "OsdShowCPU", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowResolution, "EmuCore/GS", "OsdShowResolution", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.osdShowGSStats, "EmuCore/GS", "OsdShowGSStats", false);
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.osdScale, "EmuCore/GS", "OsdScale", 100.0f);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowMessages, "EmuCore/GS", "OsdShowMessages", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowSpeed, "EmuCore/GS", "OsdShowSpeed", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowFPS, "EmuCore/GS", "OsdShowFPS", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowCPU, "EmuCore/GS", "OsdShowCPU", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowResolution, "EmuCore/GS", "OsdShowResolution", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowGSStats, "EmuCore/GS", "OsdShowGSStats", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowIndicators, "EmuCore/GS", "OsdShowIndicators", true);
dialog->registerWidgetHelp(m_ui.osdShowMessages, tr("Show OSD Messages"), tr("Checked"),
tr("Shows on-screen-display messages when events occur such as save states being "
"created/loaded, screenshots being taken, etc."));
dialog->registerWidgetHelp(m_ui.osdShowFPS, tr("Show Game Frame Rate"), tr("Unchecked"),
tr("Shows the internal frame rate of the game in the top-right corner of the display."));
dialog->registerWidgetHelp(
m_ui.osdShowSpeed, tr("Show Emulation Speed"), tr("Unchecked"),
dialog->registerWidgetHelp(m_ui.osdShowSpeed, tr("Show Emulation Speed"), tr("Unchecked"),
tr("Shows the current emulation speed of the system in the top-right corner of the display as a percentage."));
dialog->registerWidgetHelp(m_ui.osdShowResolution, tr("Show Resolution"), tr("Unchecked"),
tr("Shows the resolution of the game in the top-right corner of the display."));
@@ -124,84 +121,102 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(QWidget* parent, SettingsDialog*
//////////////////////////////////////////////////////////////////////////
// HW Settings
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.upscaleMultiplier, "EmuCore/GS", "upscale_multiplier", 1);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.textureFiltering, "EmuCore/GS", "filter",
static_cast<int>(BiFiltering::PS2));
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.trilinearFiltering, "EmuCore/GS", "UserHacks_TriFilter",
static_cast<int>(TriFiltering::Off));
SettingWidgetBinder::BindWidgetToEnumSetting(m_ui.anisotropicFiltering, "EmuCore/GS", "MaxAnisotropy",
s_anisotropic_filtering_entries, s_anisotropic_filtering_values, "1");
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.dithering, "EmuCore/GS", "dithering_ps2", 2);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.mipmapping, "EmuCore/GS", "mipmap_hw",
static_cast<int>(HWMipmapLevel::Automatic), -1);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.crcFixLevel, "EmuCore/GS", "crc_hack_level",
static_cast<int>(CRCHackLevel::Automatic), -1);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.blending, "EmuCore/GS", "accurate_blending_unit",
static_cast<int>(AccBlendLevel::Basic));
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.accurateDATE, "EmuCore/GS", "accurate_date", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.conservativeBufferAllocation, "EmuCore/GS",
"conservative_framebuffer", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.gpuPaletteConversion, "EmuCore/GS", "paltex", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.preloadTexture, "EmuCore/GS", "preload_texture", false);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.upscaleMultiplier, "EmuCore/GS", "upscale_multiplier", 1);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureFiltering, "EmuCore/GS", "filter", static_cast<int>(BiFiltering::PS2));
SettingWidgetBinder::BindWidgetToIntSetting(
sif, m_ui.trilinearFiltering, "EmuCore/GS", "UserHacks_TriFilter", static_cast<int>(TriFiltering::Off));
SettingWidgetBinder::BindWidgetToEnumSetting(
sif, m_ui.anisotropicFiltering, "EmuCore/GS", "MaxAnisotropy", s_anisotropic_filtering_entries, s_anisotropic_filtering_values, "1");
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.dithering, "EmuCore/GS", "dithering_ps2", 2);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.mipmapping, "EmuCore/GS", "mipmap_hw", static_cast<int>(HWMipmapLevel::Automatic), -1);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.crcFixLevel, "EmuCore/GS", "crc_hack_level", static_cast<int>(CRCHackLevel::Automatic), -1);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.blending, "EmuCore/GS", "accurate_blending_unit", static_cast<int>(AccBlendLevel::Basic));
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.accurateDATE, "EmuCore/GS", "accurate_date", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.conservativeBufferAllocation, "EmuCore/GS", "conservative_framebuffer", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gpuPaletteConversion, "EmuCore/GS", "paltex", false);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.texturePreloading, "EmuCore/GS", "texture_preloading",
static_cast<int>(TexturePreloadingLevel::Off));
//////////////////////////////////////////////////////////////////////////
// HW Renderer Fixes
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.halfScreenFix, "EmuCore/GS", "UserHacks_Half_Bottom_Override", -1,
-1);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.skipDrawRangeStart, "EmuCore/GS", "UserHacks_SkipDraw", 0);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.skipDrawRangeCount, "EmuCore/GS", "UserHacks_SkipDraw_Offset", 0);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.hwAutoFlush, "EmuCore/GS", "UserHacks_AutoFlush", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.frameBufferConversion, "EmuCore/GS", "UserHacks_CPU_FB_Conversion",
false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.disableDepthEmulation, "EmuCore/GS",
"UserHacks_DisableDepthSupport", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.memoryWrapping, "EmuCore/GS", "wrap_gs_mem", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.disableSafeFeatures, "EmuCore/GS",
"UserHacks_Disable_Safe_Features", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.preloadFrameData, "EmuCore/GS", "preload_frame_with_gs_data",
false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.fastTextureInvalidation, "EmuCore/GS",
"UserHacks_DisablePartialInvalidation", false);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfScreenFix, "EmuCore/GS", "UserHacks_Half_Bottom_Override", -1, -1);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.skipDrawRangeStart, "EmuCore/GS", "UserHacks_SkipDraw", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.skipDrawRangeCount, "EmuCore/GS", "UserHacks_SkipDraw_Offset", 0);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.hwAutoFlush, "EmuCore/GS", "UserHacks_AutoFlush", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.frameBufferConversion, "EmuCore/GS", "UserHacks_CPU_FB_Conversion", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableDepthEmulation, "EmuCore/GS", "UserHacks_DisableDepthSupport", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.memoryWrapping, "EmuCore/GS", "wrap_gs_mem", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableSafeFeatures, "EmuCore/GS", "UserHacks_Disable_Safe_Features", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.preloadFrameData, "EmuCore/GS", "preload_frame_with_gs_data", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fastTextureInvalidation, "EmuCore/GS", "UserHacks_DisablePartialInvalidation", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.textureInsideRt, "EmuCore/GS", "UserHacks_TextureInsideRt", false);
//////////////////////////////////////////////////////////////////////////
// HW Upscaling Fixes
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.halfPixelOffset, "EmuCore/GS", "UserHacks_HalfPixelOffset", 0);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.roundSprite, "EmuCore/GS", "UserHacks_RoundSprite", 0);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.textureOffsetX, "EmuCore/GS", "UserHacks_TCOffsetX", 0);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.textureOffsetY, "EmuCore/GS", "UserHacks_TCOffsetY", 0);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfPixelOffset, "EmuCore/GS", "UserHacks_HalfPixelOffset", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.roundSprite, "EmuCore/GS", "UserHacks_RoundSprite", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetX, "EmuCore/GS", "UserHacks_TCOffsetX", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetY, "EmuCore/GS", "UserHacks_TCOffsetY", 0);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false);
//////////////////////////////////////////////////////////////////////////
// Texture Replacements
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.dumpReplaceableTextures, "EmuCore/GS", "DumpReplaceableTextures", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.dumpReplaceableMipmaps, "EmuCore/GS", "DumpReplaceableMipmaps", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.dumpTexturesWithFMVActive, "EmuCore/GS", "DumpTexturesWithFMVActive", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.loadTextureReplacements, "EmuCore/GS", "LoadTextureReplacements", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.loadTextureReplacementsAsync, "EmuCore/GS", "LoadTextureReplacementsAsync", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.precacheTextureReplacements, "EmuCore/GS", "PrecacheTextureReplacements", false);
//////////////////////////////////////////////////////////////////////////
// Advanced Settings
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.useBlitSwapChain, "EmuCore/GS", "UseBlitSwapChain", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.useDebugDevice, "EmuCore/GS", "UseDebugDevice", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useBlitSwapChain, "EmuCore/GS", "UseBlitSwapChain", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useDebugDevice, "EmuCore/GS", "UseDebugDevice", false);
//////////////////////////////////////////////////////////////////////////
// SW Settings
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.extraSWThreads, "EmuCore/GS", "extrathreads", 2);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.swAutoFlush, "EmuCore/GS", "autoflush_sw", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.swAA1, "EmuCore/GS", "aa1", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.swMipmap, "EmuCore/GS", "mipmap", true);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.extraSWThreads, "EmuCore/GS", "extrathreads", 2);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.swAutoFlush, "EmuCore/GS", "autoflush_sw", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.swAA1, "EmuCore/GS", "aa1", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.swMipmap, "EmuCore/GS", "mipmap", true);
//////////////////////////////////////////////////////////////////////////
// Non-trivial settings
//////////////////////////////////////////////////////////////////////////
const GSRendererType current_renderer = static_cast<GSRendererType>(
QtHost::GetBaseIntSettingValue("EmuCore/GS", "Renderer", static_cast<int>(GSRendererType::Auto)));
const int renderer = m_dialog->getEffectiveIntValue("EmuCore/GS", "Renderer", static_cast<int>(GSRendererType::Auto));
for (const RendererInfo& ri : s_renderer_info)
{
m_ui.renderer->addItem(qApp->translate("GraphicsSettingsWidget", ri.name));
if (ri.type == current_renderer)
if (renderer == static_cast<int>(ri.type))
m_ui.renderer->setCurrentIndex(m_ui.renderer->count() - 1);
}
connect(m_ui.renderer, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&GraphicsSettingsWidget::onRendererChanged);
// per-game override for renderer is slightly annoying, since we need to populate the global setting field
if (sif)
{
QString global_renderer_name;
for (const RendererInfo& ri : s_renderer_info)
{
if (renderer == static_cast<int>(ri.type))
global_renderer_name = qApp->translate("GraphicsSettingsWidget", ri.name);
}
m_ui.renderer->insertItem(0, tr("Use Global Setting [%1]").arg(global_renderer_name));
int override_renderer;
if (sif->GetIntValue("EmuCore/GS", "Renderer", &override_renderer))
m_ui.renderer->setCurrentIndex(override_renderer + 1);
else
m_ui.renderer->setCurrentIndex(0);
}
connect(m_ui.renderer, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &GraphicsSettingsWidget::onRendererChanged);
connect(m_ui.enableHWFixes, &QCheckBox::stateChanged, this, &GraphicsSettingsWidget::onEnableHardwareFixesChanged);
updateRendererDependentOptions();
@@ -215,33 +230,69 @@ GraphicsSettingsWidget::~GraphicsSettingsWidget() = default;
void GraphicsSettingsWidget::onRendererChanged(int index)
{
QtHost::SetBaseIntSettingValue("EmuCore/GS", "Renderer", static_cast<int>(s_renderer_info[index].type));
if (m_dialog->isPerGameSettings())
{
if (index > 0)
m_dialog->setIntSettingValue("EmuCore/GS", "Renderer", static_cast<int>(s_renderer_info[index - 1].type));
else
m_dialog->setIntSettingValue("EmuCore/GS", "Renderer", std::nullopt);
}
else
{
m_dialog->setIntSettingValue("EmuCore/GS", "Renderer", static_cast<int>(s_renderer_info[index].type));
}
g_emu_thread->applySettings();
updateRendererDependentOptions();
}
void GraphicsSettingsWidget::onAdapterChanged(int index)
{
if (index == 0)
QtHost::RemoveBaseSettingValue("EmuCore/GS", "Adapter");
const int first_adapter = m_dialog->isPerGameSettings() ? 2 : 1;
if (index >= first_adapter)
m_dialog->setStringSettingValue("EmuCore/GS", "Adapter", m_ui.adapter->currentText().toUtf8().constData());
else if (index > 0 && m_dialog->isPerGameSettings())
m_dialog->setStringSettingValue("EmuCore/GS", "Adapter", "");
else
QtHost::SetBaseStringSettingValue("EmuCore/GS", "Adapter", m_ui.adapter->currentText().toUtf8().constData());
m_dialog->setStringSettingValue("EmuCore/GS", "Adapter", std::nullopt);
g_emu_thread->applySettings();
}
void GraphicsSettingsWidget::onFullscreenModeChanged(int index)
{
const int first_mode = m_dialog->isPerGameSettings() ? 2 : 1;
if (index >= first_mode)
m_dialog->setStringSettingValue("EmuCore/GS", "FullscreenMode", m_ui.fullscreenModes->currentText().toUtf8().constData());
else if (index > 0 && m_dialog->isPerGameSettings())
m_dialog->setStringSettingValue("EmuCore/GS", "FullscreenMode", "");
else
m_dialog->setStringSettingValue("EmuCore/GS", "FullscreenMode", std::nullopt);
g_emu_thread->applySettings();
}
void GraphicsSettingsWidget::onIntegerScalingChanged() { m_ui.bilinearFiltering->setEnabled(!m_ui.integerScaling->isChecked()); }
void GraphicsSettingsWidget::onEnableHardwareFixesChanged()
{
const bool enabled = m_ui.enableHWFixes->isChecked();
const bool enabled = (m_ui.enableHWFixes->checkState() == Qt::Checked);
m_ui.hardwareRendererGroup->setTabEnabled(2, enabled);
m_ui.hardwareRendererGroup->setTabEnabled(3, enabled);
}
GSRendererType GraphicsSettingsWidget::getEffectiveRenderer() const
{
const GSRendererType type =
static_cast<GSRendererType>(m_dialog->getEffectiveIntValue("EmuCore/GS", "Renderer", static_cast<int>(GSRendererType::Auto)));
return (type == GSRendererType::Auto) ? GSUtil::GetPreferredRenderer() : type;
}
void GraphicsSettingsWidget::updateRendererDependentOptions()
{
const int index = m_ui.renderer->currentIndex();
GSRendererType type = s_renderer_info[index].type;
if (type == GSRendererType::Auto)
type = GSUtil::GetPreferredRenderer();
const GSRendererType type = getEffectiveRenderer();
#ifdef _WIN32
const bool is_dx11 = (type == GSRendererType::DX11 || type == GSRendererType::SW);
@@ -251,6 +302,7 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
const bool is_hardware = (type == GSRendererType::DX11 || type == GSRendererType::OGL || type == GSRendererType::VK);
const bool is_software = (type == GSRendererType::SW);
const int current_tab = m_hardware_renderer_visible ? m_ui.hardwareRendererGroup->currentIndex() : m_ui.softwareRendererGroup->currentIndex();
// move advanced tab to the correct parent
static constexpr std::array<const char*, 3> move_tab_names = {{"Display", "On-Screen Display", "Advanced"}};
@@ -269,21 +321,19 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
m_ui.softwareRendererGroup->insertTab((i == 0) ? 0 : m_ui.softwareRendererGroup->count(), tab, tab_label);
}
if (is_hardware != is_software)
{
if (is_hardware)
m_ui.hardwareRendererGroup->setCurrentIndex(0);
else
m_ui.softwareRendererGroup->setCurrentIndex(0);
}
if (m_hardware_renderer_visible != is_hardware)
{
m_ui.hardwareRendererGroup->setVisible(is_hardware);
if (!is_hardware)
{
m_ui.verticalLayout->removeWidget(m_ui.hardwareRendererGroup);
}
else
{
// map first two tabs over, skip hacks
m_ui.verticalLayout->insertWidget(1, m_ui.hardwareRendererGroup);
m_ui.hardwareRendererGroup->setCurrentIndex((current_tab < 2) ? current_tab : (current_tab + 2));
}
m_hardware_renderer_visible = is_hardware;
}
@@ -291,10 +341,16 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
if (m_software_renderer_visible != is_software)
{
m_ui.softwareRendererGroup->setVisible(is_software);
if (!is_hardware)
if (is_hardware)
{
m_ui.verticalLayout->removeWidget(m_ui.softwareRendererGroup);
}
else
{
// software has no hacks tabs
m_ui.verticalLayout->insertWidget(1, m_ui.softwareRendererGroup);
m_ui.softwareRendererGroup->setCurrentIndex((current_tab >= 5) ? (current_tab - 3) : (current_tab >= 2 ? 1 : current_tab));
}
m_software_renderer_visible = is_software;
}
@@ -325,11 +381,26 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
// fill+select adapters
{
const std::string current_adapter = QtHost::GetBaseStringSettingValue("EmuCore/GS", "Adapter", "");
QSignalBlocker sb(m_ui.adapter);
std::string current_adapter = QtHost::GetBaseStringSettingValue("EmuCore/GS", "Adapter", "");
m_ui.adapter->clear();
m_ui.adapter->setEnabled(!modes.adapter_names.empty());
m_ui.adapter->addItem(tr("(Default)"));
m_ui.adapter->setCurrentIndex(0);
if (m_dialog->isPerGameSettings())
{
m_ui.adapter->insertItem(
0, tr("Use Global Setting [%1]").arg(current_adapter.empty() ? tr("(Default)") : QString::fromStdString(current_adapter)));
if (!m_dialog->getSettingsInterface()->GetStringValue("EmuCore/GS", "Adapter", &current_adapter))
{
// clear the adapter so we don't set it to the global value
current_adapter.clear();
m_ui.adapter->setCurrentIndex(0);
}
}
for (const std::string& adapter : modes.adapter_names)
{
m_ui.adapter->addItem(QString::fromStdString(adapter));
@@ -342,11 +413,21 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
{
QSignalBlocker sb(m_ui.fullscreenModes);
const std::string current_mode(QtHost::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", ""));
std::string current_mode(QtHost::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", ""));
m_ui.fullscreenModes->clear();
m_ui.fullscreenModes->addItem(tr("Borderless Fullscreen"));
if (current_mode.empty())
m_ui.fullscreenModes->setCurrentIndex(0);
m_ui.fullscreenModes->setCurrentIndex(0);
if (m_dialog->isPerGameSettings())
{
m_ui.fullscreenModes->insertItem(
0, tr("Use Global Setting [%1]").arg(current_mode.empty() ? tr("(Default)") : QString::fromStdString(current_mode)));
if (!m_dialog->getSettingsInterface()->GetStringValue("EmuCore/GS", "FullscreenMode", &current_mode))
{
current_mode.clear();
m_ui.fullscreenModes->setCurrentIndex(0);
}
}
for (const std::string& fs_mode : modes.fullscreen_modes)
{
@@ -359,23 +440,3 @@ void GraphicsSettingsWidget::updateRendererDependentOptions()
m_ui.enableHWFixes->setEnabled(is_hardware);
onEnableHardwareFixesChanged();
}
void GraphicsSettingsWidget::onIntegerScalingChanged()
{
m_ui.bilinearFiltering->setEnabled(!m_ui.integerScaling->isChecked());
}
void GraphicsSettingsWidget::onFullscreenModeChanged(int index)
{
if (index == 0)
{
QtHost::RemoveBaseSettingValue("EmuCore/GS", "FullscreenMode");
}
else
{
QtHost::SetBaseStringSettingValue("EmuCore/GS", "FullscreenMode",
m_ui.fullscreenModes->currentText().toUtf8().constData());
}
g_emu_thread->applySettings();
}
+7 -1
View File
@@ -19,6 +19,8 @@
#include "ui_GraphicsSettingsWidget.h"
enum class GSRendererType : s8;
class SettingsDialog;
class GraphicsSettingsWidget : public QWidget
@@ -26,7 +28,7 @@ class GraphicsSettingsWidget : public QWidget
Q_OBJECT
public:
GraphicsSettingsWidget(QWidget* parent, SettingsDialog* dialog);
GraphicsSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~GraphicsSettingsWidget();
void updateRendererDependentOptions();
@@ -42,6 +44,10 @@ private Q_SLOTS:
void onFullscreenModeChanged(int index);
private:
GSRendererType getEffectiveRenderer() const;
SettingsDialog* m_dialog;
Ui::GraphicsSettingsWidget m_ui;
bool m_hardware_renderer_visible = true;
+136 -34
View File
@@ -133,7 +133,7 @@
<item row="3" column="0">
<widget class="QLabel" name="label_23">
<property name="text">
<string>Interlacing:</string>
<string>Deinterlacing:</string>
</property>
</widget>
</item>
@@ -560,12 +560,12 @@
</item>
</widget>
</item>
<item row="8" column="0" colspan="2">
<item row="9" column="0" colspan="2">
<layout class="QGridLayout" name="basicCheckboxGridLayout">
<item row="0" column="0">
<widget class="QCheckBox" name="accurateDATE">
<item row="1" column="0">
<widget class="QCheckBox" name="gpuPaletteConversion">
<property name="text">
<string>Accurate Destination Alpha Test</string>
<string>GPU Palette Conversion</string>
</property>
</widget>
</item>
@@ -576,21 +576,14 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="gpuPaletteConversion">
<item row="0" column="0">
<widget class="QCheckBox" name="accurateDATE">
<property name="text">
<string>GPU Palette Conversion</string>
<string>Accurate Destination Alpha Test</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="preloadTexture">
<property name="text">
<string>Preload Textures</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="enableHWFixes">
<property name="text">
<string>Enable Hardware Renderer Fixes</string>
@@ -599,6 +592,32 @@
</item>
</layout>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Texture Preloading:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QComboBox" name="texturePreloading">
<item>
<property name="text">
<string>None</string>
</property>
</item>
<item>
<property name="text">
<string>Partial</string>
</property>
</item>
<item>
<property name="text">
<string>Full (Hash Cache)</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QGroupBox" name="hardwareFixesTab">
@@ -700,6 +719,13 @@
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="textureInsideRt">
<property name="text">
<string>Texture Inside RT</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@@ -751,7 +777,7 @@
<widget class="QComboBox" name="roundSprite">
<item>
<property name="text">
<string>Off (Default</string>
<string>Off (Default)</string>
</property>
</item>
<item>
@@ -893,6 +919,13 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="osdShowIndicators">
<property name="text">
<string>Show Indicators</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@@ -901,24 +934,93 @@
<attribute name="title">
<string>Advanced</string>
</attribute>
<layout class="QFormLayout" name="formLayout_6">
<item row="0" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QCheckBox" name="useBlitSwapChain">
<property name="text">
<string>Use Blit Swap Chain</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="useDebugDevice">
<property name="text">
<string>Use Debug Device</string>
</property>
</widget>
</item>
</layout>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Debug Options</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QCheckBox" name="useBlitSwapChain">
<property name="text">
<string>Use Blit Swap Chain</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="useDebugDevice">
<property name="text">
<string>Use Debug Device</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Texture Replacement</string>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0">
<widget class="QCheckBox" name="dumpReplaceableTextures">
<property name="text">
<string>Dump Textures</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="dumpReplaceableMipmaps">
<property name="text">
<string>Dump Mipmaps</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="loadTextureReplacementsAsync">
<property name="text">
<string>Async Texture Loading</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="precacheTextureReplacements">
<property name="text">
<string>Precache Textures</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="loadTextureReplacements">
<property name="text">
<string>Load Textures</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="dumpTexturesWithFMVActive">
<property name="text">
<string>Dump FMV Textures</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
-1
View File
@@ -1,4 +1,3 @@
/* PCSX2 - PS2 Emulator for PCs
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
*
+27 -20
View File
@@ -20,32 +20,39 @@
#include "SettingWidgetBinder.h"
#include "SettingsDialog.h"
static const char* THEME_NAMES[] = {QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Native"),
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Fusion"),
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Dark Fusion (Gray)"),
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Dark Fusion (Blue)"), nullptr};
static const char* THEME_NAMES[] = {QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Native [Light]"),
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Fusion [Light]"),
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Dark Fusion (Gray) [Dark]"),
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Dark Fusion (Blue) [Dark]"),
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Untouched Lagoon (Grayish Green/-Blue ) [Light]"),
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Baby Pastel (Pink) [Light]"),
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "PCSX2 (White/Blue) [Light]"),
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Scarlet Devil (Red/Purple) [Dark]"), nullptr};
static const char* THEME_VALUES[] = {"", "fusion", "darkfusion", "darkfusionblue", nullptr};
static const char* THEME_VALUES[] = {"", "fusion", "darkfusion", "darkfusionblue",
"UntouchedLagoon", "BabyPastel", "PCSX2Blue", "ScarletDevilRed", nullptr};
InterfaceSettingsWidget::InterfaceSettingsWidget(QWidget* parent, SettingsDialog* dialog)
InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
{
SettingsInterface* sif = dialog->getSettingsInterface();
m_ui.setupUi(this);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.inhibitScreensaver, "UI", "InhibitScreensaver", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.discordPresence, "UI", "DiscordPresence", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.confirmPowerOff, "UI", "ConfirmPowerOff", true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.saveStateOnExit, "EmuCore", "AutoStateLoadSave", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.pauseOnStart, "UI", "StartPaused", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.pauseOnFocusLoss, "UI", "PauseOnFocusLoss", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.inhibitScreensaver, "UI", "InhibitScreensaver", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.discordPresence, "UI", "DiscordPresence", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.confirmShutdown, "UI", "ConfirmShutdown", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.saveStateOnExit, "EmuCore", "AutoStateLoadSave", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnStart, "UI", "StartPaused", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnFocusLoss, "UI", "PauseOnFocusLoss", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.startFullscreen, "UI", "StartFullscreen", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.doubleClickTogglesFullscreen, "UI", "DoubleClickTogglesFullscreen",
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.startFullscreen, "UI", "StartFullscreen", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.doubleClickTogglesFullscreen, "UI", "DoubleClickTogglesFullscreen",
true);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.hideMouseCursor, "UI", "HideMouseCursor", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.renderToMainWindow, "UI", "RenderToMainWindow", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.hideMouseCursor, "UI", "HideMouseCursor", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.renderToMainWindow, "UI", "RenderToMainWindow", true);
SettingWidgetBinder::BindWidgetToEnumSetting(m_ui.theme, "UI", "Theme", THEME_NAMES, THEME_VALUES,
SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.theme, "UI", "Theme", THEME_NAMES, THEME_VALUES,
MainWindow::DEFAULT_THEME_NAME);
connect(m_ui.theme, QOverload<int>::of(&QComboBox::currentIndexChanged), [this]() { emit themeChanged(); });
@@ -57,7 +64,7 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(QWidget* parent, SettingsDialog
tr("Shows the game you are currently playing as part of your profile in Discord."));
if (true)
{
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.autoUpdateEnabled, "AutoUpdater", "CheckAtStartup", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.autoUpdateEnabled, "AutoUpdater", "CheckAtStartup", true);
dialog->registerWidgetHelp(m_ui.autoUpdateEnabled, tr("Enable Automatic Update Check"), tr("Checked"),
tr("Automatically checks for updates to the program on startup. Updates can be deferred "
"until later or skipped entirely."));
@@ -77,8 +84,8 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(QWidget* parent, SettingsDialog
}
dialog->registerWidgetHelp(
m_ui.confirmPowerOff, tr("Confirm Power Off"), tr("Checked"),
tr("Determines whether a prompt will be displayed to confirm shutting down the emulator/game "
m_ui.confirmShutdown, tr("Confirm Shutdown"), tr("Checked"),
tr("Determines whether a prompt will be displayed to confirm shutting down the virtual machine "
"when the hotkey is pressed."));
dialog->registerWidgetHelp(m_ui.saveStateOnExit, tr("Save State On Exit"), tr("Checked"),
tr("Automatically saves the emulator state when powering down or exiting. You can then "
+1 -1
View File
@@ -26,7 +26,7 @@ class InterfaceSettingsWidget : public QWidget
Q_OBJECT
public:
InterfaceSettingsWidget(QWidget* parent, SettingsDialog* dialog);
InterfaceSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~InterfaceSettingsWidget();
Q_SIGNALS:
+3 -3
View File
@@ -61,16 +61,16 @@
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="confirmPowerOff">
<widget class="QCheckBox" name="confirmShutdown">
<property name="text">
<string>Confirm Power Off</string>
<string>Confirm Shutdown</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="saveStateOnExit">
<property name="text">
<string>Save/Load State On Exit/Resume</string>
<string>Save Or Load State On Exit / Resume</string>
</property>
</widget>
</item>
@@ -0,0 +1,35 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include <QtWidgets/QMessageBox>
#include <algorithm>
#include "MemoryCardSettingsWidget.h"
#include "EmuThread.h"
#include "QtUtils.h"
#include "SettingWidgetBinder.h"
#include "SettingsDialog.h"
MemoryCardSettingsWidget::MemoryCardSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
{
// SettingsInterface* sif = dialog->getSettingsInterface();
m_ui.setupUi(this);
}
MemoryCardSettingsWidget::~MemoryCardSettingsWidget() = default;
@@ -0,0 +1,34 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QtWidgets/QWidget>
#include "ui_MemoryCardSettingsWidget.h"
class SettingsDialog;
class MemoryCardSettingsWidget : public QWidget
{
Q_OBJECT
public:
MemoryCardSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~MemoryCardSettingsWidget();
private:
Ui::MemoryCardSettingsWidget m_ui;
};
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MemoryCardSettingsWidget</class>
<widget class="QWidget" name="MemoryCardSettingsWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
</widget>
<resources/>
<connections/>
</ui>
+318 -45
View File
@@ -15,12 +15,20 @@
#include "PrecompiledHeader.h"
#include "common/FileSystem.h"
#include "common/StringUtil.h"
#include "pcsx2/Frontend/GameList.h"
#include "pcsx2/Frontend/INISettingsInterface.h"
#include "EmuThread.h"
#include "QtHost.h"
#include "QtUtils.h"
#include "SettingsDialog.h"
#include "AdvancedSystemSettingsWidget.h"
#include "BIOSSettingsWidget.h"
#include "EmulationSettingsWidget.h"
#include "GameSummaryWidget.h"
#include "GameFixSettingsWidget.h"
#include "GameListSettingsWidget.h"
#include "GraphicsSettingsWidget.h"
@@ -31,33 +39,86 @@
#include <QtWidgets/QMessageBox>
#include <QtWidgets/QTextEdit>
static constexpr char DEFAULT_SETTING_HELP_TEXT[] = "";
static QList<SettingsDialog*> s_open_game_properties_dialogs;
SettingsDialog::SettingsDialog(QWidget* parent /* = nullptr */)
SettingsDialog::SettingsDialog(QWidget* parent)
: QDialog(parent)
, m_game_crc(0)
{
m_ui.setupUi(this);
setCategoryHelpTexts();
setupUi(nullptr);
}
SettingsDialog::SettingsDialog(std::unique_ptr<SettingsInterface> sif, const GameList::Entry* game, u32 game_crc)
: QDialog()
, m_sif(std::move(sif))
, m_game_crc(game_crc)
{
setupUi(game);
s_open_game_properties_dialogs.push_back(this);
}
void SettingsDialog::setupUi(const GameList::Entry* game)
{
const bool show_advanced_settings = true;
m_ui.setupUi(this);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
m_interface_settings = new InterfaceSettingsWidget(m_ui.settingsContainer, this);
m_game_list_settings = new GameListSettingsWidget(m_ui.settingsContainer, this);
m_bios_settings = new BIOSSettingsWidget(m_ui.settingsContainer, this);
m_emulation_settings = new EmulationSettingsWidget(m_ui.settingsContainer, this);
m_system_settings = new SystemSettingsWidget(m_ui.settingsContainer, this);
m_advanced_system_settings = new AdvancedSystemSettingsWidget(m_ui.settingsContainer, this);
m_game_fix_settings_widget = new GameFixSettingsWidget(m_ui.settingsContainer, this);
m_graphics_settings = new GraphicsSettingsWidget(m_ui.settingsContainer, this);
// We don't include interface/game list/bios settings from per-game settings.
if (!isPerGameSettings())
{
addWidget(m_interface_settings = new InterfaceSettingsWidget(this, m_ui.settingsContainer), tr("Interface"),
QStringLiteral("settings-3-line"),
tr("<strong>Interface Settings</strong><hr>These options control how the software looks and behaves.<br><br>Mouse over an option for "
"additional information."));
addWidget(m_game_list_settings = new GameListSettingsWidget(this, m_ui.settingsContainer), tr("Game List"),
QStringLiteral("folder-settings-line"),
tr("<strong>Game List Settings</strong><hr>The list above shows the directories which will be searched by PCSX2 to populate the game "
"list. Search directories can be added, removed, and switched to recursive/non-recursive."));
addWidget(m_bios_settings = new BIOSSettingsWidget(this, m_ui.settingsContainer), tr("BIOS"), QStringLiteral("hard-drive-2-line"),
tr("<strong>BIOS Settings</strong><hr>"));
}
else
{
if (game)
{
addWidget(new GameSummaryWidget(game, this, m_ui.settingsContainer), tr("Summary"), QStringLiteral("file-list-line"),
tr("<strong>Summary</strong><hr>Eventually this will be where we can see patches and compute hashes/verify dumps/etc."));
}
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::InterfaceSettings), m_interface_settings);
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::GameListSettings), m_game_list_settings);
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::BIOSSettings), m_bios_settings);
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::EmulationSettings), m_emulation_settings);
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::SystemSettings), m_system_settings);
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::AdvancedSystemSettings), m_advanced_system_settings);
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::GameFixSettings), m_game_fix_settings_widget);
m_ui.settingsContainer->insertWidget(static_cast<int>(Category::GraphicsSettings), m_graphics_settings);
// remove the preset buttons. but we might want to enable these in the future.
m_ui.restoreDefaultsButton->setVisible(false);
m_ui.settingsPreset->setVisible(false);
}
// Common to both per-game and global settings.
addWidget(m_emulation_settings = new EmulationSettingsWidget(this, m_ui.settingsContainer), tr("Emulation"), QStringLiteral("dashboard-line"),
tr("<strong>Emulation Settings</strong><hr>"));
addWidget(m_system_settings = new SystemSettingsWidget(this, m_ui.settingsContainer), tr("System"), QStringLiteral("artboard-2-line"),
tr("<strong>System Settings</strong><hr>These options determine the configuration of the simulated console.<br><br>Mouse over an option for "
"additional information."));
if (show_advanced_settings)
{
addWidget(m_advanced_system_settings = new AdvancedSystemSettingsWidget(this, m_ui.settingsContainer), tr("Advanced System"),
QStringLiteral("artboard-2-line"), tr("<strong>Advanced System Settings</strong><hr>"));
// Only show the game fixes for per-game settings, there's really no reason to be setting them globally.
if (isPerGameSettings())
{
addWidget(m_game_fix_settings_widget = new GameFixSettingsWidget(this, m_ui.settingsContainer), tr("Game Fix"),
QStringLiteral("close-line"), tr("<strong>Game Fix Settings</strong><hr>"));
}
}
addWidget(m_graphics_settings = new GraphicsSettingsWidget(this, m_ui.settingsContainer), tr("Graphics"), QStringLiteral("brush-line"),
tr("<strong>Graphics Settings</strong><hr>"));
addWidget(new QWidget(m_ui.settingsContainer), tr("Audio"), QStringLiteral("volume-up-line"),
tr("<strong>Audio Settings</strong><hr>These options control the audio output of the console. Mouse over an option for additional "
"information."));
addWidget(
new QWidget(m_ui.settingsContainer), tr("Memory Cards"), QStringLiteral("sd-card-line"), tr("<strong>Memory Card Settings</strong><hr>"));
m_ui.settingsCategory->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
m_ui.settingsCategory->setCurrentRow(0);
@@ -68,37 +129,37 @@ SettingsDialog::SettingsDialog(QWidget* parent /* = nullptr */)
connect(m_ui.restoreDefaultsButton, &QPushButton::clicked, this, &SettingsDialog::onRestoreDefaultsClicked);
}
SettingsDialog::~SettingsDialog() = default;
void SettingsDialog::setCategoryHelpTexts()
SettingsDialog::~SettingsDialog()
{
m_category_help_text[static_cast<int>(Category::InterfaceSettings)] =
tr("<strong>Interface Settings</strong><hr>These options control how the software looks and behaves.<br><br>Mouse "
"over "
"an option for additional information.");
m_category_help_text[static_cast<int>(Category::SystemSettings)] =
tr("<strong>System Settings</strong><hr>These options determine the configuration of the simulated "
"console.<br><br>Mouse over an option for additional information.");
m_category_help_text[static_cast<int>(Category::GameListSettings)] =
tr("<strong>Game List Settings</strong><hr>The list above shows the directories which will be searched by "
"PCSX2 to populate the game list. Search directories can be added, removed, and switched to "
"recursive/non-recursive.");
m_category_help_text[static_cast<int>(Category::AudioSettings)] =
tr("<strong>Audio Settings</strong><hr>These options control the audio output of the console. Mouse over an option "
"for additional information.");
if (isPerGameSettings())
s_open_game_properties_dialogs.removeOne(this);
}
void SettingsDialog::setCategory(Category category)
void SettingsDialog::closeEvent(QCloseEvent*)
{
if (category >= Category::Count)
return;
// we need to clean up ourselves, since we're not modal
if (isPerGameSettings())
deleteLater();
}
m_ui.settingsCategory->setCurrentRow(static_cast<int>(category));
void SettingsDialog::setCategory(const char* category)
{
// the titles in the category list will be translated.
const QString translated_category(qApp->translate("SettingsDialog", category));
for (int i = 0; i < m_ui.settingsCategory->count(); i++)
{
if (translated_category == m_ui.settingsCategory->item(i)->text())
{
// will also update the visible widget
m_ui.settingsCategory->setCurrentRow(i);
break;
}
}
}
void SettingsDialog::onCategoryCurrentRowChanged(int row)
{
Q_ASSERT(row < static_cast<int>(Category::Count));
m_ui.settingsContainer->setCurrentIndex(row);
m_ui.helpText->setText(m_category_help_text[row]);
}
@@ -106,8 +167,8 @@ void SettingsDialog::onCategoryCurrentRowChanged(int row)
void SettingsDialog::onRestoreDefaultsClicked()
{
if (QMessageBox::question(this, tr("Confirm Restore Defaults"),
tr("Are you sure you want to restore the default settings? Any preferences will be lost."),
QMessageBox::Yes, QMessageBox::No) != QMessageBox::Yes)
tr("Are you sure you want to restore the default settings? Any preferences will be lost."), QMessageBox::Yes,
QMessageBox::No) != QMessageBox::Yes)
{
return;
}
@@ -115,6 +176,20 @@ void SettingsDialog::onRestoreDefaultsClicked()
// TODO
}
void SettingsDialog::addWidget(QWidget* widget, QString title, QString icon, QString help_text)
{
const int index = m_ui.settingsCategory->count();
QListWidgetItem* item = new QListWidgetItem(m_ui.settingsCategory);
item->setText(title);
if (!icon.isEmpty())
item->setIcon(QIcon::fromTheme(icon));
m_ui.settingsContainer->addWidget(widget);
m_category_help_text[index] = std::move(help_text);
}
void SettingsDialog::registerWidgetHelp(QObject* object, QString title, QString recommended_value, QString text)
{
// construct rich text with formatted description
@@ -153,4 +228,202 @@ bool SettingsDialog::eventFilter(QObject* object, QEvent* event)
}
return QDialog::eventFilter(object, event);
}
}
bool SettingsDialog::getEffectiveBoolValue(const char* section, const char* key, bool default_value) const
{
bool value;
if (m_sif && m_sif->GetBoolValue(section, key, &value))
return value;
else
return QtHost::GetBaseBoolSettingValue(section, key, default_value);
}
int SettingsDialog::getEffectiveIntValue(const char* section, const char* key, int default_value) const
{
int value;
if (m_sif && m_sif->GetIntValue(section, key, &value))
return value;
else
return QtHost::GetBaseIntSettingValue(section, key, default_value);
}
float SettingsDialog::getEffectiveFloatValue(const char* section, const char* key, float default_value) const
{
float value;
if (m_sif && m_sif->GetFloatValue(section, key, &value))
return value;
else
return QtHost::GetBaseFloatSettingValue(section, key, default_value);
}
std::string SettingsDialog::getEffectiveStringValue(const char* section, const char* key, const char* default_value) const
{
std::string value;
if (!m_sif || !m_sif->GetStringValue(section, key, &value))
value = QtHost::GetBaseStringSettingValue(section, key, default_value);
return value;
}
std::optional<bool> SettingsDialog::getBoolValue(const char* section, const char* key, std::optional<bool> default_value) const
{
std::optional<bool> value;
if (m_sif)
{
bool bvalue;
if (m_sif->GetBoolValue(section, key, &bvalue))
value = bvalue;
else
value = default_value;
}
else
{
value = QtHost::GetBaseBoolSettingValue(section, key, default_value.value_or(false));
}
return value;
}
std::optional<int> SettingsDialog::getIntValue(const char* section, const char* key, std::optional<int> default_value) const
{
std::optional<int> value;
if (m_sif)
{
int ivalue;
if (m_sif->GetIntValue(section, key, &ivalue))
value = ivalue;
else
value = default_value;
}
else
{
value = QtHost::GetBaseIntSettingValue(section, key, default_value.value_or(0));
}
return value;
}
std::optional<float> SettingsDialog::getFloatValue(const char* section, const char* key, std::optional<float> default_value) const
{
std::optional<float> value;
if (m_sif)
{
float fvalue;
if (m_sif->GetFloatValue(section, key, &fvalue))
value = fvalue;
else
value = default_value;
}
else
{
value = QtHost::GetBaseFloatSettingValue(section, key, default_value.value_or(0.0f));
}
return value;
}
std::optional<std::string> SettingsDialog::getStringValue(const char* section, const char* key, std::optional<const char*> default_value) const
{
std::optional<std::string> value;
if (m_sif)
{
std::string svalue;
if (m_sif->GetStringValue(section, key, &svalue))
value = std::move(svalue);
else if (default_value.has_value())
value = default_value.value();
}
else
{
value = QtHost::GetBaseStringSettingValue(section, key, default_value.value_or(""));
}
return value;
}
void SettingsDialog::setBoolSettingValue(const char* section, const char* key, std::optional<bool> value)
{
if (m_sif)
{
value.has_value() ? m_sif->SetBoolValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
m_sif->Save();
}
else
{
value.has_value() ? QtHost::SetBaseBoolSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key);
}
g_emu_thread->applySettings();
}
void SettingsDialog::setIntSettingValue(const char* section, const char* key, std::optional<int> value)
{
if (m_sif)
{
value.has_value() ? m_sif->SetIntValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
m_sif->Save();
}
else
{
value.has_value() ? QtHost::SetBaseIntSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key);
}
g_emu_thread->applySettings();
}
void SettingsDialog::setFloatSettingValue(const char* section, const char* key, std::optional<float> value)
{
if (m_sif)
{
value.has_value() ? m_sif->SetFloatValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
m_sif->Save();
}
else
{
value.has_value() ? QtHost::SetBaseFloatSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key);
}
g_emu_thread->applySettings();
}
void SettingsDialog::setStringSettingValue(const char* section, const char* key, std::optional<const char*> value)
{
if (m_sif)
{
value.has_value() ? m_sif->SetBoolValue(section, key, value.value()) : m_sif->DeleteValue(section, key);
m_sif->Save();
}
else
{
value.has_value() ? QtHost::SetBaseStringSettingValue(section, key, value.value()) : QtHost::RemoveBaseSettingValue(section, key);
}
g_emu_thread->applySettings();
}
void SettingsDialog::openGamePropertiesDialog(const GameList::Entry* game, u32 crc)
{
// check for an existing dialog with this crc
for (SettingsDialog* dialog : s_open_game_properties_dialogs)
{
if (dialog->m_game_crc == crc)
{
dialog->show();
dialog->setFocus();
return;
}
}
std::unique_ptr<INISettingsInterface> sif =
std::make_unique<INISettingsInterface>(Path::CombineStdString(EmuFolders::GameSettings, StringUtil::StdStringFromFormat("%08X.ini", crc)));
if (FileSystem::FileExists(sif->GetFileName().c_str()))
sif->Load();
const QString window_title(tr("%1 [%2]")
.arg(game ? QtUtils::StringViewToQString(game->title) : QStringLiteral("<UNKNOWN>"))
.arg(QtUtils::StringViewToQString(FileSystem::GetFileNameFromPath(sif->GetFileName()))));
SettingsDialog* dialog = new SettingsDialog(std::move(sif), game, crc);
dialog->setWindowTitle(window_title);
dialog->show();
}
+59 -31
View File
@@ -19,6 +19,14 @@
#include <QtCore/QString>
#include <QtWidgets/QDialog>
#include <array>
#include <memory>
class INISettingsInterface;
namespace GameList
{
struct Entry;
}
class InterfaceSettingsWidget;
class GameListSettingsWidget;
@@ -36,50 +44,68 @@ class SettingsDialog final : public QDialog
Q_OBJECT
public:
enum class Category
{
InterfaceSettings,
GameListSettings,
BIOSSettings,
EmulationSettings,
SystemSettings,
AdvancedSystemSettings,
GameFixSettings,
GraphicsSettings,
AudioSettings,
MemoryCardSettings,
Count
};
explicit SettingsDialog(QWidget* parent = nullptr);
explicit SettingsDialog(QWidget* parent);
SettingsDialog(std::unique_ptr<SettingsInterface> sif, const GameList::Entry* game, u32 game_crc);
~SettingsDialog();
InterfaceSettingsWidget* getInterfaceSettingsWidget() const { return m_interface_settings; }
GameListSettingsWidget* getGameListSettingsWidget() const { return m_game_list_settings; }
BIOSSettingsWidget* getBIOSSettingsWidget() const { return m_bios_settings; }
EmulationSettingsWidget* getEmulationSettingsWidget() const { return m_emulation_settings; }
SystemSettingsWidget* getSystemSettingsWidget() const { return m_system_settings; }
AdvancedSystemSettingsWidget* getAdvancedSystemSettingsWidget() const { return m_advanced_system_settings; }
GameFixSettingsWidget* getGameFixSettingsWidget() const { return m_game_fix_settings_widget; }
GraphicsSettingsWidget* getGraphicsSettingsWidget() const { return m_graphics_settings; }
AudioSettingsWidget* getAudioSettingsWidget() const { return m_audio_settings; }
MemoryCardSettingsWidget* getMemoryCardSettingsWidget() const { return m_memory_card_settings; }
static void openGamePropertiesDialog(const GameList::Entry* game, u32 crc);
__fi bool isPerGameSettings() const { return static_cast<bool>(m_sif); }
__fi SettingsInterface* getSettingsInterface() const { return m_sif.get(); }
__fi InterfaceSettingsWidget* getInterfaceSettingsWidget() const { return m_interface_settings; }
__fi GameListSettingsWidget* getGameListSettingsWidget() const { return m_game_list_settings; }
__fi BIOSSettingsWidget* getBIOSSettingsWidget() const { return m_bios_settings; }
__fi EmulationSettingsWidget* getEmulationSettingsWidget() const { return m_emulation_settings; }
__fi SystemSettingsWidget* getSystemSettingsWidget() const { return m_system_settings; }
__fi AdvancedSystemSettingsWidget* getAdvancedSystemSettingsWidget() const { return m_advanced_system_settings; }
__fi GameFixSettingsWidget* getGameFixSettingsWidget() const { return m_game_fix_settings_widget; }
__fi GraphicsSettingsWidget* getGraphicsSettingsWidget() const { return m_graphics_settings; }
__fi AudioSettingsWidget* getAudioSettingsWidget() const { return m_audio_settings; }
__fi MemoryCardSettingsWidget* getMemoryCardSettingsWidget() const { return m_memory_card_settings; }
void registerWidgetHelp(QObject* object, QString title, QString recommended_value, QString text);
bool eventFilter(QObject* object, QEvent* event) override;
void setCategory(const char* category);
// Helper functions for reading effective setting values (from game -> global settings).
bool getEffectiveBoolValue(const char* section, const char* key, bool default_value) const;
int getEffectiveIntValue(const char* section, const char* key, int default_value) const;
float getEffectiveFloatValue(const char* section, const char* key, float default_value) const;
std::string getEffectiveStringValue(const char* section, const char* key, const char* default_value) const;
// Helper functions for reading setting values for this layer (game settings or global).
std::optional<bool> getBoolValue(const char* section, const char* key, std::optional<bool> default_value) const;
std::optional<int> getIntValue(const char* section, const char* key, std::optional<int> default_value) const;
std::optional<float> getFloatValue(const char* section, const char* key, std::optional<float> default_value) const;
std::optional<std::string> getStringValue(const char* section, const char* key, std::optional<const char*> default_value) const;
void setBoolSettingValue(const char* section, const char* key, std::optional<bool> value);
void setIntSettingValue(const char* section, const char* key, std::optional<int> value);
void setFloatSettingValue(const char* section, const char* key, std::optional<float> value);
void setStringSettingValue(const char* section, const char* key, std::optional<const char*> value);
Q_SIGNALS:
void settingsResetToDefaults();
public Q_SLOTS:
void setCategory(Category category);
private Q_SLOTS:
void onCategoryCurrentRowChanged(int row);
void onRestoreDefaultsClicked();
protected:
void closeEvent(QCloseEvent*) override;
private:
void setCategoryHelpTexts();
enum : u32
{
MAX_SETTINGS_WIDGETS = 10
};
void setupUi(const GameList::Entry* game);
void addWidget(QWidget* widget, QString title, QString icon, QString help_text);
std::unique_ptr<SettingsInterface> m_sif;
Ui::SettingsDialog m_ui;
@@ -94,8 +120,10 @@ private:
AudioSettingsWidget* m_audio_settings = nullptr;
MemoryCardSettingsWidget* m_memory_card_settings = nullptr;
std::array<QString, static_cast<int>(Category::Count)> m_category_help_text;
std::array<QString, MAX_SETTINGS_WIDGETS> m_category_help_text;
QObject* m_current_help_widget = nullptr;
QMap<QObject*, QString> m_widget_help_text_map;
u32 m_game_crc;
};
+5 -90
View File
@@ -9,12 +9,12 @@
<rect>
<x>0</x>
<y>0</y>
<width>780</width>
<height>650</height>
<width>800</width>
<height>500</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -26,7 +26,7 @@
<item row="0" column="0">
<widget class="QListWidget" name="settingsCategory">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -49,86 +49,6 @@
<height>32</height>
</size>
</property>
<item>
<property name="text">
<string>Interface</string>
</property>
<property name="icon">
<iconset theme="settings-3-line"/>
</property>
</item>
<item>
<property name="text">
<string>Game List</string>
</property>
<property name="icon">
<iconset theme="folder-settings-line"/>
</property>
</item>
<item>
<property name="text">
<string>BIOS</string>
</property>
<property name="icon">
<iconset theme="hard-drive-2-line"/>
</property>
</item>
<item>
<property name="text">
<string>Emulation</string>
</property>
<property name="icon">
<iconset theme="dashboard-line"/>
</property>
</item>
<item>
<property name="text">
<string>System</string>
</property>
<property name="icon">
<iconset theme="artboard-2-line"/>
</property>
</item>
<item>
<property name="text">
<string>Advanced System</string>
</property>
<property name="icon">
<iconset theme="artboard-2-line"/>
</property>
</item>
<item>
<property name="text">
<string>Game Fixes</string>
</property>
<property name="icon">
<iconset theme="close-line"/>
</property>
</item>
<item>
<property name="text">
<string>Graphics</string>
</property>
<property name="icon">
<iconset theme="brush-line"/>
</property>
</item>
<item>
<property name="text">
<string>Audio</string>
</property>
<property name="icon">
<iconset theme="volume-up-line"/>
</property>
</item>
<item>
<property name="text">
<string>Memory Cards</string>
</property>
<property name="icon">
<iconset theme="sd-card-line"/>
</property>
</item>
</widget>
</item>
<item row="0" column="1">
@@ -139,11 +59,6 @@
<height>0</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page"/>
<widget class="QWidget" name="page_2"/>
</widget>
</item>
<item row="1" column="0" colspan="2">
@@ -151,7 +66,7 @@
<property name="minimumSize">
<size>
<width>0</width>
<height>120</height>
<height>100</height>
</size>
</property>
<property name="maximumSize">
+77 -26
View File
@@ -29,33 +29,49 @@ static constexpr int MAXIMUM_EE_CYCLE_RATE = 3;
static constexpr int DEFAULT_EE_CYCLE_RATE = 0;
static constexpr int DEFAULT_EE_CYCLE_SKIP = 0;
SystemSettingsWidget::SystemSettingsWidget(QWidget* parent, SettingsDialog* dialog)
SystemSettingsWidget::SystemSettingsWidget(SettingsDialog* dialog, QWidget* parent)
: QWidget(parent)
, m_dialog(dialog)
{
SettingsInterface* sif = dialog->getSettingsInterface();
m_ui.setupUi(this);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.eeRoundingMode, "EmuCore/CPU", "FPU.Roundmode", 3);
m_ui.eeClampMode->setCurrentIndex(getClampingModeIndex(false));
connect(m_ui.eeClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged),
[this](int index) { setClampingMode(false, index); });
m_ui.eeCycleRate->setCurrentIndex(
std::clamp(QtHost::GetBaseIntSettingValue("EmuCore/Speedhacks", "EECycleRate", DEFAULT_EE_CYCLE_RATE),
MINIMUM_EE_CYCLE_RATE, MAXIMUM_EE_CYCLE_RATE) +
(0 - MINIMUM_EE_CYCLE_RATE));
connect(m_ui.eeCycleRate, QOverload<int>::of(&QComboBox::currentIndexChanged), [](int index) {
QtHost::SetBaseIntSettingValue("EmuCore/Speedhacks", "EECycleRate", MINIMUM_EE_CYCLE_RATE + index);
g_emu_thread->applySettings();
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeCycleSkipping, "EmuCore/Speedhacks", "EECycleSkip", DEFAULT_EE_CYCLE_SKIP);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.MTVU, "EmuCore/Speedhacks", "vuThread", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.instantVU1, "EmuCore/Speedhacks", "vu1Instant", true);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.eeRoundingMode, "EmuCore/CPU", "FPU.Roundmode", 3);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.vuRoundingMode, "EmuCore/CPU", "VU.Roundmode", 3);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fastCDVD, "EmuCore/Speedhacks", "fastCDVD", false);
if (m_dialog->isPerGameSettings())
{
m_ui.eeCycleRate->insertItem(
0, tr("Use Global Setting [%1]")
.arg(m_ui.eeCycleRate->itemText(
std::clamp(QtHost::GetBaseIntSettingValue("EmuCore/Speedhacks", "EECycleRate", DEFAULT_EE_CYCLE_RATE) - MINIMUM_EE_CYCLE_RATE,
0, MAXIMUM_EE_CYCLE_RATE - MINIMUM_EE_CYCLE_RATE))));
m_ui.eeClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.eeClampMode->itemText(getGlobalClampingModeIndex(false))));
m_ui.vuClampMode->insertItem(0, tr("Use Global Setting [%1]").arg(m_ui.vuClampMode->itemText(getGlobalClampingModeIndex(true))));
}
const std::optional<int> cycle_rate =
m_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>(m_dialog->isPerGameSettings())) :
0);
connect(m_ui.eeCycleRate, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
std::optional<int> value;
if (!m_dialog->isPerGameSettings() || index > 0)
value = MINIMUM_EE_CYCLE_RATE + index - static_cast<int>(m_dialog->isPerGameSettings());
m_dialog->setIntSettingValue("EmuCore/Speedhacks", "EECycleRate", value);
});
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.eeCycleSkipping, "EmuCore/Speedhacks", "EECycleSkip", 0);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.MTVU, "EmuCore/Speedhacks", "vuThread", false);
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.instantVU1, "EmuCore/Speedhacks", "vu1Instant", true);
SettingWidgetBinder::BindWidgetToIntSetting(m_ui.vuRoundingMode, "EmuCore/CPU", "VU.Roundmode", 3);
m_ui.eeClampMode->setCurrentIndex(getClampingModeIndex(false));
m_ui.vuClampMode->setCurrentIndex(getClampingModeIndex(true));
connect(m_ui.vuClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged),
[this](int index) { setClampingMode(true, index); });
SettingWidgetBinder::BindWidgetToBoolSetting(m_ui.fastCDVD, "EmuCore/Speedhacks", "fastCDVD", false);
connect(m_ui.eeClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(false, index); });
connect(m_ui.vuClampMode, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index) { setClampingMode(true, index); });
updateVU1InstantState();
connect(m_ui.MTVU, &QCheckBox::stateChanged, this, &SystemSettingsWidget::updateVU1InstantState);
@@ -65,24 +81,59 @@ SystemSettingsWidget::~SystemSettingsWidget() = default;
void SystemSettingsWidget::updateVU1InstantState()
{
m_ui.instantVU1->setEnabled(!m_ui.MTVU->isChecked());
m_ui.instantVU1->setEnabled(!m_dialog->getEffectiveBoolValue("EmuCore/Speedhacks", "vuThread", false));
}
int SystemSettingsWidget::getClampingModeIndex(bool vu)
int SystemSettingsWidget::getGlobalClampingModeIndex(bool vu) const
{
if (QtHost::GetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", false))
return 3;
if (QtHost::GetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", false))
return 2;
if (QtHost::GetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", true))
return 1;
return 0;
}
int SystemSettingsWidget::getClampingModeIndex(bool vu) const
{
// This is so messy... maybe we should just make the mode an int in the settings too...
const bool base = m_dialog->isPerGameSettings() ? 1 : 0;
std::optional<bool> default_false = m_dialog->isPerGameSettings() ? std::nullopt : std::optional<bool>(false);
std::optional<bool> default_true = m_dialog->isPerGameSettings() ? std::nullopt : std::optional<bool>(true);
std::optional<bool> third = m_dialog->getBoolValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", default_false);
std::optional<bool> second = m_dialog->getBoolValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", default_false);
std::optional<bool> first = m_dialog->getBoolValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", default_true);
if (third.has_value() && third.value())
return base + 3;
if (second.has_value() && second.value())
return base + 2;
if (first.has_value() && first.value())
return base + 1;
else if (first.has_value())
return base + 0; // none
else
return 0; // no per game override
}
void SystemSettingsWidget::setClampingMode(bool vu, int index)
{
QtHost::SetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", (index >= 3));
QtHost::SetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", (index >= 2));
QtHost::SetBaseBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", (index >= 1));
g_emu_thread->applySettings();
std::optional<bool> first, second, third;
if (!m_dialog->isPerGameSettings() || index > 0)
{
const bool base = m_dialog->isPerGameSettings() ? 1 : 0;
third = (index >= (base + 3));
second = (index >= (base + 2));
first = (index >= (base + 1));
}
m_dialog->setBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuSignOverflow" : "fpuFullMode", third);
m_dialog->setBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuExtraOverflow" : "fpuExtraOverflow", second);
m_dialog->setBoolSettingValue("EmuCore/CPU/Recompiler", vu ? "vuOverflow" : "fpuOverflow", first);
}
+6 -3
View File
@@ -26,15 +26,18 @@ class SystemSettingsWidget : public QWidget
Q_OBJECT
public:
SystemSettingsWidget(QWidget* parent, SettingsDialog* dialog);
SystemSettingsWidget(SettingsDialog* dialog, QWidget* parent);
~SystemSettingsWidget();
private Q_SLOTS:
void updateVU1InstantState();
private:
static int getClampingModeIndex(bool vu);
static void setClampingMode(bool vu, int index);
int getGlobalClampingModeIndex(bool vu) const;
int getClampingModeIndex(bool vu) const;
void setClampingMode(bool vu, int index);
SettingsDialog* m_dialog;
Ui::SystemSettingsWidget m_ui;
};
+2 -2
View File
@@ -135,7 +135,7 @@
</item>
<item>
<property name="text">
<string>Chop/Zero (Default)</string>
<string>Chop / Zero (Default)</string>
</property>
</item>
</widget>
@@ -206,7 +206,7 @@
</item>
<item>
<property name="text">
<string>Chop/Zero (Default)</string>
<string>Chop / Zero (Default)</string>
</property>
</item>
</widget>
+18
View File
@@ -164,6 +164,9 @@
<ClCompile Include="Settings\InputBindingDialog.cpp" />
<ClCompile Include="Settings\InputBindingWidget.cpp" />
<ClCompile Include="Settings\ControllerSettingsDialog.cpp" />
<ClCompile Include="Settings\AudioSettingsWidget.cpp" />
<ClCompile Include="Settings\MemoryCardSettingsWidget.cpp" />
<ClCompile Include="Settings\GameSummaryWidget.cpp" />
<ClCompile Include="GameList\GameListModel.cpp" />
<ClCompile Include="GameList\GameListRefreshThread.cpp" />
<ClCompile Include="GameList\GameListWidget.cpp" />
@@ -193,6 +196,9 @@
<QtMoc Include="Settings\InputBindingDialog.h" />
<QtMoc Include="Settings\InputBindingWidget.h" />
<QtMoc Include="Settings\ControllerSettingsDialog.h" />
<QtMoc Include="Settings\AudioSettingsWidget.h" />
<QtMoc Include="Settings\MemoryCardSettingsWidget.h" />
<QtMoc Include="Settings\GameSummaryWidget.h" />
<QtMoc Include="GameList\GameListModel.h" />
<QtMoc Include="GameList\GameListWidget.h" />
<QtMoc Include="GameList\GameListRefreshThread.h" />
@@ -228,6 +234,9 @@
<ClCompile Include="$(IntDir)Settings\moc_HotkeySettingsWidget.cpp" />
<ClCompile Include="$(IntDir)Settings\moc_InputBindingDialog.cpp" />
<ClCompile Include="$(IntDir)Settings\moc_InputBindingWidget.cpp" />
<ClCompile Include="$(IntDir)Settings\moc_AudioSettingsWidget.cpp" />
<ClCompile Include="$(IntDir)Settings\moc_MemoryCardSettingsWidget.cpp" />
<ClCompile Include="$(IntDir)Settings\moc_GameSummaryWidget.cpp" />
<ClCompile Include="$(IntDir)GameList\moc_GameListModel.cpp" />
<ClCompile Include="$(IntDir)GameList\moc_GameListRefreshThread.cpp" />
<ClCompile Include="$(IntDir)GameList\moc_GameListWidget.cpp" />
@@ -285,6 +294,15 @@
<QtUi Include="Settings\ControllerGlobalSettingsWidget.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="Settings\AudioSettingsWidget.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="Settings\MemoryCardSettingsWidget.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="Settings\GameSummaryWidget.ui">
<FileType>Document</FileType>
</QtUi>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="$(SolutionDir)common\vsprops\QtCompile.targets" />
+37 -1
View File
@@ -173,9 +173,27 @@
<ClCompile Include="Settings\ControllerGlobalSettingsWidget.cpp">
<Filter>Settings</Filter>
</ClCompile>
<ClCompile Include="x64\Devel\Settings\moc_ControllerGlobalSettingsWidget.cpp">
<ClCompile Include="$(IntDir)Settings\moc_MemoryCardSettingsWidget.cpp">
<Filter>moc</Filter>
</ClCompile>
<ClCompile Include="$(IntDir)Settings\moc_ControllerGlobalSettingsWidget.cpp">
<Filter>moc</Filter>
</ClCompile>
<ClCompile Include="$(IntDir)Settings\moc_GameSummaryWidget.cpp">
<Filter>moc</Filter>
</ClCompile>
<ClCompile Include="$(IntDir)Settings\moc_AudioSettingsWidget.cpp">
<Filter>moc</Filter>
</ClCompile>
<ClCompile Include="Settings\GameSummaryWidget.cpp">
<Filter>Settings</Filter>
</ClCompile>
<ClCompile Include="Settings\MemoryCardSettingsWidget.cpp">
<Filter>Settings</Filter>
</ClCompile>
<ClCompile Include="Settings\AudioSettingsWidget.cpp">
<Filter>Settings</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Manifest Include="..\pcsx2\windows\PCSX2.manifest">
@@ -247,6 +265,15 @@
<QtMoc Include="Settings\ControllerGlobalSettingsWidget.h">
<Filter>Settings</Filter>
</QtMoc>
<QtMoc Include="Settings\GameSummaryWidget.h">
<Filter>Settings</Filter>
</QtMoc>
<QtMoc Include="Settings\MemoryCardSettingsWidget.h">
<Filter>Settings</Filter>
</QtMoc>
<QtMoc Include="Settings\AudioSettingsWidget.h">
<Filter>Settings</Filter>
</QtMoc>
</ItemGroup>
<ItemGroup>
<QtResource Include="resources\resources.qrc">
@@ -297,5 +324,14 @@
<QtUi Include="Settings\ControllerGlobalSettingsWidget.ui">
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="Settings\GameSummaryWidget.ui">
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="Settings\MemoryCardSettingsWidget.ui">
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="Settings\AudioSettingsWidget.ui">
<Filter>Settings</Filter>
</QtUi>
</ItemGroup>
</Project>
Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1006 B

+2
View File
@@ -203,9 +203,11 @@
<file>icons/black/64/window-2-line.png</file>
<file>icons/black/index.theme</file>
<file>icons/discord.png</file>
<file>icons/flag-cn.png</file>
<file>icons/flag-eu.png</file>
<file>icons/flag-eu.svg</file>
<file>icons/flag-eu@2x.png</file>
<file>icons/flag-hk.png</file>
<file>icons/flag-jp.png</file>
<file>icons/flag-jp.svg</file>
<file>icons/flag-jp@2x.png</file>
+11 -10
View File
@@ -376,6 +376,7 @@ set(pcsx2DEV9Headers
DEV9/ATA/ATA.h
DEV9/ATA/HddCreate.h
DEV9/DEV9.h
DEV9/DEV9Config.h
DEV9/InternalServers/DHCP_Server.cpp
DEV9/InternalServers/DNS_Logger.h
DEV9/InternalServers/DNS_Server.h
@@ -657,6 +658,8 @@ set(pcsx2GSSources
GS/Renderers/HW/GSRendererHW.cpp
GS/Renderers/HW/GSRendererNew.cpp
GS/Renderers/HW/GSTextureCache.cpp
GS/Renderers/HW/GSTextureReplacementLoaders.cpp
GS/Renderers/HW/GSTextureReplacements.cpp
GS/Renderers/SW/GSDrawScanline.cpp
GS/Renderers/SW/GSDrawScanlineCodeGenerator.cpp
GS/Renderers/SW/GSDrawScanlineCodeGenerator.all.cpp
@@ -721,6 +724,7 @@ set(pcsx2GSHeaders
GS/Renderers/HW/GSRendererHW.h
GS/Renderers/HW/GSRendererNew.h
GS/Renderers/HW/GSTextureCache.h
GS/Renderers/HW/GSTextureReplacements.h
GS/Renderers/HW/GSVertexHW.h
GS/Renderers/SW/GSDrawScanlineCodeGenerator.h
GS/Renderers/SW/GSDrawScanlineCodeGenerator.all.h
@@ -780,9 +784,6 @@ if(PCSX2_CORE)
list(APPEND pcsx2SPU2Headers
SPU2/WavFile.cpp
)
list(APPEND pcsx2DEV9Sources
DEV9/Linux/Config.cpp
)
endif()
elseif(WIN32)
list(APPEND pcsx2SPU2Sources
@@ -803,7 +804,6 @@ elseif(WIN32)
)
list(APPEND pcsx2DEV9Sources
DEV9/Win32/DEV9WinConfig.cpp
DEV9/Win32/pcap_io_win32.cpp
DEV9/Win32/tap-win32.cpp
)
@@ -874,10 +874,6 @@ else()
SPU2/wx/wxConfig.h
)
list(APPEND pcsx2DEV9Sources
DEV9/Linux/Config.cpp
)
list(APPEND pcsx2USBSources
USB/icon_buzz_24.cpp
USB/linux/config-gtk.cpp
@@ -1344,6 +1340,7 @@ set(pcsx2x86Sources
x86/iMMI.cpp
x86/iR3000A.cpp
x86/iR3000Atables.cpp
x86/iR5900Analysis.cpp
x86/iR5900Misc.cpp
x86/ir5900tables.cpp
x86/ix86-32/iCore-32.cpp
@@ -1375,6 +1372,7 @@ set(pcsx2x86Headers
x86/iR5900AritImm.h
x86/iR5900Branch.h
x86/iR5900.h
x86/iR5900Analysis.h
x86/iR5900Jump.h
x86/iR5900LoadStore.h
x86/iR5900Move.h
@@ -1566,18 +1564,17 @@ if(WIN32)
elseif(APPLE)
target_link_libraries(PCSX2_FLAGS INTERFACE
PCAP::PCAP
LibXml2::LibXml2
)
else()
if (NOT PCSX2_CORE)
target_link_libraries(PCSX2_FLAGS INTERFACE
GTK::gtk
HarfBuzz::HarfBuzz
)
endif()
target_link_libraries(PCSX2_FLAGS INTERFACE
OpenGL::GL
PCAP::PCAP
LibXml2::LibXml2
)
endif()
@@ -1633,6 +1630,10 @@ function(pcsx2_resource path basedir)
set_source_files_properties(${path} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/${subdir})
elseif(PACKAGE_MODE)
install(FILES ${path} DESTINATION ${CMAKE_INSTALL_DATADIR}/PCSX2/resources/${subdir})
else()
add_custom_command(TARGET PCSX2 POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E make_directory "$<TARGET_FILE_DIR:PCSX2>/resources/${subdir}"
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${path}" "$<TARGET_FILE_DIR:PCSX2>/resources/${subdir}")
endif()
source_group(Resources/${subdir} FILES ${path})
endfunction()
+94 -4
View File
@@ -42,7 +42,7 @@ enum GamefixId
Fix_VIF1Stall,
Fix_VuAddSub,
Fix_Ibit,
Fix_VUKickstart,
Fix_VUSync,
Fix_VUOverflow,
Fix_XGKick,
@@ -179,6 +179,13 @@ enum class AccBlendLevel : u8
Ultra,
};
enum class TexturePreloadingLevel : u8
{
Off,
Partial,
Full,
};
// Template function for casting enumerations to their underlying type
template <typename Enumeration>
typename std::underlying_type<Enumeration>::type enum_cast(Enumeration E)
@@ -421,7 +428,8 @@ struct Pcsx2Config
OsdShowFPS : 1,
OsdShowCPU : 1,
OsdShowResolution : 1,
OsdShowGSStats : 1;
OsdShowGSStats : 1,
OsdShowIndicators : 1;
bool
HWDisableReadbacks : 1,
@@ -451,7 +459,12 @@ struct Pcsx2Config
SaveFrame : 1,
SaveTexture : 1,
SaveDepth : 1,
PreloadTexture : 1;
DumpReplaceableTextures : 1,
DumpReplaceableMipmaps : 1,
DumpTexturesWithFMVActive : 1,
LoadTextureReplacements : 1,
LoadTextureReplacementsAsync : 1,
PrecacheTextureReplacements : 1;
};
};
@@ -490,6 +503,7 @@ struct Pcsx2Config
AccBlendLevel AccurateBlendingUnit{AccBlendLevel::Basic};
CRCHackLevel CRCHack{CRCHackLevel::Automatic};
BiFiltering TextureFiltering{BiFiltering::PS2};
TexturePreloadingLevel TexturePreloading{TexturePreloadingLevel::Off};
int Dithering{2};
int MaxAnisotropy{0};
int SWExtraThreads{2};
@@ -619,6 +633,80 @@ struct Pcsx2Config
}
};
struct DEV9Options
{
enum struct NetApi : int
{
Unset = 0,
PCAP_Bridged = 1,
PCAP_Switched = 2,
TAP = 3,
};
static const char* NetApiNames[];
bool EthEnable{false};
NetApi EthApi{NetApi::Unset};
std::string EthDevice;
bool EthLogDNS{false};
bool InterceptDHCP{false};
u8 PS2IP[4]{};
u8 Mask[4]{};
u8 Gateway[4]{};
u8 DNS1[4]{};
u8 DNS2[4]{};
bool AutoMask{true};
bool AutoGateway{true};
bool AutoDNS1{true};
bool AutoDNS2{true};
bool HddEnable{false};
std::string HddFile;
/* The PS2's HDD max size is 2TB
* which is 2^32 * 512 byte sectors
* Note that we don't yet support
* 48bit LBA, so our limit is lower */
uint HddSizeSectors{0};
DEV9Options();
void LoadSave(SettingsWrapper& wrap);
bool operator==(const DEV9Options& right) const
{
return OpEqu(EthEnable) &&
OpEqu(EthApi) &&
OpEqu(EthDevice) &&
OpEqu(EthLogDNS) &&
OpEqu(InterceptDHCP) &&
(*(int*)PS2IP == *(int*)right.PS2IP) &&
(*(int*)Gateway == *(int*)right.Gateway) &&
(*(int*)DNS1 == *(int*)right.DNS1) &&
(*(int*)DNS2 == *(int*)right.DNS2) &&
OpEqu(AutoMask) &&
OpEqu(AutoGateway) &&
OpEqu(AutoDNS1) &&
OpEqu(AutoDNS2) &&
OpEqu(HddEnable) &&
OpEqu(HddFile) &&
OpEqu(HddSizeSectors);
}
bool operator!=(const DEV9Options& right) const
{
return !this->operator==(right);
}
protected:
static void LoadIPHelper(u8* field, const std::string& setting);
static std::string SaveIPHelper(u8* field);
};
// ------------------------------------------------------------------------
// NOTE: The GUI's GameFixes panel is dependent on the order of bits in this structure.
struct GamefixOptions
@@ -638,7 +726,7 @@ struct Pcsx2Config
VIF1StallHack : 1, // Like above, processes FIFO data before the stall is allowed (to make sure data goes over).
VuAddSubHack : 1, // Tri-ace games, they use an encryption algorithm that requires VU ADDI opcode to be bit-accurate.
IbitHack : 1, // I bit hack. Needed to stop constant VU recompilation in some games
VUKickstartHack : 1, // Gives new VU programs a slight head start and runs VU's ahead of EE to avoid VU register reading/writing issues
VUSyncHack : 1, // Makes microVU run behind the EE to avoid VU register reading/writing sync issues. Useful for M-Bit games
VUOverflowHack : 1, // Tries to simulate overflow flag checks (not really possible on x86 without soft floats)
XgKickHack : 1; // Erementar Gerad, adds more delay to VU XGkick instructions. Corrects the color of some graphics, but breaks Tri-ace games and others.
BITFIELD_END
@@ -819,6 +907,7 @@ struct Pcsx2Config
DebugOptions Debugger;
FramerateOptions Framerate;
SPU2Options SPU2;
DEV9Options DEV9;
TraceLogFilters Trace;
@@ -878,6 +967,7 @@ namespace EmuFolders
extern wxDirName Cache;
extern wxDirName Covers;
extern wxDirName GameSettings;
extern wxDirName Textures;
// Assumes that AppRoot and DataRoot have been initialized.
void SetDefaults();
+2 -3
View File
@@ -20,7 +20,6 @@
#include <atomic>
#include <mutex>
#include <condition_variable>
#include <ghc/filesystem.h>
#include <fstream>
#include "DEV9/SimpleQueue.h"
@@ -154,7 +153,7 @@ private:
public:
ATA();
int Open(ghc::filesystem::path hddPath);
int Open(fs::path hddPath);
void Close();
void ATA_HardReset();
@@ -172,7 +171,7 @@ public:
private:
//Info
void CreateHDDinfo(int sizeMb);
void CreateHDDinfo(u64 sizeSectors);
void CreateHDDinfoCsum();
//State
+3 -3
View File
@@ -44,11 +44,11 @@ void ATA::WritePaddedString(u8* data, int* index, std::string value, u32 len)
*index += len;
}
void ATA::CreateHDDinfo(int sizeMb)
void ATA::CreateHDDinfo(u64 sizeSectors)
{
const u16 sectorSize = 512;
DevCon.WriteLn("DEV9: HddSize : %i", config.HddSize);
const u64 nbSectors = ((u64)(sizeMb / sectorSize) * 1024 * 1024);
DevCon.WriteLn("DEV9: HddSize : %i", sizeSectors * sectorSize / (1024 * 1024));
const u64 nbSectors = sizeSectors;
DevCon.WriteLn("DEV9: nbSectors : %i", nbSectors);
memset(&identifyData, 0, sizeof(identifyData));
+6 -6
View File
@@ -26,25 +26,25 @@ ATA::ATA()
ResetEnd(true);
}
int ATA::Open(ghc::filesystem::path hddPath)
int ATA::Open(fs::path hddPath)
{
readBufferLen = 256 * 512;
readBuffer = new u8[readBufferLen];
CreateHDDinfo(config.HddSize);
CreateHDDinfo(EmuConfig.DEV9.HddSizeSectors);
//Open File
if (!ghc::filesystem::exists(hddPath))
if (!fs::exists(hddPath))
{
HddCreate hddCreator;
hddCreator.filePath = hddPath;
hddCreator.neededSize = config.HddSize;
hddCreator.neededSize = ((u64)EmuConfig.DEV9.HddSizeSectors) * 512;
hddCreator.Start();
if (hddCreator.errored)
return -1;
}
hddImage = ghc::filesystem::fstream(hddPath, std::ios::in | std::ios::out | std::ios::binary);
hddImage = fs::fstream(hddPath, std::ios::in | std::ios::out | std::ios::binary);
//Store HddImage size for later check
hddImage.seekg(0, std::ios::end);
@@ -396,7 +396,7 @@ bool ATA::HDD_CanAccess(int* sectors)
s64 posEnd;
s64 maxLBA;
maxLBA = std::min<s64>((s64)config.HddSize * 1024 * 1024 / 512, hddImageSize);
maxLBA = std::min<s64>(EmuConfig.DEV9.HddSizeSectors, hddImageSize / 512) - 1;
if ((regSelect & 0x40) == 0) //CHS mode
maxLBA = std::min<s64>(maxLBA, curCylinders * curHeads * curSectors);
+1 -1
View File
@@ -73,7 +73,7 @@ void ATA::HDD_IdentifyDevice()
DevCon.WriteLn("DEV9: HddidentifyDevice");
//IDE transfer start
CreateHDDinfo(config.HddSize);
CreateHDDinfo(EmuConfig.DEV9.HddSizeSectors);
pioDRQEndTransferFunc = nullptr;
DRQCmdPIODataToHost(identifyData, 256 * 2, 0, 256 * 2, true);
+35 -13
View File
@@ -32,8 +32,13 @@ void HddCreate::Start()
return;
}
#endif
int reqMiB = (neededSize + ((1024 * 1024) - 1)) / (1024 * 1024);
#ifndef PCSX2_CORE
//This creates a modeless dialog
progressDialog = new wxProgressDialog(_("Creating HDD file"), _("Creating HDD file"), neededSize, nullptr, wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME | wxPD_REMAINING_TIME);
progressDialog = new wxProgressDialog(_("Creating HDD file"), _("Creating HDD file"), reqMiB, nullptr, wxPD_APP_MODAL | wxPD_AUTO_HIDE | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME | wxPD_REMAINING_TIME);
#endif
fileThread = std::thread(&HddCreate::WriteImage, this, filePath, neededSize);
@@ -45,9 +50,9 @@ void HddCreate::Start()
//Instead, loop here to update UI
wxString msg;
int currentSize;
while ((currentSize = written.load()) != neededSize && !errored.load())
while ((currentSize = written.load()) != reqMiB && !errored.load())
{
msg.Printf(_("%i / %i MiB"), written.load(), neededSize);
msg.Printf(_("%i / %i MiB"), written.load(), reqMiB);
#ifndef PCSX2_CORE
if (!progressDialog->Update(currentSize, msg))
@@ -78,18 +83,18 @@ void HddCreate::Start()
completedCV.notify_all();
}
void HddCreate::WriteImage(ghc::filesystem::path hddPath, int reqSizeMiB)
void HddCreate::WriteImage(fs::path hddPath, u64 reqSizeBytes)
{
constexpr int buffsize = 4 * 1024;
u8 buff[buffsize] = {0}; //4kb
if (ghc::filesystem::exists(hddPath))
if (fs::exists(hddPath))
{
SetError();
return;
}
std::fstream newImage = ghc::filesystem::fstream(hddPath, std::ios::out | std::ios::binary);
std::fstream newImage = fs::fstream(hddPath, std::ios::out | std::ios::binary);
if (newImage.fail())
{
@@ -98,14 +103,14 @@ void HddCreate::WriteImage(ghc::filesystem::path hddPath, int reqSizeMiB)
}
//Size file
newImage.seekp(((u64)reqSizeMiB) * 1024 * 1024 - 1, std::ios::beg);
newImage.seekp(reqSizeBytes - 1, std::ios::beg);
const char zero = 0;
newImage.write(&zero, 1);
if (newImage.fail())
{
newImage.close();
ghc::filesystem::remove(filePath);
fs::remove(filePath);
SetError();
return;
}
@@ -114,22 +119,39 @@ void HddCreate::WriteImage(ghc::filesystem::path hddPath, int reqSizeMiB)
newImage.seekp(0, std::ios::beg);
for (int iMiB = 0; iMiB < reqSizeMiB; iMiB++)
//Round up
const s32 reqMiB = (reqSizeBytes + ((1024 * 1024) - 1)) / (1024 * 1024);
for (s32 iMiB = 0; iMiB < reqMiB; iMiB++)
{
for (int i4kb = 0; i4kb < 256; i4kb++)
//Round down
const s32 req4Kib = std::min<s32>(1024, (reqSizeBytes / 1024) - (u64)iMiB * 1024) / 4;
for (s32 i4kb = 0; i4kb < req4Kib; i4kb++)
{
newImage.write((char*)buff, buffsize);
if (newImage.fail())
{
newImage.close();
ghc::filesystem::remove(filePath);
fs::remove(filePath);
SetError();
return;
}
}
if (req4Kib != 256)
{
const s32 remainingBytes = reqSizeBytes - (((u64)iMiB) * (1024 * 1024) + req4Kib * 4096);
newImage.write((char*)buff, remainingBytes);
if (newImage.fail())
{
newImage.close();
fs::remove(filePath);
SetError();
return;
}
}
const std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - lastUpdate).count() >= 100 || (iMiB + 1) == neededSize)
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - lastUpdate).count() >= 100 || (iMiB + 1) == reqMiB)
{
lastUpdate = now;
SetFileProgress(iMiB + 1);
@@ -137,7 +159,7 @@ void HddCreate::WriteImage(ghc::filesystem::path hddPath, int reqSizeMiB)
if (canceled.load())
{
newImage.close();
ghc::filesystem::remove(filePath);
fs::remove(filePath);
SetError();
return;
}
+3 -4
View File
@@ -24,13 +24,12 @@
#include <atomic>
#include <condition_variable>
#include <chrono>
#include "ghc/filesystem.h"
class HddCreate
{
public:
ghc::filesystem::path filePath;
int neededSize;
fs::path filePath;
u64 neededSize;
std::atomic_bool errored{false};
@@ -56,5 +55,5 @@ public:
private:
void SetFileProgress(int currentSize);
void SetError();
void WriteImage(ghc::filesystem::path hddPath, int reqSizeMB);
void WriteImage(fs::path hddPath, u64 reqSizeBytes);
};
+44 -45
View File
@@ -18,7 +18,6 @@
#include <stdio.h>
#include <vector>
#include <ghc/filesystem.h>
#include <wx/wx.h>
#include <wx/collpane.h>
@@ -27,6 +26,8 @@
#include <wx/spinctrl.h>
#include <wx/gbsizer.h>
#include "common/StringUtil.h"
#include "Config.h"
#include "DEV9.h"
#include "pcap_io.h"
@@ -80,7 +81,7 @@ class DEV9Dialog : public wxDialog
IPControl_SetValue(m_ip, ip);
m_auto->SetValue(is_auto);
}
void save(IP_Address& ip, int& is_auto)
void save(IP_Address& ip, bool& is_auto)
{
ip = IPControl_GetValue(m_ip);
is_auto = m_auto->GetValue();
@@ -89,7 +90,7 @@ class DEV9Dialog : public wxDialog
wxCheckBox* m_eth_enable;
wxChoice* m_eth_adapter_api;
wxChoice* m_eth_adapter;
std::vector<NetApi> m_api_list;
std::vector<Pcsx2Config::DEV9Options::NetApi> m_api_list;
std::vector<std::vector<AdapterEntry>> m_adapter_list;
wxCheckBox* m_intercept_dhcp;
wxTextCtrl* m_ps2_address;
@@ -142,8 +143,8 @@ public:
std::sort(list.begin(), list.end(), [](const AdapterEntry& a, AdapterEntry& b){ return a.name < b.name; });
wxArrayString adapter_api_name_list;
adapter_api_name_list.Add("");
for (const NetApi& type : m_api_list)
adapter_api_name_list.Add(NetApiToWxString(type));
for (const Pcsx2Config::DEV9Options::NetApi& type : m_api_list)
adapter_api_name_list.Add(Pcsx2Config::DEV9Options::NetApiNames[(int)type]);
auto* eth_adapter_api_label = new wxStaticText(this, wxID_ANY, _("Ethernet Device Type:"));
auto* eth_adapter_label = new wxStaticText(this, wxID_ANY, _("Ethernet Device:"));
@@ -217,9 +218,9 @@ public:
Bind(wxEVT_BUTTON, &DEV9Dialog::OnOK, this, wxID_OK);
}
void Load(const ConfigDEV9& config)
void Load(const Pcsx2Config::DEV9Options& config)
{
m_eth_enable->SetValue(config.ethEnable);
m_eth_enable->SetValue(config.EthEnable);
m_eth_adapter_api->SetSelection(0);
for (size_t i = 0; i < m_api_list.size(); i++)
{
@@ -233,7 +234,7 @@ public:
const auto& list = m_adapter_list[static_cast<u32>(config.EthApi)];
for (size_t i = 0; i < list.size(); i++)
{
if (list[i].guid == config.Eth)
if (list[i].guid == config.EthDevice)
{
m_eth_adapter->SetSelection(i + 1);
break;
@@ -241,47 +242,48 @@ public:
}
}
m_intercept_dhcp->SetValue(config.InterceptDHCP);
IPControl_SetValue(m_ps2_address, config.PS2IP);
m_subnet_mask .load(config.Mask, config.AutoMask);
m_gateway_address.load(config.Gateway, config.AutoGateway);
m_dns1_address .load(config.DNS1, config.AutoDNS1);
m_dns2_address .load(config.DNS2, config.AutoDNS2);
IPControl_SetValue(m_ps2_address, *(IP_Address*)config.PS2IP);
m_subnet_mask .load(*(IP_Address*)config.Mask, config.AutoMask);
m_gateway_address.load(*(IP_Address*)config.Gateway, config.AutoGateway);
m_dns1_address .load(*(IP_Address*)config.DNS1, config.AutoDNS1);
m_dns2_address .load(*(IP_Address*)config.DNS2, config.AutoDNS2);
m_hdd_enable->SetValue(config.hddEnable);
m_hdd_file->SetInitialDirectory(config.Hdd);
m_hdd_file->SetPath(config.Hdd);
m_hdd_size_spin->SetValue(config.HddSize / 1024);
m_hdd_size_slider->SetValue(config.HddSize / 1024);
m_hdd_enable->SetValue(config.HddEnable);
wxString wxHddFile = StringUtil::UTF8StringToWxString(config.HddFile);
m_hdd_file->SetInitialDirectory(wxHddFile);
m_hdd_file->SetPath(wxHddFile);
m_hdd_size_spin->SetValue((u64)config.HddSizeSectors * 512 / (1024 * 1024 * 1024));
m_hdd_size_slider->SetValue((u64)config.HddSizeSectors * 512 / (1024 * 1024 * 1024));
UpdateEnable();
}
void Save(ConfigDEV9& config)
void Save(Pcsx2Config::DEV9Options& config)
{
config.ethEnable = m_eth_enable->GetValue();
config.EthEnable = m_eth_enable->GetValue();
int api = m_eth_adapter_api->GetSelection();
int eth = m_eth_adapter->GetSelection();
if (api && eth)
{
const AdapterEntry& adapter = m_adapter_list[static_cast<u32>(m_api_list[api - 1])][eth - 1];
wxStrncpy(config.Eth, adapter.guid, std::size(config.Eth) - 1);
config.EthDevice = adapter.guid;
config.EthApi = adapter.type;
}
else
{
config.Eth[0] = 0;
config.EthApi = NetApi::Unset;
config.EthDevice = "";
config.EthApi = Pcsx2Config::DEV9Options::NetApi::Unset;
}
config.InterceptDHCP = m_intercept_dhcp->GetValue();
config.PS2IP = IPControl_GetValue(m_ps2_address);
m_subnet_mask .save(config.Mask, config.AutoMask);
m_gateway_address.save(config.Gateway, config.AutoGateway);
m_dns1_address .save(config.DNS1, config.AutoDNS1);
m_dns2_address .save(config.DNS2, config.AutoDNS2);
*(IP_Address*)&config.PS2IP = IPControl_GetValue(m_ps2_address);
m_subnet_mask .save(*(IP_Address*)config.Mask, config.AutoMask);
m_gateway_address.save(*(IP_Address*)config.Gateway, config.AutoGateway);
m_dns1_address .save(*(IP_Address*)config.DNS1, config.AutoDNS1);
m_dns2_address .save(*(IP_Address*)config.DNS2, config.AutoDNS2);
config.hddEnable = m_hdd_enable->GetValue();
wxStrncpy(config.Hdd, m_hdd_file->GetPath(), std::size(config.Hdd) - 1);
config.HddSize = m_hdd_size_spin->GetValue() * 1024;
config.HddEnable = m_hdd_enable->GetValue();
config.HddFile = StringUtil::wxStringToUTF8String(m_hdd_file->GetPath());
config.HddSizeSectors = (u64)m_hdd_size_spin->GetValue() * 1024 * 1024 * 1024 / 512;
}
void UpdateEnable()
@@ -316,11 +318,12 @@ public:
if (m_eth_adapter->GetCount())
current = m_eth_adapter->GetString(m_eth_adapter->GetSelection());
if (current.empty())
current = config.Eth;
current = StringUtil::UTF8StringToWxString(g_Conf->EmuOptions.DEV9.EthDevice);
for (size_t i = 0; i < list.size(); i++)
{
options.Add(list[i].name);
if (list[i].name == current)
wxString wxAdapterName = StringUtil::UTF8StringToWxString(list[i].name);
options.Add(wxAdapterName);
if (wxAdapterName == current)
selection = i + 1;
}
}
@@ -373,33 +376,29 @@ void DEV9configure()
ScopedCoreThreadPause paused_core;
DEV9Dialog dialog;
LoadConf();
dialog.Load(config);
dialog.Load(g_Conf->EmuOptions.DEV9);
if (dialog.ShowModal() == wxID_OK)
{
ConfigDEV9 oldConfig = config;
dialog.Save(config);
dialog.Save(g_Conf->EmuOptions.DEV9);
ghc::filesystem::path hddPath(config.Hdd);
fs::path hddPath(g_Conf->EmuOptions.DEV9.HddFile);
if (hddPath.is_relative())
{
//GHC uses UTF8 on all platforms
ghc::filesystem::path path(EmuFolders::Settings.ToString().wx_str());
fs::path path(EmuFolders::Settings.ToString().wx_str());
hddPath = path / hddPath;
}
if (config.hddEnable && !ghc::filesystem::exists(hddPath))
if (g_Conf->EmuOptions.DEV9.HddEnable && !fs::exists(hddPath))
{
HddCreate hddCreator;
hddCreator.filePath = hddPath;
hddCreator.neededSize = config.HddSize;
hddCreator.neededSize = ((u64)g_Conf->EmuOptions.DEV9.HddSizeSectors) * 512;
hddCreator.Start();
}
SaveConf();
ApplyConfigIfRunning(oldConfig);
AppSaveSettings();
}
paused_core.AllowResume();
+45 -81
View File
@@ -25,8 +25,6 @@
#include <err.h>
#endif
#include "ghc/filesystem.h"
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
@@ -36,6 +34,7 @@
#include "DEV9.h"
#undef EXTERN
#include "Config.h"
#include "DEV9Config.h"
#include "smap.h"
@@ -91,11 +90,25 @@ int hEeprom;
int mapping;
#endif
std::string s_strIniPath = "inis";
std::string s_strLogPath = "logs";
bool isRunning = false;
fs::path GetHDDPath()
{
//GHC uses UTF8 on all platforms
fs::path hddPath(EmuConfig.DEV9.HddFile);
if (hddPath.empty())
EmuConfig.DEV9.HddEnable = false;
if (hddPath.is_relative())
{
fs::path path(EmuFolders::Settings.ToString().wx_str());
hddPath = path / hddPath;
}
return hddPath;
}
s32 DEV9init()
{
DevCon.WriteLn("DEV9: DEV9init");
@@ -186,34 +199,18 @@ void DEV9shutdown()
s32 DEV9open()
{
DevCon.WriteLn("DEV9: DEV9open");
LoadConf();
#ifdef _WIN32
//Convert to utf8
char mbHdd[sizeof(config.Hdd)] = {0};
WideCharToMultiByte(CP_UTF8, 0, config.Hdd, -1, mbHdd, sizeof(mbHdd) - 1, nullptr, nullptr);
DevCon.WriteLn("DEV9: open r+: %s", mbHdd);
#else
DevCon.WriteLn("DEV9: open r+: %s", config.Hdd);
#endif
LoadDnsHosts();
DevCon.WriteLn("DEV9: open r+: %s", EmuConfig.DEV9.HddFile.c_str());
ghc::filesystem::path hddPath(config.Hdd);
fs::path hddPath = GetHDDPath();
if (hddPath.empty())
config.hddEnable = false;
if (hddPath.is_relative())
{
ghc::filesystem::path path(EmuFolders::Settings.ToString().wx_str());
hddPath = path / hddPath;
}
if (config.hddEnable)
if (EmuConfig.DEV9.HddEnable)
{
if (dev9.ata->Open(hddPath) != 0)
config.hddEnable = false;
EmuConfig.DEV9.HddEnable = false;
}
if (config.ethEnable)
if (EmuConfig.DEV9.EthEnable)
InitNet();
isRunning = true;
@@ -313,7 +310,7 @@ void FIFOIntr()
u8 DEV9read8(u32 addr)
{
if (!config.ethEnable & !config.hddEnable)
if (!EmuConfig.DEV9.EthEnable && !EmuConfig.DEV9.HddEnable)
return 0;
u8 hard;
@@ -379,7 +376,7 @@ u8 DEV9read8(u32 addr)
u16 DEV9read16(u32 addr)
{
if (!config.ethEnable & !config.hddEnable)
if (!EmuConfig.DEV9.EthEnable && !EmuConfig.DEV9.HddEnable)
return 0;
u16 hard;
@@ -455,9 +452,9 @@ u16 DEV9read16(u32 addr)
case SPD_R_REV_3:
hard = 0;
if (config.hddEnable)
if (EmuConfig.DEV9.HddEnable)
hard |= SPD_CAPS_ATA;
if (config.ethEnable)
if (EmuConfig.DEV9.EthEnable)
hard |= SPD_CAPS_SMAP;
hard |= SPD_CAPS_FLASH;
//DevCon.WriteLn("DEV9: SPD_R_REV_3 16bit read %x", hard);
@@ -519,7 +516,7 @@ u16 DEV9read16(u32 addr)
u32 DEV9read32(u32 addr)
{
if (!config.ethEnable & !config.hddEnable)
if (!EmuConfig.DEV9.EthEnable && !EmuConfig.DEV9.HddEnable)
return 0;
u32 hard;
@@ -545,7 +542,7 @@ u32 DEV9read32(u32 addr)
void DEV9write8(u32 addr, u8 value)
{
if (!config.ethEnable & !config.hddEnable)
if (!EmuConfig.DEV9.EthEnable && !EmuConfig.DEV9.HddEnable)
return;
if (addr >= ATA_DEV9_HDD_BASE && addr < ATA_DEV9_HDD_END)
@@ -657,7 +654,7 @@ void DEV9write8(u32 addr, u8 value)
void DEV9write16(u32 addr, u16 value)
{
if (!config.ethEnable & !config.hddEnable)
if (!EmuConfig.DEV9.EthEnable && !EmuConfig.DEV9.HddEnable)
return;
if (addr >= ATA_DEV9_HDD_BASE && addr < ATA_DEV9_HDD_END)
@@ -967,7 +964,7 @@ void DEV9write16(u32 addr, u16 value)
void DEV9write32(u32 addr, u32 value)
{
if (!config.ethEnable & !config.hddEnable)
if (!EmuConfig.DEV9.EthEnable && !EmuConfig.DEV9.HddEnable)
return;
if (addr >= ATA_DEV9_HDD_BASE && addr < ATA_DEV9_HDD_END)
@@ -1003,7 +1000,7 @@ void DEV9write32(u32 addr, u32 value)
void DEV9readDMA8Mem(u32* pMem, int size)
{
if (!config.ethEnable & !config.hddEnable)
if (!EmuConfig.DEV9.EthEnable && !EmuConfig.DEV9.HddEnable)
return;
size >>= 1;
@@ -1029,7 +1026,7 @@ void DEV9readDMA8Mem(u32* pMem, int size)
void DEV9writeDMA8Mem(u32* pMem, int size)
{
if (!config.ethEnable & !config.hddEnable)
if (!EmuConfig.DEV9.EthEnable && !EmuConfig.DEV9.HddEnable)
return;
size >>= 1;
@@ -1059,69 +1056,36 @@ void DEV9async(u32 cycles)
dev9.ata->Async(cycles);
}
// extended funcs
void DEV9setSettingsDir(const char* dir)
{
// Grab the ini directory.
// TODO: Use
s_strIniPath = (dir == NULL) ? "inis" : dir;
}
void DEV9setLogDir(const char* dir)
{
// Get the path to the log directory.
s_strLogPath = (dir == NULL) ? "logs" : dir;
}
void ApplyConfigIfRunning(ConfigDEV9 oldConfig)
void DEV9CheckChanges(const Pcsx2Config& old_config)
{
if (!isRunning)
return;
//Eth
ReconfigureLiveNet(&oldConfig);
ReconfigureLiveNet(old_config);
//Hdd
//Hdd Validate Path
ghc::filesystem::path hddPath(config.Hdd);
if (hddPath.empty())
config.hddEnable = false;
if (hddPath.is_relative())
{
//GHC uses UTF8 on all platforms
ghc::filesystem::path path(EmuFolders::Settings.ToString().wx_str());
hddPath = path / hddPath;
}
fs::path hddPath = GetHDDPath();
//Hdd Compare with old config
if (config.hddEnable)
if (EmuConfig.DEV9.HddEnable)
{
if (oldConfig.hddEnable)
if (old_config.DEV9.HddEnable)
{
//ATA::Open/Close dosn't set any regs
//So we can close/open to apply settings
#ifdef _WIN32
if (wcscmp(config.Hdd, oldConfig.Hdd))
#else
if (strcmp(config.Hdd, oldConfig.Hdd))
#endif
if (EmuConfig.DEV9.HddFile != old_config.DEV9.HddFile ||
EmuConfig.DEV9.HddSizeSectors != old_config.DEV9.HddSizeSectors)
{
dev9.ata->Close();
if (dev9.ata->Open(hddPath) != 0)
config.hddEnable = false;
}
if (config.HddSize != oldConfig.HddSize)
{
dev9.ata->Close();
if (dev9.ata->Open(hddPath) != 0)
config.hddEnable = false;
EmuConfig.DEV9.HddEnable = false;
}
}
else if (dev9.ata->Open(hddPath) != 0)
EmuConfig.DEV9.HddEnable = false;
}
else if (oldConfig.hddEnable)
else if (old_config.DEV9.HddEnable)
dev9.ata->Close();
}
+1 -27
View File
@@ -65,29 +65,7 @@ struct ConfigHost
struct ConfigDEV9
{
char Eth[256];
NetApi EthApi;
bool InterceptDHCP;
PacketReader::IP::IP_Address PS2IP;
PacketReader::IP::IP_Address Mask;
PacketReader::IP::IP_Address Gateway;
PacketReader::IP::IP_Address DNS1;
PacketReader::IP::IP_Address DNS2;
int AutoMask;
int AutoGateway;
int AutoDNS1;
int AutoDNS2;
int EthLogDNS;
std::vector<ConfigHost> EthHosts;
#ifdef _WIN32
wchar_t Hdd[256];
#else
char Hdd[256];
#endif
int HddSize;
int hddEnable;
int ethEnable;
};
@@ -156,10 +134,6 @@ EXTERN dev9Struct dev9;
EXTERN int ThreadRun;
//Yes these are meant to be a lowercase extern
extern std::string s_strIniPath;
extern std::string s_strLogPath;
#define DEV9_R_REV 0x1f80146e
@@ -742,7 +716,7 @@ u32 DEV9read32(u32 addr);
void DEV9write8(u32 addr, u8 value);
void DEV9write16(u32 addr, u16 value);
void DEV9write32(u32 addr, u32 value);
void ApplyConfigIfRunning(ConfigDEV9 oldConfig);
void DEV9CheckChanges(const Pcsx2Config& old_config);
#ifdef _WIN32
#pragma warning(error : 4013)

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