diff --git a/scripts/common.py b/scripts/common.py
index 760eb815..e4cfc93d 100644
--- a/scripts/common.py
+++ b/scripts/common.py
@@ -773,6 +773,13 @@ def load_emulator_profiles(
return profiles
+def unique_emulator_profiles(profiles: dict[str, dict]) -> dict[str, dict]:
+ """Profiles counting as distinct emulators (aliases and tests excluded)."""
+ return {
+ k: v for k, v in profiles.items() if v.get("type") not in ("alias", "test")
+ }
+
+
def group_identical_platforms(
platforms: list[str],
platforms_dir: str,
diff --git a/scripts/generate_readme.py b/scripts/generate_readme.py
index fdc4633a..61bad765 100644
--- a/scripts/generate_readme.py
+++ b/scripts/generate_readme.py
@@ -15,13 +15,14 @@ import json
import os
import sys
from datetime import datetime, timezone
-from pathlib import Path
sys.path.insert(0, os.path.dirname(__file__))
from common import (
list_registered_platforms,
load_database,
+ load_emulator_profiles,
load_platform_config,
+ unique_emulator_profiles,
write_if_changed,
)
from verify import verify_platform
@@ -116,37 +117,27 @@ def generate_readme(db: dict, platforms_dir: str) -> str:
except FileNotFoundError:
pass
- emulator_count = (
- sum(
- 1
- for f in Path("emulators").glob("*.yml")
- if not f.name.endswith(".old.yml")
- )
- if Path("emulators").exists()
- else 0
+ profiles = unique_emulator_profiles(
+ load_emulator_profiles("emulators", skip_aliases=False)
)
+ emulator_count = len(profiles)
- # Count systems from emulator profiles
system_ids: set[str] = set()
- emu_dir = Path("emulators")
- if emu_dir.exists():
- try:
- import yaml
-
- for f in emu_dir.glob("*.yml"):
- if f.name.endswith(".old.yml"):
- continue
- with open(f) as fh:
- p = yaml.safe_load(fh) or {}
- system_ids.update(p.get("systems", []))
- except ImportError:
- pass
+ for p in profiles.values():
+ system_ids.update(p.get("systems", []))
lines = [
'
',
'
',
"
",
"",
+ '',
+ ' '
+ '
',
+ ' '
+ '
',
+ "
",
+ "",
f"Complete BIOS and firmware packs for "
f"{', '.join(c['platform'] for c in sorted(coverages.values(), key=lambda x: x[
'platform'
diff --git a/scripts/generate_site.py b/scripts/generate_site.py
index 8103bf80..aacd6cff 100644
--- a/scripts/generate_site.py
+++ b/scripts/generate_site.py
@@ -12,6 +12,7 @@ Usage:
from __future__ import annotations
import argparse
+import json
import os
import shutil
import sys
@@ -24,6 +25,7 @@ from common import (
load_database,
load_emulator_profiles,
require_yaml,
+ unique_emulator_profiles,
write_if_changed,
)
@@ -242,9 +244,7 @@ def generate_home(
total_size = db.get("total_size", 0)
ts = _timestamp()
- unique = {
- k: v for k, v in profiles.items() if v.get("type") not in ("alias", "test")
- }
+ unique = unique_emulator_profiles(profiles)
emulator_count = len(unique)
# Classification stats
@@ -321,6 +321,16 @@ def generate_home(
f"[Pack]({RELEASE_URL}){{ .md-button .md-button--primary }} |"
)
+ lines.extend(
+ [
+ "",
+ "Verification is the check each platform runs itself, replicated "
+ "from its source code. RetroArch only tests that files exist; "
+ "Batocera compares MD5 checksums. "
+ "[How each mode works](wiki/verification-modes.md).",
+ ]
+ )
+
# Quick start (collapsible -- secondary info)
lines.extend(
[
@@ -393,6 +403,27 @@ def generate_home(
return "\n".join(lines) + "\n"
+def compute_stats(db: dict, coverages: dict, profiles: dict) -> dict:
+ unique = unique_emulator_profiles(profiles)
+ systems: set[str] = set()
+ for p in unique.values():
+ systems.update(p.get("systems", []))
+ return {
+ "generated_at": _timestamp(),
+ "files": db.get("total_files", 0),
+ "size_bytes": db.get("total_size", 0),
+ "platforms": len(coverages),
+ "emulators": len(unique),
+ "systems": len(systems),
+ "source": REPO_URL,
+ "downloads": RELEASE_URL,
+ }
+
+
+def generate_stats(stats: dict) -> str:
+ return json.dumps(stats, indent=2) + "\n"
+
+
# Platform pages
@@ -431,6 +462,15 @@ def generate_platform_index(coverages: dict) -> str:
f"[Pack]({RELEASE_URL}){{ .md-button .md-button--primary }} |"
)
+ lines.extend(
+ [
+ "",
+ "Verification is the check each platform runs itself, replicated "
+ "from its source code. "
+ "[How each mode works](../wiki/verification-modes.md).",
+ ]
+ )
+
return "\n".join(lines) + "\n"
@@ -2448,6 +2488,9 @@ def main():
str(docs / "index.md"), generate_home(db, coverages, profiles, registry)
)
+ stats = compute_stats(db, coverages, profiles)
+ write_if_changed(str(docs / "stats.json"), generate_stats(stats))
+
# Build system_id -> manufacturer page map (needed by all generators)
print("Building system cross-reference map...")
manufacturers = _group_by_manufacturer(db)