Уровень 4: skip по маске тайлов + порт loose_land, ворота 0xFF, пламя в фон

ОПТИМИЗАЦИЯ.  Метка «фон трогали» была одним union-прямоугольником на
страницу, и три факела комнаты склеивались в полосу x 40..280 на всю
комнату — Кид, стоящий между крайними факелами, терял пропуск перерисовки
и каждый кадр платил полным fore-проходом.  Теперь это маска тайлов
(uint16_t pop_cd_dmask[2][3]: бит = колонка, слово = ряд, набор = страница),
проверка — три AND через резидентный pop_cd_hit.  Гранулярность тайла — это
гранулярность оригинала (redraw_frames_anim[tilepos], set_wipe;
подтайловое уточнение там только по высоте, wipe_heights).  Замер на (1,7):
циан 233 515 -> 24 781, работа за кадр 517 609 -> 306 553, период 4 -> 3
растровых кадра.

BUG-LOOSE-BUTTON-1.  Упавшая плита не нажимала кнопку.  Три слоя: порт
loose_land не звал trigger_button вовсе; pop_room_col_landing считала
площадкой только чистый пол, а у оригинала их семь (пол, пика, обе кнопки,
зелье, оба факела); сигнал приходил в момент ОТРЫВА плиты, из-за чего
ворота начинали открываться, пока она ещё в воздухе.  Нажатие в оригинале
ОДНО, но с button_type = tiles_14_debris — это «открыть НАСОВСЕМ»
(modifier 0xFF), и кнопка съедается.  Посадка в комнате снизу переехала на
новый сигнал pop_loose_exit (взводит mob_tick_one, когда кусок ушёл ниже
поля).

BUG-GATE-FF-1.  0xFF был перегружен: сторожевое «тайла нет» в gate_modif и
живое «открыто навсегда» из trigger_gate.  gate_passable заворачивал Кида в
воротах, нарисованных открытыми.  Мёртвая ветка убрана.

BUG-TORCH-CHOMP-1.  Чомпер (0,7) комнаты 23 healит x 224..255 / y 30..93 и
стирал пламя факела (0,6), которое рисуется в ячейке правого соседа.  Фикс —
запекать пламя (GFX_BANK_NORMAL): у факела все девять кадров на общем
канвасе 16x18 и непрозрачны, протухнуть в ОЗУ-копии нечему, а heal чомпера
сам возвращает огонь и кладёт челюсти поверх — z-порядок как в оригинале.
Пузырёк зелья так нельзя (ползёт вверх, нужен heal) — остаётся в SPRITE.

Заведено открытым: died_on_button (seg007:776) не портирован — нужен тайл
tiles_5_stuck в атласе.

Проверено пользователем в MAME (уровень 4: плита 16(1,1) -> кнопка 17(0,1)
-> ворота 23(0,9); комната 23 с чомпером и факелом); make -C tests-host —
все 5 наборов.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-10 17:52:04 +03:00
parent 6a824dd7ab
commit 4718bff767
13 changed files with 364 additions and 47 deletions
+28
View File
@@ -69,6 +69,34 @@ MAME (`z80_profiling_method`) на роомтесте, уровень 1 комн
139 398 (27 %), циан (`PROF(6)`) 233 515 (45 % работы = 54 % растрового
кадра, начинается на 74 % первого кадра и кончается на 123 %).
## СДЕЛАНО 2026-08-10: метка «фон трогали» стала маской ТАЙЛОВ
Было: один union-прямоугольник на страницу. Три факела трогают по пятну
16x18 в колонках 1, 6 и 8, а их объединение — полоса `x 40..280` на всю
комнату; Кид, стоящий где угодно между крайними факелами, в неё попадал и
перерисовывался каждый кадр со всем fore-проходом.
Стало: `uint16_t pop_cd_dmask[2][3]` — бит на колонку, слово на ряд, набор на
страницу. Колонка берётся сдвигом (`x >> 5`), ряд — цепочкой сравнений;
проверка в `cd_quiet` — три `AND` через резидентный `pop_cd_hit`.
Гранулярность тайла — это гранулярность ОРИГИНАЛА: пометки там тоже по
тайлам (`redraw_frames_anim[tilepos]`, `set_wipe`), персонажи привязаны к
тайлу через `tile_object_redraw[tilepos]`, а единственное подтайловое
уточнение (`wipe_heights`) — по высоте, не по ширине. Полутайл (16 px) не дал
бы ничего: пламя рисуется с отступом 8 px и шириной 16, то есть занимает
середину тайла и задевает обе половины.
Замер на той же сцене, где снимался профиль ниже (Кид неподвижно на (1,7)):
| | было | стало |
|---|---:|---:|
| циан (спрайты + fore) | 233 515 | **24 781** |
| работа за кадр | 517 609 | **306 553** |
| период | 4 растровых кадра | **3** |
---
## 0. Дворцовая кладка в fore-проходе — 27 % кадра НА НОЛЬ ПИКСЕЛЕЙ
**Цена: 139 863 такта за кадр (32 % растрового кадра), полезных пикселей —