a38aa2603a
Worker B measured that recorded negatives cluster at the head of every partition: 39 of the first 40 worklist rows and 57 of 271 tier-1 rows (21%) were addresses an earlier session had already attempted and recorded. The triage tool never read the negatives index, so every closed negative returned to the queue head and workers rediscovered them. Fix: sf3_triage reads the tracked config/near_match_negatives.tsv (a new --negatives input) and excludes those rows as recorded_negative=69. The tracked index was grown from 38 Phase-8 rows to 94 by importing 56 Phase-9 negatives from the workers' reports and the coordinator's absorption record (filtered to unregistered; tracked rows win on conflict). Worklist regenerated: the head is now genuinely fresh (0x800F9134, 0x80042D88, 0x800450C4, ...). 3 new synthetic tests; plan-level tests wired for the new argument. The phase plan said extract negatives only at close; B's measurement showed the harm is per-cycle, so the index is now a living tracked input. Note for P9-T8: keep importing worker negatives each cycle.
143 lines
5.0 KiB
Makefile
143 lines
5.0 KiB
Makefile
# Phase 3 all-assembly baseline orchestration.
|
|
# All original and generated ROM-derived inputs/outputs remain ignored.
|
|
|
|
SHELL := /usr/bin/bash
|
|
|
|
EXE := extracted/SCUS_946.40;1
|
|
MANIFEST := extracted/MANIFEST.tsv
|
|
SPLAT := tools/splat/.venv/bin/splat
|
|
AS := tools/mipsel-none-elf-binutils/prefix/usr/bin/mipsel-none-elf-as
|
|
LD := tools/mipsel-none-elf-binutils/prefix/usr/bin/mipsel-none-elf-ld
|
|
OBJCOPY := tools/mipsel-none-elf-binutils/prefix/usr/bin/mipsel-none-elf-objcopy
|
|
|
|
ASM_ROOT := asm
|
|
SPLAT_CONFIG := $(ASM_ROOT)/scus_946_40.yaml
|
|
SPLAT_OUTPUT := $(ASM_ROOT)/generated
|
|
LINKER_SCRIPT := $(ASM_ROOT)/scus_946_40.ld
|
|
BUILD := build
|
|
ELF := $(BUILD)/scus_946_40.elf
|
|
REBUILT := $(BUILD)/scus_946_40.rebuilt
|
|
INPUT_REPORT := .run/p3-exe-info.tsv
|
|
|
|
# Phase 5 ordered code build: C regions listed in the tracked registry are
|
|
# compiled with the identified toolchain and linked in address order between
|
|
# data fallbacks taken from the original executable. An empty registry
|
|
# reproduces the all-payload data baseline exactly.
|
|
REGIONS := config/regions.tsv
|
|
SYMBOLS := config/symbols.tsv
|
|
INVENTORY := config/function_inventory.tsv
|
|
EXTENTS := config/function_extents.tsv
|
|
DUPES := config/duplicate_bodies.tsv
|
|
NEGATIVES := config/near_match_negatives.tsv
|
|
WORKLIST := config/match_worklist.tsv
|
|
MATCH := tools/sf3_match
|
|
EXTENTS_TOOL := tools/sf3_extents
|
|
DUPES_TOOL := tools/sf3_dupes
|
|
TRIAGE_TOOL := tools/sf3_triage
|
|
CODE_OUT := build/code
|
|
EXPECTED_SHA1 := e173426c157384ebf1b6caf8c6fea18a85a14af9
|
|
|
|
.PHONY: all validate split assemble link binary code gate extents extents-verify dupes worklist test check clean
|
|
|
|
all: binary
|
|
|
|
validate:
|
|
@test -f "$(EXE)"
|
|
@test -f "$(MANIFEST)"
|
|
@mkdir -p .run
|
|
@./tools/sf3_extract psx-exe-info "$(EXE)" "$(MANIFEST)" > "$(INPUT_REPORT)"
|
|
|
|
split: validate
|
|
@test -f "$(SPLAT)"
|
|
@test -f "$(SPLAT_CONFIG)"
|
|
@cd "$(ASM_ROOT)" && ../"$(SPLAT)" split "$$(basename "$(SPLAT_CONFIG)")" --disassemble-all
|
|
|
|
assemble: split
|
|
@test -d "$(SPLAT_OUTPUT)" && test ! -L "$(SPLAT_OUTPUT)"
|
|
@test -f "$(AS)"
|
|
@test ! -L "$(BUILD)"
|
|
@mkdir -p "$(BUILD)"
|
|
@while IFS= read -r source; do \
|
|
rel="$${source#$(ASM_ROOT)/}"; \
|
|
object="$(BUILD)/$${rel}.o"; \
|
|
mkdir -p "$$(dirname "$$object")"; \
|
|
"$(AS)" -march=r3000 -G0 -I "$(ASM_ROOT)/include" -o "$$object" "$$source"; \
|
|
done < <(find "$(SPLAT_OUTPUT)" -type f -name '*.s' -print | sort)
|
|
|
|
link: assemble
|
|
@test -f "$(LINKER_SCRIPT)"
|
|
@test -f "$(LD)"
|
|
@rm -f "$(ELF)"
|
|
@"$(LD)" -T "$(LINKER_SCRIPT)" -o "$(ELF)"
|
|
|
|
binary: link
|
|
@test -f "$(OBJCOPY)"
|
|
@rm -f "$(REBUILT)"
|
|
@"$(OBJCOPY)" -O binary "$(ELF)" "$(REBUILT)"
|
|
|
|
# Ordered code build and full-binary gate (Phase 5). `code` builds only;
|
|
# `gate` builds and then requires the whole executable to be byte-identical.
|
|
code: validate
|
|
@test -f "$(MATCH)"
|
|
@test -f "$(REGIONS)"
|
|
@test -f "$(SYMBOLS)"
|
|
@rm -rf "$(CODE_OUT)"
|
|
@"$(MATCH)" build --exe "$(EXE)" --regions "$(REGIONS)" --symbols "$(SYMBOLS)" --out "$(CODE_OUT)"
|
|
|
|
gate: validate
|
|
@test -f "$(MATCH)"
|
|
@test -f "$(REGIONS)"
|
|
@test -f "$(SYMBOLS)"
|
|
@rm -rf "$(CODE_OUT)"
|
|
@"$(MATCH)" gate --exe "$(EXE)" --regions "$(REGIONS)" --symbols "$(SYMBOLS)" --out "$(CODE_OUT)" \
|
|
--expect-sha1 "$(EXPECTED_SHA1)"
|
|
|
|
# Function extents (Phase 7). `extents` regenerates the tracked table from the
|
|
# inventory; `extents-verify` re-derives it and requires every registered region
|
|
# to agree, so a region can never silently disagree with the derived extent.
|
|
extents: validate
|
|
@test -f "$(EXTENTS_TOOL)"
|
|
@test -f "$(INVENTORY)"
|
|
@"$(EXTENTS_TOOL)" scan --exe "$(EXE)" --inventory "$(INVENTORY)" --out "$(EXTENTS)" --force
|
|
|
|
extents-verify: validate
|
|
@test -f "$(EXTENTS_TOOL)"
|
|
@test -f "$(INVENTORY)"
|
|
@test -f "$(EXTENTS)"
|
|
@"$(EXTENTS_TOOL)" verify --exe "$(EXE)" --inventory "$(INVENTORY)" \
|
|
--extents "$(EXTENTS)" --regions "$(REGIONS)"
|
|
|
|
# Duplicate-body census (Phase 7): groups byte-identical bodies so a shared body
|
|
# is matched once and registered once per address.
|
|
dupes: validate
|
|
@test -f "$(DUPES_TOOL)"
|
|
@test -f "$(EXTENTS)"
|
|
@"$(DUPES_TOOL)" census --exe "$(EXE)" --extents "$(EXTENTS)" --out "$(DUPES)" --force
|
|
|
|
# Ranked match worklist (Phase 7). The two --exclude addresses are the recorded
|
|
# near-misses deferred by developer direction in Phase 7; naming them here keeps
|
|
# the exclusion visible instead of burying it in the tool.
|
|
worklist: validate
|
|
@test -f "$(TRIAGE_TOOL)"
|
|
@test -f "$(EXTENTS)"
|
|
@test -f "$(DUPES)"
|
|
@"$(TRIAGE_TOOL)" plan --exe "$(EXE)" --extents "$(EXTENTS)" --inventory "$(INVENTORY)" \
|
|
--census "$(DUPES)" --regions "$(REGIONS)" --negatives "$(NEGATIVES)" \
|
|
--exclude 0x8005DEF8 --exclude 0x800F3160 \
|
|
--exclude 0x80108034 --exclude 0x8010804C \
|
|
--exclude 0x80012A10 --exclude 0x80012AE0 \
|
|
--exclude 0x8008A198 --out "$(WORKLIST)" --force
|
|
|
|
# Verification gates. `test` is synthetic-only and needs no game input;
|
|
# `check` adds the extents check and the full-binary byte gate (which do).
|
|
test:
|
|
@PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tools/tests
|
|
|
|
check: test extents-verify gate
|
|
|
|
clean:
|
|
@if test -e "$(BUILD)"; then \
|
|
test -d "$(BUILD)" && test ! -L "$(BUILD)"; \
|
|
rm -rf "$(BUILD)"; \
|
|
fi
|