re: census the T8aD paint-order key -- it is pak-local, not a global vocabulary
The page rested on twelve values from two screens. This walks all 4525 sprites
on the disc.
* The field is a u16 at +0x0A. The upper half of the 32-bit word the page
reads is zero in 4525/4525. Nothing above changes -- 0x00008100 sorts the
same as 0x8100 -- but a future value with the high half set would mean
something had been misread rather than that the layer got deeper.
* It is an enumeration: 45 values for 4525 sprites, one of which (0x8100)
covers 1188 of them.
* The reading worth trying -- a global layer vocabulary shared across the UI
-- is refuted. Only 4 of 45 keys cross a pak family and 33 of 45 live only
in GP_MAIN_GAME_2D; every other pak owns a narrow high-byte band (0x90-0x94
for the in-game overlays, 0xa4 mission log, 0xb1-0xb2 save/load). A screen
that owns one or two keys is not ordering itself with them.
That supports "group id in the high bits, order in the low bits", which is what
the page already suspected, but it does NOT test it: paint order has been
measured on two screens and both are inside GP_MAIN_GAME_2D, so there is no
ground truth to check the split against. Left amber.
The first number I got was 37/45 shared, which would have supported precisely
the wrong conclusion. It came from counting paks instead of pak families: the
six GP_MAIN_GAME_*2D paks are the same screens in six languages and their key
sets are byte-for-byte identical. Recorded on the page, because the shape
recurs -- a corpus with near-duplicate members manufactures agreement.
This commit is contained in:
49
tools/re-capture/paint_key_census.py
Executable file
49
tools/re-capture/paint_key_census.py
Executable file
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Census the T8aD paint-order key across every sprite on the disc.
|
||||
|
||||
`structures/ui-paint-order-key.md` established that this field sorts a screen's
|
||||
paint order, from twelve values on two measured screens. This walks all 4 525
|
||||
sprites so the open question -- what the bits mean -- is asked of the whole
|
||||
corpus rather than of one screen.
|
||||
|
||||
./paint_key_census.py <extract root>
|
||||
|
||||
Note the field is a **u16 at +0x0A**: the doc reads a 32-bit word at +0x08 and
|
||||
its upper half is zero in every sprite.
|
||||
|
||||
The language variants of `GP_MAIN_GAME_*2D.pak` are collapsed into one family.
|
||||
They hold the same screens in six languages, and counting them separately makes
|
||||
every one of their keys look shared across six paks -- which is how this script
|
||||
first reported "37 of 45 keys appear in more than one pak", a statement about
|
||||
localisation and not about the format.
|
||||
"""
|
||||
|
||||
import sys, glob, struct, re, collections
|
||||
S="/tmp/claude-1000/-home-fabi-RE-Project-Sylpheed/b113cc12-4769-4ed8-ad66-c2b48f800773/scratchpad"
|
||||
sys.path.insert(0,S+"/wt-root/Syplheed-Reborn/tools/re-capture")
|
||||
exec(open(S+"/regn_decode.py").read().split("# ── the object")[0])
|
||||
Hh=lambda b,o: struct.unpack_from(">H",b,o)[0]
|
||||
U=lambda b,o: struct.unpack_from(">I",b,o)[0]
|
||||
def family(n): return re.sub(r'_[DEFIJS]2D\.pak$','_2D.pak',n)
|
||||
byfam=collections.defaultdict(collections.Counter); keys=collections.Counter()
|
||||
langsets=collections.defaultdict(set)
|
||||
ROOT = sys.argv[1] if len(sys.argv) > 1 else "/work/sylph_extract"
|
||||
for f in sorted(glob.glob(ROOT + "/**/*.pak", recursive=True)):
|
||||
try: E=pak_entries(f)
|
||||
except Exception: continue
|
||||
base=f.split('/')[-1]
|
||||
for h,b in (E.items() if isinstance(E,dict) else E):
|
||||
if b[:4]!=b'T8aD': continue
|
||||
k=Hh(b,10); keys[k]+=1; byfam[family(base)][k]+=1
|
||||
if base.endswith('2D.pak'): langsets[base].add(k)
|
||||
fams=sorted(byfam)
|
||||
print("pak families:",{f:len(c) for f,c in byfam.items()})
|
||||
print("\nthe six language 2D paks have identical key sets:",
|
||||
len({frozenset(v) for v in langsets.values()})==1, f"({len(langsets)} paks)")
|
||||
multi=[k for k in keys if sum(1 for f in fams if k in byfam[f])>1]
|
||||
print(f"keys in more than one FAMILY: {len(multi)}/{len(keys)} -> {[('%04x'%k) for k in sorted(multi)]}")
|
||||
only2d=[k for k in keys if list(f for f in fams if k in byfam[f])==['GP_MAIN_GAME_2D.pak']]
|
||||
print(f"keys confined to GP_MAIN_GAME_2D alone: {len(only2d)}/{len(keys)}")
|
||||
print("\nper family, its keys:")
|
||||
for f in fams:
|
||||
print(f" {f:>28}: {sorted('%04x'%k for k in byfam[f])}")
|
||||
Reference in New Issue
Block a user