Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -541,8 +541,14 @@ Chrono Trigger (USA) [study-pc slot 3].state
```

Naming the machine keeps two of them from overwriting each other's slots.
RetroArch's automatic state is `[... auto]`, its `.bak` copies are skipped, and
savestate thumbnails go up with the state if you have them switched on.
RetroArch's automatic state is `[... auto]`, and its `.bak` copies are skipped.

A state goes up with the picture RetroArch takes as it writes it. RetroArch
takes one only when savestate thumbnails are on, and they are off by default,
so the built-in RetroArch launch asks for them in its generated config whenever
it is mirroring that launch's states. It asks only for that launch, and never
asks for them to be turned off. A custom mapping gets no generated config, so
there the picture goes up if you have thumbnails switched on yourself.

Only the slots a run actually wrote are sent, and anything over 128 MiB is
logged rather than sent: a state and the request framing it are both in memory
Expand Down
4 changes: 4 additions & 0 deletions src/main/launcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,10 @@ export class Launcher {
// config beats the redirect.
saveDir: savePaths?.saveDir,
stateDir: savePaths?.stateDir,
// On the same terms as the interval: the picture is only worth
// taking where there is a state mirror to carry it, and this is
// the same condition the reading below was taken under.
stateThumbnails: Boolean(savePaths) && syncsStates,
})
: null;
// The interval is the one thing the arguments below do not show: they
Expand Down
30 changes: 30 additions & 0 deletions src/main/saves/retroarch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,36 @@ test("a launch pins the directories its saves and states belong in", () => {
}
});

test("a launch mirroring its states asks for the pictures to mirror", () => {
// RetroArch writes the thumbnail beside a state only when the setting is on,
// and it is off by default, so a launch that says nothing leaves every state
// in RomM without its picture.
const written =
retroarchLaunchConfig({
autosaveSeconds: 0,
stateDir: "/data/4755/states",
stateThumbnails: true,
}) ?? "";

assert.match(written, /^savestate_thumbnail_enable = "true"$/m);
});

test("a launch not mirroring its states leaves the thumbnails alone", () => {
// Never written as "false": the shell has no use for the picture here, which
// is not a reason to take it away from a user who keeps thumbnails for
// RetroArch's own slot menu.
for (const stateThumbnails of [false, undefined]) {
const written =
retroarchLaunchConfig({
autosaveSeconds: 0,
stateDir: "/data/4755/states",
stateThumbnails,
}) ?? "";

assert.doesNotMatch(written, /savestate_thumbnail_enable/);
}
});

test("a directory a config cannot quote is left unsaid", () => {
// A retroarch.cfg value is a quoted string with no escape for a quote inside
// it, so the alternative to saying nothing is a config that does not parse.
Expand Down
13 changes: 13 additions & 0 deletions src/main/saves/retroarch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ export interface LaunchSettings {
* directories to the user's own settings. */
saveDir?: string;
stateDir?: string;
/** Whether to ask for the picture RetroArch files beside a state. False and
* undefined both ask for nothing, which leaves the user's setting alone. */
stateThumbnails?: boolean;
Comment thread
sdornan marked this conversation as resolved.
Outdated
}

/**
Expand Down Expand Up @@ -154,6 +157,16 @@ export function retroarchLaunchConfig(settings: LaunchSettings): string | null {
}
lines.push(...saveDirectoryLines(settings));

// The picture a mirrored state carries in RomM is the one RetroArch takes as
// it writes the state, and it takes none unless asked: savestate thumbnails
// are off by default, so a launch that says nothing sends every state up
// bare. Only ever turned on, never off. A launch not mirroring its states
// has no use for the picture, and a user who keeps thumbnails for
// RetroArch's own slot menu keeps them.
if (settings.stateThumbnails) {
lines.push('savestate_thumbnail_enable = "true"');
}

if (lines.length === 0) return null;
return [...GENERATED_HEADER, ...lines, ""].join("\n");
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/saves/states.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ import { safeFileName, safeFileNameComponent } from "../safety.ts";
*/
export const MAX_STATE_BYTES = 128 * 1024 * 1024;

/** The picture RetroArch writes beside a state when thumbnails are on. */
/** The picture RetroArch writes beside a state when thumbnails are on, which
* is what the generated config asks for in `retroarch.ts`: the setting is off
* by default, so without that a mirrored state never has one. */
export const THUMBNAIL_SUFFIX = ".png";

/** Whether a launch should mirror its states at all. */
Expand Down
Loading