Research 03 / Timing

可以少畫一幀,不能讓世界變慢。

極端彈幕、爆炸與背景 streaming 同時出現時,GBA 可能無法每個 VBlank 都準備新畫面。遊戲時鐘、音樂與輸入仍必須按真實時間前進。

一個 frame 的預算

GBA CPU 約 16.78 MHz,螢幕接近 59.73 Hz,一個 frame 約有 280,896 CPU cycles。這個數字包含遊戲邏輯、背景準備、Sprite cache、render、 audio update、input 與 VBlank commit,不只是「畫 sprite」。

16.78 MHzARM7TDMI
59.73 Hzdisplay cadence
≈280,896cycles / frame

Fixed timestep

邏輯累加器以 wall-clock VBlank 推進。Normal speed 保留來源節奏; 如果上一輪工作跨過 VBlank,主迴圈會消耗已發生的 IRQ,執行必要的 catch-up logic,而不是再次睡到下一個 VBlank。這避免「一次超時, 額外再停一幀」的連鎖遲滯。

Presentation defer

場景趕不及時,當前完整畫面可以再呈現一次;新 OAM、tile row 與 page flip 等到真正的 VBlank 再 commit。邏輯位置、敵人生命、武器 cooldown、 Maxmod 更新與背景 source position 不因重複畫面而停住。

Frame drop 不是把所有邏輯改成 30 Hz,也不是凍結背景來掩蓋成本。 它只改變「何時交付下一個完整 presentation」。

先優化,再允許 drop

Drop frame 是安全網,不是第一個答案。專案仍針對實測 hot path 使用:

  • Game Pak prefetch 與 3/1 waitstate;
  • IWRAM/ARM code 放置;
  • active bitmask 跳過無效碰撞候選;
  • Sprite2 raw catalog、EWRAM L2 與 VRAM upload queue;
  • 背景 row prefetch 與 bounded cache work;
  • 移除 hot loop 的軟體除法與不必要的 memory write。

Branchless 並不自動更快。ARM7TDMI 沒有現代 branch predictor, 但額外乘法、全部路徑的 memory access 也可能比簡單短路分支昂貴; 每個改動都以 cycle counter 與完整 route golden 驗證。

把漏幀分到真正狀態

總 missed VBlank 會分成 gameplay、stats、game-over、frontend transition 與其他 frontend。這能分辨「Boss 計算真的重」和「選單誤做 runtime SHP 解碼」。v89 正式版使用 LOW/Normal;完整第一關 gameplay gate 為 2%,較密集的 Episode 2 stock route 為 2.5%,而 frontend、stats、 game-over 與 transition deterministic misses 仍必須為 0。

Drop-frame 處理單一 frame 的截止期限;持續超載則交給 Adaptive 呈現派送,將完整場景鎖到穩定且有下限的 cadence。