Neither the core nor the app read .m3u. The app now does (app/src/m3u.h, RetroArch's
format: one image per line, relative to the playlist or absolute; '#' lines, a BOM,
CRLF and a "|label" suffix are ignored).
- CoreHost::loadContent: an .m3u boots its first disc and appends every disc to the
core's disc list (owner thread, inside the load). Each entry must exist and be a
cue/cdi/chd/iso, or the load fails with the entry named: a missing disc would still
register and only fail when picked.
- Identity, on #1011's model: the playlist is what was opened (loadedPath/loadedName:
one .srm per set, Restart, recents, the library's recently played, per-game
controls); the disc in the tray is the content (contentPath/contentName: the window
title, save-state slots, achievements, cheats) -- the first disc at boot, then
whatever a swap boots. finishLoad takes the opened path for this.
- File > Open filter takes .m3u; the headless load check, tv_script's load and the
library's "load this state" compare against loadedPath.
- Library: isDiscExt includes m3u; the playlist claims the discs it lists (they leave
the grid) and is identified by its first disc's track-1 CRC.
- Headless --expect-discs N: the disc list the menus read holds N images; at boot the
content is disc 1 and the .srm / recents are the playlist's; after Open tray, File >
Disc > last, Close tray the content and state slot are the last disc's while the
.srm stays the playlist's. smoke_m3u_playlist (inline) and
smoke_m3u_playlist_threaded (--emu-thread on, emu_thread label) load
tests/fixtures/synth_jagcd_set.m3u (../-relative entries to
test/roms/synth_jagcd{,_multi}.chd).
- library_unit: parser cases and the scan dedupe / hash.
Co-authored-by: Claude Opus 5.5 <[email protected]>
* docs(app): flesh out TV mode phase 2 plan against the merged phase 1 code (#991)
Screen stack beside the in-game menu, TV-owned GameRef/Art/StateRef host types,
geometry from mockups A and B, test bodies for Home/Library/Details, Auto acting
as Manual until phase 4, and the spec changes phase 2 needs approved.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(app): TV mode state machine and input ownership (#991)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(app): TV mode fullscreen hold is state, leaving fullscreen turns TV off (#991)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(app): TV shell, Manual TV mode, --tv and the View menu entry (#991)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(app): TV shell leaves bind capture and text fields their input; clickable section tabs (#991)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(app): TV Home screen with shelves and hero panel (#991)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(app): TV Library screen with rail, cover grid and letter jump (#991)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(app): TV pad trigger glyphs, held Backspace stops at an empty filter (#991)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(app): TV Game details and the TV-mode toggle in the in-game menu (#991)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* feat(app): TV script verbs for windowed screenshots (wait library, shot, quit) (#991)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(app): TV hint bar band and device-true hints; Home hides a shelf that cannot fit (#991)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
* fix(app): TV mode final-review fixes: fresh launches, focus follows the game, input ownership (#991)
- A launch from a TV screen starts the game fresh: the resume prompt needs a mouse
(X and Game details already offer the auto-save).
- ui.tv_mode is read, never written, until the setting has its UI (phase 4), so
the Auto default can still reach users.
- Focus on Home shelves and Library lists follows the game's key, so coming back
from a game lands on it after Recent reorders.
- A focused desktop text field keeps the keyboard (no forced WantCaptureKeyboard);
OS key-repeat of nav keys is dropped (NavInput repeats directions itself);
an open desktop window takes the pad away from the TV screens under it.
- Empty Library grid shows only the hints that work; Home says "Scanning your
library..." during the first scan; Ctrl/Cmd+L and File > Game library open the
desktop library window while TV mode is on.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---------
Co-authored-by: Claude Opus 5.5 <[email protected]>
A 404 from the site mirror wrote a .miss marker that held for 7 days, so a
disc looked up before the mirror served its art (or during a deploy gap)
stayed blank for a week after the site had the picture. Mirror misses now
live in memory until the app quits, and marker files an older version
wrote for the mirror are removed and ignored. libretro-thumbnails keeps
its 30-day markers.
Co-authored-by: Claude Opus 5.5 <[email protected]>
The Jaguar CD tab always said libretro-thumbnails has no Jaguar CD art,
even though discs get box art from the project mirror
(jaguar.provenance-emu.com/thumbnails/), so a fresh library showed real
covers right under a line claiming there were none.
LibraryService::missingArt(section) counts the tab's entries whose art
lookup came up empty (a transient failure waiting to retry counts too, so
the hint does not blink). The hint now shows only while that count is
non-zero, gives the count, and mentions the mirror when it is enabled
and downloads are on.
Co-authored-by: Claude Opus 5.5 <[email protected]>
Off / Ask / Always (default Ask). Closing a game, switching games or quitting
writes an Auto-save beside the numbered slots (one per game, latest only,
atomic); the next boot loads it or asks. Skipped in hardcore, during netplay,
for runs under 5 emulated seconds and for games the crash watchdog flagged.
Copies 2+ keep their own auto-saves in states/instance-N/. Shown and
deletable in the Save states tab and the tile menu.
Refs #833
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
deleteState reports a missing state as a failure; the strip tiles get the
grid's title height so a two-line title is not clipped.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Star a game on its tile (or right-click > Add to Favorites); the games that boot
are kept under Recently played (last 20). Each list shows as its own tab, as a
strip at the top of the Cartridges and Jaguar CD tabs, both, or hidden. A new
Save states tab lists every game with states and the screenshot saved with each;
clicking one boots the game and loads it (or just loads it into the same game
already running). The tile context menu gains Play, Load state, favorites,
Remove from Recently Played, Show in Finder / Explorer and Copy path.
Favorites and recents live in library/user.tsv, written as atomic operations
(re-read, apply one change, rename) so several running copies cannot clobber
each other. App state file names now come from one helper shared with the tab.
Refs #838
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
libretro-thumbnails has no Jaguar CD repository (libretro-thumbnails#141). For a
disc, after libretro-thumbnails has no art for a type, ask the project site mirror
(jaguar.provenance-emu.com/thumbnails/Atari - Jaguar CD/...). Upstream is always
first, so its art wins once it exists. Each source has its own cache folder and miss
markers: mirror art is cached under thumbnails/Atari - Jaguar CD/ and never shadows
an upstream copy fetched later; the mirror's misses expire after 7 days (upstream's
stay at 30). A transient upstream failure does not fall through to the mirror, and
carts never use it. Config key library.art_mirror (empty = off); downloads-off still
disables everything.
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The library skipped .chd and .cdi ("nothing cheap to hash") and name-matched
only on an exact file stem, so most disc rips showed no title.
- .chd: CRC32 of track 1 rebuilt the way the core reads it (2352 of each
2448-byte frame, audio put back in .bin byte order, virtual pregap left
out, tracks padded to 4 frames); CHDs the core refuses (several audio
tracks, no CHSE) are not hashed.
- .cdi: best-effort track 1 CRC from the descriptor layout.
- A disc whose checksum is not in the dat falls back to a normalized name
match of the file name, then the folder name (case, punctuation, region and
Track/Disc tags ignored; exact title first, then a unique longer title,
never a guess between two games).
- Tiles say how a disc was identified in the tooltip.
- Scan cache v2: old caches re-hash only disc images that had no checksum.
Verified against synthetic uncompressed CHD/CDI images; real Redump CHDs are
still to be checked.
Refs #838
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
libretro-thumbnails has no Atari - Jaguar CD repository, so no disc could ever
get art. Tiles with no art now draw a card with the game title and a CD / Cart
badge, and cover art can be supplied locally:
- right-click a tile > Set cover image... (PNG) / Remove cover image
- drop a PNG on a tile while the library is showing
- <data>/covers/<Title>.png (dat name, then the shown name), picked up on Rescan
- precedence: tile cover > covers folder > downloaded > card
Unidentified discs get a cleaned title (trailing "(Track N)" and doubled
extensions dropped; "(Disc N)" kept) and now have art slots keyed by dat name,
checksum or path; only identified titles ever reach the network. The Jaguar CD
tab says why discs have no art.
Refs #838
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
All of them drive the same value as the toolbar slider (library.size), through
one clamp/step (0.5x..2.5x, default 1.0x, multiplicative so trackpad deltas stay
smooth). They apply only while the library is showing and the pointer is over its
grid (pinch) or the library has focus (keys), never while a text field is being
edited. The size is written to the config once the zoom settles, and on exit.
Refs #833 Refs #838
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
The library already classified BIOS files found under user folders, but two
things kept them from being useful: a name match was case-sensitive (JAGCD.BIN
fell through to Cartridges as a playable game), and the core only reads BIOS
files from its system folder under fixed names, so a BIOS found elsewhere was
only ever labelled 'Not read here'. Names now match ignoring case, and a BIOS
tile the core would read from the system folder offers Copy, which writes it
there under the name the core searches for (never over an existing file).
Refs #833 Refs #838
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
SDL_GetWindowDisplayScale is relative to pixels and includes the pixel density, while ImGui's
SDL3 backend lays out in points: on a Retina Mac every window was twice the intended size
(Settings ~1090 points wide in a 960-point window). Use the display content scale; ui.scale
multiplies it. The BIOS tiles now decide 'read by the core' from file name, folder and size
exactly as the core does (Series K is never read from a file, jagboot_m.rom only from the
system folder under Model M, wrong-sized files are skipped), with tests.
Refs #833
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
BIOS and system files (the core's known boot ROMs and CD BIOS by CRC32, the names the
core searches for, anything named BIOS or tagged [BIOS] in the dat, Memory Track images)
are classified out of the game grid into their own tab, which also lists what is in the
core's system folder and says, per file, when the core reads it and whether it is where
the core looks. BIOS tiles do not launch. Loose Redump (Track N).bin files are skipped.
The selected section is remembered. Unit tests cover the classification.
Refs #833
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Scans user folders for cartridge and CD images, identifies them by CRC32 against the
libretro-database Jaguar dats (No-Intro carts, Redump CD track 1), and shows a grid with
box art from libretro-thumbnails, downloaded on demand into a cache and available offline
once cached. Downloads run on worker threads over libcurl (WinHTTP on Windows).
Refs #838
Co-Authored-By: Claude Opus 5.5 <[email protected]>