From 90d5a1f6874df83ab333c60d804724ef5d24e55b Mon Sep 17 00:00:00 2001 From: QIU SHENGMING Date: Fri, 2 Oct 2026 10:59:41 +0800 Subject: [PATCH] Round 17: the game paints -- the missing piece was a per-frame delay A clear-and-blit app left the panel byte-identical, but filling the whole framebuffer through api->fb and blitting turned it from 43 non-zero bytes to 596: an overlay app's framebuffer writes and blit_full do reach the panel. What blocked the frame was Minesweeper's own delay_ms(40) on the invalid-key path -- 40 ms of guest time is seconds of wall time here, on top of roughly twenty seconds of font reads per frame, so frames were minutes apart. With it removed the panel went from 43 to 390 non-zero bytes within 24 s, ink 1275, with the title, counters and field legible. Input is the remaining gap: MENU changed nothing and DOWN sent the app out of its loop (the panel returned to the launcher's 43-byte title box, which only happens on the path that treats a key as EXIT). Next: have the app draw the raw key code it receives and read it off the panel instead of guessing at the mapping. --- AGENTS.md | 17 +++++++++++++++++ AGENTS.zh-CN.md | 14 ++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 8c941b7..fcf248b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -906,6 +906,23 @@ panel model at all** -- the gutted variant was only ever measured by its PC shar The second is cheap to settle: an app that does nothing but display_clear plus blit_full should visibly erase the launcher's title box. +**Round 17: the game paints. What was missing was a per-frame delay, and the display path was never broken.** + +Three measurements settled it. A clear-and-blit app left the panel byte-identical, and filling the whole +framebuffer through api->fb and blitting turned it from 43 non-zero bytes to 596 -- so an overlay app's +framebuffer writes and blit_full do reach the panel, and the earlier reading of "the panel never changes" +was about content, not plumbing. What actually blocked the frame was Minesweeper's own delay_ms(40) on the +invalid-key path: in this emulator 40 ms of guest time is seconds of wall time, and a frame already spends +roughly twenty seconds inside the firmware's font reads, so the frames were minutes apart. Removing that +delay -- the loop redraws every pass anyway -- produced a complete frame within 24 s: the panel went from 43 +to 390 non-zero bytes, ink 1275, with the title, the counters and the field all legible in the dump. + +**Input is the remaining gap.** Pressing MENU changed nothing (596 -> 596) and pressing DOWN sent the app out +of its loop altogether: the panel went back to the launcher's 43-byte title box, which happens only on the +path that treats a key as EXIT. So get_key() is not returning the APP_KEY_* values this app compares against, +or the keys are not reaching it as sent. The cheap way to find out is to have the app draw the raw key code +it receives and read it off the panel, rather than guessing at the mapping. + That is where the next round starts: the same alternating-spin shape, one call at a time. trace. That is a much better place to be than the emulator mystery this started as. diff --git a/AGENTS.zh-CN.md b/AGENTS.zh-CN.md index b1c0876..3cbb49d 100644 --- a/AGENTS.zh-CN.md +++ b/AGENTS.zh-CN.md @@ -739,6 +739,20 @@ g_cursor、g_state、g_mine_left、g_open、g_flag、g_mine —— 正是两个 **从叠加应用发出的 blit_full 到底有没有送到面板模型** —— 掏空版当初只量了 PC 占比,从没看它的屏幕显示了什么。 第二个很便宜就能定论:一个只做 display_clear + blit_full 的应用,应当明显擦掉启动器的标题框。 +**第 17 轮:游戏画出来了。缺的只是每帧那个延时,而显示通路从头到尾都是好的。** + +三个测量把它定死了。一个只做清屏加 blit 的应用让面板逐字节未变;而通过 api->fb 把整个帧缓冲填满再 blit,面板 +从 43 个非零字节变成 596 个 —— 也就是说**叠加应用的帧缓冲写入与 blit_full 确实能到达面板**,而此前"面板从不 +变化"的读数说的是**内容**,不是**通路**。真正挡住那一帧的是扫雷自己在无效按键分支上的 delay_ms(40):在这个 +模拟器里 40 ms 的客户机时间是若干秒的真实时间,而一帧本来就已经要在固件的字库读取里花掉大约二十秒,于是帧与帧 +之间隔了几分钟。把那个延时去掉之后(这个循环本来每轮都重画),**24 秒内就出现了完整的一帧**:面板从 43 变到 +390 个非零字节、ink 1275,标题、计数器和场地在转储里都清晰可读。 + +**剩下的是输入。** 按 MENU 没有任何变化(596 → 596),按 DOWN 则让应用**直接退出了循环**:面板回到启动器那个 +43 字节的标题框,而那只会在"把某个键当成 EXIT"的那条路上发生。也就是说 get_key() 并没有返回这个应用在比较的 +那些 APP_KEY_* 值,或者按键没有按发送的那样到达它。最便宜的查法是**让应用把它收到的原始键码画出来**、从面板上 +读它,而不是猜映射。 + 下一轮就从这里开始:同样的「自旋 + 单调用」形状,一次只放一个调用。 进去、读同一份 trace。比起一开始那个模拟器悬案,这是好得多的处境。