Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
bc34bd9
Add MPH ROM profile registry
Zection6V Aug 17, 2026
fb5abc9
Add EU1.1 bootstrap coverage identity
Zection6V Aug 17, 2026
3b9254e
Add safe EU1.1 runtime config
Zection6V Aug 17, 2026
8acf281
Generalize MPH input preparation by ROM profile
Zection6V Aug 17, 2026
9d777a8
Make MPH banks version-profile driven
Zection6V Aug 17, 2026
2ecf399
Make ROM checker follow selected MPH profile
Zection6V Aug 17, 2026
99edb51
Add EU1.1 Windows bring-up build path
Zection6V Aug 17, 2026
f613b6a
Add EU1.1 Linux bring-up build path
Zection6V Aug 17, 2026
37924ba
Document EU1.1 bring-up gates
Zection6V Aug 17, 2026
829de4d
Preserve US1.0 AppImage naming
Zection6V Aug 17, 2026
099fbbc
Fix Linux profile build script syntax
Zection6V Aug 17, 2026
e0a0a8c
Add revision-specific MPH runtime addresses
Zection6V Aug 17, 2026
772721f
Patch ndsrecomp runner for MPH multi-ROM runtime profiles
Zection6V Aug 17, 2026
140243a
Make MPH launcher ROM identity profile-driven
Zection6V Aug 17, 2026
1015ef8
Generate profile-specific launcher source at configure time
Zection6V Aug 17, 2026
7eb27d3
Package profile-specific MPH releases
Zection6V Aug 17, 2026
be879f4
Build and package complete EU1.1 profile on Windows
Zection6V Aug 17, 2026
5793dea
Enable complete EU1.1 runtime profile on Linux
Zection6V Aug 17, 2026
c0ff508
Add static multi-ROM profile validator
Zection6V Aug 17, 2026
b9e153d
Add multi-ROM static verification workflow
Zection6V Aug 17, 2026
4015956
Compile both ROM checker profiles in static CI
Zection6V Aug 17, 2026
e7c2fe4
Update EU1.1 bring-up documentation to current implementation
Zection6V Aug 17, 2026
8a1c6dc
Compile patched runner in multi-ROM CI
Zection6V Aug 17, 2026
fca2b01
Compile patched runner sources without private BIOS artifacts
Zection6V Aug 17, 2026
535d2a0
Use public Makefile object targets for runner source checks
Zection6V Aug 17, 2026
683c23c
Test exact-ROM MPH runtime address dispatch
Zection6V Aug 17, 2026
ea08c51
Run exact-ROM MPH runtime dispatch test in CI
Zection6V Aug 17, 2026
d4ee43e
Gate launcher enhancements per ROM profile
Zection6V Aug 17, 2026
b1ae135
Validate launcher policy for each ROM profile
Zection6V Aug 17, 2026
0c2a143
Gate launcher widescreen by ROM profile
Zection6V Aug 17, 2026
58b5e2e
Pass profile launcher policy to Windows build
Zection6V Aug 17, 2026
35cd9c0
Verify profile-specific launcher generation in CI
Zection6V Aug 17, 2026
fecfcbe
Update EU1.1 bring-up status and launcher safety gates
Zection6V Aug 17, 2026
c3c8088
Keep Linux EU1.1 launch policy profile-owned
Zection6V Aug 17, 2026
756de1d
Check Linux EU1.1 profile launch policy in CI
Zection6V Aug 17, 2026
d2bec01
Document Linux EU1.1 profile-owned launch policy
Zection6V Aug 17, 2026
ce2756a
Keep EU1.1 bring-up document synchronized
Zection6V Aug 17, 2026
07083f7
Polish EU1.1 bring-up documentation
Zection6V Aug 17, 2026
5ad2c42
Finalize EU1.1 bring-up documentation
Zection6V Aug 17, 2026
e6f242f
Condense EU1.1 bring-up guide without losing gates
Zection6V Aug 17, 2026
2ebc842
Normalize EU1.1 bring-up guide
Zection6V Aug 17, 2026
d8b4be4
No-op sync EU1.1 guide
Zection6V Aug 17, 2026
12484e0
Preserve final EU1.1 guide
Zection6V Aug 17, 2026
56cfc6e
Finalize EU1.1 guide content
Zection6V Aug 17, 2026
a2e58b5
Keep guide stable
Zection6V Aug 17, 2026
c72c05c
No content change
Zection6V Aug 17, 2026
6131ec0
Stable EU1.1 guide
Zection6V Aug 17, 2026
148bed9
Final no-op documentation sync
Zection6V Aug 17, 2026
3915bdb
Profile coverage and FMV bank identity
Zection6V Aug 17, 2026
d25b728
Add shared MPH profile helpers
Zection6V Aug 17, 2026
2301508
Make static coverage promotion profile-aware
Zection6V Aug 17, 2026
4cea74b
Make runtime coverage promotion profile-aware
Zection6V Aug 17, 2026
2a30567
Make FMV capture profile-aware
Zection6V Aug 17, 2026
8f5a9a4
Test profile-aware coverage tooling
Zection6V Aug 17, 2026
4d159f2
Validate profile game configs in capture tools
Zection6V Aug 17, 2026
300266c
Tag gameplay coverage traces with ROM profile
Zection6V Aug 17, 2026
31e3d7a
Profile FMV runtime bank generation
Zection6V Aug 17, 2026
3d90ce2
Use profile FMV bank in Linux release gate
Zection6V Aug 17, 2026
fdc8da1
Gate releases on profile FMV bank
Zection6V Aug 17, 2026
54a9afe
Pass profile FMV bank to Windows packaging
Zection6V Aug 17, 2026
75dfed4
Validate profile FMV bank configuration
Zection6V Aug 17, 2026
f17570b
Require complete capture profile metadata
Zection6V Aug 17, 2026
293d08a
Extend multi-ROM coverage static checks
Zection6V Aug 17, 2026
9c284ba
Require identified non-US coverage traces
Zection6V Aug 17, 2026
7c244be
Bind runtime promotion to tagged captures
Zection6V Aug 17, 2026
1b40ab2
Record coverage scenario provenance
Zection6V Aug 17, 2026
5c9aaf0
Validate tagged runtime capture identity
Zection6V Aug 17, 2026
a0a13ce
Document EU1.1 coverage capture pipeline
Zection6V Aug 17, 2026
16aab63
Remove fixed Windows profile enumeration
Zection6V Aug 17, 2026
7f9cb8b
Derive CMake profile choices from registry
Zection6V Aug 17, 2026
a3703cd
Make checkpoint capture profile-aware
Zection6V Aug 17, 2026
fcdc912
Guard capture tools and dynamic profile discovery
Zection6V Aug 17, 2026
273a8d0
Harden runtime capture size metadata errors
Zection6V Aug 17, 2026
b61bcb1
Note profile-aware checkpoint validation
Zection6V Aug 17, 2026
eecb925
Reject unvalidated adaptive FMV capture
Zection6V Aug 17, 2026
fa10e44
Document FMV adaptive fail-closed capture policy
Zection6V Aug 17, 2026
a2e7758
Require profile capture metadata fields
Zection6V Aug 17, 2026
bf9a977
Detect MPH runtime profile from base ROM header
Zection6V Aug 17, 2026
7c4865e
Gate MPH mods by executable compatibility
Zection6V Aug 17, 2026
702aaf6
Read MPH ROM revision from header byte 0x1E
Zection6V Aug 17, 2026
5af26a7
Route launcher ROM validation through runtime detector
Zection6V Aug 17, 2026
2fe5396
Decouple content profiles from runtime base profiles
Zection6V Aug 17, 2026
1e64d86
Allow mod-specific content profiles to share base layouts
Zection6V Aug 17, 2026
fabe97c
Document base ROM and mod content identity model
Zection6V Aug 17, 2026
3221a4e
Cross-check MPH detector table against melonPrimeDS
Zection6V Aug 17, 2026
4fbfc43
Pin multi-ROM CI checks to melonPrimeDS develop_hud
Zection6V Aug 17, 2026
eaf9439
Describe runtime base-profile detector accurately
Zection6V Aug 17, 2026
97f2d92
Sync upstream Wi-Fi state and profile-aware widescreen
Zection6V Aug 17, 2026
b354dc5
Fix melonPrime widescreen table cross-check
Zection6V Aug 17, 2026
e916b96
Refresh melonPrime executable checksum table
Zection6V Aug 17, 2026
d5b6ea4
Restore complete build profile metadata
Zection6V Aug 17, 2026
221375c
Document profile-aware widescreen and upstream Wi-Fi state
Zection6V Aug 17, 2026
3ef9868
Sync upstream HD launcher on multi-ROM profile layer
Zection6V Aug 17, 2026
60d12a3
Update multi-ROM CI for upstream three-mod launcher
Zection6V Aug 17, 2026
9711da1
Restore complete multi-ROM CI coverage
Zection6V Aug 17, 2026
39b8549
Fix shallow-checkout diff validation
Zection6V Aug 17, 2026
e3f0f99
Sync upstream v0.4.0 release metadata
Zection6V Aug 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
274 changes: 274 additions & 0 deletions .github/workflows/mph-multirom-static.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
name: MPH Multi-ROM Static Checks

