Skip to content

Replace per-emulator boolean flags with a shared emulator registry - #100

Merged
misantronic merged 1 commit into
mainfrom
emulator-registry-refactor
Aug 11, 2026
Merged

Replace per-emulator boolean flags with a shared emulator registry#100
misantronic merged 1 commit into
mainfrom
emulator-registry-refactor

Conversation

@misantronic

Copy link
Copy Markdown
Owner

Replaces the 18 parallel *Installed / *Enabled booleans (and the fan-out they forced on every caller) with a single Emulator enum that carries everything per-emulator: display name, label, prefs keys, package candidates, and how it gets patched.

Net +902 / −2244; MainViewModel drops from 3029 to ~2300 lines. Adding an emulator is now one enum entry plus its four string resources.

Structure

Emulator describes each emulator, with two mutually exclusive patch mechanisms:

  • ConfigOverride — RetroArch, Dolphin, PPSSPP. Patched by rewriting their config files (SAF, or the Shizuku user service). Holds the hardcore/patched prefs keys, SAF-uri loader, hardcore detector, patch/revert functions, and the Shizuku wire key.
  • BroadcastOverride — ARMSX1, ARMSX2, Flycast, WatermelonDS, Mupen64Plus, EmuCoreX. Repointed with a host-override broadcast. Holds the receiver class and string resources.

Emulator.SHIZUKU_MANAGED / Emulator.BROADCAST_MANAGED derive from which override is present, so the two sets can't drift out of sync.

EmulatorSupport becomes a collection (List<EmulatorState>) with isInstalled() / isEnabled() / installedCount / hasAnyEnabled, and is what MainUiState now holds instead of the 18 flags.

Deduplication

  • The six broadcast patchers (Armsx1CfgPatcher, Armsx2CfgPatcher, FlycastCfgPatcher, Mupen64CfgPatcher, WatermelonDsCfgPatcher, EmuCoreXCfgPatcher) were identical apart from names, receiver class and string resources. Deleted in favour of one registry-driven BroadcastCfgPatcher.
  • PatchResult / DolphinPatchResult / PpssppPatchResult were structurally identical — unified into ConfigPatchResult in the new ConfigCfgPatcher.
  • The nine setXEnabled methods collapse to setEmulatorEnabled(emulator, enabled).
  • The patch/revert chains in startProxy / stopProxy / recoverPatchedCfgIfProxyStopped / BootReceiver / ProxyService become loops over the registry.
  • HomeFragment inflates its toggle rows from Emulator.entries, so dialog_emulator_selector.xml is an empty container instead of nine hardcoded <include>s.

Bug fixes

Four issues surfaced while making the fan-out uniform:

  1. Shizuku revert never restored hardcore mode. The user service hardcoded restoreHardcore = false and never reported the pre-patch state, so hardcore stayed off after stopping the proxy — unlike the SAF path, which persists and restores it. The service now detects hardcore before patching, returns it, and the app persists it in the existing *_HARDCORE_WAS_ENABLED prefs and passes it back on revert.
  2. BootReceiver and ProxyService only handled ARMSX2 among the six broadcast emulators, so Flycast/Mupen64Plus/EmuCoreX/ARMSX1/WatermelonDS stayed pointed at a dead proxy after a reboot-autostart or a service kill. Both now loop over all of them.
  3. A disabled RetroArch was marked as patched on boot. patchRetroArchAndPersist lacked the !skippedNotInstalled guard its Dolphin/PPSSPP counterparts had, so retroarch_patched_this_run was set to true even with RetroArch disabled.
  4. PPSSPP Gold was patched while running. The Shizuku service resolves the ini across both PPSSPP package candidates but force-stopped only org.ppsspp.ppsspp, so Gold could overwrite the patched ini on exit. Force-stop is now driven by packageCandidates.

Verification

Debug + release compile, testDebugUnitTest green, including four new cases covering the hardcore round trip (restoreHardcore = true had no coverage at all before) and the uniqueness of the Shizuku wire keys.

On-device:

  • Retroid Pocket Nova — registry resolution, enabled-emulator icon cluster, emulator selector dialog, and the enable/disable toggles writing the correct per-emulator prefs keys.
  • Android 14 AVD — full Shizuku patch/revert round trip for RetroArch + Dolphin + PPSSPP, including PPSSPP's custom memstick root (root-mode prompt → SAF grant → candidate-path fallback), and the hardcore fix in both directions (on → restored on; off → stays off).

Not yet exercised at runtime: the non-Shizuku SAF patch/revert path, BootReceiver on a real reboot, a broadcast emulator confirming receipt of the override, and the PPSSPP Gold force-stop.

@misantronic misantronic self-assigned this Aug 11, 2026
@misantronic misantronic added Android enhancement New feature or request labels Aug 11, 2026
@misantronic
misantronic merged commit bb1027a into main Aug 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Android enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant