Repository navigation
fix(bios): take the BIOS verdict from the resolver, per launching emulator and per file - #2457
Merged
Merged
Conversation
danielcopper
force-pushed
the
feature/2190-bios-verdict
branch
4 times, most recently
from
October 19, 2026 13:08
a0ba8cd to
5c36850
Compare
…lator and per file The colour of a platform, a game and the play badge is now the resolver's requirements_met for the launching emulator: met, not met, or not established. The one exception is a one-of group whose verdict is open only because the disc's region decides it, which reads amber on the platform page; every part of that rule is read off the resolver. Where the game's region is clear, the game page judges the image serving that region instead, and reads grey with a sentence where none serves it. Where the resolver shows the console's own image absent (system_firmware_met false), the game reads red whatever its region; a verdict not met that nothing the resolver states explains reads grey, and the console's image is never inferred from a group or the rows. An emulator the answer holds no entry for counts as not read, for its rows as for its level. The regions a one-of group carries no option for are read off the resolver's own statement of them (unstated on the group's region-decided-by-disc note) and nothing else. Such a region is open: it keeps a covered group off met and the platform off amber, and a game of that region reads grey on its page. Wherever no game region narrows the group, on the platform page and on the page of a game with no clear region, where the platform's verdict stands, one clause follows the group's sentence: "Beetle PSX has a BIOS image for Japan only — Europe discs will not start — for USA discs Beetle PSX states no BIOS image, so whether they start could not be established". Where no image is missing, the clause follows the regions covered, with the status "1 / 3 regions · regions not checked". An emulator that names no image and finds none, DuckStation over a BIOS folder holding nothing of a size it accepts, answers not met with no row to show. Both reads now send that answer, so the platform reads red and the play row warns, and the panel words the verdict rather than "Nothing could be established" for an emulator read as stating nothing. Where the console needs an image and the emulator names none, the sentence is the console's need with no count: "PlayStation does not start without a BIOS image". Each file row is the launching emulator's own requirement at the place the resolver names for it, with the resolver's per-file verdict rather than presence. Placements are no longer folded across emulators by file name, and the platform downloads place each file where the launching emulator opens it; a game page's download places it for the game's own pick. Every other emulator the resolver answered for gets an entry of its own on the payload, listing that emulator's own requirements, which both pages can show in place of the launching emulator's; showing one never changes the colour, the counts or the badge. The game page still lists only the rows it can act on, and counts the rest on a line that names the shown emulator and points at the platform page. A file whose place the resolver could not look at is never downloaded into: its row is grey, it offers no download, and Download required neither counts nor fetches it. The system_image axis is gone from the wire; the console's need for an image reaches the panel only as words under a red verdict, naming the console by RomM's platform name. Refused required declarations, a BIOS no one chose in PCSX2's settings, and images that tie are worded from the resolver's own statements. Amber is never a row's colour. Fields no surface reads (per-emulator row entries, the raw verdict, a count of partly covered groups) leave the wire.
The resolver states how each emulator finds its firmware: it opens the
names it declares, it searches the BIOS folder by content after a
configured name, or nobody has established which. The summary now words
the required files by it ("opens by name", "lists as required" with a
note that how the emulator finds its BIOS is not established, and
"requires" for an emulator that also searches by content), states what a
search by content found instead of a ratio, names a missing file beside
one nothing could check, and says when the resolver does not cover an
emulator at all. None of it moves the colour.
What a search found is worded only from the resolver's own statements.
"Found by content" needs it to state the image was identified by its
contents. A settled search that reached no image is its statement with
the folder it searched and how many files of an accepted size it held:
"SwanStation found no BIOS image in bios/ for a USA console" (No BIOS
image found) or "bios/ holds 2 files of a size SwanStation accepts, and
it recognises none of them" (No image recognised). DuckStation's search
states the folder and no count, and is worded by the folder alone;
behind the console's need it reads "PlayStation does not start without a
BIOS image — DuckStation (Standalone) found no BIOS image in bios/". A
statement about a setting that names no file is told apart from a search
by its fields: PCSX2's empty BIOS setting names a folder with neither a
count nor regions, and still reads that no BIOS is chosen. A required
file that is not met is never read as a search that found nothing.
The resolver's answers about the launching emulator and the per-emulator
entries move from services/firmware/status.py into
services/firmware/emulator_answers.py, keeping the module under the size
threshold. A tie between two images reads "for Europe two images are in
place; which one SwanStation uses is not established".
…t is there
The platform page's Contents column words the resolver's check for every
file at its place: right file, wrong file, refused, not comparable, not
recognised, could not be read, not checked, or not established. The
words explain the row's mark and never contradict it, a folder's
contents read "not established" rather than "unknown", and a file
nothing was asked about keeps the em dash. A wrong or refused file that
is not required keeps the muted mark a missing optional file gets, and
every mark says "wrong file" or "refused" rather than "missing" where
the file is there.
The game page says the same for a wrong or a refused file, in the same
words and naming the emulator, and the platform page does not repeat
them under the row. A file whose place could not be looked at names that
place rather than reading as missing.
Every row states what the shown emulator needs of the file, on both
pages: required, optional, "one of these · for USA discs" for an option
of a one-of group, not required, or need not established. The game page
puts it on the file's own line, after its name and description, after a
"·", with tighter rows; the platform page puts it under the name, in the
name's own cell so the row's button is centred against both lines, and
sets its rows a little closer. A met required file and a met optional
file no longer read alike, and an option's line no longer says whether
it is in place; its mark or dot says that.
Where the console needs an image and a search of the BIOS folder found
nothing, the console's sentence stands first and the search's follows it
as a note. A file nothing could check and a declaration the resolver
would not follow take the same verb as the count ("opens by name",
"lists as required" or "requires"), so one emulator is never worded two
ways.
Both pages choose which emulator's requirements the BIOS table shows
with an emulator selector: a row "L2 ◀ ● <emulator> 1 / 5 ▶ R2" whose
arrows and triggers step through the emulators, wrapping around, and
under it a carousel of every emulator with its verdict dot, each
emulator once, the shown one in the middle and outlined, each chosen by
pressing it. The L2 and R2 marks are Steam's own controller glyphs. The
launching emulator comes first, its name in the accent blue and its
carousel entry outlined in it; an emulator that is not installed is
listed too, its name in red, which wins over the blue. Choosing another
never changes what launches, the header or the badge. The shown name
stands on the row's own centre, the axis the carousel centres on; on the
wide game page the selector is held to about the platform page's width
and centred. L2 and R2 step on the Library's Platforms page wherever
focus is, the platform list included, and on a game's page anywhere in
Tender's section while its BIOS tab is open; any other button, and a
trigger where no selector is shown, goes on to Steam. Steam's own
dropdown is not used: in Game Mode it opens a menu over the whole
screen, and it keeps the option it was given while the label is not a
string, so after a download its dot stayed red under a green header.
Every dot now comes from the answer the page holds.
Where none of a platform's emulators can be baked into a shortcut, the
BIOS answer is about the emulator RetroDECK declares first, installed or
not, which its plain launch starts unless an alternative emulator is set
in ES-DE: its verdict heads the BIOS part, "Download required" fetches
for it, and so does a game's "Download BIOS" where the game resolves to
no emulator. Only where that emulator cannot be identified, because no
emulator is listed or the resolver names no identity for the first one,
does the BIOS part read that nothing could be established; the backend
fetches nothing for such a pick and no row is presented as its
requirement. It has no entry in the selector, so the platform page opens
on the first other emulator and offers that one's "Download required",
and with no other there is no such button.
Focus no longer falls back to the top of the platform page. A greyed
button keeps the focus, as Steam's own greyed buttons do, and a press on
it does nothing. Its look is Steam's own grey alone: a red Delete or
Failed label is drawn only while its button can be pressed. While a
row's download or delete, or a bulk button's work, runs, the pressed
button stays enabled and the others wait greyed; a delete's dialog hands
focus back to its button, and a row left with nothing to press takes the
focus itself. After a step, focus on a row of the table stays on the
same file's row, else goes to the new table's top row, else to the
carousel's shown entry; on the game page it goes to the shown entry
where the new emulator lists no file. The pane keeps its scroll position
through a row's or a bulk button's work, put back at once and again
after Steam's own scroll, while focus stays in the BIOS part. Another
emulator's rows are not muted; on the game page an unmet option of its
one-of group reads not established, since only the launching emulator's
group is judged for the game. On the platform page every emulator's rows
offer their download and their delete, and a download, a row's own or
"Download required for <emulator>", lands where the shown emulator opens
the file. The two endpoints take that emulator's identity, and one the
answer holds no verdict for is refused with emulator_unknown rather than
placed where another emulator opens the file. "Download all" and "Delete
downloads" stand apart under the sub-heading "For all of <platform>",
smaller than a section title. The game page offers no BIOS download or
delete of its own. In the selector, one emulator identity listed under
several labels is one entry named by all of them in the list's order,
"LRPS2 / PCSX2", whichever of them is the pick, and the BIOS sentences
and rows name the launching emulator the same way. The platform page's
note that BIOS files can be put in place by hand is left out under the
sentence that no BIOS is chosen in the emulator's settings.
The RomM library's files no emulator here declares stand in a section of
their own on both pages, under the sub-heading "In your RomM library,
asked for by no emulator here", the same whichever emulator is shown; it
replaces the lines that counted them. The docs state that Tender keeps
one download record per file name on a platform, so a row's Delete
removes Tender's download of that name wherever it was placed.
The emulator menus on the platform page and on a game's page, the
platform header, the game page's Emulator column, the toast after a
game's switch, the line under the button while a platform switches, and
the emulator RetroDECK would fall back to now name an emulator by its
launch command rather than by one label: labels that run the same
command are one entry, named by all of them in RetroDECK's order.
RetroDECK lists pcsx2_libretro.so for PlayStation 2 as LRPS2 and as
PCSX2 under one command, so the menu offers "LRPS2 / PCSX2" once. Labels
of one emulator that run different commands stay separate entries,
because each is its own way to launch: RPCS3 by game serial against
"RPCS3 Directory (Standalone) / RPCS3 ISO (Standalone)", and EKA2L1's
device variants. Picking a joined entry stores its first label, and an
override stored under any of its labels reads as that entry, its check
mark, "(default)", "(system)" and "Use System Override (…)" included, so
stored overrides need no migration and launching is unchanged. The
picker payload carries an entry's labels and their joined name beside
the label a pick stores. The BIOS selector keeps one entry per emulator
identity, because the firmware is the same for every way an emulator
launches. On Arcade consoles RetroDECK's two disabled shortcut forms run
the same command and are one entry too.
Docs and comments that still described per-emulator lines on the game
page, presence as a row's verdict, the removed console axis or a
"requires" no payload produces are brought in line with the code, and
required_by_active is documented as the requirement of the emulator
whose list the row is on.
danielcopper
force-pushed
the
feature/2190-bios-verdict
branch
from
October 19, 2026 14:58
5c36850 to
65ea9f8
Compare
|
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.



The BIOS answer on the Library's platform page and on a game's BIOS tab now comes from the resolver's verdicts rather than from Tender's own presence checks. A platform's or a game's colour is the launching emulator's
requirements_met; a file's row is the resolver's per-file verdict, and the Contents column words the check behind it: right file, wrong file, refused, not comparable, not recognised, could not be read. A one-of group, such as the PlayStation region images, is judged per region on the platform page and narrowed to the game's region on its page, and the regions the resolver states nothing for are named. The wording follows how each emulator finds its firmware: opened by name, searched for by content with what the search found, or chosen in its settings.An emulator selector covers every emulator the resolver answers for, installed or not: L2 and R2 step through them, a carousel shows them all, the launching one is blue and one that is not installed is red. "Download required for
<emulator>" and each row's download place a file where the shown emulator looks for it, and "Delete downloads" removes only what Tender downloaded. RomM library files no emulator asks for stand in a section of their own.The emulator menus on the platform page and on a game's page, the platform header, the game page's Emulator column and the play row name a launch entry by its command: labels that run the same command are one entry, "LRPS2 / PCSX2", while one emulator's different ways to launch stay apart, such as RPCS3 by game serial against RPCS3 from a folder or an ISO. Choosing a joined entry stores its first label, and a choice stored under any of its labels reads as that entry. The BIOS part names the emulator by every label it goes by, because its firmware is the same for every way it launches.
DuckStation (Standalone) over a BIOS folder with no image of an accepted size now reads red — "PlayStation does not start without a BIOS image — DuckStation (Standalone) found no BIOS image in bios/" — and the play row shows BIOS Missing.
Tender's own reading of the console's demand (
system_image) leaves the wire; the docs, the glossary and the invariant register say what is read now.Decisions
From #2190:
?in the On-disk column, the dot of a row without a verdict, the group line for a region that could not be checked. Another emulator's files are shown on that emulator's own tab (D15), not as muted rows beside the launching emulator's. A file whose need nothing could establish gets a grey?, not the grey✗that means "not required". Gold for an emulator the user picked stays; it is not a status.docs/architecture/invariants.mdandbackend-architecture.mdpassages that say the verdict is not read, that presence is the row verdict, or that the console's demand never comes fromrequirements_met, are rewritten in this change. The trap in CLAUDE.md that namesrequirements_metas the verdict stays.<emulator>" and a row's download on the platform page fetch from the RomM library to the place the resolver names for the emulator shown (D15): with Kronos shown for Saturn,saturn_bios.bingoes tobios/kronos/; with YabaSanshiro shown, tobios/. An emulator the resolver's answer holds nothing for is refused. Placing a file after the launching emulator changes (D2) is built in fix(bios): match library firmware by platform and content, keep it once in Tender's firmware store, and link it where the resolver names #2191 together with the store; until then the new emulator's missing rows are red and offer their download like any other. Where a file goes stays the same once the store exists; only where it comes from changes.core-mode-unestablishednote with the reasonregion-decided-by-disc. Tender counts nothing of its own here.system_image: not demanded, held, absent, unsettled) goes. The colour isrequirements_met, which already weighs the console's demand. The sentence that the console does not start without one of the images stays: that the console needs one comes from the resolver'ssystem_firmwareand itssystem-firmware-world-knowledgenote, and which image is in place from the per-file verdicts (D3), never from presence. With no PlayStation image, SwanStation reads red: "PlayStation does not start without a BIOS image, and none of the five SwanStation knows is in place". The play-button warning follows the red verdict. The value leaves the wire, and the glossary, register and docs passages on it are rewritten with D8.<emulator>1 / 5 ▶ R2", with Steam's own L2 and R2 glyphs: L2 and R2, and the arrows, step to the previous and next emulator, wrapping around. Below it every emulator stands with its verdict dot in a carousel, in the smallest font Tender uses on the Deck: the shown one always centred and outlined in grey, the launching one outlined in blue, the others on either side in stepping order, wrapping around, each one selectable, and a step moves the carousel visibly rather than redrawing it. A name says the emulator's state by its colour, in the top row and the carousel: the launching emulator's in blue, a not-installed emulator's in red, and red where both apply; no words are added after the name. On the game page the selector is held to about the platform page's width and centred. Steam's own dropdown is not used, because in Game Mode it opens a menu over the whole screen. An entry names no emulator source: one source answers a platform (feat(emulators): choose among every emulator source's emulators, per platform and per game #2222). The table shows the chosen emulator's requirements exactly as the resolver answers them: its places, needs, per-file verdicts and contents; a group option is shown once, not again as the plain row the group speaks for. Choosing an emulator never changes the launching emulator: the header, the count and the play-button warning stay the launching emulator's. On the platform page every emulator's rows offer their download (D9) and delete; the game page offers no BIOS download or delete of its own, and the play row's "Download BIOS" fetches for the game's own pick.✗a missing optional file gets, and its contents say which. The sentences are feat(bios): say whether a BIOS file is the right one, not just that it is there #1803's words naming the emulator, the same on both pages: "wrong file — not the image Beetle PSX expects", "refused — Beetle PSX does not accept a file of this size".firmware-path-names-no-filewith the folder it searched and how many candidates it held), never from how the emulator finds its firmware plus the verdict: "SwanStation found no BIOS image in bios/ for a Europe console", or "bios/ holds 2 files of a size SwanStation accepts, and it recognises none of them", with the statuses "No BIOS image found" and "No image recognised". Where the resolver states nothing of the search, nothing is said of it. "opens by name" is used only for an emulator that opens its firmware by name; one that searches by name and then by content "requires" its files. Where the console needs an image, D13's sentence stands first and this one follows as a note.<platform>": "Download all", which places each file for the platform's pick, and "Delete downloads (N)", which removes every download Tender recorded for the platform, whichever emulator it was made for; its dialog says that only Tender's downloads are removed. The label is short so that both buttons fit on one line.pcsx2_libretro.soas "LRPS2" and as "PCSX2") is one option, named by every label the resolver gives it: "LRPS2 / PCSX2", whichever of them is picked.<emulator>'s settings" sentence, where the files are there and a setting is missing. Wherever else nothing could be established, it stays.<platform>" and "In your RomM library, asked for by no emulator here" are sub-headings under BIOS files, smaller than a section title, so neither reads as a section of the platform page of its own. One legend at the end of the BIOS part serves both tables.<emulator>" is offered (D9); the header still says nothing could be established. Where no emulator is listed at all, there is no selector and no "Download required".requirements_met(D1).pcsx2_libretro.so. Labels of one emulator that run different commands stay separate entries, because each is its own way to launch: RPCS3's "Game Serial" against "Directory / ISO", whose two labels run the same command, and EKA2L1's device variants. Choosing a merged entry writes the first label RetroDECK lists among them; an override stored under any of its labels reads as that entry. Stored overrides are not migrated, and launching is unchanged. The BIOS selector keeps grouping by emulator (D28): the firmware is the same for every way an emulator launches.From #1883:
Closes #2190
Closes #1883
Closes #1803