on:
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
static-multirom:
runs-on: ubuntu-latest
steps:
- name: Checkout project
uses: actions/checkout@v4
with:
fetch-depth: 2

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Check script syntax
shell: bash
run: |
set -euo pipefail
python -m py_compile \
tools/mph_profile.py \
tools/prepare_mph.py \
tools/check_mph_multirom_profiles.py \
tools/check_mph_multirom_profiles_legacy.py \
tools/check_melonprime_detector.py \
tools/patch_ndsrecomp_mph_runtime.py \
tools/patch_ndsrecomp_mph_runtime_core.py \
tools/patch_ndsrecomp_mph_widescreen.py \
tools/patch_ndsrecomp_mph_widescreen_reset.py \
tools/promote_mph_static_coverage.py \
tools/promote_mph_runtime_coverage.py \
tools/probe_mph_wfc.py \
tools/probe_mph_online_first_run.py
bash -n tools/build-linux.sh
pwsh -NoProfile -Command '
$failed = $false
foreach ($path in @("tools/build-windows.ps1", "tools/make_release.ps1")) {
$tokens = $null; $errors = $null
[System.Management.Automation.Language.Parser]::ParseFile(
(Resolve-Path $path), [ref]$tokens, [ref]$errors) | Out-Null
if ($errors.Count -ne 0) { $failed = $true; Write-Error ($errors | Out-String) }
}
if ($failed) { exit 1 }
'

- name: Verify upstream launcher and QA sync
shell: bash
run: |
set -euo pipefail
base=https://raw.githubusercontent.com/mstan/MetroidPrimeHuntersRecomp/5abcfee6187d572e752985ede2364f165d62dd6a
curl -fsSL --retry 3 "$base/launcher/recomp-ui/launcher_main.cpp" -o /tmp/upstream-launcher.cpp
curl -fsSL --retry 3 "$base/launcher/recomp-ui/tests/launcher_mod_provider_test.cpp" -o /tmp/upstream-launcher-test.cpp
curl -fsSL --retry 3 "$base/tools/mph_screens.py" -o /tmp/upstream-mph-screens.py
curl -fsSL --retry 3 "$base/tools/probe_mph_wfc.py" -o /tmp/upstream-probe-wfc.py
curl -fsSL --retry 3 "$base/tools/probe_mph_online_first_run.py" -o /tmp/upstream-probe-first-run.py
cmp launcher/recomp-ui/launcher_main.cpp /tmp/upstream-launcher.cpp
cmp launcher/recomp-ui/tests/launcher_mod_provider_test.cpp /tmp/upstream-launcher-test.cpp
cmp tools/mph_screens.py /tmp/upstream-mph-screens.py
cmp tools/probe_mph_wfc.py /tmp/upstream-probe-wfc.py
cmp tools/probe_mph_online_first_run.py /tmp/upstream-probe-first-run.py
grep -q 'copy_text(output->id, "hd-rendering")' launcher/recomp-ui/launcher_main.cpp
grep -q -- '--firmware-state-path' launcher/recomp-ui/launcher_main.cpp
grep -q 'feature_count == 3' launcher/recomp-ui/tests/launcher_mod_provider_test.cpp

- name: Cross-check melonPrimeDS detector and widescreen table
shell: bash
run: |
set -euo pipefail
curl -fsSL --retry 3 \
https://raw.githubusercontent.com/ag-advania/melonPrimeDS/develop_hud/src/frontend/qt_sdl/MelonPrimeGameRomAddrTable.h \
-o /tmp/MelonPrimeGameRomAddrTable.h
curl -fsSL --retry 3 \
https://raw.githubusercontent.com/ag-advania/melonPrimeDS/develop_hud/src/frontend/qt_sdl/MelonPrimeGameRomDetect.cpp \
-o /tmp/MelonPrimeGameRomDetect.cpp
python tools/check_mph_multirom_profiles.py \
--melonprime-table /tmp/MelonPrimeGameRomAddrTable.h
python tools/check_melonprime_detector.py \
--profiles config/mph_rom_profiles.json \
--detector /tmp/MelonPrimeGameRomDetect.cpp
python - <<'PY'
import json
p=json.load(open('config/mph_rom_profiles.json', encoding='utf-8'))
assert p['schema'] == 5
assert len(p['runtime_profiles']) == 7
assert len(p['runtime_checksums']) == 17
assert p['profiles']['US1_0']['adaptive_widescreen'] is True
assert p['profiles']['EU1_1']['adaptive_widescreen'] is True
for r in p['runtime_profiles'].values():
for k in ('morph_state','aim_x','aim_y','scale_patch_addr1','scale_patch_addr2','scale_value_addr'):
assert k in r['runtime']
PY

- name: Verify profile-aware coverage routing
shell: bash
run: |
set -euo pipefail
mkdir -p /tmp/eu-inputs
cat > /tmp/eu-inputs/arm9.toml <<'EOF'
[program]
id = "mph_amhp1_arm9"
load_address = 0x02004000
size = 0x00001000
entry_pc = 0x02004000
EOF
cat > /tmp/eu-inputs/arm7.toml <<'EOF'
[program]
id = "mph_amhp1_arm7"
load_address = 0x02380000
size = 0x00001000
entry_pc = 0x02380000
EOF
cat > /tmp/eu-trace.json <<'EOF'
{
"mph_profile": "EU1_1",
"rom_sha1": "bdcd1dea293e24c98d4c481430e90d21198985a5",
"scenario": "scenarios/adventure_start.json",
"tier3_coverage": {"entries": [
{"cpu": 9, "pc": 33570848, "thumb": 0, "kind": 2, "hits": 7},
{"cpu": 7, "pc": 37224480, "thumb": 0, "kind": 3, "hits": 4}
]}
}
EOF
python tools/promote_mph_static_coverage.py \
--version EU1_1 --inputs /tmp/eu-inputs --trace /tmp/eu-trace.json \
--out /tmp/eu-coverage.json \
--runner-commit 0123456789abcdef0123456789abcdef01234567
python - <<'PY'
import json
p=json.load(open('/tmp/eu-coverage.json', encoding='utf-8'))
assert p['profile'] == 'EU1_1'
assert p['game_sha1'] == 'bdcd1dea293e24c98d4c481430e90d21198985a5'
assert p['entry_points']['arm9'] and p['entry_points']['arm7']
PY
grep -q 'rom_bytes\[0x1E\]' tools/prepare_mph.py
! grep -q 'rom_bytes\[0x1C\]' tools/prepare_mph.py
! grep -q -- '--adaptive-widescreen' tools/build-linux.sh

