mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-26 13:33:34 -04:00
757bd82a0f
The §9.1 "scattered .bss commons" exclusion class (Phase 8 → P31) is closed 3/3. New tools/psyq_bss_split.py (own ELF32 REL reader/writer) cuts an object's packed .bss into per-base NOBITS pieces: bases derived from the game bytes per HI16/LO16 pair, references walked in offset order into single-base runs, cuts snapped to symbol starts (the linker scattered SYMBOLS), symbols moved, a LOCAL section symbol per piece inserted, relocs retargeted with the addend rewritten in the immediates, self-diffed. It runs inside the one prepare step shared by psyq_link.link_object / psyq_link_region.build_region / psyq_integrate.integrate (prepare_object before classify), re-derived every build. GS_001.o was certified "5 interleaved bases, NOT splittable" by the S77 probe, which grouped by BASE; by RUN it is six symbol-aligned pieces. All seven cuts across the three objects are confirmed by the other objects' by-name recoveries (_que 0x800C5510, _svm_sreg_buf 0x800B9B58, PSDBASEX/CLIP2/PSDBASEY/POSITION/GsDRAWENV). R39 negative control: 235 placed objects across 9 curated dirs, 0 refusals, exactly 3 splits (a libcd .bss+size end pointer refused the first build → reference problems are fatal only when a split is needed). Wiring: yaml 800c→libgpu2, sgap_6→sgap_6+snd12, gsgap3→libgs8 (comments rewritten); LIBGPU_ELF := .run/obj40/libgpu (curated libgpu_used retired); libgs 34 objs/8 blocks (make_libgs.sh +GS_001); snd 63/12 (make_snd_used.py exclusions 4→3). src/800c.c and src/gsgap3.c removed (Sony code hand-matched as REAL/verbatim), sgap_6.c keeps only func_8003FA54; splat-emitted libgpu2.c/libgs8.c/snd12.c stubs for the no-SDK fallback. Verified: main 143dbb89f34491258bbc27810d0a12ec8b43a8dd WITH the SDK objects and WITHOUT them from a fresh extract; make tools-health OK; R22 fleet clean extract-all 212/212 + check-all 213/213. Metrics: main REAL 886→839, LINKED 1,040→1,150, VERBATIM 85→29, stubs 29 (unchanged); game-code weighted 91.1% (40,895/44,870) — both terms lost the 3,667 SDK ins; the remainder is still exactly the 3,975-ins open-stub sum. Verbatim manifest --update 200→33 rows (subtractive). Docs: cookbook §489 (+index), psyq-worklist rows + "S78 task #4", SETUP S79 R21 table, decision-log S79 addendum, accelerators S79, CURRENT_PHASE S79 FINAL 🛑.
81 lines
3.9 KiB
Python
81 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Build the curated .run/obj40/snd_used dir = the combined libspu+libsnd sound region (Phase 8).
|
|
|
|
libspu and libsnd are tightly interleaved in 0x8003A444..0x8004239C (the tail of the 800 subseg), so
|
|
they are linked as ONE combined region rather than two passes. This:
|
|
- places both libraries' objects (psyq_identify) and merges them by vram,
|
|
- for an aliased address (>1 object, same masked .text) picks the object whose linked .text
|
|
byte-matches the EXE (psyq_link.link_object) — the real one,
|
|
- EXCLUDES 3 ADDRESSES that don't reconcile in the combined region (ALL candidates there stay
|
|
byte-identical stubs — excluding by address, not name, since the alias twin fails identically):
|
|
0x3C438 (S_R/S_W), 0x3D424 (S_GRMDT/FB/T) — commons referenced at a minority address the
|
|
region's single defsym can't satisfy (cookbook §9.1, cross-object form; these objects have NO
|
|
.bss of their own — psyq_bss_probe — so the S78 split does not apply to them),
|
|
0x3D94C (S_IH/UT_RON) — false placement: 0x3D94C is INSIDE libsnd SSSTART.o.
|
|
0x3FA64 (VM_F.o, 237 ins) was the 4th exclusion (scattered-.bss commons) until P31 S78 #4: its
|
|
`.bss` is now SPLIT at link-prepare (psyq_bss_split, cookbook §489) and it links as snd12.
|
|
- copies the survivors into .run/obj40/snd_used.
|
|
|
|
The build is byte-identical with OR without snd_used (stub fallback), so a fresh clone need not run
|
|
this unless it wants the SDK objects linked. Regenerate: tools/psyq_build_libs.sh LIBSPU LIBSND first.
|
|
"""
|
|
import os, re, shutil, subprocess, sys
|
|
from collections import defaultdict
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
from psyq_link import link_object # noqa: E402
|
|
|
|
# EXE-curation tool: --exe/--vram-base default to the retail EXE's values (threaded explicitly into
|
|
# psyq_identify + link_object, which require them post-T8). RLO/RHI/EXCLUDE_ADDR are the EXE's sound
|
|
# region + the 4 unreconcilable addresses (EXE-specific; an overlay would supply its own).
|
|
EXE = "extracted/retail/SLUS_007.26"
|
|
VRAM_BASE = 0x8000F800
|
|
RLO, RHI = 0x8003A444, 0x8004239C
|
|
EXCLUDE_ADDR = {0x8003C438, 0x8003D424, 0x8003D94C} # see module docstring (VM_F 0x8003FA64 rejoined S78 #4)
|
|
|
|
|
|
def place(lib, exe, vram_base):
|
|
out = subprocess.check_output(["python3", "tools/psyq_identify.py", f".run/obj40/{lib}",
|
|
"--vram-base", hex(vram_base), "--exe", exe], text=True)
|
|
d = {}
|
|
for ln in out.splitlines():
|
|
m = re.match(r"\s+0x([0-9A-Fa-f]+)\s+(\S+\.o)\s+\((\d+) ins\)", ln)
|
|
if m:
|
|
d[m.group(2)] = int(m.group(1), 16)
|
|
return d
|
|
|
|
|
|
def main():
|
|
import argparse
|
|
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
ap.add_argument("--exe", default=EXE)
|
|
ap.add_argument("--vram-base", default=hex(VRAM_BASE))
|
|
args = ap.parse_args()
|
|
exe_path, vram_base = args.exe, int(args.vram_base, 0)
|
|
exe = open(exe_path, "rb").read()
|
|
byaddr = defaultdict(list)
|
|
for lib in ("libspu", "libsnd"):
|
|
for nm, a in place(lib, exe_path, vram_base).items():
|
|
byaddr[a].append((lib, nm))
|
|
|
|
dst = ".run/obj40/snd_used"
|
|
shutil.rmtree(dst, ignore_errors=True)
|
|
os.makedirs(dst)
|
|
n = 0
|
|
for a in sorted(byaddr):
|
|
if not (RLO <= a < RHI) or a in EXCLUDE_ADDR:
|
|
continue
|
|
cands = byaddr[a]
|
|
pick = next(((lib, nm) for lib, nm in cands
|
|
if link_object(f".run/obj40/{lib}/{nm}", a, name=nm, exe_bytes=exe,
|
|
vram_base=vram_base)["ok"]),
|
|
cands[0])
|
|
lib, nm = pick
|
|
shutil.copy(f".run/obj40/{lib}/{nm}", f"{dst}/{nm}")
|
|
n += 1
|
|
print(f"snd_used: {n} objects (libspu+libsnd combined; {len(EXCLUDE_ADDR)} addresses excluded: "
|
|
f"{[hex(x) for x in sorted(EXCLUDE_ADDR)]})")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|