re: EXTRAS complete -- ptframe4, pteff21/22/23 and pteff10 are all ADDITIVE
The four elements the port measured as the worst on EXTRAS, and which appeared in no draw, were in a draw all along: the 24-index additive batch holds six quads and Canary printed the first two. Cap raised to 64, screen re-captured, all six named. Same draw as ptframe3, whose state was already measured -- the one-way implication doing real work. pteff10 is identified too, and it needed the resting SCALE: it ships as 409x144 and is drawn at 200 % x 500 % = 816x720. The matcher's 'try 1x and 2x' rule could not name it at any scale and reported a near miss against something else, which is a failure wearing the clothes of an answer. Candidates are now the declaration's pivot*2 scaled by the resting keyframe as well as the texture at 1x and 2x, and the tolerance is the log's own NDC print quantisation rather than a chosen number. Flagged rather than buried: pteff10 measuring additive is in tension with the port measuring it nearly exact under alpha-over. Both can be true for a dim semi-transparent glow over a dark background, and it is the one row a rendering check does not corroborate. Also stated: the three full-screen alpha-over draws are NOT individually identified -- four elements declare 1280x720 -- so the label on those rows is a candidate, not an identification. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
This commit is contained in:
@@ -45,32 +45,49 @@ def blend_name(raw):
|
||||
return "%s+%s" % (FACTOR.get(src, src), FACTOR.get(dst, dst))
|
||||
|
||||
|
||||
def sprite_sizes(builds):
|
||||
"""name -> (w, h), straight off the disc via the formats crate.
|
||||
def candidates(builds):
|
||||
"""Every size a UI draw could legitimately have, with a label and a basis.
|
||||
|
||||
`builds` is a list because the live title is TWO builds composited -- 4 draws
|
||||
the art and 2 draws the `PRESS (A)` plate over it -- so a capture of the
|
||||
title contains elements from both and a one-build size table cannot name
|
||||
them all.
|
||||
Two bases, because neither alone names every element:
|
||||
|
||||
declared the declaration's `pivot * 2` scaled by the RESTING keyframe's
|
||||
scale_x/scale_y. This is the only thing that names `pteff10`,
|
||||
which ships as 409x144 and is drawn at 200 % x 500 % = 816x720 --
|
||||
a scale-guessing matcher called it "no match" and offered a near
|
||||
miss against something else instead.
|
||||
texture the decoded `.t32`'s own pixel size, at 1x and 2x. Needed because
|
||||
the pivot is NOT always half the texture (`ptmsg2` declares
|
||||
384x38 for a 354x38 sprite) and because a button's focused `f`
|
||||
variant has a texture and no declaration of its own.
|
||||
|
||||
`builds` is a list: the live title is TWO builds composited, 4 for the art
|
||||
and 2 for the `PRESS (A)` plate.
|
||||
"""
|
||||
out = subprocess.run(
|
||||
["cargo", "run", "--release", "-q", "-p", "sylpheed-formats",
|
||||
"--example", "frame_alpha_census", "--"] + [str(b) for b in builds],
|
||||
capture_output=True, text=True, cwd="/work",
|
||||
env={**__import__("os").environ, "SYLPHEED_DISC": "/disc"}).stdout
|
||||
sizes = {}
|
||||
for line in out.splitlines():
|
||||
env = {**__import__("os").environ, "SYLPHEED_DISC": "/disc"}
|
||||
def run(example):
|
||||
return subprocess.run(
|
||||
["cargo", "run", "--release", "-q", "-p", "sylpheed-formats",
|
||||
"--example", example, "--"] + [str(b) for b in builds],
|
||||
capture_output=True, text=True, cwd="/work", env=env).stdout
|
||||
out = []
|
||||
for line in run("rest_scale_of").splitlines():
|
||||
m = re.match(r"(\S+\.(?:t32|prm|rat))\s+\d+,\d+\s+\d+\s+\d+\s+([\d.]+)x([\d.]+)", line)
|
||||
if m:
|
||||
out.append((m.group(1), "declared", float(m.group(2)), float(m.group(3))))
|
||||
for line in run("frame_alpha_census").splitlines():
|
||||
m = re.match(r"(\S+\.t32)\s+(\d+)x(\d+)", line)
|
||||
if m:
|
||||
sizes[m.group(1)] = (int(m.group(2)), int(m.group(3)))
|
||||
return sizes
|
||||
w, h = float(m.group(2)), float(m.group(3))
|
||||
out.append((m.group(1), "texture", w, h))
|
||||
out.append((m.group(1), "texture@2x", w * 2, h * 2))
|
||||
return out
|
||||
|
||||
|
||||
def main():
|
||||
path = sys.argv[1]
|
||||
spec = sys.argv[sys.argv.index("--build") + 1] if "--build" in sys.argv else "5"
|
||||
builds = [int(b) for b in spec.split(",")]
|
||||
sizes = sprite_sizes(builds)
|
||||
cands = candidates(builds)
|
||||
lines = open(path).read().splitlines()
|
||||
rows = []
|
||||
for i, line in enumerate(lines):
|
||||
@@ -95,19 +112,17 @@ def main():
|
||||
w = (max(xs) - min(xs)) / 2 * W
|
||||
h = (max(ys) - min(ys)) / 2 * H
|
||||
heights.append(h)
|
||||
# A sprite is drawn at its native size or at 2x: the screen is
|
||||
# 1280x720 and the design space is 640x360, so `ptbase` (640x360)
|
||||
# covers the screen while `pteff05` (1280x720) is 1:1. Both are
|
||||
# tried and the scale is reported, because guessing one would
|
||||
# silently mis-name half the draws.
|
||||
best, bd, bs = "-", 1e9, 1
|
||||
for n, (sw, sh) in sizes.items():
|
||||
for sc in (1, 2):
|
||||
d = abs(sw * sc - w) + abs(sh * sc - h)
|
||||
if d < bd:
|
||||
best, bd, bs = n, d, sc
|
||||
tag = ("%s @%dx" % (best, bs)) if bd <= 8 else \
|
||||
"(no match, nearest %s @%dx off %.0f)" % (best, bs, bd)
|
||||
# The log prints NDC to TWO DECIMALS, so a width is quantised to
|
||||
# 0.01 * 1280 / 2 = 6.4 px and a height to 3.6 px. The tolerance
|
||||
# below is that quantisation, not a fudge factor: a match inside it
|
||||
# is as close as this instrument can report.
|
||||
best, bd, bb = "-", 1e9, ""
|
||||
for n, basis, sw, sh in cands:
|
||||
d = abs(sw - w) / 6.4 + abs(sh - h) / 3.6
|
||||
if d < bd:
|
||||
best, bd, bb = n, d, basis
|
||||
tag = ("%s [%s]" % (best, bb)) if bd <= 2.0 else \
|
||||
"(no match, nearest %s [%s] off %.1f quanta)" % (best, bb, bd)
|
||||
print("%4d %4d %4d 0x%08X %-20s %7.1f x %7.1f %s"
|
||||
% (idx, prim, nidx, raw, blend_name(raw), w, h, tag))
|
||||
tall = sorted(h for h in heights if h > 900)
|
||||
|
||||
Reference in New Issue
Block a user