feat: cross-reference platform -> core -> systems -> upstream

This commit is contained in:
Abdessamad Derraz
2026-03-25 14:03:36 +01:00
parent 0f4fed2f47
commit 3d2762bbc3

View File

@@ -710,72 +710,155 @@ def generate_cross_reference(
coverages: dict, coverages: dict,
profiles: dict, profiles: dict,
) -> str: ) -> str:
"""Generate a cross-reference page mapping platforms to emulators and back.""" """Generate cross-reference: Platform -> Core -> Systems -> Upstream."""
unique = {k: v for k, v in profiles.items() unique = {k: v for k, v in profiles.items()
if v.get("type") not in ("alias", "test", "launcher")} if v.get("type") not in ("alias", "test")}
# Build system -> emulators map # Build core -> profile lookup by core name
system_emus: dict[str, list[str]] = {} core_to_profile: dict[str, str] = {}
for emu_name, p in unique.items(): for pname, p in unique.items():
for sys_id in p.get("systems", []): for core in p.get("cores", [pname]):
system_emus.setdefault(sys_id, []).append(emu_name) core_to_profile[str(core)] = pname
# Build platform -> systems map
platform_systems: dict[str, list[str]] = {}
for name, cov in coverages.items():
config = cov["config"]
platform_systems[name] = sorted(config.get("systems", {}).keys())
lines = [ lines = [
f"# Cross-reference - {SITE_NAME}", f"# Cross-reference - {SITE_NAME}",
"", "",
"Which emulators serve which platforms, mapped through shared system IDs.", "Platform → Core → Systems → Upstream emulator.",
"",
"The libretro core is a port of the upstream emulator. "
"Files, features, and validation may differ between the two.",
"", "",
] ]
# Platform -> systems -> emulators # Per platform
lines.extend(["## By platform", ""])
for pname in sorted(coverages.keys(), key=lambda x: coverages[x]["platform"]): for pname in sorted(coverages.keys(), key=lambda x: coverages[x]["platform"]):
display = coverages[pname]["platform"] cov = coverages[pname]
systems = platform_systems.get(pname, []) display = cov["platform"]
lines.append(f"### [{display}](platforms/{pname}.md)") config = cov["config"]
lines.append("") platform_cores = config.get("cores", [])
lines.append(f"{len(systems)} systems")
lines.append(f"## [{display}](platforms/{pname}.md)")
lines.append("") lines.append("")
lines.append("| System | Emulators |") # Resolve which profiles this platform uses
lines.append("|--------|----------|") if platform_cores == "all_libretro":
for sys_id in systems: matched = {k: v for k, v in unique.items()
emus = system_emus.get(sys_id, []) if "libretro" in v.get("type", "")}
if emus: elif isinstance(platform_cores, list):
emu_links = ", ".join(f"[{e}](emulators/{e}.md)" for e in sorted(emus)) matched = {}
else: for cname in platform_cores:
emu_links = "-" cname_str = str(cname)
lines.append(f"| {sys_id} | {emu_links} |") if cname_str in unique:
matched[cname_str] = unique[cname_str]
elif cname_str in core_to_profile:
pkey = core_to_profile[cname_str]
matched[pkey] = unique[pkey]
else:
# Fallback: system intersection
psystems = set(config.get("systems", {}).keys())
matched = {k: v for k, v in unique.items()
if set(v.get("systems", [])) & psystems}
if platform_cores == "all_libretro":
lines.append(f"**{len(matched)} cores** (all libretro)")
else:
lines.append(f"**{len(matched)} cores**")
lines.append("") lines.append("")
# Emulator -> systems -> platforms lines.append("| Core | Classification | Systems | Files | Upstream |")
lines.extend(["## By emulator", ""]) lines.append("|------|---------------|---------|-------|----------|")
lines.append("| Emulator | Type | Classification | Systems | Platforms |")
lines.append("|----------|------|---------------|---------|-----------|")
for emu_name in sorted(unique.keys()): for emu_name in sorted(matched.keys()):
p = unique[emu_name] p = matched[emu_name]
emu_display = p.get("emulator", emu_name) emu_display = p.get("emulator", emu_name)
emu_type = p.get("type", "") cls = p.get("core_classification", "-")
cls = p.get("core_classification", "") emu_type = p.get("type", "")
emu_systems = set(p.get("systems", [])) upstream = p.get("upstream", "")
# Find platforms that share systems with this emulator source = p.get("source", "")
emu_plats = set() systems = p.get("systems", [])
for pname, psystems in platform_systems.items(): files = p.get("files", [])
if emu_systems & set(psystems):
emu_plats.add(pname) sys_str = ", ".join(systems[:3])
plat_str = ", ".join(sorted(emu_plats)) if emu_plats else "-" if len(systems) > 3:
sys_count = len(emu_systems) sys_str += f" +{len(systems) - 3}"
file_count = len(files)
# Count mode divergences
libretro_only = sum(1 for f in files if f.get("mode") == "libretro")
standalone_only = sum(1 for f in files if f.get("mode") == "standalone")
file_str = str(file_count)
if libretro_only or standalone_only:
parts = []
if libretro_only:
parts.append(f"{libretro_only} libretro-only")
if standalone_only:
parts.append(f"{standalone_only} standalone-only")
file_str += f" ({', '.join(parts)})"
upstream_display = "-"
if upstream:
upstream_short = upstream.replace("https://github.com/", "")
upstream_display = f"[{upstream_short}]({upstream})"
elif source:
source_short = source.replace("https://github.com/", "")
upstream_display = f"[{source_short}]({source})"
lines.append(
f"| [{emu_display}](emulators/{emu_name}.md) | {cls} | "
f"{sys_str} | {file_str} | {upstream_display} |"
)
lines.append("")
# Reverse view: by upstream emulator
lines.extend([
"## By upstream emulator",
"",
"| Upstream | Cores | Classification | Platforms |",
"|----------|-------|---------------|-----------|",
])
# Group profiles by upstream
by_upstream: dict[str, list[str]] = {}
for emu_name, p in sorted(unique.items()):
upstream = p.get("upstream", p.get("source", ""))
if upstream:
by_upstream.setdefault(upstream, []).append(emu_name)
# Build platform membership per core
platform_membership: dict[str, set[str]] = {}
for pname, cov in coverages.items():
config = cov["config"]
pcores = config.get("cores", [])
if pcores == "all_libretro":
for k, v in unique.items():
if "libretro" in v.get("type", ""):
platform_membership.setdefault(k, set()).add(pname)
elif isinstance(pcores, list):
for cname in pcores:
cname_str = str(cname)
if cname_str in unique:
platform_membership.setdefault(cname_str, set()).add(pname)
elif cname_str in core_to_profile:
pkey = core_to_profile[cname_str]
platform_membership.setdefault(pkey, set()).add(pname)
for upstream_url in sorted(by_upstream.keys()):
cores = by_upstream[upstream_url]
upstream_short = upstream_url.replace("https://github.com/", "")
classifications = set()
all_plats: set[str] = set()
for c in cores:
classifications.add(unique[c].get("core_classification", "-"))
all_plats.update(platform_membership.get(c, set()))
cls_str = ", ".join(sorted(classifications))
plat_str = ", ".join(sorted(all_plats)) if all_plats else "-"
core_links = ", ".join(f"[{c}](emulators/{c}.md)" for c in sorted(cores))
lines.append( lines.append(
f"| [{emu_display}](emulators/{emu_name}.md) | {emu_type} | " f"| [{upstream_short}]({upstream_url}) | {core_links} | "
f"{cls} | {sys_count} | {plat_str} |" f"{cls_str} | {plat_str} |"
) )
lines.extend(["", f"*Generated on {_timestamp()}*"]) lines.extend(["", f"*Generated on {_timestamp()}*"])