Compare commits

...
92 Commits
Author SHA1 Message Date
RedPanda4552andrefractionpcsx2 f43b5ee76f Pad: Respect non-standard vibration mappings and pure digital button query 2023-07-30 23:48:12 +01:00
refractionpcsx2 bab16a5251 UI: Update glyphs for asian languages. 2023-07-30 19:20:29 +01:00
Mrlinkwiiandrefractionpcsx2 08c734d7fd GameDB: various fixes 2023-07-30 14:23:45 +01:00
Connor McLaughlin 36126a3ad9 GS: Drop alignment from ClearValue 2023-07-30 21:44:44 +10:00
kamfretozandConnor McLaughlin ce505d33bd Qt: Make incompatible savestate message translateable 2023-07-30 20:28:50 +10:00
Stenzek de0d859502 Qt: Fix changing cover file formats 2023-07-30 19:25:51 +10:00
Stenzek ce96d4bcc5 SaveState: Store the current PCSX2 version in the save state 2023-07-30 18:13:25 +10:00
ChromaryuandConnor McLaughlin fb242274d5 GameDB: Fix PoPoLoCrois Naming 2023-07-30 16:18:55 +10:00
Stenzek 938bc7cdd7 GS/HW: Allow fast clears even when expanding
Doesn't make sense not to.
2023-07-30 16:18:04 +10:00
Stenzek 36865f2930 GS/HW: Skip target conversion when alpha doesn't exist 2023-07-30 16:18:04 +10:00
refractionpcsx2 12e79cccf6 GS/HW: Improve detection of reverse texture shuffles 2023-07-30 07:04:39 +01:00
PCSX2 BotandConnor McLaughlin 6180f12ba3 Qt: Update Base Translation 2023-07-30 12:26:53 +10:00
refractionpcsx2 c00b6c6237 GameDB: Sort and append missing entried from Redump 2023-07-30 02:37:18 +01:00
RedPanda4552andrefractionpcsx2 dbdc74fdef Memcard: Remove erroneous auto eject decrement 2023-07-29 19:11:33 +01:00
pgertandrefractionpcsx2 5bb0a07164 GameDB: correct an entry 2023-07-29 18:32:26 +01:00
Stenzek 543f09999f GS/HW: Fix target memory usage underflowing 2023-07-30 01:03:46 +10:00
Connor McLaughlinandGitHub 812f32efdd README: Update DirectX Requirements 2023-07-29 22:32:20 +10:00
Stenzek 784264eba4 GS: Drop alpha gather from FXAA
It's not used by any backends.
2023-07-29 22:28:49 +10:00
Stenzek ff9ca059c7 GS/DX11: Require feature level 11.0
Feature level 11.0 GPUs were first released in 2009, almost 14 years ago
now. Older GPUs have not had drivers released in a long time, and are
known to be buggy.

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

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

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

* Pad: Serialize 'stage' state

[SAVEVERSION+]

* Pad: Reduce Freeze duplication and add markers

Catch any possible unhandled device type change.

[SAVEVERSION+]

* Pad: Localize controller type names

* Pad: Handle mismatch between state and current config

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

We don't use exceptions.

* Pad: Remove redundant GetUnifiedSlot()

Sio has routines for converting these.

* Sio2: Remove redundant optional in Pad()

* Pad: Constify and finalize controller classes

* Pad: Move PadManager to Pad namespace

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

* Pad: Move PadConfig to Pad namespace

* Pad: Move PadMacros to Pad namespace

* Pad: Re-localize controller bindings/settings

* Pad: Make controller info local

Don't want to create duplicates.

* Pad: Use span for ControllerInfo settings/bindings

* Pad: Fix auto-toggled macro buttons

* Pad: Fix pressure for macros

* Pad: Merge PadConfig/PadManager/PadMacros

Faster compile time.

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

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

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

[SAVEVERSION+] Bump savestate version

CI: Update locations of pad/memcard sources

Discard leftover old PAD code

Fix additional merge oddities

Add translations for OSD messages

Copyright headers

Version bump

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

Partial redo of PS1 pad support

Fix incorrect mode due to analog behavior at startup

Mostly reimplement SIO0 memory card logic

Still needs pocketstation

Use new runtime wrapped translate function

Dead code

Fix multiple port/slot/presence issues for PS1

Save State version bump

Clean up some duplicate/unused headers

More header consistency

Remove old stray files

Fix incorrect return

Fix uninitialized array

Add missing overrides

Switch to init/close model used by other subsystems

Remove old input recording references

Rename SIO globals

Rename SIO2 FIFO globals

Remove commented SIO0 code for illegal write

