Fetch a ROM's whole folder when it holds more than one file - #140
Merged
gantoine merged 5 commits intoSep 24, 2026
Merged
Conversation
Contributor
|
… load Uninstall only deletes a directory no other game also claims, so a flat platform folder that ends up inside a repointed destination is no longer wiped. A missing mapping or ROM list now falls back safely instead of throwing. Pre-upgrade multi-file sidecars regain DownloadAsArchive at deserialisation rather than at one reader, and the revision-to-install-info copy lives in one place. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- Add RomMInstallPaths.IsSingleRomInFolder; UsesFlatLayout takes it instead of re-deriving it, and BuildRoms reads the same value - Drop the leftover downloadsArchive alias in the install controller - Check PlayableFile with IsContained before combining it - Share one StartsWithDirectory between IsInside and IsClaimedByAnother, normalising each path once; skip games with no install directory Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
gantoine
approved these changes
Sep 24, 2026
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.
Addresses the first half of #127 — pulling DLC and update files alongside the game.
The problem
RomM reports a ROM whose folder holds the game at the root with extras in subfolders (
dlc/,patch/— the "Structure A" layout it documents) ashas_nested_single_file, nothas_multiple_files: the game is the only file at the folder's root.RomMRevisionFactory.Build()branched on
has_multiple_filesalone, so it took the single-file path and asked for the base gameby itself. The
fileslist was never read as a set, so the DLC and the update were never requestedat all.
The folder-level endpoint already used for multi-file ROMs returns everything, with
patch/preserved at the archive root — the layout the install path expects. Full analysis and server
responses in #127.
The change
Two meanings were riding on one flag:
HasMultipleFiles— what RomM says. Unchanged. Decides whether every extracted file is aplayable ROM, i.e. the discs of a multi-disc game.
DownloadAsArchive— new. Decides whether the folder is fetched whole:HasMultipleFiles || (HasNestedSingleFile && Files.Count > 1).PlayableFile— new. The file to launch, relative to the ROM's folder.has_simple_single_fileis excluded on purpose: therefs_namenames the file itself, so there isno folder to ask for.
BuildRoms()registers every extracted file matching the emulator profile's extensions, which iswhat exposes the discs of a genuine multi-file ROM. It is narrowed only when
DownloadAsArchive && !HasMultipleFiles, where the file to launch is named outright sopatch/anddlc/contents arenot offered as alternative ROMs. If that file is missing after extraction the scan still runs, with
a warning, rather than leaving the game with no ROM at all.
ROM.HasMultipleFilesis left alone deliberately:RomMImportuses it to rebuild the legacyprotobuf GameIds that migrate pre-0.6 libraries.
Install flat
A ROM fetched as a folder carries its own subfolders, so it cannot go flat: they would land in the
platform folder, where every game's
patch/would merge into one, and a flat uninstall — whichremoves only the registered ROM files — would leave them behind. These ROMs keep their own folder
even under flat; single files still install flat. The importer and the install controller share one
helper, so the two paths cannot drift apart and break IsInstalled detection.
Uninstall now asks whether the install directory sits inside the mapping's destination, instead of
reading the setting. That keeps games already installed flat working, and fixes a pre-existing bug
where toggling the setting after installing sent uninstall down the wrong branch. "Inside" rather
than "different from" is deliberate: once a mapping is repointed, the recorded path is the previous
platform folder, and deleting it would take every ROM still in it. Uninstall also resolves
{PlayniteDir}now, so a portable install no longer skips what it was asked to delete.Not covered
nothing sits at the folder's root. That is not a layout the docs describe:
dlcandupdatearerecognised subfolder names, a
Gameone is not, and the base game belongs at the root of itsfolder. RomM classifies it accordingly —
top_level_file_countcounts only files sitting directlyin the ROM folder, so it is 0 and all three shape flags come out false — and the importer's
existing fail-safe is what turns it into a multi-file ROM, where update and DLC still appear as
launchable ROMs. Moving the base game up one level makes it the case this PR covers.
files that are not registered as ROMs. Pre-existing.
Testing
The unit suite is green, with new cases for the criterion, the file-endpoint paths it must not
disturb, and the flat-layout decision — including a repointed mapping, which must not have its old
folder deleted.
Verified in Playnite 10.35 against RomM server 5.2.0:
single-file ones were left as they were.
patch/—263,200,904 bytes, matching the server's
fs_size_bytes, where 0.9.0 fetched the base file alone.Playnite registered one ROM, the base game; the update and the server-generated
.m3uappearnowhere in the library.
patch/across the platform folder, and uninstalling removed that folder whole.