FORE-DUP: передний слой рисуется дважды при перекрытии — заведено с разбором
Найдено вопросом пользователя. У нас fore-проход зовёт каждый рисующий по своему прямоугольнику, поэтому тайл, накрытый двумя объектами, рисуется два раза (Кид+отражение — всегда, Кид+соперник — весь ближний бой). В оригинале дубль невозможен по построению: redraw_at_char (seg003:0427) только ПОМЕЧАЕТ тайлы, а set_redraw_fore (seg007:0550) — redraw_frames_fore[tilepos] = frames, присваивание. Единственный обход тайлов рисует передний кусок один раз. Картинку не портит (прозрачный блит идемпотентен), тратит такты в самом горячем месте. Запись требует СНАЧАЛА замера: окно клипа вместо перебора тайлов в своё время дало 3.2x, и переход на пометки может часть вернуть. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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»; сравнить число нарисованных кусков с числом уникальных тайлов.
|
||||
Если дубль мал — оставить как есть и закрыть запись.
|
||||
|
||||
Reference in New Issue
Block a user