diff --git a/docs/port/DECISIONS.md b/docs/port/DECISIONS.md index 8bdf6f90..fcb4bf6e 100644 --- a/docs/port/DECISIONS.md +++ b/docs/port/DECISIONS.md @@ -3855,3 +3855,74 @@ between the two of us this session. **What it is not:** it identifies focus in *one frame*. It says nothing about what *selects* focus; Q5's instability stands. + +## The title's 1.82 % — three of my own explanations refuted, and the format has no blend mode + +`title` is the port's largest disagreement with the oracle, and last iteration I +attributed it to the moving `ptloop` sweeps *without checking*. That attribution +is wrong, and so were the two hypotheses I formed after it. + +**❌ Not the sweeps.** `ptloop01`/`ptloop02` are **399×180 at (441, 270)** — small +and central — and their exported keyframes hold `pos`, `scale` and `rotation` +constant, varying only alpha. The difference peaks at **x ≈ 1088**, nowhere near +them. + +**❌ Not an over-held element.** `--screen` holds every element at its own +`rest.t`, so I added `--no-hold` to render the other answer. Playing the title's +groups past their rest **fades the whole screen to black by t = 5.2 s** — +30.97 % differing against 1.82 % held. Holding at rest is right. + +**❌ Not a timing offset.** Sweeping the build-in: 24.05 % at t=1.6, falling +monotonically to **1.68 % at t=4.18** and 1.82 % settled. The capture is at the +settled end; there is no earlier moment that fits better than marginally. + +### What it actually looks like: a horizontal redistribution + +Signed difference (port − capture), by cell: + +| | x=0 | x=320 | x=640 | x=960 | +|---|---|---|---|---| +| y=0 | +1.1 | **−13.1** | −6.6 | **+16.0** | +| y=169 | +2.1 | **−8.3** | +4.2 | **+9.9** | +| y=338 | +5.8 | −4.5 | −0.0 | +3.2 | +| y=507 | +3.9 | +3.3 | +2.0 | +2.3 | + +**The port is darker centre-left and brighter right, and it nearly cancels** — +whole-frame means 63.8 against 62.5. That is not a level error and not a tone +ramp; it is brightness in the wrong *place*. And it falls in exactly the rows +spanned by the two wide elements `ptlogo_back2` (1118×262 at 71,126) and +`ptlogo_back2eff` (1133×280 at 64,117), with the column profile falling off past +x≈1152 against their right edges at 1189 and 1197. + +### 🔴 The export carries no blend mode, so the port cannot draw one + +`ptlogo_back2eff`'s exported keys are `declared, id, index, keyframes, kind_raw, +layer, layer_source, pivot, rest, role, sprite`. **There is no blend field**, in +this element or in `FORMAT.md` at all. The port composites everything with normal +alpha. + +If the game draws `_eff` layers **additively**, a wide gradient sprite would +produce precisely this signature — surplus where the sprite is bright, deficit +where the underlying art is brighter than the sum — and **nothing in the export +would reveal it.** That is a decoding question, not a port one, and it is asked +rather than assumed. ⚠️ It is a hypothesis I have not tested; I am recording it +because the three I could test are dead. + +### A separate `rest.t` casualty, recorded and not acted on + +`pteff02` is a full-frame primitive whose group runs `0x40000000` (25 % black) at +t=46 → `0xd4000000` at 76 → `0xcc000000` at 118 → **`0x00000000` at 236**. Its +`rest.t` is **46**, so the port holds a **25 % black veil the screen's own +timeline removes**. This is the third instance of `rest.t` naming a hold that is +not the settled state — after the loading screen's opaque quad and `ptlogo1`'s +creep. ⚠️ **It does not explain the residual** — removing a darkening veil would +make the port brighter still, and it is already brighter where it disagrees — so +it is recorded rather than fixed. + +### And a new diagnostic + +`--no-hold` plays a screen past its rest instead of clamping each element at +`rest.t`. Added because the question *"is the held pose what the idle game +shows"* could not be asked otherwise. ⚠️ Its first version set the flag thirty +lines before `view` exists and silently rendered nothing — caught because the +comparison loop found no files, not because anything reported an error. diff --git a/port/scripts/boot.gd b/port/scripts/boot.gd index 44014d6f..ccdeb7f6 100644 --- a/port/scripts/boot.gd +++ b/port/scripts/boot.gd @@ -182,6 +182,18 @@ func _ready() -> void: # own logic on purpose -- see `looping_focus` there for the census that says # this cannot be a rule. _looping = timing.get("looping_focus_records", {}) + # `--no-hold` plays a screen's groups PAST their rest instead of clamping each + # element at its own `rest.t`. A diagnostic, not a mode: `rest.t` is the last + # HOLD keyframe before the exit, not the settled state, and the only way to + # ask "is the port's held pose what the idle game shows" is to be able to + # render the other answer. Added when the title's 1.8 % disagreement with the + # oracle could not be attributed without it. + # + # It goes HERE and not with the other flags: `view` does not exist until this + # point, and the first version set it thirty lines too early and silently + # rendered nothing. + if args.has("no-hold"): + view.holding = false viewport.add_child(view) view.looping_focus = _looping_for(name)