fix(validators): libretro/RetroDECK format compat (GBA signature + GB rtc)#11
Open
terafin wants to merge 1 commit into
Open
fix(validators): libretro/RetroDECK format compat (GBA signature + GB rtc)#11terafin wants to merge 1 commit into
terafin wants to merge 1 commit into
Conversation
… rtc) Two related libretro-vs-standalone validator gaps in one batch — both fix real data-loss paths reported by SGM-Helper users on Steam Deck (RetroDECK) and SS1 (libretro cores), both stay strict for anonymous uploads, both ship with happy-path + regression-guard tests. ## Part 1 — GBA library-signature advisory under helper trust (was PR joeblack2k#8, fixes joeblack2k#7) Standalone mGBA / VBA-M write a library version footer (`EEPROM_V`, `SRAM_V`, `FLASH_V`, `FLASH1M_V`, `FLASH512_V`) into the .srm. RetroArch's libretro-mGBA core does NOT — confirmed across both EA Sports games (007 - Everything or Nothing, header `3500DNOB`) and canonical mGBA-targeted titles (Pokemon Emerald, sparse FRAM data). RSM's `hasGBASignature()` rejects every libretro GBA save → HTTP 422. Adds `SignatureAdvisoryWithHelperTrust bool` to `strictRawSaveValidationProfile`. When true, a failing `RequireSignature` check is downgraded from reject → warning IFF (a) `HelperTrusted` AND (b) `rom_sha1` present AND (c) payload non-blank. Anonymous uploads or uploads without `rom_sha1` still hard-reject. GBA's profile opts in. NES / SNES / Master System / Genesis are unchanged because their `RequireSignature` is nil (no signature required at all). ## Part 2 — Game Boy .rtc sidecar size validation (was PR joeblack2k#9) RetroArch / libretro Game Boy cores write a small `.rtc` sidecar next to the canonical `.srm` for cartridges with real-time clock state (Pokemon Crystal, Pokemon Gold/Silver, Harvest Moon GBC). Observed sizes 8–48 bytes. The strict gameboy raw-save profile's `AllowedSizes` only listed canonical SRAM sizes (512..65536), so every `.rtc` upload rejected with "game boy raw save size N is not recognized" → silent data loss for clock state. Adds optional `AllowedSizesByExt map[string]func(int) bool` to `strictRawSaveValidationProfile`. When the incoming extension matches a registered predicate, that predicate replaces the canonical size-set check for that extension only. Other extensions fall through to `AllowedSizes` unchanged. Gameboy opts in for `.rtc` with `1..=64` bytes. `.sav` / `.srm` / `.ram` / `.gme` still validate against `strictRawGBSizes` exactly as before — scoped relaxation, not a blanket loosening. ## Tests - `TestNormalizeSaveInputAcceptsLibretroGBASaveUnderHelperTrust` — accepts libretro GBA save without library footer when HelperTrusted + rom_sha1 - `TestNormalizeSaveInputRejectsLibretroGBASaveWithoutHelperTrust` — regression guard: anonymous upload still rejected - `TestNormalizeSaveInputRejectsLibretroGBASaveWithoutROMSHA1` — same - `TestNormalizeSaveInputRejectsBlankLibretroGBASave` — blank payload still rejected even under helper trust - `TestNormalizeSaveInputAcceptsTinyGameBoyRTCFile` — accepts 8/13/32/48/64 byte gameboy `.rtc` payloads - `TestNormalizeSaveInputRejectsTinyGameBoySRMFile` — regression guard: 8-byte `.srm` still rejected, proves relaxation is `.rtc`-scoped - `TestNormalizeSaveInputRejectsOversizedGameBoyRTCFile` — 65-byte `.rtc` rejected with new per-ext message ## Scope - Only GBA opts into `SignatureAdvisoryWithHelperTrust`; only gameboy opts into `AllowedSizesByExt`. Every other system's behavior is byte-identical to before. - Pre-existing trust / blank / executable-payload / text-noise checks still run — only the size predicate and signature requirement get the per-extension / per-trust-context overrides. Consolidates and supersedes PR joeblack2k#8 (GBA advisory) + PR joeblack2k#9 (gameboy .rtc). Both are scanner.rs/validator-relaxation fixes from the same lens (libretro-vs-standalone format gaps). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Jun 8, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related libretro-vs-standalone validator gaps in one batch — both fix real data-loss paths reported by SGM-Helper users on Steam Deck (RetroDECK) and SS1 (libretro cores). Both stay strict for anonymous uploads, both ship with happy-path + regression-guard tests.
Consolidates and supersedes PR #8 + PR #9 — same files (
nintendo_validation.go,raw_save_validation.go), same lens (libretro-vs-standalone format gaps), squashed to one commit.Part 1 — GBA library-signature advisory under helper trust (was #8, fixes #7)
Standalone mGBA / VBA-M write a library version footer (
EEPROM_V,SRAM_V,FLASH_V,FLASH1M_V,FLASH512_V) into the .srm. RetroArch's libretro-mGBA core does NOT — confirmed across both EA Sports games (007 - Everything or Nothing, header3500DNOB) and canonical mGBA-targeted titles (Pokemon Emerald, sparse FRAM data). RSM'shasGBASignature()rejects every libretro GBA save → HTTP 422.Adds
SignatureAdvisoryWithHelperTrust booltostrictRawSaveValidationProfile. When true, a failingRequireSignaturecheck is downgraded from reject → warning IFFHelperTrustedANDrom_sha1present AND payload non-blank. Anonymous uploads or uploads withoutrom_sha1still hard-reject. GBA's profile opts in.Part 2 — Game Boy .rtc sidecar size validation (was #9)
RetroArch / libretro Game Boy cores write a small
.rtcsidecar next to the canonical.srmfor cartridges with real-time clock state (Pokemon Crystal, Pokemon Gold/Silver, Harvest Moon GBC). Observed sizes 8–48 bytes. The strict gameboy raw-save profile'sAllowedSizesonly listed canonical SRAM sizes (512..65536), so every.rtcupload rejected with HTTP 422 → silent data loss for clock state.Adds optional `AllowedSizesByExt map[string]func(int) bool` to `strictRawSaveValidationProfile`. When the incoming extension matches a registered predicate, that predicate replaces the canonical size-set check for that extension only. Gameboy opts in for `.rtc` with `1..=64` bytes.
`.sav` / `.srm` / `.ram` / `.gme` still validate against `strictRawGBSizes` exactly as before — scoped relaxation, not a blanket loosening.
Tests (7 new)
Scope
🤖 Generated with Claude Code