roomtest: двойная буферизация (два экрана + флип), тумблер SPACE
Убирает мерцание/тиринг при перерисовке слоёв (Kid/fore/пол-оверлей): рендер всего кадра в скрытую страницу, tear-free флип на vblank. Инфра libbgi (gfx_set_draw_page/visible_page/wait_vsync) уже была. - фон комнаты рисуется в ОБЕ графические страницы (у каждой своя ОЗУ-копия — источник heal); палитра 0->1 уже синкалась gfx_pal_sync; - kid_heal/kid_draw: прямоугольник Kid запоминается ПО СТРАНИЦЕ (kid_l*[2]) — при чередовании страниц heal стирает пиксели своей страницы (прошлый Kid там был 2 логических кадра назад); - цикл: draw в back, 3x wait_vsync (пейсинг), gfx_set_visible_page(back); - SPACE (edge) — тумблер: off = однобуфер (draw==visible==0) для отладки. Мерцание при подъёме подтверждено устранённым в MAME (пользователь). План: applications/PoP/docs/double_buffer_plan.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# Double buffer (два экрана + флип) — план
|
||||
|
||||
Цель: убрать мерцание/тиринг при перерисовке слоёв (Kid ↔ fore/пол-оверлей)
|
||||
и гарантировать, что на экране ВСЕГДА готовый кадр с правильным порядком
|
||||
слоёв. Нужно для отладки fore-слоя (видно момент композиции, а не
|
||||
промежуточные состояния heal-рендера). **Тумблер обязателен** —
|
||||
однобуферный режим удобнее для отладки багов рисования.
|
||||
|
||||
## Что уже готово (libbgi — трогать НЕ нужно)
|
||||
|
||||
- Две графических страницы 0/1: `gfx_set_draw_page(p)` (двигает
|
||||
`_gfx_addr_base` 0xC000/0xC140 — рисуют все примитивы),
|
||||
`gfx_set_visible_page(p)` (ESTEX $54 SELPAGE — display-учёт DSS).
|
||||
- `gfx_wait_vsync()` — луч (bit5 порта 0xFE), момент без разрывов.
|
||||
- Паттерн из gfx.h: `set_draw_page(hidden); draw(); wait_vsync();
|
||||
set_visible_page(hidden);`
|
||||
- Замечание gfx.h: у каждой страницы СВОЯ плоскость палитры
|
||||
(page0→pal0, page1→pal1) — для seamless грузить одну палитру в ОБЕ.
|
||||
|
||||
## Текущая модель рендера roomtest (однобуфер)
|
||||
|
||||
`roomtest.c`: `draw_page=0`, `visible_page=0` фиксированы. Фон комнаты
|
||||
рисуется ОДИН раз в видео-ОЗУ + теневую копию (GFX_BANK_TRANSPARENT).
|
||||
Цикл: 3× `gfx_wait_vsync` (пейсинг) → `pop_ctrl_tick` → `kid_heal()`
|
||||
(восстановить прямоугольник Кида из тени) → `kid_tick`/`pop_phys_tick`
|
||||
→ `kid_draw` → `pop_fore_over_kid`. Мерцание = heal+draw+fore длиннее
|
||||
бланка, луч ловит промежуток.
|
||||
|
||||
## Работа на стороне PoP
|
||||
|
||||
1. **Инициализация обеих страниц**: `pop_room_draw` в page 0 И page 1
|
||||
(теневая копия одна — общая, из неё heal'ит любая страница).
|
||||
2. **Палитра в обе плоскости**: сейчас `gfx_pal_fload(0,...)` + sync.
|
||||
Продублировать в plane 1 (проверить сигнатуру gfx_pal_fload/sync —
|
||||
plane-параметр).
|
||||
3. **Per-page heal-история** (ядро): вынести `kid_lx/ly/lw/lh` в
|
||||
массивы `[2]`, индекс = страница, в которую рисуем. `kid_heal(page)`
|
||||
восстанавливает СВОЙ прошлый прямоугольник (кадр -2, т.к. рисуем
|
||||
через страницу). То же для fore/пол-оверлея, если они рисуют вне
|
||||
футпринта Кида.
|
||||
4. **Ping-pong в цикле**:
|
||||
```
|
||||
uint8_t back = dbuf ? (front ^ 1) : 0;
|
||||
gfx_set_draw_page(back);
|
||||
kid_heal(back); kid_tick; phys; kid_draw; fore;
|
||||
gfx_wait_vsync();
|
||||
if (dbuf) { gfx_set_visible_page(back); front = back; }
|
||||
```
|
||||
5. **Тумблер** `dbuf`: off → draw==visible==0, без флипа, heal[0] —
|
||||
бит-в-бит текущее поведение. Управление — клавишей (напр. F2) или
|
||||
compile-флагом.
|
||||
6. **Пейсинг**: сейчас 3× vsync/лог.кадр. При флипе — один vsync перед
|
||||
свопом; недостающий пейсинг добрать `gfx_set_fps_div(3)` или ручным
|
||||
счётом кадров, чтобы скорость игры не изменилась.
|
||||
|
||||
## Порядок
|
||||
|
||||
- D1: обе страницы + палитра в обе плоскости; ping-pong без per-page
|
||||
heal (проверить, что флип работает, фон корректен на обеих).
|
||||
- D2: per-page heal-история (kid_l*[2]) — убрать «хвост» Кида.
|
||||
- D3: тумблер dbuf + сверка однобуферного пути с текущим (регресс-нет).
|
||||
- D4: пейсинг (fps_div) — вернуть исходную скорость.
|
||||
|
||||
## Связанные
|
||||
|
||||
Рендер-модель — [[pop_fore_layer]], [[pop_background_strategy]];
|
||||
heal — kid_heal/gfx_heal. Будущие динамические слои (loose-floors
|
||||
[[двойной буфер требует их per-page перерисовки]]) должны рисоваться в
|
||||
обе страницы по той же дисциплине.
|
||||
Reference in New Issue
Block a user