Reported by EddyOP (60 FPS and Widescreen disabled under RetroAchievements
Hardcore) and diagnosed by Jetup, who found that moving the same lines under a
widescreen heading re-enabled them — ARMSX2 issue #541.
The Hardcore gate from 2f3f28faae allows a group through only if it DECLARES
gsaspectratio or gsinterlacemode. That rule was picked to separate a Skip
Cutscenes cheat from a Widescreen patch living in the same pnach, and it does
separate those two. What it does not survive is the rest of the database.
Measured across the shipped 4437 files, the groups it blocked were overwhelmingly
not cheats:
305 50 FPS
177 60 FPS
168 50/60 FPS
102 Remove Blackbars <- a widescreen patch
100 NTSC Mode
31 480p Mode
Almost every real presentation patch changes the picture by writing EE memory and
declares nothing, so the declaration test caught the tail and missed the bulk.
The original commit sampled Car select and Auto-activate analogs and concluded
the blocked set read like cheats; across the whole database it does not.
So the name is now consulted too, matched case-insensitively against the labels
the database actually uses. Matched on the EFFECT rather than the verb — Remove
Blur, Disable Blur and No Blur are the same patch, and listing verbs caught one
spelling while blocking the others.
After: 4673 groups stay by declaration, 1206 more stay by name, 495 remain
blocked. What still blocks reads the way it should — Adjusted triggers
sensitivity, Trigger control mappings, GT3 Chase Camera, and Skip Cutscenes
itself, which is the case the gate was written for.
An unrecognised name still fails CLOSED, which is the safe direction: a new cheat
is blocked by default and only an understood presentation class is let through.
★ Frame-rate patches are the judgement call here. They are in the allowlist
because they are what was reported broken and desktop PCSX2 permits them, but
they are the entry RetroAchievements is most likely to object to. If RA rules
them out, deleting three strings from ALLOWED is the whole change.
Reported as "patches apply with every patch setting off, and won't turn off" —
SOTC/KH2/GOW2. One chain of defects, verified on device:
- PatchManagerViewModel.refresh() called syncAllEnableLists() unconditionally, so
merely OPENING the Patch Manager persisted every uncommented group of every
on-disk .pnach as enabled. Community pnach files ship uncommented, and patches
are matched by NAME, so a name like "60 FPS" then armed the same-named group in
any of the ~4000 bundled files, for games never opened. Removed; import still
registers its own file, which was the only legitimate use.
- EnumeratePnachFiles fell back to the bundled zip even when disk files existed,
contradicting its own "prefer files on disk" comment. Deleting a pnach silently
promoted the identically-named bundled group in its place.
- delete() removed the file but never dropped its names from the enable list, so
they stayed armed forever.
- ReloadPatchAffectingOptions never reset CurrentCustomAspectRatio, which only
ever gets set, so 16:9 survived disabling widescreen.
- LocalCheatRow and OnlineEntryRow armed the row under the cursor on D-pad Right,
so scrolling a cheat list enabled everything you passed. Confirm only now.
Patches cannot be un-applied without a reboot: PatchCommand has no original-value
field and UnloadPatches never touches guest RAM, so disabling one mid-session only
stops it being re-written.
A skip cutscene cheat for God of War 2 keeps working with RetroAchievements
Hardcore active. It is not a user file. It ships in our own patches.zip:
gametitle=God of War 2 (SCUS-97481)
[Widescreen 16:9] gsaspectratio=16:9 patch=1,EE,00234A48,word,46000406
[Skip Cutscenes] author=Ezedequias patch=1,EE,202D8194,byte,01
Hardcore only ever gated the cheats side. ReloadEnabledLists empties the enabled
cheats list, the on-disk walk skips the cheats folder, and the cheat enable call
sits behind EnableCheats. The patches list gets none of that: it is re-read
verbatim and applied unconditionally, not even behind EnablePatches. Anything
filed as a patch has always been exempt, and place=1 reapplies it every vsync.
Neither of the obvious rules can separate those two groups. They live in the same
pnach, so file location cannot, and the widescreen one writes EE memory too, so
"block memory writes" would take widescreen with it. What does separate them is
whether the group says what it is for. gsaspectratio or gsinterlacemode means
widescreen or no-interlacing, which we deliberately keep working under Hardcore.
A group that declares nothing and only writes memory is a cheat whatever its
label says.
Measured against the shipped database before settling on it: 1284 groups declare
presentation and stay, 478 write memory with nothing declared and now stop. The
ones that stop read like Car select, Auto-activate analogs and Throttle/brake on
right stick. On the reported game, Widescreen 16:9 stays and Skip Cutscenes goes.
The check runs at group selection rather than against the enable list, because an
unlabelled group never consults that list and would have sailed through a filter
applied there.
GameDB patches are left alone on purpose. They are a curated compatibility layer,
and dropping them under Hardcore would break games instead of stopping cheating.
Worth knowing what this does not cover: a pnach author can still launder a cheat
by pasting a gsaspectratio line into the group. That stops shipped and accidental
content, not somebody determined to cheat themselves.
Patches under RetroAchievements hardcore: the gate dropped every on-disk pnach,
which is asymmetric with the fallback below it - the bundled patches.zip stays
enabled in hardcore, so a widescreen or bug-fix patch worked from the archive and
silently did nothing from disk, killing everything the in-app Patch Manager
writes. Gate cheats only; they remain blocked at enumeration and in
ReloadEnabledLists, and the two feed separate stores.
Overscan crop (issue #293): the core has always honoured GSConfig.Crop but
Android never exposed it. Four sliders in native PS2 pixels, so a value means the
same thing at any upscale multiplier.
Custom OSD colour: new GSOptions::OsdColor, with the ImGui overlay drawing from
it instead of a hardcoded white.
Fast-forward now uses Unlimited rather than Turbo. Turbo caps at
EmulationSpeed.TurboScalar (2.0x) and produced no visible speed-up on these
devices while "frame limit off" - the same Unlimited mode - demonstrably did.
Settings.applyTo() also forced the limiter back to 0/3 on every apply, cancelling
an active fast-forward while the UI still reported it on; it now preserves the
latch like the in-game overlay path already did.
Per-game settings when launching from a frontend: an external launch passed a
null GameInfo, so settingsKey was null and launchGame resolved global settings -
per-game settings, per-game memory cards and per-game orientation all ignored,
while the same title from our own library applied them. Build a GameInfo for the
incoming URI, probing the serial off the image the way the library scan does.
(cherry picked from commit 7c16cbfa13)
This allows users with monitors of any aspect ratios to use patches made for any other aspect ratio.
For example, if on 32:9 one uses a 21:9 patch, pcsx2 will automatically size the presentation to 21:9 within 32:9.
This also removes some ugly or hardcoded stuff from the code :).
It also opens the door to add a "Custom" user aspect ratio, without the patch needing to specify the aspect ratio, so users could stretch the image to any AR they'd like, but for now there's no need to add that.
(cherry picked from commit 3ae2520aa19efe32d8d0c12b2b174dcd3d3bc745)