mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-27 22:45:39 -04:00
3207d52491
- 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
56 lines
2.7 KiB
Bash
56 lines
2.7 KiB
Bash
#!/usr/bin/env bash
|
|
# tools/ghidra_mcp_start.sh
|
|
# Idempotent, fully-detached start of the headless GhidrAssistMCP server for BFM,
|
|
# using BfmMcpServer.java (server + clean save-on-shutdown — see that file).
|
|
# Serves a program from the "bfm" Ghidra project over MCP on 127.0.0.1:8080.
|
|
# Program defaults to SLUS_007.26 (retail); pass an alternate as $1 to serve a
|
|
# prototype, e.g. tools/ghidra_mcp_start.sh sep8_SLUS_007.26
|
|
# (only ONE program is served per session; stop with ghidra_mcp_stop.sh to switch).
|
|
#
|
|
# Designed to run from a SessionStart hook:
|
|
# * no-op if the server is already serving on :8080 (safe to run every session),
|
|
# * the launched server is fully detached (setsid+nohup+disown) so it OUTLIVES the
|
|
# launching shell and the Claude Code session (persists across sessions in a phase).
|
|
#
|
|
# After "serving" appears in the log, run `/mcp` in Claude Code once per session to
|
|
# attach the mcp__ghidra__* tools (a running session cannot self-reconnect).
|
|
#
|
|
# PERSISTENCE: MCP writes are saved only on CLEAN SHUTDOWN (analyzeHeadless commits the
|
|
# open transaction + saves on close). Save+stop with tools/ghidra_mcp_stop.sh; resume by
|
|
# re-running this script. There is no mid-session save (GhidrAssist holds an open txn).
|
|
set -uo pipefail
|
|
|
|
GHIDRA="${GHIDRA_INSTALL_DIR:-$HOME/ghidra_12.1_PUBLIC}"
|
|
PROJ_DIR="$HOME/bfm-decomp/ghidra"
|
|
PROJ="bfm"
|
|
PROG="${1:-SLUS_007.26}" # program to serve; default retail, pass a proto name to override
|
|
PORT="8080"
|
|
RUNDIR="$HOME/bfm-decomp/.run"; mkdir -p "$RUNDIR" # project-local runtime scratch (never /tmp)
|
|
LOG="$RUNDIR/ghidra-mcp.log"
|
|
SCRIPTS="$HOME/bfm-decomp/tools/ghidra_scripts"
|
|
STOPREQ="${BFM_MCP_STOPREQ:-$RUNDIR/mcp-stop.req}"
|
|
|
|
# 1) Already serving? no-op (idempotent across sessions).
|
|
if ss -tln 2>/dev/null | grep -qE ":$PORT([^0-9]|$)"; then
|
|
echo "ghidra-mcp: already serving on :$PORT — no-op"
|
|
exit 0
|
|
fi
|
|
|
|
# 2) Clear stale stop sentinel + a stale project lock (only when no analyzer is alive).
|
|
rm -f "$STOPREQ" 2>/dev/null || true
|
|
if ! pgrep -f 'ghidra.app.util.headless.AnalyzeHeadless' >/dev/null 2>&1; then
|
|
rm -f "$PROJ_DIR/$PROJ.lock" "$PROJ_DIR/$PROJ.lock~" 2>/dev/null || true
|
|
fi
|
|
|
|
# 3) Launch fully detached so it survives this shell and the Claude session.
|
|
echo "ghidra-mcp: starting headless server (detached) -> $LOG"
|
|
setsid nohup "$GHIDRA/support/analyzeHeadless" "$PROJ_DIR" "$PROJ" \
|
|
-process "$PROG" -noanalysis \
|
|
-scriptPath "$SCRIPTS" \
|
|
-preScript BfmMcpServer.java host=127.0.0.1 "port=$PORT" "stopreq=$STOPREQ" \
|
|
>"$LOG" 2>&1 </dev/null &
|
|
disown 2>/dev/null || true
|
|
|
|
echo "ghidra-mcp: launched (pid $!). Project load takes ~10-60s."
|
|
echo "ghidra-mcp: wait for 'serving' in $LOG, then run /mcp in Claude Code."
|