fix: send unreleased platforms to the installer

A release recorded without a platform's pack linked its button to that release, which serves no pack for AmberELEC, EmuELEC, KNULLI, MinUI, NextUI or MyMinUI. The cell now names the release and points to the installer, which reads the file lists on main. Core folder links resolve each core name to the profile page that describes it (mednafen_vb is beetle_vb).
This commit is contained in:
Abdessamad Derraz committed 2026-10-22 11:04:25 +02:00
1 parent 4501601769
commit 87a4e8e1b6
4 files changed
+52 -12

No files matched your search

+7 -7
View File
@@ -47,17 +47,17 @@ The Files column counts what a pack holds once extracted, the figure a file mana
| Platform | Files | Extracted size | Extract to | Download |
|----------|------:|---------------:|-----------|----------|
| AmberELEC | - | - | `/storage/roms/` | [Download](../../releases/latest) |
| AmberELEC | - | - | `/storage/roms/` | Not in v2026.10.10: [use the installer](https://abdess.github.io/retrobios/wiki/installer/) |
| Batocera | 12,810 | 7.5 GB | `/userdata/bios/` | Download: [part 1 of 3](../../releases/download/v2026.10.10/Batocera_43.1_BIOS_Pack.part1of3.zip), [part 2 of 3](../../releases/download/v2026.10.10/Batocera_43.1_BIOS_Pack.part2of3.zip), [part 3 of 3](../../releases/download/v2026.10.10/Batocera_43.1_BIOS_Pack.part3of3.zip) |
| BizHawk | 950 | 2.4 GB | `Firmware/` | [Download](../../releases/download/v2026.10.10/BizHawk_2.11.1_BIOS_Pack.zip) |
| EmuDeck | 620 | 3.2 GB | `~/Emulation/bios/` | [Download](../../releases/download/v2026.10.10/EmuDeck_2.7EA_BIOS_Pack.zip) |
| EmuELEC | - | - | `/storage/roms/` | [Download](../../releases/latest) |
| KNULLI | - | - | `/userdata/bios/` | [Download](../../releases/latest) |
| EmuELEC | - | - | `/storage/roms/` | Not in v2026.10.10: [use the installer](https://abdess.github.io/retrobios/wiki/installer/) |
| KNULLI | - | - | `/userdata/bios/` | Not in v2026.10.10: [use the installer](https://abdess.github.io/retrobios/wiki/installer/) |
| Lakka | 8,504 | 6.0 GB | `/storage/system/` | Download: [part 1 of 2](../../releases/download/v2026.10.10/RetroArch_Lakka_v1.22.2_BIOS_Pack.part1of2.zip), [part 2 of 2](../../releases/download/v2026.10.10/RetroArch_Lakka_v1.22.2_BIOS_Pack.part2of2.zip) |
| MiSTer FPGA | 83 | 29 MB | `/media/fat/games/` | [Download](../../releases/download/v2026.10.10/MiSTer_FPGA_2026-09-29_BIOS_Pack.zip) |
| MinUI | - | - | `<SD card>/` | [Download](../../releases/latest) |
| MyMinUI | - | - | `<SD card>/` | [Download](../../releases/latest) |
| NextUI | - | - | `<SD card>/` | [Download](../../releases/latest) |
| MinUI | - | - | `<SD card>/` | Not in v2026.10.10: [use the installer](https://abdess.github.io/retrobios/wiki/installer/) |
| MyMinUI | - | - | `<SD card>/` | Not in v2026.10.10: [use the installer](https://abdess.github.io/retrobios/wiki/installer/) |
| NextUI | - | - | `<SD card>/` | Not in v2026.10.10: [use the installer](https://abdess.github.io/retrobios/wiki/installer/) |
| ROCKNIX | 5,804 | 6.1 GB | `/storage/roms/bios/` | Download: [part 1 of 2](../../releases/download/v2026.10.10/ROCKNIX_20261001_BIOS_Pack.part1of2.zip), [part 2 of 2](../../releases/download/v2026.10.10/ROCKNIX_20261001_BIOS_Pack.part2of2.zip) |
| Recalbox | 3,222 | 3.9 GB | `/recalbox/share/bios/` | Download: [part 1 of 2](../../releases/download/v2026.10.10/Recalbox_10.1.1_BIOS_Pack.part1of2.zip), [part 2 of 2](../../releases/download/v2026.10.10/Recalbox_10.1.1_BIOS_Pack.part2of2.zip) |
| RetroArch | 8,504 | 6.0 GB | `system/` | Download: [part 1 of 2](../../releases/download/v2026.10.10/RetroArch_Lakka_v1.22.2_BIOS_Pack.part1of2.zip), [part 2 of 2](../../releases/download/v2026.10.10/RetroArch_Lakka_v1.22.2_BIOS_Pack.part2of2.zip) |
@@ -208,4 +208,4 @@ The scripts and tooling are released under the [MIT License](LICENSE).
The BIOS and firmware files are not covered by that license: they are third-party system software, preserved and provided for personal backup, archival, and interoperability with emulation software. [NOTICE](NOTICE) sets out their status and how to ask for a file to be removed.
The reasoning, and where it is weakest, is in the [FAQ](https://abdess.github.io/retrobios/wiki/faq/#is-this-legal).
*Auto-generated on 2026-10-22T08:44:18Z*
*Auto-generated on 2026-10-22T08:57:23Z*
+7 -3
View File
@@ -134,14 +134,18 @@ def download_links(
A pack published whole gets one link labelled *label*. A pack in parts
gets one link per part, since every part is needed. *repo* is the
repository URL, absolute or relative, and *attrs* a MkDocs attribute list
put after each link. Without a pack in the record the link falls back to
the latest release page.
put after each link. Without a recorded release the link is the latest
release page. A release recorded without this platform's pack says so and
names the installer, which reads the file lists on main: a button to the
release served six platforms a page with no pack for them.
"""
pack = release_record.pack_for(platform_name, record)
tag = record.get("tag")
assets = pack.get("assets") if pack else None
if not tag or not assets:
if not tag:
return f"[{label}]({repo}/releases/latest){attrs}"
if not assets:
return f"Not in {tag}: [use the installer]({SITE_URL}wiki/installer/)"
urls = [f"{repo}/releases/download/{tag}/{asset}" for asset in assets]
if len(urls) == 1:
return f"[{label}]({urls[0]}){attrs}"
+30 -1
View File
@@ -15,6 +15,7 @@ from siterender import WIKI_SRC_DIR
import argparse
import csv
import hashlib
import functools
import html
import io
import json
@@ -33,6 +34,7 @@ from pathlib import Path
sys.path.insert(0, os.path.dirname(__file__))
from common import (
upstream_profile_index,
build_zip_contents_index,
compute_composition,
count_catalog_matched,
@@ -2088,6 +2090,33 @@ def _category_evidence_md(evidence: dict) -> str:
return f"No reader found ({cores})"
@functools.lru_cache(maxsize=1)
def _profiles_by_core_name() -> dict[str, list[str]]:
"""Core name as a platform writes it -> the profiles with a page for it.
MinUI writes `mednafen_vb`, the profile and its page are `beetle_vb`.
"""
profiles = load_emulator_profiles(str(_REPO_ROOT / "emulators"))
with_page = {k for k, v in profiles.items() if v.get("type") not in ("alias", "test")}
return {
core: sorted(k for k in keys if k in with_page)
for core, keys in upstream_profile_index(profiles).items()
}
def _core_name_links(cores: list[str]) -> list[str]:
"""A link per core to its profile page, the bare name where none exists."""
index = _profiles_by_core_name()
links = []
for core in cores:
keys = [core] if core in index.get(core, []) else index.get(core, [])
if keys:
links.extend(_emulator_link(k, "../") for k in keys)
else:
links.append(f"`{core}`")
return links
def _core_folders_section(name: str, config: dict) -> list[str]:
"""Each folder the frontend hands a core, and the files the pack puts in it.
@@ -2111,7 +2140,7 @@ def _core_folders_section(name: str, config: dict) -> list[str]:
f["dest"][len(folder) + 1:] for f in files
if f.get("dest", "").startswith(folder + "/")
)
cores = ", ".join(_emulator_link(c, "../") for c in info.get("cores", []))
cores = ", ".join(_core_name_links(info.get("cores", [])))
shown = ", ".join(f"`{n}`" for n in held) if held else "none needed"
lines.append(f"| `{folder}/` | {cores} | {shown} |")
lines.append("")
+8 -1
View File
@@ -112,9 +112,16 @@ class DownloadLinksNameTheFile(unittest.TestCase):
cell = download_links("batocera", SPLIT_RECORD, REPO, "Pack", " { .x }")
self.assertEqual(cell.count("{ .x }"), 2)
def test_without_a_pack_the_link_is_the_release_page(self):
def test_a_release_without_the_pack_names_the_installer(self):
self.assertEqual(
download_links("bizhawk", SPLIT_RECORD, "../..", "Download"),
"Not in v2000.01.01: "
"[use the installer](https://abdess.github.io/retrobios/wiki/installer/)",
)
def test_without_a_recorded_release_the_link_is_the_release_page(self):
self.assertEqual(
download_links("bizhawk", {}, "../..", "Download"),
"[Download](../../releases/latest)",
)