formats: a keyless primitive that would hide the screen is forced to paint first
Partly closes ui-prm-primitives.md's standing blocker, "where an UNMEASURED
primitive paints". Raised by the port: build_12/build_15 composite to solid
black at every instant of their declared life, because pgloading_eff00.prm -- a
full-screen opaque quad -- sorts last.
The rule is a constraint read off the file, not a preference: an element that
covers the screen and is fully opaque at some instant cannot paint above
anything visible at that instant. Where the elements visible during its opaque
span are ALL of them, its position is forced to first.
pgloading_eff00.prm is opaque for 39 instants and all 9 other elements are
visible inside that span -> forced first, 4/4 instances.
Two controls, both measured orders from the running game, and the rule has to
survive both:
* palogo_eff0.prm is measured painting FIRST -- opaque 211 instants, forced
below 6 of 6. It is NAMED like an overlay, so a name-based rule sorts it
wrong against a measured order. Occlusion gets it right.
* pteff00.prm is measured painting LAST -- opaque for 2 instants at its
screen's entry and exit, forced below only 3 of 23, so the constraint
permits it on top where it belongs.
Disc-wide: 80 instances forced first, 50 constrained but not forced, 0
unconstrained. The split runs almost exactly along the names -- every *base* is
forced, every *eff00* is not -- with three families crossing it, which is
exactly why the name is not the rule.
It also explains 36 builds the corpus had recorded as "coming out one colour"
with no cause: pzeff00.prm is forced first in 32 of 32 instances, so they were
wiped by our own sort rather than by the game.
The rule's real limit was found by its own disc-wide test failing. Applied to
any element it claimed 22 .t32 SPRITES must sort first against their own layer
keys -- pneff01.t32 (key 0xd850, #8 of 13) and pbfriendly.t32 (0x9230, #17 of
49). A sprite's ELEMENT alpha says nothing about whether its TEXTURE covers the
screen, so forced_backdrop is now restricted to untextured primitives, which is
also the only case derived_paint_order consults it for.
Reach stated: assumes straight alpha-over (blend mode is still open, and an
additive quad at alpha 255 would not occlude); it is a lower bound, not an
ordering; and there is no new oracle measurement -- both controls are prior
ones, and a loading screen is not reachable from the title path.
3 new disc tests; the 13 paint-order tests are green, including
the_derived_order_matches_the_measured_ones_up_to_ties.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QsEPXWVaEpyfudtR6re1Pd
This commit is contained in:
110
docs/re/structures/ui-forced-backdrop.md
Normal file
110
docs/re/structures/ui-forced-backdrop.md
Normal file
@@ -0,0 +1,110 @@
|
||||
# Where a keyless primitive paints, when the file forces it
|
||||
|
||||
**Classification: decoded.** Derived from the keyframes and the element's own
|
||||
geometry, checked disc-wide, and validated against **both** primitives whose
|
||||
position was measured in the running game — one it must reproduce, one it must
|
||||
not disturb.
|
||||
|
||||
## The question
|
||||
|
||||
A `.prm` / `.tbm` primitive carries **no layer key**: the key is read from a
|
||||
sprite's header, and a primitive has no sprite.
|
||||
[`ui-prm-primitives.md`](ui-prm-primitives.md) established that the key is not in
|
||||
the bundle either — the declaration entry's unread words are constant, and the
|
||||
bundle has no RATC child for a primitive — so `implied_layer_key` is a **measured
|
||||
per-name table**, and anything not in it keeps `u32::MAX` and sorts **last**.
|
||||
|
||||
"❔ Where an *unmeasured* primitive paints" has been that page's standing blocker.
|
||||
|
||||
The port hit it: `build_12` / `build_15` composited to solid black at every
|
||||
instant of their declared life, because `pgloading_eff00.prm` — a full-screen
|
||||
opaque quad — sorted on top.
|
||||
|
||||
## The rule
|
||||
|
||||
> **An element that covers the screen and is fully opaque at some instant cannot
|
||||
> paint above anything visible at that instant.** Where the elements visible
|
||||
> during its opaque span are *all* of them, its position is forced to first.
|
||||
|
||||
This is a constraint read off the file, not a preference, and it is not an
|
||||
analogy to a neighbouring screen.
|
||||
|
||||
`pgloading_eff00.prm` is opaque for **39** instants, and **all 9** other elements
|
||||
on the loading screen are visible inside that span. **Forced first**, 4/4
|
||||
instances.
|
||||
|
||||
## The controls — the rule has to survive both, and it does
|
||||
|
||||
| primitive | measured in the game | opaque instants | forced below | rule says |
|
||||
|---|---|---|---|---|
|
||||
| `palogo_eff0.prm` | **paints FIRST** | 211 | **6 of 6** | ✅ forced first |
|
||||
| `pteff00.prm` (title) | **paints LAST** | 2 | 3 of 23 | ✅ permitted on top |
|
||||
| `pteff00.prm` (menu) | **paints LAST** | 2 | 7 of 15 | ✅ permitted on top |
|
||||
|
||||
🔴 **The first row is the one that matters.** `palogo_eff0.prm` is named like an
|
||||
overlay, and a rule keyed on the *name* would sort it last — against a measured
|
||||
order. Occlusion gets it right. `pteff00.prm` is opaque only for two instants, at
|
||||
its screen's entry and exit, so the constraint never binds it: it is the fade
|
||||
cover, and it belongs on top.
|
||||
|
||||
## Disc-wide
|
||||
|
||||
Keyless **full-screen** primitives with an opaque interval:
|
||||
|
||||
| | count |
|
||||
|---|---|
|
||||
| position **forced first** | **80** |
|
||||
| constrained below some, not all | 50 |
|
||||
| occluding nothing | 0 |
|
||||
|
||||
The split falls almost exactly along the names — every `*base*` is forced, every
|
||||
`*eff00*` is not — with three families crossing it: `palogo_eff0.prm`,
|
||||
`pgloading_eff00.prm` and `pzeff00.prm` are named like overlays and are forced
|
||||
first. **That is precisely why the name is not the rule.**
|
||||
|
||||
✅ **And it explains a symptom the corpus had recorded without a cause.**
|
||||
`ui-prm-primitives.md` notes 36 builds that "come out one colour ... wiped by
|
||||
`pzeff00.prm` and `pceff00.prm`, whose positions have never been measured".
|
||||
`pzeff00.prm` is forced first in **32 of 32** instances. Those builds were wiped by
|
||||
our own sort, not by the game.
|
||||
|
||||
## 🔴 The rule's real limit, found by its own test
|
||||
|
||||
An earlier version applied to any element. Its disc-wide test asserted that no
|
||||
*keyed* element is ever forced — and that assertion failed, on **22** of them:
|
||||
`pneff01.t32` (key `0xd850`, paints #8 of 13) and `pbfriendly.t32` (key `0x9230`,
|
||||
#17 of 49).
|
||||
|
||||
Both are `.t32` **sprites**, and that is the flaw: a sprite's *element* alpha
|
||||
being 255 says nothing about whether its **texture** covers the screen. Most of it
|
||||
may be transparent. The disagreements were the rule overreaching, not the keys
|
||||
being wrong.
|
||||
|
||||
`forced_backdrop` is now restricted to elements with **no sprite** — untextured
|
||||
primitives, which are solid quads and do occlude what they cover. That is also the
|
||||
only case `derived_paint_order` consults it for.
|
||||
|
||||
## Reach
|
||||
|
||||
⚠️ **Assumes straight alpha-over blending.** Blend mode is ❔ on
|
||||
[`ui-prm-primitives.md`](ui-prm-primitives.md): an *additive* quad at alpha 255
|
||||
would not occlude, and the rule would then be placing it wrongly. The
|
||||
`palogo_eff0.prm` control is evidence the assumption holds at least there.
|
||||
|
||||
⚠️ **It gives a lower bound, not an ordering.** It settles the 80 instances where
|
||||
occlusion forces the position, and says nothing about the 50 where the primitive
|
||||
is opaque only part of the time — including `pteff00.prm`, whose place on top is
|
||||
still a *measured* per-name entry, not a decoded one.
|
||||
|
||||
⚠️ **No new oracle measurement.** The two controls are orders measured previously;
|
||||
nothing here was captured from a running game. A draw capture of a loading screen
|
||||
would confirm it directly, and the loading screens are not reachable from the
|
||||
title path.
|
||||
|
||||
## Reproducing
|
||||
|
||||
```bash
|
||||
cargo run -p sylpheed-formats --example prm_forced_first
|
||||
cargo run -p sylpheed-formats --example prm_occlusion_check
|
||||
SYLPHEED_DISC=/disc cargo test -p sylpheed-formats --test ui_forced_backdrop_disc
|
||||
```
|
||||
Reference in New Issue
Block a user