Вторая страница запечки — КОПИЕЙ с первой (зелёная 546 900 -> 423 558)
Идея пользователя: то, что пишется в ДВЕ видеостраницы, на вторую можно копировать, а не считать заново — тем же приёмом, что при перевороте экрана (зелёное зелье), только без зеркала. Точечные запечки ставятся с pages = 2, срабатывают два кадра подряд (по разу на страницу дабл-буфера) и оба раза считают одно и то же. А после первого раза нужный прямоугольник уже лежит в ОЗУ-копии первой страницы: gfx_copy_page берёт источником ОЗУ-копию НЕактивной страницы (то есть ЧИСТЫЙ фон — спрайты рисуются банком без тени и в копию не попадают), а приёмник обновляет и в видео-ОЗУ, и в ОЗУ-копии. запечь щебень (RD_FLOOR) 179 914 -> 107 844 в среднем (копия ~35 000) запечь колодец (RDA_CEIL_GONE) 138 318 -> 80 810 в среднем (копия ~17 500) зелёная пик 546 900 -> 423 558 работа пик 916 458 -> 793 266 Слот на тайл (bake_pg / bake_pg_above) помнит, НА КАКОЙ странице сделана первая запечка. Копируем только если первая была на ДРУГОЙ странице и дабл-буфер включён; иначе честно пересчитываем. Такая проверка выдерживает и переплетение двух запечек в одном кадре, и однобуфер (чит SPACE), и смену комнаты (pop_bake_forget в enter_room — номера тайлов повторяются). Проверено: 8 наборов tests-host зелёные. Мерцания через кадр нет — шесть снимков подряд после каскада попиксельно совпадают в поле, различаются ТОЛЬКО полосы профилировочного бордюра (снимок ловит разную строку растра); пользователь подтвердил визуально. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -168,6 +168,11 @@ void pop_loose_mob_spawn_at(uint8_t room, int row, int col) __banked;
|
||||
void pop_loose_mob_tick(void) __banked;
|
||||
void pop_loose_mob_reset(void) __banked; /* убрать все куски (СТАРТ УРОВНЯ, mobs_count=0) */
|
||||
|
||||
/* Забыть, на какой странице сделана первая запечка тайлов (см. bake_copy в
|
||||
* pop_room.c). Звать при смене комнаты/уровня: номера тайлов повторяются, и
|
||||
* первый же тайл с тем же номером получил бы копию вместо честной запечки. */
|
||||
void pop_bake_forget(void) __banked;
|
||||
|
||||
/* Смена комнаты: куски продолжают падать в СВОИХ комнатах (do_mobs крутит
|
||||
* mobs[] независимо от drawn_room), сбрасывается только heal-история. */
|
||||
void pop_loose_mob_room_changed(void) __banked;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "pop_level.h" /* pop_doorlink2 — состояние нажатия кнопки */
|
||||
#include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев */
|
||||
#include "pop_cdraw.h" /* pop_cd — габарит кадра Кида (y-порядок плиты) */
|
||||
#include "pop_map.h" /* pop_upside — переворот (зелье инверсии) */
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -685,6 +686,54 @@ void pop_room_redraw_seam_left(uint8_t rows) __banked
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- ЗАПЕЧКА НА ВТОРУЮ СТРАНИЦУ — копией, а не пересчётом ----------- *
|
||||
* Точечные запечки ставятся с pages = 2, то есть срабатывают ДВА кадра подряд
|
||||
* — по разу на каждую страницу дабл-буфера, — и оба раза считают одно и то же.
|
||||
* А после первого раза нужный прямоугольник уже лежит в ОЗУ-копии первой
|
||||
* страницы, и его можно просто скопировать: gfx_copy_page берёт источником
|
||||
* ОЗУ-копию НЕактивной страницы (то есть ЧИСТЫЙ фон — спрайты рисуются банком
|
||||
* без тени и в копию не попадают), а приёмник обновляет и в видео-ОЗУ, и в
|
||||
* ОЗУ-копии.
|
||||
*
|
||||
* Замер 2026-08-17: полная запечка щебня — 179 914 такта, колодца — 138 318;
|
||||
* копия прямоугольника 60x39 стоит ~30 000, а 64x9 — ~14 000.
|
||||
*
|
||||
* Слот на тайл помнит, НА КАКОЙ странице сделана первая запечка (+1; 0 = не
|
||||
* было). Копируем только если первая была на ДРУГОЙ странице и дабл-буфер
|
||||
* включён; иначе честно пересчитываем. Такая проверка выдерживает и
|
||||
* переплетение двух запечек в одном кадре, и отключённый дабл-буфер (чит
|
||||
* SPACE), и смену комнаты между кадрами. */
|
||||
static uint8_t bake_pg[30], bake_pg_above[10];
|
||||
|
||||
static uint8_t bake_copy(uint8_t *slot, int x, int ytop, int w, int h)
|
||||
{
|
||||
uint8_t pg = (uint8_t)(gfx_get_draw_page() & 1);
|
||||
gfx_rect_t r;
|
||||
if (!*slot || (uint8_t)(*slot - 1) == pg ||
|
||||
gfx_get_draw_page() == gfx_get_visible_page()) {
|
||||
*slot = (uint8_t)(pg + 1); /* это ПЕРВАЯ запечка */
|
||||
return 0;
|
||||
}
|
||||
*slot = 0;
|
||||
if (pop_upside) ytop = POP_FLIP_TOP(ytop, h); /* копируем ЭКРАННЫЙ прямоугольник */
|
||||
r.x = (int16_t)x; r.y = (int16_t)ytop;
|
||||
r.w = (uint16_t)w; r.h = (uint16_t)h;
|
||||
gfx_copy_page(&r, GFX_COPY_DIRECT);
|
||||
pop_cd_touch(x, ytop, w, h); /* область изменилась и на этой странице */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Смена комнаты/уровня: запечки прошлой комнаты недоделанными не остаются
|
||||
* (pop_trob_room_changed сбрасывает пометки), но слоты обнулить надо — иначе
|
||||
* первый же тайл с тем же номером в новой комнате получит копию вместо
|
||||
* честной запечки. */
|
||||
void pop_bake_forget(void) __banked
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 30; i++) bake_pg[i] = 0;
|
||||
for (i = 0; i < 10; i++) bake_pg_above[i] = 0;
|
||||
}
|
||||
|
||||
/* ---- Плита-потолок (loose ряда 2 комнаты СВЕРХУ) ------------------- *
|
||||
* В полосе кладки у потолка (наш ряд −1) виден только НИЗ плиты
|
||||
* (draw_tile_aboveroom: bottom+loose, всё выше отрезано клипом POP_YOFF).
|
||||
@@ -728,6 +777,8 @@ void pop_ceil_shake_draw(int col) __banked
|
||||
void pop_ceil_bake_empty(int col) __banked
|
||||
{
|
||||
int x = POP_COL_XH[col] * 8;
|
||||
/* Вторая страница — копией с первой (см. bake_copy). */
|
||||
if (bake_copy(&bake_pg_above[col], x, POP_YOFF, 64, CEIL_BAND_H + 1)) return;
|
||||
gfx_set_bank(GFX_BANK_NORMAL);
|
||||
/* Отдельного pop_cd_touch тут не надо: pop_bar_black метит сам, и ровно
|
||||
* этот же прямоугольник (было два вызова на одну область). */
|
||||
@@ -864,6 +915,8 @@ void pop_floor_bake(int row, int col) __banked
|
||||
{
|
||||
int x = POP_COL_XH[col] * 8;
|
||||
int yb = POP_YOFF + 63 * row;
|
||||
/* Вторая страница — копией с первой (см. bake_copy). */
|
||||
if (bake_copy(&bake_pg[row * 10 + col], x, yb + 26, 60, 39)) return;
|
||||
/* Пометку ставит сам pop_bar_black — по тому же прямоугольнику; отдельный
|
||||
* pop_cd_touch тут был вторым вызовом на одну область (4 502 такта). */
|
||||
/* Wipe СВОЕЙ ячейки + правой грани (заходит в соседа) + перерисовка пола.
|
||||
|
||||
@@ -341,6 +341,7 @@ void enter_room_side(uint8_t room, uint8_t side) __banked
|
||||
Kid.room = room;
|
||||
pop_loose_reset(); /* loose-состояние не тянем из старой комнаты */
|
||||
pop_trob_room_changed(); /* отложенные перерисовки пик — не из старой комнаты */
|
||||
pop_bake_forget(); /* и слоты «первая запечка была на странице N» */
|
||||
pop_trob_anim_room(room); /* факелы/зелья: стартовая фаза + trob */
|
||||
pop_start_chompers(room, Kid.curr_row); /* seg000:1288: чомперы РЯДА Кида */
|
||||
pop_check_fall_flo(); /* спецсобытие ур.13: гряда плит сверху */
|
||||
|
||||
Reference in New Issue
Block a user