11 Commits

Author SHA1 Message Date
Drew T 936d7d741c feat(phase-33): B5 Ghidra regenerability PROVEN — the RE work as text (config/ghidra/*.jsonl + ROSTER.md), six programs rebuilt from disc + symbol files + that file with PROOF PASS
- ImportAnnotations.java: the S86 OSGi-bundle blocker was 3 javac errors (Long->int unboxing x2, a nonexistent
  LocalVariableImpl ctor -> VariableStorage); "/undefined" resolves to DataType.DEFAULT (it lives in neither type
  manager — main's first proof passed the cmp with failed=13 because the plate-comment rows had set the same function
  comments); ghidra_rebuild.sh now dies unless the import printed failed=0 (R49), writes .proof markers
- ghidra_annotations_delta.py: analysis drift measured and encoded as three counted classes — Error/Analysis bookmarks;
  auto-named DEFAULT functions the rebuild did not create (29 in main's LINKED regions); auto-named rows lagging the curated
  symbol file (10 sep8 + 5 aug31, R15). Result: main 38 hand-authored rows (13 annotated fns incl. 3 the ELF does not
  define, 22 comments, 3 labels); resident/overlays/protos container rows only; the DB holds no hand-authored types
- controls (R39): mutated block row -> PROOF FAIL; synthetic comment/bookmark/label/signature round-trip -> PROOF PASS
  twice (idempotent); the filter keeps the synthetic rows and a hand-renamed name-only diff; fake failed=2 refused,
  resident re-proven; roster --check controls both ways
- proofs, all PASS failed=0: resident 65s, ov_SC01_077 169s, ov_SC06_018 173s, SLUS_007.26 210s, sep8 202s, aug31 206s
- tools/ghidra_roster.py -> config/ghidra/ROSTER.md (--check in tools-health, ignores the per-machine proof column)
- .claude/settings.json hooks $CLAUDE_PROJECT_DIR-relative; ghidra_mcp_start.sh is a silent exit 0 without Ghidra or
  the project (both controlled); SETUP P33 B5 section + 5 inventory rows + §2.8 (R21); CURRENT_PHASE log + checkpoint
2026-09-06 20:32:35 -06:00
Drew T cabab00c0e wip(phase-33): B5 Ghidra regenerability — ExportAnnotations.java + ghidra_export_annotations.sh PROVEN (all 129 programs exported to byte-stable JSONL in 18.5 s), ghidra_annotations_delta.py (live − baseline), ImportAnnotations.java + ghidra_rebuild.sh WRITTEN but unproven (the resident rebuild hit an OSGi script-bundle load error — a compile error in the new importer breaks every script in the dir; the known bad LocalVariableImpl ctor is named in CURRENT_PHASE); Makefile print-% + GHIDRA_PROJ repo-relative; the six ghidra_*.sh repo-relative (BFM_GHIDRA_PROJ); DefineFunctions arg path; ImportPsyqGdt install-dir default; ExportSymbols R15 fix; scratch project under build/ (Ghidra refuses '.'-prefixed path components); SETUP P33 B5 section; checkpoint refreshed for the next session (S86 paused at 87% context) 2026-09-06 19:31:34 -06:00
Drew T a7394f44dc feat(phase-31): S78 #12 — the 800c3 "wall" band is LIBPAD 4.2.1 + LIBAPI 4.2: 46 names applied; integrate wired by subseg range; renames via ApplySymbols
- provenance: the psx loader's per-version PsyQ signature sets place PADENTRY/PADCMD/PADPORTD/
  PADSEQD (4.2), WAITRC2 (4.3), COUNTER/C114/FIRST/PAD/PATCH/CHCLRPAD (libapi 4.2) byte-exact in
  0x8005CE48-0x8005FC68 / 800c2 -> 12 of main's 29 stubs incl. all four §332 walls are Sony's
  DualShock library in reorder mode. 46 names -> symbols.us.txt (count 1081), band TUs, verbatim
  manifest, wave_exclude; firstfile/firstfile2 (4.2 naming); CdGetToc @0x800430B8 (was the Phase-21
  xdedup mislabel DecDCToutCallback). SETUP §5.1 corrected; psyq-worklist S78; cookbook §487;
  decision-log + accelerators S78; CHECKSUMS +Psy-Q_46.zip +PSYQ_SDevTC_v4.5.zip.
- psyq_integrate: --yaml maps stub<->objects by SUBSEG RANGE with an exact-tiling check and PRINTS
  the located-but-unwired residue (libgte: 13 objs / 1,264 ins) — main's LINKED build had been RED
  at HEAD since the S77 psyq_identify fix (22 libgte blocks merged to 3; gate worktrees take the
  stub fallback so it never showed); a library object's exported symbol whose recovered address the
  curated file names differently is --redefine-sym'd (R15; A66 firstfile->firstfile2).
- Ghidra: 47 MCP renames did NOT persist through the sentinel stop (R9 caught it) -> NEW
  tools/ghidra_scripts/ApplySymbols.java + tools/ghidra_apply_symbols.sh mirror the curated file
  headless with a real save: 73 renamed, R9-verified x4. SETUP inventory rows (R21).
- lint_symbol_refs: scans verbatim __asm__ bodies (`.ent\tfunc_X` is invisible to \b and to the
  string-masked scan); negative-controlled (red on the pre-fix TUs, green on the passing tree).
- R22: clean extract-all 212/212 + check-all green on the final config; main rebuilt byte-identical
  143dbb89 after the last src-only fix -> 213/213; tools-health OK.
2026-09-04 15:57:06 -06:00
Drew T a0f07d629e chore(phase-30 S45 II.2): retirements (R33) + SETUP module recipe
- DELETED: disc_code_sweep.py (superseded by disc_audit/make audit-disc), reconcile_decls.py
  (superseded by reconcile_tu; incumbent row removed from cdecl audit_differential — the
  differential existed to prove this deletion safe), rollout_801457a4_o0/rollout_whale_o0/
  rollout_o0_cluster one-shots (rollout_o0.py is the live generic), ImportOverlay.java +
  VerifyOverlay.java (ghidra_import_raw.sh is the live path)
- reference check first (R14): the plan's 'zero build refs' was wrong for 3 — comment refs
  annotated, the one LIVE import (cdecl) reworked; audit-cdecl + tools-health re-proven green
- SETUP §6.7: module-class recipe (TEXT_LO derivation, paired-.rodata hdr carve, A4 symbol-
  window law, ELF-seeded sig-modules) + new_binary.sh inventory row + 3 RETIRED rows (R21);
  disc-completeness Reproduce marked retired
2026-08-06 13:34:50 -06:00
Drew T 5674587bcb feat(phase-21): T2 — fuel prefetch, Ghidra-C cache complete for the ROI pool
- headless DecompileFunctions over 263 uncached ROI-pool fns (MCP stopped, R23):
  263 ok / 0 fail / 0 no-func. cache 300 -> 563. ROI-pool fuel now 325/325 cached
  (28/28 giants, 310/310 reach-134, 7/7 capped) -> the unattended run never needs MCP.
- FIX DecompileFunctions.java: key output by entry address func_<UPPERHEX>.c (Ghidra's
  raw-import default is FUN_<lowerhex>, which every consumer + the existing 300 files
  miss). Renamed the 263; the tool fix makes re-prefetch reproducible.
- build_fuel_manifest.py --emit-prefetch: reproducible uncached-ROI-pool addr-list
  (for the T7 runbook). 349 reach-1 x1-leverage fns intentionally excluded (P9).
- ghidra/ db churn is the MCP-stop no-op save (R23 restart-noise, not staged).
2026-06-21 12:00:47 -06:00
Drew T 0dd9bf6bac feat(phase-17): calibration harvest wave — fleet 55.04%->55.51% (+0.47%)
- Ultracode wave: 30 high-reach tractable residuals, parallel guided-hand-matching
  agents (m2c + Ghidra-C cache + asm + actor-struct + S1/S2/S3a playbook), self-
  validate match_one. 18/30 match_one MATCH (60%); 10/30 whole-binary verified (33%)
  after sig_unify recovered 2 -> all 10 propagated x134; 2 demo fns caught up
- 136/136 byte-identical (R22 clean check-all); REAL +1,610; 1421 dedup groups
- KEY FINDING: the match_one->whole-binary gap (60%->33%) is 100% SIG CONFLICTS
  (shared callees like func_80131CA8 declared inconsistently across parallel agents),
  NOT codegen. The canonical-sig layer (deferred as low-value) is the ESSENTIAL
  enabler -> would lift 33% toward 60%. 12/30 are the genuine gcc-quirk tail (DIFF).
- Ghidra pre-pass: tools/ghidra_scripts/DecompileFunctions.java (headless batch
  decompile -> .run/ghidra_c cache; no /mcp needed); 300 tractable targets sized
- harness: .run/harvest_wave_s3.js (embedded-targets Workflow; args channel doesn't
  transit arrays). cost ~1.89M tokens / 30 fns
2026-06-19 20:54:45 -06:00
Drew T 03978ec4ba feat(phase-10): T4 — resident Ghidra program (2nd binary) + symbol seed + sig
- tools/ghidra_import_raw.sh (NEW): raw-blob importer (BinaryLoader + --loader-baseAddr +
  PSX:LE:32:default) — the Gen2 counterpart to ghidra_import.sh (PS-X-EXE only); reusable for
  Phase-13 location overlays. Imports the resident blob as program 'resident' @0x800CEDF8.
- tools/ghidra_scripts/DefineFunctions.java (NEW): seed splat's validated entry points
  (.run/<prog>_funcs.txt) — raw-binary auto-analysis finds only the reachable subset (23/143);
  this defines all 143 (created=120/existed=23/failed=0). R9-verified 143 funcs persisted.
- FINDING: DetectPsyQ reports the resident is PsyQ 4.7.0 (the EXE is 4.0.0); the lone in-range
  PsyQ-signature hit is DsMix (libsnd -> resident holds the sound driver). 4.7 .LIBs DEFERRED to
  Phase 11 start (Drew); carried to PhaseEnd Notes. Phase 10 needs nothing from 4.7.
- config/symbols.resident.txt: seed DsMix (R13 candidate, 4.0-sig vs 4.7 blob — confirm in Phase 11);
  stacked under symbols.us.txt, applied on re-extract -> resident still 8e17e02f BYTE-IDENTICAL (R22),
  main still 143dbb89 (no regression)
- Makefile: per-binary GHIDRA_PROG -> 'make sig-refresh BINARY=resident' (.run/sig.resident.jsonl)
- dup_report.resident now real (6 byte-identical intra-resident groups — Phase-11 dedup fodder)
- ghidra DB committed (R23, MCP stopped): new resident program 00000003.* (+ main db.15->16 no-op)
2026-06-15 23:25:00 -06:00
Drew T 3207d52491 feat(phase-3.5): prototype research spike — go/no-go (protos don't accelerate Gen1 matching)
- extract_proto_exe.py: subdir-aware proto main-EXE extraction (reuses iso9660); extracted
  sep8 SLUS_007.26 (413,696 B) + aug31 MUSASHI/USA_DEMO.EXE (415,744 B, base 0x80018000)
- ghidra_import.sh: reusable headless import; both protos imported into the bfm project
  (sep8 1726 funcs, aug31 1737 funcs, both PsyQ 4.0.0), R9-verified
- DumpFunctionSignatures.java + match_protos.py: 3-tier (exact/norm/seq) cross-binary
  correspondence; MIPS normalizer validated by anchors
- FINDINGS: (T2) no debug symbols in either proto — Hidden Palace "no symbols" VERIFIED;
  recon "Sep-8 less-stripped" REFUTED by per-file byte compare. (T3) Sep-8 99.6% byte-identical
  to retail (only 3 funcs differ: DebugMenuHandler, CdReadSectorReadyCB, SaveLoadRoutine);
  Aug-31 66% norm-identical, 862 1:1 correspondences. (T4) demo shares retail's 18-entry
  game-mode dispatch architecture but the handler code diverged — Q#10 resolved
- VERDICT (docs/proto-correspondence.md): NO-GO as a Gen1 label/symbol accelerator; GO to retain
  Sep-8 (Phase-6 compiler corroborant) + both (Gen2 assets); proto-side labels in
  config/symbols.proto-{sep8,demo}.txt (R13-tagged, never feed symbols.us.txt)
- reorg extracted/ into per-ROM subfolders (extracted/retail/, extracted/proto/); nested
  gitignore allowlist; extractor defaults updated; manifest --verify PASS
- memory-map.md: Phase-3.5 block + demo dispatch anchors; Q#10 RESOLVED; §5 proto notes VERIFIED
- ghidra_mcp_start.sh: PROG arg to serve a prototype
- rules R13 (proto-provenance/confidence tagging), R14 (verify recon counts vs bytes)
- bumps project version 1.3.0 -> 1.3.1
2026-06-14 03:19:23 -06:00
Drew T bd5e21b366 feat(phase-3): file-loader & overlay-map RE + PCSX-Redux runtime oracle
- RE'd the full file-loader/overlay subsystem in Ghidra via MCP: CdReadRequest ->
  CdReadStateMachine (hand-rolled CdControl SeekL/ReadN reader, NOT PsyQ CdRead);
  LIST.CD RAM cache cdFileLocTable + ResourceGetCdLoc/resourceIdMap lookup; LZSS
  staging buffer 0x80079A70; loadDestPtrTable; ~50 symbols named (T1-T5,T8)
- T6b MILESTONE: resident blob @0x800CEDF8 + location overlay @0x80128158 proven
  byte-identical (sha1-equal contiguous prefixes) vs live PCSX-Redux RAM; blobs
  imported into Ghidra (ImportOverlay.java); overlay-map table -> memory-map.md §4.3
- PCSX-Redux runtime oracle: Windows-native build, WSL reads RAM via the web API
  at 172.17.208.1:8081; ledger #4 resolved
- live-verified player/time state: gold(/10) HP BP day hour tiredness boss-HP;
  save-header template (Q#5) + debug-menu dispatch (Q#9: DEBUG.BIN path is dead)
- overlay map: 13 area-states across SC01/02/03, 2 duplicate pairs, location x
  chapter keying, free-roam vs menu-hub granularity
- resolves Open Q#1/#3/#4/#5/#6/#8/#9/#12; corrects SLUS-90029 (FF8 demo, not BFM)
- 2 US prototypes acquired + CRC-verified (Aug-31 1369DE07, Sep-8 5C24728E)
- rules R9 (verify persistence), R10 (>=3-datapoint live verification),
  R11 (runtime oracle Windows-native, bridged to WSL)
- bumps project version 1.2.0 -> 1.3.0
2026-06-14 02:04:28 -06:00
Drew T 5b6ffc0664 chore(phase-1): headless .gdt attach + MCP type-resolution test (ledger #2)
- tools/ghidra_scripts/ImportPsyqGdt.java: opens psyq400.gdt and resolve()s
  all 2599 PsyQ 4.0 types into the program DTM (205 -> 2609), registering
  psyq400 as a SourceArchive; saved to ghidra/bfm.rep
- verified over MCP: types get DRAWENV -> full 92-byte struct (/LIBGPU.H),
  SVECTOR (/LIBGTE.H) -> the .gdt "attach" is doable headlessly, no GUI
- docs/SETUP.md: ledger #2 RESOLVED; §2.5 step 5 answered (import types into
  the program; MCP type tools then resolve them)
2026-06-13 16:46:03 -06:00
Drew T 36a366ba3f chore(phase-1): install RE stack + headless import (PsyQ 4.0.0, MCP live)
- WSL RE stack installed: JDK 21.0.11, Ghidra 12.1 PUBLIC, GhidrAssistMCP
  v2.8.0, ghidra_psx_ldr 2026.06.04 (extensions extracted into
  Ghidra/Extensions/ at version=12.1; exact-12.1 pin held, no version-lock)
- headless import of extracted/SLUS_007.26: PSX loader auto-selected
  (PSX:LE:32:default), PsyQ Version = 4.0.0 recorded, 1726 functions,
  saved to ghidra/bfm.{gpr,rep} (gitignored)
- GhidrAssistMCP headless server verified on 127.0.0.1:8080 (41 tools);
  get_code(0x80018730) returns the LZSS streaming decompressor
  (milestone substance, also confirmed via headless decompiler)
- tools/ghidra_scripts: DumpProgramInfo.java, DecompileAt.java (helpers)
- docs/SETUP.md: confirm PsyQ 4.0.0; 41 tools + async get_code/SSE notes;
  headless -loader rejected -> use auto-detect; extension-install path;
  ledger #1 moot, #12 resolved
2026-06-13 15:52:37 -06:00