Put the frame in a container with no decoder, and find the palette is not free
ROADMAP K2. DLXP1: a 49,664 B record that is 97 sectors exactly, no index and no length word, because a packed record's length is geometry rather than content. 582.0 KB/s, which is what FINDINGS 61.9 predicted to the tenth, and it encodes in 3.3 s because there is no k-means in it. px68k's own x68k/gvram.c renders the container's bytes index-exact with the harness computing no interleave -- the only test that can catch an encoder whose byte order is wrong, since a container round-trips against its own inverse either way. Both negative controls fail as they must. The picture is re-derived against this project's builder rather than PIL's (34.05 dB against 61.9's 34.08) and the GGGGGRRRRRBBBBBI word is charged for the first time in this tree: 0.53 dB, on every row, so it moves no comparison. What the control found is the finding. A packed container on a SCENE palette lands exactly on the codec's ceiling, so the whole +2.31 dB is the per-frame palette and nothing else -- and 231 of 256 entries change every frame, which makes a mismatched paint 12.8 dB worse than the correct pairing, on screen for roughly half of every frame slot if buffer mode does not blank. So B2 now decides which packed CONTAINER ships, not only which player. The fallback is already a flag: --scene-palette --no-palette is 30.79 dB, zero churn, 576.0 KB/s and still +2.07 dB on the shipping codec. 62.5 is priced and is a wash: palette first 20.32 dB, palette last 20.33. Claude-Session: https://claude.ai/code/session_01194oWYW8DQXK1SZ2DnChW6
This commit is contained in:
@@ -97,6 +97,17 @@ int main(int argc, char **argv)
|
||||
int iw = (d[4] << 8) | d[5], ih = (d[6] << 8) | d[7];
|
||||
if (n < (size_t)(8 + 768 + iw * ih)) { fprintf(stderr, "short blob\n"); return 2; }
|
||||
const BYTE *pix = d + 8 + 768;
|
||||
/* 'DLXQ' -- the blob is PRE-INTERLEAVED: `pix` is already the bytes a DLXP1
|
||||
* record carries, in GVRAM order. The ordinary 'DLXR' path computes the
|
||||
* interleave here, which tests the LAYOUT; this path tests the CONTAINER,
|
||||
* by writing its bytes verbatim and asking px68k's own gvram.c what they
|
||||
* display as. The two agreeing is the claim ROADMAP K2 has to make: the
|
||||
* encoder's byte order is the one 47.2 verified as a picture. */
|
||||
int prepacked = (d[3] == 'Q');
|
||||
if (prepacked && !packed) {
|
||||
fprintf(stderr, "a pre-interleaved blob has no unpacked form\n");
|
||||
return 2;
|
||||
}
|
||||
int yoff = (H - ih) / 2;
|
||||
const BYTE BLACK = 255;
|
||||
|
||||
@@ -121,8 +132,23 @@ int main(int argc, char **argv)
|
||||
for (int y = 0; y < H; y++) {
|
||||
DWORD base = 0xC00000 + y * 1024;
|
||||
for (int i = 128; i < 512; i++) wr16(base + i * 2, 0);
|
||||
for (int i = 0; i < 128; i++)
|
||||
wr16(base + i * 2, (WORD)((PIX(y, i + 128) << 8) | PIX(y, i)));
|
||||
for (int i = 0; i < 128; i++) {
|
||||
WORD w;
|
||||
if (prepacked) {
|
||||
/* The letterbox rows are STATIC SETUP and are not in a
|
||||
* record (dlxp.py), so they are supplied here, the way a
|
||||
* player's scene setup supplies them: both halves BLACK. */
|
||||
if (y < yoff || y >= yoff + ih)
|
||||
w = (WORD)((BLACK << 8) | BLACK);
|
||||
else {
|
||||
const BYTE *row = pix + (y - yoff) * iw;
|
||||
w = (WORD)((row[i * 2] << 8) | row[i * 2 + 1]);
|
||||
}
|
||||
} else {
|
||||
w = (WORD)((PIX(y, i + 128) << 8) | PIX(y, i));
|
||||
}
|
||||
wr16(base + i * 2, w);
|
||||
}
|
||||
}
|
||||
if (!keepbuf) set_r20(R20_DISPLAY); /* back to display */
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user