mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
60919f5a87
Bundled releases link OpenBIOS only; retail-BIOS-derived C never ships.
"Bring your own BIOS" now works without it: when a dump matching a shipped
profile (psx_bios_known_images.h) is selected, the runtime builds that
backend on the player's machine with the overlay toolchain the release
already carries, caches it, and loads it as one more registered backend.
- runtime/include/psx_bios_module.h: the module contract. An overlay-style
self-contained shared library (no imports from the executable) exporting
psx_bios_module_{abi,codegen_hash,init,backend}; reaches the runtime only
through OverlayCallbacks plus a new PsxBiosModuleCallbacks table (traps,
dirty-RAM/kernel-bless probes, fntrace, log_probe) and pointer aliases of
the globals the generated dispatcher touches. Its #defines rewrite the
emitter's own extern lines, so the generated C compiles unchanged.
- runtime/include/psx_bios_module_glue.c.inc: module-side forwarders and the
four exports, compiled after overlay_dispatch_preamble.c.inc.
- runtime/src/psx_bios_module.c: host side. Cache path
<exe>/cache/bios/<os-arch>/bm<abi>_<codegen hash>_f<flavor>/<STEM>_<crc>,
ABI + codegen-hash gated load, callback fill, and a blocking build via
overlay_toolchain/bios_module_build.py (gcc via compiler.txt or PATH,
else tcc), then psx_bios_register().
- psx_bios_backend.c: the registry is now a mutable table seeded from the
CMake-generated psx_bios_builtin_registry by a constructor, with
psx_bios_register(); every existing walker keeps working.
- main.cpp: validate_bios_for_launch acquires a module (announcing a first
build) before declaring a mismatch; discovery accepts a buildable dump;
the launcher verify reports it usable ("ready" / "compiled on first
launch") with no Generate & rebuild; the BIOS row shows whenever the
toolchain is present; bundled_only respects module support.
- emitter: the CPS-marker constructor is not emitted in a module build.
- overlay_api.h: OverlayCallbacks gains a struct tag;
overlay_loader_callbacks() exposes the host table before loader init.
- tools/bios_module_build.py (ships in the toolchain): identity + profile
SHA-256 gate, staged emitter tree, emit, three-TU compile, ctypes
self-check, atomic publish. release_stage.py stages psxrecomp-bios, every
bios/*.toml, the seeds and the builder into overlay_toolchain/.
- Tests: runtime/tests/test_bios_module_host.c against three fake modules
(good / wrong ABI / wrong hash) on real dlopen; recompiler/tests/
test_bios_module_build.py builds the bundled OpenBIOS end to end and reads
the descriptor back; guards extended.
Verified on Twisted Metal 4 (bundled build + staged toolchain, headless):
first launch with --bios SCPH1001.BIN builds and loads the module and boots
on image=SCPH-1001; the second launch loads it from cache.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
106 lines
4.3 KiB
C
106 lines
4.3 KiB
C
/* psx_bios_backend.h — the routing seam between the runtime and whichever
|
|
* recompiled BIOS is active.
|
|
*
|
|
* Every build links more than one recompiled BIOS (bundled OpenBIOS plus a
|
|
* retail image). Each one exports exactly ONE symbol — its backend descriptor,
|
|
* named <STEM>_psx_bios_backend — and everything else it defines is either
|
|
* static or stem-prefixed, so the images cannot collide at link time.
|
|
*
|
|
* The runtime picks a backend at startup (docs/BIOS_SELECTION.md: no explicit
|
|
* player choice -> OpenBIOS; an explicit, identity-matching choice -> that
|
|
* image) and publishes it as psx_bios_active.
|
|
*
|
|
* Callers do not go through this struct. The unprefixed psx_dispatch() /
|
|
* psx_dispatch_call() the game's generated C and the runtime already call are
|
|
* thin forwarders (psx_bios_backend.c) that route to the active backend, and
|
|
* psx_bios_image is assigned from it at selection time — so adding a second
|
|
* BIOS changed no call sites.
|
|
*
|
|
* Adding another BIOS later is one more descriptor and one more registry
|
|
* entry; it is not another round of symbol collisions.
|
|
*/
|
|
#ifndef PSX_BIOS_BACKEND_H
|
|
#define PSX_BIOS_BACKEND_H
|
|
|
|
#include <stdint.h>
|
|
|
|
#include "psx_bios_image.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
struct CPUState;
|
|
|
|
typedef struct PsxBiosBackend {
|
|
/* Identity, kernel-bless window and HLE anchors for this image. Copied
|
|
* into the global psx_bios_image when this backend is selected. */
|
|
const PsxBiosImageInfo *image;
|
|
|
|
/* Dispatch entry points for this image. */
|
|
void (*dispatch)(struct CPUState *cpu, uint32_t addr);
|
|
void (*dispatch_call)(struct CPUState *cpu, uint32_t addr,
|
|
uint32_t return_addr);
|
|
|
|
/* Kernel body-extent table used by the kernel-image bless mechanism
|
|
* (memory.c). Published as psx_bios_kernel_bodies/_count on selection.
|
|
*
|
|
* The native call-stub table is deliberately absent: it is only read by
|
|
* the generated dispatch itself, so it stays static there. */
|
|
const PsxKernelBody *kernel_bodies;
|
|
uint32_t kernel_body_count;
|
|
|
|
/* Kernel-RAM ranges the guest legitimately patches at runtime, from this
|
|
* image's [[recompiler.install_slots]] (psx_bios_image.h). The bless
|
|
* verifier skips them and the dirty-RAM interpreter resumes native at
|
|
* each range's hi. Null/0 for an image that declares no slots. */
|
|
const PsxKernelPatchRange *kernel_patch_ranges;
|
|
uint32_t kernel_patch_range_count;
|
|
} PsxBiosBackend;
|
|
|
|
/* Dispatch nesting depth, shared by every backend (psx_bios_backend.c). */
|
|
extern int g_psx_dispatch_depth;
|
|
|
|
/* The backend in use. Null before psx_bios_select() runs; every forwarder and
|
|
* every consumer of psx_bios_image depends on it being set first. */
|
|
extern const PsxBiosBackend *psx_bios_active;
|
|
|
|
/* Backends compiled into this binary, in preference order (bundled OpenBIOS
|
|
* first). Emitted by the build as psx_bios_registry.c. */
|
|
extern const PsxBiosBackend *const psx_bios_builtin_registry[];
|
|
extern const uint32_t psx_bios_builtin_registry_count;
|
|
|
|
/* The live registry: the builtins plus any backend registered at run time
|
|
* (a BIOS module built from the player's dump, psx_bios_module.h). Walk it
|
|
* only after psx_bios_registry_seeded_count() or any lookup below has run;
|
|
* the count is 0 until then in a process that never looked. */
|
|
extern const PsxBiosBackend *psx_bios_registry[];
|
|
extern uint32_t psx_bios_registry_count;
|
|
uint32_t psx_bios_registry_seeded_count(void);
|
|
|
|
/* Add a backend loaded at run time. Idempotent for a pointer already present;
|
|
* 0 when the table is full or the descriptor has no image. */
|
|
int psx_bios_register(const PsxBiosBackend *backend);
|
|
|
|
/* Look up a compiled-in backend by its profile id ("SCPH-1001", "OPENBIOS").
|
|
* Null if this build does not carry it. */
|
|
const PsxBiosBackend *psx_bios_find(const char *image_id);
|
|
|
|
/* Select a backend and publish it (also assigns the global psx_bios_image).
|
|
* Returns 0 if backend is null. */
|
|
int psx_bios_activate(const PsxBiosBackend *backend);
|
|
|
|
/* The bundled, redistributable backend (image_bundled != 0), or null if this
|
|
* build has none. */
|
|
const PsxBiosBackend *psx_bios_bundled(void);
|
|
|
|
/* True if a player-supplied image is meaningful for this build (some linked
|
|
* backend is not the bundled one). */
|
|
int psx_bios_has_selectable(void);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* PSX_BIOS_BACKEND_H */
|