mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-28 06:49:47 -04:00
7df4895e7b
BYTE-IDENTICAL with NO function banked (gate_main --assert-baseline, clean rebuild), which is the whole point: the structure lands first and proves neutral, then drafts bank against it. One code object contributes exactly ONE contiguous .rodata run, and 800.o's is span A, so spans B and C each needed their own object: 800 vram 0x800123F0-0x8002B0B4 -> .rodata span A (0x80072A38-0x80072C70) 800_b vram 0x8002B0B4-0x80035270 -> .rodata span B (0x80072E44-0x80073140) 800_c vram 0x80035270-0x8003A444 -> .rodata span C (0x800732A0-0x8007344C) The span owners' address ranges are disjoint and ordered — tables pack tight WITHIN a TU and are separated by other data ACROSS TUs — so these are (at least some of) the original translation-unit boundaries. Splitting here is both the fix and the minimum; any extra split would be speculation. main's island is now a 7-piece data->rodata sandwich, so ld_interleave moves from --front/--tail to --order. THE SPLIT WAS CHEAP, AND MY FIRST ESTIMATE WAS WRONG. I costed it at '2,318 scattered extern lines' — that is the TOTAL; what matters is how many CROSS a boundary, and that is 57 of 1,247 declared names (4.6%), of which 19 are typedefs with exactly one definition each and zero shape conflicts. Zero file-local statics. src/800_shared.h carries exactly those, derived from the COMPILER's own errors rather than a regex model of C (R33), and each typedef was MOVED, never copied. Unlocks 17 functions / 4,471 instructions = 39% of what is left in main, incl. SaveLoadRoutine (1139) and func_8003388C (663).
240 lines
18 KiB
YAML
240 lines
18 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)
|
|
# P31 S72 — SPLIT AT THE JTBL-SPAN TU BOUNDARIES. One code object contributes exactly ONE
|
|
# contiguous `.rodata` run, so each jump-table span needs its own object. The span owners'
|
|
# address ranges are DISJOINT AND ORDERED, which is the evidence that these are (at least
|
|
# some of) the original translation-unit boundaries — tables pack tight WITHIN a TU and are
|
|
# separated by other data ACROSS TUs (§8e/§426). Splitting here is therefore both the fix
|
|
# and the minimum: any extra split would be speculation. `800` keeps its legacy name so the
|
|
# matched fns + their asm/nonmatchings/800 paths don't migrate.
|
|
- [0x2BF0, c, 800] # -O2 game code -> src/800.c (vram 0x800123F0-0x8002B0B4); owns .rodata span A
|
|
- [0x1B8B4, c, 800_b] # -O2 game code -> src/800_b.c (vram 0x8002B0B4-0x80035270); owns .rodata span B
|
|
- [0x25A70, c, 800_c] # -O2 game code -> src/800_c.c (vram 0x80035270-0x8003A444); owns .rodata span C
|
|
# 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)
|
|
# P31 S72 — SPAN EXTENSION. The Phase-7 carve stopped at the LZSS table because a FULL
|
|
# island migration hits the interleaved game data and the library jtbls. But the island
|
|
# opens with a CONTIGUOUS run of game tables owned entirely by subseg 800:
|
|
# 0x80072A38 jtbl (LzssDecodeSector, matched, cc1-emitted)
|
|
# 0x80072A4C A7C A94 AB4 ADC B0C B24 B3C B64 B88 BFC (11 tables, 8 stubbed owners)
|
|
# 0x80072C70 loadDestPtrTable <- first non-table datum, the span's hard end
|
|
# One code object may contribute exactly ONE contiguous .rodata run, and this whole run is
|
|
# 800.o's, in address order = src/800.c source order. So the span carves as one piece and
|
|
# the 3-piece data->rodata->data sandwich is unchanged in SHAPE, only in where it splits.
|
|
# This is what blocked every main switch function: gcc emits the drafted function's table
|
|
# into .rodata while the raw copy stayed here, so the image GREW (measured +28/+52/+76/+84
|
|
# on four drafts) and all 238 symbols above 0x80072A4C shifted. 25 of main's 59 frontier
|
|
# functions (6,215 of 12,912 instructions) are in that class.
|
|
# The island is data -> rodata -> data -> rodata -> data -> rodata -> data. Each `.rodata`
|
|
# piece is dotted onto the code subseg that OWNS those tables, so spimdisasm migrates each
|
|
# table into its referencing function and ld_interleave --order lays the pieces back down in
|
|
# address order. Span D (0x80073494-0x80073514) belongs to snd2, not to game code.
|
|
- [0x63238, .rodata, 800] # span A: LZSS jtbl + 11 game jtbls (vram 0x80072A38-0x80072C70)
|
|
- [0x63470, data, 63470] # loadDestPtrTable + globals (vram 0x80072C70-0x80072E44)
|
|
- [0x63644, .rodata, 800_b] # span B: 14 game jtbls (vram 0x80072E44-0x80073140)
|
|
- [0x63940, data, 63940] # globals (vram 0x80073140-0x800732A0)
|
|
- [0x63AA0, .rodata, 800_c] # span C: 8 game jtbls (vram 0x800732A0-0x8007344C)
|
|
- [0x63C4C, data, 63C4C] # tail: snd2 jtbls + globals (vram 0x8007344C-0x80074800)
|
|
- [0x65000]
|