Уровень 6: переход на 7-й, портал, многокомнатное падение плиты

Всё проверено пользователем в MAME.

1. Переход 6 -> 7 падением.  leave_room (seg002:0504) для «вниз» на уровне 6
   из комнаты 1 даёт особый результат −2, главный цикл (seg000:0893) читает
   его как ++next_level; вход на 7-м (set_start_pos, seg003:0196) ставит Кида
   в комнату 17 и сразу переводит экран на комнату под ней.  Проверка ОБЯЗАНА
   идти раньше связи вниз: у комнаты 1 сосед снизу есть (шахта, комната 3).

2. BUG-BALCONY-RIGHT: правая половина портала не рисовалась.  id 12 стоял в
   FORE_ENV_IDS (в tile_table он fore_id ЗЕЛЬЯ), но зелье рисуется из
   chtab_1, а в chtab_6 под этим номером — правая часть арки балкона 32x62,
   идущая в backtable.  Спрайт уезжал в fore-атлас, env-страница получала
   дырку (idx 12: w=0 h=0).  Найдено трассой POP_TRACE_BT + чтением каталога
   .atl; дифф комнаты с оригиналом 1151 -> 375.

3. BUG-BELOWROW-WALL: жёлтые треугольники в шахте падения.  load_rowbelow
   (seg008:368) при отсутствующей комнате снизу подставляет tiles_0_empty
   колонкам 1..9 и tiles_20_wall только левому краю; у нас стеной забивались
   все 11 позиций.

4. BUG-MOB-MULTIROOM: честный mob_down_a_row (seg007:1387) — кусок переходит
   в комнату снизу и летит дальше.  Плита (1,7) комнаты 6 пролетает шахту
   комнаты 7 и жмёт кнопку (2,7) комнаты 11, открывая ворота комнаты 18.

5. BUG-MOB-STALE-PAGE: чистка следа куска стояла под гейтом «в отрисованной
   комнате» — улетевший вниз оставлял себя на одной из страниц навсегда.

6. BUG-CHAR-STALE-PAGE: тень застывала на двух страницах в РАЗНЫХ позах.
   Прямоугольник и valid пишутся внутри `if (w && h)`, а снимок состояния
   брался безусловно — при нулевом спрайте слот залипал «тихим».  Остаток
   (почему спрайт нулевой) заведён как SPRITE-ZERO-W0 в BUGS_OPEN.

NEXT_SESSION переписан: следующая задача — зацеп за край пола в свободном
падении (вход на уровень 7).  tests-host 5/5, size-check чист.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 23:01:58 +03:00
parent e4ef489872
commit 9ecea17ba6
13 changed files with 310 additions and 65 deletions
+21
View File
@@ -14,6 +14,7 @@
| ID | что | тип | статус |
|----|-----|-----|--------|
| [SPRITE-ZERO-W0](#sprite-zero-w0) | кадр персонажа изредка отдаёт спрайт 0x0 (залипание уже вылечено) | **редкий** | открыт: нужна трасса маппинга W0 |
| [GATE-FORE-KID](#gate-fore-kid) | Кид в проёме ворот виден поверх решётки | окклюзия | открыт: портирован только шовный случай |
| [FORE-DUP](#fore-dup) | передний слой тайла рисуется дважды при перекрытии объектов | оптимизация | открыт: **сначала замерить**, потом чинить |
| [DIED-ON-BUTTON](#died-on-button) | `died_on_button` (seg007:776) не портирован | порт | открыт |
@@ -339,6 +340,26 @@ for (tile_row = x_top_row; tile_row <= char_bottom_row; ++tile_row)
---
<a id="sprite-zero-w0"></a>
## SPRITE-ZERO-W0. Кадр персонажа изредка отдаёт спрайт 0x0 — РЕДКИЙ
Всплыло при разборе [BUG-CHAR-STALE-PAGE](BUGS_CLOSED.md#bug-char-stale-page)
(тень застыла на двух страницах в разных позах). Залипание слота вылечено —
`cd_sig_make` больше не берёт снимок, если кадр не рисовали, — но САМА
причина нулевого спрайта не найдена: `atlas_image` для валидного кадра
изредка отдаёт запись 0x0.
Подозрение: конкуренция за окно W0. `pop_char_draw` маппит страницу атласа
(`gfx_w0_map(pages[page].page)`) и держит её до `gfx_w0_unmap()` в конце, а
внутри этого окна успевают отработать `cd_splash` и `pop_sword_draw`; рядом
в кадре W0 маппят чтение данных уровня (`pop_level_tile`, `pop_level_set_tile`)
и mob-тик. Если какой-то путь размапливает окно раньше времени, чтение
заголовка спрайта даст нули.
Как ловить: watchpoint на порт окна 0 либо счётчик «w==0 при непустом кадре»
в `pop_char_draw` с записью кадра/страницы/idx в отладочную ячейку, дальше
читать её из MAME. Симптом редкий (пользователь поймал дважды).
<a id="gate-fore-kid"></a>
## GATE-FORE-KID. Кид, стоящий В ПРОЁМЕ ворот, виден ПОВЕРХ решётки