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

Слой 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
+8
View File
@@ -372,6 +372,7 @@ int main(void)
pop_mirror_heal();
pop_fore_heal(); /* + следы оверлея (шире прямоугольника Kid) */
PROF(2); /* логика (тот же синий) */
pop_dbg_m1(); /* ЗАМЕР: начало логики */
kid_tick(); /* play_seq: следующий кадр */
pop_phys_tick(); /* K3: падение/приземление/стена */
pop_guard_tick(); /* логика стража — В БАНКЕ (guards.c) */
@@ -447,6 +448,7 @@ int main(void)
}
PROF(4); /* слой фона */
pop_dbg_m2(); /* ЗАМЕР: конец логики / начало фона */
pop_loose_tick(); /* loose-полы: анимация + перерисовка (СЛОЙ ФОНА */
/* — ДО Kid, чтобы Kid всегда был поверх плиты) */
@@ -613,6 +615,7 @@ int main(void)
}
update_kid_render_dx(); /* straddle: смещение спрайта, если kid_room≠cur_room */
PROF(6); /* спрайты: страж, Kid, fore поверх */
pop_dbg_m3(); /* ЗАМЕР: конец фона / начало спрайтов */
/* check_mirror (seg003:0798) — ПЕРВАЯ строка draw_people
* (seg008:228A), до отрисовки кого бы то ни было: если Кид только что
* пролетел сквозь зеркало, тень должна родиться ДО того, как слот
@@ -645,6 +648,10 @@ int main(void)
if (pop_kid_hurt) pop_kid_hurt = 0;
}
pop_loose_mob_draw_over(); /* падающая плита НИЖЕ Kid → поверх него (y-порядок) */
/* ПЕРЕДНИЙ СЛОЙ по пометкам — последним в кадре, как foretable у
* оригинала (draw_tables, seg008:1373). Пометки ставят сами
* объекты вокруг себя (pop_redraw.h). */
pop_fore_needed();
pop_hp_draw(); /* полоса HP — только при изменении */
PROF(6); /* fore поверх Kid + борта */
/* Fore-слой Кида — В КОНЦЕ, после плиты и полосы HP: окно fore-клипа
@@ -673,6 +680,7 @@ int main(void)
pop_dbg_room_label(cur_room); /* номер комнаты палочками — в банке */
#endif
pop_dbg_m4(); /* ЗАМЕР: конец спрайтов */
gfx_wait_vsync();
if (flash_on) { /* строб: цвет держался один кадр растра */
flash_bg(0, 0, 0);