PoP roomtest: плита-потолок, порядок слоёв по SDLPoP, фиксы окклюзии и Y

Фича — плита-ПОТОЛОК (loose ряда 2 комнаты сверху, комн.5 (2,5) над комн.6):
- check_press (seg006:1683) портирован целиком: кадры виса 87..99 и подъёма
  135..140 «нажимают» тайл, за который Kid держится; кадр 79 — удар снизу
  (с проверкой action, как в оригинале); стояние — тайл под ним;
- ряд −1 в pop_map.get_tile = ряд 2 комнаты сверху (порт find_room_of_tile),
  состояние тряски/падения — pop_ceil_modif[10]; do_knock(-1) трясёт потолок;
- падение: mob переведён на координаты оригинала (y_loose_land/y_something),
  спавнится в ряду −1, по move_loose находит пол → loose_land: debris +
  do_knock; heal коридора — по прошлой позиции ДЛЯ КАЖДОЙ страницы;
- урон: check_loose_fall_on_kid + fell_on_your_head (seq_52/seq_22, −1 HP)
  и «брызги» draw_hurt_splash (kid image 218);
- колодец наверх: leave_room «вверх» проверяется ПЕРВЫМ (иначе y≈248 при
  подтягивании ловил check_leave_below и ронял Kid из уровня);
- персистентность: общий tile-override (щебень внизу, пустота в комнате
  сверху) вместо debris-only.

Окклюзия — приведена к оригиналу (найдено трассировкой собранного SDLPoP):
- draw_tile_right/anim_right/draw_loose кладут спрайты в add_backtable
  НАПРЯМУЮ, минуя ptr_add_table → правая грань соседа («шахматка» столба 93),
  blueline и грани loose/пик соседа ВСЕГДА под персонажем.  draw_other_overlay
  поверх Kid даёт только: 42 при левом соседе-поле, base, свои пики, bottom
  (overlay_mid_tile);
- порядок объектов: тайл Kid (set_objtile_at_char) и порядок обхода
  (ряды 2→0, колонки 0→9), внутри тайла — сортировка по y (sort_curr_objs);
  то же правило для падающей плиты (pop_loose_mob_draw_over);
- fore-слой рисуется ПОСЛЕ оверлеев (foretable после midtable), иначе тёмный
  скос floor_left_overlay ложился поверх колонны;
- fore_tile больше не рисует bottom_id (в оригинале он в backtable) — минус
  2..4 блита за кадр;
- полоса потолка поверх Kid = draw_tile_bottom(1)+draw_loose(1)+draw_tile_fore
  (arg_0=1 добавляет в foretable), остальное — под ним;
- следы оверлея восстанавливаются на ОБЕИХ страницах (pop_fore_heal).

Прочее:
- control(): при action bumped/in_freefall управление игнорируется целиком
  (seg005) — иначе прерванный присед терял dy(1)+dy(1) из medland и Kid
  навсегда оставался на 2px выше пола;
- check_bumped: стена ищется по колонке переднего края (а не curr_col) +
  гард разворота — Kid больше не проходит сквозь опущенную решётку шва;
- pop_floor_bake для смены floor→debris (bake_empty стирал верх стены ряда
  ниже — чёрный прямоугольник);
- в pop_room_redraw_seam_left восстанавливается полоса потолка над решёткой.

Проверено в MAME (bridge); эталон — собранный SDLPoP из applications/PoP/SDLPoP.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 17:35:25 +03:00
parent 86d7615841
commit 63a3b60524
10 changed files with 731 additions and 103 deletions
@@ -256,3 +256,36 @@ save/restore. Детально — `pop_banking_architecture`, `graphics_constr
`libc_one_function_per_module`, `sprite_engine_perf`, `mdview2_size_budget`.
- `applications/PoP/roomtest/bug_list.md` — открытые баги Фазы B (не блокируют
оптимизацию, но держать в уме при рефакторе pop_map/pop_bg).
---
## 7. Лишние блиты в горячем пути (добавлено 2026-07-27)
Найдено при разборе окклюзии по эталону SDLPoP: **наш «передний слой» рисовал
спрайты, которых в оригинале там нет** — это и артефакты, и лишняя работа
каждый кадр. Исправлено: `fore_tile` (вызывается для КАЖДОГО тайла футпринта
Kid, обычно 2–4 за кадр) рисовал ещё и `bottom_id` — переднюю кромку пола; в
оригинале `draw_tile_fore` (seg008:690) добавляет только `add_foretable`-часть,
а `bottom` идёт через `draw_tile_bottom` в backtable (ПОД персонажем).
Итог: −2..4 блита за кадр, `_CODE` −388 Б, ушла «тень» у основания колонны.
**Что проверить тем же методом (по одному вопросу к каждому месту: а есть ли
этот спрайт в оригинале в ЭТОЙ таблице?):**
1. `pop_room_draw`/`draw_tile` — вызовы на входе в комнату не критичны по
скорости, но по ним стоит сверить состав слоёв (backtable vs foretable).
2. `overlay_mid_tile` — сейчас точный порт midtable-части `draw_tile2`;
проверить, не рисуем ли `base_id` там, где оригинал его не рисует
(loose: base=0, потому что кадр плиты идёт через `draw_loose` в backtable).
3. `pop_loose_mob_tick` — перерисовка соседнего тайла (`draw_tile(mob_row,
mob_col+1)`) КАЖДЫЙ кадр падения: в оригинале это `set_redraw_full` на
один кадр; можно ограничить только тайлом, который реально пересекается
с куском.
4. `pop_ceil_shake_draw` — heal 64×8 + два `draw_tile(-1,·)` на кадр тряски;
проверить, нужен ли второй тайл (правую грань loose в полосе потолка
оригинал не рисует вовсе — `draw_tile_aboveroom` без `draw_tile_anim_right`).
5. `fore_only_tile` для полосы потолка: вызывается для всех колонок габарита,
а оригинал (`redraw_needed_above`) — только для колонок с флагом
`redraw_frames_above`; сузить до колонок, реально задетых спрайтом.
6. `wall_pattern` внутри fore/overlay — тяжёлая (PRNG + до 4 блитов); проверить,
не зовём ли её там, где оригинал ограничивается `wall_fram_main`.