From 8beb66a48df2e37ee73b59a27eba5eeda0bc6642 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Mon, 10 Aug 2026 22:22:48 +0300 Subject: [PATCH] =?UTF-8?q?FORE-DUP:=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9=20=D1=81=D0=BB=D0=BE=D0=B9=20=D1=80=D0=B8?= =?UTF-8?q?=D1=81=D1=83=D0=B5=D1=82=D1=81=D1=8F=20=D0=B4=D0=B2=D0=B0=D0=B6?= =?UTF-8?q?=D0=B4=D1=8B=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=BA=D1=80=D1=8B=D1=82=D0=B8=D0=B8=20=E2=80=94=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=BE=20=D1=81=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D0=B1=D0=BE=D1=80=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Найдено вопросом пользователя. У нас fore-проход зовёт каждый рисующий по своему прямоугольнику, поэтому тайл, накрытый двумя объектами, рисуется два раза (Кид+отражение — всегда, Кид+соперник — весь ближний бой). В оригинале дубль невозможен по построению: redraw_at_char (seg003:0427) только ПОМЕЧАЕТ тайлы, а set_redraw_fore (seg007:0550) — redraw_frames_fore[tilepos] = frames, присваивание. Единственный обход тайлов рисует передний кусок один раз. Картинку не портит (прозрачный блит идемпотентен), тратит такты в самом горячем месте. Запись требует СНАЧАЛА замера: окно клипа вместо перебора тайлов в своё время дало 3.2x, и переход на пометки может часть вернуть. Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/bug_list.md | 52 +++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/applications/PoP/roomtest/bug_list.md b/applications/PoP/roomtest/bug_list.md index ed25f2d..578dbdd 100644 --- a/applications/PoP/roomtest/bug_list.md +++ b/applications/PoP/roomtest/bug_list.md @@ -329,3 +329,55 @@ seg007:0101) и перерисовывает весь его слой `anim` п добавить в `trob_rcode`-проверку нужные коды и соответствующий вид пометки (`POP_RD_SPIKE` / `POP_RD_FLOOR`), а зелье — переставить в порядке обхода так, чтобы оно рисовалось ПОСЛЕ факела. + +--- + +## FORE-DUP. Передний слой тайла рисуется ДВАЖДЫ при перекрытии объектов + +Найдено пользователем 2026-08-10 (вопросом, а не по симптому — картинка +верная, страдают только такты). + +**У нас.** Fore-проход зовёт КАЖДЫЙ рисующий по своему прямоугольнику: +`pop_char_fore` для слотов Кида и соперника, `pop_mirror_draw` для отражения. +Окно клипа (`pop_fore_set_clip`) у каждого своё. Если футпринты двух +объектов накрывают один тайл, его передний кусок рисуется два раза. + +Когда случается: +- **Кид и отражение** — ВСЕГДА (стоят на одном тайле зеркала); этот случай + создан фиксом fore-прохода над отражением 2026-08-10; +- **Кид и соперник в одном тайле** — то есть весь ближний бой; +- Кид и падающий кусок плиты. + +**Картинку не портит:** куски переднего слоя идут прозрачным блитом-копией, +операция идемпотентная. Портило бы при XOR/mono с накоплением — таких в +fore-слое нет. + +**Такты тратит,** и в самом дорогом месте: fore-проход исторически самая +тяжёлая часть кадра (memory `pop_fore_layer_cost` — было 78 % кадра, окно +клипа и кэш кладки дали 3.2×). + +**Как устроено в оригинале — дубль НЕВОЗМОЖЕН по построению.** +`redraw_at_char` (seg003:0427) ничего не рисует, а только помечает тайлы +своего прямоугольника: + +```c +for (tile_row = x_top_row; tile_row <= char_bottom_row; ++tile_row) + for (tile_col = x_col_left; tile_col <= x_col_right; ++tile_col) + set_redraw_fore(get_tilepos(tile_col, tile_row), 1); +``` + +а `set_redraw_fore` (seg007:0550) — это `redraw_frames_fore[tilepos] = frames`, +ПРИСВАИВАНИЕ. Два персонажа на одном тайле оставят там ту же единицу, и +единственный обход тайлов нарисует передний кусок один раз. + +**Что делать.** Механизм пометок у нас уже есть и прямо назван портом этой +архитектуры — `pop_redraw.h`. Fore-слой остался единственным местом на +прямом вызове. Приведение к оригиналу: `pop_char_fore`/`pop_mirror_draw` +вместо прохода ставят пометки, а один проход в конце кадра их разбирает. + +**СНАЧАЛА ЗАМЕРИТЬ, потом чинить.** Это самый горячий путь, и окно клипа +(вместо перебора тайлов) в своё время дало 3.2× — переход на пометки может +часть этого вернуть назад. Замер: брейкпоинт на листьях fore-слоя со +счётчиком, сцена «бой в комнате 3 уровня 1» и «Кид на тайле зеркала, +ур. 4»; сравнить число нарисованных кусков с числом уникальных тайлов. +Если дубль мал — оставить как есть и закрыть запись.