Merging preserves authorship in git history, but nobody reads git log to find
out who wrote a file. The tree already had the convention -- "Feature
contributed by misantronic (PR #391)" on exportRecentGamesPublic -- it just was
not applied to the three PRs merged here.
MemoryCardBackup.kt bmdhacks (PR #608)
PerGameOverrides.{h,cpp} bmdhacks (PR #593)
RecentGamesContentProvider.kt misantronic (PR #566)
The provider's line also records that the opt-in gate was added on merge, so the
gate is not mistaken for part of the contribution.
The tables are meant to be complete and the drift tests are what say so, but
ForCoreKnob returns no section for an enumerator nobody mapped, and both callers
walked straight into strcmp with it.
Change a setting in the per-game settings screen and it does not take. The widget
keeps the new value, the file on disk keeps it, and the emulator runs with
something else — for every game the database has an entry for, which is most of
the ones anyone plays.
The layered read is not the problem; it already puts the per-game file above the
global one. The inversion is that the database writes into EmuConfig afterwards,
from ApplyGameFixes, with no idea where any value came from. So the real order is
global < per-game < database, and the only ways out are two switches that are all
or nothing: EnableGameFixes for the CPU side, Manual Hardware Fixes for graphics.
Either one rescues the setting you wanted by throwing away every other fix the
game had, which usually just trades one glitch for a different one.
So tell the database which settings are not its to write. A key sitting in a
per-game file is a deliberate act: every settings screen represents "use the
global setting" by deleting the key, not by writing the global value. That makes
presence the record we need, with nothing new to store and no frontend to change,
and it works for files already on disk rather than only for edits made from here
on.
PerGameOverrides reads one per-game file — the game layer alone, since the layered
stack cannot tell a per-game choice from a global one and only the per-game one
wins — and reports what it claims. Both apply functions take it and leave those
settings alone, down the road they already had for the global switches, so each
one still gets named in the log and now also on screen.
This generalises the pin that already existed for graphics hacks and had no writer
outside iOS. That mask stays, because MaskUserHacks and any INI already carrying
one speak it, and the derived bits merge into it. But the claim itself is keyed by
hardware-fix id rather than by that mask: there are more fixes than its 32 bits can
name, its width is a persisted format, and the settings players actually change —
mipmapping, trilinear, deinterlacing, texture preloading, blend level, download
mode — were never user hacks and so had no bit at all. That is also why the pin
test moves out from under isUserHackHWFix: nested there, none of them could be
claimed.
The database keeps the last word where it should. The three renderer routine
selectors have no setting and no UI, so nothing can claim them. The BIOS path is
untouched — it forces instant DMA on for a hardware reason and strips hacks
deliberately, and its own comment already says claims get no say there.
The iOS bridge derived the same thing from its own copy of the key table; it now
calls the shared one, so the two cannot drift. Android's live GS apply re-derives
the claims after its reload, or masking would strip a hack the player set.
Drive-by: the division rounding mode logged eeRoundMode's value under its own name,
in both the applied and the skipped message.