Skip to content

feat(scan): embed Switch title IDs into file names during scan - #3883

Closed
lucid-void wants to merge 1 commit into
rommapp:masterfrom
lucid-void:feat/switch-title-id-autorename
Closed

feat(scan): embed Switch title IDs into file names during scan#3883
lucid-void wants to merge 1 commit into
rommapp:masterfrom
lucid-void:feat/switch-title-id-autorename

Conversation

@lucid-void

Copy link
Copy Markdown

Description
Adds an opt-in capability that automatically embeds Nintendo Switch title IDs into ROM file names during a scan, so external tools that parse the title ID out of the file name (e.g. CyberFoil) can index them:

Super Mario Odyssey.nsp → Super Mario Odyssey [0100000000010000][v0].nsp

RomM already caches the blawar TitleDB and pulls a title ID out of file names for metadata matching. This adds the reverse direction (name → title ID) and uses it to rename files that don't yet have one.

How it works

  • New env flag ENABLE_SWITCH_TITLE_ID_RENAME (default false). Backend-behavioral only, no UI/schema change.
  • The Switch TitleDB update task now also builds a reverse index (romm:switch_name_to_id) mapping a normalized base-game name to its title ID. It only keeps names that resolve to a single base title, so ambiguous names are never renamed to the wrong game. Updates (0x800) and DLC (0x1000) are excluded.
  • During a scan, _maybe_add_switch_title_id renames matching files on disk (reusing the existing rename_fs_rom) and, for an already-tracked entry, moves its DB record and RomFiles onto the new name (mirroring the manual rename endpoint).

Conservative by design — it skips files that already carry a title ID, non-served extensions, nested/multi-file folders, and any name that is unknown or ambiguous. Requires no Nintendo keys.

Scope / follow-ups

  • v1 covers flat, single-file base games (.nsp .xci .nsz .xcz .nro).
  • Nested folders and update/DLC files (per-file base±offset ID math + version tags) are left as a deliberate follow-up.
  • Composes cleanly with the separate Switch base/update/DLC categorization work: this produces IDs in file names, that consumes them.
  • The reverse index populates on the next TitleDB update run; existing caches degrade gracefully (no index → no renames).

AI assistance disclosure

This PR was written with substantial AI assistance (Claude Code / Claude Opus 4.8): design, implementation, and tests were AI-generated and human-reviewed.

Checklist

  • I've tested the changes locally
  • I've updated relevant comments
  • I've assigned reviewers for this PR
  • I've added unit tests that cover the changes

Add an opt-in capability (ENABLE_SWITCH_TITLE_ID_RENAME) that renames flat
Switch/Switch 2 ROMs lacking a title ID by resolving it from the game name
against the cached TitleDB, e.g. `Super Mario Odyssey.nsp` ->
`Super Mario Odyssey [0100000000010000][v0].nsp`, so tools that parse title
IDs out of the file name (e.g. CyberFoil) can index them.

The Switch TitleDB update task now also builds a reverse index
(romm:switch_name_to_id) mapping a normalized base-game name to its title ID,
keeping only names that resolve to a single base title so ambiguous names are
never auto-renamed to the wrong game. The scan hook is conservative: it skips
files that already carry an ID, non-served extensions, nested folders, and
unresolved/ambiguous names, and moves an already-tracked DB entry and its
files onto the new name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds optional Switch title ID embedding during scans. The main changes are:

  • A name-to-title-ID index built from base-game TitleDB entries.
  • Scan-time filesystem and database renaming for matching flat Switch ROMs.
  • A disabled-by-default environment flag and focused unit tests.

Confidence Score: 4/5

The reverse-index refresh can preserve invalid mappings and needs a fix before merging.

  • Removed mappings are never deleted from Redis.
  • Names that become ambiguous can retain their old unique mapping.
  • Those stale values can drive persistent filesystem renames.

backend/tasks/scheduled/update_switch_titledb.py

Important Files Changed

Filename Overview
backend/endpoints/sockets/scan.py Adds guarded scan-time file renaming and updates existing ROM database records.
backend/tasks/scheduled/update_switch_titledb.py Builds the reverse title index but leaves obsolete Redis fields after refreshes.
backend/handler/metadata/base_handler.py Adds normalized name lookup against the new Redis index.
backend/config/init.py Adds the disabled-by-default rename flag.
env.template Documents the new rename setting.

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
backend/tasks/scheduled/update_switch_titledb.py:114-115
**Stale Name Mappings Survive Refreshes**

This only upserts the current mappings, so a name removed from TitleDB or newly marked ambiguous remains in the Redis hash. A later scan can use that obsolete mapping and permanently rename a ROM with a title ID that the current data no longer considers valid or unique.

Reviews (1): Last reviewed commit: "feat(scan): embed Switch title IDs into ..." | Re-trigger Greptile

Comment on lines +114 to +115
for name_batch in batched(name_to_id.items(), 2000, strict=False):
await pipe.hset(SWITCH_NAME_TO_ID_KEY, mapping=dict(name_batch))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Stale Name Mappings Survive Refreshes

This only upserts the current mappings, so a name removed from TitleDB or newly marked ambiguous remains in the Redis hash. A later scan can use that obsolete mapping and permanently rename a ROM with a title ID that the current data no longer considers valid or unique.

Prompt To Fix With AI
This is a comment left during a code review.
Path: backend/tasks/scheduled/update_switch_titledb.py
Line: 114-115

Comment:
**Stale Name Mappings Survive Refreshes**

This only upserts the current mappings, so a name removed from TitleDB or newly marked ambiguous remains in the Redis hash. A later scan can use that obsolete mapping and permanently rename a ROM with a title ID that the current data no longer considers valid or unique.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

@gantoine gantoine added the on-hold Pending further research or blocked by another issue label Jul 22, 2026
@tmgast

tmgast commented Jul 24, 2026

Copy link
Copy Markdown
Member

Thanks for the PRs, this one and #3876. This overlaps with something I already had in progress: a native library (sigil) that reads the title ID and serial straight out of the ROM binary during a scan. We talked it over internally and decided to handle it there, since reading the Switch content metadata gets the real per-file ids and versions (base, update, and DLC) without depending on the filename, and it extends to serials and title ids on most other platforms too.

The filename embedding your PR is going for did make it in, as an opt-in config flag that renames Switch files to embed the id and version for external tools that read it out of the name. That said, I'd rather clients and users pull this from the API than transform or rename files on disk, so the rename is off by default.

It's all in #3925.

@gantoine gantoine closed this Jul 24, 2026
@lucid-void
lucid-void deleted the feat/switch-title-id-autorename branch July 30, 2026 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

on-hold Pending further research or blocked by another issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants