From 9be6364a5b1cb18db6c2033b9885f7e499ea78fd Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:06:03 -0600 Subject: [PATCH] =?UTF-8?q?feat(phase-33):=20B2=20portable=20includes=20?= =?UTF-8?q?=E2=80=94=2034=20absolute=20#include=20lines=20in=2019=20overla?= =?UTF-8?q?y=20sources=20(15=20binaries)=20respelled=20to=20../shared/=20(?= =?UTF-8?q?30=20engine=5Fcore.h=20+=204=20engine=5Ftypes.h);=20audit=5Ftex?= =?UTF-8?q?t=5Fsources.py=20gains=20the=20portable-include=20class=20(abso?= =?UTF-8?q?lute=20/=20angle-bracket=20/=20unresolvable=20/=20outside-repo)?= =?UTF-8?q?,=20controls=2034=20offenders=20before=20->=200=20after=20over?= =?UTF-8?q?=204,299=20sources;=20the=2015=20binaries=20re-gated=20byte-ide?= =?UTF-8?q?ntical=20(15/15=20OK,=2029=20s=20wall);=20SETUP=20P33=20B2=20(R?= =?UTF-8?q?21)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/SETUP.md | 10 ++++ phase-ends/CURRENT_PHASE.md | 41 +++++++------ src/ov_SC02_000/ov_SC02_000_jr_8018173C.c | 2 +- src/ov_SC02_000/ov_SC02_000_jr_80187B40.c | 2 +- src/ov_SC02_011/ov_SC02_011_jr_80183178.c | 4 +- src/ov_SC02_011/ov_SC02_011_jr_80188E3C.c | 8 +-- src/ov_SC02_016/ov_SC02_016_jr_8017DC70.c | 2 +- src/ov_SC02_016/ov_SC02_016_jr_801810C8.c | 2 +- src/ov_SC02_017/ov_SC02_017_jr_8017DF34.c | 6 +- src/ov_SC02_026/ov_SC02_026_jr_8017C180.c | 6 +- src/ov_SC02_039/ov_SC02_039_jr_8017BEBC.c | 2 +- src/ov_SC03_001/ov_SC03_001_jr_8017AE2C.c | 2 +- src/ov_SC03_006/ov_SC03_006_jr_8017AE2C.c | 2 +- src/ov_SC03_091/ov_SC03_091_jr_80182268.c | 2 +- src/ov_SC03_105/ov_SC03_105_jr_80186DDC.c | 2 +- src/ov_SC04_018/ov_SC04_018_jr_8017AE2C.c | 2 +- src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c | 12 ++-- src/ov_SC05_010/ov_SC05_010_jr_80181CDC.c | 2 +- src/ov_SC06_000/ov_SC06_000_jr_8017AE2C.c | 2 +- src/ov_SC06_029/ov_SC06_029_jr_801867D0.c | 2 +- src/ov_SC06_029/ov_SC06_029_jr_801898CC.c | 6 +- tools/audit_text_sources.py | 70 +++++++++++++++++++---- 22 files changed, 129 insertions(+), 60 deletions(-) diff --git a/docs/SETUP.md b/docs/SETUP.md index 6070d3234d..dda3ad767d 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -1069,6 +1069,16 @@ fills fast). Nothing is leaking — but the host does not get the memory back on * `gate_main` **REFUSES a draft containing its own `INCLUDE_ASM`** (substituting it restores the stub, so the build passes for free and the function counts as banked), and counts banks from the SOURCE. +### P33 B2 (S86, 2026-09-06) — portable includes, audited +- 34 lines in 19 `src/ov_*/…_jr_*.c` files (15 binaries) carried `#include "/home/musashi/bfm-decomp/src/shared/ + engine_core.h"` (30) / `engine_types.h` (4) — the absolute spelling the jr-isolation tooling once wrote; byte-neutral + here, a hard build failure on any other machine. Respelled to the tree's own `../shared/…` form (3,978 prior uses) and + each of the 15 binaries re-gated (`make extract BINARY= && make check BINARY=`). +- `tools/audit_text_sources.py` (in `tools-health`) gained the **portable-include class**: an absolute path, an + angle-bracket include (no system/SDK header is on the include path — the build's only include path is `-Iinclude`), + or a quoted include that resolves to no file / outside the repo is an offender. R39 controls: 34 offenders in 19 files + before the fix (all ABSOLUTE), 0 after; 4,299 sources scanned (the coverage line, R32). + ### P33 B1 (S86, 2026-09-06) — `make disc-extract`: the rom→decoder step, promoted into the build - **`make disc-extract`** (`DISC_DIR ?= disks`): the repository ships no ROM bytes (H1 in force). The target (1) probes `extracted/retail/` against the committed oracle (`extract.py --verify`, **0.7 s** when up to date → no-op), else (2) diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md index a33a167565..700f74ca22 100644 --- a/phase-ends/CURRENT_PHASE.md +++ b/phase-ends/CURRENT_PHASE.md @@ -51,7 +51,7 @@ one-time snapshot, `CLAUDE.md` gains "never `git clean -x`" (R20 amendment propo - [x] **A4** `tools/family_hseq.py` regen — Low (became an instrument fix: the map now carries its own coverage) — see Log - [x] **B1** `make disc-extract` (extract.py `--expect-manifest` / `--allow-missing-audio`; check-env; `.gitignore` re-tightened; the 4 splat preset headers tracked; `clean` fixed) — Max — see Log 2026-09-06 B1 -- [ ] **B2** 34 absolute includes → `../shared/` + portable-include audit + 15-binary re-gate — xHigh +- [x] **B2** 34 absolute includes → `../shared/` + portable-include audit + 15-binary re-gate — xHigh — see Log 2026-09-06 B2 - [ ] **B3** `tools/bootstrap.sh` / `make bootstrap` + check-env extensions + fresh-clone proof 218/218 — xHigh - [ ] **B4** `tools/fetch_psyq.sh` + CHECKSUMS rows (20 lib40 LIBs, psyq-obj-parser) BEFORE `tools/psyq/` leaves git — xHigh - [ ] **B5** Ghidra regenerability (ExportAnnotations/ImportAnnotations/ghidra_rebuild.sh `--proof` on SLUS_007.26 + @@ -142,18 +142,25 @@ Mid-phase rules check after every 4 completed tasks (P6). Commit banked artifact tree IDENTICAL for all 1,801 retail files; second run "up to date" in 0.7 s; `make check-env` OK with the new PASS lines. Slip, recorded: the previous tree also held `extracted/proto/` (the two prototype EXEs from the prototype discs, not the retail one) and I removed the moved-aside copy in the same command as the diff — regenerated from `disks/` with - `tools/bfm_extract/extract_proto_exe.py` (see the next line). + `tools/bfm_extract/extract_proto_exe.py` (sep8 413,696 B sha1 `43006a31…`, aug31 415,744 B sha1 `6150b0f8…`). Commit + `commit:4016`. +- **2026-09-06 (S86) — B2 (portable includes).** `tools/audit_text_sources.py` gained the portable-include class (absolute / + angle-bracket / unresolvable / outside-repo `#include`); positive control BEFORE the fix: 34 offenders in 19 files, all + ABSOLUTE (4,299 sources scanned); the sed → `../shared/engine_core.h` ×30 + `../shared/engine_types.h` ×4; + `grep -rn /home/musashi src include` → 0; negative control → OK. Re-gate of the 15 binaries (derived from the diff, 5 in + parallel): 15/15 `[ OK ]` BYTE-IDENTICAL in 29 s wall (`.run/P33/b2_gate/.log`). SETUP: P33 B2 section (R21). -## 🛑 SESSION CHECKPOINT — A1–A4 ✓, B1 ✓; NEXT = B2 (the 34 absolute includes + the portable-include audit + 15-binary re-gate, xHigh) (2026-09-06, written by session bd19e14a "S86"; SUPERSEDES the earlier blocks) +## 🛑 SESSION CHECKPOINT — A1–A4 ✓, B1 ✓, B2 ✓; NEXT = B3 (`tools/bootstrap.sh` + `make bootstrap` + check-env extensions + the fresh-clone proof, xHigh) (2026-09-06, written by session bd19e14a "S86"; SUPERSEDES the earlier blocks) ### 0. How to use this block You are a FRESH SESSION that has read `PROJECT_CONTEXT.md`, `phase-ends/DIGEST.md`, `PhaseEnd_Phase30/31/32.md` and this file, and nothing else (R64). Replay this block verbatim, state phase / done / NEXT / effort, list the rules from the digest -(R1–R73), then WAIT for Drew. **NEXT = B2** (xHigh: the 34 absolute `#include "/home/musashi/bfm-decomp/src/shared/…"` -lines in 19 `src/ov_*/…_jr_*.c` files across 15 binaries → `../shared/`; extend `tools/audit_text_sources.py` with a -portability class; controls 34 → 0; re-gate the 15 binaries with `make extract BINARY= && make check BINARY=`). -If `git log -1 --format=%s` does not start with `feat(phase-33): B1`, B1's commit did not land: re-run `make disc-extract` -(expect "up to date" in ~1 s) and `make check-env` (OK) before committing. +(R1–R73), then WAIT for Drew. **NEXT = B3** (xHigh: `tools/bootstrap.sh` / `make bootstrap` — apt presence check, venv + +requirements, submodules, cc1 tarball checksums + untar, `make check-env`; check-env gains submodule state, the 4 tracked +headers, disc/extracted state; the fresh-clone proof: `git clone --no-local` into `.run/P33/fresh/` → bootstrap → disc +symlinked → `make disc-extract && make extract-all && make check-all` → 218/218). If `git log -1 --format=%s` does not start +with `feat(phase-33): B2`, B2's commit did not land: `tools/audit_text_sources.py` must print OK and the 15 gate logs under +`.run/P33/b2_gate/` must each say BYTE-IDENTICAL before committing. ### 1. Where we are **Phase 33 — 100% verification + the public flip + Gen2 exit.** Gate 1 approved 2026-09-06 (plan mode, Max). R65–R73 ratified at @@ -222,14 +229,16 @@ items can be cut). Harness tasks: #1 A1 done, #2 A2 done, #3 A3 next … #41 G2. ### 3. NEXT — in order 0. **Preflight:** `git status --short | grep -v ghidra/` (empty) · `git log -1 --format='%h %s'` · `df -h ~` (≈13 GB free) · `.venv/bin/python -c 'import splat'` · `ls build/us/SLUS_007.26.map` (main is built; `make check BINARY=main` if not). -1. **B2** (xHigh): `grep -rl '#include "/home/musashi/bfm-decomp/src/shared/' src | xargs sed -i 's|#include - "/home/musashi/bfm-decomp/src/shared/|#include "../shared/|'`; `grep -rn '/home/musashi' src include` must print nothing; - `tools/audit_text_sources.py` gains the portability class (absolute, `<…>`, outside-repo includes are offenders; run it - BEFORE the sed → exactly 34 offenders in 19 files, AFTER → 0); re-gate the 15 binaries: `for b in ov_SC02_000 ov_SC02_011 - ov_SC02_016 ov_SC02_017 ov_SC02_026 ov_SC02_039 ov_SC03_001 ov_SC03_006 ov_SC03_091 ov_SC03_105 ov_SC04_018 ov_SC05_003 - ov_SC05_010 ov_SC06_000 ov_SC06_029; do make extract BINARY=$b && make -j8 check BINARY=$b || exit 1; done` (derive the - list from the grep, do not trust this one). Commit "feat(phase-33): B2 …". -2. Then B3 → B4 → B5 (MCP stopped) → B6 → B7 → B8 → A5 → B9/C3 … per the task list. After every task: tick the box, +1. **B3** (xHigh) per the plan's Block B: `tools/bootstrap.sh` (idempotent; prints the apt line for missing packages from + SETUP §4.3, no sudo; `python3 -m venv .venv && .venv/bin/pip install -r requirements-python.txt`; `git submodule update + --init`; `sha256sum --check tools/bin/CHECKSUMS.sha256` then `tar xzf` each cc1 tarball into `tools/bin/gcc-2.7.2-{psx,cdk}/` + unless `cc1` exists; `make check-env`), `make bootstrap`; check-env additions (submodule gitlinks populated, the 4 tracked + headers present, extracted/ state). Proof = the "stranger with their own dump" criterion: `git clone --no-local ~/bfm-decomp + .run/P33/fresh` → `tools/bootstrap.sh` → `ln -s ~/bfm-decomp/disks .run/P33/fresh/disks` → `make disc-extract && make + extract-all && make check-all` in the clone → `check-all: 218 passed, 0 failed of 218`. Disk: the clone + its extracted/ + + build ≈ 3 GB (13 GB free); delete `.run/P33/fresh` afterwards. NOTE the clone's HEAD still tracks the EXE and the + purge paths until C3 — that is fine for the proof (the EXE arrives from git AND from disc-extract, same bytes). +2. Then B4 → B5 (MCP stopped) → B6 → B7 → B8 → A5 → B9/C3 … per the task list. After every task: tick the box, add a Log line, refresh this checkpoint block (the 🛑 block is the ONLY in-phase context the next session inherits), commit. Next P6 rules check after B4 (8 tasks done). `extracted/proto/` (sep8 + aug31 EXEs) is regenerated from the prototype discs by `tools/bfm_extract/extract_proto_exe.py` (docstring examples) — B5 needs both files. diff --git a/src/ov_SC02_000/ov_SC02_000_jr_8018173C.c b/src/ov_SC02_000/ov_SC02_000_jr_8018173C.c index c5edcee303..4f8724ae8a 100644 --- a/src/ov_SC02_000/ov_SC02_000_jr_8018173C.c +++ b/src/ov_SC02_000/ov_SC02_000_jr_8018173C.c @@ -5336,7 +5336,7 @@ void func_801863AC(void *a0) { DEFINE_func_801863E8() /* dedup: shared engine-core @0x801863E8 (src/shared) */ #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" DEFINE_func_80186424() /* dedup: shared engine-core @0x80186424 (src/shared) */ diff --git a/src/ov_SC02_000/ov_SC02_000_jr_80187B40.c b/src/ov_SC02_000/ov_SC02_000_jr_80187B40.c index 58e8097c4c..c6a34fd148 100644 --- a/src/ov_SC02_000/ov_SC02_000_jr_80187B40.c +++ b/src/ov_SC02_000/ov_SC02_000_jr_80187B40.c @@ -4280,7 +4280,7 @@ void func_80189A70(s32 *a0) #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" typedef struct { s16 start; diff --git a/src/ov_SC02_011/ov_SC02_011_jr_80183178.c b/src/ov_SC02_011/ov_SC02_011_jr_80183178.c index 9a156065cb..b17bcd9897 100644 --- a/src/ov_SC02_011/ov_SC02_011_jr_80183178.c +++ b/src/ov_SC02_011/ov_SC02_011_jr_80183178.c @@ -3918,7 +3918,7 @@ void func_801883EC(s32 a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" void func_80188430(s32 a0) { extern s32 func_80133784(s32 a0, void *a1, s32 a2); @@ -3971,7 +3971,7 @@ void func_80188508(s32 a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern s32 rand(void); extern s32 func_8012B744(void *a0, void *a1); diff --git a/src/ov_SC02_011/ov_SC02_011_jr_80188E3C.c b/src/ov_SC02_011/ov_SC02_011_jr_80188E3C.c index a7064b0be0..2933c8b07d 100644 --- a/src/ov_SC02_011/ov_SC02_011_jr_80188E3C.c +++ b/src/ov_SC02_011/ov_SC02_011_jr_80188E3C.c @@ -127,7 +127,7 @@ void func_80189050(s32 param_1) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern s16 D_801960CC; extern s16 D_801960CE; @@ -1003,7 +1003,7 @@ void func_8018A2C0(s32 param_1) } -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" /* match_one-only: gives MATRIX/SVECTOR; the real TU already includes this */ +#include "../shared/engine_core.h" /* match_one-only: gives MATRIX/SVECTOR; the real TU already includes this */ extern s32 func_80012C6C(s32 a0, s32 a1, s32 a2); extern s32 func_80012ABC(s32 a0, s32 a1, s32 a2); @@ -3919,7 +3919,7 @@ u8 * func_8018D820(s32 a0, s32 a1, s32 a2) { } -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" /* match_one-only: gives Mat32_8018A390_8018FE94; the real TU already includes this */ +#include "../shared/engine_core.h" /* match_one-only: gives Mat32_8018A390_8018FE94; the real TU already includes this */ extern u16 D_80126CB4; extern u16 D_80126CB6; @@ -4205,7 +4205,7 @@ s32 func_8018DDD0(s32 a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern s32 func_80133784(s32 a0, void *a1, s32 a2); extern s32 func_80134510(s32 arg); diff --git a/src/ov_SC02_016/ov_SC02_016_jr_8017DC70.c b/src/ov_SC02_016/ov_SC02_016_jr_8017DC70.c index 346ca731d7..31b710bff5 100644 --- a/src/ov_SC02_016/ov_SC02_016_jr_8017DC70.c +++ b/src/ov_SC02_016/ov_SC02_016_jr_8017DC70.c @@ -3562,7 +3562,7 @@ void func_8017F33C(void *a0) } -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern u16 D_80126B5E; extern u16 D_80126B62; diff --git a/src/ov_SC02_016/ov_SC02_016_jr_801810C8.c b/src/ov_SC02_016/ov_SC02_016_jr_801810C8.c index ee14854d66..1625fdcffd 100644 --- a/src/ov_SC02_016/ov_SC02_016_jr_801810C8.c +++ b/src/ov_SC02_016/ov_SC02_016_jr_801810C8.c @@ -3020,7 +3020,7 @@ void func_801814A8(s32 a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern s16 D_8018864C; extern s16 D_8018864E; diff --git a/src/ov_SC02_017/ov_SC02_017_jr_8017DF34.c b/src/ov_SC02_017/ov_SC02_017_jr_8017DF34.c index 4a1a5c584a..40fcd025f1 100644 --- a/src/ov_SC02_017/ov_SC02_017_jr_8017DF34.c +++ b/src/ov_SC02_017/ov_SC02_017_jr_8017DF34.c @@ -6533,7 +6533,7 @@ void func_80183790(s32 param_1) #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" /* neighbour func_80187D80 (same TU) uses SV3 in/out + func_8012F214 with the same call convention; house style adopted here (§tu_ref). */ @@ -8516,7 +8516,7 @@ u8 *a0; #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern s32 func_80133784(s32 a0, void *a1, s32 a2); extern void func_8012B23C(s32 a0); @@ -8579,7 +8579,7 @@ void func_8018626C(s32 a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern s32 rand(void); extern s32 func_8012B744(void *a0, void *a1); diff --git a/src/ov_SC02_026/ov_SC02_026_jr_8017C180.c b/src/ov_SC02_026/ov_SC02_026_jr_8017C180.c index 2b0de2f1f2..c2d70a1c43 100644 --- a/src/ov_SC02_026/ov_SC02_026_jr_8017C180.c +++ b/src/ov_SC02_026/ov_SC02_026_jr_8017C180.c @@ -6760,7 +6760,7 @@ s32 func_80182318_def(s32 a0, s32 a1) #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" /* match_one-only: the real TU already includes this */ +#include "../shared/engine_core.h" /* match_one-only: the real TU already includes this */ /* func_801823E8 -- ov_SC02_026 / ov_SC02_026_jr_8017C180 * Same TU declares this at line 4712 (extern void func_801823E8(s32 a0);) and @@ -6979,7 +6979,7 @@ void func_801828C8(s32 arg0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" /* match_one-only: gives SV3_8012CC88; the real TU (ov_SC02_026_jr_8017C180.c) already includes "../shared/engine_core.h" at file top */ +#include "../shared/engine_core.h" /* match_one-only: gives SV3_8012CC88; the real TU (ov_SC02_026_jr_8017C180.c) already includes "../shared/engine_core.h" at file top */ extern s32 func_80182CE4(s32 a0, s32 a1); extern void func_801292C8(u8 *a0); @@ -7092,7 +7092,7 @@ void func_80182AF4(s32 a0) { } -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" /* match_one-only: gives struct vec + SV3_8012CC88; the real TU already includes this */ +#include "../shared/engine_core.h" /* match_one-only: gives struct vec + SV3_8012CC88; the real TU already includes this */ extern void func_8012931C(struct vec *a0); extern s32 func_8012CEB0(s32 a0, s32 a1, s32 a2); diff --git a/src/ov_SC02_039/ov_SC02_039_jr_8017BEBC.c b/src/ov_SC02_039/ov_SC02_039_jr_8017BEBC.c index 9c0c4c7215..f924ad2ada 100644 --- a/src/ov_SC02_039/ov_SC02_039_jr_8017BEBC.c +++ b/src/ov_SC02_039/ov_SC02_039_jr_8017BEBC.c @@ -4661,7 +4661,7 @@ void func_8017EED8(s32 a0in) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" /* func_8012DEB8: shared engine-core collision-probe routine, verified sig at * src/ov_SC03_099/ov_SC03_099_jr_8017BEBC.c:3492 (also used TU:375,6408,6479). */ diff --git a/src/ov_SC03_001/ov_SC03_001_jr_8017AE2C.c b/src/ov_SC03_001/ov_SC03_001_jr_8017AE2C.c index b1baa608b8..a7f0c9bf37 100644 --- a/src/ov_SC03_001/ov_SC03_001_jr_8017AE2C.c +++ b/src/ov_SC03_001/ov_SC03_001_jr_8017AE2C.c @@ -4171,7 +4171,7 @@ void func_8017C710(s32 arg0) } #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" /* fleet-modal spelling (engine_core.h, n=1411 occurrences) */ extern void func_8012ADE4(u8 *a0); diff --git a/src/ov_SC03_006/ov_SC03_006_jr_8017AE2C.c b/src/ov_SC03_006/ov_SC03_006_jr_8017AE2C.c index 0d33cd7a99..ce333119fa 100644 --- a/src/ov_SC03_006/ov_SC03_006_jr_8017AE2C.c +++ b/src/ov_SC03_006/ov_SC03_006_jr_8017AE2C.c @@ -10509,7 +10509,7 @@ s32 func_80185EFC(s32 a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_types.h" +#include "../shared/engine_types.h" extern s32 func_80133784(s32 a0, void *a1, s32 a2); extern s32 func_80134510(s32 arg); diff --git a/src/ov_SC03_091/ov_SC03_091_jr_80182268.c b/src/ov_SC03_091/ov_SC03_091_jr_80182268.c index 693c5b4e1a..ad3c7c4acf 100644 --- a/src/ov_SC03_091/ov_SC03_091_jr_80182268.c +++ b/src/ov_SC03_091/ov_SC03_091_jr_80182268.c @@ -2923,7 +2923,7 @@ void func_801826C8(s32 a0) { } -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern u16 func_80148800(s32 *a0); extern void func_80182B48(s32 param_1, s16 *param_2); diff --git a/src/ov_SC03_105/ov_SC03_105_jr_80186DDC.c b/src/ov_SC03_105/ov_SC03_105_jr_80186DDC.c index 50137c0461..14909b8766 100644 --- a/src/ov_SC03_105/ov_SC03_105_jr_80186DDC.c +++ b/src/ov_SC03_105/ov_SC03_105_jr_80186DDC.c @@ -3129,7 +3129,7 @@ s32 func_801870E8(s32 a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern s32 rand(void); extern s32 func_8012C51C(void *a0, s32 a1); diff --git a/src/ov_SC04_018/ov_SC04_018_jr_8017AE2C.c b/src/ov_SC04_018/ov_SC04_018_jr_8017AE2C.c index 74068428a0..895e500b32 100644 --- a/src/ov_SC04_018/ov_SC04_018_jr_8017AE2C.c +++ b/src/ov_SC04_018/ov_SC04_018_jr_8017AE2C.c @@ -6571,7 +6571,7 @@ void func_80180B6C(void *a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern void func_8012E8E0(s32 a0, s32 a1); extern void func_8012E88C(s32 a0); diff --git a/src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c b/src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c index ac2cc96111..5518597caa 100644 --- a/src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c +++ b/src/ov_SC05_003/ov_SC05_003_jr_8017BEBC.c @@ -4702,7 +4702,7 @@ ret0: } -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern s32 rand(void); extern u8 D_80078E78[]; @@ -5234,7 +5234,7 @@ void func_8017FEC0(s32 a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" /* func_8017FF60 — 4-state handler on the u16 state word at +0x34. * Symbols spelled from asm/ov_SC05_003/nonmatchings/ov_SC05_003_jr_8017BEBC/func_8017FF60.s @@ -5655,7 +5655,7 @@ void func_801807F8(s32 a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern void func_8012F14C(s32 a0, s32 a1, s32 a2); extern s32 func_80135888(s32 a0, s32 a1, s32 a2, s32 a3); @@ -5679,7 +5679,7 @@ s32 func_80180834(void *a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern void func_8012AD80(struct vec *a0); extern s32 func_80133784(s32, void *, s32); @@ -5747,7 +5747,7 @@ ret: #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern void func_8012AD80(struct vec *a0); extern s32 func_80133784(s32, void*, s32); @@ -6349,7 +6349,7 @@ void func_8018187C(void *a0) { repeated typedef even with an identical body). Absolute path so match_one's standalone compile resolves it; the header guard makes it a no-op in the TU. Same idiom as the neighbouring draft func_8017FF60. */ -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern s32 rand(void); extern s32 D_801A47B8; diff --git a/src/ov_SC05_010/ov_SC05_010_jr_80181CDC.c b/src/ov_SC05_010/ov_SC05_010_jr_80181CDC.c index 4c72b24cff..833ee86318 100644 --- a/src/ov_SC05_010/ov_SC05_010_jr_80181CDC.c +++ b/src/ov_SC05_010/ov_SC05_010_jr_80181CDC.c @@ -3137,7 +3137,7 @@ void func_80182AC0(void *a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_types.h" +#include "../shared/engine_types.h" extern void (*D_80192A28[])(void); extern u8 D_80192924[]; diff --git a/src/ov_SC06_000/ov_SC06_000_jr_8017AE2C.c b/src/ov_SC06_000/ov_SC06_000_jr_8017AE2C.c index 64f7016c29..517b85d5ca 100644 --- a/src/ov_SC06_000/ov_SC06_000_jr_8017AE2C.c +++ b/src/ov_SC06_000/ov_SC06_000_jr_8017AE2C.c @@ -8288,7 +8288,7 @@ void func_8018371C(s32 a0) #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_types.h" +#include "../shared/engine_types.h" extern MatEntry D_8018C558[]; extern s32 func_80178B18(s32 param_1, s32 param_2); diff --git a/src/ov_SC06_029/ov_SC06_029_jr_801867D0.c b/src/ov_SC06_029/ov_SC06_029_jr_801867D0.c index 93585065fe..9b40efaa9f 100644 --- a/src/ov_SC06_029/ov_SC06_029_jr_801867D0.c +++ b/src/ov_SC06_029/ov_SC06_029_jr_801867D0.c @@ -4076,7 +4076,7 @@ s32 func_80187CE4(void) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern s32 func_80047948(s32 a0); extern s32 func_8004787C(s32 a0); diff --git a/src/ov_SC06_029/ov_SC06_029_jr_801898CC.c b/src/ov_SC06_029/ov_SC06_029_jr_801898CC.c index f7c0eaec23..98e5efcbad 100644 --- a/src/ov_SC06_029/ov_SC06_029_jr_801898CC.c +++ b/src/ov_SC06_029/ov_SC06_029_jr_801898CC.c @@ -3432,7 +3432,7 @@ void func_80189B74(void *a0) { #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern Blk20 D_800AE620; extern u8 D_801B5EC8; @@ -3592,7 +3592,7 @@ void func_80189F50(void) { } #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_types.h" +#include "../shared/engine_types.h" extern s32 func_8012C1B8(void); extern void func_8012CAE4(void *a0); @@ -3641,7 +3641,7 @@ void func_8018A07C(void) { } #include "common.h" -#include "/home/musashi/bfm-decomp/src/shared/engine_core.h" +#include "../shared/engine_core.h" extern Blk20 D_800AE620; extern s32 D_801A7A34; diff --git a/tools/audit_text_sources.py b/tools/audit_text_sources.py index 5877567bd7..9234db3aed 100644 --- a/tools/audit_text_sources.py +++ b/tools/audit_text_sources.py @@ -18,17 +18,53 @@ blind to it (R34): the bytes are correct, so it has nothing to say. It needs its R32: this asserts COVERAGE (every candidate file was classified) and fails on the gap, rather than scanning until it happens to find something. + +SECOND CLASS — PORTABLE INCLUDES (P33 B2, the public flip). The build's only include path is +`-Iinclude` (no system headers, no Sony headers), so every `#include` in `src/` and `include/` must +resolve inside the repository, relative to the including file or under include/. 34 lines in 19 +overlay sources carried `#include "/home/musashi/bfm-decomp/src/shared/engine_core.h"` — byte-neutral +here (same header text), a hard build failure on any other machine, and invisible to the byte-gate +for the same reason the NUL was (R34). Offenders: an absolute path, an angle-bracket include +(nothing on the include path is a system header), or a quoted include that resolves outside the +repo / to no file. Controls (R39): 34 offenders in 19 files before the fix, 0 after. """ import os +import re import sys REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) ROOTS = ("src", "include") EXTS = (".c", ".h") +INCLUDE_DIR = os.path.join(REPO, "include") +_INCLUDE_RE = re.compile(rb'^\s*#\s*include\s*([<"])([^>"]+)[>"]') + + +def include_offenders(p, data): + """[(reason)] for every non-portable #include in one source (see the docstring).""" + out = [] + here = os.path.dirname(p) + for ln_no, line in enumerate(data.split(b"\n"), 1): + m = _INCLUDE_RE.match(line) + if not m: + continue + kind, target = m.group(1), m.group(2).decode("utf-8", "replace") + if kind == b"<": + out.append(f"line {ln_no}: angle-bracket include <{target}> (no system/SDK header is on the include path)") + continue + if target.startswith("/"): + out.append(f"line {ln_no}: ABSOLUTE include \"{target}\" (breaks every other machine)") + continue + cands = [os.path.normpath(os.path.join(here, target)), os.path.normpath(os.path.join(INCLUDE_DIR, target))] + hit = next((c for c in cands if os.path.isfile(c)), None) + if hit is None: + out.append(f"line {ln_no}: unresolvable include \"{target}\" (not relative to the file, not under include/)") + elif not (hit + os.sep).startswith(REPO + os.sep): + out.append(f"line {ln_no}: include \"{target}\" resolves OUTSIDE the repo ({hit})") + return out def offenders(): - """[(path, reason)] for every tracked-source file grep would treat as binary.""" + """[(path, reason)] for every tracked source that is not TEXT or carries a non-portable #include.""" bad, seen = [], 0 for root in ROOTS: for dirpath, _dirs, files in os.walk(os.path.join(REPO, root)): @@ -38,12 +74,14 @@ def offenders(): seen += 1 p = os.path.join(dirpath, f) data = open(p, "rb").read() + rel = os.path.relpath(p, REPO) n = data.count(b"\x00") if n: - rel = os.path.relpath(p, REPO) i = data.find(b"\x00") line = data[:i].count(b"\n") + 1 bad.append((rel, f"{n} NUL byte(s), first at line {line}")) + for why in include_offenders(p, data): + bad.append((rel, why)) return bad, seen @@ -51,15 +89,27 @@ def main(): bad, seen = offenders() print(f"audit-text-sources: scanned {seen} tracked {'/'.join(EXTS)} file(s) under {'/'.join(ROOTS)}") if not bad: - print("audit-text-sources: OK — every source is TEXT (grep can see all of them).") + print("audit-text-sources: OK — every source is TEXT (grep can see all of them) and every " + "#include is PORTABLE (resolves inside the repo).") return 0 - print(f"audit-text-sources: {len(bad)} FILE(S) GREP WOULD SILENTLY SKIP:") - for rel, why in bad: - print(f" {rel}: {why}") - print("\nA NUL in C source is almost always a raw control character written into a char " - "literal (`''` instead of `'\\0'`). It COMPILES, so no byte-gate objects — but the " - "file becomes invisible to grep and to every grep-based audit. Fix the literal, then " - "re-gate the affected binary to prove the change is byte-neutral.") + nul = [b for b in bad if "NUL byte" in b[1]] + inc = [b for b in bad if "NUL byte" not in b[1]] + if nul: + print(f"audit-text-sources: {len(nul)} FILE(S) GREP WOULD SILENTLY SKIP:") + for rel, why in nul: + print(f" {rel}: {why}") + print("\nA NUL in C source is almost always a raw control character written into a char " + "literal (`''` instead of `'\\0'`). It COMPILES, so no byte-gate objects — but the " + "file becomes invisible to grep and to every grep-based audit. Fix the literal, then " + "re-gate the affected binary to prove the change is byte-neutral.") + if inc: + print(f"audit-text-sources: {len(inc)} NON-PORTABLE #include line(s) in " + f"{len({rel for rel, _ in inc})} file(s):") + for rel, why in inc: + print(f" {rel}: {why}") + print("\nThe build's only include path is -Iinclude; an absolute, angle-bracket, unresolvable or " + "outside-repo include builds here and nowhere else. Respell it (`../shared/…` from src//), " + "then re-gate the binary.") return 1