Вторая страница запечки — КОПИЕЙ с первой (зелёная 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_tick(void) __banked;
|
||||||
void pop_loose_mob_reset(void) __banked; /* убрать все куски (СТАРТ УРОВНЯ, mobs_count=0) */
|
void pop_loose_mob_reset(void) __banked; /* убрать все куски (СТАРТ УРОВНЯ, mobs_count=0) */
|
||||||
|
|
||||||
|
/* Забыть, на какой странице сделана первая запечка тайлов (см. bake_copy в
|
||||||
|
* pop_room.c). Звать при смене комнаты/уровня: номера тайлов повторяются, и
|
||||||
|
* первый же тайл с тем же номером получил бы копию вместо честной запечки. */
|
||||||
|
void pop_bake_forget(void) __banked;
|
||||||
|
|
||||||
/* Смена комнаты: куски продолжают падать в СВОИХ комнатах (do_mobs крутит
|
/* Смена комнаты: куски продолжают падать в СВОИХ комнатах (do_mobs крутит
|
||||||
* mobs[] независимо от drawn_room), сбрасывается только heal-история. */
|
* mobs[] независимо от drawn_room), сбрасывается только heal-история. */
|
||||||
void pop_loose_mob_room_changed(void) __banked;
|
void pop_loose_mob_room_changed(void) __banked;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "pop_level.h" /* pop_doorlink2 — состояние нажатия кнопки */
|
#include "pop_level.h" /* pop_doorlink2 — состояние нажатия кнопки */
|
||||||
#include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев */
|
#include "pop_kid.h" /* Kid.curr_col/curr_row — порядок оверлеев */
|
||||||
#include "pop_cdraw.h" /* pop_cd — габарит кадра Кида (y-порядок плиты) */
|
#include "pop_cdraw.h" /* pop_cd — габарит кадра Кида (y-порядок плиты) */
|
||||||
|
#include "pop_map.h" /* pop_upside — переворот (зелье инверсии) */
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.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 комнаты СВЕРХУ) ------------------- *
|
/* ---- Плита-потолок (loose ряда 2 комнаты СВЕРХУ) ------------------- *
|
||||||
* В полосе кладки у потолка (наш ряд −1) виден только НИЗ плиты
|
* В полосе кладки у потолка (наш ряд −1) виден только НИЗ плиты
|
||||||
* (draw_tile_aboveroom: bottom+loose, всё выше отрезано клипом POP_YOFF).
|
* (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
|
void pop_ceil_bake_empty(int col) __banked
|
||||||
{
|
{
|
||||||
int x = POP_COL_XH[col] * 8;
|
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);
|
gfx_set_bank(GFX_BANK_NORMAL);
|
||||||
/* Отдельного pop_cd_touch тут не надо: pop_bar_black метит сам, и ровно
|
/* Отдельного 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 x = POP_COL_XH[col] * 8;
|
||||||
int yb = POP_YOFF + 63 * row;
|
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_bar_black — по тому же прямоугольнику; отдельный
|
||||||
* pop_cd_touch тут был вторым вызовом на одну область (4 502 такта). */
|
* pop_cd_touch тут был вторым вызовом на одну область (4 502 такта). */
|
||||||
/* Wipe СВОЕЙ ячейки + правой грани (заходит в соседа) + перерисовка пола.
|
/* Wipe СВОЕЙ ячейки + правой грани (заходит в соседа) + перерисовка пола.
|
||||||
|
|||||||
@@ -341,6 +341,7 @@ void enter_room_side(uint8_t room, uint8_t side) __banked
|
|||||||
Kid.room = room;
|
Kid.room = room;
|
||||||
pop_loose_reset(); /* loose-состояние не тянем из старой комнаты */
|
pop_loose_reset(); /* loose-состояние не тянем из старой комнаты */
|
||||||
pop_trob_room_changed(); /* отложенные перерисовки пик — не из старой комнаты */
|
pop_trob_room_changed(); /* отложенные перерисовки пик — не из старой комнаты */
|
||||||
|
pop_bake_forget(); /* и слоты «первая запечка была на странице N» */
|
||||||
pop_trob_anim_room(room); /* факелы/зелья: стартовая фаза + trob */
|
pop_trob_anim_room(room); /* факелы/зелья: стартовая фаза + trob */
|
||||||
pop_start_chompers(room, Kid.curr_row); /* seg000:1288: чомперы РЯДА Кида */
|
pop_start_chompers(room, Kid.curr_row); /* seg000:1288: чомперы РЯДА Кида */
|
||||||
pop_check_fall_flo(); /* спецсобытие ур.13: гряда плит сверху */
|
pop_check_fall_flo(); /* спецсобытие ур.13: гряда плит сверху */
|
||||||
|
|||||||
Reference in New Issue
Block a user