mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-04-13 12:22:33 -05:00
117 lines
3.7 KiB
Python
117 lines
3.7 KiB
Python
"""Exporter for libretro System.dat (clrmamepro DAT format).
|
|
|
|
Produces a single 'game' block with all ROMs grouped by system,
|
|
matching the exact format of libretro-database/dat/System.dat.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
|
|
from scraper.dat_parser import parse_dat
|
|
|
|
from .base_exporter import BaseExporter
|
|
|
|
|
|
def _slug_to_native(slug: str) -> str:
|
|
"""Convert a system slug to 'Manufacturer - Console' format."""
|
|
parts = slug.split("-", 1)
|
|
if len(parts) == 1:
|
|
return parts[0].title()
|
|
manufacturer = parts[0].replace("-", " ").title()
|
|
console = parts[1].replace("-", " ").title()
|
|
return f"{manufacturer} - {console}"
|
|
|
|
|
|
class Exporter(BaseExporter):
|
|
"""Export truth data to libretro System.dat format."""
|
|
|
|
@staticmethod
|
|
def platform_name() -> str:
|
|
return "retroarch"
|
|
|
|
def export(
|
|
self,
|
|
truth_data: dict,
|
|
output_path: str,
|
|
scraped_data: dict | None = None,
|
|
) -> None:
|
|
native_map: dict[str, str] = {}
|
|
if scraped_data:
|
|
for sys_id, sys_data in scraped_data.get("systems", {}).items():
|
|
nid = sys_data.get("native_id")
|
|
if nid:
|
|
native_map[sys_id] = nid
|
|
|
|
lines: list[str] = [
|
|
"clrmamepro (",
|
|
'\tname "System"',
|
|
'\tdescription "System"',
|
|
'\tcomment "System, firmware, and BIOS files used by libretro cores."',
|
|
")",
|
|
"",
|
|
"game (",
|
|
'\tname "System"',
|
|
]
|
|
|
|
systems = truth_data.get("systems", {})
|
|
for sys_id in sorted(systems):
|
|
sys_data = systems[sys_id]
|
|
files = sys_data.get("files", [])
|
|
if not files:
|
|
continue
|
|
|
|
native_name = native_map.get(sys_id, _slug_to_native(sys_id))
|
|
lines.append("")
|
|
lines.append(f'\tcomment "{native_name}"')
|
|
|
|
for fe in files:
|
|
name = fe.get("name", "")
|
|
if name.startswith("_") or self._is_pattern(name):
|
|
continue
|
|
|
|
rom_parts = [f"name {name}"]
|
|
size = fe.get("size")
|
|
if size:
|
|
rom_parts.append(f"size {size}")
|
|
crc = fe.get("crc32", "")
|
|
if crc:
|
|
rom_parts.append(f"crc {crc.upper()}")
|
|
md5 = fe.get("md5", "")
|
|
if isinstance(md5, list):
|
|
md5 = md5[0] if md5 else ""
|
|
if md5:
|
|
rom_parts.append(f"md5 {md5}")
|
|
sha1 = fe.get("sha1", "")
|
|
if isinstance(sha1, list):
|
|
sha1 = sha1[0] if sha1 else ""
|
|
if sha1:
|
|
rom_parts.append(f"sha1 {sha1}")
|
|
|
|
lines.append(f"\trom ( {' '.join(rom_parts)} )")
|
|
|
|
lines.append(")")
|
|
lines.append("")
|
|
Path(output_path).write_text("\n".join(lines), encoding="utf-8")
|
|
|
|
def validate(self, truth_data: dict, output_path: str) -> list[str]:
|
|
content = Path(output_path).read_text(encoding="utf-8")
|
|
parsed = parse_dat(content)
|
|
|
|
exported_names: set[str] = set()
|
|
for rom in parsed:
|
|
exported_names.add(rom.name)
|
|
|
|
issues: list[str] = []
|
|
for sys_data in truth_data.get("systems", {}).values():
|
|
for fe in sys_data.get("files", []):
|
|
name = fe.get("name", "")
|
|
if name.startswith("_") or self._is_pattern(name):
|
|
continue
|
|
if name not in exported_names:
|
|
issues.append(f"missing: {name}")
|
|
return issues
|