From e6f921d44279bb4664e8662993727511a6e01e84 Mon Sep 17 00:00:00 2001 From: sylph-decoder Date: Wed, 2 Sep 2026 15:29:34 +0000 Subject: [PATCH] re: the game interpolates every frame, and its splash is ALSO mostly frozen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Answers question 1 of the 2026-09-02 play-test: interpolate or hold. It interpolates, piecewise-linearly, evaluated once per present at one unit per present. palogo_sqex_eff gives 28 distinct alphas over 28 consecutive presents, changing on 26 of 27 adjacent pairs. It is not one slope, and the disc says why: that element declares 0:a=0 -> 15:a=255 -> 30:a=212 -> 45:a=0, three segments with three gradients. Predicted -2.87 and -14.13 per unit against measured modal steps of -3 (x6) and -14 (x9). The declared keyframes predict the per-frame steps, which makes this a prediction rather than a description. So the port must lerp: hold-to-next-key would emit 3 states where the game emits 28. And "eased" is the wrong description -- there is no easing function, the envelope only looks eased because consecutive declared segments have different gradients. Alpha lives in the per-vertex k_8_8_8_8 colour, rewritten into a fresh vertex buffer every frame. Not a PS constant (ps_c[n=0] on 1048/1048), not a blend factor, not a texture swap. πŸ”΄ And the game's splash is ALSO mostly frozen. Measured with the same statistic the play-test used on the port: the game moves 21.2% and 27.8% against the port's 16.4%, and its longest frozen run is 3.34 s against the port's 3.20 s. The publisher declares 205 of 255 units -- 80% -- as a flat hold at full opacity. That refutes the play-test's second clause. "A fade does not hold one picture for 3.20 s" -- this one does, for 3.34 s. Its first clause stands: 26 states for a 45-unit build-in is too few, the game gives 49 and 51. The deficit is the state count, not the freeze: ~100 against 26. Acting on the second clause would have sent the port to remove the one part of its splash that is already right. Not answered: which function does it. This is the behaviour; the image-side half of question 1 is still open. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Jc4pciRArGHfxGGhEbwp5t --- .../re/data/splash-per-frame-alpha-series.txt | 127 ++++++++++++++++++ docs/re/splash-interpolates-every-frame.md | 106 +++++++++++++++ 2 files changed, 233 insertions(+) create mode 100644 docs/re/data/splash-per-frame-alpha-series.txt create mode 100644 docs/re/splash-interpolates-every-frame.md diff --git a/docs/re/data/splash-per-frame-alpha-series.txt b/docs/re/data/splash-per-frame-alpha-series.txt new file mode 100644 index 00000000..3798fa85 --- /dev/null +++ b/docs/re/data/splash-per-frame-alpha-series.txt @@ -0,0 +1,127 @@ +# PER-FRAME ALPHA, every splash quad, off the guest's own vertex buffer. +# Alpha lives in the per-vertex k_8_8_8_8 colour, REWRITTEN EVERY FRAME into a +# fresh vertex buffer. Not a PS constant (ps_c[n=0] on every splash draw), not a +# blend factor (the blend register is constant across the whole splash). +# 'present' = one guest swap. Quad names decoded from the disc, 8/8. + +## palogo_sqex_eff x[-0.53,0.54] y[-0.13,0.12] presents 4..32 (n=28) + 4:34 5:85 7:204 8:221 9:238 10:254 11:249 12:246 13:243 14:237 + 15:232 16:229 17:226 18:223 19:214 20:211 21:197 22:169 23:141 24:127 + 25:113 26:98 27:84 28:70 29:56 30:42 31:28 32:14 + steps between adjacent presents: {-28: 2, -15: 1, -14: 9, -9: 1, -6: 1, -5: 2, -3: 6, 16: 1, 17: 2, 51: 1} + distinct alphas 28 ; changed on 26 of 27 presents + +## palogo_sqex x[-0.52,0.52] y[-0.10,0.08] presents 11..231 (n=221) + 11:34 12:51 13:68 14:102 15:136 16:153 17:170 18:187 19:238 20:255 + 21:255 22:255 23:255 24:255 25:255 26:255 27:255 28:255 29:255 30:255 + 31:255 32:255 33:255 34:255 35:255 36:255 37:255 38:255 39:255 40:255 + 41:255 42:255 43:255 44:255 45:255 46:255 47:255 48:255 49:255 50:255 + 51:255 52:255 53:255 54:255 55:255 56:255 57:255 58:255 59:255 60:255 + 61:255 62:255 63:255 64:255 65:255 66:255 67:255 68:255 69:255 70:255 + 71:255 72:255 73:255 74:255 75:255 76:255 77:255 78:255 79:255 80:255 + 81:255 82:255 83:255 84:255 85:255 86:255 87:255 88:255 89:255 90:255 + 91:255 92:255 93:255 94:255 95:255 96:255 97:255 98:255 99:255 100:255 + 101:255 102:255 103:255 104:255 105:255 106:255 107:255 108:255 109:255 110:255 + 111:255 112:255 113:255 114:255 115:255 116:255 117:255 118:255 119:255 120:255 + 121:255 122:255 123:255 124:255 125:255 126:255 127:255 128:255 129:255 130:255 + 131:255 132:255 133:255 134:255 135:255 136:255 137:255 138:255 139:255 140:255 + 141:255 142:255 143:255 144:255 145:255 146:255 147:255 148:255 149:255 150:255 + 151:255 152:255 153:255 154:255 155:255 156:255 157:255 158:255 159:255 160:255 + 161:255 162:255 163:255 164:255 165:255 166:255 167:255 168:255 169:255 170:255 + 171:255 172:255 173:255 174:255 175:255 176:255 177:255 178:255 179:255 180:255 + 181:255 182:255 183:255 184:255 185:255 186:255 187:255 188:255 189:255 190:255 + 191:255 192:255 193:255 194:255 195:255 196:255 197:255 198:255 199:255 200:255 + 201:255 202:255 203:255 204:255 205:255 206:255 207:255 208:255 209:255 210:255 + 211:255 212:254 213:249 214:243 215:237 216:231 217:215 218:198 219:181 220:165 + 221:148 222:131 223:115 224:98 225:81 226:65 227:48 228:31 229:23 230:15 + 231:7 + steps between adjacent presents: {-17: 8, -16: 4, -8: 3, -6: 3, -5: 1, -1: 1, 17: 6, 34: 2, 51: 1} + distinct alphas 30 ; changed on 29 of 220 presents + +## palogo_gamearts_eff x[-0.41,0.41] y[0.32,0.57] presents 236..275 (n=40) + 236:17 237:34 238:51 239:68 240:85 241:136 242:170 243:187 244:204 245:221 + 246:238 247:255 248:255 249:255 250:255 251:255 252:255 253:255 254:255 255:255 + 256:255 257:255 258:255 259:255 260:255 261:254 262:237 263:220 264:203 265:186 + 266:169 267:152 268:135 269:118 270:101 271:84 272:67 273:50 274:33 275:16 + steps between adjacent presents: {-17: 14, -1: 1, 17: 9, 34: 1, 51: 1} + distinct alphas 27 ; changed on 26 of 39 presents + +## palogo_seta_eff x[-0.20,0.21] y[-0.15,0.15] presents 236..275 (n=40) + 236:17 237:34 238:51 239:68 240:85 241:136 242:170 243:187 244:204 245:221 + 246:238 247:255 248:255 249:255 250:255 251:255 252:255 253:255 254:255 255:255 + 256:255 257:255 258:255 259:255 260:255 261:254 262:237 263:220 264:203 265:186 + 266:169 267:152 268:135 269:118 270:101 271:84 272:67 273:50 274:33 275:16 + steps between adjacent presents: {-17: 14, -1: 1, 17: 9, 34: 1, 51: 1} + distinct alphas 27 ; changed on 26 of 39 presents + +## palogo_anima_eff x[-0.32,0.31] y[-0.65,-0.22] presents 236..275 (n=40) + 236:17 237:34 238:51 239:68 240:85 241:136 242:170 243:187 244:204 245:221 + 246:238 247:254 248:252 249:249 250:246 251:243 252:240 253:234 254:232 255:229 + 256:226 257:223 258:220 259:217 260:214 261:211 262:197 263:183 264:169 265:155 + 266:141 267:127 268:113 269:98 270:84 271:70 272:56 273:42 274:28 275:14 + steps between adjacent presents: {-15: 1, -14: 13, -6: 1, -3: 11, -2: 2, 16: 1, 17: 8, 34: 1, 51: 1} + distinct alphas 40 ; changed on 39 of 39 presents + +## palogo_gamearts x[-0.39,0.39] y[0.35,0.55] presents 248..416 (n=169) + 248:17 249:34 250:51 251:68 252:85 253:119 254:136 255:153 256:170 257:187 + 258:204 259:221 260:238 261:255 262:255 263:255 264:255 265:255 266:255 267:255 + 268:255 269:255 270:255 271:255 272:255 273:255 274:255 275:255 276:255 277:255 + 278:255 279:255 280:255 281:255 282:255 283:255 284:255 285:255 286:255 287:255 + 288:255 289:255 290:255 291:255 292:255 293:255 294:255 295:255 296:255 297:255 + 298:255 299:255 300:255 301:255 302:255 303:255 304:255 305:255 306:255 307:255 + 308:255 309:255 310:255 311:255 312:255 313:255 314:255 315:255 316:255 317:255 + 318:255 319:255 320:255 321:255 322:255 323:255 324:255 325:255 326:255 327:255 + 328:255 329:255 330:255 331:255 332:255 333:255 334:255 335:255 336:255 337:255 + 338:255 339:255 340:255 341:255 342:255 343:255 344:255 345:255 346:255 347:255 + 348:255 349:255 350:255 351:255 352:255 353:255 354:255 355:255 356:255 357:255 + 358:255 359:255 360:255 361:255 362:255 363:255 364:255 365:255 366:255 367:255 + 368:255 369:255 370:255 371:255 372:255 373:255 374:255 375:255 376:255 377:255 + 378:255 379:255 380:255 381:255 382:255 383:255 384:255 385:255 386:255 387:255 + 388:255 389:255 390:255 391:255 392:255 393:255 394:255 395:255 396:255 397:255 + 398:255 399:255 400:255 401:255 402:255 403:255 404:255 405:255 406:255 407:249 + 408:237 409:215 410:181 411:148 412:115 413:81 414:48 415:23 416:15 + steps between adjacent presents: {-34: 2, -33: 3, -25: 1, -22: 1, -12: 1, -8: 1, -6: 1, 17: 12, 34: 1} + distinct alphas 24 ; changed on 23 of 168 presents + +## palogo_seta x[-0.19,0.19] y[-0.12,0.12] presents 248..416 (n=169) + 248:17 249:34 250:51 251:68 252:85 253:119 254:136 255:153 256:170 257:187 + 258:204 259:221 260:238 261:255 262:255 263:255 264:255 265:255 266:255 267:255 + 268:255 269:255 270:255 271:255 272:255 273:255 274:255 275:255 276:255 277:255 + 278:255 279:255 280:255 281:255 282:255 283:255 284:255 285:255 286:255 287:255 + 288:255 289:255 290:255 291:255 292:255 293:255 294:255 295:255 296:255 297:255 + 298:255 299:255 300:255 301:255 302:255 303:255 304:255 305:255 306:255 307:255 + 308:255 309:255 310:255 311:255 312:255 313:255 314:255 315:255 316:255 317:255 + 318:255 319:255 320:255 321:255 322:255 323:255 324:255 325:255 326:255 327:255 + 328:255 329:255 330:255 331:255 332:255 333:255 334:255 335:255 336:255 337:255 + 338:255 339:255 340:255 341:255 342:255 343:255 344:255 345:255 346:255 347:255 + 348:255 349:255 350:255 351:255 352:255 353:255 354:255 355:255 356:255 357:255 + 358:255 359:255 360:255 361:255 362:255 363:255 364:255 365:255 366:255 367:255 + 368:255 369:255 370:255 371:255 372:255 373:255 374:255 375:255 376:255 377:255 + 378:255 379:255 380:255 381:255 382:255 383:255 384:255 385:255 386:255 387:255 + 388:255 389:255 390:255 391:255 392:255 393:255 394:255 395:255 396:255 397:255 + 398:255 399:255 400:255 401:255 402:255 403:255 404:255 405:255 406:255 407:249 + 408:237 409:215 410:181 411:148 412:115 413:81 414:48 415:23 416:15 + steps between adjacent presents: {-34: 2, -33: 3, -25: 1, -22: 1, -12: 1, -8: 1, -6: 1, 17: 12, 34: 1} + distinct alphas 24 ; changed on 23 of 168 presents + +## palogo_anima x[-0.30,0.30] y[-0.62,-0.25] presents 248..416 (n=169) + 248:17 249:34 250:51 251:68 252:85 253:119 254:136 255:153 256:170 257:187 + 258:204 259:221 260:238 261:255 262:255 263:255 264:255 265:255 266:255 267:255 + 268:255 269:255 270:255 271:255 272:255 273:255 274:255 275:255 276:255 277:255 + 278:255 279:255 280:255 281:255 282:255 283:255 284:255 285:255 286:255 287:255 + 288:255 289:255 290:255 291:255 292:255 293:255 294:255 295:255 296:255 297:255 + 298:255 299:255 300:255 301:255 302:255 303:255 304:255 305:255 306:255 307:255 + 308:255 309:255 310:255 311:255 312:255 313:255 314:255 315:255 316:255 317:255 + 318:255 319:255 320:255 321:255 322:255 323:255 324:255 325:255 326:255 327:255 + 328:255 329:255 330:255 331:255 332:255 333:255 334:255 335:255 336:255 337:255 + 338:255 339:255 340:255 341:255 342:255 343:255 344:255 345:255 346:255 347:255 + 348:255 349:255 350:255 351:255 352:255 353:255 354:255 355:255 356:255 357:255 + 358:255 359:255 360:255 361:255 362:255 363:255 364:255 365:255 366:255 367:255 + 368:255 369:255 370:255 371:255 372:255 373:255 374:255 375:255 376:255 377:255 + 378:255 379:255 380:255 381:255 382:255 383:255 384:255 385:255 386:255 387:255 + 388:255 389:255 390:255 391:255 392:255 393:255 394:255 395:255 396:255 397:255 + 398:255 399:255 400:255 401:255 402:255 403:255 404:255 405:255 406:255 407:249 + 408:237 409:215 410:181 411:148 412:115 413:81 414:48 415:23 416:15 + steps between adjacent presents: {-34: 2, -33: 3, -25: 1, -22: 1, -12: 1, -8: 1, -6: 1, 17: 12, 34: 1} + distinct alphas 24 ; changed on 23 of 168 presents + diff --git a/docs/re/splash-interpolates-every-frame.md b/docs/re/splash-interpolates-every-frame.md new file mode 100644 index 00000000..febb9882 --- /dev/null +++ b/docs/re/splash-interpolates-every-frame.md @@ -0,0 +1,106 @@ +# βœ… The game **interpolates piecewise-linearly, every frame** β€” and its splash is *also* mostly frozen + +**Status: βœ… measured, and the declared keyframes predict the measured steps.** +2026-09-02. Instrument: ⟨capture⟩ β€” per-frame vertex alpha off the guest's own +vertex buffer; ⟨disc⟩ for the keyframes that predict it. +Series: [`data/splash-per-frame-alpha-series.txt`](data/splash-per-frame-alpha-series.txt). + +Answers question 1 of [`../agents/PLAYTEST-2026-09-02.md`](../agents/PLAYTEST-2026-09-02.md) +β€” *"what does it do BETWEEN keyframes β€” interpolate, or hold to the next key? +That single answer decides whether the port should lerp at all."* + +--- + +## 1 β€” it interpolates. Every frame. Piecewise-linearly. + +`palogo_sqex_eff`, 28 consecutive presents, **28 distinct alphas**, changing on +**26 of 27** adjacent pairs: + +``` +34 85 204 221 238 254 249 246 243 237 232 229 226 223 214 211 197 169 141 +127 113 98 84 70 56 42 28 14 +``` + +**It is not one slope, and the disc says why.** That element declares +`0:a=0 β†’ 15:a=255 β†’ 30:a=212 β†’ 45:a=0`, which is three segments with three +different gradients. Predicted against measured, per unit: + +| declared segment | predicted Δα/unit | measured modal step | +|---|---|---| +| `15 β†’ 30` (255 β†’ 212) | **βˆ’2.87** | **βˆ’3** Γ—6 | +| `30 β†’ 45` (212 β†’ 0) | **βˆ’14.13** | **βˆ’14** Γ—9 | + +**The declared keyframes predict the per-frame steps.** That is the whole answer: +the game evaluates a linear interpolation between the two bracketing keyframes, +once per present, at one unit per present. + +> **The port must lerp.** Hold-to-next-key would emit 3 states where the game +> emits 28. + +⚠️ **And "eased" is the wrong description**, which matters because a port that +believes it will fit a curve. There is no easing function β€” the *envelope* looks +eased only because consecutive declared segments have different gradients. Every +segment is straight. + +## 2 β€” where the alpha lives, so it can be watched + +**The per-vertex `k_8_8_8_8` colour**, in a vertex buffer the guest rewrites into +a fresh address every frame. Ruled out by the same captures: + +* **not a PS constant** β€” `ps_c[n=0]` on 1 048 / 1 048 splash draws; +* **not a blend factor** β€” the blend register is constant across the whole splash; +* **not a texture swap** β€” one texture is bound throughout. + +## 3 β€” πŸ”΄ the game's splash is ALSO mostly frozen, and the port's 3.2 s hold is CORRECT + +Measured with the same statistic the play-test applied to the port: + +| | **game** publisher | **game** developer | **port** (both) | +|---|---|---|---| +| moving | **21.2 %** | **27.8 %** | 16.4 % | +| longest frozen run | **3.34 s** | **2.50 s** | 3.20 s | +| distinct states | **49** | **51** | **26 total** | + +πŸ“Œ **The play-test's inference does not hold, though its observation does.** It +reads *"a fade does not hold one picture for 3.20 s"* as proof of breakage. **The +game holds one picture for 3.34 s.** The publisher's declared timeline is +`0:a=0 β†’ 15:a=0 β†’ 30:a=255 β†’ 235:a=255 β†’ …`, i.e. **205 of 255 units β€” 80 % β€” is +a flat hold at full opacity.** A splash that is static most of the time is what +the disc describes. + +πŸ”΄ **So the deficit is not the freeze. It is the state count: ~100 against 26.** +The game changes alpha on *every present* during a ramp β€” 15 distinct values for +a 15-unit ramp β€” and the port produces roughly a quarter of that across both +splashes. **Fixing the hold would make it worse; the ramps are where the states +are missing.** + +## What the port should do + +1. **Lerp between bracketing keyframes, evaluated once per frame** β€” not + hold-to-next-key, and not an easing function. +2. **Keep the long hold.** ~3.3 s of genuinely identical frames is correct. +3. Expect **~15 distinct alphas per 15-unit ramp**, ~100 across both splashes. +4. Alpha is a **per-quad scalar**, uniform across the quad's four vertices. + +## Refutation attempt, recorded per the adversarial duty + +**Target:** the play-test's *"A 45-unit build-in cannot be drawn in 26 states, and +a fade does not hold one picture for 3.20 s."* + +**Result: the first clause SURVIVES, the second is REFUTED.** 26 states for a +45-unit build-in is indeed too few β€” the game gives 49 and 51. But the game holds +one picture for **3.34 s**, longer than the port's 3.20 s, and the disc declares +80 % of the publisher splash as a flat hold. Recorded because acting on the second +clause would have sent the port to remove the one part of its splash that is +right. + +## Reach + +⟨capture⟩, one boot, both splashes, English locale. The interpolation law is +checked against ⟨disc⟩ keyframes on one element with three gradients, which is +what makes it a prediction rather than a description β€” **it has not been checked +on the title or the menus**, and doing so is the obvious next step. + +❔ **Not answered here: which function does it.** This is the *behaviour*, measured. +The image-side half of question 1 β€” the function that advances the clock and +evaluates the segment β€” is not found yet.