fix(build): link a BIOS backend only when its generated C provides one

PSXRECOMP_BIOS_STEMS defaults to "OpenBIOS;SCPH1001", so every game link
required a SCPH1001 backend. That backend is compiled from generated C which is
a derivative of a copyrighted Sony BIOS, so it is gitignored and only exists
after a developer regenerates it from their own dump. A checkout that has only
the bundled MIT OpenBIOS -- the documented default, and what a fresh clone gets
-- configured fine and then failed at link with:

    undefined reference to `SCPH1001_psx_bios_backend'

Hit while building Tomba 1, Tomba 2 and MMX6 to validate an unrelated branch;
all three needed -DPSXRECOMP_BIOS_STEMS=OpenBIOS as a workaround.

Filter the stem list to those that actually supply a backend, rather than
flipping the default. Flipping it would silently drop SCPH1001 for developers
who HAVE regenerated it; filtering keeps it fully supported when present and
simply absent when not.

Presence of the files is not a sufficient test. A generated/ tree produced
before the backend-descriptor mechanism existed has both <stem>_full.c and
<stem>_dispatch.c yet defines no descriptor -- exactly the local state that
produced the error above. The check therefore probes for the descriptor symbol
itself, in <stem>_dispatch.c (~1MB, where the emitter puts it) rather than the
multi-megabyte <stem>_full.c, so configure stays fast.

Also report what happened instead of leaving it implicit:
  - STATUS line naming the linked backends
  - STATUS line naming skipped stems with the regen command to fix them
  - FATAL_ERROR, with the OpenBIOS regen command, if no backend resolves at all
    (previously an empty registry would have surfaced as a confusing link error)

Verified: with default flags and a stale local SCPH1001 tree, Tomba 2 now
reports "BIOS backends skipped ... SCPH1001" / "BIOS backends linked: OpenBIOS",
links, and boots.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthew Stanley
2026-07-27 12:32:30 -07:00
parent 4c6aee392b
commit da093d4374
+53 -8
View File
@@ -279,21 +279,66 @@ set(PSXRECOMP_BIOS_STEM "${PSXRECOMP_BIOS_STEM_PRIMARY}" CACHE STRING
set(PSXRECOMP_BIOS_PROFILE "${PSXRECOMP_ROOT}/bios/${PSXRECOMP_BIOS_STEM}.toml" CACHE FILEPATH
"BIOS profile TOML this build regenerates from (staleness stamp input)")
# Link a stem only if its generated sources are actually present.
#
# PSXRECOMP_BIOS_STEMS lists every stem this build WOULD like. SCPH1001 is in
# the default list, but its generated C is a derivative of a copyrighted Sony
# BIOS, so it is gitignored and only exists once a developer regenerates it
# from their own dump. Requiring it unconditionally meant a fresh checkout --
# which legitimately has only the bundled MIT OpenBIOS -- failed every game
# link with "undefined reference to SCPH1001_psx_bios_backend", long after
# configure had succeeded. Filtering here keeps SCPH1001 fully supported for
# anyone who has regenerated it, without making it mandatory for everyone else.
set(PSXRECOMP_BIOS_GENERATED "")
set(_psxrt_registry_externs "")
set(_psxrt_registry_entries "")
set(_psxrt_bios_linked "")
set(_psxrt_bios_skipped "")
foreach(_stem IN LISTS PSXRECOMP_BIOS_STEMS)
list(APPEND PSXRECOMP_BIOS_GENERATED
${PSXRECOMP_ROOT}/generated/${_stem}_full.c
${PSXRECOMP_ROOT}/generated/${_stem}_dispatch.c)
string(APPEND _psxrt_registry_externs
"extern const PsxBiosBackend ${_stem}_psx_bios_backend;
# Presence is not enough: a generated/ tree left over from before the
# backend-descriptor mechanism has both files but defines no descriptor,
# which links fine at configure time and then fails at link with an
# undefined reference. Probe the descriptor itself. It is emitted into
# <stem>_dispatch.c (~1MB), never the multi-megabyte <stem>_full.c, so
# this scan stays cheap.
set(_psxrt_desc "")
if(EXISTS "${PSXRECOMP_ROOT}/generated/${_stem}_dispatch.c")
file(STRINGS "${PSXRECOMP_ROOT}/generated/${_stem}_dispatch.c" _psxrt_desc
REGEX "${_stem}_psx_bios_backend" LIMIT_COUNT 1)
endif()
if(EXISTS "${PSXRECOMP_ROOT}/generated/${_stem}_full.c" AND _psxrt_desc)
list(APPEND PSXRECOMP_BIOS_GENERATED
${PSXRECOMP_ROOT}/generated/${_stem}_full.c
${PSXRECOMP_ROOT}/generated/${_stem}_dispatch.c)
string(APPEND _psxrt_registry_externs
"extern const PsxBiosBackend ${_stem}_psx_bios_backend;
")
string(APPEND _psxrt_registry_entries
" &${_stem}_psx_bios_backend,
string(APPEND _psxrt_registry_entries
" &${_stem}_psx_bios_backend,
")
list(APPEND _psxrt_bios_linked "${_stem}")
else()
list(APPEND _psxrt_bios_skipped "${_stem}")
endif()
endforeach()
list(LENGTH PSXRECOMP_BIOS_STEMS _psxrt_bios_count)
if(_psxrt_bios_skipped)
message(STATUS
"BIOS backends skipped (generated C missing or predates the backend "
"descriptor): ${_psxrt_bios_skipped} -- regenerate with "
"tools/regen_bios.sh --config bios/<stem>.toml")
endif()
if(NOT _psxrt_bios_linked)
message(FATAL_ERROR
"No recompiled BIOS backend available. Wanted: ${PSXRECOMP_BIOS_STEMS}, "
"but no matching generated/<stem>_full.c + <stem>_dispatch.c were found "
"under ${PSXRECOMP_ROOT}/generated.\n"
"Generate at least one before building the runtime:\n"
" bash tools/regen_bios.sh --config bios/OpenBIOS.toml\n"
"(OpenBIOS is bundled and MIT-licensed, so this needs no BIOS dump.)")
endif()
message(STATUS "BIOS backends linked: ${_psxrt_bios_linked}")
list(LENGTH _psxrt_bios_linked _psxrt_bios_count)
# Registry of the compiled-in backends, in preference order. Generated so the
# stem list stays the single source of truth.