mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-10-01 07:40:42 -04:00
fix(tools): jr_isolate_all was SILENTLY DELETING asm-label-alias definitions during a repartition
ROOT CAUSE (byte-witnessed, P30 S38 — the fifth tool with this same blindness).
A function banked under the §37/§73 DEFINITION-SIDE ASM-LABEL ALIAS form is spelled with a private
C identifier and bound to its real symbol by a GNU asm label:
void aF8018A860(s32, s16 *, u8 *, u8 *) __asm__("func_80183AF8"); <- decl, stays in preamble
void aF8018A860(s32, s16 *, u8 *, u8 *) { ... } <- THIS emits func_80183AF8
overlay_src_split.addr_of() resolves `func_<hex>` arithmetically and everything else through `syms`.
`aF8018A860` matches NEITHER, so it returned None — and partition() keeps only items with a
resolved address, so the definition was dropped from EVERY region. The file was then rewritten
without it and nothing said so. One carve of ov_SC02_028 deleted the definitions emitting BOTH
func_80183AF8 and func_80184268; the overlay stopped linking with `undefined reference`, and six
wave-6 drafts were written off against that as a plumbing/compiler wall.
TWO FIXES:
- CAUSE: overlay_src_split now builds an asm-label alias map from the source and resolves a
definition through its EMITTED SYMBOL rather than its C name (verified: aF8018A860 -> 0x80183AF8,
aF8018AFD0 -> 0x80184268 — exactly the two symbols the link was missing).
- SILENCE: partition() and jr_isolate_all._partition() now REFUSE to rewrite a file when any
construct's address does not resolve (R32), instead of discarding it. That guard alone would
have surfaced this the first time it happened.
RESULT: 3 of the 6 alias-class wave-6 drafts bank immediately, for ZERO agent tokens —
func_801884D8 (137 ins) · func_80180B04 (251) · func_801380E0 (438). R22 clean-fleet 140/140.
The other 3 (the three LARGEST: 557/513/710 ins) have a second, size-correlated cause — open.
NOTE FOR THE FLYWHEEL: family_remap._alias_decl_for ALREADY handled this exact form, and its
docstring records the identical lesson ("that blindness was the WHOLE of the h_seq sweep's 137 'no
matched unit' skips. The tool, not the compiler (R35)"). The fix was never propagated. The alias
form needs ONE shared oracle, the way §134 comment-masking ended up on cdecl._mask — five tools
have now independently rediscovered it.
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Reproduce the wave-6 ALIAS-CLASS link failure and INSPECT the post-carve tree, then revert.
|
||||
|
||||
harvest_verify does carve -> build -> revert, so the interesting state (where the asm-label alias
|
||||
definition ended up relative to its callers) is destroyed before anyone can look at it. This does
|
||||
the same carve, dumps the evidence, builds to capture the real linker error, and reverts.
|
||||
|
||||
READ THE EVIDENCE, DO NOT GUESS: the hypothesis under test is that `jr_isolate_all` repartitions the
|
||||
TU and separates the call site of `func_<X>` from the DEFINITION that emits it — which in this
|
||||
overlay is a §37/§124 definition-side asm-label alias:
|
||||
void aF8018A860(...) __asm__("func_80183AF8"); /* decl binds the symbol */
|
||||
void aF8018A860(...) { ... } /* THIS is what emits func_80183AF8 */
|
||||
A tool that moves code by ADDRESS cannot see that the symbol emitted at 0x80183AF8 is spelled
|
||||
`aF8018A860` in the source.
|
||||
|
||||
Usage: w6_alias_repro.py <ov> <fn> <callee_sym>
|
||||
"""
|
||||
import sys, os, re, glob, subprocess, shutil
|
||||
|
||||
OV, FN, CALLEE = sys.argv[1], sys.argv[2], sys.argv[3]
|
||||
PY = '.venv/bin/python'
|
||||
sys.path.insert(0, 'tools')
|
||||
import corpus
|
||||
|
||||
|
||||
def sh(cmd, **kw):
|
||||
return subprocess.run(cmd, capture_output=True, text=True, **kw)
|
||||
|
||||
|
||||
def snapshot(tag):
|
||||
print(f"\n----- {tag} -----")
|
||||
files = sorted(glob.glob(f'src/{OV}/*.c'))
|
||||
print(f" TUs in src/{OV}/: {len(files)}")
|
||||
for f in files:
|
||||
t = open(f).read()
|
||||
defs = len(re.findall(r'__asm__\s*\(\s*"' + re.escape(CALLEE) + r'"\s*\)', t))
|
||||
refs = len(re.findall(r'\b' + re.escape(CALLEE) + r'\b', t))
|
||||
stub = len(re.findall(r'INCLUDE_ASM\([^)]*\b' + re.escape(CALLEE) + r'\b', t))
|
||||
if defs or refs or stub:
|
||||
print(f" {os.path.basename(f):<46} asm-label-binds={defs} textual-refs={refs} INCLUDE_ASM={stub}")
|
||||
|
||||
|
||||
st = corpus.stubs(OV)
|
||||
addr = int(FN.split('_')[1], 16)
|
||||
rec = st.get(addr)
|
||||
if not rec:
|
||||
sys.exit(f"{FN} is not a live stub in {OV}")
|
||||
tu, stub_line = rec.path, f'INCLUDE_ASM("{rec.asm_dir}", {rec.symbol});'
|
||||
draft = open(f'.run/w6/{OV}/{FN}.c').read()
|
||||
|
||||
orig = open(tu).read()
|
||||
assert orig.count(stub_line) == 1, "stub line not unique"
|
||||
snapshot("BEFORE the carve (HEAD)")
|
||||
|
||||
print(f"\n[1] splicing the draft over the stub in {tu}")
|
||||
open(tu, 'w').write(orig.replace(stub_line, draft, 1))
|
||||
|
||||
print(f"[2] jtbl_carve {OV} --func {FN}")
|
||||
r = sh([PY, 'tools/jtbl_carve.py', OV, '--func', FN])
|
||||
out = (r.stdout or '') + (r.stderr or '')
|
||||
print(f" rc={r.returncode} {out.strip().splitlines()[-1][:130] if out.strip() else ''}")
|
||||
|
||||
if r.returncode:
|
||||
print(f"[3] carve refused -> jr_isolate_all --only {FN} (the §61b ladder: isolate WITH the body spliced)")
|
||||
r2 = sh([PY, 'tools/jr_isolate_all.py', OV, '--only', FN])
|
||||
print(f" isolate rc={r2.returncode}")
|
||||
r3 = sh(['make', '--no-print-directory', 'extract', f'BINARY={OV}'])
|
||||
print(f" extract rc={r3.returncode}")
|
||||
r = sh([PY, 'tools/jtbl_carve.py', OV, '--func', FN])
|
||||
print(f" carve retry rc={r.returncode}")
|
||||
sh(['make', '--no-print-directory', 'extract', f'BINARY={OV}'])
|
||||
|
||||
snapshot("AFTER the carve/isolation — WHERE DID THE ALIAS DEFINITION GO?")
|
||||
|
||||
print(f"\n[4] make build BINARY={OV} — the real linker error")
|
||||
rb = sh(['make', 'build', f'BINARY={OV}'])
|
||||
allout = (rb.stdout or '') + (rb.stderr or '')
|
||||
hits = [l for l in allout.splitlines()
|
||||
if 'undefined reference' in l or 'multiple definition' in l or re.search(r'\.[ch]:\d+.*error', l)]
|
||||
print(f" build rc={rb.returncode}, {len(hits)} hard diagnostic line(s):")
|
||||
for l in hits[:10]:
|
||||
print(" ", l.strip()[:190])
|
||||
|
||||
print("\n[5] reverting")
|
||||
sh(['git', 'checkout', '--', f'src/{OV}', 'config'])
|
||||
sh(['git', 'clean', '-fdq', f'src/{OV}'])
|
||||
sh(['make', '--no-print-directory', 'extract', f'BINARY={OV}'])
|
||||
print(" reverted + re-extracted (R22 corollary: a reverted config needs a re-extract)")
|
||||
+3
-3
@@ -1114,7 +1114,7 @@ ov_SC02_028_ELF := $(ov_SC02_028_OUT).elf
|
||||
ov_SC02_028_MAPFILE := $(ov_SC02_028_OUT).map
|
||||
ov_SC02_028_LD_SCRIPT := $(ov_SC02_028_OUT).ld
|
||||
ov_SC02_028_SPLAT_YAML := config/splat.ov_SC02_028.yaml
|
||||
ov_SC02_028_JTBL_INTERLEAVE := --order tail.data.o,ov_SC02_028.o,ov_SC02_028_jr_8012ACE0.o,tail2.data.o,ov_SC02_028_jr_80135888.o,tail3.data.o,ov_SC02_028_jr_80135A4C.o,tail4.data.o,ov_SC02_028_jr_80135D20.o,tail5.data.o,ov_SC02_028_jr_801380E0.o,ov_SC02_028_o0c.o,tail6.data.o,ov_SC02_028_jr_8013F350.o,tail7.data.o,ov_SC02_028_jr_8013FFD8.o,tail8.data.o,ov_SC02_028_jr_80140608.o,tail9.data.o,ov_SC02_028_jr_8015444C.o,ov_SC02_028_jr_80154C24.o,ov_SC02_028_jr_801588CC.o,ov_SC02_028_jr_80159C84.o,tail10.data.o,ov_SC02_028_jr_8015A3C8.o,tail11.data.o,ov_SC02_028_jr_8015AE2C.o,tail12.data.o,ov_SC02_028_jr_8015C32C.o,tail13.data.o,ov_SC02_028_jr_8016AB6C.o,tail14.data.o,ov_SC02_028_jr_80171B4C.o,ov_SC02_028_jr_801734BC.o,tail15.data.o,ov_SC02_028_jr_801789AC.o,ov_SC02_028_jr_80178D40.o,tail16.data.o,ov_SC02_028_jr_8017A4AC.o,tail17.data.o,ov_SC02_028_jr_8017AE2C.o,ov_SC02_028_jr_8017D898.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
|
||||
ov_SC02_028_JTBL_INTERLEAVE := --order tail.data.o,ov_SC02_028.o,ov_SC02_028_jr_8012ACE0.o,tail2.data.o,ov_SC02_028_jr_80135888.o,tail3.data.o,ov_SC02_028_jr_80135A4C.o,tail4.data.o,ov_SC02_028_jr_80135D20.o,tail5.data.o,ov_SC02_028_jr_801380E0.o,ov_SC02_028_o0c.o,tail6.data.o,ov_SC02_028_jr_8013F350.o,tail7.data.o,ov_SC02_028_jr_8013FFD8.o,tail8.data.o,ov_SC02_028_jr_80140608.o,tail9.data.o,ov_SC02_028_jr_8015444C.o,ov_SC02_028_jr_80154C24.o,ov_SC02_028_jr_801588CC.o,ov_SC02_028_jr_80159C84.o,tail10.data.o,ov_SC02_028_jr_8015A3C8.o,tail11.data.o,ov_SC02_028_jr_8015AE2C.o,tail12.data.o,ov_SC02_028_jr_8015C32C.o,tail13.data.o,ov_SC02_028_jr_8016AB6C.o,tail14.data.o,ov_SC02_028_jr_80171B4C.o,ov_SC02_028_jr_801734BC.o,tail15.data.o,ov_SC02_028_jr_801789AC.o,ov_SC02_028_jr_80178D40.o,tail16.data.o,ov_SC02_028_jr_8017A4AC.o,tail17.data.o,ov_SC02_028_jr_8017AE2C.o,ov_SC02_028_jr_8017D898.o,tail18.data.o,ov_SC02_028_jr_801884D8.o,tail19.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
|
||||
build/src/ov_SC02_028/ov_SC02_028.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14
|
||||
build/src/ov_SC02_028/ov_SC02_028_jr_8012ACE0.o: JTBL_PADS := 0,0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0xcc,+0xe0
|
||||
build/src/ov_SC02_028/ov_SC02_028_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18
|
||||
@@ -4288,7 +4288,7 @@ ov_SC06_020_ELF := $(ov_SC06_020_OUT).elf
|
||||
ov_SC06_020_MAPFILE := $(ov_SC06_020_OUT).map
|
||||
ov_SC06_020_LD_SCRIPT := $(ov_SC06_020_OUT).ld
|
||||
ov_SC06_020_SPLAT_YAML := config/splat.ov_SC06_020.yaml
|
||||
ov_SC06_020_JTBL_INTERLEAVE := --order tail.data.o,ov_SC06_020.o,ov_SC06_020_jr_8012ACE0.o,tail2.data.o,ov_SC06_020_jr_80135888.o,tail3.data.o,ov_SC06_020_jr_80135A4C.o,tail4.data.o,ov_SC06_020_jr_80135D20.o,tail5.data.o,ov_SC06_020_jr_801380E0.o,ov_SC06_020_o0c.o,tail6.data.o,ov_SC06_020_jr_8013F350.o,tail7.data.o,ov_SC06_020_jr_8013FFD8.o,tail8.data.o,ov_SC06_020_jr_80140608.o,tail9.data.o,ov_SC06_020_jr_8015444C.o,ov_SC06_020_jr_80154C24.o,ov_SC06_020_jr_801588CC.o,ov_SC06_020_jr_80159C84.o,tail10.data.o,ov_SC06_020_jr_8015A3C8.o,tail11.data.o,ov_SC06_020_jr_8015AE2C.o,tail12.data.o,ov_SC06_020_jr_8015C32C.o,tail13.data.o,ov_SC06_020_jr_8016AB6C.o,tail14.data.o,ov_SC06_020_jr_80171B4C.o,ov_SC06_020_jr_801734BC.o,tail15.data.o,ov_SC06_020_jr_801789AC.o,ov_SC06_020_jr_80178D40.o,tail16.data.o,ov_SC06_020_jr_8017A4AC.o,tail17.data.o,ov_SC06_020_jr_8017AE2C.o,ov_SC06_020_jr_8017C24C.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
|
||||
ov_SC06_020_JTBL_INTERLEAVE := --order tail.data.o,ov_SC06_020.o,ov_SC06_020_jr_8012ACE0.o,tail2.data.o,ov_SC06_020_jr_80135888.o,tail3.data.o,ov_SC06_020_jr_80135A4C.o,tail4.data.o,ov_SC06_020_jr_80135D20.o,tail5.data.o,ov_SC06_020_jr_801380E0.o,ov_SC06_020_o0c.o,tail6.data.o,ov_SC06_020_jr_8013F350.o,tail7.data.o,ov_SC06_020_jr_8013FFD8.o,tail8.data.o,ov_SC06_020_jr_80140608.o,tail9.data.o,ov_SC06_020_jr_8015444C.o,ov_SC06_020_jr_80154C24.o,ov_SC06_020_jr_801588CC.o,ov_SC06_020_jr_80159C84.o,tail10.data.o,ov_SC06_020_jr_8015A3C8.o,tail11.data.o,ov_SC06_020_jr_8015AE2C.o,tail12.data.o,ov_SC06_020_jr_8015C32C.o,tail13.data.o,ov_SC06_020_jr_8016AB6C.o,tail14.data.o,ov_SC06_020_jr_80171B4C.o,ov_SC06_020_jr_801734BC.o,tail15.data.o,ov_SC06_020_jr_801789AC.o,ov_SC06_020_jr_80178D40.o,tail16.data.o,ov_SC06_020_jr_8017A4AC.o,tail17.data.o,ov_SC06_020_jr_8017AE2C.o,ov_SC06_020_jr_8017C24C.o,tail18.data.o,ov_SC06_020_jr_80180B04.o,tail19.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
|
||||
build/src/ov_SC06_020/ov_SC06_020.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14
|
||||
build/src/ov_SC06_020/ov_SC06_020_jr_8012ACE0.o: JTBL_PADS := 0,0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0xcc,+0xe0
|
||||
build/src/ov_SC06_020/ov_SC06_020_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18
|
||||
@@ -4747,7 +4747,7 @@ ov_SC07_006_ELF := $(ov_SC07_006_OUT).elf
|
||||
ov_SC07_006_MAPFILE := $(ov_SC07_006_OUT).map
|
||||
ov_SC07_006_LD_SCRIPT := $(ov_SC07_006_OUT).ld
|
||||
ov_SC07_006_SPLAT_YAML := config/splat.ov_SC07_006.yaml
|
||||
ov_SC07_006_JTBL_INTERLEAVE := --order tail.data.o,ov_SC07_006.o,ov_SC07_006_jr_80131340.o,tail2.data.o,ov_SC07_006_jr_80135888.o,tail3.data.o,ov_SC07_006_jr_80135A4C.o,tail4.data.o,ov_SC07_006_jr_80135D20.o,tail5.data.o,ov_SC07_006_o0c.o,tail6.data.o,ov_SC07_006_jr_8013F350.o,tail7.data.o,ov_SC07_006_jr_8014032C.o,tail8.data.o,ov_SC07_006_jr_80140608.o,tail9.data.o,ov_SC07_006_jr_8015444C.o,ov_SC07_006_jr_80154C24.o,ov_SC07_006_jr_801588CC.o,ov_SC07_006_jr_80159C84.o,tail10.data.o,ov_SC07_006_jr_8015A3C8.o,tail11.data.o,ov_SC07_006_jr_8015B950.o,tail12.data.o,ov_SC07_006_jr_8015C32C.o,tail13.data.o,ov_SC07_006_jr_8016AE5C.o,tail14.data.o,ov_SC07_006_jr_80171B4C.o,tail15.data.o,ov_SC07_006_jr_801789AC.o,ov_SC07_006_jr_80179B74.o,tail16.data.o,ov_SC07_006_jr_8017AE2C.o,ov_SC07_006_jr_8017BEBC.o,tail17.data.o,ov_SC07_006_jr_80183814.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
|
||||
ov_SC07_006_JTBL_INTERLEAVE := --order tail.data.o,ov_SC07_006.o,ov_SC07_006_jr_80131340.o,tail2.data.o,ov_SC07_006_jr_80135888.o,tail3.data.o,ov_SC07_006_jr_80135A4C.o,tail4.data.o,ov_SC07_006_jr_80135D20.o,tail5.data.o,ov_SC07_006_jr_801380E0.o,ov_SC07_006_o0c.o,tail6.data.o,ov_SC07_006_jr_8013F350.o,tail7.data.o,ov_SC07_006_jr_8014032C.o,tail8.data.o,ov_SC07_006_jr_80140608.o,tail9.data.o,ov_SC07_006_jr_8015444C.o,ov_SC07_006_jr_80154C24.o,ov_SC07_006_jr_801588CC.o,ov_SC07_006_jr_80159C84.o,tail10.data.o,ov_SC07_006_jr_8015A3C8.o,tail11.data.o,ov_SC07_006_jr_8015B950.o,tail12.data.o,ov_SC07_006_jr_8015C32C.o,tail13.data.o,ov_SC07_006_jr_8016AE5C.o,tail14.data.o,ov_SC07_006_jr_80171B4C.o,tail15.data.o,ov_SC07_006_jr_801789AC.o,ov_SC07_006_jr_80179B74.o,tail16.data.o,ov_SC07_006_jr_8017AE2C.o,ov_SC07_006_jr_8017BEBC.o,tail17.data.o,ov_SC07_006_jr_80183814.o,tail18.data.o,trailing.o # Phase-26 §8 jtbl-rodata carve
|
||||
build/src/ov_SC07_006/ov_SC07_006.o: JTBL_PADS := 0,0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14,+0xdc
|
||||
build/src/ov_SC07_006/ov_SC07_006_jr_80131340.o: JTBL_PADS := 0,0 # §8e pads (jtbl_carve.py) tables=+0x0,+0x14
|
||||
build/src/ov_SC07_006/ov_SC07_006_jr_80135D20.o: JTBL_PADS := 0,4 # §8e pads (jtbl_carve.py) tables=+0x0,+0x18
|
||||
|
||||
@@ -121,6 +121,7 @@ segments:
|
||||
- [0x52354, c, ov_SC02_028_jr_8017A4AC]
|
||||
- [0x52cd4, c, ov_SC02_028_jr_8017AE2C]
|
||||
- [0x55740, c, ov_SC02_028_jr_8017D898]
|
||||
- [0x60380, c, ov_SC02_028_jr_801884D8]
|
||||
- [0x632a0, data, tail]
|
||||
- [0xa87e0, .rodata, ov_SC02_028] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0xa88bc, .rodata, ov_SC02_028_jr_8012ACE0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
@@ -164,6 +165,8 @@ segments:
|
||||
- [0xa9900, .rodata, ov_SC02_028_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0xa9914, .rodata, ov_SC02_028_jr_8017D898] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0xa9934, data, tail18]
|
||||
- [0xa9968, .rodata, ov_SC02_028_jr_801884D8] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0xa9980, data, tail19]
|
||||
- [0xAB4E4, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word)
|
||||
- [0xAB4E7] # EOF marker = the 0.4.dec byte length
|
||||
# @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes
|
||||
|
||||
@@ -121,6 +121,7 @@ segments:
|
||||
- [0x52354, c, ov_SC06_020_jr_8017A4AC]
|
||||
- [0x52cd4, c, ov_SC06_020_jr_8017AE2C]
|
||||
- [0x540f4, c, ov_SC06_020_jr_8017C24C]
|
||||
- [0x589ac, c, ov_SC06_020_jr_80180B04]
|
||||
- [0x5ceb8, data, tail]
|
||||
- [0x9001c, .rodata, ov_SC06_020] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0x900f8, .rodata, ov_SC06_020_jr_8012ACE0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
@@ -164,6 +165,8 @@ segments:
|
||||
- [0x9113c, .rodata, ov_SC06_020_jr_8017AE2C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0x91150, .rodata, ov_SC06_020_jr_8017C24C] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0x91184, data, tail18]
|
||||
- [0x91268, .rodata, ov_SC06_020_jr_80180B04] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0x9127c, data, tail19]
|
||||
- [0x92894, bin, trailing] # final 3 bytes (EOF not 4-aligned; spimdisasm drops a partial word)
|
||||
- [0x92897] # EOF marker = the 0.4.dec byte length
|
||||
# @TRAILING@ (above) is replaced by tools/new_overlay.sh: for a non-4-aligned overlay it becomes
|
||||
|
||||
@@ -98,6 +98,7 @@ segments:
|
||||
- [0xd730, c, ov_SC07_006_jr_80135888]
|
||||
- [0xd8f4, c, ov_SC07_006_jr_80135A4C]
|
||||
- [0xdbc8, c, ov_SC07_006_jr_80135D20]
|
||||
- [0xff88, c, ov_SC07_006_jr_801380E0]
|
||||
- [0x13410, c, ov_SC07_006_o0c]
|
||||
- [0x14834, c, ov_SC07_006_jr_8013C98C]
|
||||
- [0x171f8, c, ov_SC07_006_jr_8013F350]
|
||||
@@ -127,6 +128,7 @@ segments:
|
||||
- [0xcbc20, data, tail4]
|
||||
- [0xcbc24, .rodata, ov_SC07_006_jr_80135D20] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0xcbc68, data, tail5]
|
||||
- [0xcbc74, .rodata, ov_SC07_006_jr_801380E0] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0xcbcd8, .rodata, ov_SC07_006_o0c] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
- [0xcbe5c, data, tail6]
|
||||
- [0xcc2e4, .rodata, ov_SC07_006_jr_8013F350] # Phase-26 §8 jtbl-rodata carve (jtbl_carve.py)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1529,732 +1529,3 @@ int func_80137D08(int arg0, int arg1, short arg2)
|
||||
DEFINE_func_80137DD4() /* dedup: shared engine-core @0x80137DD4 (src/shared) */
|
||||
|
||||
DEFINE_func_80137FD8() /* dedup: shared engine-core @0x80137fd8 (src/shared) */
|
||||
|
||||
|
||||
INCLUDE_ASM("asm/ov_SC07_006/nonmatchings/ov_SC07_006_jr_80135D20", func_801380E0);
|
||||
|
||||
/* de-macroized: per-overlay-local decl for func_80138DE0 (byte-true sig); do NOT re-macroize */
|
||||
void func_801387B8(s32 arg0) {
|
||||
extern s32 func_80138DE0(u8*, u8, s32);
|
||||
extern s32 func_80139220(s32 a0);
|
||||
extern void func_80138948(void *a0);
|
||||
extern void func_80139A8C(s32 a0);
|
||||
extern void func_80139B18(s32 a0);
|
||||
extern s32 D_80127530[];
|
||||
u16 *p;
|
||||
s32 base;
|
||||
s32 cont;
|
||||
u8 cmd;
|
||||
s32 sub;
|
||||
s32 pc;
|
||||
for (;;) {
|
||||
cont = 0;
|
||||
if (*(s32 *)(arg0 + 8) & 0x400) {
|
||||
base = D_80127530[*(u16 *)(arg0 + 0x4A)];
|
||||
p = (u16 *)(arg0 + 0x44);
|
||||
} else {
|
||||
p = (u16 *)(arg0 + 0x10);
|
||||
base = *(s32 *)(arg0 + 0);
|
||||
}
|
||||
pc = *p;
|
||||
cmd = *(u8 *)(base + pc);
|
||||
sub = *(u8 *)(base + pc + 1);
|
||||
if (cmd >= 0x20) {
|
||||
cont = func_80138DE0(arg0, cmd, sub);
|
||||
if (!(*(s32 *)(arg0 + 8) & 0x80220)) {
|
||||
cont = 0;
|
||||
}
|
||||
} else {
|
||||
if (cmd != 0) {
|
||||
switch (cmd) {
|
||||
case 10:
|
||||
func_80139220(arg0);
|
||||
*p += 1;
|
||||
goto loop_end;
|
||||
case 1:
|
||||
cont = 1;
|
||||
*(u8 *)(arg0 + 0x23) = sub;
|
||||
*p += 2;
|
||||
goto loop_end;
|
||||
case 7:
|
||||
if (!(*(s32 *)(arg0 + 8) & 0x20000)) {
|
||||
*(s32 *)(arg0 + 8) &= ~0x20;
|
||||
}
|
||||
break;
|
||||
case 23:
|
||||
*(s32 *)(arg0 + 8) |= 2;
|
||||
default:
|
||||
cont = 1;
|
||||
*p += 1;
|
||||
goto loop_end;
|
||||
}
|
||||
}
|
||||
func_80138948((void *)arg0);
|
||||
}
|
||||
loop_end:
|
||||
if (cont == 0) {
|
||||
func_80139A8C(arg0);
|
||||
func_80139B18(arg0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} /* dedup: shared engine-core @0x801387B8 (src/shared) */
|
||||
|
||||
DEFINE_func_80138948() /* dedup: shared engine-core @0x80138948 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013895C() /* dedup: shared engine-core @0x8013895c (src/shared) */
|
||||
|
||||
|
||||
/* de-macroized: per-overlay-local decl for func_80138DE0 (byte-true sig); do NOT re-macroize */
|
||||
extern s16 D_80127540[4];
|
||||
extern s32 func_80139D04(s32 a0, s32 a1);
|
||||
extern s32 func_80138DE0(u8*, u8, s32);
|
||||
extern void func_80139B18(s32 a0);
|
||||
void func_80138AB4(s32 a0) {
|
||||
u8 sp10[8];
|
||||
s32 s0 = a0;
|
||||
s32 s1;
|
||||
s32 a0v;
|
||||
s1 = func_80139D04((s32)sp10, (u16)D_80127540[*(u16 *)(s0 + 0x48)]) & 0xFFFF;
|
||||
do {
|
||||
s32 v1 = *(u16 *)(s0 + 0x44);
|
||||
a0v = 0;
|
||||
if ((s32)v1 < s1) {
|
||||
s32 a1v = (sp10[v1] + 0x30) & 0xFF;
|
||||
a0v = func_80138DE0(s0, a1v, 0);
|
||||
if (*(s32 *)(s0 + 0x8) & 0x80220) {
|
||||
/* a0v stays */
|
||||
} else {
|
||||
a0v = 0;
|
||||
}
|
||||
} else {
|
||||
s32 t = *(u16 *)(s0 + 0x48);
|
||||
if ((u32)t < 3) {
|
||||
*(s16 *)(s0 + 0x48) = t + 1;
|
||||
}
|
||||
*(s16 *)(s0 + 0x4) = 2;
|
||||
}
|
||||
} while (a0v != 0);
|
||||
func_80139B18(s0);
|
||||
} /* dedup: shared engine-core @0x80138ab4 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80138B88() /* dedup: shared engine-core @0x80138b88 (src/shared) */
|
||||
|
||||
|
||||
|
||||
// @class: struct
|
||||
// @stuck: none — MATCH (match_one: MATCH 20 ins)
|
||||
|
||||
|
||||
void func_80138BE0(int p)
|
||||
{
|
||||
|
||||
extern void (*D_8018AA10[])(void);
|
||||
if (*(unsigned short *)(p + 0xe) != 0) {
|
||||
*(unsigned short *)(p + 0xe) -= 1;
|
||||
}
|
||||
D_8018AA10[*(short *)(p + 4)]();
|
||||
}
|
||||
|
||||
|
||||
void func_80138C30(void *a0) {
|
||||
if (*(s16 *)((s32)a0 + 4) == 4) {
|
||||
*(s16 *)((s32)a0 + 4) = 2;
|
||||
} else {
|
||||
*(u32 *)((s32)a0 + 8) |= 0x800;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extern s32 func_80139BE0(s32);
|
||||
|
||||
s32 func_80138C60(s32 arg0)
|
||||
{
|
||||
typedef struct {
|
||||
u8 b0;
|
||||
u8 b1;
|
||||
u8 b2;
|
||||
u8 b3;
|
||||
} Q_80138C60;
|
||||
extern Q_80138C60 D_8018A9DC[];
|
||||
u16 t;
|
||||
u8 b;
|
||||
s32 f;
|
||||
s32 idx;
|
||||
|
||||
if (*(s32 *)(arg0 + 8) & 0x2000) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
t = *(u8 *)(arg0 + 0x22) & 7;
|
||||
*(s16 *)(arg0 + 0x18) = t;
|
||||
if (t < 2) {
|
||||
*(u8 *)(arg0 + 0x20) = 0;
|
||||
}
|
||||
|
||||
f = *(s32 *)(arg0 + 8);
|
||||
if (f & 0x40) {
|
||||
*(u8 *)(arg0 + 0x22) = (*(u8 *)(arg0 + 0x22) & 0x67) | (f & ~0x67);
|
||||
}
|
||||
|
||||
b = *(u8 *)(arg0 + 0x22);
|
||||
if (b & 0x80) {
|
||||
idx = (b & 0x18) >> 3;
|
||||
} else {
|
||||
idx = (b & 0x78) >> 3;
|
||||
if (b & 0x60) {
|
||||
*(s16 *)(arg0 + 0x1C) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*(Q_80138C60 *)(arg0 + 0x24) = D_8018A9DC[idx];
|
||||
|
||||
func_80139BE0(arg0);
|
||||
func_80139C7C((u8 *)arg0);
|
||||
return func_8013A8FC(arg0);
|
||||
}
|
||||
|
||||
|
||||
DEFINE_func_80138D58() /* dedup: shared engine-core @0x80138d58 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80138DB8() /* dedup: shared engine-core @0x80138db8 (src/shared) */
|
||||
|
||||
|
||||
// @class: struct
|
||||
// @stuck: none — MATCH
|
||||
/* func_80138DE0 — advance the text cursor by 1 or 2 after emitting a glyph.
|
||||
*
|
||||
* Key levers (both required; the body itself is a plain if/else-if):
|
||||
* - D_80127548 MUST be declared as an ARRAY (`extern s32 D_80127548[];`) and accessed as
|
||||
* D_80127548[0]. As a scalar, gcc emits the assembler-macro form twice in the tail
|
||||
* (lui+lw %lo / lui+sw %lo via $at, 8 insns); as an array the address is materialised once
|
||||
* (la $v1 = lui+addiu) and the lw/sw use 0($v1), which is what the target does and is one
|
||||
* instruction shorter. This is the §40b indexed-global idiom, and it is also the form the
|
||||
* shared engine-core macro DEFINE_func_80138ED0() already uses for this same symbol.
|
||||
* - arg1 is a byte param (u8): each use re-emits `andi ...,0xFF` (§I2), which is why the
|
||||
* 0x20-subtraction path recomputes the mask instead of reusing $v1.
|
||||
* - The 2nd argument of func_80138ED0 is u32, so the (u16) cast supplies the `andi 0xFFFF`.
|
||||
* - The `if (arg2 != 0) return 0;` tail check is redundant on the two call paths; gcc's
|
||||
* thread_jumps folds them straight to the return-0 tails (.L80138EB8 / .L80138EBC), and the
|
||||
* `*p = ...` store is cross-jumped between the +2 and +1 arms.
|
||||
*/
|
||||
#include "common.h"
|
||||
|
||||
extern s32 D_80127548[];
|
||||
extern u8 D_800D3AB4[];
|
||||
extern s32 func_80138ED0(u8 *param_1, u32 param_2, u8 *param_3);
|
||||
|
||||
s32 func_80138DE0(u8 *arg0, u8 arg1, s32 arg2) {
|
||||
u16 *p;
|
||||
|
||||
if (D_80127548[0] == 0) {
|
||||
return 0;
|
||||
}
|
||||
p = (u16 *)(arg0 + 0x44);
|
||||
if ((*(u32 *)(arg0 + 8) & 0x400) == 0) {
|
||||
p = (u16 *)(arg0 + 0x10);
|
||||
if (*(s16 *)(arg0 + 4) == 8) {
|
||||
p = (u16 *)(arg0 + 0x44);
|
||||
}
|
||||
}
|
||||
if (arg1 >= 0xE0) {
|
||||
arg2 = func_80138ED0(arg0, 0x1F, D_800D3AB4);
|
||||
if (arg2 != 0) {
|
||||
return 0;
|
||||
}
|
||||
*p = *p + 2;
|
||||
} else if (arg1 >= 0x20) {
|
||||
arg2 = func_80138ED0(arg0, (u16)(arg1 - 0x20), D_800D3AB4);
|
||||
if (arg2 != 0) {
|
||||
return 0;
|
||||
}
|
||||
*p = *p + 1;
|
||||
}
|
||||
if (arg2 != 0) {
|
||||
return 0;
|
||||
}
|
||||
D_80127548[0] = D_80127548[0] - 1;
|
||||
return D_80127548[0];
|
||||
}
|
||||
|
||||
|
||||
DEFINE_func_80138ED0() /* dedup: shared engine-core @0x80138ed0 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013914C() /* dedup: shared engine-core @0x8013914c (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_801391F0() /* dedup: shared engine-core @0x801391f0 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139220() /* dedup: shared engine-core @0x80139220 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_801392C8() /* dedup: shared engine-core @0x801392c8 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_801392FC() /* dedup: shared engine-core @0x801392fc (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_801395D4() /* dedup: shared engine-core @0x801395D4 (src/shared) */
|
||||
|
||||
DEFINE_func_80139634() /* dedup: shared engine-core @0x80139634 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139680() /* dedup: shared engine-core @0x80139680 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139788() /* dedup: shared engine-core @0x80139788 (src/shared) */
|
||||
|
||||
|
||||
|
||||
extern void GsSortSprite(void *a0, u8 *a1, s32 a2);
|
||||
|
||||
void func_801397B0(s32 arg0)
|
||||
{
|
||||
|
||||
extern short D_800B9A02;
|
||||
extern u8 D_800A6518[];
|
||||
extern u8 D_8018AA54;
|
||||
extern u8 D_8018AA98;
|
||||
register u8 *e __asm__("$7");
|
||||
register s32 off __asm__("$4");
|
||||
s32 buf[12];
|
||||
u8 *b164;
|
||||
u8 *b1A8;
|
||||
s32 sc;
|
||||
s32 t2;
|
||||
s32 t0;
|
||||
s32 hi;
|
||||
s32 lo;
|
||||
s32 uu;
|
||||
s32 vv;
|
||||
|
||||
e = (u8 *)arg0;
|
||||
b164 = (u8 *)&D_8018AA54;
|
||||
off = ((s32)*(u8 *)(e + 0x20) - 1) << 2;
|
||||
b164 = off + b164;
|
||||
|
||||
*(s32 *)((u8 *)buf + 0x00) = 0;
|
||||
|
||||
t2 = *(s16 *)(b164 + 2);
|
||||
t0 = *(s16 *)(b164 + 0);
|
||||
hi = (t2 & 0x100) >> 4;
|
||||
lo = ((t0 & 0x3C0) >> 6) | 0x20;
|
||||
*(s16 *)((u8 *)buf + 0x0C) = hi | lo | ((t2 & 0x200) << 2);
|
||||
|
||||
b1A8 = (u8 *)&D_8018AA98 + off;
|
||||
*(s16 *)((u8 *)buf + 0x10) = *(u16 *)(b1A8 + 0);
|
||||
*(s16 *)((u8 *)buf + 0x12) = *(u16 *)(b1A8 + 2);
|
||||
*(u8 *)((u8 *)buf + 0x16) = 0x80;
|
||||
*(u8 *)((u8 *)buf + 0x15) = 0x80;
|
||||
*(u8 *)((u8 *)buf + 0x14) = 0x80;
|
||||
*(s16 *)((u8 *)buf + 0x06) = *(u16 *)(e + 0x32);
|
||||
*(s16 *)((u8 *)buf + 0x08) = 0x20;
|
||||
*(s16 *)((u8 *)buf + 0x0A) = 0x28;
|
||||
|
||||
uu = (*(u16 *)(b164 + 0) & 0x3F) << 2;
|
||||
*(u8 *)((u8 *)buf + 0x0E) = uu;
|
||||
vv = *(u16 *)(b164 + 2);
|
||||
*(u8 *)((u8 *)buf + 0x0F) = vv;
|
||||
|
||||
if (*(u8 *)(e + 0x22) & 8) {
|
||||
*(s16 *)((u8 *)buf + 0x04) =
|
||||
*(u16 *)(e + 0x30) + *(u16 *)(e + 0x34) + 0x28;
|
||||
sc = -*(u16 *)(e + 0x28);
|
||||
} else {
|
||||
*(s16 *)((u8 *)buf + 0x04) = *(u16 *)(e + 0x30) - 0x28;
|
||||
sc = *(u16 *)(e + 0x28);
|
||||
}
|
||||
*(s16 *)((u8 *)buf + 0x1C) = sc;
|
||||
*(s16 *)((u8 *)buf + 0x1E) = *(u16 *)(e + 0x2A);
|
||||
*(s16 *)((u8 *)buf + 0x1A) = 0;
|
||||
*(s16 *)((u8 *)buf + 0x18) = 0;
|
||||
*(s32 *)((u8 *)buf + 0x20) = 0;
|
||||
|
||||
GsSortSprite(buf, &D_800A6518[(u16)D_800B9A02 * 20],
|
||||
*(u16 *)(e + 0x1A));
|
||||
}
|
||||
|
||||
|
||||
DEFINE_func_80139914() /* dedup: shared engine-core @0x80139914 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139954() /* dedup: shared engine-core @0x80139954 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_801399A8() /* dedup: shared engine-core @0x801399a8 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_801399F0() /* dedup: shared engine-core @0x801399f0 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139A34() /* dedup: shared engine-core @0x80139a34 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139A44() /* dedup: shared engine-core @0x80139a44 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139A68() /* dedup: shared engine-core @0x80139a68 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139A8C() /* dedup: shared engine-core @0x80139a8c (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139B18() /* dedup: shared engine-core @0x80139b18 (src/shared) */
|
||||
|
||||
|
||||
|
||||
/* func_80139BE0 — ov_SC01_077 / ov_SC01_077_jr_801380E0, 39 ins, MATCH.
|
||||
*
|
||||
* REDRAFT of the decayed backlog draft: the stored draft was -1 instruction
|
||||
* (LENGTH-DRIFT) because the target keeps a QI->SI zero-extend of the masked
|
||||
* byte (`andi $a1,$v0,0xFF` after `andi $v0,$v0,0x60`) that gcc-2.7.2 folds
|
||||
* away: combine proves nonzero_bits(x & 0x60) <= 0xff and simplifies the
|
||||
* extend to nothing. No pure-C spelling survives that fold when the def and
|
||||
* the extend sit in the SAME basic block (verified: u8 local, (u8) cast at
|
||||
* the use, `& 0xff` at the use, u8-via-int, u16 hold, hard-register pins) —
|
||||
* a cross-BB def keeps it but lands the andi in the wrong block.
|
||||
* The opacity idiom (already used in src/ov_SC03_099) makes the value's range
|
||||
* unprovable in place, so the extend survives at its original position.
|
||||
* cookbook §1/I2 ("masked andi survives only if the value's range is
|
||||
* unprovable"), §17 (pins/barriers).
|
||||
*/
|
||||
|
||||
s32 func_80139BE0(int param_1)
|
||||
{
|
||||
|
||||
extern unsigned char D_8018A9D8[];
|
||||
int v;
|
||||
|
||||
if ((*(unsigned int *)(param_1 + 8) & 0x2000) == 0) {
|
||||
int t = *(unsigned char *)(param_1 + 0x22) & 0x60;
|
||||
int h = *(unsigned short *)(param_1 + 0x18);
|
||||
unsigned int idx;
|
||||
|
||||
__asm__("" : "=r"(t) : "0"(t));
|
||||
idx = (unsigned char)t;
|
||||
if (h < 7) {
|
||||
if (h >= 2) {
|
||||
v = D_8018A9D8[idx >> 5];
|
||||
} else {
|
||||
v = D_8018A9D8[0];
|
||||
}
|
||||
} else {
|
||||
v = D_8018A9D8[0];
|
||||
}
|
||||
*(short *)(param_1 + 0x2e) = 3;
|
||||
*(short *)(param_1 + 0x2c) = v;
|
||||
}
|
||||
*(short *)(param_1 + 0x34) = *(short *)(param_1 + 0x2c) * 6;
|
||||
{
|
||||
int x = *(short *)(param_1 + 0x2e);
|
||||
*(short *)(param_1 + 0x36) = x * 12 + (x - 1) * 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFINE_func_80139C7C() /* dedup: shared engine-core @0x80139c7c (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139D04() /* dedup: shared engine-core @0x80139d04 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139DC8() /* dedup: shared engine-core @0x80139dc8 (src/shared) */
|
||||
|
||||
|
||||
void func_80139DEC(void) {
|
||||
}
|
||||
|
||||
DEFINE_func_80139DF4() /* dedup: shared engine-core @0x80139df4 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139E84() /* dedup: shared engine-core @0x80139e84 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139F0C() /* dedup: shared engine-core @0x80139f0c (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139FBC() /* dedup: shared engine-core @0x80139fbc (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_80139FE8() /* dedup: shared engine-core @0x80139fe8 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A0A4() /* dedup: shared engine-core @0x8013a0a4 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A164() /* dedup: shared engine-core @0x8013a164 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A1E8() /* dedup: shared engine-core @0x8013a1e8 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A250() /* dedup: shared engine-core @0x8013a250 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A2BC() /* dedup: shared engine-core @0x8013a2bc (src/shared) */
|
||||
|
||||
|
||||
void func_8013A378(void) {
|
||||
}
|
||||
|
||||
DEFINE_func_8013A380() /* dedup: shared engine-core @0x8013a380 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A448() /* dedup: shared engine-core @0x8013a448 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A4C4() /* dedup: shared engine-core @0x8013a4c4 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A530() /* dedup: shared engine-core @0x8013a530 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A860() /* dedup: shared engine-core @0x8013a860 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A8B0() /* dedup: shared engine-core @0x8013a8b0 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A8BC() /* dedup: shared engine-core @0x8013a8bc (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A8FC() /* dedup: shared engine-core @0x8013a8fc (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A9B4() /* dedup: shared engine-core @0x8013a9b4 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013A9F8() /* dedup: shared engine-core @0x8013a9f8 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013AA24() /* dedup: shared engine-core @0x8013aa24 (src/shared) */
|
||||
|
||||
|
||||
extern void func_8013AD38(void *a0, s32 a1, void *a2, void *a3);
|
||||
extern void func_8013B274(s32 a0, s32 a1, void *a2);
|
||||
extern void func_8013AF20();
|
||||
s32 func_8013AB54(s32 a0, s32 a1, s32 a2, s32 a3) {
|
||||
|
||||
extern s32 D_800A5E60;
|
||||
u8 buf[0xE4]; /* spans 0x10 .. 0xF4 */
|
||||
s32 neg;
|
||||
s32 a, b;
|
||||
s32 t4, t6;
|
||||
t4 = *(s16 *)(a2 + 4) * 12;
|
||||
*(s16 *)(buf + 0xE0) = t4 + 0x10; /* sp+0xF0 */
|
||||
neg = a3 & 0x8000;
|
||||
t6 = *(s16 *)(a2 + 6) * 12 + (*(s16 *)(a2 + 6) - 1) * 2;
|
||||
*(s16 *)(buf + 0xE2) = t6 + 8;
|
||||
if (neg == 0) {
|
||||
*(s16 *)(buf + 0xE0) = t4 + 0x38;
|
||||
*(s16 *)(buf + 0xE2) = t6 + 0x10;
|
||||
}
|
||||
a = ((s32)*(s16 *)(buf + 0xE0) << 12) / 154;
|
||||
b = ((s32)*(s16 *)(buf + 0xE2) << 12) / 42;
|
||||
*(s16 *)(buf + 0xE0) = a;
|
||||
*(s16 *)(buf + 0xE2) = b;
|
||||
if (neg != 0) {
|
||||
*(s16 *)(buf + 0xE0) = -a;
|
||||
}
|
||||
*(s16 *)(buf + 0xC8) = b; /* 0xD8 */
|
||||
*(s16 *)(buf + 0xC2) = 0; /* 0xD2 */
|
||||
*(s16 *)(buf + 0xC4) = 0; /* 0xD4 */
|
||||
*(s16 *)(buf + 0xC6) = 0; /* 0xD6 */
|
||||
*(s16 *)(buf + 0xCA) = 0; /* 0xDA */
|
||||
*(s16 *)(buf + 0xCC) = 0; /* 0xDC */
|
||||
*(s16 *)(buf + 0xCE) = 0; /* 0xDE */
|
||||
*(s16 *)(buf + 0xD0) = 0x1000; /* 0xE0 */
|
||||
*(s16 *)(buf + 0xC0) = *(u16 *)(buf + 0xE0); /* 0xD0 */
|
||||
*(s32 *)(buf + 0xD4) = *(s16 *)(a2 + 0); /* 0xE4 */
|
||||
*(s32 *)(buf + 0xD8) = *(s16 *)(a2 + 2); /* 0xE8 */
|
||||
*(s32 *)(buf + 0xDC) = 0; /* 0xEC */
|
||||
__asm__ __volatile__("" ::: "memory");
|
||||
{
|
||||
register s32 *p __asm__("$2") = (s32 *)(buf + 0xC0);
|
||||
__asm__ __volatile__(
|
||||
"lw $12, 0(%0)\n"
|
||||
"lw $13, 4(%0)\n"
|
||||
"ctc2 $12, $0\n"
|
||||
"ctc2 $13, $1\n"
|
||||
"lw $12, 8(%0)\n"
|
||||
"lw $13, 12(%0)\n"
|
||||
"lw $14, 16(%0)\n"
|
||||
"ctc2 $12, $2\n"
|
||||
"ctc2 $13, $3\n"
|
||||
"ctc2 $14, $4\n"
|
||||
"lw $12, 20(%0)\n"
|
||||
"lw $13, 24(%0)\n"
|
||||
"ctc2 $12, $5\n"
|
||||
"lw $14, 28(%0)\n"
|
||||
"ctc2 $13, $6\n"
|
||||
"ctc2 $14, $7\n"
|
||||
: : "r"(p) : "$12", "$13", "$14", "memory");
|
||||
}
|
||||
func_8013AD38(buf + 0xE0, 0, buf + 0x00, buf + 0x80);
|
||||
D_800A5E60 = a0;
|
||||
if (a3 != 0) {
|
||||
func_8013B274(a1, 0x80, buf + 0xE0);
|
||||
}
|
||||
func_8013AF20(a1, a2, buf + 0x00, buf + 0x80);
|
||||
return D_800A5E60;
|
||||
}
|
||||
|
||||
|
||||
#define gte_ldv0(r0) __asm__ __volatile__( \
|
||||
"lwc2 $0, 0(%0)\n" \
|
||||
"lwc2 $1, 4(%0)\n" \
|
||||
: : "r"(r0) : "memory")
|
||||
#define gte_mvmva0() __asm__ __volatile__( \
|
||||
"nop\n" \
|
||||
"nop\n" \
|
||||
"mvmva 1, 0, 0, 0, 0\n" \
|
||||
: : : "memory")
|
||||
#define gte_stlvnl(r0) __asm__ __volatile__( \
|
||||
"swc2 $25, 0(%0)\n" \
|
||||
"swc2 $26, 4(%0)\n" \
|
||||
"swc2 $27, 8(%0)\n" \
|
||||
: : "r"(r0) : "memory")
|
||||
|
||||
void func_8013AD38(void *flag, s32 a1, void *out2, void *out3) {
|
||||
|
||||
extern s16 D_800D45F4[];
|
||||
extern u8 D_8018AADC[];
|
||||
extern s16 D_800D466C[];
|
||||
extern u8 D_8018AB18[];
|
||||
|
||||
u8 *tbl;
|
||||
s16 vec[4];
|
||||
s32 res[3];
|
||||
s32 i;
|
||||
|
||||
tbl = D_8018AB18;
|
||||
if (((s16)a1) < 0xC00) {
|
||||
tbl = D_8018AADC;
|
||||
}
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
vec[0] = D_800D45F4[2 * i] + (((D_800D466C[2 * i] - D_800D45F4[2 * i]) * ((s16)a1)) >> 12);
|
||||
vec[1] = D_800D45F4[2 * i + 1] + (((D_800D466C[2 * i + 1] - D_800D45F4[2 * i + 1]) * ((s16)a1)) >> 12);
|
||||
gte_ldv0(vec);
|
||||
gte_mvmva0();
|
||||
gte_stlvnl(res);
|
||||
((Pair *)out2)[i].x = res[0];
|
||||
((Pair *)out2)[i].y = res[1];
|
||||
if (((s16 *)flag)[0] < 0) ((s8 *)out3)[2 * i] = -tbl[2 * i]; else ((s8 *)out3)[2 * i] = tbl[2 * i];
|
||||
if (((s16 *)flag)[1] < 0) ((s8 *)out3)[2 * i + 1] = -tbl[2 * i + 1]; else ((s8 *)out3)[2 * i + 1] = tbl[2 * i + 1];
|
||||
}
|
||||
((Pair *)out2)[i] = ((Pair *)out2)[0];
|
||||
if (((s16 *)flag)[0] < 0) ((s8 *)out3)[2 * i] = -tbl[0]; else ((s8 *)out3)[2 * i] = tbl[0];
|
||||
if (((s16 *)flag)[1] < 0) ((s8 *)out3)[2 * i + 1] = -tbl[1]; else ((s8 *)out3)[2 * i + 1] = tbl[1];
|
||||
}
|
||||
|
||||
|
||||
DEFINE_func_8013AF20() /* dedup: shared engine-core @0x8013af20 (src/shared) */
|
||||
|
||||
|
||||
DEFINE_func_8013B204() /* dedup: shared engine-core @0x8013b204 (src/shared) */
|
||||
|
||||
|
||||
|
||||
|
||||
extern void *func_80010A08(s32);
|
||||
|
||||
void func_8013B274(s32 a0, s32 a1, void *a2)
|
||||
{
|
||||
|
||||
extern s16 D_8018AB54, D_8018AB56, D_8018AB58, D_8018AB5A, D_8018AB5C, D_8018AB5E;
|
||||
extern u16 D_800D45F6;
|
||||
u8 *p;
|
||||
s32 L[10];
|
||||
s16 sa;
|
||||
s32 quot;
|
||||
s16 ang;
|
||||
|
||||
p = (u8 *)func_80010A08(0x28);
|
||||
p[3] = 9;
|
||||
p[7] = 0x2C;
|
||||
p[4] = 0x80;
|
||||
p[5] = 0x80;
|
||||
p[6] = 0x80;
|
||||
*(s16 *)(p + 0x16) = 0x37;
|
||||
*(s16 *)(p + 0xE) = 0x6FD6;
|
||||
p[0xC] = 0xE0;
|
||||
p[0xD] = 0;
|
||||
p[0x14] = 0xEF;
|
||||
p[0x15] = 0;
|
||||
p[0x1C] = 0xE0;
|
||||
p[0x1D] = 0xF;
|
||||
p[0x24] = 0xEF;
|
||||
p[0x25] = 0xF;
|
||||
|
||||
sa = (s16)a1;
|
||||
if (sa == 0) {
|
||||
*(s16 *)L = 0;
|
||||
} else {
|
||||
quot = ((s32)sa << 12) / ((s16*)a2)[0];
|
||||
ang = (s16)quot;
|
||||
if (!(D_8018AB56 < ang)) goto outer_else;
|
||||
if (!(ang < D_8018AB5C)) goto inner_else;
|
||||
if (ang < D_8018AB58) { *(s16 *)L = D_8018AB58; goto done; }
|
||||
if (D_8018AB5A < ang) { *(s16 *)L = D_8018AB5A; goto done; }
|
||||
*(s16 *)L = quot;
|
||||
goto done;
|
||||
outer_else:
|
||||
if (ang < D_8018AB54) { *(s16 *)L = D_8018AB54; goto done; }
|
||||
*(s16 *)L = quot;
|
||||
goto done;
|
||||
inner_else:
|
||||
if (D_8018AB5E < ang) { *(s16 *)L = D_8018AB5E; goto done; }
|
||||
*(s16 *)L = quot;
|
||||
done: ;
|
||||
}
|
||||
*(s16 *)((u8 *)L + 2) = D_800D45F6;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"lwc2 $0, 0(%0)\n"
|
||||
"lwc2 $1, 4(%0)\n"
|
||||
"nop\n" "nop\n"
|
||||
"mvmva 1, 0, 0, 0, 0\n"
|
||||
: : "r"(L) : "memory");
|
||||
__asm__ __volatile__(
|
||||
"swc2 $25, 0(%0)\n"
|
||||
"swc2 $26, 4(%0)\n"
|
||||
"swc2 $27, 8(%0)\n"
|
||||
: : "r"((u8 *)L + 8) : "memory");
|
||||
|
||||
if (((s16*)a2)[1] > 0)
|
||||
*(s32 *)((u8 *)L + 0xC) -= 1;
|
||||
else
|
||||
*(s32 *)((u8 *)L + 0xC) += 2;
|
||||
|
||||
*(s16 *)L = 9;
|
||||
*(s16 *)((u8 *)L + 2) = 9;
|
||||
__asm__ __volatile__(
|
||||
"lwc2 $0, 0(%0)\n"
|
||||
"lwc2 $1, 4(%0)\n"
|
||||
"nop\n" "nop\n"
|
||||
"mvmva 1, 0, 0, 3, 0\n"
|
||||
: : "r"(L) : "memory");
|
||||
__asm__ __volatile__(
|
||||
"swc2 $25, 0(%0)\n"
|
||||
"swc2 $26, 4(%0)\n"
|
||||
"swc2 $27, 8(%0)\n"
|
||||
: : "r"((u8 *)L + 0x18) : "memory");
|
||||
|
||||
*(s16 *)(p + 8) = *(volatile s32 *)((u8 *)L + 8);
|
||||
*(s16 *)(p + 0xA) = *(volatile s32 *)((u8 *)L + 0xC);
|
||||
*(s16 *)(p + 0x10) = *(volatile s32 *)((u8 *)L + 8) + *(volatile s32 *)((u8 *)L + 0x18);
|
||||
*(s16 *)(p + 0x12) = *(volatile s32 *)((u8 *)L + 0xC);
|
||||
*(s16 *)(p + 0x18) = *(volatile s32 *)((u8 *)L + 8);
|
||||
*(s16 *)(p + 0x1A) = *(volatile s32 *)((u8 *)L + 0xC) + *(volatile s32 *)((u8 *)L + 0x1C);
|
||||
*(s16 *)(p + 0x20) = *(volatile s32 *)((u8 *)L + 8) + *(volatile s32 *)((u8 *)L + 0x18);
|
||||
*(s16 *)(p + 0x22) = *(volatile s32 *)((u8 *)L + 0xC) + *(volatile s32 *)((u8 *)L + 0x1C);
|
||||
|
||||
((P_TAG *)p)->addr = ((P_TAG *)a0)->addr;
|
||||
((P_TAG *)a0)->addr = (u32)p;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -307,6 +307,17 @@ def _partition(srcpath, cuts, syms):
|
||||
if any(it[0] is None and it[2] == "tail" for it in items):
|
||||
sys.exit(f"jr_isolate_all: unaddressable content in {srcpath}")
|
||||
footer = [it for it in items if it[2] == "footer"]
|
||||
# R32 COVERAGE — the same guard as overlay_src_split.partition, and for the same reason:
|
||||
# `addressed` silently discards any construct whose vram did not resolve, so this function
|
||||
# rewrote the TU WITHOUT it. Measured P30 S38: one carve of ov_SC02_028 deleted the two
|
||||
# definition-side asm-label-alias definitions emitting func_80183AF8 and func_80184268 (their
|
||||
# C identifiers are aF*, which matched neither `func_<hex>` nor `syms`), and the overlay then
|
||||
# failed to link. Six wave-6 drafts were written off against that. Fail loud instead.
|
||||
lost = [it for it in items if it[0] is None and it[2] not in ("tail", "footer")]
|
||||
if lost:
|
||||
sys.exit(f"jr_isolate_all: {srcpath} has {len(lost)} construct(s) with no resolvable "
|
||||
f"address — refusing to rewrite the file without them (R32):\n" +
|
||||
"\n".join(f" kind={it[2]} name={it[1]} :: {it[3].strip()[:110]}" for it in lost[:6]))
|
||||
addressed = [it for it in items if it[0] is not None]
|
||||
cuts = sorted(set(cuts))
|
||||
bounds = [None] + cuts + [None]
|
||||
|
||||
@@ -58,13 +58,39 @@ def load_syms(path):
|
||||
return s
|
||||
|
||||
|
||||
def addr_of(name, syms):
|
||||
# §37/§73 DEFINITION-SIDE ASM-LABEL ALIAS. A body whose byte-true signature conflicts with the
|
||||
# fleet-canonical decl is banked by giving the DEFINITION a different C identifier and binding the
|
||||
# emitted SYMBOL with a GNU asm label:
|
||||
# void aF8018A860(s32, s16 *, u8 *, u8 *) __asm__("func_80183AF8"); <- decl (stays in preamble)
|
||||
# void aF8018A860(s32, s16 *, u8 *, u8 *) { ... } <- THIS emits func_80183AF8
|
||||
# `addr_of` resolved a def by its C NAME, so `aF8018A860` matched neither `func_<hex>` nor `syms`
|
||||
# and returned None — and `partition()` then DROPPED the item, because it keeps only addressed
|
||||
# ones. That is SILENT CODE LOSS during a repartition: measured P30 S38, one carve deleted the
|
||||
# definitions emitting BOTH func_80183AF8 and func_80184268, and the overlay then failed to link
|
||||
# with `undefined reference` — read for two sessions as a compiler/plumbing wall.
|
||||
# `family_remap._alias_decl_for` already handled this exact form (and its docstring records the
|
||||
# same lesson costing 137 sweep skips); the fix was never propagated here. This is the FIFTH tool
|
||||
# with the same structural blindness — see cookbook §134/§139.
|
||||
_ALIAS_DECL = re.compile(
|
||||
r'\b([A-Za-z_]\w*)\s*\([^;{}]*\)\s*__asm__\s*\(\s*"([^"]+)"\s*\)\s*;', re.S)
|
||||
|
||||
|
||||
def asm_label_aliases(src):
|
||||
"""{C identifier -> emitted symbol} for every definition-side asm-label alias in `src`."""
|
||||
return {m.group(1): m.group(2) for m in _ALIAS_DECL.finditer(src)}
|
||||
|
||||
|
||||
def addr_of(name, syms, aliases=None):
|
||||
if not name:
|
||||
return None
|
||||
m = re.match(r'func_([0-9A-Fa-f]{8})$', name)
|
||||
if m:
|
||||
return int(m.group(1), 16)
|
||||
return syms.get(name)
|
||||
if name in syms:
|
||||
return syms[name]
|
||||
if aliases and name in aliases: # resolve through the EMITTED symbol, not the C name
|
||||
return addr_of(aliases[name], syms)
|
||||
return None
|
||||
|
||||
|
||||
def item_func_name(text):
|
||||
@@ -224,6 +250,7 @@ def parse_overlay_c(src, syms):
|
||||
"""Return (header, items) where items = [(addr, name, kind, text)] in file order.
|
||||
kind in {asm, define, def, nonmatch, tail}. `tail` = trailing content with no
|
||||
following anchor (addr None) — normally absent in a well-formed file."""
|
||||
aliases = asm_label_aliases(src)
|
||||
lines = src.split("\n")
|
||||
hdr_end = split_header(lines)
|
||||
header = "\n".join(lines[:hdr_end])
|
||||
@@ -279,7 +306,7 @@ def parse_overlay_c(src, syms):
|
||||
j += 1
|
||||
j = min(j + 1, n)
|
||||
name = item_func_name("\n".join(lines[i:j]))
|
||||
items.append((addr_of(name, syms), name, "nonmatch",
|
||||
items.append((addr_of(name, syms, aliases), name, "nonmatch",
|
||||
"\n".join(lines[pre_start:j])))
|
||||
i = j
|
||||
pre_start = i
|
||||
@@ -288,7 +315,7 @@ def parse_overlay_c(src, syms):
|
||||
j, is_def = scan_construct(lines, i)
|
||||
if is_def:
|
||||
name = def_name(lines[i:j])
|
||||
items.append((addr_of(name, syms), name, "def",
|
||||
items.append((addr_of(name, syms, aliases), name, "def",
|
||||
"\n".join(lines[pre_start:j])))
|
||||
i = j
|
||||
pre_start = i
|
||||
@@ -591,6 +618,15 @@ def partition(srcpath, cuts, syms_path, verbose=True):
|
||||
sys.exit(f"partition: {srcpath} has unaddressable trailing content:\n"
|
||||
f"{tail[0][3][:160]}")
|
||||
footer = [it for it in items if it[2] == "footer"]
|
||||
# R32 COVERAGE: a construct we could not place is a DEFECT, never a no-op. `addressed` keeps
|
||||
# only items with a resolved vram, so an unresolved def/nonmatch used to vanish from every
|
||||
# region — the file was rewritten WITHOUT it and nothing said so (P30 S38: two asm-label-alias
|
||||
# definitions deleted by one carve). Fail loud instead.
|
||||
lost = [it for it in items if it[0] is None and it[2] not in ("tail", "footer")]
|
||||
if lost:
|
||||
sys.exit(f"partition: {srcpath} has {len(lost)} construct(s) with no resolvable address — "
|
||||
f"refusing to rewrite the file without them (R32):\n" +
|
||||
"\n".join(f" kind={it[2]} name={it[1]} :: {it[3].strip()[:110]}" for it in lost[:6]))
|
||||
addressed = [it for it in items if it[0] is not None]
|
||||
cuts = sorted(set(cuts))
|
||||
bounds = [None] + cuts + [None] # (start,cut0),(cut0,cut1),...,(cutN,end)
|
||||
|
||||
Reference in New Issue
Block a user