Skip to content

fix(scanner): add missing TurboGrafx-16 / PC Engine classifier block (fixes #9)#10

Closed
terafin wants to merge 1 commit into
joeblack2k:mainfrom
intarweb:feat/add-tgfx16-pcengine-classifier
Closed

fix(scanner): add missing TurboGrafx-16 / PC Engine classifier block (fixes #9)#10
terafin wants to merge 1 commit into
joeblack2k:mainfrom
intarweb:feat/add-tgfx16-pcengine-classifier

Conversation

@terafin

@terafin terafin commented Jun 8, 2026

Copy link
Copy Markdown

Fixes #9.

Summary

classify_supported_save had no path-hint block for NEC's TurboGrafx-16 / PC Engine family — every TGFX16 save was being skipped at "outside allowed console families" before upload, regardless of source. Same shape as PR #6 (Sega RetroDECK dirs) — a previously-unrecognized family.

Fix

  • New if contains_any(...) block matching all common TGFX16/PCE path hints (RetroDECK pcengine/pcenginecd, MiSTer TGFX16, libretro mednafen-pce/beetle pce, standalone PC Engine/TurboGrafx, plus SuperGrafx and various dash/underscore variants).
  • New infer_nec_slug returning tgfx16 (single slug — MiSTer's TGFX16 core handles HuCard + CD).
  • is_plausible_save_for_system "tgfx16" entry: extensions sav/srm/ram/bkr/brm, sizes 2KB/4KB/8KB/16KB/32KB.

Applied identically to all 3 helpers (mister/steamdeck/windows).

Tests

classify_recognizes_pcengine_tgfx16_paths covers 7 path variants, each must classify as tgfx16:

  • pcengine (RetroDECK)
  • pcenginecd (RetroDECK CD variant)
  • tg16 (MiSTer convention)
  • tg-cd (older CD convention)
  • supergrafx
  • PC Engine (standalone English w/ space)
  • TurboGrafx (standalone English name)

Notes

  • Single slug tgfx16 covers both HuCard and CD on MiSTer's core; could split tgfx16-cd later if a downstream consumer needs the distinction.
  • The TGFX16-CD BRAM extensions (8KB, 32KB Memory Base 128) are covered by the size match.
  • Helper config's default SYSTEMS= list also doesn't include tgfx16 — separate gap, will file as a follow-up if you want it tackled here.

🤖 Generated with Claude Code

@terafin terafin force-pushed the feat/add-tgfx16-pcengine-classifier branch from c228722 to f903612 Compare June 8, 2026 05:36
classify_supported_save in scanner.rs has dedicated path-hint blocks
for Nintendo, Sega, NeoGeo and Sony families, but is MISSING any block
for NEC's TurboGrafx-16 / PC Engine family. Result: every TGFX16 save
from any source (RetroDECK / Mednafen / libretro Beetle PCE / standalone
emulators / MiSTer's own /media/fat/saves/TGFX16/ path on the SS1) is
silently skipped at classification with "outside allowed console
families" before the helper even attempts to upload.

This is the same family of gap as PR #6 (Sega RetroDECK single-word
dirs) — the classifier was never extended to recognize NEC paths at all.

Fix:
  - New if-block matching "pc engine" / "pcengine" / "pc-engine" /
    "pcenginecd" / "pc-engine-cd" / "turbografx" / "turbo grafx" /
    "tgfx16" / "/tg16/" / "/tg-cd/" / "supergrafx" / "/sgx/" / "/pce/" /
    "/pce-cd/" / "/pcecd/" / "nec - pc engine" / "nec - turbografx" /
    "mednafen-pce" / "beetle pce" — the substring set covers all
    common conventions across RetroDECK, MiSTer, libretro core names,
    and standalone emulator output.
  - New infer_nec_slug helper that returns "tgfx16" (single slug —
    MiSTer's TurboGrafx-16 core handles HuCard + CD under one core).
  - is_plausible_save_for_system gets a "tgfx16" extension entry
    (sav/srm/ram/bkr/brm) and a size match (HuCard 2KB SRAM, BRAM
    extensions up to 32KB).

Applied identically to all 3 helpers (mister/steamdeck/windows).

Tests (helpers/steamdeck/src/scanner.rs inline test module):
  - classify_recognizes_pcengine_tgfx16_paths covers 7 path variants:
    pcengine / pcenginecd / tg16 / tg-cd / supergrafx / "PC Engine" /
    "TurboGrafx" — each must classify as "tgfx16".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@terafin terafin force-pushed the feat/add-tgfx16-pcengine-classifier branch from f903612 to ab9eccd Compare June 8, 2026 06:19
terafin referenced this pull request in intarweb/SGM-Helper Jun 8, 2026
terafin referenced this pull request in intarweb/SGM-Helper Jun 8, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@terafin

terafin commented Jun 8, 2026

Copy link
Copy Markdown
Author

Consolidated into #11 (squashed with the other 3 scanner.rs format-gap fixes under the same libretro-vs-standalone lens). Closing in favor of #11 — same fixes, single commit, fewer threads for the maintainer to track.

@terafin terafin closed this Jun 8, 2026
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 11, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 11, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 12, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 12, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 12, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 12, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 12, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 12, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 12, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 13, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 13, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 14, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 14, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 14, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 14, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 14, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
intarweb-sync-bot Bot referenced this pull request in intarweb/SGM-Helper Jun 14, 2026
…C/MPK/CPK + TG-16)

Four related libretro-vs-standalone scanner gaps in one batch — all fix
real data-loss / silent-skip paths reported by SGM-Helper users on Steam
Deck (RetroDECK) and SS1 (libretro cores), all touch helpers/*/scanner.rs
(plus helpers/*/syncer.rs for the RTC dedup-key fix), all ship with
happy-path + regression-guard tests.

## Part 1 — PS1 memcard trailing-frame relax (was PR #4, fixes #3)

Real PS1 hardware writes "MC" magic at memcard frame 63 (the "write test
sector" — bytes 8064-8191). SwanStation (libretro Duckstation port) and
Beetle PSX leave frame 63 zero-filled OR write actual game-state
continuation bytes through it. Validator was rejecting every libretro
PS1 save with "outside allowed console families."

Drops the over-strict trailing-frame check. Frame 0 magic + frames 1-15
directory frame checksums are sufficient — these are real structural
validators a corrupt memcard would fail. Tests added: zero-filled
trailing-frame accepted, non-MC bytes accepted, frame 0 magic still
required, directory checksum still required, strict-format memcards
still accepted (regression guard).

## Part 2 — Sega RetroDECK path-hints (was PR #6, fixes #5)

RetroDECK's flatpak (net.retrodeck.retrodeck) writes saves under
single-word lowercase directory names. The Sega classifier had matched
some (megadrive, megacd, sega32x) but was missing several:
gamegear, mastersystem, megacdjp, sega32xjp, saturnjp, sega32xna,
megadrivejp.

Adds the missing variants. Test enumerates all 11 cases (5 fixes + 6
regression guards proving the previously-working paths still classify
correctly).

## Part 3 — Preserve .rtc / .mpk / .cpk through dedup (was PR #8, fixes #7)

Helper's save_selection_key collapsed Pokemon Crystal.rtc and
Pokemon Crystal.srm to the same key (stem-only), so the .rtc was
silently dropped — losing the in-game real-time clock state. Same
class of bug exists for N64 controller-pak data (.mpk / .cpk) which
sits alongside cart .srm.

Suffixes the dedup key with the extension when ext is rtc/mpk/cpk:
"crystal:rtc" vs "crystal:srm" no longer collide. Also adds
classifier size-check arm for gameboy .rtc (1..=64 bytes) so the
small clock-state payload doesn't get filtered as "implausible save."

Test: classify_accepts_tiny_rtc_files_for_gameboy with 8 / 13 / 32 /
48 / 64-byte .rtc payloads, regression guard that an 8-byte .srm is
still rejected as bogus (proves the relaxation is .rtc-scoped).

## Part 4 — TurboGrafx-16 / PC Engine classifier (was PR #10, fixes #9)

The classify_supported_save function had branches for every other
Sega/Nintendo/Sony system but no TG-16 / PCEngine / SuperGrafx block.
Saves from RetroArch's Beetle PCE Fast / Beetle SuperGrafx core were
returning None and getting skipped with "outside allowed console
families" — but they're well-formed BRAM/SRAM saves.

Adds contains_any block matching pcengine|tgfx16|turbografx|supergrafx,
an infer_nec_slug returning "tgfx16", and an is_plausible_save_for_system
arm for tgfx16 covering .sav 2KB / 8KB and .brm 2KB BRAM sizes. Test:
classify_recognizes_pcengine_tgfx16_paths enumerates RetroDECK,
RetroArch, and Beetle subdir variants.

## Scope

- All 4 fixes are additive: missing branches added, over-strict checks
  relaxed in a single direction. No previously-accepted save shape is
  now rejected.
- All test coverage is parallel across helpers/mister, helpers/steamdeck,
  helpers/windows — the triplet structure stays in sync.

Consolidates and supersedes PR #4 + PR #6 + PR #8 + PR #10. All four
share helpers/*/scanner.rs and the same libretro-vs-standalone lens.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TurboGrafx-16 / PC Engine classifier block missing entirely from scanner.rs

1 participant