Add guitar icon
2023-07-24 16:41:17 +01:00
Stenzek 876b576679 CI: Pin flat-manager-client version 2023-07-24 21:26:41 +10:00
Stenzek c927e4785b GS/HW: Get rid of 2 frame forced preload 2023-07-24 18:31:07 +10:00
refractionpcsx2 97672828e8 GameDB: Add patch for Shadow Hearts NTSC-U bad clip arrangement 2023-07-24 09:01:44 +01:00
refractionpcsx2 b96978494b GS/HW: Fix Double Half Clear bug + better detect double buffer changes 2023-07-23 19:40:14 +01:00
Stenzekandrefractionpcsx2 2f105cbe15 VMManager: Display title as serial or ELF 2023-07-23 19:09:41 +01:00
Stenzekandrefractionpcsx2 2539a07b7d Qt: Add dump verification to game properties 2023-07-23 19:09:31 +01:00
Stenzekandrefractionpcsx2 73f903f402 GameDatabase: Add hash database parse/lookup 2023-07-23 19:09:31 +01:00
Stenzekandrefractionpcsx2 94c48a4c2d CDVD: Add IsoHasher 2023-07-23 19:09:31 +01:00
Stenzekandrefractionpcsx2 eb8d938c94 Resources: Add redump database 2023-07-23 19:09:31 +01:00
CRASHARKIandrefractionpcsx2 92b8316182 GameDB: Add nativePaletteDraw and halfPixelOffset to Crash Tag Team Racing 2023-07-23 19:09:15 +01:00
Stenzekandrefractionpcsx2 610cb2626b GS/HW: Use GetUnwrappedEndBlockAddress() where appropriate 2023-07-23 19:09:01 +01:00
Stenzekandrefractionpcsx2 2033f813da GS/HW: Fix incorrect usage of bit_ceil() 2023-07-23 19:09:01 +01:00
pgertandrefractionpcsx2 a6fbd0fe69 GameDB: correct an entry 2023-07-23 19:00:55 +01:00
Stenzek abadb7f80f GSRunner: Fix Unicode command line on Win32 2023-07-24 00:55:54 +10:00
JordanTheToasterandrefractionpcsx2 1c6be3f400 GameDB: Various fixes
Fixes for Link being a doughnut and missing a line and for crusty field textures in all NCAA Football games TW PGA golf games and Madden games.
2023-07-23 13:28:40 +01:00
CRASHARKIandrefractionpcsx2 52111be20a GameDB: Change halfPixelOffset to Spyro: A Hero's Tail 2023-07-23 13:27:51 +01:00
195 changed files with 191353 additions and 60539 deletions
+4 -4
View File
@@ -115,11 +115,11 @@
- 'pcsx2/IPU/*'
- 'pcsx2/IPU/**/*'
'Memory Card':
- 'pcsx2/gui/MemoryCard*'
- 'pcsx2/gui/**/MemoryCard*'
- 'pcsx2/SIO/Memcard/*'
- 'pcsx2/SIO/Memcard/**/*'
'PAD':
- 'pcsx2/PAD/*'
- 'pcsx2/PAD/**/*'
- 'pcsx2/SIO/Pad/*'
- 'pcsx2/SIO/Pad/**/*'
'SPU2':
- 'pcsx2/SPU2/*'
- 'pcsx2/SPU2/**/*'
@@ -37,5 +37,6 @@ jobs:
cmakeflags: ""
publish: true
branch: stable
fetchTags: true
secrets: inherit
@@ -49,7 +49,7 @@ retry_command sudo flatpak -y install "${FLATPAK_PACKAGES[@]}"
echo "Downloading flat-manager-client"
mkdir -p "$FLAT_MANAGER_CLIENT_DIR"
pushd "$FLAT_MANAGER_CLIENT_DIR"
aria2c -Z "https://raw.githubusercontent.com/flatpak/flat-manager/master/flat-manager-client"
aria2c -Z "https://raw.githubusercontent.com/flatpak/flat-manager/9401efbdc0d6bd489507d8401c567ba219d735d5/flat-manager-client"
chmod +x flat-manager-client
echo "$FLAT_MANAGER_CLIENT_DIR" >> $GITHUB_PATH
popd
+1 -1
View File
@@ -22,7 +22,7 @@ Installers and binaries for both stable and development builds are available fro
| Operating System | CPU | GPU | RAM |
| ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| - Windows 10 Version 1809 or later (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1800<br/> - Two physical cores, with hyperthreading | - Direct3D10 support <br/> - OpenGL 3.x support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
| - Windows 10 Version 1809 or later (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1800<br/> - Two physical cores, with hyperthreading | - Direct3D 11 (Feature Level 11.0) support <br/> - OpenGL 3.3 support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
_Note: Recommended Single Thread Performance is based on moderately complex games. Games that pushed the PS2 hardware to its limits will struggle on CPUs at this level. Some release titles and 2D games which underutilized the PS2 hardware may run on CPUs rated as low as 1200. A quick reference for CPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:CPU_intensive_games), [Forum](https://forums.pcsx2.net/Thread-LIST-The-Most-CPU-Intensive-Games) and CPU **light** games: [Forum](https://forums.pcsx2.net/Thread-LIST-Games-that-don-t-need-a-strong-CPU-to-emulate)_
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+5 -69
View File
@@ -13,14 +13,6 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(SHADER_MODEL) || defined(FXAA_GLSL_130) || defined(FXAA_GLSL_VK) || defined(__METAL_VERSION__)
#ifndef SHADER_MODEL
#define SHADER_MODEL 0
#endif
#ifndef FXAA_HLSL_4
#define FXAA_HLSL_4 0
#endif
#ifndef FXAA_HLSL_5
#define FXAA_HLSL_5 0
#endif
@@ -51,7 +43,7 @@ layout(location = 0) in vec2 PSin_t;
layout(location = 0) out vec4 SV_Target0;
layout(set = 0, binding = 0) uniform sampler2D TextureSampler;
#elif (SHADER_MODEL >= 0x400)
#elif (FXAA_HLSL_5 == 1)
Texture2D Texture : register(t0);
SamplerState TextureSampler : register(s0);
@@ -80,26 +72,6 @@ static constexpr sampler MAIN_SAMPLER(coord::normalized, address::clamp_to_edge,
[FXAA CODE SECTION]
------------------------------------------------------------------------------*/
// We don't use gather4 for alpha/luminance because it would require an additional
// pass to compute the values, which would be slower than the extra shader loads.
#if (SHADER_MODEL >= 0x500)
#undef FXAA_HLSL_5
#define FXAA_HLSL_5 1
#define FXAA_GATHER4_ALPHA 0
#elif (SHADER_MODEL >= 0x400)
#undef FXAA_HLSL_4
#define FXAA_HLSL_4 1
#define FXAA_GATHER4_ALPHA 0
#elif (FXAA_GLSL_130 == 1 || FXAA_GLSL_VK == 1)
#define FXAA_GATHER4_ALPHA 0
#elif defined(__METAL_VERSION__)
#define FXAA_GATHER4_ALPHA 0
#endif
#if (FXAA_HLSL_5 == 1)
struct FxaaTex { SamplerState smpl; Texture2D tex; };
#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
@@ -109,13 +81,6 @@ struct FxaaTex { SamplerState smpl; Texture2D tex; };
#define FxaaDiscard clip(-1)
#define FxaaSat(x) saturate(x)
#elif (FXAA_HLSL_4 == 1)
struct FxaaTex { SamplerState smpl; Texture2D tex; };
#define FxaaTexTop(t, p) t.tex.SampleLevel(t.smpl, p, 0.0)
#define FxaaTexOff(t, p, o, r) t.tex.SampleLevel(t.smpl, p, 0.0, o)
#define FxaaDiscard clip(-1)
#define FxaaSat(x) saturate(x)
#elif (FXAA_GLSL_130 == 1 || FXAA_GLSL_VK == 1)
#define int2 ivec2
#define float2 vec2
@@ -127,12 +92,6 @@ struct FxaaTex { SamplerState smpl; Texture2D tex; };
#define FxaaTexTop(t, p) textureLod(t, p, 0.0)
#define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o)
#if (FXAA_GATHER4_ALPHA == 1)
// use #extension GL_ARB_gpu_shader5 : enable
#define FxaaTexAlpha4(t, p) textureGather(t, p, 3)
#define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3)
#endif
#elif defined(__METAL_VERSION__)
#define FxaaTex texture2d<float>
#define FxaaTexTop(t, p) t.sample(MAIN_SAMPLER, p)
@@ -221,21 +180,6 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
posM.x = pos.x;
posM.y = pos.y;
#if (FXAA_GATHER4_ALPHA == 1)
float4 rgbyM = FxaaTexTop(tex, posM);
float4 luma4A = FxaaTexAlpha4(tex, posM);
float4 luma4B = FxaaTexOffAlpha4(tex, posM, int2(-1, -1));
rgbyM.w = RGBLuminance(rgbyM.xyz);
#define lumaM rgbyM.w
#define lumaE luma4A.z
#define lumaS luma4A.x
#define lumaSE luma4A.y
#define lumaNW luma4B.w
#define lumaN luma4B.z
#define lumaW luma4B.x
#else
float4 rgbyM = FxaaTexTop(tex, posM);
rgbyM.w = RGBLuminance(rgbyM.xyz);
#define lumaM rgbyM.w
@@ -244,7 +188,6 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
float lumaE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1, 0), fxaaRcpFrame.xy));
float lumaN = FxaaLuma(FxaaTexOff(tex, posM, int2( 0,-1), fxaaRcpFrame.xy));
float lumaW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 0), fxaaRcpFrame.xy));
#endif
float maxSM = max(lumaS, lumaM);
float minSM = min(lumaS, lumaM);
@@ -264,15 +207,10 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
if(earlyExit) { return rgbyM; }
#endif
#if (FXAA_GATHER4_ALPHA == 0)
float lumaNW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1,-1), fxaaRcpFrame.xy));
float lumaSE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1, 1), fxaaRcpFrame.xy));
float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1,-1), fxaaRcpFrame.xy));
float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 1), fxaaRcpFrame.xy));
#else
float lumaNE = FxaaLuma(FxaaTexOff(tex, posM, int2( 1,-1), fxaaRcpFrame.xy));
float lumaSW = FxaaLuma(FxaaTexOff(tex, posM, int2(-1, 1), fxaaRcpFrame.xy));
#endif
float lumaNS = lumaN + lumaS;
float lumaWE = lumaW + lumaE;
@@ -518,14 +456,14 @@ float4 FxaaPixelShader(float2 pos, FxaaTex tex, float2 fxaaRcpFrame, float fxaaS
#if (FXAA_GLSL_130 == 1 || FXAA_GLSL_VK == 1)
float4 FxaaPass(float4 FxaaColor, float2 uv0)
#elif (SHADER_MODEL >= 0x400)
#elif (FXAA_HLSL_5 == 1)
float4 FxaaPass(float4 FxaaColor : COLOR0, float2 uv0 : TEXCOORD0)
#elif defined(__METAL_VERSION__)
float4 FxaaPass(float4 FxaaColor, float2 uv0, texture2d<float> tex)
#endif
{
#if (SHADER_MODEL >= 0x400)
#if (FXAA_HLSL_5 == 1)
FxaaTex tex;
tex.tex = Texture;
tex.smpl = TextureSampler;
@@ -559,8 +497,8 @@ void main()
SV_Target0 = float4(color.rgb, 1.0);
}
#elif (SHADER_MODEL >= 0x400)
PS_OUTPUT ps_main(VS_OUTPUT input)
#elif (FXAA_HLSL_5 == 1)
PS_OUTPUT main(VS_OUTPUT input)
{
PS_OUTPUT output;
@@ -576,5 +514,3 @@ PS_OUTPUT ps_main(VS_OUTPUT input)
// Metal main function in in fxaa.metal
#endif
#endif
-4
View File
@@ -13,8 +13,6 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
struct VS_INPUT
{
float4 p : POSITION;
@@ -413,5 +411,3 @@ float ps_stencil_image_init_1(PS_INPUT input) : SV_Target
c = float(0x7FFFFFFF);
return c;
}
#endif
-4
View File
@@ -13,8 +13,6 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
Texture2D Texture;
SamplerState Sampler;
@@ -195,5 +193,3 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
return float4(0.0f, 0.0f, 0.0f, 0.0f);
}
#endif
-3
View File
@@ -13,8 +13,6 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
Texture2D Texture;
SamplerState Sampler;
@@ -45,4 +43,3 @@ float4 ps_main1(PS_INPUT input) : SV_Target0
c.a = BGColor.a;
return c;
}
#endif
-8
View File
@@ -13,12 +13,6 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
#ifndef PS_SCALE_FACTOR
#define PS_SCALE_FACTOR 1
#endif
struct VS_INPUT
{
float4 p : POSITION;
@@ -451,5 +445,3 @@ PS_OUTPUT ps_automagical_supersampling(PS_INPUT input)
output.c = float4(col / div, 1);
return output;
}
#endif
-4
View File
@@ -13,8 +13,6 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
Texture2D Texture;
SamplerState Sampler;
@@ -64,5 +62,3 @@ float4 ps_main(PS_INPUT input) : SV_Target0
float4 c = Texture.Sample(Sampler, input.t);
return ContrastSaturationBrightness(c);
}
#endif
+1 -1
View File
@@ -661,7 +661,7 @@ float4 sample_color(float2 st, float uv_w)
float4 tfx(float4 T, float4 C)
{
float4 C_out;
float4 FxT = trunc(trunc(C) * T / 128.0f);
float4 FxT = trunc((C * T) / 128.0f);
#if (PS_TFX == 0)
C_out = FxT;
+1 -1
View File
@@ -614,7 +614,7 @@ vec4 sample_color(vec2 st)
vec4 tfx(vec4 T, vec4 C)
{
vec4 C_out;
vec4 FxT = trunc(trunc(C) * T / 128.0f);
vec4 FxT = trunc((C * T) / 128.0f);
#if (PS_TFX == 0)
C_out = FxT;
+1 -1
View File
@@ -849,7 +849,7 @@ vec4 sample_color(vec2 st)
vec4 tfx(vec4 T, vec4 C)
{
vec4 C_out;
vec4 FxT = trunc(trunc(C) * T / 128.0f);
vec4 FxT = trunc((C * T) / 128.0f);
#if (PS_TFX == 0)
C_out = FxT;
+4
View File
@@ -643,7 +643,9 @@ bool unpack_bc7_mode0_2(uint32_t mode, const uint64_t* data_chunks, color_rgba*
const uint32_t ENDPOINT_BITS = (mode == 0) ? 4 : 5;
const uint32_t ENDPOINT_MASK = (1 << ENDPOINT_BITS) - 1;
const uint32_t PBITS = (mode == 0) ? 6 : 0;
#ifndef BC7DECOMP_USE_SSE2
const uint32_t WEIGHT_VALS = 1 << WEIGHT_BITS;
#endif
const uint32_t PART_BITS = (mode == 0) ? 4 : 6;
const uint32_t PART_MASK = (1 << PART_BITS) - 1;
@@ -740,7 +742,9 @@ bool unpack_bc7_mode1_3_7(uint32_t mode, const uint64_t* data_chunks, color_rgba
const uint32_t ENDPOINT_MASK = (1 << ENDPOINT_BITS) - 1;
const uint32_t PBITS = (mode == 1) ? 2 : 4;
const uint32_t SHARED_PBITS = (mode == 1) ? true : false;
#ifndef BC7DECOMP_USE_SSE2
const uint32_t WEIGHT_VALS = 1 << WEIGHT_BITS;
#endif
const uint64_t low_chunk = data_chunks[0];
const uint64_t high_chunk = data_chunks[1];
+33 -5
View File
@@ -48,7 +48,7 @@
#include "pcsx2/Input/InputManager.h"
#include "pcsx2/LogSink.h"
#include "pcsx2/MTGS.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/SIO/Pad/Pad.h"
#include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/VMManager.h"
@@ -85,11 +85,13 @@ static double s_last_render_passes = 0;
static double s_last_barriers = 0;
static double s_last_copies = 0;
static double s_last_uploads = 0;
static double s_last_readbacks = 0;
static u64 s_total_draws = 0;
static u64 s_total_render_passes = 0;
static u64 s_total_barriers = 0;
static u64 s_total_copies = 0;
static u64 s_total_uploads = 0;
static u64 s_total_readbacks = 0;
static u32 s_total_frames = 0;
bool GSRunner::InitializeConfig()
@@ -115,7 +117,7 @@ bool GSRunner::InitializeConfig()
si.SetStringValue("SPU2/Output", "OutputModule", "nullout");
// none of the bindings are going to resolve to anything
PAD::ClearPortBindings(si, 0);
Pad::ClearPortBindings(si, 0);
si.ClearSection("Hotkeys");
// make sure any gamesettings inis in your tree don't get loaded
@@ -255,7 +257,7 @@ void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
{
}
void Host::SetRelativeMouseMode(bool enabled)
void Host::SetMouseMode(bool relative_mode, bool hide_cursor)
{
}
@@ -293,6 +295,7 @@ void Host::BeginPresentFrame()
update_stat(GSPerfMon::Barriers, s_total_barriers, s_last_barriers);
update_stat(GSPerfMon::TextureCopies, s_total_copies, s_last_copies);
update_stat(GSPerfMon::TextureUploads, s_total_uploads, s_last_uploads);
update_stat(GSPerfMon::Readbacks, s_total_readbacks, s_last_readbacks);
s_total_frames++;
std::atomic_thread_fence(std::memory_order_release);
}
@@ -382,12 +385,15 @@ void Host::RequestVMShutdown(bool allow_confirm, bool allow_save_state, bool def
VMManager::SetState(VMState::Stopping);
}
#ifdef ENABLE_ACHIEVEMENTS
void Host::OnAchievementsLoginRequested(Achievements::LoginRequestReason reason)
{
// noop
}
void Host::OnAchievementsRefreshed()
{
// noop
}
#endif
std::optional<u32> InputManager::ConvertHostKeyboardStringToCode(const std::string_view& str)
{
@@ -641,9 +647,15 @@ void GSRunner::DumpStats()
Console.WriteLn(fmt::format("@HWSTAT@ Barriers: {} (avg {})", s_total_barriers, static_cast<u64>(std::ceil(s_total_barriers / static_cast<double>(s_total_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Copies: {} (avg {})", s_total_copies, static_cast<u64>(std::ceil(s_total_copies / static_cast<double>(s_total_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Uploads: {} (avg {})", s_total_uploads, static_cast<u64>(std::ceil(s_total_uploads / static_cast<double>(s_total_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Readbacks: {} (avg {})", s_total_readbacks, static_cast<u64>(std::ceil(s_total_readbacks / static_cast<double>(s_total_frames)))));
Console.WriteLn("============================================");
}
#ifdef _WIN32
// We can't handle unicode in filenames if we don't use wmain on Win32.
#define main real_main
#endif
int main(int argc, char* argv[])
{
GSRunner::InitializeConsole();
@@ -808,4 +820,20 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
return DefWindowProcW(hwnd, msg, wParam, lParam);
}
int wmain(int argc, wchar_t** argv)
{
std::vector<std::string> u8_args;
u8_args.reserve(static_cast<size_t>(argc));
for (int i = 0; i < argc; i++)
u8_args.push_back(StringUtil::WideStringToUTF8String(argv[i]));
std::vector<char*> u8_argptrs;
u8_argptrs.reserve(u8_args.size());
for (int i = 0; i < argc; i++)
u8_argptrs.push_back(u8_args[i].data());
u8_argptrs.push_back(nullptr);
return real_main(argc, u8_argptrs.data());
}
#endif // _WIN32
+19
View File
@@ -380,6 +380,8 @@ void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
changes_html.prepend(tr("<h2>Save State Warning</h2><p>Installing this update will make your save states "
"<b>incompatible</b>. Please ensure you have saved your games to a Memory Card "
"before installing this update or you will lose progress.</p>"));
m_update_will_break_save_states = true;
}
if (update_increases_settings_version)
@@ -407,6 +409,23 @@ void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
void AutoUpdaterDialog::downloadUpdateClicked()
{
if (m_update_will_break_save_states)
{
QMessageBox msgbox;
msgbox.setIcon(QMessageBox::Critical);
msgbox.setWindowTitle(tr("Savestate Warning"));
msgbox.setText(tr("<h1>WARNING</h1><p style='font-size:12pt;'>Installing this update will make your <b>save states incompatible</b>, <i>be sure to save any progress to your memory cards before proceeding</i>.</p><p>Do you wish to continue?</p>"));
msgbox.addButton(QMessageBox::Yes);
msgbox.addButton(QMessageBox::No);
msgbox.setDefaultButton(QMessageBox::No);
// This makes the box wider, for some reason sizing boxes in Qt is hard - Source: The internet.
QSpacerItem* horizontalSpacer = new QSpacerItem(500, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
QGridLayout* layout = (QGridLayout*)msgbox.layout();
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
if (msgbox.exec() != QMessageBox::Yes)
return;
}
m_display_messages = true;
QUrl url(m_download_url);
QNetworkRequest request(url);
+2
View File
@@ -55,6 +55,7 @@ target_sources(pcsx2-qt PRIVATE
Settings/BIOSSettingsWidget.ui
Settings/ControllerBindingWidget.ui
Settings/ControllerBindingWidget_DualShock2.ui
Settings/ControllerBindingWidget_Guitar.ui
Settings/ControllerBindingWidgets.cpp
Settings/ControllerBindingWidgets.h
Settings/ControllerLEDSettingsDialog.ui
@@ -133,6 +134,7 @@ target_sources(pcsx2-qt PRIVATE
Settings/SettingsDialog.ui
Settings/USBBindingWidget_DrivingForce.ui
Settings/USBBindingWidget_GTForce.ui
Settings/USBBindingWidget_GunCon2.ui
Debugger/CpuWidget.cpp
Debugger/CpuWidget.h
Debugger/CpuWidget.ui
+1 -1
View File
@@ -589,7 +589,7 @@ static std::vector<u32> searchWorkerByteArray(DebugInterface* cpu, u32 start, u3
bool hit = true;
for (qsizetype i = 0; i < value.length(); i++)
{
if (cpu->read8(addr + i) != value[i])
if (static_cast<char>(cpu->read8(addr + i)) != value[i])
{
hit = false;
break;
+4 -3
View File
@@ -151,9 +151,10 @@ void DisassemblyWidget::contextNoopInstruction()
void DisassemblyWidget::contextRunToCursor()
{
Host::RunOnCPUThread([&] { CBreakPoints::AddBreakPoint(m_cpu->getCpuType(), m_selectedAddressStart); });
m_cpu->resumeCpu();
Host::RunOnCPUThread([&] {
CBreakPoints::AddBreakPoint(m_cpu->getCpuType(), m_selectedAddressStart, true);
m_cpu->resumeCpu();
});
}
void DisassemblyWidget::contextJumpToCursor()
+1 -1
View File
@@ -78,7 +78,7 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
{
QString type("");
type += (mc->cond & MEMCHECK_READ) ? tr("Read") : "";
type += ((mc->cond & MEMCHECK_BOTH) == MEMCHECK_BOTH) ? ", " : " ";
type += ((mc->cond & MEMCHECK_READWRITE) == MEMCHECK_READWRITE) ? ", " : " ";
//: (C) = changes, as in "look for changes".
type += (mc->cond & MEMCHECK_WRITE) ? (mc->cond & MEMCHECK_WRITE_ONCHANGE) ? tr("Write(C)") : tr("Write") : "";
return type;
+25 -6
View File
@@ -25,6 +25,7 @@
#include "QtHost.h"
#include "QtUtils.h"
#include "SettingWidgetBinder.h"
#include "Settings/AchievementLoginDialog.h"
#include "Settings/ControllerSettingsDialog.h"
#include "Settings/GameListSettingsWidget.h"
#include "Settings/InterfaceSettingsWidget.h"
@@ -414,7 +415,7 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
connect(thread, &EmuThread::onAcquireRenderWindowRequested, this, &MainWindow::acquireRenderWindow, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onReleaseRenderWindowRequested, this, &MainWindow::releaseRenderWindow, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onResizeRenderWindowRequested, this, &MainWindow::displayResizeRequested);
connect(thread, &EmuThread::onRelativeMouseModeRequested, this, &MainWindow::relativeMouseModeRequested);
connect(thread, &EmuThread::onMouseModeRequested, this, &MainWindow::mouseModeRequested);
connect(thread, &EmuThread::onVMStarting, this, &MainWindow::onVMStarting);
connect(thread, &EmuThread::onVMStarted, this, &MainWindow::onVMStarted);
connect(thread, &EmuThread::onVMPaused, this, &MainWindow::onVMPaused);
@@ -423,6 +424,7 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
connect(thread, &EmuThread::onGameChanged, this, &MainWindow::onGameChanged);
connect(thread, &EmuThread::onCaptureStarted, this, &MainWindow::onCaptureStarted);
connect(thread, &EmuThread::onCaptureStopped, this, &MainWindow::onCaptureStopped);
connect(thread, &EmuThread::onAchievementsLoginRequested, this, &MainWindow::onAchievementsLoginRequested);
connect(m_ui.actionReset, &QAction::triggered, thread, &EmuThread::resetVM);
connect(m_ui.actionPause, &QAction::toggled, thread, &EmuThread::setVMPaused);
@@ -628,6 +630,14 @@ void MainWindow::onCaptureStopped()
m_ui.actionToolsVideoCapture->setChecked(false);
}
void MainWindow::onAchievementsLoginRequested(Achievements::LoginRequestReason reason)
{
auto lock = pauseAndLockVM();
AchievementLoginDialog dlg(this, reason);
dlg.exec();
}
void MainWindow::onSettingsTriggeredFromToolbar()
{
if (s_vm_valid)
@@ -887,7 +897,8 @@ bool MainWindow::isRenderingToMain() const
bool MainWindow::shouldHideMouseCursor() const
{
return (isRenderingFullscreen() && Host::GetBoolSettingValue("UI", "HideMouseCursor", false)) || m_relative_mouse_mode;
return ((isRenderingFullscreen() && Host::GetBoolSettingValue("UI", "HideMouseCursor", false)) ||
m_relative_mouse_mode || m_hide_mouse_cursor);
}
bool MainWindow::shouldHideMainWindow() const
@@ -2003,12 +2014,13 @@ void MainWindow::displayResizeRequested(qint32 width, qint32 height)
QtUtils::ResizePotentiallyFixedSizeWindow(this, width, height + extra_height);
}
void MainWindow::relativeMouseModeRequested(bool enabled)
void MainWindow::mouseModeRequested(bool relative_mode, bool hide_cursor)
{
if (m_relative_mouse_mode == enabled)
if (m_relative_mouse_mode == relative_mode && m_hide_mouse_cursor == hide_cursor)
return;
m_relative_mouse_mode = enabled;
m_relative_mouse_mode = relative_mode;
m_hide_mouse_cursor = hide_cursor;
if (m_display_widget && !s_vm_paused)
updateDisplayWidgetCursor();
}
@@ -2273,7 +2285,8 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
if (filename.isEmpty())
return;
if (!GameList::GetCoverImagePathForEntry(entry).empty())
const QString old_filename = QString::fromStdString(GameList::GetCoverImagePathForEntry(entry));
if (!old_filename.isEmpty())
{
if (QMessageBox::question(this, tr("Cover Already Exists"),
tr("A cover image for this game already exists, do you wish to replace it?"), QMessageBox::Yes,
@@ -2299,6 +2312,12 @@ void MainWindow::setGameListEntryCoverImage(const GameList::Entry* entry)
return;
}
if (!old_filename.isEmpty() && old_filename != new_filename && !QFile::remove(old_filename))
{
QMessageBox::critical(this, tr("Copy Error"), tr("Failed to remove '%1'").arg(old_filename));
return;
}
m_game_list_widget->refreshGridCovers();
}
+9 -1
View File
@@ -39,6 +39,11 @@ class ControllerSettingsDialog;
class EmuThread;
namespace Achievements
{
enum class LoginRequestReason;
}
namespace GameList
{
struct Entry;
@@ -124,7 +129,7 @@ private Q_SLOTS:
std::optional<WindowInfo> acquireRenderWindow(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
void displayResizeRequested(qint32 width, qint32 height);
void relativeMouseModeRequested(bool enabled);
void mouseModeRequested(bool relative_mode, bool hide_cursor);
void releaseRenderWindow();
void focusDisplayWidget();
@@ -186,6 +191,8 @@ private Q_SLOTS:
void onCaptureStarted(const QString& filename);
void onCaptureStopped();
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
protected:
void showEvent(QShowEvent* event) override;
void closeEvent(QCloseEvent* event) override;
@@ -293,6 +300,7 @@ private:
bool m_display_created = false;
bool m_relative_mouse_mode = false;
bool m_hide_mouse_cursor = false;
bool m_was_paused_on_surface_loss = false;
bool m_was_disc_change_request = false;
bool m_is_closing = false;
+16
View File
@@ -184,6 +184,10 @@
<property name="title">
<string>Input Recording</string>
</property>
<property name="icon">
<iconset theme="keyboard-line">
<normaloff>.</normaloff>.</iconset>
</property>
<addaction name="actionInputRecNew"/>
<addaction name="actionInputRecPlay"/>
<addaction name="actionInputRecStop"/>
@@ -863,6 +867,10 @@
<property name="text">
<string>Toggle Software Rendering</string>
</property>
<property name="icon">
<iconset theme="brush-line">
<normaloff>.</normaloff>.</iconset>
</property>
</action>
<action name="actionDebugger">
<property name="icon">
@@ -877,6 +885,10 @@
<property name="text">
<string>Reload Cheats/Patches</string>
</property>
<property name="icon">
<iconset theme="refresh-line">
<normaloff>.</normaloff>.</iconset>
</property>
</action>
<action name="actionEnableSystemConsole">
<property name="checkable">
@@ -914,6 +926,10 @@
<property name="text">
<string>Save Single Frame GS Dump</string>
</property>
<property name="icon">
<iconset theme="save-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
</action>
<action name="actionInputRecNew">
<property name="enabled">
+8 -3
View File
@@ -40,7 +40,6 @@
#include "pcsx2/Input/InputManager.h"
#include "pcsx2/LogSink.h"
#include "pcsx2/MTGS.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/SysForwardDefs.h"
#include "pcsx2/VMManager.h"
@@ -1080,6 +1079,11 @@ void Host::OnSaveStateSaved(const std::string_view& filename)
}
#ifdef ENABLE_ACHIEVEMENTS
void Host::OnAchievementsLoginRequested(Achievements::LoginRequestReason reason)
{
emit g_emu_thread->onAchievementsLoginRequested(reason);
}
void Host::OnAchievementsRefreshed()
{
u32 game_id = 0;
@@ -1469,9 +1473,9 @@ void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
emit g_emu_thread->onInputDeviceDisconnected(identifier.empty() ? QString() : QString::fromUtf8(identifier.data(), identifier.size()));
}
void Host::SetRelativeMouseMode(bool enabled)
void Host::SetMouseMode(bool relative_mode, bool hide_cursor)
{
emit g_emu_thread->onRelativeMouseModeRequested(enabled);
emit g_emu_thread->onMouseModeRequested(relative_mode, hide_cursor);
}
//////////////////////////////////////////////////////////////////////////
@@ -1779,6 +1783,7 @@ void QtHost::RegisterTypes()
qRegisterMetaType<InputBindingKey>();
qRegisterMetaType<CDVD_SourceType>();
qRegisterMetaType<const GameList::Entry*>();
qRegisterMetaType<Achievements::LoginRequestReason>();
}
bool QtHost::RunSetupWizard()
+10 -1
View File
@@ -41,11 +41,17 @@ struct VMBootParameters;
enum class CDVD_SourceType : uint8_t;
namespace Achievements
{
enum class LoginRequestReason;
}
Q_DECLARE_METATYPE(std::shared_ptr<VMBootParameters>);
Q_DECLARE_METATYPE(std::optional<bool>);
Q_DECLARE_METATYPE(GSRendererType);
Q_DECLARE_METATYPE(InputBindingKey);
Q_DECLARE_METATYPE(CDVD_SourceType);
Q_DECLARE_METATYPE(Achievements::LoginRequestReason);
class EmuThread : public QThread
{
@@ -119,7 +125,7 @@ Q_SIGNALS:
std::optional<WindowInfo> onAcquireRenderWindowRequested(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
void onResizeRenderWindowRequested(qint32 width, qint32 height);
void onReleaseRenderWindowRequested();
void onRelativeMouseModeRequested(bool enabled);
void onMouseModeRequested(bool relative_mode, bool hide_cursor);
/// Called when the VM is starting initialization, but has not been completed yet.
void onVMStarting();
@@ -155,6 +161,9 @@ Q_SIGNALS:
/// just signifies that the save has started, not necessarily completed.
void onSaveStateSaved(const QString& path);
/// Called when achievements login is requested.
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
/// Called when achievements are reloaded/refreshed (e.g. game change, login, option change).
void onAchievementsRefreshed(quint32 id, const QString& game_info_string, quint32 total, quint32 points);
+10 -1
View File
@@ -22,13 +22,22 @@
#include <QtWidgets/QMessageBox>
AchievementLoginDialog::AchievementLoginDialog(QWidget* parent)
AchievementLoginDialog::AchievementLoginDialog(QWidget* parent, Achievements::LoginRequestReason reason)
: QDialog(parent)
{
m_ui.setupUi(this);
m_ui.loginIcon->setPixmap(QIcon::fromTheme("login-box-line").pixmap(32));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
// Adjust text if needed based on reason.
if (reason == Achievements::LoginRequestReason::TokenInvalid)
{
m_ui.instructionText->setText(
tr("<strong>Your RetroAchievements login token is no longer valid.</strong> You must re-enter your "
"credentials for achievements to be tracked. Your password will not be saved in PCSX2, an access token "
"will be generated and used instead."));
}
m_login = m_ui.buttonBox->addButton(tr("&Login"), QDialogButtonBox::AcceptRole);
m_login->setEnabled(false);
connectUi();
+7 -1
View File
@@ -18,12 +18,17 @@
#include <QtWidgets/QDialog>
#include <QtWidgets/QPushButton>
namespace Achievements
{
enum class LoginRequestReason;
}
class AchievementLoginDialog : public QDialog
{
Q_OBJECT
public:
AchievementLoginDialog(QWidget* parent);
AchievementLoginDialog(QWidget* parent, Achievements::LoginRequestReason reason);
~AchievementLoginDialog();
private Q_SLOTS:
@@ -38,4 +43,5 @@ private:
Ui::AchievementLoginDialog m_ui;
QPushButton* m_login;
Achievements::LoginRequestReason m_reason;
};
+1 -1
View File
@@ -51,7 +51,7 @@
</layout>
</item>
<item>
<widget class="QLabel" name="label_3">
<widget class="QLabel" name="instructionText">
<property name="text">
<string>Please enter user name and password for retroachievements.org below. Your password will not be saved in PCSX2, an access token will be generated and used instead.</string>
</property>
@@ -173,7 +173,7 @@ void AchievementSettingsWidget::onLoginLogoutPressed()
return;
}
AchievementLoginDialog login(this);
AchievementLoginDialog login(this, Achievements::LoginRequestReason::UserInitiated);
int res = login.exec();
if (res != 0)
return;
@@ -0,0 +1,317 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ControllerBindingWidget_Guitar</class>
<widget class="QWidget" name="ControllerBindingWidget_Guitar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1100</width>
<height>500</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1101</width>
<height>322</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label">
<property name="maximumSize">
<size>
<width>800</width>
<height>320</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="../resources/resources.qrc">:/images/guitar.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>320</y>
<width>1101</width>
<height>181</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="6">
<widget class="QGroupBox" name="groupBox_7">
<property name="title">
<string>Yellow</string>
</property>
<widget class="InputBindingWidget" name="Yellow">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Start</string>
</property>
<widget class="InputBindingWidget" name="Start">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="7">
<widget class="QGroupBox" name="groupBox_8">
<property name="title">
<string>Red</string>
</property>
<widget class="InputBindingWidget" name="Red">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="8">
<widget class="QGroupBox" name="groupBox_9">
<property name="title">
<string>Green</string>
</property>
<widget class="InputBindingWidget" name="Green">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="3">
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Orange</string>
</property>
<widget class="InputBindingWidget" name="Orange">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Select</string>
</property>
<widget class="InputBindingWidget" name="Select">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Strum Up</string>
</property>
<widget class="InputBindingWidget" name="Up">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="1" column="2">
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Strum Down</string>
</property>
<widget class="InputBindingWidget" name="Down">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="0" column="5">
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Blue</string>
</property>
<widget class="InputBindingWidget" name="Blue">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_10">
<property name="title">
<string>Whammy Bar</string>
</property>
<widget class="InputBindingWidget" name="Whammy">
<property name="geometry">
<rect>
<x>24</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="groupBox_11">
<property name="title">
<string>Tilt</string>
</property>
<widget class="InputBindingWidget" name="Tilt">
<property name="geometry">
<rect>
<x>20</x>
<y>30</y>
<width>90</width>
<height>40</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
</item>
</layout>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>InputBindingWidget</class>
<extends>QPushButton</extends>
<header>Settings/InputBindingWidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../resources/resources.qrc"/>
</resources>
<connections/>
</ui>
+69 -28
View File
@@ -26,7 +26,7 @@
#include "common/StringUtil.h"
#include "pcsx2/Host.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/SIO/Pad/Pad.h"
#include "Settings/ControllerBindingWidgets.h"
#include "Settings/ControllerSettingsDialog.h"
@@ -38,6 +38,7 @@
#include "ui_USBBindingWidget_DrivingForce.h"
#include "ui_USBBindingWidget_GTForce.h"
#include "ui_USBBindingWidget_GunCon2.h"
ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSettingsDialog* dialog, u32 port)
: QWidget(parent)
@@ -52,7 +53,7 @@ ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSett
onTypeChanged();
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(
m_dialog->getProfileSettingsInterface(), m_ui.controllerType, m_config_section, "Type", PAD::GetDefaultPadType(port));
m_dialog->getProfileSettingsInterface(), m_ui.controllerType, m_config_section, "Type", Pad::GetDefaultPadType(port));
connect(m_ui.controllerType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ControllerBindingWidget::onTypeChanged);
connect(m_ui.bindings, &QPushButton::clicked, this, &ControllerBindingWidget::onBindingsClicked);
@@ -71,14 +72,14 @@ QIcon ControllerBindingWidget::getIcon() const
void ControllerBindingWidget::populateControllerTypes()
{
for (const auto& [name, display_name] : PAD::GetControllerTypeNames())
m_ui.controllerType->addItem(qApp->translate("Pad", display_name), QString::fromStdString(name));
for (const auto& [name, display_name] : Pad::GetControllerTypeNames())
m_ui.controllerType->addItem(QString::fromUtf8(display_name), QString::fromUtf8(name));
}
void ControllerBindingWidget::onTypeChanged()
{
const bool is_initializing = (m_ui.stackedWidget->count() == 0);
m_controller_type = m_dialog->getStringValue(m_config_section.c_str(), "Type", PAD::GetDefaultPadType(m_port_number));
m_controller_type = m_dialog->getStringValue(m_config_section.c_str(), "Type", Pad::GetDefaultPadType(m_port_number));
if (m_bindings_widget)
{
@@ -99,25 +100,32 @@ void ControllerBindingWidget::onTypeChanged()
m_macros_widget = nullptr;
}
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(m_controller_type);
const bool has_settings = (cinfo && cinfo->num_settings > 0);
const bool has_macros = (cinfo && cinfo->num_bindings > 0);
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_controller_type);
const bool has_settings = (cinfo && !cinfo->settings.empty());
const bool has_macros = (cinfo && !cinfo->bindings.empty());
m_ui.settings->setEnabled(has_settings);
m_ui.macros->setEnabled(has_macros);
if (m_controller_type == "DualShock2")
{
m_bindings_widget = ControllerBindingWidget_DualShock2::createInstance(this);
}
else if (m_controller_type == "Guitar")
{
m_bindings_widget = ControllerBindingWidget_Guitar::createInstance(this);
}
else
{
m_bindings_widget = new ControllerBindingWidget_Base(this);
}
m_ui.stackedWidget->addWidget(m_bindings_widget);
m_ui.stackedWidget->setCurrentWidget(m_bindings_widget);
if (has_settings)
{
const std::span<const SettingInfo> settings(cinfo->settings, cinfo->num_settings);
m_settings_widget = new ControllerCustomSettingsWidget(
settings, m_config_section, std::string(), "Pad", getDialog(), m_ui.stackedWidget);
cinfo->settings, m_config_section, std::string(), "Pad", getDialog(), m_ui.stackedWidget);
m_ui.stackedWidget->addWidget(m_settings_widget);
}
@@ -210,13 +218,13 @@ void ControllerBindingWidget::onClearBindingsClicked()
{
{
auto lock = Host::GetSettingsLock();
PAD::ClearPortBindings(*Host::Internal::GetBaseSettingsLayer(), m_port_number);
Pad::ClearPortBindings(*Host::Internal::GetBaseSettingsLayer(), m_port_number);
}
Host::CommitBaseSettingChanges();
}
else
{
PAD::ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number);
Pad::ClearPortBindings(*m_dialog->getProfileSettingsInterface(), m_port_number);
m_dialog->getProfileSettingsInterface()->Save();
}
@@ -240,14 +248,14 @@ void ControllerBindingWidget::doDeviceAutomaticBinding(const QString& device)
{
{
auto lock = Host::GetSettingsLock();
result = PAD::MapController(*Host::Internal::GetBaseSettingsLayer(), m_port_number, mapping);
result = Pad::MapController(*Host::Internal::GetBaseSettingsLayer(), m_port_number, mapping);
}
if (result)
Host::CommitBaseSettingChanges();
}
else
{
result = PAD::MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping);
result = Pad::MapController(*m_dialog->getProfileSettingsInterface(), m_port_number, mapping);
if (result)
{
m_dialog->getProfileSettingsInterface()->Save();
@@ -312,7 +320,7 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare
ControllerSettingsDialog* dialog = m_bwidget->getDialog();
const std::string& section = m_bwidget->getConfigSection();
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(m_bwidget->getControllerType());
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_bwidget->getControllerType());
if (!cinfo)
{
// Shouldn't ever happen.
@@ -325,20 +333,19 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare
for (const std::string_view& button : buttons_split)
{
for (u32 i = 0; i < cinfo->num_bindings; i++)
for (const InputBindingInfo& bi : cinfo->bindings)
{
if (button == cinfo->bindings[i].name)
if (button == bi.name)
{
m_binds.push_back(&cinfo->bindings[i]);
m_binds.push_back(&bi);
break;
}
}
}
// populate list view
for (u32 i = 0; i < cinfo->num_bindings; i++)
for (const InputBindingInfo& bi : cinfo->bindings)
{
const InputBindingInfo& bi = cinfo->bindings[i];
if (bi.bind_type == InputBindingInfo::Type::Motor)
continue;
@@ -350,8 +357,12 @@ ControllerMacroEditWidget::ControllerMacroEditWidget(ControllerMacroWidget* pare
ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(
dialog->getProfileSettingsInterface(), m_ui.pressure, section, fmt::format("Macro{}Pressure", index + 1u), 100.0f, 1.0f);
ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(
dialog->getProfileSettingsInterface(), m_ui.deadzone, section, fmt::format("Macro{}Deadzone", index + 1u), 100.0f, 0.0f);
connect(m_ui.pressure, &QSlider::valueChanged, this, &ControllerMacroEditWidget::onPressureChanged);
connect(m_ui.deadzone, &QSlider::valueChanged, this, &ControllerMacroEditWidget::onDeadzoneChanged);
onPressureChanged();
onDeadzoneChanged();
m_frequency = dialog->getIntValue(section.c_str(), fmt::format("Macro{}Frequency", index + 1u).c_str(), 0);
updateFrequencyText();
@@ -384,6 +395,11 @@ void ControllerMacroEditWidget::onPressureChanged()
m_ui.pressureValue->setText(tr("%1%").arg(m_ui.pressure->value()));
}
void ControllerMacroEditWidget::onDeadzoneChanged()
{
m_ui.deadzoneValue->setText(tr("%1%").arg(m_ui.deadzone->value()));
}
void ControllerMacroEditWidget::onSetFrequencyClicked()
{
bool okay;
@@ -423,12 +439,12 @@ void ControllerMacroEditWidget::updateFrequencyText()
void ControllerMacroEditWidget::updateBinds()
{
ControllerSettingsDialog* dialog = m_bwidget->getDialog();
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(m_bwidget->getControllerType());
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(m_bwidget->getControllerType());
if (!cinfo)
return;
std::vector<const InputBindingInfo*> new_binds;
for (u32 i = 0, bind_index = 0; i < cinfo->num_bindings; i++)
for (u32 i = 0, bind_index = 0; i < static_cast<u32>(cinfo->bindings.size()); i++)
{
const InputBindingInfo& bi = cinfo->bindings[i];
if (bi.bind_type == InputBindingInfo::Type::Motor)
@@ -793,16 +809,15 @@ QIcon ControllerBindingWidget_Base::getIcon() const
void ControllerBindingWidget_Base::initBindingWidgets()
{
const PAD::ControllerInfo* cinfo = PAD::GetControllerInfo(getControllerType());
const Pad::ControllerInfo* cinfo = Pad::GetControllerInfo(getControllerType());
if (!cinfo)
return;
const std::string& config_section = getConfigSection();
SettingsInterface* sif = getDialog()->getProfileSettingsInterface();
for (u32 i = 0; i < cinfo->num_bindings; i++)
for (const InputBindingInfo& bi : cinfo->bindings)
{
const InputBindingInfo& bi = cinfo->bindings[i];
if (bi.bind_type == InputBindingInfo::Type::Axis || bi.bind_type == InputBindingInfo::Type::HalfAxis ||
bi.bind_type == InputBindingInfo::Type::Button || bi.bind_type == InputBindingInfo::Type::Pointer ||
bi.bind_type == InputBindingInfo::Type::Device)
@@ -820,7 +835,7 @@ void ControllerBindingWidget_Base::initBindingWidgets()
switch (cinfo->vibration_caps)
{
case PAD::VibrationCapabilities::LargeSmallMotors:
case Pad::VibrationCapabilities::LargeSmallMotors:
{
InputVibrationBindingWidget* widget = findChild<InputVibrationBindingWidget*>(QStringLiteral("LargeMotor"));
if (widget)
@@ -832,7 +847,7 @@ void ControllerBindingWidget_Base::initBindingWidgets()
}
break;
case PAD::VibrationCapabilities::SingleMotor:
case Pad::VibrationCapabilities::SingleMotor:
{
InputVibrationBindingWidget* widget = findChild<InputVibrationBindingWidget*>(QStringLiteral("Motor"));
if (widget)
@@ -840,7 +855,7 @@ void ControllerBindingWidget_Base::initBindingWidgets()
}
break;
case PAD::VibrationCapabilities::NoVibration:
case Pad::VibrationCapabilities::NoVibration:
default:
break;
}
@@ -867,6 +882,27 @@ ControllerBindingWidget_Base* ControllerBindingWidget_DualShock2::createInstance
return new ControllerBindingWidget_DualShock2(parent);
}
ControllerBindingWidget_Guitar::ControllerBindingWidget_Guitar(ControllerBindingWidget* parent)
: ControllerBindingWidget_Base(parent)
{
m_ui.setupUi(this);
initBindingWidgets();
}
ControllerBindingWidget_Guitar::~ControllerBindingWidget_Guitar()
{
}
QIcon ControllerBindingWidget_Guitar::getIcon() const
{
return QIcon::fromTheme("guitar-line");
}
ControllerBindingWidget_Base* ControllerBindingWidget_Guitar::createInstance(ControllerBindingWidget* parent)
{
return new ControllerBindingWidget_Guitar(parent);
}
//////////////////////////////////////////////////////////////////////////
USBDeviceWidget::USBDeviceWidget(QWidget* parent, ControllerSettingsDialog* dialog, u32 port)
@@ -1240,6 +1276,11 @@ USBBindingWidget* USBBindingWidget::createInstance(
has_template = true;
}
}
else if (type == "guncon2")
{
Ui::USBBindingWidget_GunCon2().setupUi(widget);
has_template = true;
}
if (has_template)
widget->bindWidgets(bindings);
+20 -2
View File
@@ -15,7 +15,7 @@
#pragma once
#include "PAD/Host/PAD.h"
#include "pcsx2/SIO/Pad/PadTypes.h"
#include <QtWidgets/QWidget>
@@ -23,6 +23,7 @@
#include "ui_ControllerBindingWidget.h"
#include "ui_ControllerBindingWidget_DualShock2.h"
#include "ui_ControllerBindingWidget_Guitar.h"
#include "ui_ControllerMacroWidget.h"
#include "ui_ControllerMacroEditWidget.h"
#include "ui_USBDeviceWidget.h"
@@ -91,7 +92,7 @@ public:
void updateListItem(u32 index);
private:
static constexpr u32 NUM_MACROS = PAD::NUM_MACRO_BUTTONS_PER_CONTROLLER;
static constexpr u32 NUM_MACROS = Pad::NUM_MACRO_BUTTONS_PER_CONTROLLER;
void createWidgets(ControllerBindingWidget* parent);
@@ -114,6 +115,7 @@ public:
private Q_SLOTS:
void onPressureChanged();
void onDeadzoneChanged();
void onSetFrequencyClicked();
void updateBinds();
@@ -193,6 +195,22 @@ private:
Ui::ControllerBindingWidget_DualShock2 m_ui;
};
class ControllerBindingWidget_Guitar final : public ControllerBindingWidget_Base
{
Q_OBJECT
public:
ControllerBindingWidget_Guitar(ControllerBindingWidget* parent);
~ControllerBindingWidget_Guitar();
QIcon getIcon() const override;
static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent);
private:
Ui::ControllerBindingWidget_Guitar m_ui;
};
//////////////////////////////////////////////////////////////////////////
class USBDeviceWidget final : public QWidget
+44 -1
View File
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>691</width>
<height>547</height>
<height>433</height>
</rect>
</property>
<property name="windowTitle">
@@ -83,6 +83,9 @@
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item>
@@ -123,6 +126,46 @@
</property>
</widget>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="deadzoneLayout" stretch="0,1,0">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Deadzone:</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="deadzone">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>100</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>10</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="deadzoneValue">
<property name="text">
<string>100%</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
+10 -10
View File
@@ -22,8 +22,8 @@
#include "Settings/HotkeySettingsWidget.h"
#include "pcsx2/INISettingsInterface.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/Sio.h"
#include "pcsx2/SIO/Pad/Pad.h"
#include "pcsx2/SIO/Sio.h"
#include "pcsx2/VMManager.h"
#include "common/Assertions.h"
@@ -130,7 +130,7 @@ void ControllerSettingsDialog::onNewProfileClicked()
{
// from global
auto lock = Host::GetSettingsLock();
PAD::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true, false);
Pad::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true, false);
USB::CopyConfiguration(&temp_si, *Host::Internal::GetBaseSettingsLayer(), true, true);
}
else
@@ -138,7 +138,7 @@ void ControllerSettingsDialog::onNewProfileClicked()
// from profile
const bool copy_hotkey_bindings = m_profile_interface->GetBoolValue("Pad", "UseProfileHotkeyBindings", false);
temp_si.SetBoolValue("Pad", "UseProfileHotkeyBindings", copy_hotkey_bindings);
PAD::CopyConfiguration(&temp_si, *m_profile_interface, true, true, copy_hotkey_bindings);
Pad::CopyConfiguration(&temp_si, *m_profile_interface, true, true, copy_hotkey_bindings);
USB::CopyConfiguration(&temp_si, *m_profile_interface, true, true);
}
}
@@ -167,7 +167,7 @@ void ControllerSettingsDialog::onLoadProfileClicked()
{
auto lock = Host::GetSettingsLock();
PAD::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false);
Pad::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true, false);
USB::CopyConfiguration(Host::Internal::GetBaseSettingsLayer(), *m_profile_interface, true, true);
}
Host::CommitBaseSettingChanges();
@@ -403,8 +403,8 @@ void ControllerSettingsDialog::createWidgets()
m_port_bindings[global_slot] = new ControllerBindingWidget(m_ui.settingsContainer, this, global_slot);
m_ui.settingsContainer->addWidget(m_port_bindings[global_slot]);
const PAD::ControllerInfo* ci = PAD::GetControllerInfo(m_port_bindings[global_slot]->getControllerType());
const QString display_name(ci ? qApp->translate("Pad", ci->display_name) : QStringLiteral("Unknown"));
const Pad::ControllerInfo* ci = Pad::GetControllerInfo(m_port_bindings[global_slot]->getControllerType());
const QString display_name(QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown"));
QListWidgetItem* item = new QListWidgetItem();
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
@@ -459,8 +459,8 @@ void ControllerSettingsDialog::updateListDescription(u32 global_slot, Controller
const auto [port, slot] = sioConvertPadToPortAndSlot(global_slot);
const bool mtap_enabled = getBoolValue("Pad", (port == 0) ? "MultitapPort1" : "MultitapPort2", false);
const PAD::ControllerInfo* ci = PAD::GetControllerInfo(widget->getControllerType());
const QString display_name(ci ? qApp->translate("Pad", ci->display_name) : QStringLiteral("Unknown"));
const Pad::ControllerInfo* ci = Pad::GetControllerInfo(widget->getControllerType());
const QString display_name = QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown");
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
item->setText(mtap_enabled ? (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name)) :
@@ -492,7 +492,7 @@ void ControllerSettingsDialog::updateListDescription(u32 port, USBDeviceWidget*
void ControllerSettingsDialog::refreshProfileList()
{
const std::vector<std::string> names(PAD::GetInputProfileNames());
const std::vector<std::string> names = Pad::GetInputProfileNames();
QSignalBlocker sb(m_ui.currentProfile);
m_ui.currentProfile->clear();
+218 -2
View File
@@ -15,21 +15,28 @@
#include "PrecompiledHeader.h"
#include "pcsx2/SIO/Pad/Pad.h"
#include "GameSummaryWidget.h"
#include "SettingsDialog.h"
#include "MainWindow.h"
#include "QtHost.h"
#include "QtProgressCallback.h"
#include "QtUtils.h"
#include "pcsx2/CDVD/IsoHasher.h"
#include "pcsx2/GameDatabase.h"
#include "pcsx2/GameList.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "common/Error.h"
#include "common/MD5Digest.h"
#include "common/ScopedGuard.h"
#include "common/StringUtil.h"
#include "fmt/format.h"
#include <QtCore/QDir>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QMessageBox>
GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent)
: m_dialog(dialog)
@@ -51,15 +58,18 @@ GameSummaryWidget::GameSummaryWidget(const GameList::Entry* entry, SettingsDialo
populateInputProfiles();
populateDetails(entry);
populateDiscPath(entry);
populateTrackList(entry);
connect(m_ui.inputProfile, &QComboBox::currentIndexChanged, this, &GameSummaryWidget::onInputProfileChanged);
connect(m_ui.verify, &QAbstractButton::clicked, this, &GameSummaryWidget::onVerifyClicked);
connect(m_ui.searchHash, &QAbstractButton::clicked, this, &GameSummaryWidget::onSearchHashClicked);
}
GameSummaryWidget::~GameSummaryWidget() = default;
void GameSummaryWidget::populateInputProfiles()
{
for (const std::string& name : PAD::GetInputProfileNames())
for (const std::string& name : Pad::GetInputProfileNames())
m_ui.inputProfile->addItem(QString::fromStdString(name));
}
@@ -137,3 +147,209 @@ void GameSummaryWidget::onDiscPathBrowseClicked()
// let the signal take care of it
m_ui.discPath->setText(QDir::toNativeSeparators(filename));
}
void GameSummaryWidget::populateTrackList(const GameList::Entry* entry)
{
if (entry->type != GameList::EntryType::PS1Disc && entry->type != GameList::EntryType::PS2Disc)
{
m_ui.verify->setEnabled(false);
m_ui.verifyResult->setPlainText(tr("Game is not a CD/DVD."));
return;
}
if (QtHost::IsVMValid())
{
m_ui.verify->setEnabled(false);
m_ui.verifyResult->setPlainText(tr("Track list unavailable while virtual machine is running."));
return;
}
IsoHasher hasher;
Error error;
if (!hasher.Open(m_entry_path, &error))
{
m_ui.verify->setEnabled(false);
m_ui.verifyResult->setPlainText(QString::fromStdString(error.GetDescription()));
return;
}
const auto AddColumn = [this](const QString& text) {
QTableWidgetItem* item = new QTableWidgetItem(text);
const int column = m_ui.tracks->columnCount();
m_ui.tracks->insertColumn(column);
m_ui.tracks->setHorizontalHeaderItem(column, item);
};
const auto SetColumn = [this](int row, int column, const QString& text) {
QTableWidgetItem* item = new QTableWidgetItem(text);
m_ui.tracks->setItem(row, column, item);
};
// columns depend on CD vs DVD.
AddColumn(tr("#"));
if (hasher.IsCD())
{
AddColumn(tr("Mode"));
AddColumn(tr("Start"));
AddColumn(tr("Sectors"));
AddColumn(tr("Size"));
AddColumn(tr("MD5"));
AddColumn(tr("Status"));
}
else
{
AddColumn(tr("Start"));
AddColumn(tr("Sectors"));
AddColumn(tr("Size"));
AddColumn(tr("MD5"));
AddColumn(tr("Status"));
}
for (const IsoHasher::Track& track : hasher.GetTracks())
{
const int row = m_ui.tracks->rowCount();
m_ui.tracks->insertRow(row);
SetColumn(row, 0, tr("%1").arg(track.number));
if (hasher.IsCD())
{
SetColumn(row, 1, QtUtils::StringViewToQString(IsoHasher::GetTrackTypeString(track.type)));
SetColumn(row, 2, tr("%1").arg(track.start_lsn));
SetColumn(row, 3, tr("%1").arg(track.sectors));
SetColumn(row, 4, tr("%1").arg(track.size));
SetColumn(row, 5, tr("<not computed>"));
SetColumn(row, 6, QString());
}
else
{
SetColumn(row, 1, tr("%1").arg(track.start_lsn));
SetColumn(row, 2, tr("%1").arg(track.sectors));
SetColumn(row, 3, tr("%1").arg(track.size));
SetColumn(row, 4, tr("<not computed>"));
SetColumn(row, 5, QString());
}
}
if (hasher.IsCD())
QtUtils::ResizeColumnsForTableView(m_ui.tracks, {20, 60, 70, 70, 100, 220, 40});
else
QtUtils::ResizeColumnsForTableView(m_ui.tracks, {20, 100, 100, 100, 220, 40});
}
void GameSummaryWidget::onVerifyClicked()
{
// Can't do this while a VM is running because of stupid CDVD.
if (QtHost::IsVMValid())
{
QMessageBox::critical(QtUtils::GetRootWidget(this), tr("Error"), tr("Cannot verify image while a game is running."));
return;
}
IsoHasher hasher;
Error error;
if (!hasher.Open(m_entry_path, &error))
{
setVerifyResult(QString::fromStdString(error.GetDescription()));
return;
}
QtModalProgressCallback callback(this);
hasher.ComputeHashes(&callback);
if (callback.IsCancelled())
return;
const int hash_column = hasher.IsCD() ? 5 : 4;
int row = 0;
// convert to database format
std::vector<GameDatabase::TrackHash> thashes;
thashes.reserve(hasher.GetTrackCount());
for (const IsoHasher::Track& track : hasher.GetTracks())
{
GameDatabase::TrackHash thash;
thash.size = track.size;
if (track.hash.empty() || !thash.parseHash(track.hash))
{
m_ui.verify->setEnabled(false);
m_ui.verifyResult->setPlainText(tr("One or more tracks is missing."));
return;
}
// Use the first track's hash as the redump search term.
if (m_redump_search_keyword.empty())
m_redump_search_keyword = thash.toString();
thashes.push_back(thash);
}
// match the hashes. can't use vector<bool> here because it's not an actual array
std::unique_ptr<bool[]> val_results = std::make_unique<bool[]>(hasher.GetTrackCount());
std::string match_error;
const GameDatabase::HashDatabaseEntry* hentry =
GameDatabase::lookupHash(thashes.data(), thashes.size(), val_results.get(), &match_error);
// fill the UI with both the hashes and validation results
for (u32 i = 0; i < hasher.GetTrackCount(); i++)
{
QTableWidgetItem* const hash_item = m_ui.tracks->item(row, hash_column);
QTableWidgetItem* const status_item = m_ui.tracks->item(row, hash_column + 1);
const bool result = val_results[i];
const QBrush brush(result ? QColor(0, 200, 0) : QColor(200, 0, 0));
hash_item->setText(QString::fromStdString(hasher.GetTrack(i).hash));
hash_item->setForeground(brush);
status_item->setText(result ? QStringLiteral("\u2713") : QStringLiteral("\u2715"));
status_item->setForeground(brush);
row++;
}
if (hentry)
{
if (!hentry->version.empty())
{
setVerifyResult(tr("Verified as %1 [%2] (Version %3).")
.arg(QString::fromStdString(hentry->name))
.arg(QString::fromStdString(hentry->serial))
.arg(QString::fromStdString(hentry->version)));
}
else
{
setVerifyResult(tr("Verified as %1 [%2].")
.arg(QString::fromStdString(hentry->name))
.arg(QString::fromStdString(hentry->serial)));
}
}
else
{
setVerifyResult(QString::fromStdString(match_error));
}
}
void GameSummaryWidget::onSearchHashClicked()
{
if (m_redump_search_keyword.empty())
return;
QtUtils::OpenURL(this, fmt::format("http://redump.org/discs/quicksearch/{}", m_redump_search_keyword).c_str());
}
void GameSummaryWidget::setVerifyResult(QString error)
{
m_ui.verify->setVisible(false);
m_ui.verifyButtonLayout->removeWidget(m_ui.verify);
m_ui.verify->deleteLater();
m_ui.verify = nullptr;
m_ui.verifyButtonLayout->removeItem(m_ui.verifyButtonSpacer);
delete m_ui.verifyButtonSpacer;
m_ui.verifyButtonSpacer = nullptr;
m_ui.verifyLayout->removeItem(m_ui.verifyButtonLayout);
m_ui.verifyButtonLayout->deleteLater();
m_ui.verifyButtonLayout = nullptr;
m_ui.verifyLayout->update();
updateGeometry();
m_ui.verifyResult->setPlainText(error);
m_ui.verifyResult->setVisible(true);
m_ui.searchHash->setVisible(true);
}
+10 -4
View File
@@ -34,16 +34,22 @@ public:
GameSummaryWidget(const GameList::Entry* entry, SettingsDialog* dialog, QWidget* parent);
~GameSummaryWidget();
private Q_SLOTS:
void onInputProfileChanged(int index);
void onDiscPathChanged(const QString& value);
void onDiscPathBrowseClicked();
void onVerifyClicked();
void onSearchHashClicked();
private:
void populateInputProfiles();
void populateDetails(const GameList::Entry* entry);
void populateDiscPath(const GameList::Entry* entry);
void onInputProfileChanged(int index);
void onDiscPathChanged(const QString& value);
void onDiscPathBrowseClicked();
void populateTrackList(const GameList::Entry* entry);
void setVerifyResult(QString error);
Ui::GameSummaryWidget m_ui;
SettingsDialog* m_dialog;
std::string m_entry_path;
std::string m_redump_search_keyword;
};
+87 -3
View File
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>692</width>
<height>562</height>
<width>641</width>
<height>467</height>
</rect>
</property>
<layout class="QFormLayout" name="detailsFormLayout">
@@ -413,7 +413,7 @@
</item>
</layout>
</item>
<item row="9" column="1">
<item row="10" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@@ -426,6 +426,90 @@
</property>
</spacer>
</item>
<item row="9" column="0" colspan="2">
<layout class="QVBoxLayout" name="verifyLayout">
<item>
<widget class="QTableWidget" name="tracks">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="verifyButtonLayout">
<item>
<spacer name="verifyButtonSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="verify">
<property name="text">
<string>Verify</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" rowspan="3">
<widget class="QPlainTextEdit" name="verifyResult">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>60</height>
</size>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="searchHash">
<property name="text">
<string>Search on Redump.org...</string>
</property>
<property name="visible">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
+1 -1
View File
@@ -218,12 +218,12 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsDialog* dialog, QWidget*
//////////////////////////////////////////////////////////////////////////
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.halfPixelOffset, "EmuCore/GS", "UserHacks_HalfPixelOffset", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.roundSprite, "EmuCore/GS", "UserHacks_round_sprite_offset", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.bilinearHack, "EmuCore/GS", "UserHacks_BilinearHack", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetX, "EmuCore/GS", "UserHacks_TCOffsetX", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.textureOffsetY, "EmuCore/GS", "UserHacks_TCOffsetY", 0);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.alignSprite, "EmuCore/GS", "UserHacks_align_sprite_X", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.mergeSprite, "EmuCore/GS", "UserHacks_merge_pp_sprite", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.wildHack, "EmuCore/GS", "UserHacks_WildHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.bilinearHack, "EmuCore/GS", "UserHacks_BilinearHack", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.nativePaletteDraw, "EmuCore/GS", "UserHacks_NativePaletteDraw", false);
//////////////////////////////////////////////////////////////////////////
// Texture Replacements
+36 -17
View File
@@ -1168,14 +1168,14 @@
</item>
</widget>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="textureOffsetLabel">
<property name="text">
<string>Texture Offsets:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<layout class="QHBoxLayout" name="textureOffsetLayout" stretch="0,1,0,1">
<item>
<widget class="QLabel" name="textureOffsetXLabel">
@@ -1207,7 +1207,7 @@
</item>
</layout>
</item>
<item row="3" column="0" colspan="2">
<item row="4" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QCheckBox" name="alignSprite">
@@ -1216,20 +1216,6 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="bilinearHack">
<property name="text">
<string>Bilinear Dirty Upscale</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="mergeSprite">
<property name="text">
<string>Merge Sprite</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="nativePaletteDraw">
<property name="text">
@@ -1244,8 +1230,41 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="mergeSprite">
<property name="text">
<string>Merge Sprite</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Bilinear Dirty Upscale:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="bilinearHack">
<item>
<property name="text">
<string>Automatic (Default)</string>
</property>
</item>
<item>
<property name="text">
<string>Force Bilinear</string>
</property>
</item>
<item>
<property name="text">
<string>Force Nearest</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab">
+1 -1
View File
@@ -23,7 +23,7 @@
#include "MemoryCardConvertWorker.h"
#include "pcsx2/MemoryCardFile.h"
#include "pcsx2/SIO/Memcard/MemoryCardFile.h"
class MemoryCardConvertDialog final : public QDialog
{
+2 -2
View File
@@ -7,8 +7,8 @@
#include "QtProgressCallback.h"
#include "pcsx2/MemoryCardFile.h"
#include "pcsx2/MemoryCardFolder.h"
#include "pcsx2/SIO/Memcard/MemoryCardFile.h"
#include "pcsx2/SIO/Memcard/MemoryCardFolder.h"
class MemoryCardConvertWorker : public QtAsyncProgressThread
{
+1 -1
View File
@@ -24,7 +24,7 @@
#include "Settings/MemoryCardCreateDialog.h"
#include "pcsx2/MemoryCardFile.h"
#include "pcsx2/SIO/Memcard/MemoryCardFile.h"
#include "pcsx2/System.h"
MemoryCardCreateDialog::MemoryCardCreateDialog(QWidget* parent /* = nullptr */)
@@ -32,7 +32,7 @@
#include "SettingWidgetBinder.h"
#include "SettingsDialog.h"
#include "pcsx2/MemoryCardFile.h"
#include "pcsx2/SIO/Memcard/MemoryCardFile.h"
static constexpr const char* CONFIG_SECTION = "MemoryCards";
+4 -2
View File
@@ -79,8 +79,10 @@ void SettingsDialog::setupUi(const GameList::Entry* game)
if (isPerGameSettings())
{
QString summary = tr("<strong>Summary</strong><hr>Eventually this will be where we can see patches and compute "
"hashes/verify dumps/etc.");
QString summary = tr("<strong>Summary</strong><hr>This page shows details about the selected game. Changing the Input "
"Profile will set the controller binding scheme for this game to whichever profile is chosen, instead "
"of the default (Shared) configuration. The track list and dump verification can be used to determine "
"if your disc image matches a known good dump. If it does not match, the game may be broken.");
if (game)
{
addWidget(new GameSummaryWidget(game, this, m_ui.settingsContainer), tr("Summary"),
@@ -0,0 +1,779 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>USBBindingWidget_GunCon2</class>
<widget class="QWidget" name="USBBindingWidget_GunCon2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1000</width>
<height>400</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>1000</width>
<height>400</height>
</size>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QGridLayout" name="gridLayout_16">
<item row="2" column="2" colspan="2">
<widget class="QGroupBox" name="groupBox_16">
<property name="title">
<string>Buttons</string>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_19">
<property name="title">
<string>A</string>
</property>
<layout class="QGridLayout" name="gridLayout_19">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="A">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="3">
<widget class="QGroupBox" name="groupBox_20">
<property name="title">
<string>C</string>
</property>
<layout class="QGridLayout" name="gridLayout_20">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="C">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_23">
<property name="title">
<string>Start</string>
</property>
<layout class="QGridLayout" name="gridLayout_23">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Start">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="2" colspan="2">
<widget class="QGroupBox" name="groupBox_35">
<property name="title">
<string>Select</string>
</property>
<layout class="QGridLayout" name="gridLayout_35">
<item row="0" column="0">
<widget class="InputBindingWidget" name="Select">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_18">
<property name="title">
<string>B</string>
</property>
<layout class="QGridLayout" name="gridLayout_18">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="B">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="3" rowspan="2">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>D-Pad</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="3" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>Down</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Down">
<property name="minimumSize">
<size>
<width>125</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Left</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Left">
<property name="minimumSize">
<size>
<width>125</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Up</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Up">
<property name="minimumSize">
<size>
<width>125</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Right</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Right">
<property name="minimumSize">
<size>
<width>125</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_15">
<property name="title">
<string>Pointer Setup</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>&lt;p&gt;By default, GunCon2 will use the mouse pointer. To use the mouse, you &lt;strong&gt;do not&lt;/strong&gt; need to configure any bindings apart from the trigger and buttons.&lt;/p&gt;
&lt;p&gt;If you want to use a controller, or lightgun which simulates a controller instead of a mouse, then you should bind it to Relative Aiming. Otherwise, Relative Aiming should be &lt;strong&gt;left unbound&lt;/strong&gt;.&lt;/p&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="4" rowspan="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" rowspan="3">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2" rowspan="2">
<widget class="QGroupBox" name="groupBox_10">
<property name="title">
<string extracomment="Try to use Sony's official terminology for this. A good place to start would be in the console or the DualShock 2's manual. If this element was officially translated to your language by Sony in later DualShocks, you may use that term.">Relative Aiming</string>
</property>
<layout class="QGridLayout" name="gridLayout_11">
<item row="3" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_11">
<property name="title">
<string>Down</string>
</property>
<layout class="QGridLayout" name="gridLayout_12">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="RelativeDown">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_12">
<property name="title">
<string>Left</string>
</property>
<layout class="QGridLayout" name="gridLayout_13">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="RelativeLeft">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QGroupBox" name="groupBox_13">
<property name="title">
<string>Up</string>
</property>
<layout class="QGridLayout" name="gridLayout_14">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="RelativeUp">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="2" colspan="2">
<widget class="QGroupBox" name="groupBox_14">
<property name="title">
<string>Right</string>
</property>
<layout class="QGridLayout" name="gridLayout_15">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="RelativeRight">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1" rowspan="2">
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Trigger</string>
</property>
<layout class="QGridLayout" name="gridLayout_9">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_7">
<property name="title">
<string>Trigger</string>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="Trigger">
<property name="minimumSize">
<size>
<width>125</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_8">
<property name="title">
<string>Shoot Offscreen</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="InputBindingWidget" name="ShootOffscreen">
<property name="minimumSize">
<size>
<width>125</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QGroupBox" name="groupBox_9">
<property name="title">
<string>Calibration Shot</string>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="1">
<widget class="InputBindingWidget" name="Recalibrate">
<property name="minimumSize">
<size>
<width>125</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>125</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string notr="true">PushButton</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="3">
<widget class="QLabel" name="label">
<property name="text">
<string>Calibration shot is required to pass the setup screen in some games.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0" colspan="5">
<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>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>InputBindingWidget</class>
<extends>QPushButton</extends>
<header>Settings/InputBindingWidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../resources/resources.qrc"/>
</resources>
<connections/>
</ui>
+6 -6
View File
@@ -15,7 +15,7 @@
#include "PrecompiledHeader.h"
#include "PAD/Host/PAD.h"
#include "pcsx2/SIO/Pad/Pad.h"
#include "QtHost.h"
#include "QtUtils.h"
#include "SettingWidgetBinder.h"
@@ -151,7 +151,7 @@ void SetupWizardDialog::updatePageLabels(int prev_page)
void SetupWizardDialog::updatePageButtons()
{
const int page = m_ui.pages->currentIndex();
m_ui.next->setText((page == Page_Complete) ? "&Finish" : "&Next");
m_ui.next->setText((page == Page_Complete) ? tr("&Finish") : tr("&Next"));
m_ui.back->setEnabled(page > 0);
}
@@ -414,10 +414,10 @@ void SetupWizardDialog::setupControllerPage()
const std::string section = fmt::format("Pad{}", port + 1);
const PadWidgets& w = pad_widgets[port];
for (const auto& [name, display_name] : PAD::GetControllerTypeNames())
w.type_combo->addItem(qApp->translate("Pad", display_name), QString::fromStdString(name));
for (const auto& [name, display_name] : Pad::GetControllerTypeNames())
w.type_combo->addItem(QString::fromUtf8(display_name), QString::fromUtf8(name));
ControllerSettingWidgetBinder::BindWidgetToInputProfileString(
nullptr, w.type_combo, section, "Type", PAD::GetDefaultPadType(port));
nullptr, w.type_combo, section, "Type", Pad::GetDefaultPadType(port));
w.mapping_result->setText((port == 0) ? tr("Default (Keyboard)") : tr("Default (None)"));
@@ -473,7 +473,7 @@ void SetupWizardDialog::doDeviceAutomaticBinding(u32 port, QLabel* update_label,
bool result;
{
auto lock = Host::GetSettingsLock();
result = PAD::MapController(*Host::Internal::GetBaseSettingsLayer(), port, mapping);
result = Pad::MapController(*Host::Internal::GetBaseSettingsLayer(), port, mapping);
}
if (!result)
return;
+5 -4
View File
@@ -258,6 +258,7 @@ std::vector<std::pair<QString, QString>> QtHost::GetAvailableLanguageList()
{QStringLiteral("Italiano (it-IT)"), QStringLiteral("it-IT")},
{QStringLiteral("日本語 (ja-JP)"), QStringLiteral("ja-JP")},
{QStringLiteral("한국어 (ko-KR)"), QStringLiteral("ko-KR")},
{QStringLiteral("Latvija (lv-LV)"), QStringLiteral("lv-LV")},
{QStringLiteral("Nederlands (nl-NL)"), QStringLiteral("nl-NL")},
{QStringLiteral("Norsk (no-NO)"), QStringLiteral("no-NO")},
{QStringLiteral("Polski (pl-PL)"), QStringLiteral("pl-PL")},
@@ -337,22 +338,22 @@ static constexpr const QtHost::GlyphInfo s_glyph_info[] = {
{
"ja-JP", "msgothic.ttc", nullptr, "ヒラギノ角ゴシック W3.ttc",
// auto update by update_glyph_ranges.py with pcsx2-qt_ja-JP.ts
u"​□□△△◯◯✕✕、。〜〜ああいいううええおきくぐここささしすせせそそただっつてにのはびびへべほほまみめもややよれわわをんァイウコサソタチッツテニネパビロワワンンー一一上下不不中中丸丸了了互互今今他他代代仮仮作作使使保保信信修修倍倍値値停停備備像像入入全全公公内内再再出出切切別別利利制制削削副副割割力力加加効効動動勧勧化化十十南南参参反収取古古可台右右合合同名向向回回固固国国在在報報場場境境壊壊変変外外大大失失奨奨始始字存完完定定実実左左帰帰常常幅幅度度式式張張形形待待後後御御性性情情想想意意感感態態成成投投択択拡拡推推提換換敗敗数数整整新新方方既既日日明明時時更更書書替最有有期期本本果果検検標標橙橙機機止正毎毎比比況況注注消消港港湾湾準準無無照照状状率率現現璧璧環環生生用用画画異異的的直直知知確確示示種種稿稿空空索索終終緑緑編編績績能能自自般般行行表表製製複複視視覧覧解解言言設設認認語語読読赤赤起起跡跡転転軸軸込込近近追追送送通通速速進進遅遅遊遊適適選選部部長長閉閉開開関関防防限限除除隅隅集集青青非非面面韓韓音音類類香香高高黄黄++??"
u"……□□△△◯◯✕✕ 。々々「』〜〜ああいいううええおせそそたちっぬのばびびぶぶへべほぼまやょろわわをんァイウチッツテニネロワワンンー一一上下不与世世両両中中乗乗了了予予事事互互交交今介他他付付代以仮仮件件任任伸伸似似位低体体何何作作使使例例供供係係保保信信修修個個倍倍借借値値停停側側備備像像優優元元先光入入全全公公共共具典内内再再冗冗処処出出分切列列初初判別利利制刷則則削削前前副副割割力力加加効効動動勧勧化化区区十十半半南単印印即即去去参参及及反収取古古可台右右号号各各合合同名向向否否含含告告周周味味命命品品商商問問善善四四回回囲囲固固国国圧在地地均均垂垂型型域域基基報報場場境境増増壊壊声声変変外外多多大大太太央央失失奇奇奨奨好好妙妙妨妨始始子子字存安安完完定定実実容容寄寄密密対対射射小小少少尾尾展展岐岐崩崩左左巨巨己己帰帰常常幅幅平平序序度座延延式式引引弱弱張張強強当当形形彩彩影影役役待待後後得得御御復復微微心心必必応応忠忠念念急急性性悪悪情情想想意意感感態態慣慣成成戻戻所所手手打打承承投投択択抱抱押押拒拒招招拡拡拳拳持持指指振振挿挿捗捗排排接接推推提換換揮揮援援揺揺損損撃撃撮撮操操支支改改放放敗敗数数整整文文料料断断新新方方既既日日早早明明時時曲曲更更書書替最有有望望期期未本条条析析果果桁桁案案械械検検極極楽楽概概構構標標権権橙橙機機欄欄欠次止正殊残毎毎比比水水求求汎汎決決況況法法波波注注浪浪浮浮消消深深済済減減渡渡港港湾湾満満源源準準滑滑点為無無照照牲牲特特犠犠状状獲獲率率現現理理璧璧環環生生用用由由申申画画番番異異発登白白的的目目直直相相省省知知短短破破確確示示禁禁秒秒移移程程種種稿稿空空立立端端競競第第算算管管範範精精索索細細終終組組経経結結絞絞統統続続維維緑緒線線編編縦縦縮縮績績繰繰置置義義者者肢肢能能自自致致般般良良色色荷荷落落蔵蔵行行表表衰衰装装製製複複要要見見規規視視覚覚覧覧観観角角解解言言計計記記設設許許訳訳証証試試該詳認認語語誤誤説読調調識識警警象象負負責責費貼質質赤赤起起超超足足跡跡転転軸軸軽軽辞辞込込近近返返追追送送逆逆途途通通速速連連進進遅遅遊遊過過適適選選避避部部配配重量鉄鉄録録長長閉閉開開間間関関閾閾防防降降限限除除陽陽隅隅際際集集離難電電青青非非面面韓韓音音響響頂頂順順領領頻頼題題類類飾飾香香駄駄高高鮮鮮黄黄!!()//12::>?~~"
},
{
"ko-KR", "malgun.ttf", nullptr, "AppleSDGothicNeo.ttc",
// auto update by update_glyph_ranges.py with pcsx2-qt_ko-KR.ts
u""
u"“”……□□▲△▶▶▼▼◀◀◯◯✕✕んん茶茶가각간간갈갈감값강강같같개개거거건건걸걸검겁것것게게겠겠격격견견결결경경계계고곡공공과과관관교교구국군군권권귀귀규규균균그극근근글글금급긍긍기기긴긴길길깁깁깃깃깅깅깊깊까까깝깝깨깨꺼꺼께께꾸꾸끄끄끔끔끝끝나나날날남남낭낮내내낸낸냅냅너너널널넣네넬넬넷넷노녹높놓누누눈눈눌눌뉴뉴느느는는늘늘능능니닉닌닌님닙닛닛다다단단닫달담담당당대대댑댑더더덜덜덤덤덩덩덮덮데덱덴덴델델뎁뎁도독돌돌동동됐됐되되된된될될됨됩두두듀듀듈듈드득든든들들듬듭등등디디딩딩때때떠떠떤떤떨떨또또뛰뛰뛸뛸뜁뜁뜨뜨라락란란랍랍랑랑래랙랜랜램램랫랫량량러럭런런럴럴럼럽렀렀렇렉렌렌렛렛려력련련렬렬렸령로록롤롤롭롭롯롯료료루루룸룸류류률률르르른른를를름름리릭린린릴릴림립릿릿링링마막만만많많말말맞맞매매맨맨맵맵맺맺머머먼먼멀멀멈멈멋멋메메며며면면명명모목못못몽몽무무문문뮬뮬므므미믹민민밀밀밉밉밍밍및및바바반반받밝밥밥방방배백밴밴뱃뱃버버번번벌벌범법벗벗베벡벤벤벨벨벼벽변변별별병병보복본본볼볼부부분분불불붙붙뷰뷰브브블블비빅빈빈빌빌빙빙빛빛빠빠빨빨사삭산산살살삼삽상상새색샘샘생생샷샷서석선선설설성성세섹센센셀셀셈셉셋셋셔셔션션셰셰소속손손솔솔송송쇄쇄쇠쇠쇼쇼수수순순숨숨쉬쉬슈슈스스슬슬습습시식신신실실심십싱싱싶싶쌍쌍쓰쓰쓸쓸씬씬아아안안않않알알암압았앙애액앤앤앨앨앵앵야약양양어어언언얻얼업없었었에에엔엔여역연연열열영영예예오오온온올올옵옵와와완완왑왑외외왼왼요요용용우우운운울울움웁웃웃워워원원월월웨웨웹웹위위유유율율으으은은을을음음응응의의이이인인일읽임입있있자작잘잘잠잠장장재재잿잿저적전전절절점접정정제제젠젠젤젤젯젯져져조족존존종종좋좌죄죄주주준준줄줄줍줍중중즈즉즌즌즐즐즘즘증증지직진진질질짐집짝짝짧짧째째쪽쪽찌찍차착참참창찾채책챕챕처척천천철철첨첩첫첫청청체체쳐쳐초초촬촬최최추축출출춤춥충충춰춰취취츠측치칙칠칠침칩칭칭카카칸칸칼칼캐캐캔캔캘캘캠캡커커컨컨컬컬컴컴케케켓켓켜켜코코콘콘콜콜콩콩쿳쿳쿼쿼퀀퀀퀴퀴큐큐크크큰큰클클큽큽키키킨킨킬킬킵킵킹킹타타탈탈탐탐태택탠탠탬탭터터턴턴텀텀테텍텐텐텔텔템템토토톱톱통통투투툴툴트특튼튼틀틀티틱팀팀팅팅파파팔팔팝팝패패팻팻퍼퍼페펙편편평평포포폴폴폼폼표표푸푸풀풀품품풍풍퓨퓨프프픈픈플플피픽필필핑핑하하한한할할함합핫핫항항해핵했행향향허허헌헌헤헤현현형형호혹혼혼홈홈홍홍화확환환활활황황회획횟횟횡횡효효후후훨훨휠휠휴휴흐흐흔흔희희히히힌힌"
},
{
"zh-CN", "msyh.ttc", nullptr, "Hiragino Sans GB.ttc",
// auto update by update_glyph_ranges.py with pcsx2-qt_zh-CN.ts
u"‘’□□△△○○、。一丁三下不与且且世世丢丢两两个个中中丰丰串串为主么义之之乎乎乐乐乘乘也也了了事二于于互互亚些交交产产享享亮亮亲亲人人什什仅仅介介仍从他他代以们们件价任任份份伍伍休休优优会会传传估估伸伸似似但但位住佑佑体体何何余余作作佣佣佳佳使使例例供供侧侧便便俄俄保保信信修修倍倍值值倾倾假假偏偏做做停停储储像像儿儿允允元元充充先光克克免免入入全全六六兰共关关兵典兼兼内内册再写写冲决况况净净准准减减几几出击函函刀刀刃刃分切列列则则创创删删利利别别到到制刷刹刹前前剪剪副副力力功务动助势势勿勿包包化化匹区十十升升半半协协单单南南占卡卫卫印印即即压压原原去去参参及双反发发取变叠叠口古另另只只可台右右号号各各合吉同后向向吗吗否否含含启启呈呈告告员员味味命命和和哈哈响响哪哪唤唤商商善善器器四四回回因因团团围围国图圈圈在在地地场场址址均均坏坐块块坛坛垂垂型型域域基基堆堆堪堪塔塔填填增增士士声声处处备备复复外外多多够够大大天太失失头头夹夹奇奇奏奏套套奥奥奶奶好好如如始始威威娱娱婴婴媒媒子子字存它它安安完完宏宏官官定定宝实害害家家容容宽宽宿宿寄寄密密富富寸对导导封封射射将将小小少少尔尔尚尚尝尝就就尺尺尼尾局局层层屏屏展展属属崩崩工左巨巨差差己已巴巴希希带帧帮帮常常幅幅幕幕平平并并幸幸序序库底度度延延建建开开异弃弊弊式式引引张张弹强归当录录形形彩彩影影径待很很得得循循微微德德心心必忆志志忙忙快快忽忽态态性性怪怪恢恢息息您您悬悬情情惑惑惯惯意意感感慢慢戏我或或战战截截戳戳户户所扁手手打打托托执执扩扩扫扬扳扳找找技技抑抑抖抗护护拆拆拉拉拍拍拒拒拟拟拦择择括括拳拳持持指指按按挑挑挡挡挪挪振振捕捕损损换换据据掌掌排排接接控掩描提插插握握搜搜摇摇撕撕撤撤播播操擎支支收收改改放放故故效效敏敏散散数数整整文文断断斯新方方旋旋无无日日旧旧时时明明易易星映是是显显晕晕普普晰晰暂暂暗暗曲曲更更替最有有服服期期未未本本机机权权杆杆束束条条来来板板极极果果柄柄某某染染查查栅栅标栈栏栏校校样根格格框框案案档档桥桥检检棕棕榜榜模模橙橙次欧欧止步死死殊殊段段每每比比毫毫水水求求汇汇没没油油法法波波注注泻泻洲洲活活流流浅浅测测浏浏浪浪浮浮海海消消深深混混添添清清港港渲渲游游湖湖湾湾溃溃源源溢溢滑滑满满滤滤演演澳澳激激灰灰灵灵点点烈烈热热焦焦然然煞煞照照片版牌牌牙牙特特状状狂狂独独狼狼猎猎猩猩率率王王玩玩环现班班理理瑞瑞甚甚生生用用由电电画画畅畅界界留留略略疤疤登登白百的的皇皇盖盘目目直直相相省省看看真眠着着知知短短石石码码破破础础硬硬确确碌碌磁磁示示神神禁禁离离种种秒秒积称移移程程稍稍稳稳空空突突窗窗立立站站端端符符第第等等筛筛签签简简算算管管类类粉粉粘粘精精糊糊系系素素索索紫紫纠纠红红级级纯纯纳纳纹纹线线组组细终经经绑绑结结绕绕绘给络绝统统继继绪绪续续维维绿缀缓缓编编缩缩网网罗罗置置美美翻翻考考者者而而耗耗耳耳联联肩肩胖胖能能腊腊自自至致舍舍良良色色节节芬芬英英范范荐荐荷荷莱莱获获菜菜萄萄著著葡葡蓝蓝藏藏虑虑虚虚融融行行衡衡补补表表被被裁裂装装西西要要覆覆观规规视视览觉角角解解触触言言警警计计认认让让议议记记许许论论设访证证诊诊译译试试询询该详语语误误说说请诸读读调调谍谍豹豹负负败账质质贴贴费费赛赛起起超超越越足足跟跟跨跨路路跳跳踏踏踪踪身身车车轨轨转转轮软轴轴轻轻载载较较辅辅辑辑输输辨辨边边达达过过运近还这进进连迟述述追追退适选选逐逐递递通通速造遇遇道道避避那那部部都都配配醒醒采采释释里重量量针针钮钮铁铁铺铺链链销锁锐锐错错键锯镜镜长长门门闭问闲闲间间队队防防阴阴附附陆陆降降限限除除险险随隐隔隔隙隙障障雄雄集集零零雾雾需需震震静静非非靠靠面面韩韩音音顶顶项须顿顿预预频频题题颜额风风饱饱馈馈首首香香马马驱驱验验高高鬼鬼魂魂魔魔麦麦黄黄黑黑默默鼓鼓鼠鼠齐齐齿齿,,??"
u"‘’□□△△○○、。一丁三下不与且且世世丢丢两两个个中中串串为主么义之之乎乎乐乐乘乘也也了了事二于于互互亚些交交产产享享亮亮亲亲人人什什仅仅今今仍从他他代以们们件价任任份份伍伍休休优优会会传传估估伸伸似似但但位住佑佑体体何何余余作作你你佳佳使使例例供供侧侧便便俄俄保保信信修修倍倍借借值值倾倾假假偏偏做做停停储储像像儿儿允允元元充充先光克克免免入入全全六六兰共关关其兹兼兼内内册再写写冲决况况准准减减几几出击函函刀刀刃刃分切列列则则创创删删利利别别到到制刷刹刹前前剪剪副副力力功务动助势势勿勿包包化化匹区十十升升半半协协单单南南占卡卫卫印印即即卸卸压压原原去去参参及双反发发取变叠叠口古另另只只可台右右号号各各合吉同后向向吗吗否否含含启启呈呈告告员员味味命命和和哈哈响响哪哪唤唤商商善善器器四四回回因因团团围围国图圈圈在在地地场场址址均均坏坐块块坛坛垂垂型型域域基基堆堆堪堪塔塔填填增增士士声声处处备备复复外外多多够够大大天太失失头头夹夹奇奇奏奏套套奥奥奶奶好好如如始始威威娱娱婴婴媒媒子子字存它它安安完完宏宏官官定定宝实害害家家容容宽宽宿宿寄寄密密富富寸对导导封封射射将将小小少少尔尔尚尚尝尝就就尺尺尼尾局局层层屏屏展展属属崩崩工左巨巨差差己已巴巴希希带帧帮帮常常幅幅幕幕平平并并幸幸序序库底度度延延建建开开异弃弊弊式式引引张张弹强归当录录形形彩彩影影径待很很律律得得循循微微德德心心必忆志志忙忙快快忽忽态态性性怪怪恢恢息息您您悬悬情情惑惑惯惯想想愉愉意意感感慢慢戏我或或战战截截戳戳户户所扁手手才才打打托托执执扩扩扫扬扳扳找找技技抑抑抖抗护护拆拆拉拉拍拍拒拒拟拟拦择择括括拳拳持持指指按按挑挑挡挡挪挪振振捕捕损损换换据据捷捷掌掌排排接接控掩描提插插握握搜搜摇摇摘摘撕撕撤撤播播操擎支支收收改改放放故故效效敏敏散散数数整整文文断断斯新方方旋旋无无日日旧旧时时明明易易星映是是显显晕晕普普晰晰暂暂暗暗曲曲更更替最有有服服望望期期未未本本机机权权杆杆束束条条来来板板极极果果柄柄某某染染查查栅栅标栈栏栏校校样根格格框框案案档档桥桥检检棕棕榜榜槽槽模模橙橙次欧欧止步死死殊殊段段每每比比毫毫水水求求汇汇没没油油法法波波注注泻泻洲洲活活流流浅浅测测浏浏浪浪浮浮海海消消淡淡深深混混添添清清港港渲渲游游湖湖湾湾溃溃源源溢溢滑滑满满滤滤演演澳澳激激灰灰灵灵点点烈烈热热焦焦然然煞煞照照片版牌牌牙牙特特状状狂狂独独狼狼猎猎猩猩率率王王玩玩环现班班理理瑞瑞甚甚生生用用由电电画画畅畅界界留留略略疤疤登登白百的的皇皇盖盘目目直直相相省省看看真眠着着知知短短石石码码破破础础硬硬确确碌碌磁磁示示神神禁禁离离种种秒秒积称移移程程稍稍稳稳空空突突窗窗立立站站端端符符第第等等答答筛筛签签简简算算管管类类粉粉粘粘精精糊糊系系素素索索紫紫纠纠红红级级纳纳纹纹线线组组细终经经绑绑结结绕绕绘给络绝统统继继绪绪续续维维绿缀缓缓编编缩缩缺缺网网罗罗置置美美翻翻考考者者而而耗耗耳耳联联肩肩胖胖能能腊腊自自至致舍舍航航良良色色节节芬芬英英范范荐荐荷荷莱莱获获菜菜萄萄著著葡葡蓝蓝藏藏虑虑虚虚融融行行衡衡补补表表被被裁裂装装西西要要覆覆观规规视视览觉角角解解触触言言警警计计认认让让议议记记许许论论设访证证识识诊诊译译试试询询该详语语误误说说请诸读读调调谍谍豹豹负负败账质质贴贴费费赛赛赫赫起起超超越越足足跃跃跟跟跨跨路路跳跳踏踏踪踪身身车车轨轨转转轮软轴轴轻轻载载较较辅辅辑辑输输辨辨边边达达过过迎迎运近还这进进连迟述述追追退适逆逆选选逐逐递递通通速造遇遇道道避避那那邻邻部部都都配配醒醒采采释释里重量量针针钮钮铁铁铺铺链链销锁锐锐错错键锯镜镜长长门门闭问闲闲间间阅阅队队防防阴阴附陆降降限限除除险险随隐隔隔隙隙障障雄雄集集零零雾雾需需震震静静非非靠靠面面韩韩音音顶顶项须顿顿预预频频题题颜额风风饱饱馈馈首首香香马马驱驱骤骤高高鬼鬼魂魂魔魔麦麦黄黄黑黑默默鼓鼓鼠鼠齐齐齿齿,,::??"
},
{
"zh-TW", "msyh.ttc", nullptr, "Hiragino Sans GB.ttc",
// auto update by update_glyph_ranges.py with pcsx2-qt_zh-TW.ts
u""
u"、。一一上下不不且且並並中中主主了了互互今今令以件件任任位位何何使使來來係係保保個個優優儲儲免免入入內全具具兼兼冊冊再再到到創創功加助助動動務務勢勢包包協協南南及及取取只只可可合合名名和和商商問問啟啟嘗嘗器器嚮嚮在在壇壇多多失失如如始始娛娛存存它它安安完完官官定定容容密密將將對導就就尼尼局局希希幫幫序序庫庫建建後後得得從從您您情情意意態態應應成成戲戲戶戶所所持持指指接接擇擇擬擬支支改改敗敗新新方方於於是是時時更更會會有有服服望望本本果果查查樂樂標標模模機機檢檢次次歡步沒沒況況消消源源為為然然版版牌牌狀狀獲獲玩玩現現理理生生用用界界登發的的看看硬硬確確碼碼程程種種站站第第管管系系索索組組絡絡統統網網緒緒編編置置而而聯聯能能自自與與虛虛裝裝要要解解言言訪訪設設許許註註試試該該認認語語誤誤請請論論譯議費費起起載載輸輸迎迎這通連連遊遊過過選選配配釋釋重重錄錄錯錯鏈鏈開開間間關關防防附附需需面面項項題題驟驟默默"
},
};
// clang-format on
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+12 -2
View File
@@ -306,6 +306,9 @@
<QtUi Include="Settings\ControllerBindingWidget_DualShock2.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="Settings\ControllerBindingWidget_Guitar.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="Settings\ControllerBindingWidget.ui">
<FileType>Document</FileType>
</QtUi>
@@ -371,6 +374,9 @@
</QtUi>
</ItemGroup>
<ItemGroup>
<QtUi Include="Settings\USBBindingWidget_GunCon2.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="SetupWizardDialog.ui">
<FileType>Document</FileType>
</QtUi>
@@ -392,8 +398,12 @@
<QtUi Include="Settings\GamePatchSettingsWidget.ui">
<FileType>Document</FileType>
</QtUi>
<None Include="Settings\USBBindingWidget_DrivingForce.ui" />
<None Include="Settings\USBBindingWidget_GTForce.ui" />
<QtUi Include="Settings\USBBindingWidget_DrivingForce.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="Settings\USBBindingWidget_GTForce.ui">
<FileType>Document</FileType>
</QtUi>
<QtUi Include="Settings\USBDeviceWidget.ui">
<FileType>Document</FileType>
</QtUi>
+12 -6
View File
@@ -531,6 +531,9 @@
<QtUi Include="Settings\ControllerBindingWidget_DualShock2.ui">
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="Settings\ControllerBindingWidget_Guitar.ui">
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="Settings\ControllerBindingWidget.ui">
<Filter>Settings</Filter>
</QtUi>
@@ -621,17 +624,20 @@
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="SetupWizardDialog.ui" />
<QtUi Include="Settings\USBBindingWidget_DrivingForce.ui">
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="Settings\USBBindingWidget_GTForce.ui">
<Filter>Settings</Filter>
</QtUi>
<QtUi Include="Settings\USBBindingWidget_GunCon2.ui">
<Filter>Settings</Filter>
</QtUi>
</ItemGroup>
<ItemGroup>
<None Include="Settings\FolderSettingsWidget.ui">
<Filter>Settings</Filter>
</None>
<None Include="Settings\USBBindingWidget_GTForce.ui">
<Filter>Settings</Filter>
</None>
<None Include="Settings\USBBindingWidget_DrivingForce.ui">
<Filter>Settings</Filter>
</None>
</ItemGroup>
<ItemGroup>
<QtTs Include="Translations\pcsx2-qt_en.ts">
@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="cheats" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1{fill:none;}.cls-2{fill-rule:evenodd;}</style></defs><g id="tela"><g><path class="cls-1" d="M0,0H24V24H0V0Z"/><path d="M2,4c0-.5,.5-1,1-1H21c.5,0,1,.4,1,1v14c0,.5-.5,1-1,1H3c-.5,0-1-.5-1-1h0V4Zm2,1v12H20V5H4Zm1,15h14v2H5v-2Z"/></g></g><g id="by_maxihplay"><path class="cls-2" d="M13.4,6.7c-1.1-1.2-2.6-.9-4,0-1.4-.9-2.9-1.1-4,0-.3,.4-.4,.9-.5,1.4-.2,1.1,.3,2.3,1.1,3.1l3.4,3.5,3.4-3.5c.8-.8,1.3-1.9,1.1-3.1,0-.5-.1-1-.5-1.4Z"/><path d="M17.1,12.2c.6,0,1,.2,1.5,.6,.4,.4,.6,.9,.6,1.5s-.2,1.1-.6,1.5c-.4,.4-.9,.6-1.5,.6s-1.3-.4-1.8-1c-.6,.7-1.2,1-1.8,1s-1.1-.2-1.4-.6c-.4-.4-.6-.9-.6-1.5s.2-1.1,.6-1.5c.4-.4,.9-.6,1.4-.6,.6,0,1.3,.4,1.8,1.1,.6-.8,1.2-1.1,1.8-1.1Zm-3.7,3c.4,0,.8-.3,1.2-.9-.4-.6-.8-.9-1.2-.9-.2,0-.3,0-.5,.1s-.3,.2-.3,.3-.1,.3-.1,.4c0,.2,.1,.5,.3,.6,.1,.3,.3,.4,.6,.4h0Zm3.9,0h.3c.1,0,.2-.1,.3-.1s.1-.1,.1-.2,.1-.2,.1-.3v-.3c0-.2-.1-.5-.3-.6-.2-.2-.4-.3-.7-.3-.4,0-.8,.3-1.2,.9,.6,.6,1,.9,1.4,.9h0Z"/></g></svg>
<?xml version="1.0" encoding="UTF-8"?><svg id="cheats" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1{fill:none;}</style></defs><path class="cls-1" d="M0,0H24V24H0V0Z"/><g id="by_maxihplay"><path d="M14.38,5.18c.73,0,1.32,.26,1.87,.82,2.15,3.05-.83,6.31-5.25,10.57-.43,.41-.85,.82-1.25,1.22l-1.88-1.93-2.39-2.46c-.39-.4-.78-.8-1.18-1.13l.04-.04c-1.85-1.78-1.93-3.85-1.39-5.18,.22-.55,.92-1.83,2.53-1.83,.9,0,1.94,.41,3,1.17l1.22,.88,1.26-.81c1.29-.83,2.48-1.27,3.43-1.27m0-2.2c-1.49,0-3.08,.63-4.62,1.62-1.55-1.12-3.01-1.59-4.29-1.59-4.76,0-7.07,6.54-2.67,10.8,0,0,6.96,7.16,6.96,7.16,3.41-4.03,12.75-10.19,8.18-16.37-1.05-1.14-2.27-1.62-3.57-1.62h0Z"/><path d="M20.93,16.35c.72,0,1.34,.27,1.85,.8,.51,.53,.77,1.17,.77,1.92s-.26,1.39-.77,1.92-1.13,.8-1.85,.8c-.84,0-1.61-.45-2.34-1.34-.72,.9-1.5,1.34-2.34,1.34-.72,0-1.34-.27-1.85-.8s-.77-1.17-.77-1.92,.26-1.39,.77-1.92c.51-.53,1.13-.8,1.85-.8,.84,0,1.61,.45,2.34,1.34,.72-.9,1.5-1.34,2.34-1.34Zm-4.67,3.81c.48,0,.97-.36,1.45-1.09-.48-.73-.97-1.09-1.45-1.09-.21,0-.39,.05-.56,.14s-.31,.23-.41,.4-.15,.35-.15,.54c0,.3,.11,.55,.33,.77,.22,.22,.49,.32,.8,.32Zm4.67,0c.12,0,.24-.02,.36-.05s.22-.09,.31-.15,.18-.15,.25-.24,.13-.19,.16-.31,.05-.23,.05-.34c0-.3-.11-.55-.33-.77-.22-.22-.49-.32-.8-.32-.48,0-.97,.36-1.45,1.09,.48,.73,.97,1.09,1.45,1.09Z"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1,81 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Agrupar_1_copiar"
data-name="Agrupar 1 copiar"
width="384"
height="384"
viewBox="0 0 384 384"
version="1.1"
sodipodi:docname="floppy-in-line-black.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview11"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="1.5733333"
inkscape:cx="118.53814"
inkscape:cy="137.92373"
inkscape:window-width="1920"
inkscape:window-height="956"
inkscape:window-x="0"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="Agrupar_1_copiar" />
<defs
id="defs4">
<style
id="style2">
.cls-1, .cls-2, .cls-3 {
fill: none;
stroke: #fff;
fill-rule: evenodd;
}
.cls-1 {
stroke-width: 23px;
}
.cls-2 {
stroke-width: 25px;
}
.cls-3 {
stroke-width: 33px;
}
</style>
</defs>
<path
id="Forma_1"
data-name="Forma 1"
class="cls-1"
d="m 325.91068,295.77571 c 0,0 0.24169,10.49815 0.73613,22.57934 0.49445,12.08118 -9.96947,12.17987 -9.96947,12.17987 0,0 -243.07578,-1.34336 -251.339361,-1.10772 -8.263582,0.23564 -8.86175,-9.96443 -8.86175,-9.96443 V 74.766689 c 0,0 1.492399,-7.461996 8.86175,-8.86175 7.36935,-1.399754 214.801761,0 214.801761,0 l 46.50304,46.503041 0.27492,86.6941"
style="stroke:#000000;stroke-width:23;stroke-dasharray:none" />
<path
id="Forma_2"
data-name="Forma 2"
class="cls-1"
d="m 127.34606,65.908967 1.10771,88.578223 c 0,0 -1.75825,2.69881 5.5386,3.32316 7.29684,0.62435 121.79468,1.10772 121.79468,1.10772 a 5.4681025,5.4681025 0 0 0 3.32316,-5.53859 c -0.0866,-4.38556 0,-88.578232 0,-88.578232"
style="stroke:#000000;stroke-width:23;stroke-dasharray:none" />
<path
id="Forma_5"
data-name="Forma 5"
class="cls-2"
d="m 224.20196,202.12313 c -0.44409,0.33533 -53.03656,46.50304 -53.03656,46.50304 l 51.02253,47.14954"
style="stroke:#000000;stroke-width:25;stroke-dasharray:none" />
<path
id="Forma_6"
data-name="Forma 6"
class="cls-3"
d="M 175.86514,248.44591 339.0019,247.43889"
style="stroke:#000000;stroke-width:33;stroke-dasharray:none" />
</svg>
<?xml version="1.0" encoding="UTF-8"?><svg id="PCSX2_-_load" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 384"><defs><style>.cls-1{stroke-width:28px;}.cls-1,.cls-2{fill:none;stroke:#000;}.cls-2{stroke-width:29px;}</style></defs><g id="By_maxihplay"><path id="Forma_5" class="cls-1" d="M217.39,192.85c-.45,.33-52.68,43.98-52.68,43.98l52.04,47.7"/><path id="Forma_6" class="cls-1" d="M173.41,238.01l161.32-.73"/><path id="Forma_2" class="cls-1" d="M114.53,59.5l1.11,89.07s-1.77,2.71,5.57,3.34c7.33,.63,122.47,1.11,122.47,1.11,2.21-.93,3.56-3.18,3.34-5.57-.09-4.41,0-89.07,0-89.07"/><path id="Forma_1" class="cls-2" d="M322.31,290.47s-.12,21.8-.1,22.87c.31,13.33-11.31,12.25-11.31,12.25,0,0-244.42-1.35-252.73-1.11s-8.91-10.02-8.91-10.02V68.41s1.5-7.5,8.91-8.91,215.99,0,215.99,0l48.05,46.76,.27,72.95"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 818 B

@@ -1,81 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Agrupar_1"
data-name="Agrupar 1"
width="384"
height="384"
viewBox="0 0 384 384"
version="1.1"
sodipodi:docname="floppy-out-line-black.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview11"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="1.2683333"
inkscape:cx="158.08148"
inkscape:cy="207.35874"
inkscape:window-width="1920"
inkscape:window-height="956"
inkscape:window-x="0"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="Agrupar_1" />
<defs
id="defs4">
<style
id="style2">
.cls-1, .cls-2, .cls-3 {
fill: none;
stroke: #fff;
fill-rule: evenodd;
}
.cls-1 {
stroke-width: 23px;
}
.cls-2 {
stroke-width: 25px;
}
.cls-3 {
stroke-width: 33px;
}
</style>
</defs>
<path
id="Forma_1"
data-name="Forma 1"
class="cls-1"
d="m 325.86348,300.4432 c 0,0 0.24183,10.50408 0.73655,22.59208 0.49472,12.08801 -9.9751,12.18675 -9.9751,12.18675 0,0 -243.213007,-1.34412 -251.481254,-1.10834 -8.268247,0.23577 -8.866752,-9.97006 -8.866752,-9.97006 V 79.309414 c 0,0 1.493241,-7.466209 8.866752,-8.866753 7.373511,-1.400544 214.923034,0 214.923034,0 l 46.52929,46.529289 0.27507,86.74304"
style="stroke:#000000;stroke-width:23;stroke-dasharray:none" />
<path
id="Forma_2"
data-name="Forma 2"
class="cls-1"
d="m 127.18676,70.446691 1.10835,88.628229 c 0,0 -1.75925,2.70033 5.54172,3.32503 7.30096,0.62471 121.86344,1.10835 121.86344,1.10835 a 5.4711894,5.4711894 0 0 0 3.32503,-5.54172 c -0.0867,-4.38804 0,-88.628233 0,-88.628233"
style="stroke:#000000;stroke-width:23;stroke-dasharray:none" />
<path
id="Forma_5"
data-name="Forma 5"
class="cls-2"
d="m 267.20286,207.74533 c 1.47007,1.13656 53.06651,44.51412 53.06651,44.51412 l -51.05134,47.17617"
style="stroke:#000000;stroke-width:25;stroke-dasharray:none" />
<path
id="Forma_6"
data-name="Forma 6"
class="cls-3"
d="M 315.56697,253.08668 152.33811,252.0791"
style="stroke:#000000;stroke-width:33;stroke-dasharray:none" />
</svg>
<?xml version="1.0" encoding="UTF-8"?><svg id="PCSX2_-_load" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 384"><defs><style>.cls-1{stroke-width:28px;}.cls-1,.cls-2{fill:none;stroke:#000;}.cls-2{stroke-width:29px;}</style></defs><g id="By_maxihplay"><path id="Forma_6" class="cls-1" d="M309.03,236.01l-132.24-.6"/><path id="Forma_5" class="cls-1" d="M261.32,188.75c.45,.33,52.68,43.98,52.68,43.98l-52.04,47.7"/><path id="Forma_2" class="cls-1" d="M114.53,59.5l1.11,89.07s-1.77,2.71,5.57,3.34c7.33,.63,122.47,1.11,122.47,1.11,2.21-.93,3.56-3.18,3.34-5.57-.09-4.41,0-89.07,0-89.07"/><path id="Forma_1" class="cls-2" d="M322.31,290.47s-.12,21.8-.1,22.87c.31,13.33-11.31,12.25-11.31,12.25,0,0-244.42-1.35-252.73-1.11s-8.91-10.02-8.91-10.02V68.41s1.5-7.5,8.91-8.91,215.99,0,215.99,0l48.05,46.76,.27,72.95"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 818 B

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="guitar_PCSX2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 493.66 474.14"><defs><style>.cls-1,.cls-2{stroke:#000;stroke-miterlimit:10;}.cls-2{stroke-width:20px;}</style></defs><g id="By_maxihplay"><path id="corpo" class="cls-1" d="M188.41,192.55c-.75,14.56,6.75,47.85,20.03,67.76,19.32,28.97,42.12,37.78,54.54,43.83-17.76,8.99-43.47,27.14-53.18,55-1.18,3.26-1.97,6.71-2.27,10.24-3.93,46.09-40.35,63.32-70.26,64.13-14.57,.4-29.14-2.93-42.13-9.52-14.19-7.25-26.02-17.98-35.01-32.02-.41-.58-.81-1.15-1.22-1.73-10.27-14.2-16.49-30.76-17.93-47.84-1.42-16.1,1.39-31.83,7.86-45.71,2.65-5.68,10.86-21.28,28.05-31.02,12.09-6.86,22.94-7.51,28.71-8.28,17.19-2.32,61.18-15.77,82.82-64.84Zm19.53-71.29c-38.91,1.06-45.85,41.06-64.11,71.01-14.61,23.88-38.65,24.92-40.31,24.97h-.1C10.15,223.2-29.95,335.62,26.37,413.63c26.97,41.92,70.63,61.09,111.99,59.96,53.67-1.46,103.78-36.96,109.18-100.8h0c19.93-58.65,105.53-15.58,93.41-112.5-23.14,8.75-40.07,12.44-52.19,12.77-26.98,.73-31.85-18.13-27.99-30.95l-25.37-31.05c-20.51-52.62-2.68-69.18,10.16-86.16-6.4-1.49-32.54-3.87-37.62-3.63h0Z"/><path id="cordas" class="cls-2" d="M103.87,365.16l-2.97-3.25c-3.52-3.71-3.25-9.64,.56-13.17l65.75-61.02c3.8-3.52,9.64-3.25,13.17,.46l2.97,3.25c3.52,3.71,3.25,9.64-.56,13.17l-65.75,61.02c-3.71,3.52-9.64,3.25-13.17-.46h0Z"/><polygon id="braco" class="cls-2" points="239.3 255.5 223.65 236.65 365.87 104.18 382.89 121.88 239.3 255.5"/><path class="cls-1" d="M485.96,27.45l-16.94-18.24c-10.07-10.97-27.21-11.69-38.25-1.56l-68.38,63.39c-10.94,10.08-11.64,27.19-1.51,38.22l16.94,18.24c5.31,5.78,12.58,8.71,19.88,8.71,6.56,0,13.14-2.37,18.37-7.16l68.35-63.35c5.33-4.89,8.42-11.56,8.72-18.79,.29-7.2-2.23-14.09-7.17-19.47Z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -1 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="cheats" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1,.cls-2{fill:#fff;}.cls-2{fill-rule:evenodd;}.cls-3{fill:none;}</style></defs><g id="tela"><g><path class="cls-3" d="M0,0H24V24H0V0Z"/><path class="cls-1" d="M2,4c0-.5,.5-1,1-1H21c.5,0,1,.4,1,1v14c0,.5-.5,1-1,1H3c-.5,0-1-.5-1-1h0V4Zm2,1v12H20V5H4Zm1,15h14v2H5v-2Z"/></g></g><g id="by_maxihplay"><path class="cls-2" d="M13.4,6.7c-1.1-1.2-2.6-.71-4,.19-1.4-.9-2.9-1.29-4-.19-.3,.4-.4,.9-.5,1.4-.2,1.1,.3,2.3,1.1,3.1l3.4,3.5,3.4-3.5c.8-.8,1.3-1.9,1.1-3.1,0-.5-.1-1-.5-1.4Z"/><path class="cls-1" d="M17.1,12.2c.6,0,1,.2,1.5,.6,.4,.4,.6,.9,.6,1.5s-.2,1.1-.6,1.5c-.4,.4-.9,.6-1.5,.6s-1.3-.4-1.8-1c-.6,.7-1.2,1-1.8,1s-1.1-.2-1.4-.6c-.4-.4-.6-.9-.6-1.5s.2-1.1,.6-1.5c.4-.4,.9-.6,1.4-.6,.6,0,1.3,.4,1.8,1.1,.6-.8,1.2-1.1,1.8-1.1Zm-3.7,3c.4,0,.8-.3,1.2-.9-.4-.6-.8-.9-1.2-.9-.2,0-.3,0-.5,.1s-.3,.2-.3,.3-.1,.3-.1,.4c0,.2,.1,.5,.3,.6,.1,.3,.3,.4,.6,.4h0Zm3.9,0h.3c.1,0,.2-.1,.3-.1s.1-.1,.1-.2,.1-.2,.1-.3v-.3c0-.2-.1-.5-.3-.6-.2-.2-.4-.3-.7-.3-.4,0-.8,.3-1.2,.9,.6,.6,1,.9,1.4,.9h0Z"/></g></svg>
<?xml version="1.0" encoding="UTF-8"?><svg id="cheats" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:none;}</style></defs><path class="cls-2" d="M0,0H24V24H0V0Z"/><g id="by_maxihplay"><path class="cls-1" d="M14.38,5.18c.73,0,1.32,.26,1.87,.82,2.15,3.05-.83,6.31-5.25,10.57-.43,.41-.85,.82-1.25,1.22l-1.88-1.93-2.39-2.46c-.39-.4-.78-.8-1.18-1.13l.04-.04c-1.85-1.78-1.93-3.85-1.39-5.18,.22-.55,.92-1.83,2.53-1.83,.9,0,1.94,.41,3,1.17l1.22,.88,1.26-.81c1.29-.83,2.48-1.27,3.43-1.27m0-2.2c-1.49,0-3.08,.63-4.62,1.62-1.55-1.12-3.01-1.59-4.29-1.59-4.76,0-7.07,6.54-2.67,10.8,0,0,6.96,7.16,6.96,7.16,3.41-4.03,12.75-10.19,8.18-16.37-1.05-1.14-2.27-1.62-3.57-1.62h0Z"/><path class="cls-1" d="M20.93,16.35c.72,0,1.34,.27,1.85,.8,.51,.53,.77,1.17,.77,1.92s-.26,1.39-.77,1.92-1.13,.8-1.85,.8c-.84,0-1.61-.45-2.34-1.34-.72,.9-1.5,1.34-2.34,1.34-.72,0-1.34-.27-1.85-.8s-.77-1.17-.77-1.92,.26-1.39,.77-1.92c.51-.53,1.13-.8,1.85-.8,.84,0,1.61,.45,2.34,1.34,.72-.9,1.5-1.34,2.34-1.34Zm-4.67,3.81c.48,0,.97-.36,1.45-1.09-.48-.73-.97-1.09-1.45-1.09-.21,0-.39,.05-.56,.14s-.31,.23-.41,.4-.15,.35-.15,.54c0,.3,.11,.55,.33,.77,.22,.22,.49,.32,.8,.32Zm4.67,0c.12,0,.24-.02,.36-.05s.22-.09,.31-.15,.18-.15,.25-.24,.13-.19,.16-.31,.05-.23,.05-.34c0-.3-.11-.55-.33-.77-.22-.22-.49-.32-.8-.32-.48,0-.97,.36-1.45,1.09,.48,.73,.97,1.09,1.45,1.09Z"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

@@ -1,77 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Agrupar_1_copiar"
data-name="Agrupar 1 copiar"
width="384"
height="384"
viewBox="0 0 384 384"
version="1.1"
sodipodi:docname="floppy-in-line.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview11"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="1.5733333"
inkscape:cx="135.06356"
inkscape:cy="136.65255"
inkscape:window-width="1920"
inkscape:window-height="956"
inkscape:window-x="0"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="Agrupar_1_copiar" />
<defs
id="defs4">
<style
id="style2">
.cls-1, .cls-2, .cls-3 {
fill: none;
stroke: #fff;
fill-rule: evenodd;
}
.cls-1 {
stroke-width: 23px;
}
.cls-2 {
stroke-width: 25px;
}
.cls-3 {
stroke-width: 33px;
}
</style>
</defs>
<path
id="Forma_1"
data-name="Forma 1"
class="cls-1"
d="m 325.91068,295.77571 c 0,0 0.24169,10.49815 0.73613,22.57934 0.49445,12.08118 -9.96947,12.17987 -9.96947,12.17987 0,0 -243.07578,-1.34336 -251.339361,-1.10772 -8.263582,0.23564 -8.86175,-9.96443 -8.86175,-9.96443 V 74.766689 c 0,0 1.492399,-7.461996 8.86175,-8.86175 7.36935,-1.399754 214.801761,0 214.801761,0 l 46.50304,46.503041 0.27492,86.6941" />
<path
id="Forma_2"
data-name="Forma 2"
class="cls-1"
d="m 127.34606,65.908967 1.10771,88.578223 c 0,0 -1.75825,2.69881 5.5386,3.32316 7.29684,0.62435 121.79468,1.10772 121.79468,1.10772 a 5.4681025,5.4681025 0 0 0 3.32316,-5.53859 c -0.0866,-4.38556 0,-88.578232 0,-88.578232" />
<path
id="Forma_5"
data-name="Forma 5"
class="cls-2"
d="m 224.20196,202.12313 c -0.44409,0.33533 -53.03656,46.50304 -53.03656,46.50304 l 51.02253,47.14954" />
<path
id="Forma_6"
data-name="Forma 6"
class="cls-3"
d="M 175.86514,248.44591 339.0019,247.43889" />
</svg>
<?xml version="1.0" encoding="UTF-8"?><svg id="PCSX2_-_Save" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 384"><defs><style>.cls-1{stroke-width:29px;}.cls-1,.cls-2{fill:none;stroke:#fff;}.cls-2{stroke-width:28px;}</style></defs><g id="By_maxihplay"><path id="Forma_5" class="cls-2" d="M217.39,192.85c-.45,.33-52.68,43.98-52.68,43.98l52.04,47.7"/><path id="Forma_6" class="cls-2" d="M173.41,238.01l161.32-.73"/><path id="Forma_2" class="cls-2" d="M114.53,59.5l1.11,89.07s-1.77,2.71,5.57,3.34c7.33,.63,122.47,1.11,122.47,1.11,2.21-.93,3.56-3.18,3.34-5.57-.09-4.41,0-89.07,0-89.07"/><path id="Forma_1" class="cls-1" d="M322.31,290.47s-.12,21.8-.1,22.87c.31,13.33-11.31,12.25-11.31,12.25,0,0-244.42-1.35-252.73-1.11s-8.91-10.02-8.91-10.02V68.41s1.5-7.5,8.91-8.91,215.99,0,215.99,0l48.05,46.76,.27,72.95"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 818 B

@@ -1,77 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Agrupar_1"
data-name="Agrupar 1"
width="384"
height="384"
viewBox="0 0 384 384"
version="1.1"
sodipodi:docname="floppy-out-line.svg"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview11"
pagecolor="#505050"
bordercolor="#ffffff"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="1"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="1.2683333"
inkscape:cx="179.36926"
inkscape:cy="207.35874"
inkscape:window-width="1920"
inkscape:window-height="956"
inkscape:window-x="0"
inkscape:window-y="42"
inkscape:window-maximized="1"
inkscape:current-layer="Agrupar_1" />
<defs
id="defs4">
<style
id="style2">
.cls-1, .cls-2, .cls-3 {
fill: none;
stroke: #fff;
fill-rule: evenodd;
}
.cls-1 {
stroke-width: 23px;
}
.cls-2 {
stroke-width: 25px;
}
.cls-3 {
stroke-width: 33px;
}
</style>
</defs>
<path
id="Forma_1"
data-name="Forma 1"
class="cls-1"
d="m 325.86348,300.4432 c 0,0 0.24183,10.50408 0.73655,22.59208 0.49472,12.08801 -9.9751,12.18675 -9.9751,12.18675 0,0 -243.213007,-1.34412 -251.481254,-1.10834 -8.268247,0.23577 -8.866752,-9.97006 -8.866752,-9.97006 V 79.309414 c 0,0 1.493241,-7.466209 8.866752,-8.866753 7.373511,-1.400544 214.923034,0 214.923034,0 l 46.52929,46.529289 0.27507,86.74304" />
<path
id="Forma_2"
data-name="Forma 2"
class="cls-1"
d="m 127.18676,70.446691 1.10835,88.628229 c 0,0 -1.75925,2.70033 5.54172,3.32503 7.30096,0.62471 121.86344,1.10835 121.86344,1.10835 a 5.4711894,5.4711894 0 0 0 3.32503,-5.54172 c -0.0867,-4.38804 0,-88.628233 0,-88.628233" />
<path
id="Forma_5"
data-name="Forma 5"
class="cls-2"
d="m 267.20286,207.74533 c 1.47007,1.13656 53.06651,44.51412 53.06651,44.51412 l -51.05134,47.17617" />
<path
id="Forma_6"
data-name="Forma 6"
class="cls-3"
d="M 315.56697,253.08668 152.33811,252.0791" />
</svg>
<?xml version="1.0" encoding="UTF-8"?><svg id="PCSX2_-_load" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 384"><defs><style>.cls-1{stroke-width:29px;}.cls-1,.cls-2{fill:none;stroke:#fff;}.cls-2{stroke-width:28px;}</style></defs><g id="By_maxihplay"><path id="Forma_5" class="cls-2" d="M265.05,192.85c.45,.33,52.68,43.98,52.68,43.98l-52.04,47.7"/><path id="Forma_6" class="cls-2" d="M309.03,238.01l-132.24-.6"/><path id="Forma_2" class="cls-2" d="M114.53,59.5l1.11,89.07s-1.77,2.71,5.57,3.34c7.33,.63,122.47,1.11,122.47,1.11,2.21-.93,3.56-3.18,3.34-5.57-.09-4.41,0-89.07,0-89.07"/><path id="Forma_1" class="cls-1" d="M322.31,290.47s-.12,21.8-.1,22.87c.31,13.33-11.31,12.25-11.31,12.25,0,0-244.42-1.35-252.73-1.11s-8.91-10.02-8.91-10.02V68.41s1.5-7.5,8.91-8.91,215.99,0,215.99,0l48.05,46.76,.27,72.95"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 818 B

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg id="guitar_PCSX2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 492.66 473.14"><defs><style>.cls-1,.cls-2{fill:#fff;}.cls-2{stroke:#fff;stroke-miterlimit:10;stroke-width:20px;}</style></defs><g id="By_maxihplay"><path id="corpo" class="cls-1" d="M187.91,192.05c-.75,14.56,6.75,47.85,20.03,67.76,19.32,28.97,42.12,37.78,54.54,43.83-17.76,8.99-43.47,27.14-53.18,55-1.18,3.26-1.97,6.71-2.27,10.24-3.93,46.09-40.35,63.32-70.26,64.13-14.57,.4-29.14-2.93-42.13-9.52-14.19-7.25-26.02-17.98-35.01-32.02-.41-.58-.81-1.15-1.22-1.73-10.27-14.2-16.49-30.76-17.93-47.84-1.42-16.1,1.39-31.83,7.86-45.71,2.65-5.68,10.86-21.28,28.05-31.02,12.09-6.86,22.94-7.51,28.71-8.28,17.19-2.32,61.18-15.77,82.82-64.84Zm19.53-71.29c-38.91,1.06-45.85,41.06-64.11,71.01-14.61,23.88-38.65,24.92-40.31,24.97h-.1C9.65,222.7-30.45,335.12,25.87,413.13c26.97,41.92,70.63,61.09,111.99,59.96,53.67-1.46,103.78-36.96,109.18-100.8h0c19.93-58.65,105.53-15.58,93.41-112.5-23.14,8.75-40.07,12.44-52.19,12.77-26.98,.73-31.85-18.13-27.99-30.95l-25.37-31.05c-20.51-52.62-2.68-69.18,10.16-86.16-6.4-1.49-32.54-3.87-37.62-3.63h0Z"/><path id="cordas" class="cls-2" d="M103.37,364.66l-2.97-3.25c-3.52-3.71-3.25-9.64,.56-13.17l65.75-61.02c3.8-3.52,9.64-3.25,13.17,.46l2.97,3.25c3.52,3.71,3.25,9.64-.56,13.17l-65.75,61.02c-3.71,3.52-9.64,3.25-13.17-.46h0Z"/><polygon id="braco" class="cls-2" points="238.8 255 223.15 236.15 365.37 103.68 382.39 121.38 238.8 255"/><path class="cls-1" d="M485.46,26.95l-16.94-18.24c-10.07-10.97-27.21-11.69-38.25-1.56l-68.38,63.39c-10.94,10.08-11.64,27.19-1.51,38.22l16.94,18.24c5.31,5.78,12.58,8.71,19.88,8.71,6.56,0,13.14-2.37,18.37-7.16l68.35-63.35c5.33-4.89,8.42-11.56,8.72-18.79,.29-7.2-2.23-14.09-7.17-19.47Z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

@@ -24,9 +24,9 @@
inkscape:deskcolor="#505050"
inkscape:document-units="px"
showgrid="false"
inkscape:zoom="0.921875"
inkscape:cx="47.728814"
inkscape:cy="215.32203"
inkscape:zoom="1.3037281"
inkscape:cx="-8.0538264"
inkscape:cy="358.20352"
inkscape:window-width="1920"
inkscape:window-height="956"
inkscape:window-x="0"
@@ -46,13 +46,13 @@
cy="256.1091"
r="231.50449" />
<path
style="fill:none;stroke:#ffffff;stroke-width:38.6591;stroke-linecap:round;stroke-dasharray:none"
d="M 256,93.780771 V 418.43743"
style="fill:none;stroke:#ffffff;stroke-width:50;stroke-linecap:round;stroke-dasharray:none"
d="m 256,132.18075 v 247.8567"
id="path1039"
sodipodi:nodetypes="cc" />
<path
style="fill:none;stroke:#ffffff;stroke-width:37.7963;stroke-linecap:round;stroke-dasharray:none"
d="M 87.841479,256.1091 H 423.27606"
style="fill:none;stroke:#ffffff;stroke-width:50;stroke-linecap:round;stroke-dasharray:none"
d="M 137.09627,256.1091 H 374.90373"
id="path1041"
sodipodi:nodetypes="cc" />
</g>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -24,9 +24,9 @@
inkscape:deskcolor="#505050"
inkscape:document-units="px"
showgrid="false"
inkscape:zoom="0.921875"
inkscape:cx="47.728814"
inkscape:cy="215.32203"
inkscape:zoom="1.3037281"
inkscape:cx="-7.2867955"
inkscape:cy="358.20352"
inkscape:window-width="1920"
inkscape:window-height="956"
inkscape:window-x="0"
@@ -46,8 +46,8 @@
cy="256.1091"
r="231.50449" />
<path
style="fill:none;stroke:#ffffff;stroke-width:37.7963;stroke-linecap:round;stroke-dasharray:none"
d="M 87.841479,256.1091 H 423.27606"
style="fill:none;stroke:#ffffff;stroke-width:50;stroke-linecap:round;stroke-dasharray:none"
d="M 137.09627,256.1091 H 374.90373"
id="path1041"
sodipodi:nodetypes="cc" />
</g>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

+148 -145
View File
@@ -1,147 +1,150 @@
<RCC>
<qresource>
<file>icons/AppIcon64.png</file>
<file>icons/applications-system-24.png</file>
<file>icons/black/index.theme</file>
<file>icons/black/svg/arrow-left-right-line.svg</file>
<file>icons/black/svg/artboard-2-line.svg</file>
<file>icons/black/svg/at.svg</file>
<file>icons/black/svg/band-aid-line.svg</file>
<file>icons/black/svg/brush-line.svg</file>
<file>icons/black/svg/cheats-line.svg</file>
<file>icons/black/svg/checkbox-multiple-blank-line.svg</file>
<file>icons/black/svg/chip-line.svg</file>
<file>icons/black/svg/close-line.svg</file>
<file>icons/black/svg/controller-line.svg</file>
<file>icons/black/svg/controller-strike-line.svg</file>
<file>icons/black/svg/delete-back-2-line.svg</file>
<file>icons/black/svg/disc-2-line.svg</file>
<file>icons/black/svg/disc-eject-line.svg</file>
<file>icons/black/svg/discord.svg</file>
<file>icons/black/svg/door-open-line.svg</file>
<file>icons/black/svg/download-2-line.svg</file>
<file>icons/black/svg/eject-line.svg</file>
<file>icons/black/svg/emulation-line.svg</file>
<file>icons/black/svg/file-add-line.svg</file>
<file>icons/black/svg/file-line.svg</file>
<file>icons/black/svg/file-list-line.svg</file>
<file>icons/black/svg/file-reduce-line.svg</file>
<file>icons/black/svg/file-search-line.svg</file>
<file>icons/black/svg/file-settings-line.svg</file>
<file>icons/black/svg/filter-line.svg</file>
<file>icons/black/svg/flashlight-line.svg</file>
<file>icons/black/svg/floppy-in-line.svg</file>
<file>icons/black/svg/floppy-out-line.svg</file>
<file>icons/black/svg/folder-add-line.svg</file>
<file>icons/black/svg/folder-open-line.svg</file>
<file>icons/black/svg/folder-reduce-line.svg</file>
<file>icons/black/svg/folder-settings-line.svg</file>
<file>icons/black/svg/fullscreen-line.svg</file>
<file>icons/black/svg/function-line.svg</file>
<file>icons/black/svg/github.svg</file>
<file>icons/black/svg/global-line.svg</file>
<file>icons/black/svg/heart-circle-line.svg</file>
<file>icons/black/svg/heart-monitor-line.svg</file>
<file>icons/black/svg/image-fill.svg</file>
<file>icons/black/svg/interface-line.svg</file>
<file>icons/black/svg/keyboard-line.svg</file>
<file>icons/black/svg/lightbulb-line.svg</file>
<file>icons/black/svg/list-check.svg</file>
<file>icons/black/svg/login-box-line.svg</file>
<file>icons/black/svg/memcard-line.svg</file>
<file>icons/black/svg/mouse-line.svg</file>
<file>icons/black/svg/pause-line.svg</file>
<file>icons/black/svg/play-line.svg</file>
<file>icons/black/svg/price-tag-3-line.svg</file>
<file>icons/black/svg/refresh-line.svg</file>
<file>icons/black/svg/restart-line.svg</file>
<file>icons/black/svg/save-3-line.svg</file>
<file>icons/black/svg/screenshot-2-line.svg</file>
<file>icons/black/svg/settings-3-line.svg</file>
<file>icons/black/svg/shut-down-line.svg</file>
<file>icons/black/svg/tools-line.svg</file>
<file>icons/black/svg/trophy-line.svg</file>
<file>icons/black/svg/tv-2-line.svg</file>
<file>icons/black/svg/usb-fill.svg</file>
<file>icons/black/svg/volume-up-line.svg</file>
<file>icons/black/svg/warning-line.svg</file>
<file>icons/black/svg/window-2-line.svg</file>
<file>icons/black/svg/zoom-in-line.svg</file>
<file>icons/black/svg/zoom-out-line.svg</file>
<file>icons/logo.png</file>
<file>icons/media-optical-24.png</file>
<file>icons/media-optical-gear-24.png</file>
<file>icons/media-optical.png</file>
<file>icons/QT.png</file>
<file>icons/update.png</file>
<file>icons/white/index.theme</file>
<file>icons/white/svg/arrow-left-right-line.svg</file>
<file>icons/white/svg/artboard-2-line.svg</file>
<file>icons/white/svg/at.svg</file>
<file>icons/white/svg/band-aid-line.svg</file>
<file>icons/white/svg/brush-line.svg</file>
<file>icons/white/svg/cheats-line.svg</file>
<file>icons/white/svg/checkbox-multiple-blank-line.svg</file>
<file>icons/white/svg/chip-line.svg</file>
<file>icons/white/svg/close-line.svg</file>
<file>icons/white/svg/controller-line.svg</file>
<file>icons/white/svg/controller-strike-line.svg</file>
<file>icons/white/svg/delete-back-2-line.svg</file>
<file>icons/white/svg/disc-2-line.svg</file>
<file>icons/white/svg/disc-eject-line.svg</file>
<file>icons/white/svg/discord.svg</file>
<file>icons/white/svg/door-open-line.svg</file>
<file>icons/white/svg/download-2-line.svg</file>
<file>icons/white/svg/eject-line.svg</file>
<file>icons/white/svg/emulation-line.svg</file>
<file>icons/white/svg/file-add-line.svg</file>
<file>icons/white/svg/file-line.svg</file>
<file>icons/white/svg/file-list-line.svg</file>
<file>icons/white/svg/file-reduce-line.svg</file>
<file>icons/white/svg/file-search-line.svg</file>
<file>icons/white/svg/file-settings-line.svg</file>
<file>icons/white/svg/filter-line.svg</file>
<file>icons/white/svg/flashlight-line.svg</file>
<file>icons/white/svg/floppy-in-line.svg</file>
<file>icons/white/svg/floppy-out-line.svg</file>
<file>icons/white/svg/folder-add-line.svg</file>
<file>icons/white/svg/folder-open-line.svg</file>
<file>icons/white/svg/folder-reduce-line.svg</file>
<file>icons/white/svg/folder-settings-line.svg</file>
<file>icons/white/svg/fullscreen-line.svg</file>
<file>icons/white/svg/function-line.svg</file>
<file>icons/white/svg/github.svg</file>
<file>icons/white/svg/global-line.svg</file>
<file>icons/white/svg/heart-circle-line.svg</file>
<file>icons/white/svg/heart-monitor-line.svg</file>
<file>icons/white/svg/image-fill.svg</file>
<file>icons/white/svg/interface-line.svg</file>
<file>icons/white/svg/keyboard-line.svg</file>
<file>icons/white/svg/lightbulb-line.svg</file>
<file>icons/white/svg/list-check.svg</file>
<file>icons/white/svg/login-box-line.svg</file>
<file>icons/white/svg/memcard-line.svg</file>
<file>icons/white/svg/mouse-line.svg</file>
<file>icons/white/svg/pause-line.svg</file>
<file>icons/white/svg/play-line.svg</file>
<file>icons/white/svg/price-tag-3-line.svg</file>
<file>icons/white/svg/refresh-line.svg</file>
<file>icons/white/svg/restart-line.svg</file>
<file>icons/white/svg/save-3-line.svg</file>
<file>icons/white/svg/screenshot-2-line.svg</file>
<file>icons/white/svg/settings-3-line.svg</file>
<file>icons/white/svg/shut-down-line.svg</file>
<file>icons/white/svg/tools-line.svg</file>
<file>icons/white/svg/trophy-line.svg</file>
<file>icons/white/svg/tv-2-line.svg</file>
<file>icons/white/svg/usb-fill.svg</file>
<file>icons/white/svg/volume-up-line.svg</file>
<file>icons/white/svg/warning-line.svg</file>
<file>icons/white/svg/window-2-line.svg</file>
<file>icons/white/svg/zoom-in-line.svg</file>
<file>icons/white/svg/zoom-out-line.svg</file>
<file>images/DrivingForce.png</file>
<file>images/dualshock-2.png</file>
<file>images/GTForce.png</file>
</qresource>
<qresource>
<file>icons/AppIcon64.png</file>
<file>icons/applications-system-24.png</file>
<file>icons/black/index.theme</file>
<file>icons/black/svg/arrow-left-right-line.svg</file>
<file>icons/black/svg/artboard-2-line.svg</file>
<file>icons/black/svg/at.svg</file>
<file>icons/black/svg/band-aid-line.svg</file>
<file>icons/black/svg/brush-line.svg</file>
<file>icons/black/svg/cheats-line.svg</file>
<file>icons/black/svg/checkbox-multiple-blank-line.svg</file>
<file>icons/black/svg/chip-line.svg</file>
<file>icons/black/svg/close-line.svg</file>
<file>icons/black/svg/controller-line.svg</file>
<file>icons/black/svg/controller-strike-line.svg</file>
<file>icons/black/svg/delete-back-2-line.svg</file>
<file>icons/black/svg/disc-2-line.svg</file>
<file>icons/black/svg/disc-eject-line.svg</file>
<file>icons/black/svg/discord.svg</file>
<file>icons/black/svg/door-open-line.svg</file>
<file>icons/black/svg/download-2-line.svg</file>
<file>icons/black/svg/eject-line.svg</file>
<file>icons/black/svg/emulation-line.svg</file>
<file>icons/black/svg/file-add-line.svg</file>
<file>icons/black/svg/file-line.svg</file>
<file>icons/black/svg/file-list-line.svg</file>
<file>icons/black/svg/file-reduce-line.svg</file>
<file>icons/black/svg/file-search-line.svg</file>
<file>icons/black/svg/file-settings-line.svg</file>
<file>icons/black/svg/filter-line.svg</file>
<file>icons/black/svg/flashlight-line.svg</file>
<file>icons/black/svg/floppy-in-line.svg</file>
<file>icons/black/svg/floppy-out-line.svg</file>
<file>icons/black/svg/folder-add-line.svg</file>
<file>icons/black/svg/folder-open-line.svg</file>
<file>icons/black/svg/folder-reduce-line.svg</file>
<file>icons/black/svg/guitar-line.svg</file>
<file>icons/black/svg/folder-settings-line.svg</file>
<file>icons/black/svg/fullscreen-line.svg</file>
<file>icons/black/svg/function-line.svg</file>
<file>icons/black/svg/github.svg</file>
<file>icons/black/svg/global-line.svg</file>
<file>icons/black/svg/heart-circle-line.svg</file>
<file>icons/black/svg/heart-monitor-line.svg</file>
<file>icons/black/svg/image-fill.svg</file>
<file>icons/black/svg/interface-line.svg</file>
<file>icons/black/svg/keyboard-line.svg</file>
<file>icons/black/svg/lightbulb-line.svg</file>
<file>icons/black/svg/list-check.svg</file>
<file>icons/black/svg/login-box-line.svg</file>
<file>icons/black/svg/memcard-line.svg</file>
<file>icons/black/svg/mouse-line.svg</file>
<file>icons/black/svg/pause-line.svg</file>
<file>icons/black/svg/play-line.svg</file>
<file>icons/black/svg/price-tag-3-line.svg</file>
<file>icons/black/svg/refresh-line.svg</file>
<file>icons/black/svg/restart-line.svg</file>
<file>icons/black/svg/save-3-line.svg</file>
<file>icons/black/svg/screenshot-2-line.svg</file>
<file>icons/black/svg/settings-3-line.svg</file>
<file>icons/black/svg/shut-down-line.svg</file>
<file>icons/black/svg/tools-line.svg</file>
<file>icons/black/svg/trophy-line.svg</file>
<file>icons/black/svg/tv-2-line.svg</file>
<file>icons/black/svg/usb-fill.svg</file>
<file>icons/black/svg/volume-up-line.svg</file>
<file>icons/black/svg/warning-line.svg</file>
<file>icons/black/svg/window-2-line.svg</file>
<file>icons/black/svg/zoom-in-line.svg</file>
<file>icons/black/svg/zoom-out-line.svg</file>
<file>icons/logo.png</file>
<file>icons/media-optical-24.png</file>
<file>icons/media-optical-gear-24.png</file>
<file>icons/media-optical.png</file>
<file>icons/QT.png</file>
<file>icons/update.png</file>
<file>icons/white/index.theme</file>
<file>icons/white/svg/arrow-left-right-line.svg</file>
<file>icons/white/svg/artboard-2-line.svg</file>
<file>icons/white/svg/at.svg</file>
<file>icons/white/svg/band-aid-line.svg</file>
<file>icons/white/svg/brush-line.svg</file>
<file>icons/white/svg/cheats-line.svg</file>
<file>icons/white/svg/checkbox-multiple-blank-line.svg</file>
<file>icons/white/svg/chip-line.svg</file>
<file>icons/white/svg/close-line.svg</file>
<file>icons/white/svg/controller-line.svg</file>
<file>icons/white/svg/controller-strike-line.svg</file>
<file>icons/white/svg/delete-back-2-line.svg</file>
<file>icons/white/svg/disc-2-line.svg</file>
<file>icons/white/svg/disc-eject-line.svg</file>
<file>icons/white/svg/discord.svg</file>
<file>icons/white/svg/door-open-line.svg</file>
<file>icons/white/svg/download-2-line.svg</file>
<file>icons/white/svg/eject-line.svg</file>
<file>icons/white/svg/emulation-line.svg</file>
<file>icons/white/svg/file-add-line.svg</file>
<file>icons/white/svg/file-line.svg</file>
<file>icons/white/svg/file-list-line.svg</file>
<file>icons/white/svg/file-reduce-line.svg</file>
<file>icons/white/svg/file-search-line.svg</file>
<file>icons/white/svg/file-settings-line.svg</file>
<file>icons/white/svg/filter-line.svg</file>
<file>icons/white/svg/flashlight-line.svg</file>
<file>icons/white/svg/floppy-in-line.svg</file>
<file>icons/white/svg/floppy-out-line.svg</file>
<file>icons/white/svg/folder-add-line.svg</file>
<file>icons/white/svg/folder-open-line.svg</file>
<file>icons/white/svg/folder-reduce-line.svg</file>
<file>icons/white/svg/folder-settings-line.svg</file>
<file>icons/white/svg/fullscreen-line.svg</file>
<file>icons/white/svg/function-line.svg</file>
<file>icons/white/svg/github.svg</file>
<file>icons/white/svg/global-line.svg</file>
<file>icons/white/svg/guitar-line.svg</file>
<file>icons/white/svg/heart-circle-line.svg</file>
<file>icons/white/svg/heart-monitor-line.svg</file>
<file>icons/white/svg/image-fill.svg</file>
<file>icons/white/svg/interface-line.svg</file>
<file>icons/white/svg/keyboard-line.svg</file>
<file>icons/white/svg/lightbulb-line.svg</file>
<file>icons/white/svg/list-check.svg</file>
<file>icons/white/svg/login-box-line.svg</file>
<file>icons/white/svg/memcard-line.svg</file>
<file>icons/white/svg/mouse-line.svg</file>
<file>icons/white/svg/pause-line.svg</file>
<file>icons/white/svg/play-line.svg</file>
<file>icons/white/svg/price-tag-3-line.svg</file>
<file>icons/white/svg/refresh-line.svg</file>
<file>icons/white/svg/restart-line.svg</file>
<file>icons/white/svg/save-3-line.svg</file>
<file>icons/white/svg/screenshot-2-line.svg</file>
<file>icons/white/svg/settings-3-line.svg</file>
<file>icons/white/svg/shut-down-line.svg</file>
<file>icons/white/svg/tools-line.svg</file>
<file>icons/white/svg/trophy-line.svg</file>
<file>icons/white/svg/tv-2-line.svg</file>
<file>icons/white/svg/usb-fill.svg</file>
<file>icons/white/svg/volume-up-line.svg</file>
<file>icons/white/svg/warning-line.svg</file>
<file>icons/white/svg/window-2-line.svg</file>
<file>icons/white/svg/zoom-in-line.svg</file>
<file>icons/white/svg/zoom-out-line.svg</file>
<file>images/DrivingForce.png</file>
<file>images/dualshock-2.png</file>
<file>images/GTForce.png</file>
<file>images/guitar.png</file>
</qresource>
</RCC>
+56 -22
View File
@@ -106,7 +106,8 @@ namespace Achievements
static void EndLoadingScreen(bool was_running_idle);
static void LoginCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data);
static void LoginASyncCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data);
static void SendLogin(const char* username, const char* password, Common::HTTPDownloader* http_downloader,
static void LoginWithTokenCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data);
static void SendLogin(const char* username, const char* password, const char* api_token, Common::HTTPDownloader* http_downloader,
Common::HTTPDownloader::Request::Callback callback);
static void DownloadImage(std::string url, std::string cache_filename);
static void DisplayAchievementSummary();
@@ -129,7 +130,7 @@ namespace Achievements
static void UpdateRichPresence();
static void SendPingCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data);
static void UnlockAchievementCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data);
static void SubmitLeaderboardCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data);
static void SubmitLeaderboardCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data, u32 lboard_id);
static bool s_active = false;
static bool s_logged_in = false;
@@ -164,7 +165,6 @@ namespace Achievements
static Common::Timer s_last_ping_time;
static u32 s_last_queried_lboard = 0;
static u32 s_submitting_lboard_id = 0;
static std::optional<std::vector<Achievements::LeaderboardEntry>> s_lboard_entries;
template <typename T>
@@ -445,6 +445,11 @@ bool Achievements::IsLoggedIn()
return s_logged_in;
}
bool Achievements::HasSavedCredentials()
{
return !s_username.empty() && !s_api_token.empty();
}
bool Achievements::ChallengeModeActive()
{
#ifdef ENABLE_RAINTEGRATION
@@ -513,7 +518,7 @@ void Achievements::Initialize()
s_last_ping_time.Reset();
s_username = Host::GetBaseStringSettingValue("Achievements", "Username");
s_api_token = Host::GetBaseStringSettingValue("Achievements", "Token");
s_logged_in = (!s_username.empty() && !s_api_token.empty());
s_logged_in = false; // We are not logged in until we confirm those credentials
if (VMManager::HasValidVM())
GameChanged(VMManager::GetDiscCRC(), VMManager::GetCurrentCRC());
@@ -634,7 +639,7 @@ void Achievements::SetChallengeMode(bool enabled)
s_challenge_mode = enabled;
if (HasActiveGame())
ImGuiFullscreen::ShowToast(std::string(), enabled ? "Hardcore mode is now enabled." : "Hardcore mode is now disabled.", 10.0f);
ImGuiFullscreen::ShowToast(std::string(), enabled ? TRANSLATE("Achievements", "Hardcore mode is now enabled.") : TRANSLATE("Achievements", "Hardcore mode is now disabled."), 10.0f);
if (HasActiveGame() && !IsTestModeActive())
{
@@ -953,13 +958,36 @@ void Achievements::LoginASyncCallback(s32 status_code, const std::string& conten
LoginCallback(status_code, std::move(content_type), std::move(data));
}
void Achievements::LoginWithTokenCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data)
{
std::unique_lock lock(s_achievements_mutex);
RAPIResponse<rc_api_login_response_t, rc_api_process_login_response, rc_api_destroy_login_response> response(status_code, data);
if (!response)
{
lock.unlock();
Logout();
Host::OnAchievementsLoginRequested(LoginRequestReason::TokenInvalid);
return;
}
if (s_active)
{
s_logged_in = true;
// If we have a game running, set it up.
if (!s_game_hash.empty())
SendGetGameId();
}
}
void Achievements::SendLogin(
const char* username, const char* password, Common::HTTPDownloader* http_downloader, Common::HTTPDownloader::Request::Callback callback)
const char* username, const char* password, const char* api_token, Common::HTTPDownloader* http_downloader, Common::HTTPDownloader::Request::Callback callback)
{
RAPIRequest<rc_api_login_request_t, rc_api_init_login_request> request;
request.username = username;
request.password = password;
request.api_token = nullptr;
request.api_token = api_token;
request.Send(http_downloader, std::move(callback));
}
@@ -975,7 +1003,7 @@ bool Achievements::LoginAsync(const char* username, const char* password)
ImGuiFullscreen::OpenBackgroundProgressDialog("cheevos_async_login", "Logging in to RetroAchievements...", 0, 0, 0);
}
SendLogin(username, password, s_http_downloader.get(), LoginASyncCallback);
SendLogin(username, password, nullptr, s_http_downloader.get(), LoginASyncCallback);
return true;
}
@@ -989,7 +1017,7 @@ bool Achievements::Login(const char* username, const char* password)
if (s_active)
{
SendLogin(username, password, s_http_downloader.get(), LoginCallback);
SendLogin(username, password, nullptr, s_http_downloader.get(), LoginCallback);
s_http_downloader->WaitForAllRequests();
return IsLoggedIn();
}
@@ -1000,12 +1028,21 @@ bool Achievements::Login(const char* username, const char* password)
if (!http_downloader)
return false;
SendLogin(username, password, http_downloader.get(), LoginCallback);
SendLogin(username, password, nullptr, http_downloader.get(), LoginCallback);
http_downloader->WaitForAllRequests();
return !Host::GetBaseStringSettingValue("Achievements", "Token").empty();
}
bool Achievements::LoginWithTokenAsync(const char* username, const char* api_token)
{
if (s_logged_in || std::strlen(username) == 0 || std::strlen(api_token) == 0 || IsUsingRAIntegration())
return false;
SendLogin(username, nullptr, api_token, s_http_downloader.get(), LoginWithTokenCallback);
return true;
}
void Achievements::Logout()
{
if (s_active)
@@ -1015,11 +1052,11 @@ void Achievements::Logout()
if (s_logged_in)
{
ClearGameInfo();
std::string().swap(s_username);
std::string().swap(s_api_token);
s_logged_in = false;
Host::OnAchievementsRefreshed();
}
std::string().swap(s_username);
std::string().swap(s_api_token);
}
// remove from config
@@ -1477,6 +1514,8 @@ void Achievements::GameChanged(u32 disc_crc, u32 crc)
if (IsLoggedIn())
SendGetGameId();
else if (HasSavedCredentials())
LoginWithTokenAsync(s_username.c_str(), s_api_token.c_str());
}
void Achievements::SendGetGameId()
@@ -1777,7 +1816,7 @@ void Achievements::UnlockAchievementCallback(s32 status_code, const std::string&
Console.WriteLn("Successfully unlocked achievement %u, new score %u", response.awarded_achievement_id, response.new_player_score);
}
void Achievements::SubmitLeaderboardCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data)
void Achievements::SubmitLeaderboardCallback(s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data, u32 lboard_id)
{
if (!VMManager::HasValidVM())
return;
@@ -1791,11 +1830,7 @@ void Achievements::SubmitLeaderboardCallback(s32 status_code, const std::string&
// Force the next leaderboard query to repopulate everything, just in case the user wants to see their new score
s_last_queried_lboard = 0;
// RA API doesn't send us the leaderboard ID back.. hopefully we don't submit two at once :/
if (s_submitting_lboard_id == 0)
return;
const Leaderboard* lb = GetLeaderboardByID(std::exchange(s_submitting_lboard_id, 0u));
const Leaderboard* lb = GetLeaderboardByID(lboard_id);
if (!lb || !FullscreenUI::IsInitialized() || !EmuConfig.Achievements.Notifications)
return;
@@ -1925,16 +1960,15 @@ void Achievements::SubmitLeaderboard(u32 leaderboard_id, int value)
return;
}
std::unique_lock lock(s_achievements_mutex);
s_submitting_lboard_id = leaderboard_id;
RAPIRequest<rc_api_submit_lboard_entry_request_t, rc_api_init_submit_lboard_entry_request> request;
request.username = s_username.c_str();
request.api_token = s_api_token.c_str();
request.game_hash = s_game_hash.c_str();
request.leaderboard_id = leaderboard_id;
request.score = value;
request.Send(SubmitLeaderboardCallback);
request.Send([leaderboard_id](s32 status_code, const std::string& content_type, Common::HTTPDownloader::Request::Data data) {
SubmitLeaderboardCallback(status_code, content_type, std::move(data), leaderboard_id);
});
// Technically not going through the resource API, but since we're passing this to something else, we can't.
if (EmuConfig.Achievements.SoundEffects)
+9 -1
View File
@@ -31,6 +31,12 @@
namespace Achievements
{
enum class LoginRequestReason
{
UserInitiated,
TokenInvalid,
};
enum class AchievementCategory : u8
{
Local = 0,
@@ -88,6 +94,7 @@ namespace Achievements
bool IsActive();
bool IsLoggedIn();
bool HasSavedCredentials();
bool ChallengeModeActive();
bool LeaderboardsActive();
bool IsTestModeActive();
@@ -131,6 +138,7 @@ namespace Achievements
bool LoginAsync(const char* username, const char* password);
bool Login(const char* username, const char* password);
bool LoginWithTokenAsync(const char* username, const char* api_token);
void Logout();
void GameChanged(u32 disc_crc, u32 crc);
@@ -253,6 +261,6 @@ namespace Achievements
/// Functions implemented in the frontend.
namespace Host
{
void OnAchievementsLoginRequested(Achievements::LoginRequestReason reason);
void OnAchievementsRefreshed();
void OnAchievementsChallengeModeChanged();
} // namespace Host
+1 -1
View File
@@ -30,7 +30,7 @@
#include "IopHw.h"
#include "IopDma.h"
#include "VMManager.h"
#include "Sio.h"
#include "SIO/Sio.h"
#include "common/Error.h"
#include "common/FileSystem.h"
+200
View File
@@ -0,0 +1,200 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "CDVD/CDVDcommon.h"
#include "CDVD/IsoHasher.h"
#include "Host.h"
#include "common/Error.h"
#include "common/MD5Digest.h"
#include "common/StringUtil.h"
#include "fmt/core.h"
#include <algorithm>
IsoHasher::IsoHasher() = default;
IsoHasher::~IsoHasher()
{
Close();
}
std::string_view IsoHasher::GetTrackTypeString(u32 type)
{
switch (type)
{
case CDVD_AUDIO_TRACK:
return TRANSLATE_SV("CDVD", "Audio");
case CDVD_MODE1_TRACK:
return TRANSLATE_SV("CDVD", "Mode 1");
case CDVD_MODE2_TRACK:
return TRANSLATE_SV("CDVD", "Mode 2");
default:
return TRANSLATE_SV("CDVD", "Unknown");
}
}
bool IsoHasher::Open(std::string iso_path, Error* error)
{
Close();
CDVDsys_SetFile(CDVD_SourceType::Iso, std::move(iso_path));
CDVDsys_ChangeSource(CDVD_SourceType::Iso);
m_is_open = DoCDVDopen();
if (!m_is_open)
{
Error::SetString(error, "Failed to open CDVD.");
return false;
}
const s32 type = DoCDVDdetectDiskType();
switch (type)
{
case CDVD_TYPE_PSCD:
case CDVD_TYPE_PSCDDA:
case CDVD_TYPE_PS2CD:
case CDVD_TYPE_PS2CDDA:
m_is_cd = true;
break;
case CDVD_TYPE_PS2DVD:
m_is_cd = false;
break;
default:
Error::SetString(error, fmt::format("Unknown CDVD disk type {}", type));
return false;
}
cdvdTN tn;
if (CDVD->getTN(&tn) < 0)
{
Error::SetString(error, "Failed to get track count.");
return false;
}
for (u8 track = tn.strack; track <= tn.etrack; track++)
{
cdvdTD td, next_td;
if (CDVD->getTD(track, &td) < 0 || CDVD->getTD((track == tn.etrack) ? 0 : (track + 1), &next_td) < 0)
{
Error::SetString(error, fmt::format("Failed to get track range for {}", static_cast<unsigned>(track)));
return false;
}
// sanity check..
if (next_td.lsn < td.lsn)
{
Error::SetString(error,
fmt::format("Invalid track range for {} ({},{})", static_cast<unsigned>(track), td.lsn, next_td.lsn));
return false;
}
Track strack;
strack.number = track;
strack.type = td.type;
strack.start_lsn = td.lsn;
strack.sectors = next_td.lsn - td.lsn;
strack.size = static_cast<u64>(strack.sectors) * (m_is_cd ? 2352 : 2048);
m_tracks.push_back(std::move(strack));
}
return true;
}
void IsoHasher::Close()
{
if (!m_is_open)
return;
DoCDVDclose();
m_tracks.clear();
m_is_cd = false;
m_is_open = false;
}
void IsoHasher::ComputeHashes(ProgressCallback* callback)
{
callback->SetProgressRange(GetTrackCount());
callback->SetProgressValue(0);
callback->SetCancellable(true);
for (u32 index = 0; index < GetTrackCount(); index++)
{
Track& track = m_tracks[index];
if (!track.hash.empty())
{
callback->SetProgressValue(index + 1);
continue;
}
callback->PushState();
const bool result = ComputeTrackHash(track, callback);
callback->PopState();
if (!result)
break;
callback->SetProgressValue(index + 1);
callback->IncrementProgressValue();
}
callback->SetProgressValue(GetTrackCount());
}
bool IsoHasher::ComputeTrackHash(Track& track, ProgressCallback* callback)
{
// use 2048 byte reads for DVDs, otherwise 2352 raw.
const int read_mode = m_is_cd ? CDVD_MODE_2352 : CDVD_MODE_2048;
const u32 sector_size = m_is_cd ? 2352 : 2048;
std::vector<u8> sector_buffer(sector_size);
const u32 update_interval = std::max<u32>(track.sectors / 100u, 1u);
callback->SetFormattedStatusText("Computing hash for track %u...", track.number);
callback->SetProgressRange(track.sectors);
MD5Digest md5;
for (u32 i = 0; i < track.sectors; i++)
{
if (callback->IsCancelled())
return false;
const u32 lsn = track.start_lsn + i;
if (DoCDVDreadSector(sector_buffer.data(), lsn, read_mode) != 0)
{
callback->DisplayFormattedModalError("Read error at LSN %u", lsn);
return false;
}
md5.Update(sector_buffer.data(), sector_size);
if ((i % update_interval) == 0)
callback->SetProgressValue(i);
}
u8 digest[16];
md5.Final(digest);
track.hash =
fmt::format("{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8],
digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15]);
callback->SetProgressValue(track.sectors);
return true;
}

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