7ae691b070
Найдено пользователем (2026-08-17, уровень 1 комната 6): падающая плита (-1,5) перекрывает собой кромку потолка (-1,6), чего физически быть не может. Дыра архитектурная: pop_fore_needed обходил только ряды 0..2, ряда -1 в переднем слое не было вовсе. Сверено с оригиналом. redraw_needed_tiles (seg008:1B06) обходит ряды 2,1,0, а ПОТОМ отдельным проходом ряд 2 комнаты сверху (redraw_needed_above), и его draw_tile_fore кладёт куски в FOREtable. Падающая плита идёт в MIDtable (draw_mobs). draw_tables рисует back -> mid -> fore (seg008:1373), поэтому у оригинала кромка потолка оказывается поверх плиты сама собой. Порт: - pop_fore_needed: проход по ряду -1 добавлен и идёт ПОСЛЕДНИМ, как в оригинале. Свой набор пометок (rdfa/rdfa_pending) — как и у самих перерисовок ряда -1 (rda_*), это отдельный проход, а не 11-я колонка; - новый лист pop_ceil_fore_tile_b (pop_bg.c) — тот же redraw_needed_above, что уже рисовался над персонажем (ceil_over_kid_tile), плюс окно клипа ровно на полосу столбца и ov_mark (полоса идёт банком без тени, на второй странице её восстановит pop_fore_heal); - mob_mark_neighbour помечает ряд -1, пока кусок достаёт до кромки. Кромка живёт в трёх верхних строках поля (dby = 2 при клипе по POP_YOFF), спрайт куска занимает mob_y-16 .. mob_y, отсюда условие mob_y <= 18 — три кадра после отрыва (y = 2, 5, 11 при ускорении 3). Помечаются ОБА столбца, которые кусок накрывает по x (mob_x .. mob_x+62 = col и col+1); именно поэтому страдал сосед. По бюджету работа появляется только в эти три кадра на кусок и попадает в циановую фазу, где сейчас запас (270 тыс. из 400 тыс.). Замер на ур.13 — следующим шагом. 8 наборов tests-host зелёные. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
68 lines
4.8 KiB
C
68 lines
4.8 KiB
C
/*
|
||
* pop_redraw.h — пометки «перерисовать тайл» и их разбор.
|
||
*
|
||
* Порт архитектуры оригинала: логика анимации НИЧЕГО не рисует, она ставит
|
||
* флаг (`set_redraw_full`/`set_wipe`/`redraw_20h`/`redraw_21h`, seg007), а
|
||
* отрисовка идёт отдельным проходом (`redraw_needed`, seg008:0178). У нас
|
||
* так же: pop_map/pop_trob зовут pop_set_redraw*, а pop_redraw_needed()
|
||
* (главный цикл) разбирает пометки и дёргает pop_bg.
|
||
*
|
||
* ЗАЧЕМ (кроме сходства с SDLPoP): из __banked-кода резидентная страница W3
|
||
* недостижима — ни напрямую, ни транзитивно (docs/layout_plan_v2.md §2 R2).
|
||
* Пока pop_map звал pop_bg, его нельзя было использовать из банка стражей.
|
||
* Пометки живут в W1/W2 и зовутся откуда угодно.
|
||
*
|
||
* ОТЛИЧИЕ ОТ ОРИГИНАЛА: у нас не один экран с dirty-rect, а две страницы
|
||
* дабл-буфера со своей ОЗУ-копией фона, поэтому счётчик пометки — это ЧИСЛО
|
||
* СТРАНИЦ (обычно 2), а вид перерисовки хранится явно: heal+рисовать поверх
|
||
* (транзиент) или запечь новый фон. В оригинале вид кодируется тем, в какой
|
||
* из таблиц redraw_frames_* стоит флаг.
|
||
*/
|
||
#ifndef POP_REDRAW_H
|
||
#define POP_REDRAW_H
|
||
|
||
#include <stdint.h>
|
||
|
||
/* Виды перерисовки тайла (row*10+col). */
|
||
#define POP_RD_SPIKE 1 /* пики: heal + оба тайла (redraw_21h) */
|
||
#define POP_RD_LOOSE 2 /* loose: дрожащий кадр / кадр покоя */
|
||
#define POP_RD_LOOSE_GONE 3 /* loose провалился: запечь пусто */
|
||
#define POP_RD_FLOOR 4 /* пол изменился: кнопка/щебень/поднятый меч */
|
||
#define POP_RD_LEVELDOOR 5 /* створка двери уровня (ПРАВАЯ половина) */
|
||
#define POP_RD_GATE 6 /* решётка ворот (tilepos = САМИ ворота) */
|
||
#define POP_RD_CHOMP 7 /* чомпер: кадр смыкания челюстей */
|
||
|
||
/* Виды перерисовки полосы у потолка (по колонке). */
|
||
#define POP_RDA_CEIL 1 /* плита-потолок: дрожащий кадр / покой */
|
||
#define POP_RDA_CEIL_GONE 2 /* плита-потолок провалилась: колодец */
|
||
|
||
/* Пометить тайл/колонку: kind — вид, pages — на скольких страницах
|
||
* дабл-буфера перерисовать (1 = только текущая, 2 = обе). Повторная
|
||
* пометка перекрывает вид и берёт максимум счётчика. */
|
||
void pop_set_redraw(uint8_t tilepos, uint8_t kind, uint8_t pages) __banked;
|
||
|
||
/* ПЕРЕДНИЙ СЛОЙ по пометкам — порт redraw_frames_fore/set_redraw_fore
|
||
* (seg007:0550). В оригинале эти пометки ставят ОБЪЕКТЫ, каждый вокруг
|
||
* себя: персонаж — прямоугольник футпринта (redraw_at_char, seg003:0576),
|
||
* падающий кусок — соседа справа и второй тайл на границе рядов (draw_mob,
|
||
* seg007:1147), анимация тайла — свой тайл (draw_trob). Пометка
|
||
* ОДНОКАДРОВАЯ: передний слой транзиентен, его снимает heal.
|
||
*
|
||
* Разбор (pop_fore_needed) звать ПОСЛЕ отрисовки всех объектов кадра. */
|
||
void pop_set_redraw_fore(uint8_t tilepos) __banked;
|
||
|
||
/* Пометить передний слой полосы у потолка (ряд −1), столбец col. Ставит
|
||
* падающий кусок, достающий до кромки потолка. */
|
||
void pop_set_redraw_fore_above(uint8_t col) __banked;
|
||
void pop_fore_needed(void) __banked;
|
||
void pop_set_redraw_above(uint8_t col, uint8_t kind, uint8_t pages) __banked;
|
||
|
||
/* Разобрать пометки: нарисовать всё помеченное на ТЕКУЩЕЙ (back) странице и
|
||
* уменьшить счётчики. Звать из главного цикла в слое ФОНА — до персонажей. */
|
||
void pop_redraw_needed(void) __banked;
|
||
|
||
/* Сбросить все пометки (смена комнаты/уровня). */
|
||
void pop_redraw_reset(void) __banked;
|
||
|
||
#endif
|