L2: падение с мечом, разбег-прыжок через 3 тайла, стартовое состояние ворот
BUG-FALL-SWORD-1 — start_fall (seg006:1044) был портирован не целиком: не хватало трёх веток выбора последовательности и уборки меча в ножны. Из-за seq_7 с set_fall(1,15) (дрейф 1 px/кадр) Кид с мечом уезжал примерно на тайл вбок; в оригинале это seq_81_fightfall — падение строго вниз. Сверено по логу SDLPoP: кадры 102..105 дают x = 155,157,159,160. BUG-RJUMP-1 — run_jump (seg005:0AA8) не выравнивал Кида по кромке пола перед толчком, а был заглушкой «полировка K3». Суммарный dx seq_4 — 62 px при тайле 14, то есть провал ровно в три тайла берётся ТОЛЬКО с кромки: без выравнивания Кид не перепрыгивал его никогда. Порт — pop_run_jump_align() в pop_map (беззнаковое сравнение оригинала = «сдвиг не попал в [-8,-1]»). На харнессе: было — толчок с x=165, кадр 44 в колонке 3 (провал); стало — 5 кадров добега, толчок с x=149, кадр 44 даёт x=87 col=1 row=1. Остальные 8 сценариев не изменились. BUG-GATEMOD-1 — load_alter_mod (seg008:198E) был портирован только для зелий, поэтому ворота с bg=1 («Open» по спецификации DAT, табл. 8) стартовали закрытыми. Добавлены ветки gate (1 -> 188) и loose. Ветка wall намеренно НЕ портируется: связи стен наш pop_bg считает по типам соседей в момент отрисовки. На уровнях 1-3 таких ворот всего двое (ур. 1 комн. 5 (0,9); ур. 2 комн. 13 (1,5)) — у остальных bg=2, а 2 и 0 ведут себя одинаково. Убран временный трассировщик pop_dbg_trace/pop_dbg_draw; pop_dbg_trap() оставлен как многоразовый инструмент. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,8 +27,10 @@ BUG-GATE-PASS-1 — однократное наблюдение прохода
|
||||
|
||||
| ID | что | тип | статус |
|
||||
|----|-----|-----|--------|
|
||||
| [Уровень 2](#уровень-2) | баги отрисовки с приёмки | — | **ждут списка от пользователя** |
|
||||
| [BUG-GATE-PASS-1](#bug-gate-pass-1) | проход сквозь закрывшуюся решётку (0,9) комнаты 5 | Major | **ждёт сценария воспроизведения** |
|
||||
| [BUG-GRAB-1](#bug-grab-1) | ур. 2 комн. 9: прыжок с места через 3 тайла — нет зацепа за кромку | Major | **причина найдена (клавиатура, BUG-KBD-5), фикс есть, ждёт игровой проверки** |
|
||||
| [BUG-GATEMOD-1](#bug-gatemod-1) | ворота стартуют закрытыми, хотя в уровне открыты | Major | **фикс есть, ждёт проверки** |
|
||||
| [Уровень 2](#уровень-2) | остальные баги с приёмки | — | принимаются по ходу |
|
||||
| [BUG-GATE-PASS-1](#bug-gate-pass-1) | проход сквозь закрывшуюся решётку (0,9) комнаты 5 | Major | **перепроверить после [BUG-GATEMOD-1](#bug-gatemod-1)** — та же решётка стартовала не в том состоянии |
|
||||
| [T-1](#t-1) | пики перерисовываются безусловно | оптимизация | открыт |
|
||||
| [T-2](#t-2) | Кид перерисовывается в покое | оптимизация | открыт |
|
||||
| [обход 24 комнат](#обход-всех-24-комнат-уровня-1) | таблица заполнена на 5 строк из 24 | ревизия | открыт |
|
||||
@@ -54,10 +56,146 @@ BUG-GATE-PASS-1 — однократное наблюдение прохода
|
||||
вводит ровно три новых фоновых тайла — **большая колонна (низ 8 / верх 9)
|
||||
и верх двери (12)**; если артефакт рядом с ними, это первый подозреваемый.
|
||||
|
||||
*(записей пока нет)*
|
||||
<a id="bug-grab-1"></a>
|
||||
## BUG-GRAB-1. Прыжок с места через провал в 3 тайла: зацепа нет — **ПРИЧИНА НАЙДЕНА, ФИКС ЕСТЬ, ЖДЁТ ИГРОВОЙ ПРОВЕРКИ**
|
||||
|
||||
> **Итог 2026-08-05.** Физика тут ни при чём — виновата клавиатура.
|
||||
> Зажатый Shift снимался автоповтором зажатой стрелки, поэтому к кадрам
|
||||
> 102…106 (окно зацепа) движок видел Shift отпущенным. Полный разбор и
|
||||
> фикс — [BUG-KBD-5](bug_closed.md#bug-kbd-5); поведение Shift в MAME
|
||||
> проверено замером карты `_kbdraw_down`. Осталось подтвердить сам зацеп
|
||||
> живой игрой; версии 2 и 3 ниже проверять только если он всё ещё не выйдет.
|
||||
|
||||
|
||||
**Симптом.** Уровень 2, комната 9. Перепрыгнув на (1,1), Кид должен
|
||||
вернуться обратно: разбегаться негде, поэтому он встаёт на самый край
|
||||
плиты, прыгает с места и **цепляется руками за (1,5)**, после чего
|
||||
подтягивается. У нас Кид с зажатым Shift всё равно срывается.
|
||||
|
||||
**Что уже точно известно (и не надо перепроверять).**
|
||||
|
||||
1. **Физика прыжка у нас совпадает с оригиналом кадр в кадр.** Сверено по
|
||||
логу SDLPoP против трассы харнесса при одинаковом старте `x=95`:
|
||||
|
||||
```
|
||||
кадр 16 18 22 23 24 25 102 103 104 105
|
||||
SDLPoP 95 97 105 112 121 126 128 130 131 133
|
||||
наш 95 97 105 112 121 126 128 130 131 133
|
||||
```
|
||||
Совпадает и по `y`, и по колонке/ряду, и по приземлению на 107–108.
|
||||
|
||||
2. **В оригинале зацеп срабатывает на кадре 106, а не 102..105.**
|
||||
`check_grab` зовётся из ДВУХ мест: ветка «в воздухе» в `check_action`
|
||||
(кадры 102..105) и `do_fall` (seg005) для `actions_4_in_freefall`.
|
||||
Успешная попытка из лога:
|
||||
|
||||
```
|
||||
GRAB try f=106 x=135 y=166 col=4 row=2 fall_y=18
|
||||
GRAB probe x=127 col=4 through=0 front_above=3 modif=0
|
||||
GRAB can_grab=1
|
||||
GRAB OK dist=9
|
||||
-> f=91 x=136 y=181 col=5 row=2 act=2 (повис)
|
||||
```
|
||||
Наш `do_fall` (`pop_map.c`) `check_grab()` из этой ветки тоже зовёт —
|
||||
то есть структура на месте, расходится что-то внутри.
|
||||
|
||||
3. **По харнессу зацеп у нас РАБОТАЕТ**: окно стартовых `x = 91…95`, и
|
||||
короткий шаг ставит Кида ровно туда (91 после первого нажатия, 95 после
|
||||
второго). Зафиксировано тестом `t_grab`.
|
||||
|
||||
**Отсюда главный вопрос был: почему харнесс говорит «работает», а живая
|
||||
машина — «нет».** Расхождение между ними и оказалось уликой; версии
|
||||
выдвигались по убыванию правдоподобия, и сработала первая:
|
||||
|
||||
- **Shift не доезжает до движка — ПОДТВЕРЖДЕНО, это и была причина.**
|
||||
Харнесс подменяет клавиатуру и потому этот путь не проверяет вовсе, а у
|
||||
нас есть история проблем ровно с «Shift + стрелки» (KBD-1, BUG-KBD-3/4).
|
||||
Замер в MAME: при зажатом Shift и зажатой стрелке бит `LSh` в
|
||||
`_kbdraw_down` стоял в нуле. Разбор — [BUG-KBD-5](bug_closed.md#bug-kbd-5).
|
||||
- **Сцена харнесса не равна комнате 9.** Там изолированная комната
|
||||
(соседи — стена), а в игре слева комната 8; кромки шва участвуют в
|
||||
`get_tile`. Проверять чтением `Kid.x` в момент прыжка: попал ли он в
|
||||
окно 91…95 вообще.
|
||||
- **Расхождение в `check_grab`.** Наш вариант зовёт `determine_col()`
|
||||
там, где оригинал зовёт `load_fram_det_col()` (перезагрузка кадра +
|
||||
колонка). Для Кида это обычно одно и то же (`cur_frame` в фазе физики
|
||||
принадлежит ему), но проверить стоит.
|
||||
|
||||
**Инструменты готовы.** В SDLPoP включена отладка (пометка `DBG-GRAB`):
|
||||
`JMP` — покадровая трасса прыжка/падения/виса, `GRAB try|probe|fail|OK` —
|
||||
вход в `check_grab` и причина отказа. Снимается поиском по `DBG-GRAB`.
|
||||
|
||||
**Найдено попутно, отдельным наблюдением.** После касания площадки на
|
||||
кадрах 107–108 (x=140) оба движка снова падают, но X расходится: SDLPoP
|
||||
уводит Кида на 134 (колонка 4), мы — на 141 (колонка 5). Похоже на разную
|
||||
отработку `in_wall()` у стены (2,7). На зацеп не влияет.
|
||||
|
||||
---
|
||||
|
||||
<a id="bug-gatemod-1"></a>
|
||||
## BUG-GATEMOD-1. Ворота стартуют закрытыми, хотя в уровне открыты — **ФИКС ЕСТЬ, ЖДЁТ ПРОВЕРКИ**
|
||||
|
||||
**Симптом (пользователь, 2026-08-04).** Уровень 2, комната 13: решётка
|
||||
между (2,5) и (2,6) обязана быть ОТКРЫТА в начале и захлопнуться, когда Кид
|
||||
нажмёт кнопку (2,4) — после этого назад дороги нет. У нас она закрыта
|
||||
сразу, кнопка бессмысленна, проход не работает.
|
||||
|
||||
**Корень.** Модификатор тайла в ФАЙЛЕ уровня и модификатор в РАНТАЙМЕ —
|
||||
разные величины; оригинал переводит их при загрузке в `load_alter_mod`
|
||||
(seg008:198E), которую зовёт `alter_mods_allrm` из `load_level`:
|
||||
|
||||
```c
|
||||
case tiles_4_gate: *modif = (*modif == 1) ? 188 : 0; break;
|
||||
case tiles_11_loose:*modif = 0; break;
|
||||
case tiles_10_potion:*modif <<= 3; break;
|
||||
```
|
||||
|
||||
Наш `pop_trob_modif` портировал из неё **только зелье**. Для ворот
|
||||
`bg = 1` — это «открыты» (Table 8 спецификации DAT), а в рантайме открытость
|
||||
измеряется высотой подъёма 0..188; мы клали в рантайм-модификатор сырую
|
||||
единицу, то есть «закрыты на 1/188».
|
||||
|
||||
**Фикс.** Ветки ворот и loose дописаны в ленивую инициализацию
|
||||
`pop_trob_modif` (`pop_trob.c`). Ветка СТЕН не портируется намеренно: у нас
|
||||
`pop_bg` считает связи кладки по типам соседей прямо при отрисовке
|
||||
(`wall_modifier`), сохранённый модификатор стены не читается.
|
||||
|
||||
**Что это ещё задевает.** Решётка (0,9) комнаты 5 уровня 1 тоже имеет
|
||||
`bg = 1`, то есть обязана стартовать открытой — Кид сваливается в комнату 1
|
||||
именно через неё, и она захлопывается у него за спиной. Закрывает её
|
||||
стартовый триггер `do_startpos` (seg003:167): для уровней с
|
||||
`tbl_entry_pose == 1` оригинал ВИРТУАЛЬНО ЖМЁТ кнопку комнаты 5 (0,2) —
|
||||
|
||||
```c
|
||||
// Special event: press button + falling entry
|
||||
get_tile(5, 2, 0); trigger_button(0, 0, -1); seqtbl_offset_char(seq_7_fall);
|
||||
```
|
||||
|
||||
Замер в SDLPoP (лог по кадрам): `gate(5,0,9)` идёт `188 → 148 → 88 → 8 → 0`,
|
||||
шаги 40/60/80 — это `gate_close_speeds`, то есть быстрое закрытие
|
||||
(`trigger_gate` вернул тип 3). У нас этот триггер портирован, и закрытие
|
||||
работает.
|
||||
|
||||
Полный список ворот с `bg = 1`: ур. 1 комн. 5 (0,9); ур. 2 комн. 13 (1,5).
|
||||
Остальные ворота уровней 1–3 имеют `bg = 2` → 0, и для них ничего не
|
||||
меняется (при модификаторе 2 и 0 и отрисовка, и `can_bump_into_gate` дают
|
||||
одно и то же).
|
||||
|
||||
**Побочная находка: чит обхода комнат отматывал мир.** После фикса
|
||||
пользователь увидел «ворота снова открылись», пройдя `+` в комнату 2 и `-`
|
||||
обратно. Причина не в воротах: `ROOMNAV` звал `pop_trob_reset()` перед
|
||||
`enter_room`, тот обнулял `room_seen[]`, и `pop_trob_modif()` перечитывал
|
||||
модификаторы из уровня заново — то есть чит откатывал открытые/закрытые
|
||||
ворота, выдвинутые пики и нажатые кнопки. Пока ворота с `bg=1` ошибочно
|
||||
стартовали закрытыми, откат был не виден. `pop_trob_reset()` из навигации
|
||||
убран: она обязана только телепортировать, исходное состояние даёт
|
||||
перезапуск уровня. Замер, который это показал: `room_modif` комнаты 5
|
||||
после `+`/`-` = `00 00 0B 00 09 00 08 01 00 BC` — последний байт 0xBC = 188,
|
||||
файловое значение.
|
||||
|
||||
---
|
||||
|
||||
|
||||
<a id="ручная-перепроверка-2026-08-03"></a>
|
||||
# Ручная перепроверка фиксов (2026-08-03)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user