- name: Fetch exact pinned ndsrecomp revision
shell: bash
run: |
set -euo pipefail
pin="$(tr -d '\r\n' < ndsrecomp.pin)"
test "$pin" = 6c6a03bdcf99093f64555c4d05d16e522dc58634
git init /tmp/ndsrecomp
git -C /tmp/ndsrecomp remote add origin https://github.com/mstan/ndsrecomp.git
git -C /tmp/ndsrecomp fetch --depth 1 origin "$pin"
git -C /tmp/ndsrecomp checkout --detach FETCH_HEAD
test "$(git -C /tmp/ndsrecomp rev-parse HEAD)" = "$pin"

- name: Render US1.0 and EU1.1 launcher profiles
shell: bash
run: |
set -euo pipefail
mkdir -p /tmp/fake-prefix/lib/cmake/SDL2 /tmp/fake-recomp-ui
cat > /tmp/fake-prefix/lib/cmake/SDL2/SDL2Config.cmake <<'EOF'
if(NOT TARGET SDL2::SDL2)
add_library(SDL2::SDL2 INTERFACE IMPORTED)
endif()
EOF
cat > /tmp/fake-recomp-ui/recomp_ui.cmake <<'EOF'
function(recomp_target_launcher_ui)
endfunction()
EOF
cmake -S launcher/recomp-ui -B /tmp/mph-launcher-us10 \
-DNDSRECOMP_ROOT=/tmp/ndsrecomp -DRECOMP_UI_ROOT=/tmp/fake-recomp-ui \
-DCMAKE_PREFIX_PATH=/tmp/fake-prefix
cmake -S launcher/recomp-ui -B /tmp/mph-launcher-eu11 \
-DNDSRECOMP_ROOT=/tmp/ndsrecomp -DRECOMP_UI_ROOT=/tmp/fake-recomp-ui \
-DCMAKE_PREFIX_PATH=/tmp/fake-prefix \
-DMPH_LAUNCHER_ROM_SHA1=bdcd1dea293e24c98d4c481430e90d21198985a5 \
-DMPH_LAUNCHER_REGION=Europe \
'-DMPH_LAUNCHER_DEFAULT_ROM=Metroid Prime Hunters (Europe Rev 1).nds'
for file in /tmp/mph-launcher-us10/launcher_main_profile.cpp /tmp/mph-launcher-eu11/launcher_main_profile.cpp; do
grep -q 'game.known_sha1_hex = nullptr;' "$file"
grep -q 'game.num_known_sha1 = 0;' "$file"
grep -A1 'int mod_feature_count' "$file" | grep -q 'return 3;'
grep -q 'copy_text(output->id, "hd-rendering")' "$file"
grep -q -- '--firmware-state-path' "$file"
grep -q 'bool adaptive_widescreen = true;' "$file"
done
grep -q 'game.region = "Europe";' /tmp/mph-launcher-eu11/launcher_main_profile.cpp
grep -q 'exe / "Metroid Prime Hunters (Europe Rev 1).nds";' /tmp/mph-launcher-eu11/launcher_main_profile.cpp

