mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-10-03 16:16:50 -04:00
feat(o0): md_MAIN_011 compiles -O0 — 21 functions / 4,321 ins unlocked, byte-proven
Its entire code subseg is the -O0 run and the .c is stub-only, so this is the boot
precedent: a whole-object CC1FLAGS override, no splat change, no carve, and none of
the 18-P29 re-disassembly risk. Proven byte-neutral by a CLEAN per-binary rebuild —
build dirs deleted, re-extract, rebuild:
sha1 80731bac0ddd6b3e354f43b2c179582b12590752 == config/check.md_MAIN_011.sha
Landed with the coupling fix it requires, or the 21 would have stayed invisible.
Three tools decided -O0-ness from the subseg NAME ('_o0' in it, or 'boot'); this
object keeps its plain name, so match_one would have warned 'cannot bank' about
functions that now bank and the wave draw would have kept refusing to draw them. All
three now ask corpus.o0_subseg(), which derives the answer from the Makefile itself
(R33: a name is a convention, the Makefile is ground truth).
Verified end to end: match_one compiles md_MAIN_011 targets at -O0 with the
cannot-bank warning correctly gone, the wave draw emits cards for them, and
test_o0_detect still passes 167/167 coverage with 0 false positives.
This commit is contained in:
@@ -724,6 +724,16 @@ $(WHALE_O0B_OBJS): CC1FLAGS := -quiet -O0 -G0 -mips1 -mcpu=3000 -mgas -msoft-flo
|
||||
O0_CLUSTER_OBJS := $(patsubst src/%.c,build/src/%.o,$(filter-out src/ov_SC01_077/ov_SC01_077_o0.c,$(wildcard src/ov_*/ov_*_o0.c)))
|
||||
$(O0_CLUSTER_OBJS): CC1FLAGS := -quiet -O0 -G0 -mips1 -mcpu=3000 -mgas -msoft-float -fgnu-linker
|
||||
|
||||
# md_MAIN_011 IS AN ENTIRELY -O0 MODULE (P31 S59, census in .run/s59_o0/). All 21 functions in its
|
||||
# single code subseg carry the -O0 frame-pointer prologue (`sw $fp` + `addu $fp,$sp,$zero`), the
|
||||
# .c is stub-only, and no -O0 glob matches `src/md_*/` at all — so its functions were unbankable no
|
||||
# matter how good a draft was, and the wave draw now refuses to draw them (build_wave_atlas's
|
||||
# `o0-in-an-O2-object` skip). Whole-object override, the `boot` precedent (§6): no splat change, no
|
||||
# carve, and therefore none of the §18-P29 re-disassembly risk. Byte-neutral while the file is
|
||||
# stub-only — proven by gating md_MAIN_011 when this landed. `corpus.o0_sources()` parses this rule,
|
||||
# so every -O0-aware tool picks the object up without a name convention.
|
||||
build/src/md_MAIN_011/md_MAIN_011.o: CC1FLAGS := -quiet -O0 -G0 -mips1 -mcpu=3000 -mgas -msoft-float -fgnu-linker
|
||||
|
||||
# link (the .ld pulls in the .o by path) + objcopy to the raw PS-X EXE image.
|
||||
$(OUT): $(OBJS) $(ASSET_OBJS) $(LD_SCRIPT)
|
||||
@set -e
|
||||
|
||||
@@ -273,8 +273,10 @@ def _o0_unbankable(spath):
|
||||
`addu $fp,$sp,$zero` inside the function's first instructions, anchored at `glabel` so a
|
||||
migrated jump table or .asciz blob ahead of the code is not read as the prologue."""
|
||||
seg = os.path.basename(os.path.dirname(str(spath)))
|
||||
if '_o0' in seg or seg == 'boot':
|
||||
return False # the build compiles this object -O0
|
||||
parts = os.path.normpath(str(spath)).split(os.sep)
|
||||
binary = 'main' if (len(parts) > 1 and parts[1] == 'nonmatchings') else parts[1]
|
||||
if corpus.o0_subseg(binary, seg):
|
||||
return False # the Makefile compiles this object -O0
|
||||
try:
|
||||
head, started = [], False
|
||||
for ln in open(os.path.join(REPO, str(spath))):
|
||||
|
||||
@@ -298,6 +298,21 @@ def o0_sources():
|
||||
return frozenset(out)
|
||||
|
||||
|
||||
def o0_subseg(binary, subseg):
|
||||
"""Is the OBJECT built from this asm subseg compiled at -O0?
|
||||
|
||||
Derived from the Makefile via o0_sources() (R33), not from the subseg NAME. Three tools used to
|
||||
ask `'_o0' in name or name == 'boot'` — a convention, and it broke the moment P31 S59 gave
|
||||
md_MAIN_011 a whole-object -O0 rule while it kept its plain name: `match_one` would have warned
|
||||
"this cannot bank" about 21 functions that now bank fine, and the wave draw would have kept
|
||||
refusing to draw them. A name is a convention; the Makefile is the ground truth.
|
||||
|
||||
The subseg name is the .c basename by construction (splat writes `src/<bin>/<subseg>.c`, and
|
||||
main's subsegs live at the tree root as `src/<subseg>.c`)."""
|
||||
rel = f"src/{subseg}.c" if binary == "main" else f"src/{binary}/{subseg}.c"
|
||||
return is_o0(rel)
|
||||
|
||||
|
||||
def is_o0(src_path):
|
||||
"""Is this .c compiled at -O0? `src_path` is repo-relative (a Stub.path) or absolute."""
|
||||
rel = os.path.relpath(src_path, REPO) if os.path.isabs(src_path) else src_path
|
||||
|
||||
+10
-1
@@ -97,12 +97,21 @@ def detect_o0(spath):
|
||||
|
||||
|
||||
_sub = os.path.basename(a.asm_subdir.rstrip('/'))
|
||||
# The BINARY, from the asm tree layout: asm/<bin>/nonmatchings/<sub> for every alias except main,
|
||||
# which splat writes at the tree root as asm/nonmatchings/<sub>.
|
||||
_parts = os.path.normpath(a.asm_subdir).split(os.sep)
|
||||
_bin = 'main' if (len(_parts) > 1 and _parts[1] == 'nonmatchings') else (_parts[1] if len(_parts) > 1 else 'main')
|
||||
# TWO ORACLES, and they answer different questions (R34). The PROLOGUE says what the target bytes
|
||||
# were compiled as; the SUBSEG NAME says what this build will compile the C as (Makefile:697/702/
|
||||
# 716/724 give `boot` and every `*_o0*.c` object -O0 flags). Either one alone is wrong somewhere:
|
||||
# `boot/start.s` has no ordinary prologue yet is built -O0, and an -O0 function sitting in an -O2
|
||||
# subseg has the prologue but cannot bank until it is carved.
|
||||
_sub_o0 = ('_o0' in _sub) or _sub == 'boot'
|
||||
try:
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
import corpus as _corpus
|
||||
_sub_o0 = _corpus.o0_subseg(_bin, _sub) # the Makefile is the ground truth, not the name
|
||||
except Exception:
|
||||
_sub_o0 = ('_o0' in _sub) or _sub == 'boot' # fallback: the old name convention
|
||||
_tell_o0 = detect_o0('%s/%s.s' % (a.asm_subdir, a.fn))
|
||||
_o0 = a.o0 or (not a.no_auto_o0 and (_tell_o0 or _sub_o0))
|
||||
if _o0 and not a.o0:
|
||||
|
||||
@@ -38,13 +38,19 @@ _NS = {"re": re, "os": os}
|
||||
exec(_FN, _NS)
|
||||
detect_o0 = _NS["detect_o0"]
|
||||
|
||||
sys.path.insert(0, os.path.join(REPO, "tools"))
|
||||
import corpus # noqa: E402
|
||||
|
||||
FAIL = []
|
||||
|
||||
|
||||
def sub_is_o0(path):
|
||||
"""Does the BUILD compile this subseg -O0? (Makefile:697/702/716/724)"""
|
||||
"""Does the BUILD compile this subseg -O0? Asked of the Makefile, never of the name (R33) —
|
||||
md_MAIN_011 keeps its plain name and is compiled -O0 by an explicit whole-object rule."""
|
||||
sub = os.path.basename(os.path.dirname(path))
|
||||
return ("_o0" in sub) or sub == "boot"
|
||||
parts = os.path.normpath(path).split(os.sep)
|
||||
binary = "main" if (len(parts) > 1 and parts[1] == "nonmatchings") else parts[1]
|
||||
return corpus.o0_subseg(binary, sub)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
Reference in New Issue
Block a user