From 4bf868da4fd761f34d2fb95e751a7a46ac09d30c Mon Sep 17 00:00:00 2001 From: Matthew Stanley <1379tech@gmail.com> Date: Sat, 25 Jul 2026 18:11:57 -0700 Subject: [PATCH] feat(bios): ship OpenBIOS as a runtime dependency --- README.md | 35 ++++++++++++++------------- RELEASE_NOTES.md | 20 +++++++++------- THIRD_PARTY_ATTRIBUTION.md | 7 +++--- docs/BIOS_SELECTION.md | 10 ++++++-- docs/BUILDING.md | 48 ++++++++++++++++++++------------------ docs/config_schema.md | 9 +++---- runtime/CMakeLists.txt | 1 + runtime/runtime.cmake | 46 ++++++++++++++++++++++++++++++++++++ tools/package_release.ps1 | 39 +++++++++++++++++++++---------- 9 files changed, 145 insertions(+), 70 deletions(-) diff --git a/README.md b/README.md index d21116fa..c36f8a8a 100644 --- a/README.md +++ b/README.md @@ -286,16 +286,18 @@ release from the [Games](#games) table. 3. It boots on the bundled OpenBIOS. To use your own dump instead, pick it in settings. -The package includes OpenBIOS but no retail PS1 BIOS, game disc image, generated -game code, or save data. If you choose your own BIOS, that path is remembered -next to the executable as `bios.cfg`; clear the choice (or delete that file) to -go back to OpenBIOS. +The package includes `bios/openbios.bin` and its MIT notice at +`bios/OpenBIOS.LICENSE`, but no retail PS1 BIOS, game disc image, generated game +code, or save data. If you choose your own BIOS, that path is remembered next +to the executable as `bios.cfg`; clear the choice (or delete that file) to go +back to OpenBIOS. The game recomp projects use the same runtime picker contract but ship a -**Dear ImGui launcher**: on first run it prompts for your legally obtained BIOS -and game disc image, then lets you configure video, controls, and per-game -settings before launching. Keyboard/controller mappings live in each game's repo -and launcher, not here. +**Dear ImGui launcher**: on first run it asks for the game disc image and uses +OpenBIOS automatically. The optional BIOS row lets you select your own verified +retail dump or clear that choice to return to OpenBIOS. The launcher also +configures video, controls, and per-game settings. Keyboard/controller mappings +live in each game's repo and launcher, not here. ## Setup @@ -322,7 +324,7 @@ Build the framework (recompiler tool + BIOS-only runtime): git clone --recurse-submodules https://github.com/mstan/psxrecomp.git && cd psxrecomp cmake -S recompiler -B recompiler/build -G Ninja -DCMAKE_BUILD_TYPE=Release && cmake --build recompiler/build -cmake -S runtime -B runtime/build -G Ninja -DCMAKE_BUILD_TYPE=Release && cmake --build runtime/build --target psx-runtime +cmake -S runtime -B runtime/build -G Ninja -DCMAKE_BUILD_TYPE=Release -DPSX_RECOMP_UI=OFF && cmake --build runtime/build --target psx-runtime ``` On Windows swap `-G Ninja` for your generator if you prefer (e.g. @@ -425,13 +427,14 @@ discussion happens in the **R.A.I.D.** Discord (invite below). PolyForm Noncommercial 1.0.0. See `LICENSE`. -The PSX BIOS and game disc images remain copyrighted by their respective -owners. This project distributes no BIOS images, no disc images, and no -game assets — those are always supplied by the user from their own -collection. Release executables (and per-game overlay caches) contain -statically recompiled (machine-translated) builds of the original code, -the same distribution model used by other static recompilation projects -such as N64: Recompiled. +Retail PS1 BIOS images and game disc images remain copyrighted by their +respective owners and are not distributed. This project does distribute the +from-scratch, MIT-licensed OpenBIOS image under the notice in +[`bios/OpenBIOS.LICENSE`](bios/OpenBIOS.LICENSE). Game assets and disc data are +always supplied by the user from their own collection. Release executables (and +per-game overlay caches) contain statically recompiled (machine-translated) +builds of the original code, the same distribution model used by other static +recompilation projects such as N64: Recompiled. --- diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4837695b..942b1ae9 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,17 +1,19 @@ -# PSXRecomp v0.1.0-alpha +# PSXRecomp OpenBIOS integration -Initial public BIOS-only framework release package. +OpenBIOS is now a first-class, redistributable runtime backend. Highlights: - Packages the PSXRecomp v4 BIOS runtime as `PSXRecomp.exe`. -- Prompts for a user-provided `SCPH1001.BIN` BIOS on first launch. -- Saves the selected BIOS path in `bios.cfg` next to the executable. +- Bundles PCSX-Redux OpenBIOS and its MIT notice. +- Uses OpenBIOS when the player has not explicitly selected another BIOS. +- Keeps a verified, user-provided `SCPH1001.BIN` as an optional runtime choice. +- Lets launcher users clear a retail selection and return to OpenBIOS. +- Prevents savestates created under one BIOS from loading under the other. - Adds Xbox-style controller support through SDL/XInput. - Adds configurable controller mapping via `input.ini`. -- Includes the recent Tomba-driven renderer/runtime fixes for the BIOS logo, - menu text seams, dialog/pause panel seams, terrain shading, and shaded - textured primitives. +- Includes the load-delay ownership fix validated in Tomba!, plus OpenBIOS + smoke coverage in Ape Escape, Tomba! 2, and Mega Man X6. -This package does not include a PS1 BIOS, game disc image, generated game code, -save data, or copyrighted Sony/game assets. +This package does not include a retail PS1 BIOS, game disc image, generated game +code, save data, or copyrighted Sony/game assets. diff --git a/THIRD_PARTY_ATTRIBUTION.md b/THIRD_PARTY_ATTRIBUTION.md index a693f1a6..b57d5f90 100644 --- a/THIRD_PARTY_ATTRIBUTION.md +++ b/THIRD_PARTY_ATTRIBUTION.md @@ -1,6 +1,6 @@ # Third-Party Attribution -## OpenBIOS — PCSX-Redux's free PS1 BIOS (optional recompilation target) +## OpenBIOS — PCSX-Redux's free PS1 BIOS [OpenBIOS](https://github.com/grumpycoders/pcsx-redux) (src/mips/openbios) by the PCSX-Redux authors, licensed **MIT** (notice: `bios/OpenBIOS.LICENSE`; @@ -9,9 +9,8 @@ the binary also links permissively-licensed code from as the prebuilt image `bios/openbios.bin` (pin and build recipe recorded in `bios/OpenBIOS.toml`) and statically recompiled by `psxrecomp-bios --config bios/OpenBIOS.toml` exactly like the retail BIOS. -Because MIT permits redistribution, a game verified against OpenBIOS can ship -it with the build (`[program.image] redistributable = true`) so players supply -only a disc; `bios/OpenBIOS.LICENSE` must ride along with the shipped image. +Normal runtime builds stage it automatically so players supply only a disc; +`bios/OpenBIOS.LICENSE` always rides alongside the shipped image. ## sljit — stack-less JIT compiler (Tier-2 in-process overlay backend) diff --git a/docs/BIOS_SELECTION.md b/docs/BIOS_SELECTION.md index f2913607..372e366c 100644 --- a/docs/BIOS_SELECTION.md +++ b/docs/BIOS_SELECTION.md @@ -6,8 +6,10 @@ allowed to redistribute — so a player can be handed a build and a disc image a just play. A player who prefers their own dumped retail BIOS can use that instead. -Both BIOSes are compiled into every build. Which one runs is decided when the -game launches, not when it is built. +Both recompiled BIOS backends are linked into every normal build. The OpenBIOS +image itself and its MIT notice are staged in `bios/` beside the executable; +the retail image is never shipped and comes from the player. Which backend runs +is decided when the game launches, not when it is built. ## The rule @@ -110,5 +112,9 @@ with the upstream source pin and build recipe in `bios/OpenBIOS.toml` and attribution in `THIRD_PARTY_ATTRIBUTION.md`. Builds that ship it credit the PCSX-Redux authors in the launcher, whether or not the licence compels it. +Native runtime builds automatically stage both `bios/openbios.bin` and +`bios/OpenBIOS.LICENSE`. Release packaging must copy that directory as a unit; +shipping the image without its notice violates the distribution contract. + Retail BIOS images are **not** redistributable and are never shipped. A player using one supplies their own dump. diff --git a/docs/BUILDING.md b/docs/BUILDING.md index 9007f106..d19ad07a 100644 --- a/docs/BUILDING.md +++ b/docs/BUILDING.md @@ -10,7 +10,7 @@ Silicon & Intel), and **Linux**. There are two things you can build: For the retail **`SCPH1001.BIN` BIOS** you supply your own dump; the MIT-licensed **OpenBIOS** alternative is bundled (`bios/openbios.bin`, see -[Selecting the BIOS to recompile](#selecting-the-bios-to-recompile)). For a +[Regenerating BIOS backends](#regenerating-bios-backends)). For a game you always supply your own legally-obtained **disc image** — this project ships no game data. @@ -77,14 +77,15 @@ Two CMake trees: the recompiler (a tool) and the runtime (the engine). cmake -S recompiler -B recompiler/build -G Ninja -DCMAKE_BUILD_TYPE=Release cmake --build recompiler/build -# 2. (Optional) regenerate the BIOS C from your SCPH1001.BIN -# Requires bios/SCPH1001.BIN to be present. To target the bundled -# OpenBIOS instead: --config bios/OpenBIOS.toml (see "Selecting the -# BIOS to recompile" below). -bash tools/regen_bios.sh +# 2. (Optional) regenerate either statically recompiled BIOS backend. +# OpenBIOS can always be regenerated from the tracked image. Regenerating +# the retail backend requires your own bios/SCPH1001.BIN dump. +bash tools/regen_bios.sh --config bios/OpenBIOS.toml +bash tools/regen_bios.sh --config bios/SCPH1001.toml # 3. Runtime → produces psx-runtime (BIOS-only for this repo) -cmake -S runtime -B runtime/build -G Ninja -DCMAKE_BUILD_TYPE=Release +cmake -S runtime -B runtime/build -G Ninja -DCMAKE_BUILD_TYPE=Release \ + -DPSX_RECOMP_UI=OFF cmake --build runtime/build --target psx-runtime ``` @@ -197,28 +198,29 @@ pack beside the repo at `../sdl2-msvc/SDL2-*`. Use the MSYS2/MinGW toolchain for the `gcc` tier; otherwise areas stay in the interpreter. See [`EXECUTION_MODEL.md`](EXECUTION_MODEL.md). -## Selecting the BIOS to recompile +## Regenerating BIOS backends -The runtime links exactly one statically recompiled BIOS (generated symbols -collide across images), chosen at configure time: +Every normal runtime links both statically recompiled BIOS backends. OpenBIOS +symbols and retail SCPH-1001 symbols are namespaced so they coexist in one +executable; the active backend is selected at launch: ```bash -# Retail SCPH1001 (default; user supplies the dump at first launch) -tools/regen_bios.sh # == --config bios/SCPH1001.toml -cmake -B build ... # PSXRECOMP_BIOS_STEM defaults to SCPH1001 - -# OpenBIOS (redistributable; ships with the game, player supplies only a disc) +# OpenBIOS (tracked and redistributable) tools/regen_bios.sh --config bios/OpenBIOS.toml -cmake -B build -DPSXRECOMP_BIOS_STEM=OpenBIOS \ - -DPSXRECOMP_BIOS_PROFILE=$PWD/bios/OpenBIOS.toml ... + +# Retail SCPH-1001 (requires your own local dump) +tools/regen_bios.sh --config bios/SCPH1001.toml ``` -Game repos set `DEFAULT_BIOS_PATH` (psxrecomp_add_runtime_target) to the -image the profile names, and `[recompiler] bios_config` in game.toml so game -codegen folds BIOS-copy RAM aliases through the same profile. Per-title -compatibility is NOT implied: verify a title on the target BIOS in a -reference emulator before switching its build (the identity gate refuses a -mismatched image at launch either way). +`PSXRECOMP_BIOS_STEMS` defaults to `OpenBIOS;SCPH1001`. The runtime build +automatically stages `bios/openbios.bin` and `bios/OpenBIOS.LICENSE` beside +every native executable. A release packager must copy that `bios/` directory +unchanged. + +At runtime, no explicit player choice means OpenBIOS. A retail BIOS selected +with the launcher, `settings.toml`, or `--bios` wins after its exact identity is +verified. `[runtime] openbios = false` is reserved for a title with a verified +OpenBIOS incompatibility. See [`BIOS_SELECTION.md`](BIOS_SELECTION.md). OpenBIOS seeds come from its ELF symbol tables (no Ghidra pass needed): see the pin + regeneration recipe in `bios/OpenBIOS.toml`. diff --git a/docs/config_schema.md b/docs/config_schema.md index 3359e7f3..c1f87191 100644 --- a/docs/config_schema.md +++ b/docs/config_schema.md @@ -250,15 +250,16 @@ These are noted here so future work knows where to slot them: One profile per BIOS image; the profile is the single source of truth for the image identity, the relocation windows, and the runtime anchors. Two ship: `bios/SCPH1001.toml` (retail; user supplies the dump) and `bios/OpenBIOS.toml` -(MIT, redistributable, shipped with the build). Selected at configure time: -`-DPSXRECOMP_BIOS_STEM= -DPSXRECOMP_BIOS_PROFILE=`, and per game -by `[recompiler] bios_config` in game.toml. +(MIT, redistributable, shipped with the build). Normal runtimes link both +generated backends (`PSXRECOMP_BIOS_STEMS=OpenBIOS;SCPH1001`) and select one at +launch. The recompiler's `[recompiler] bios_config` identifies the profile used +for game code generation; it does not choose the player's runtime BIOS. ```toml [program.image] # identity; recompiler refuses a mismatched ROM sha256 = "..." # pins the exact image (empty = unchecked) redistributable = false # true: BIOS ships with the game; runtime hides - # the whole BIOS-selection surface + # any requirement to provide that image [recompiler.address_model] # boot-time bulk code copies out of ROM normalize_mask = "0x1FFFFFFF" diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 9a253320..70918bc8 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -30,6 +30,7 @@ psxrecomp_add_runtime_target(psx-runtime DEBUG_PORT 4370 WINDOW_TITLE "psxrecomp - BIOS" DEFAULT_BIOS_PATH "${PSXRECOMP_ROOT}/bios/SCPH1001.BIN" + EXE_NAME "PSXRecomp" ) if(BUILD_TESTING) diff --git a/runtime/runtime.cmake b/runtime/runtime.cmake index 636370b9..7f236609 100644 --- a/runtime/runtime.cmake +++ b/runtime/runtime.cmake @@ -262,6 +262,10 @@ endif() # cross-checking them, and it linked cleanly when they disagreed. set(PSXRECOMP_BUNDLED_BIOS_PATH "bios/openbios.bin" CACHE STRING "Bundled redistributable BIOS image, relative to the executable") +set(PSXRECOMP_BUNDLED_BIOS_SOURCE "${PSXRECOMP_ROOT}/bios/openbios.bin" CACHE FILEPATH + "Source image copied into native runtime builds as the bundled BIOS") +set(PSXRECOMP_BUNDLED_BIOS_LICENSE "${PSXRECOMP_ROOT}/bios/OpenBIOS.LICENSE" CACHE FILEPATH + "License notice copied alongside the bundled BIOS") set(PSXRECOMP_BIOS_STEMS "OpenBIOS;SCPH1001" CACHE STRING "Recompiled BIOS stems to link (first bundled/redistributable one is the default at runtime)") # The profile is still needed as the staleness-stamp input for the primary stem. @@ -619,6 +623,48 @@ function(psxrecomp_add_runtime_target target) $<$:SDL_MAIN_HANDLED> ) + # OpenBIOS is part of the native runtime product, not a developer-machine + # prerequisite. Stage both the exact ROM consumed by the compiled backend + # and its required MIT notice beside every native executable. Release + # packagers copy this directory as a unit. + if(NOT PSXRT_ORACLE) + list(FIND PSXRECOMP_BIOS_STEMS "OpenBIOS" _psxrt_openbios_index) + if(NOT _psxrt_openbios_index EQUAL -1) + if(NOT EXISTS "${PSXRECOMP_BUNDLED_BIOS_SOURCE}") + message(FATAL_ERROR + "Bundled OpenBIOS image is missing: " + "${PSXRECOMP_BUNDLED_BIOS_SOURCE}") + endif() + if(NOT EXISTS "${PSXRECOMP_BUNDLED_BIOS_LICENSE}") + message(FATAL_ERROR + "Bundled OpenBIOS license is missing: " + "${PSXRECOMP_BUNDLED_BIOS_LICENSE}") + endif() + get_filename_component( + _psxrt_bundled_bios_dir + "${PSXRECOMP_BUNDLED_BIOS_PATH}" + DIRECTORY) + get_filename_component( + _psxrt_bundled_bios_license_name + "${PSXRECOMP_BUNDLED_BIOS_LICENSE}" + NAME) + add_custom_command(TARGET ${target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory + "$/${_psxrt_bundled_bios_dir}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${PSXRECOMP_BUNDLED_BIOS_SOURCE}" + "$/${PSXRECOMP_BUNDLED_BIOS_PATH}" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${PSXRECOMP_BUNDLED_BIOS_LICENSE}" + "$/${_psxrt_bundled_bios_dir}/${_psxrt_bundled_bios_license_name}" + COMMENT "Staging bundled OpenBIOS image and MIT notice" + VERBATIM) + set_property(TARGET ${target} APPEND PROPERTY LINK_DEPENDS + "${PSXRECOMP_BUNDLED_BIOS_SOURCE}" + "${PSXRECOMP_BUNDLED_BIOS_LICENSE}") + endif() + endif() + if(PSXRT_ORACLE) target_compile_definitions(${target} PRIVATE PSX_ORACLE_BUILD=1) else() diff --git a/tools/package_release.ps1 b/tools/package_release.ps1 index 6e0d1612..9e0871de 100644 --- a/tools/package_release.ps1 +++ b/tools/package_release.ps1 @@ -14,7 +14,10 @@ $MingwBin = "C:\msys64\mingw64\bin" $env:PATH = "$MingwBin;$env:PATH" -cmake -S (Join-Path $Root "runtime") -B $BuildPath -G Ninja -DCMAKE_BUILD_TYPE=Release -DPSX_DEBUG_TOOLS=OFF +cmake -S (Join-Path $Root "runtime") -B $BuildPath -G Ninja ` + -DCMAKE_BUILD_TYPE=Release ` + -DPSX_DEBUG_TOOLS=OFF ` + -DPSX_RECOMP_UI=OFF cmake --build $BuildPath --target psx-runtime -j $env:NUMBER_OF_PROCESSORS if (Test-Path $StageRoot) { @@ -23,16 +26,18 @@ if (Test-Path $StageRoot) { New-Item -ItemType Directory -Force $Stage | Out-Null New-Item -ItemType Directory -Force (Join-Path $Stage "saves") | Out-Null -Copy-Item (Join-Path $BuildPath "psx-runtime.exe") (Join-Path $Stage "PSXRecomp.exe") +Copy-Item (Join-Path $BuildPath "PSXRecomp.exe") (Join-Path $Stage "PSXRecomp.exe") Copy-Item (Join-Path $Root "README.md") $Stage Copy-Item (Join-Path $Root "LICENSE") $Stage +Copy-Item -Recurse -Force (Join-Path $BuildPath "bios") (Join-Path $Stage "bios") +Copy-Item (Join-Path $Root "THIRD_PARTY_ATTRIBUTION.md") $Stage if (Test-Path (Join-Path $Root "RELEASE_NOTES.md")) { Copy-Item (Join-Path $Root "RELEASE_NOTES.md") $Stage } # The Release build is statically linked (PSX_STATIC_RUNTIME defaults ON for # MinGW Release in runtime.cmake), so the exe imports ONLY Windows system DLLs -# — no SDL2.dll / libgcc_s_seh-1.dll / libstdc++-6.dll to bundle. Shipping +# so there is no SDL2.dll / libgcc_s_seh-1.dll / libstdc++-6.dll to bundle. Shipping # those side-by-side was the cause of the 0xc000007b launch crash on user # machines that had a mismatched copy earlier on the DLL search path. # @@ -47,7 +52,7 @@ $systemDlls = @("kernel32.dll","user32.dll","gdi32.dll","shell32.dll","msvcrt.dl "dinput8.dll","rpcrt4.dll","hid.dll","cfgmgr32.dll") $nonSystem = $imports | Where-Object { $systemDlls -notcontains $_.ToLower() } if ($nonSystem) { - throw "Release exe is NOT self-contained — imports non-system DLL(s): $($nonSystem -join ', ')" + throw "Release exe is NOT self-contained; imports non-system DLL(s): $($nonSystem -join ', ')" } Write-Host "Verified self-contained: imports only system DLLs ($($imports.Count) total)" @@ -58,11 +63,13 @@ $exeBytes = [System.IO.File]::ReadAllBytes((Join-Path $Stage "PSXRecomp.exe")) $exeText = [System.Text.Encoding]::ASCII.GetString($exeBytes) $bakedBios = [regex]::Matches($exeText, '[A-Za-z]:[/\\][ -~]*?SCPH1001\.BIN') | ForEach-Object { $_.Value } | Select-Object -Unique if ($bakedBios) { - throw "Release exe contains baked absolute BIOS path(s): $($bakedBios -join '; ') — build with a relative DEFAULT_BIOS_PATH" + throw "Release exe contains baked absolute BIOS path(s): $($bakedBios -join '; '); build with a relative DEFAULT_BIOS_PATH" } Write-Host "Verified no baked absolute BIOS path in the exe" -# No user-machine or copyrighted files may ride along in the stage. +# No user-machine or copyrighted files may ride along in the stage. OpenBIOS +# is intentionally present and redistributable; retail SCPH images remain +# forbidden. $strayPatterns = @("SCPH*.BIN","*.cue","*.iso","*.mcd","bios.cfg","disc.cfg", "settings.toml","keybinds.ini","overlay_captures.json") $stray = foreach ($pat in $strayPatterns) { Get-ChildItem $Stage -Recurse -File -Filter $pat -ErrorAction SilentlyContinue } @@ -73,7 +80,14 @@ $savesFiles = Get-ChildItem (Join-Path $Stage "saves") -Recurse -File -ErrorActi if ($savesFiles) { throw "Stage saves/ directory must be empty, contains: $(($savesFiles | ForEach-Object FullName) -join '; ')" } -Write-Host "Verified stage carries no BIOS/disc/save/sidecar files" +$bundledBios = Join-Path $Stage "bios/openbios.bin" +$bundledLicense = Join-Path $Stage "bios/OpenBIOS.LICENSE" +if (!(Test-Path $bundledBios) -or + (Get-Item $bundledBios).Length -ne 524288 -or + !(Test-Path $bundledLicense)) { + throw "Stage must contain the 512 KiB OpenBIOS image and its MIT notice" +} +Write-Host "Verified bundled OpenBIOS + notice; no retail BIOS/disc/save/sidecar files" @" ; PSXRecomp input mapping. PSX buttons are active when any listed source is pressed. @@ -108,15 +122,16 @@ select = back @" PSXRecomp $Version -This package does not include a PlayStation BIOS, game disc image, generated -game source, save data, or any copyrighted Sony/game assets. +This package includes the MIT-licensed OpenBIOS from PCSX-Redux. Its notice is +in bios/OpenBIOS.LICENSE. It does not include a retail PlayStation BIOS, game +disc image, generated game source, save data, or copyrighted Sony/game assets. First launch: 1. Run PSXRecomp.exe. -2. Select your legally obtained SCPH1001.BIN BIOS when prompted. +2. OpenBIOS runs by default. No external BIOS is required. -The selected BIOS path is saved in bios.cfg next to the executable. Delete that -file if you want to pick a different BIOS later. +You can select your legally obtained SCPH1001.BIN instead. The selected path is +saved in bios.cfg next to the executable; clear it to return to OpenBIOS. This framework package is BIOS-only. Game-specific PSXRecomp releases use the same BIOS picker and additionally prompt for the required game disc image.