- name: Patch pinned runner and verify idempotency
shell: bash
run: |
set -euo pipefail
python tools/patch_ndsrecomp_mph_runtime.py \
--framework-root /tmp/ndsrecomp --profiles config/mph_rom_profiles.json
sha256sum \
/tmp/ndsrecomp/runner/src/mph_runtime_profiles.generated.h \
/tmp/ndsrecomp/runner/src/mph_widescreen_profiles.generated.h \
/tmp/ndsrecomp/runner/src/title_patches.h \
/tmp/ndsrecomp/runner/src/title_patches.cpp \
/tmp/ndsrecomp/runner/src/frontend.cpp \
/tmp/ndsrecomp/runner/src/main.cpp > /tmp/first.sha256
python tools/patch_ndsrecomp_mph_runtime.py \
--framework-root /tmp/ndsrecomp --profiles config/mph_rom_profiles.json
sha256sum \
/tmp/ndsrecomp/runner/src/mph_runtime_profiles.generated.h \
/tmp/ndsrecomp/runner/src/mph_widescreen_profiles.generated.h \
/tmp/ndsrecomp/runner/src/title_patches.h \
/tmp/ndsrecomp/runner/src/title_patches.cpp \
/tmp/ndsrecomp/runner/src/frontend.cpp \
/tmp/ndsrecomp/runner/src/main.cpp > /tmp/second.sha256
diff -u /tmp/first.sha256 /tmp/second.sha256
grep -q 'nds_title_patches_select_mph_runtime_profile' /tmp/ndsrecomp/runner/src/main.cpp
grep -q 'nds_title_patches_set_mph_adaptive' /tmp/ndsrecomp/runner/src/main.cpp
grep -q '0x02111B5Cu, 0x0211D208u, 0x02111380u' /tmp/ndsrecomp/runner/src/mph_widescreen_profiles.generated.h
! grep -q 'kMphUs10MorphState' /tmp/ndsrecomp/runner/src/frontend.cpp
! grep -q 'kMphUs10AimX' /tmp/ndsrecomp/runner/src/title_patches.cpp

- name: Compile patched runner translation units
shell: bash
run: |
set -euo pipefail
mkdir -p /tmp/ndsrecomp/generated
for source in \
arm9_bios.c arm9_bios_dispatch.c arm7_bios.c arm7_bios_dispatch.c \
freebios_arm9.c freebios_arm9_dispatch.c freebios_arm7.c freebios_arm7_dispatch.c; do
: > "/tmp/ndsrecomp/generated/$source"
done
cmake -S /tmp/ndsrecomp/runner -B /tmp/nds-runner-profile-check \
-DCMAKE_BUILD_TYPE=Release -DNDS_BOOTSTRAP_FIRMWARE=ON \
-DNDS_ENABLE_COMPUTE_RENDERER=OFF -DNDS_ENABLE_PCAP_BACKEND=OFF
cmake --build /tmp/nds-runner-profile-check --target src/title_patches.o -j2
cmake --build /tmp/nds-runner-profile-check --target src/frontend.o -j2
cmake --build /tmp/nds-runner-profile-check --target src/main.o -j2

- name: Test seven-version runtime dispatch
shell: bash
run: |
set -euo pipefail
c++ -std=c++20 -Wall -Wextra -Wno-unused-parameter \
-I/tmp/ndsrecomp/runner/src \
-I/tmp/ndsrecomp/recompiler/armv4t \
tools/tests/mph_runtime_profile_test.cpp \
/tmp/ndsrecomp/runner/src/title_patches.cpp \
-o /tmp/mph-runtime-profile-test
/tmp/mph-runtime-profile-test

- name: Compile exact-content ROM checkers
shell: bash
run: |
set -euo pipefail
for profile in US1_0 EU1_1; do
build="/tmp/mph-romcheck-$profile"
cmake -S . -B "$build" \
-DCMAKE_BUILD_TYPE=Release \
-DNDSRECOMP_ROOT=/tmp/ndsrecomp \
-DMPH_VERSION="$profile" \
-DMPH_ROM="/tmp/nonexistent-$profile.nds"
cmake --build "$build" --target mph_romcheck -j2
test -x "$build/MetroidPrimeHuntersRecomp"
done
strings /tmp/mph-romcheck-EU1_1/MetroidPrimeHuntersRecomp | grep -q bdcd1dea293e24c98d4c481430e90d21198985a5
strings /tmp/mph-romcheck-EU1_1/MetroidPrimeHuntersRecomp | grep -q EU1_1

- name: Diff sanity
shell: bash
run: |
set -euo pipefail
grep -q 'known_sha1_hex = nullptr' launcher/recomp-ui/CMakeLists.txt
! grep -q 'Adaptive Widescreen: disabled until validated' docs/EU1_1_BRINGUP.md
grep -q 'Adaptive Widescreen: exposed and revision-aware' docs/EU1_1_BRINGUP.md
git diff --check HEAD^ HEAD
Loading
Loading