-
Notifications
You must be signed in to change notification settings - Fork 7
NKDS OGMR
Store all regional variants, revisions, and language editions of each game together in a single dedicated NKDS set — maximising deduplication where it matters most.
These OGMR lists could be maintained alongside meta-cataloguing sites such as Redump, No-Intro, and Tosec — providing a community-maintained grouping layer on top of existing dat files.
Pre-built OGMR YAML files for 8 systems and the dat_grouper.py generation script are available in the OGMR folder of the public repo.
OGMR (One Game, Many ROMs) is a storage strategy for NKDS where each game gets its own .nkds set file containing all of its variants. A single game may exist as 13+ separate entries in a Redump dat — different regions, languages, discs, revisions, demos, and localised titles all get their own line. In an OGMR collection, all of these live together in one compact set.
This matters because regional variants of the same game share the vast majority of their data. The game engine, textures, models, audio, and system files are often identical — only region-specific text, voiceover, and metadata differ. By storing them together, NKDS deduplicates all that shared content, and the per-game set becomes extremely small relative to the total raw size.
- Maximum deduplication — Variants of the same game have the highest overlap (often 90%+)
-
Portable — Each
.nkdsfile is self-contained and can be copied, backed up, or shared independently - Mountable — Mount a directory of OGMR sets and NKDS merges them into a unified view
- Manageable — Add/remove games individually without touching the rest of your collection
- Embedded mode — With shard size 0, each game is a single file (index + data combined)
The nkds ogmr command batch-imports disc images into per-game sets by matching filenames against regex patterns defined in a YAML file:
- Input files are scanned (from folders, archives, or masks)
- Each filename is tested against the regex masks in order (first match wins)
- Matched files are routed to the corresponding game's set (created automatically if needed)
- The full NKit pipeline runs for each image: detect system, normalise, deduplicate, verify
- Unmatched files are reported separately so you can update the YAML and reprocess
nkds ogmr wii_ogmr.yaml --datastore D:\NKitData D:\WiiISOs --recursive --shard-size 0The YAML file maps game names to regex patterns. Each game entry has a name (used as the set filename) and a list of masks (regex patterns to match input filenames):
games:
- name: Example Game
masks:
- '^Example Game(?= \(|\.iso|$)'
- '^Foreign Title(?= \(|\.iso|$)'
- name: "Racing Game"
masks:
- '^Racing Game(?= \(|\.iso|$)'
- name: Shadow Platformer
masks:
- '^Shadow Platformer(?= \(|\.iso|$)'
- '^Foreign Shadow Title(?= \(|\.iso|$)'
- "^Alternate Name, A(?= \\(|\\.iso|$)"
- name: Party Game
masks:
- '^Party Game(?= \(|\.iso|$)'
- '^Party Pop(?= \(|\.iso|$)'
- '^Rainbow Party(?= \(|\.iso|$)'- Masks are .NET regex patterns — tested case-insensitively against input filenames (without directory path)
- First match wins — game entries are evaluated in YAML order; once a file matches, evaluation stops
-
Boundary lookahead — The
(?= \(|\.iso|$)at the end prevents^Example Gamefrom matchingExample Game 2. It ensures the base name is followed by((start of metadata),.iso(bare extension), or end of string. - Multiple masks per game — Covers foreign titles, regional name differences, and localised variants
- Tolerant of dat changes — Because masks match on the base title rather than exact filenames, they remain valid through most dat name changes and adjustments (region tag edits, revision bumps, language additions). Only a title rename would require a mask update — and the validation step would catch it for attention.
-
Set name from
namefield — Filesystem-unsafe characters (: ? * < > | " / \) are replaced with_
Creating these YAML files by hand for thousands of games would be impractical. A companion tool (dat_grouper.py) automates the process by parsing Redump datfiles and generating validated masks.
Redump XML Datfile → dat_grouper.py → OGMR YAML (per platform)
The script:
-
Parses the datfile — reads every
<game name>entry - Normalises titles — strips parenthesized metadata (region, language, disc, revision), inverts articles ("Title, The" → "The Title"), applies subtitle formatting
- Applies translations — looks up foreign-language game titles in external YAML files to map them to their English canonical name (e.g., a Japanese title → its English equivalent)
- Groups variants — all entries that normalise to the same title are grouped together
- Generates regex masks — creates anchored patterns with boundary lookaheads for each group
- Validates — runs every mask against every entry in the dat to confirm zero false positives, zero missed items, zero orphans, and zero double-claims (each dat entry matched exactly once by exactly one game group)
The validation is built into dat_grouper.py itself — re-run the script at any time to verify that your masks still correctly cover every dat entry after edits or dat updates.
Foreign-only titles that don't match any English game are flagged in a review report. An iterative process of human-verified translations builds up the mapping file over time:
translations:
'Foreign Horror Title': English Horror Title
'Foreign Adventure Title': 'English Adventure Title: Subtitle'
'Regional Party Name': Party Game
'Alt Regional Name': Party GameA companion AI-suggestion tool (review_fixer.py) accelerates this by proposing matches based on word overlap and franchise patterns — but every suggestion requires human verification. Sequels, spin-offs, and similarly-named but different games all need manual judgment.
The initial draft of these mask files was time-consuming to create, involving automated grouping followed by extensive manual testing and verification across thousands of entries. Going forward, the intention is that they would be fine-tuned and manually maintained where groupings are not 100% correct — adjusting masks when titles are renamed, new entries appear, or edge cases are discovered.
Pre-built OGMR YAML files are available for the following systems, generated from current Redump datfiles with validated translations:
| System | Dat Entries | Unique Games | Translations |
|---|---|---|---|
| GameCube | 2,019 | 779 | 421 |
| Wii | 3,779 | 1,774 | 1,069 |
| Wii U | 541 | 228 | 81 |
| PlayStation | 10,909 | 5,957 | 930 |
| PlayStation 2 | 11,767 | 6,310 | 639 |
| PlayStation 3 | 4,493 | 1,894 | 713 |
| Xbox | 2,678 | 1,295 | 230 |
| Xbox 360 | 3,686 | 1,800 | 315 |
Translations refers to translated game titles — foreign-language title variants mapped to their canonical English name (not language ports of the game itself).
All pass with zero orphans, zero false positives, zero missed items.
For example: 3,779 Wii dat entries collapse to 1,774 unique games — meaning each game has an average of ~2.1 regional/revision variants. Some popular titles have far more (10+ variants across regions, discs, revisions, and demos).
nkds ogmr nintendo_wii_ogmr.yaml --datastore D:\NKitData\Wii D:\WiiISOs --recursive
nkds ogmr nintendo_wii_ogmr.yaml --datastore D:\NKitData\Wii D:\WiiISOs --recursive --shard-size 0nkds ogmr nintendo_wiiu_ogmr.yaml --datastore D:\NKitData\WiiU D:\WiiU --recursive -keys WiiUKeys.zip --shard-size 0nkds ogmr nintendo_wii_ogmr.yaml --datastore D:\NKitData\Wii D:\WiiISOs --recursive -cfg nkit.yamlWhen you point --datastore at a directory of per-game .nkds files, NKDS merges them all into one unified view:
nkds mount --datastore D:\NKitData\Wii --mount W:\Your emulator sees a flat collection of ISOs grouped by system — it doesn't know or care that each game is stored in its own deduplicated set.
In an OGMR collection, Wii and WiiU images all contain update partitions that are identical (or near-identical) across every game. Without aux stores, each per-game set would store its own copy of the same update data.
An aux store is a companion set (e.g., wii.aux.nkds) in the same directory that holds the shared update partition blocks. When NKDS adds a game, update blocks are automatically routed to the aux store; game-specific blocks go to the per-game set.
This means:
- The ~30–50 MB update partition is stored exactly once across your entire OGMR collection
- Each per-game set contains only truly unique game data
- During reads/mounts, blocks are resolved transparently from both the game set and the aux store
Aux store routing happens automatically if the naming convention is followed — no extra flags needed.
After an ogmr import completes, any input files that didn't match any mask in the YAML are listed separately. This lets you:
- Identify gaps in your YAML (new releases, titles not in your datfile)
- Add new masks or translations
- Reprocess the unmatched files in a subsequent run
- NKDS — Full DataStore documentation
- NKDS Cheat Sheet — CLI examples including OGMR
- Processing Tasks — Dedupe task details