mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-27 10:38:46 -04:00
ff4be21c90
The v3.0 Japanese (SCPH-5500, 09/09/96) and US (SCPH-5501, 11/18/96) retail BIOS images join SCPH-1001, SCPH-101 and SCPH-5552, so every v3.0 region (J, A, E) has a profile. Both images match SCPH-1001 v2.2 byte for byte in the kernel, ROM [0x80, 0x18000). SCPH-5501's reset vector is identical too; SCPH-5500's differs in 24 bytes. The shell differs in both. So each profile is SCPH1001.toml with its own identity (name, id, rom, sha256 pin, stem): the copy windows and install slots are kernel properties and carry over unchanged. The shell runs through the dirty-RAM interpreter, as for SCPH5552. Each image gets its own seed list, derived by the same rule as phase2_ghidra_seeds_SCPH5552.json: the SCPH-1001 corpus filtered to seeds whose 64-byte ROM window is identical in both images (534 kept, 569 dropped), plus the two architectural vectors and 6 A0/B0/C0 kernel-table targets. The files carry only addresses, labels and rationales, plus the SHA-256 of both ROMs. - psx_bios_known_images.h: CRC-32 FF3EEB8C (SCPH-5500) and 8D8CB7E4 (SCPH-5501), both 512 KiB. A build that does not link these backends builds one from the player's own dump as a loadable module, like SCPH-5552, and the netplay lobby can name the image. - main_cli.cpp: map SCPH5500 / SCPH5501 dumps to their profiles. - build_cli.py: package both profiles with the CLI framework. - docs/BIOS_SELECTION.md: list them among the module-built images.
142 lines
6.7 KiB
TOML
142 lines
6.7 KiB
TOML
# bios/SCPH5501.toml — BIOS build profile for the retail Sony SCPH-5501 image
|
|
# (USA, v3.0 11/18/96).
|
|
#
|
|
# Compared byte for byte with the SCPH-1001 v2.2 image (bios/SCPH1001.toml):
|
|
# ROM [0x00000,0x00080) reset vector identical
|
|
# ROM [0x00080,0x18000) kernel identical
|
|
# ROM [0x18000,0x80000) shell differs
|
|
# So every kernel property below (copy windows, install slots) carries over
|
|
# unchanged. The seed list, recompiler/seeds/phase2_ghidra_seeds_SCPH5501.json,
|
|
# is the SCPH-1001 corpus filtered to seeds whose 64-byte window is identical
|
|
# in both ROMs, plus the architectural vectors and this ROM's own A0/B0/C0
|
|
# table targets (the same rule as phase2_ghidra_seeds_SCPH5552.json). The shell
|
|
# has no seeds of its own; it runs through the dirty-RAM interpreter (build
|
|
# with -DPSX_SHELLWIN_INTERP=ON), as for SCPH5552.
|
|
#
|
|
# One profile per BIOS image. Consumed by `psxrecomp-bios --config`, by
|
|
# tools/regen_bios.sh and by tools/bios_emitter_fingerprint.sh, as for
|
|
# SCPH1001.toml. The .BIN image itself stays untracked (bios/* gitignore rule).
|
|
|
|
[program]
|
|
name = "Sony SCPH-5501 BIOS (USA, v3.0 11/18/96)"
|
|
id = "SCPH-5501"
|
|
rom = "bios/SCPH5501.BIN"
|
|
load_address = "0xBFC00000"
|
|
entry_pc = "0xBFC00000"
|
|
text_size = "0x80000"
|
|
|
|
# Declared identity. The emitter refuses to generate from any other image
|
|
# (main_bios.cpp's declared-identity gate). SCPH-5501 v3.0: CRC32 8D8CB7E4,
|
|
# 512 KiB.
|
|
[program.image]
|
|
sha256 = "11052b6499e466bbf0a709b1f9cb6834a9418e66680387912451e971cf8a1fef"
|
|
license = "proprietary"
|
|
redistributable = false
|
|
|
|
[recompiler]
|
|
seeds = "recompiler/seeds/phase2_ghidra_seeds_SCPH5501.json"
|
|
out_dir = "generated"
|
|
out_stem = "SCPH5501"
|
|
strict = true
|
|
|
|
# The BIOS's boot-time bulk copies of CODE out of ROM into RAM. Single source
|
|
# of truth for every relocation window in the recompiler AND in the C it
|
|
# emits (the generated dispatch's normalize(), the kernel-bless guard, the
|
|
# game/shell-overlap tests). Each entry is a CLAIM that the copy is
|
|
# byte-verbatim; the runtime's kernel-bless memcmp enforces it for the
|
|
# bless window. All bounds are [lo, hi) with hi EXCLUSIVE.
|
|
#
|
|
# dispatch_key = "ram": functions in the window are keyed by RAM address
|
|
# (normalize folds ROM -> RAM).
|
|
# dispatch_key = "rom": functions keep their ROM key (normalize folds the
|
|
# RAM alias back to ROM).
|
|
[recompiler.address_model]
|
|
normalize_mask = "0x1FFFFFFF"
|
|
|
|
[[recompiler.address_model.copy]]
|
|
name = "Kernel Part 2"
|
|
rom_lo = "0x1FC10000"
|
|
rom_hi = "0x1FC18000"
|
|
ram_lo = "0x00000500"
|
|
runtime_base = "0x00000500" # KUSEG — the kernel executes uncached-region code cached at 0x500
|
|
dispatch_key = "ram"
|
|
kernel_bless = true
|
|
|
|
[[recompiler.address_model.copy]]
|
|
name = "Shell"
|
|
rom_lo = "0x1FC18000"
|
|
rom_hi = "0x1FC43000"
|
|
ram_lo = "0x00030000"
|
|
runtime_base = "0x80030000" # KSEG0 — LoadRunShell jumps to 0x80030000
|
|
dispatch_key = "rom"
|
|
kernel_bless = false
|
|
# NOTE (do not "fix" without evidence): runtime/src/bios_hle.c documents the
|
|
# actual LoadRunShell copy as 0x67FF0 bytes (ROM 0xBFC18000 -> RAM 0x30000..
|
|
# 0x97FF0). Every pre-profile window constant covered only 0x2B000 of that,
|
|
# and dirty_ram_interp.c tracks live RAM in [0x5B000,0x8F000) as an open
|
|
# class-B bug. Widening this window is a REAL BEHAVIOR CHANGE requiring its
|
|
# own evidence-backed commit — it is not a parameterization cleanup.
|
|
|
|
# Kernel-RAM RANGES the BIOS and the game's Psy-Q libapi patchers overwrite at
|
|
# runtime (CLAUDE.md rule 18; docs/dynamic_handler_install.md). The emitter
|
|
# plants a compare-against-ROM hook at each range start so the guest's patched
|
|
# instructions execute; the runtime excludes the range from the kernel-bless
|
|
# memcmp and resumes native at the range end, so only the patched words
|
|
# interpret.
|
|
#
|
|
# `resume` says how the compiled body picks up again: "jalr" for the classic
|
|
# 4-word lui/addiu/jalr/nop stub (the call returns to ram_addr+0x10),
|
|
# "fallthrough" when the patched words ARE the function, "none" when the patch
|
|
# jumps out and never comes back.
|
|
#
|
|
# Measured on a live boot of Breath of Fire III (SLPS-00990, Psy-Q SDK 3.70)
|
|
# against the ROM source, 30 s in, identical at t+8 s — the patchers are
|
|
# _patch_gte / _patch_card / _patch_card2 / _patch_pad. Every SDK title runs
|
|
# these, so the ranges are a property of the BIOS revision and libapi release,
|
|
# not of one game. Re-measure per SDK version before trusting the numbers:
|
|
# the schema tolerates declaring the union.
|
|
|
|
[[recompiler.install_slots]]
|
|
ram_addr = "0x00000C88" # exception handler: register-save prologue
|
|
len = "0x30" # shifted two words + an inserted mfc0 v0,Cause
|
|
resume = "fallthrough" # the patched words are the function itself
|
|
|
|
[[recompiler.install_slots]]
|
|
ram_addr = "0x00000CF0" # SIO data-byte handler dispatch slot
|
|
len = "0x10" # lui/addiu/jalr/nop over ROM zeros
|
|
resume = "jalr" # the stub's call returns to 0x0D00
|
|
|
|
[[recompiler.install_slots]]
|
|
ram_addr = "0x00004964" # pad driver clear routine, 11 words NOP'd
|
|
len = "0x2C" # (RemovePatchPad / ChgclrPAD family)
|
|
resume = "fallthrough"
|
|
|
|
[[recompiler.install_slots]]
|
|
ram_addr = "0x00004D98" # _patch_card2 payload: jalr into boot EXE
|
|
len = "0x14" # 0x8017EB6C; the ra landing word is NOP'd too,
|
|
resume = "fallthrough" # so the body resumes past it, not at +0x10
|
|
|
|
[[recompiler.install_slots]]
|
|
ram_addr = "0x00006444" # _patch_card payload: the kernel's card
|
|
len = "0x10" # handler replaced by jr into boot EXE
|
|
resume = "none" # 0x8017EAA0 — a jr never returns here
|
|
|
|
# NOT declared: RAM 0x0500, one word of kernel_trampoline_0 cleared to zero
|
|
# (ROM `lui t2, 0`). It differs on every boot, but what writes it is not yet
|
|
# identified, and a range declared on a guess would tell the bless verifier to
|
|
# stop checking a word it should be checking. Rule 14: unknown is acceptable,
|
|
# guessing is not. Undeclared means that body keeps interpreting, exactly as
|
|
# it does today.
|
|
|
|
# Per-image anchors couriered into the generated C (psx_bios_image) for the
|
|
# runtime HLE tier. Values are FACTS about this image, not tunables: the
|
|
# shell entry is where LoadRunShell (ROM 0xBFC06FF0) jumps after its copy;
|
|
# deliver_event_ret is the instruction after the kernel DeliverEvent loop's
|
|
# `jalr v0` (kernel RAM 0x1718), the $ra a delivered event callback returns
|
|
# through. Omit a key on a BIOS that has no such anchor — the runtime then
|
|
# treats that HLE feature as structurally unavailable instead of firing on a
|
|
# wrong address.
|
|
[recompiler.runtime_exports]
|
|
shell_entry_phys = "0x00030000"
|
|
deliver_event_ret = "0x80001720"
|