Падающие плиты: передний слой по пометкам, честные спрайты, замер кадра

Слой fore переведён на пометки ОБЪЕКТОВ вместо окна вокруг персонажа —
порт set_redraw_fore/redraw_frames_fore (seg007:0550, seg008:214):
pop_set_redraw_fore + pop_fore_needed + pop_fore_tile_b, пометки ставит
падающий кусок вокруг себя (draw_mob, seg007:1147).

Ключевая правка: пометки соседа считаются в ПРОХОДЕ ОТРИСОВКИ, а не в
тике.  Стояли в цикле тика — то есть по позиции ДО mob_tick_one, а кусок
рисовался уже по новой; пока он летит внутри ряда, тайлы совпадают, но в
кадр пересечения границы пометка указывала на прежний тайл и колонна кусок
не перекрывала.  Ровно один кадр, как и наблюдалось.

Спрайты падающего куска: obj_id = 10 (add_mob_to_objtable, seg007:1170),
части берутся по этому индексу — 70/74/72, а не 41/43/42 (плита В ПОКОЕ).
Отсюда была «цельная ровная плита» вместо двух половин со сдвигом.

Убрана подпорка «перерисовать соседний тайл поверх куска»: тащила на плиту
чужой узор и окно и стоила по полной отрисовке тайла на кусок за кадр.
Коридор heal сужен по высоте 32 -> 24 (реальный след спрайта 16 px).
gfx_set_bank вынесен из потайлового цикла в обрамление прохода.

Выяснено и зафиксировано: clip.right = 40 в add_mob_to_objtable — МЁРТВЫЕ
данные.  set_clip_rect вызывается под chtab_flip_clip[chtab_id], а для
окружения флаг равен нулю — оригинал падающие куски не клипует вовсе.
Портировать нечего; две попытки это сделать были ошибочны.

Замер кадра (маркеры m1..m4, оставлены временно для проверки правок):
покой 196 614 тактов (15,2 % кадра при периоде 1 290 000), во время
падения гряды среднее 222 667, пик 1 428 990 — то есть 111 % кадра,
шесть кадров подряд за пределом.  Логика неизменна (88 020), растут фон
(до 887 376) и спрайты (до 660 792).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-13 21:38:59 +03:00
parent c31930dcad
commit 50e4eda2ad
8 changed files with 123 additions and 1 deletions
+18
View File
@@ -889,6 +889,24 @@ static void char_footprint(int obj_x, int obj_y, uint16_t w, uint16_t h,
* obj_x — ЛОГИЧЕСКАЯ X кадра (до ×8/7), obj_y — низ спрайта, w/h — размер
* кадра; всё остальное берётся из самого персонажа (ch). Окно fore-клипа к
* этому моменту уже стоит: его задаёт тот, кто нарисовал спрайт. */
/* Передний слой ОДНОГО тайла — вход для прохода по пометкам
* (pop_fore_needed). Без окна fore-клипа: пометка уже сузила работу до
* нужных тайлов, а кусок тайла обязан лечь целиком — у оригинала foretable
* ничем не режется. */
void pop_fore_tile_b(int row, int col) __banked
{
uint8_t saved = pop_t_fclip_on;
pop_t_fclip_on = 0;
fore_tile(row, col);
pop_t_fclip_on = saved;
}
/* Банк на ВЕСЬ проход пометок, а не на каждый тайл: помеченных тайлов за
* кадр бывает больше десятка, и две смены банка на каждый — заметная доля
* прохода, который сам по себе дешёвый. */
void pop_fore_pass_begin(void) __banked { gfx_set_bank(GFX_BANK_SPRITE); }
void pop_fore_pass_end(void) __banked { gfx_set_bank(GFX_BANK_NORMAL); }
void pop_fore_over_char(const pop_char_t *ch, int obj_x, int obj_y,
uint16_t w, uint16_t h) __banked
{