mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-27 22:45:39 -04:00
af2f40d153
R22 CLEAN-FLEET: make clean -> extract 136 -> build 136 -> check-all = 136 PASSED, 0 FAILED.
make audit-corpus: 0 PHANTOM + 0 TRUNCATED (was 193).
=== A4: a CORPUS defect the byte-gate could never have caught ===
config/symbols.us.txt:981 declared `listCdBuffer = 0x80180000` — a correct Phase-3 name for MAIN's
LIST.CD RAM buffer. But that address is OUTSIDE main's image and INSIDE the overlay slot, and every
overlay's splat config stacks symbols.us.txt. High RAM is REUSED: an address that is a buffer to main
is live CODE to an overlay. So splat saw a symbol boundary mid-code and, across 97 of 134 overlays:
* CUT 97 REAL FUNCTIONS IN HALF (a head ending on a `lui`, no return), and
* INVENTED 96 PHANTOM ONES (a tail beginning by reading the assembler temp $at).
193 slices NOBODY COULD EVER MATCH — not "hard", not "a compiler wall": unmatchable by construction.
They sat in the harvest queue as ordinary work, so agents would burn on them forever and the failures
would be filed as intrinsic compiler residuals.
The phantom listCdBuffer.s in ov_SC01_005 literally begins:
lw $ra, 0x10($sp) / addiu $sp, $sp, 0x18 / jr $ra
splat cut a function immediately before its EPILOGUE and called the epilogue a function.
AND IT HAD ALREADY CONTAMINATED REAL WORK: in ov_SC03_031 the cut landed where the epilogue was
exactly `jr $ra; nop`, so the Phase-26 x134 sweep innocently BANKED the phantom as
`void listCdBuffer(void) {}` — byte-correct, gate-green, entirely fictitious — while leaving
func_8017FFC4 permanently unmatchable. Removed.
WHY NO GATE CAUGHT IT, AND WHY THAT IS THE POINT: INCLUDE_ASM pastes the two .s halves back VERBATIM
in original order, so the image is byte-identical either way. The byte-gate was green the whole time
and always would have been. It is a perfect CORRECTNESS oracle and a NULL COVERAGE oracle. No
assertion added INSIDE it could ever have found this. What found it was a SECOND, INDEPENDENT oracle:
tools/sig_image.py derives boundaries from the ORIGINAL bytes without splat, and DISAGREED with the
corpus (58,524/58,621 agreement with spimdisasm; correct on all 97 disagreements).
=> When one oracle is structurally blind to a class of error, the answer is not a better assertion
inside it. It is a SECOND ORACLE THAT CAN DISAGREE WITH IT. (`make audit-corpus` is now that.)
THE RULE (the mirror of R13/R15, never written down): a symbol whose address falls inside ANOTHER
binary's vram window must never enter that binary's symbol stack.
FIX: config/symbols.us.ram.txt — main-scoped symbols outside main's image — stacked ONLY by
config/splat.us.exe.yaml. Main keeps the name it needs (10 %hi / 11 %lo refs; 143dbb89 byte-identical);
the overlays never see it. Exactly one symbol was in scope fleet-wide; the resident window was clean.
AND A REAL FUNCTION THE ACCIDENT WAS HIDING: in ov_SC01_084 / ov_SC02_041 / ov_SC03_094 / ov_SC06_008
there IS a genuine function at 0x80180000 (111 / 35 / 28 / 74 ins), reachable ONLY via a fn-pointer
table (.word func_80180000) and never by `jal` — so splat cannot find it and needs the boundary
DECLARED. listCdBuffer had been supplying it by luck. Now declared honestly, per-overlay, in
config/symbols.<ov>.txt — exactly where R13/R15 says an overlay-scoped symbol belongs.
=== A5: the closeness oracle every crack agent trusts was lying on 155 functions ===
masked_diff._reloc_kind() knew 26/HI16/LO16. An over-approximating sweep of every reloc objdump emits
across all 3,367 build objects found FOUR: R_MIPS_26, HI16, LO16 — and R_MIPS_PC16 (211). PC16 fell
through to a FULL-WORD compare, but the object holds an UNRESOLVED PLACEHOLDER in the branch
displacement, so that compare can NEVER succeed.
DECISIVE TEST (derived from the invariant, not from reading the regex): INCLUDE_ASM pastes the
ORIGINAL asm, so for every stub diff_object_s() MUST be 0. Measured, coverage-asserted:
2,741 functions scored — old mask: 150 LIES; PC16 masked: 4 LIES.
(The 4 survivors are the separate length-delta defect.) A phantom non-zero sends an agent to grind at
a wall that is not there, and the wasted attempt is then booked as a MATCHING failure, feeding
reserved_walls() and PERMANENTLY BLACKLISTING a function that was never broken.
=== NEW FINDING (found by cutting the R22 corner): a STALE OBJECT CAN PRODUCE A FALSE PASS ===
`.o <- .s` is not a dependency make can see: assembly arrives via INCLUDE_ASM, expanded to a `.include`
consumed by maspsx/as AFTER cpp, while -MMD tracks headers only. Re-extract, build incrementally, and
make links a STALE object. This is not merely slow — INCLUDE_ASM pastes the ORIGINAL bytes, so a stale
object still yields the original image: SHA1 GOES GREEN while the split just changed is never exercised.
A broken config change can be "verified" by an incremental build. Live proof: 8 of 136 binaries linked
stale objects here; they failed LOUDLY ONLY BY LUCK (the dead symbol was an undefined reference) — a
merely-different-but-valid split would have gone green on all 136.
R22/H3 already legislate this, and I broke them. But a rule that needs a human to remember it is not a
gate. FIX: `extract` now invalidates the objects that include what it just rewrote (main's are top-level,
so -maxdepth 1 — verified it cannot clobber the other 1,605 objects). Structural, not advisory.
R14 self-catch, recorded: my first A5 test passed `fn=` to diff_object_s(), which takes two args; the
TypeError was swallowed by my own `except Exception: continue` and it reported 0 scored / 0 lies. I
wrote the exact bug I was auditing, inside the test for it. Caught only because 0 looked wrong. The
test now asserts its own coverage.
210 lines
15 KiB
YAML
210 lines
15 KiB
YAML
# splat config — Brave Fencer Musashi main EXE (SLUS-00726, USA)
|
|
# Phase 5: rebuild SLUS_007.26 byte-for-byte from disassembly (all-asm skeleton).
|
|
#
|
|
# Derived from splat 0.41.0's own `python -m splat create_config <PS-X EXE>`
|
|
# (splat/scripts/create_config.py::create_psx_config), adapted to this repo's
|
|
# paths and the Phase-3 symbol export. PSX-specific values that the generator
|
|
# pins (do NOT "tidy" them without evidence): compiler PSYQ, subalign 2,
|
|
# section_order rodata/text/data/bss, find_file_boundaries False, gp_value from
|
|
# the EXE header's Initial-GP field.
|
|
#
|
|
# Boundaries (file offsets) come from splat's psxexeinfo estimate:
|
|
# text @ file 0x800 (vram 0x80010000)
|
|
# data @ file 0x531DC (vram 0x800629DC) <- iterate if the link/bytes disagree
|
|
# end @ file 0x65000 (= 413,696 B)
|
|
name: SLUS_007.26
|
|
sha1: 143dbb89f34491258bbc27810d0a12ec8b43a8dd
|
|
options:
|
|
basename: SLUS_007.26
|
|
target_path: extracted/retail/SLUS_007.26
|
|
elf_path: build/us/SLUS_007.26.elf
|
|
# base_path is resolved relative to THIS yaml's dir (config/), so `..` = repo root
|
|
base_path: ..
|
|
platform: psx
|
|
compiler: PSYQ
|
|
|
|
asm_path: asm
|
|
src_path: src
|
|
build_path: build
|
|
ld_script_path: build/us/SLUS_007.26.ld
|
|
ld_dependencies: True
|
|
|
|
find_file_boundaries: False
|
|
gp_value: 0x80074750
|
|
|
|
o_as_suffix: True
|
|
use_legacy_include_asm: False
|
|
|
|
section_order: [".rodata", ".text", ".data", ".bss"]
|
|
|
|
symbol_addrs_path:
|
|
- config/symbols.us.txt
|
|
# main-scoped symbols OUTSIDE main's image (high RAM the overlays reuse as CODE).
|
|
# NEVER stacked by an overlay/resident — see the header of that file (Phase 26-A).
|
|
- config/symbols.us.ram.txt
|
|
|
|
subalign: 2
|
|
|
|
string_encoding: ASCII
|
|
data_string_encoding: ASCII
|
|
rodata_string_guesser_level: 2
|
|
data_string_guesser_level: 2
|
|
|
|
# Enable if maspsx reorders INCLUDE_ASM output once the code segment is `c`
|
|
# (https://github.com/mkst/maspsx#include_asm-reordering-workaround-hack):
|
|
# include_asm_macro_style: maspsx_hack
|
|
|
|
segments:
|
|
- name: header
|
|
type: header
|
|
start: 0x0
|
|
|
|
- name: main
|
|
type: code
|
|
start: 0x800
|
|
vram: 0x80010000
|
|
# align 4 (not the code-segment default 16): the text→data boundary at vram
|
|
# 0x800629DC is word-aligned but not 16-aligned, so ALIGN(.,16) would inject
|
|
# 4 padding bytes the original lacks. MIPS is word-aligned, so ALIGN(.,4) is a
|
|
# no-op at every real boundary here.
|
|
align: 4
|
|
subsegments:
|
|
# Per-module optimization mixing (SETUP §5.5): the boot/main/game-mode-dispatch
|
|
# module (vram 0x80010000-0x800123F0) was compiled at -O0; the rest of the text at
|
|
# -O2. Split into two c-subsegments so the Makefile applies per-file flags
|
|
# (build/src/boot.o is overridden to -O0). The split is byte-identical at 100%
|
|
# INCLUDE_ASM (Phase-7 regression gate) — opt level only affects matched C, not stubs.
|
|
# Boundary = func_800123F0 (vram 0x800123F0 -> file vram-0x8000F800 = 0x2BF0).
|
|
- [0x800, c, boot] # -O0 boot module -> src/boot.c (vram 0x80010000-0x800123F0)
|
|
- [0x2BF0, c, 800] # -O2 game code -> src/800.c (vram 0x800123F0-0x8003A444); name "800" kept (legacy) so the matched fns + their asm/nonmatchings/800 paths don't migrate
|
|
# PsyQ libspu+libsnd COMBINED sound region (Phase 8): the two SDK sound libs are interleaved here,
|
|
# so they link as one 60-object region (curated by tools/make_snd_used.py; 4 addresses excluded as
|
|
# scattered-.bss/false-positive stubs: S_R/S_W 0x3C438, S_GRMDT* 0x3D424, S_IH/UT_RON 0x3D94C,
|
|
# VM_F 0x3FA64). Subsegs via gen_lib_subsegs.py; integrate window 0x3A444..0x4239C. snd1..snd9 link;
|
|
# sgap* = game code + the 4 excluded stubs. (libsnd SSGM.o @0x1BD80 stays a stub in 800.)
|
|
- [0x2AC44, c, snd1] # snd block 1: 15 obj (S_INI.o..S_SK.o) vram 0x8003A444-0x8003C438
|
|
- [0x2CC38, c, sgap] # game code (vram 0x8003C438-0x8003C498)
|
|
- [0x2CC98, c, snd2] # snd block 2: 8 obj (S_STSA.o..S_SRMD.o) vram 0x8003C498-0x8003D424
|
|
- [0x2DC24, c, sgap_2] # game code + excluded S_GRMDT stub (vram 0x8003D424-0x8003D434)
|
|
- [0x2DC34, c, snd3] # snd block 3: 4 obj (S_GRMD.o..SSINIT.o) vram 0x8003D434-0x8003D630
|
|
- [0x2DE30, c, sgap_3] # game code (vram 0x8003D630-0x8003D650)
|
|
- [0x2DE50, c, snd4] # snd block 4: 3 obj (SSSATTR.o..SSCALL.o) vram 0x8003D650-0x8003DC90
|
|
- [0x2E490, c, sgap_4] # game code (vram 0x8003DC90-0x8003E248)
|
|
- [0x2EA48, c, snd5] # snd block 5: 1 obj (PAUSE.o) vram 0x8003E248-0x8003E2E4
|
|
- [0x2EAE4, c, sgap_5] # game code (vram 0x8003E2E4-0x8003E310)
|
|
- [0x2EB10, c, snd6] # snd block 6: 12 obj (MIDIREAD.o..VM_ALOC2.o) vram 0x8003E310-0x8003FA54
|
|
- [0x30254, c, sgap_6] # game code + excluded VM_F stub (vram 0x8003FA54-0x8003FE18)
|
|
- [0x30618, c, snd7] # snd block 7: 5 obj (S_SNV.o..VM_N2P.o) vram 0x8003FE18-0x800403A4
|
|
- [0x30BA4, c, sgap_7] # game code (vram 0x800403A4-0x80040868)
|
|
- [0x31068, c, snd8] # snd block 8: 1 obj (VM_NOWOF.o) vram 0x80040868-0x80040938
|
|
- [0x31138, c, sgap_8] # game code (vram 0x80040938-0x800414E4)
|
|
- [0x31CE4, c, snd9] # snd block 9: 11 obj (VM_VSU.o..VS_VTC.o) vram 0x800414E4-0x8004239C
|
|
# PsyQ libetc region (Phase 8): 5 objects (VSYNC/INTR/INTR_VB/INTR_DMA/VMODE) form ONE
|
|
# contiguous block at the tail of the old 800 subseg, ending exactly at libcd1 (0x80043088).
|
|
# psyq_integrate swaps src/libetc.o(.text) -> build/psyq/libetc/*.o + NOLOAD data (libcd model).
|
|
- [0x32B9C, c, libetc] # libetc block -> src/libetc.c (vram 0x8004239C-0x80043088, 5 objs)
|
|
# PsyQ libcd region (Phase 7 Task 2'): the real libcd objects are linked here in place of
|
|
# stubs (the .ld swaps build/src/libcd{1,2}.o -> build/psyq/libcd/*.o + NOLOAD data). The
|
|
# 18 objects form two contiguous blocks split by a 76-B non-libcd gap (stays a stub).
|
|
- [0x33888, c, libcd1] # libcd block 1 -> src/libcd1.c (vram 0x80043088-0x80046980, 11 objs)
|
|
- [0x37180, c, gap] # non-libcd gap -> src/gap.c (vram 0x80046980-0x800469CC, stub)
|
|
- [0x371CC, c, libcd2] # libcd block 2 -> src/libcd2.c (vram 0x800469CC-0x8004787C, 7 objs)
|
|
# PsyQ libgs (Phase 7 Task #9, FULL integration): 31 libgs objects in 6 contiguous blocks
|
|
# across vram 0x80051804-0x80057928, separated by 5 non-libgs gaps. psyq_integrate swaps each
|
|
# block stub's build/src/libgsN.o(.text) for the real objects + NOLOAD data (same mechanism as
|
|
# libcd). The 5 gaps stay asm stubs (gsgapN): 80 / 48 / 1536[GS_001] / 48 / 304 B. GS_001 is
|
|
# EXCLUDED (scattered-.bss hard case, cookbook §9.1) and stays a stub (gsgap3). GS_106 (block 4)
|
|
# is an 8-ins object that only anchors uniquely within the libgs window, so make extract passes
|
|
# 0x80051804 0x80057928 to psyq_integrate. Object lists + disambiguation: tools/make_libgs.sh.
|
|
# PsyQ libgte (Phase 8): GTE matrix/vector math, 53 objects in 22 blocks across the old 800b region,
|
|
# interleaved with game code (800b/800b_2..800b_7). Subseg lines generated by gen_lib_subsegs.py
|
|
# (section-size-correct boundaries). integrate window 0x4787C..0x51804. The 5 libgs-gap libgte
|
|
# objects (MTX_05/07/11/REG03/REG11) are DEFERRED — gsgap1/2/4/5 stay stubs (see worklist).
|
|
- [0x3807C, c, libgte1] # libgte block 1: 5 obj (GEO_00.o..MSC00.o) vram 0x8004787C-0x80047D3C
|
|
- [0x3853C, c, 800b] # game code (vram 0x80047D3C-0x8004818C)
|
|
- [0x3898C, c, libgte2] # libgte block 2: 2 obj (MTX_000.o..MTX_001.o) vram 0x8004818C-0x8004838C
|
|
- [0x38B8C, c, libgte3] # libgte block 3: 5 obj (MTX_003.o..MTX_009.o) vram 0x8004838C-0x8004880C
|
|
- [0x3900C, c, libgte4] # libgte block 4: 3 obj (MTX_00B.o..MTX_01.o) vram 0x8004880C-0x80048CAC
|
|
- [0x394AC, c, libgte5] # libgte block 5: 5 obj (MTX_02.o..MTX_08.o) vram 0x80048CAC-0x8004914C
|
|
- [0x3994C, c, libgte6] # libgte block 6: 7 obj (MTX_09.o..REG12.o) vram 0x8004914C-0x8004923C
|
|
- [0x39A3C, c, libgte7] # libgte block 7: 1 obj (REG13.o) vram 0x8004923C-0x8004924C
|
|
- [0x39A4C, c, 800b_2] # game code (vram 0x8004924C-0x8004945C)
|
|
- [0x39C5C, c, libgte8] # libgte block 8: 3 obj (SMP_01.o..SMP_03.o) vram 0x8004945C-0x800495EC
|
|
- [0x39DEC, c, 800b_3] # game code (vram 0x800495EC-0x80049600)
|
|
- [0x39E00, c, libgte9] # libgte block 9: 1 obj (SMP_06.o) vram 0x80049600-0x80049610
|
|
- [0x39E10, c, 800b_4] # game code (vram 0x80049610-0x8004961C)
|
|
- [0x39E1C, c, libgte10] # libgte block 10: 1 obj (CMB_00.o) vram 0x8004961C-0x8004969C
|
|
- [0x39E9C, c, libgte11] # libgte block 11: 2 obj (CMB_05.o..FGO_00.o) vram 0x8004969C-0x8004978C
|
|
- [0x39F8C, c, 800b_5] # game code (vram 0x8004978C-0x8004A41C)
|
|
- [0x3AC1C, c, libgte12] # libgte block 12: 2 obj (PRS_F3.o..PRS_F4.o) vram 0x8004A41C-0x8004AE3C
|
|
- [0x3B63C, c, libgte13] # libgte block 13: 3 obj (PRS_G3.o..PRS_FT3.o) vram 0x8004AE3C-0x8004BE8C
|
|
- [0x3C68C, c, libgte14] # libgte block 14: 2 obj (PRS_FT4.o..PRS_GT3.o) vram 0x8004BE8C-0x8004C98C
|
|
- [0x3D18C, c, libgte15] # libgte block 15: 1 obj (PRS_GT4.o) vram 0x8004C98C-0x8004CFEC
|
|
- [0x3D7EC, c, libgte16] # libgte block 16: 1 obj (RATAN.o) vram 0x8004CFEC-0x8004D16C
|
|
- [0x3D96C, c, 800b_6] # game code (vram 0x8004D16C-0x8004D20C)
|
|
- [0x3DA0C, c, libgte17] # libgte block 17: 1 obj (TRR.o) vram 0x8004D20C-0x8004D6BC
|
|
- [0x3DEBC, c, libgte18] # libgte block 18: 2 obj (F3.o..F4.o) vram 0x8004D6BC-0x8004E19C
|
|
- [0x3E99C, c, libgte19] # libgte block 19: 1 obj (G3.o) vram 0x8004E19C-0x8004E74C
|
|
- [0x3EF4C, c, libgte20] # libgte block 20: 1 obj (G4.o) vram 0x8004E74C-0x8004EE0C
|
|
- [0x3F60C, c, libgte21] # libgte block 21: 2 obj (FT3.o..FT4.o) vram 0x8004EE0C-0x8004FA5C
|
|
- [0x4025C, c, libgte22] # libgte block 22: 2 obj (GT3.o..GT4.o) vram 0x8004FA5C-0x8005080C
|
|
- [0x4100C, c, 800b_7] # game code (vram 0x8005080C-0x80051804)
|
|
- [0x42004, c, libgs1] # libgs block 1: 2D_COM0 -> src/libgs1.c (vram 0x80051804-0x80051D78, 1 obj)
|
|
- [0x42578, c, gsgap1] # gap 80 B (non-libgs stub) -> src/gsgap1.c (vram 0x80051D78-0x80051DC8)
|
|
- [0x425C8, c, libgs2] # libgs block 2: 2D_LIN0/COM1/SP0 -> src/libgs2.c (vram 0x80051DC8-0x80052430, 3 objs)
|
|
- [0x42C30, c, gsgap2] # gap 48 B (non-libgs stub) -> src/gsgap2.c (vram 0x80052430-0x80052460)
|
|
- [0x42C60, c, libgs3] # libgs block 3: 2D_SP1 -> src/libgs3.c (vram 0x80052460-0x800525DC, 1 obj)
|
|
- [0x42DDC, c, gsgap3] # gap 1536 B: GS_001 excluded -> src/gsgap3.c (vram 0x800525DC-0x80052BDC)
|
|
- [0x433DC, c, libgs4] # libgs block 4: GS_002/003/MATRIX/103/104/105/106/107 -> src/libgs4.c (vram 0x80052BDC-0x800538BC, 8 objs)
|
|
- [0x440BC, c, gsgap4] # gap 48 B (non-libgs stub) -> src/gsgap4.c (vram 0x800538BC-0x800538EC)
|
|
- [0x440EC, c, libgs5] # libgs block 5: GS_108/109 -> src/libgs5.c (vram 0x800538EC-0x800539C8, 2 objs)
|
|
- [0x441C8, c, gsgap5] # gap 304 B (non-libgs stub) -> src/gsgap5.c (vram 0x800539C8-0x80053AF8)
|
|
- [0x442F8, c, libgs6] # libgs block 6 (16 objs) -> src/libgs6.c (vram 0x80053AF8-0x80057928)
|
|
- [0x48128, c, 800b2] # -O2 game code (post-libgs, pre-libgpu) -> src/800b2.c (vram 0x80057928-0x80058890)
|
|
# PsyQ libgpu (Phase 8): EXT/PRIM linked; SYS.o EXCLUDED — scattered-.bss commons (cookbook §9.1,
|
|
# the GS_001 class: SYS references .bss by section+offset but the original linker scattered the
|
|
# commons across 0x80078xxx/0x800c5xxx, so no single NOLOAD base reproduces it). SYS stays a stub
|
|
# in 800c. Curated dir .run/obj40/libgpu_used = {EXT,PRIM}.
|
|
- [0x49090, c, libgpu] # libgpu block -> src/libgpu.c (vram 0x80058890-0x80059234, EXT+PRIM)
|
|
- [0x49A34, c, 800c] # -O2 game code (incl. excluded libgpu SYS stub) -> src/800c.c (vram 0x80059234-0x8005C2C8)
|
|
# PsyQ libc2 (Phase 8): C stdlib. Main block = 16 objs (BZERO/MEMCPY/STRCMP/PRINTF/PRNT[jtbl ok]/
|
|
# …/SETJMP); STRCAT.o is a 2nd block at 0x80061E90 (start of the old 800c2). integrate libc2_1,libc2_2.
|
|
- [0x4CAC8, c, libc2_1] # libc2 main block (16 objs) -> src/libc2_1.c (vram 0x8005C2C8-0x8005CE18);
|
|
# end = SETJMP.o's .text SECTION size (0x80, 8-aligned), NOT its 30-ins
|
|
# count (0x78) — the trailing 8-byte align pad belongs to the object.
|
|
- [0x4D618, c, 800c3] # -O2 game code -> src/800c3.c (vram 0x8005CE18-0x8005FC68)
|
|
# PsyQ libmcrd (Phase 8): 2 objects — LIBMCRD.o (2186 ins; the 55 LIBMCRD_OBJ_* + _card_* memcard
|
|
# I/O) and USERFUNC.o (68 ins, at the very end), 2 non-adjacent blocks split by game/libc2/libapi/
|
|
# libcard code (800c2). psyq_integrate libmcrd1,libmcrd2. (The GAME save logic / Q#5 is Phase 12.)
|
|
- [0x50468, c, libmcrd1] # libmcrd block 1: LIBMCRD.o -> src/libmcrd1.c (vram 0x8005FC68-0x80061E90)
|
|
- [0x52690, c, libc2_2] # libc2 block 2: STRCAT.o -> src/libc2_2.c (vram 0x80061E90-0x80061F38)
|
|
# PsyQ libapi+libcard COMBINED 800c2 region (Phase 8): BIOS syscall trampolines + card I/O,
|
|
# 22 objects in 4 blocks (curated by tools/make_apicard_used.py; C112.o shared, no exclusions).
|
|
# integrate window 0x61F38..0x62888. (libapi's ~22 objects in the 800c3 region are DEFERRED.)
|
|
- [0x52738, c, apicard1] # apicard block 1: 7 obj (C112.o..A69.o) vram 0x80061F38-0x80061FA8
|
|
- [0x527A8, c, 800c2] # game code (vram 0x80061FA8-0x80062248)
|
|
- [0x52A48, c, apicard2] # apicard block 2: 7 obj (A66.o..INIT.o) vram 0x80062248-0x80062388
|
|
- [0x52B88, c, 800c2_2] # game code (vram 0x80062388-0x80062688)
|
|
- [0x52E88, c, apicard3] # apicard block 3: 4 obj (A18.o..A21.o) vram 0x80062688-0x800626C8
|
|
- [0x52EC8, c, 800c2_3] # game code (vram 0x800626C8-0x800627D8)
|
|
- [0x52FD8, c, apicard4] # apicard block 4: 4 obj (A74.o..END.o) vram 0x800627D8-0x80062888
|
|
- [0x53088, c, libmcrd2] # libmcrd block 2: USERFUNC.o -> src/libmcrd2.c (vram 0x80062888-0x80062998)
|
|
# Phase 7 (Task 2' / LZSS) — SURGICAL rodata carve for the LZSS switch only.
|
|
# The rodata island (0x80072A38-0x80074750) interleaves game jtbls, game data
|
|
# (loadDestPtrTable @0x80072C70 etc.) and library jtbls (PRESET/OBJT/PRNT @0x800737CC+),
|
|
# so a full-island migration is messy and hits the +24 .align-3 library artifact.
|
|
# But LZSS's jtbl_80072A38 is the FIRST jtbl (right after LzssStateTable/D_80072A34,
|
|
# right before jtbl_80072A4C), so carve ONLY it: a dotted .rodata sibling of the "800"
|
|
# code subseg covering exactly 0x63238-0x6324C migrates jtbl_80072A38 into
|
|
# asm/nonmatchings/800/LzssDecodeSector.s; everything else stays raw in the tail data.
|
|
# tools/ld_interleave.py then places .data(front) -> .rodata(LZSS jtbl) -> .data(tail).
|
|
# front data starts at 0x53198 (vram 0x80062998), NOT 0x531DC: the 68-B data descriptor
|
|
# table at 0x80062998-0x800629DC (boot.c's __do_global_dtors references D_80062998/D_800629D4)
|
|
# is data-in-text (cookbook §8). The big-800b era auto-labelled it; the libgs6 resegment made
|
|
# splat mis-detect it as func_80062998 (shadowing D_80062998). Carving it as the head of the
|
|
# front-data subseg forces the data labels deterministically. (ld_interleave FRONT_DATA matches.)
|
|
- [0x53198, data, 53198] # data table + front data (vram 0x80062998-0x80072A38)
|
|
- [0x63238, .rodata, 800] # LZSS jtbl_80072A38 ONLY (vram 0x80072A38-0x80072A4C) -> migrates into LzssDecodeSector
|
|
- [0x6324C, data, 6324C] # tail data: rest of island (raw) + globals (vram 0x80072A4C-0x80074800)
|
|
- [0x65000]
|