safe_step по оригиналу + BUG-CHOMP-JUMP-1 в низкоприоритетные, T-2 закрыт

safe_step при distance == 0: возвращена ветка оригинала (seg005:0604) —
seq_39 (шаг 11) вместо нашего «шага-1».  Для СТЕНЫ результат прежний: первый
же dx(1) даёт бамп, ровно как в трассе живого SDLPoP из BUG-SEAM-PINGPONG.
Для ЧОМПЕРА бампа нет (в разомкнутой фазе он не препятствие), и оригинал
уносит Кида на все 11 px — а мы шагали на один.  Это и был «микрошаг вместо
нормального короткого шага» перед челюстями.
ВНИМАНИЕ на приёмке ур.1: это тот самый safe_step из BUG-SEAM-PINGPONG —
проверить комнату 6, осторожный шаг вплотную к воротам шва.

BUG-CHOMP-JUMP-1 (низкий, маловоспроизводим, на пререлиз): прыжок с места
вплотную к чомперу иногда даёт кадр с отступом назад.  В запись сложено всё,
что выяснено: seq_3_standing_jump состоит ТОЛЬКО из положительных dx (значит
отступ даёт bumped, а не анимация); is_obstacle для чомпера у нас совпадает
с оригиналом; прямая трасса (UP+RIGHT одновременно) отката не показала —
главная гипотеза в порядке нажатий (↑ раньше → уводит в up_pressed с
выравниванием x).  Там же метод ловли.

T-2 (idle-skip) закрыт — сделан шире, чем формулировался, как DRAW-COST
шаг 1 (a25ce58).
This commit is contained in:
2026-08-08 19:46:34 +03:00
parent db4106a55e
commit 073a6e0264
2 changed files with 69 additions and 23 deletions
+60 -16
View File
@@ -20,8 +20,9 @@
| [BUG-CHEAT-FIGHT-1](#bug-cheat-fight-1) | `+`/`` в бою с вынутым мечом → Кид теряет управление | Major (чит) | открыт | | [BUG-CHEAT-FIGHT-1](#bug-cheat-fight-1) | `+`/`` в бою с вынутым мечом → Кид теряет управление | Major (чит) | открыт |
| [BUG-GATE-PASS-1](#bug-gate-pass-1) | проход сквозь закрывшуюся решётку (0,9) комнаты 5 | Major | **ждёт сценария**: прогоном 2026-08-07 не воспроизведён | | [BUG-GATE-PASS-1](#bug-gate-pass-1) | проход сквозь закрывшуюся решётку (0,9) комнаты 5 | Major | **ждёт сценария**: прогоном 2026-08-07 не воспроизведён |
| [BUG-SPIKE-1](#bug-spike-1) | пики залипают выдвинутыми рядом с Кидом | **низкий** | маловоспроизводимый: ни сценарием, ни попиксельной подгонкой X не поднимается | | [BUG-SPIKE-1](#bug-spike-1) | пики залипают выдвинутыми рядом с Кидом | **низкий** | маловоспроизводимый: ни сценарием, ни попиксельной подгонкой X не поднимается |
| [BUG-CHOMP-JUMP-1](#bug-chomp-jump-1) | прыжок с места вплотную к чомперу: кадр с отступом назад | **низкий** | маловоспроизводимый: на повторе не поднялся; на пререлиз |
| [T-1](#t-1) | пики перерисовываются безусловно | оптимизация | открыт | | [T-1](#t-1) | пики перерисовываются безусловно | оптимизация | открыт |
| [T-2](#t-2) | Кид перерисовывается в покое | оптимизация | открыт | | ~~T-2~~ | Кид перерисовывается в покое | оптимизация | **ЗАКРЫТ 2026-08-08** — [DRAW-COST шаг 1](TASKS_OPEN.md#draw-cost) |
--- ---
@@ -279,26 +280,69 @@ Smoke-прогон уровня 3 (пользователь, 2026-08-05) дал
**Приоритет:** отдаётся почти бесплатно ПОСЛЕ T-2, отдельно не окупается. **Приоритет:** отдаётся почти бесплатно ПОСЛЕ T-2, отдельно не окупается.
<a id="t-2"></a> <a id="t-2"></a>
## T-2. Idle-skip: не перерисовывать Кида, когда ничего не происходит ## T-2. Idle-skip — **ЗАКРЫТ 2026-08-08**
**Сейчас:** `kid_heal``kid_draw``pop_fore_over_kid` идут каждый кадр, Сделан как шаг 1 задачи [DRAW-COST](TASKS_OPEN.md#draw-cost) (коммит
даже когда Kid стоит и в его тайлах ничего не меняется. Это ровно поведение `a25ce58`), и шире, чем формулировался здесь: пропускается не только Кид, а
оригинала (`draw_game_frame`, seg000:917 — `draw_moving()` + `draw_tables()` ЛЮБОЙ персонаж, у которого с прошлой отрисовки этой страницы дабл-буфера не
безусловно), но у него это дёшево, а у нас нет. изменился ни один вход отрисовки, — включая труп стража и ждущего стража.
Условие «обе страницы уже получили это состояние», которого требовала эта
запись, выполнено само собой: снимок входов хранится ПО СТРАНИЦАМ.
**Надо:** пропускать heal+draw Кида, когда кадр/поза/координаты не менялись Замер: комната 1.3 с трупом стража, Кид стоит — 210 % -> 116 % кадрового
и в его тайлах нет активной анимации. периода, ноль вызовов `pop_heal_fast` за кадр. Контракт — шапка
`pop_cdraw.h`, разбор и что делать дальше — `TASKS_OPEN.md#draw-cost`.
**Осторожно (дабл-буфер):** пропускать можно **не раньше второго подряд** Связь с T-1 сработала как и предсказано: пока Кида не перерисовываем, heal'а
неизменного кадра — иначе одна из двух страниц останется со старым нет, стирать пики нечем. Но T-1 остаётся открытым — трогать пики
содержимым. Условие «обе страницы уже получили это состояние». безусловно мы всё ещё продолжаем, когда Кид рядом ДВИЖЕТСЯ.
**Связь с T-1:** после T-2 пики отпадают сами — раз Кида не перерисовываем, ---
heal'а нет, стирать пики нечем, редрой не нужен.
**Связь с KBD-1:** это ещё и минус DI-окна в самых спокойных кадрах — ровно <a id="bug-chomp-jump-1"></a>
там, где тапают Shift+стрелку (остаток KBD-1 отложен, см.
[`TASKS_CLOSED.md`](TASKS_CLOSED.md#kbd-1)). ## BUG-CHOMP-JUMP-1. Прыжок с места вплотную к чомперу: кадр с отступом назад — НИЗКИЙ ПРИОРИТЕТ, МАЛОВОСПРОИЗВОДИМ
> **Статус 2026-08-08.** Наблюдение пользователя на приёмке L3-CHOMP: Кид
> стоит вплотную СЛЕВА от чомпера лицом вправо, прыжок с места — в анимации
> проскакивает кадр, где он «чуть отступил назад», и только потом идёт
> прыжок. В оригинале прыжок идёт прямо с места. **На повторе в тот же
> заход не воспроизвёлся** — отложено до пререлиза.
**Что уже установлено (чтобы не разбирать заново).**
1. **Это НЕ анимация.** `seq_3_standing_jump` (SDLPoP `seqtbl.c:382`)
состоит только из положительных смещений:
`act(run_jump), f16, f17, dx(2) f18…f22, dx(7) f23, dx(9) f24, dx(5) dy(-6) f25`.
Ни одного отрицательного `dx` — отката в последовательности нет вовсе.
Значит отступ даёт `bumped()`, то есть физика посчитала въезд в
препятствие и выровняла `Char.x` назад.
2. **`is_obstacle` для чомпера у нас совпадает с оригиналом** (seg004:037E):
препятствие только при `modif == 2`, причём именно `== 2`, БЕЗ маски
`0x7F` — то есть окровавленный чомпер (`0x82`) в ванили не бампит вовсе.
Проверено, расхождения нет.
3. **Прямая трасса прыжка отката НЕ показала.** Ввод «UP и RIGHT
одновременно» (mame bridge, `key UP 24` + `key RIGHT 24`) даёт чистое
движение вперёд: `x` 148 -> 155, кадр становится 178 (перемололо). Ни
одного кадра с уменьшением `x`.
**Главная гипотеза — ПОРЯДОК НАЖАТИЙ.** Если ↑ приходит на кадр раньше →,
то `control_standing` уходит не в `standing_jump()`, а в `up_pressed()`
вертикальный прыжок с зацепом, а он **выравнивает `Char.x`**. Отсюда и
«отступил, потом прыгнул». Проверять надо `check_jump_up` /
`jump_up_or_grab` / `grab_up_no_floor_behind` (seg005:0836 и далее), а не
прыжок с места. Внимание на `can_climb_up` (seg005:0828): там у чомпера
ЕСТЬ спецкейс (`seq_73_climb_up_to_closed_gate` при взгляде ВПРАВО) — он у
нас портирован (`pop_map.c`, ветка `TILE_MIRROR || TILE_CHOMPER`), но именно
вокруг него и стоит копать.
**Как ловить.** Брейкпоинт на резидентном `_kid_tick` с
`{printf "f=%d x=%d act=%d col=%d",b@Kid+0,b@Kid+1,b@Kid+6,b@Kid+4; g}`
одна строка на кадр, адрес `_Kid` из `.sprinter-cc-roomtest/roomtest.map`
(после КАЖДОЙ пересборки другой). Плюс стоп-кадр `1` в момент отступа и
чтение `Kid` из памяти. Метод — memory `z80_profiling_method`.
--- ---
+9 -7
View File
@@ -229,16 +229,18 @@ static void safe_step(void)
if (distance) { if (distance) {
Char.repeat = 1; Char.repeat = 1;
seqtbl_offset_char((uint8_t)(distance + SEQ_STEP_BASE)); seqtbl_offset_char((uint8_t)(distance + SEQ_STEP_BASE));
} else if (pop_edge_type() == EDGE_WALL) { } else if (pop_edge_type() != EDGE_WALL && Char.repeat != 0) {
/* вплотную к стене: маленький шаг-1 — check_bumped отскочит назад
* (шаг назад со звуком, как оригинал), НЕ seq_39 (шаг за край=падение). */
Char.repeat = 1;
seqtbl_offset_char((uint8_t)(1 + SEQ_STEP_BASE));
} else if (Char.repeat != 0) {
Char.repeat = 0; Char.repeat = 0;
seqtbl_offset_char(SEQ_44_STEP_ON_EDGE); seqtbl_offset_char(SEQ_44_STEP_ON_EDGE);
} else { } else {
seqtbl_offset_char(SEQ_39_UNSAFE_STEP); /* реальный обрыв (edge=CLOSER) */ /* Вплотную к СТЕНЕ оригинал тоже уходит сюда — seq_39 (шаг 11).
* Раньше здесь стоял «маленький шаг-1»: у стены результат тот же
* (трасса живого SDLPoP в BUG-SEAM-PINGPONG: `safe_step(d=0) -> step,
* на первом dx(1) x=62 -> bump`), но у ЧОМПЕРА бампа нет — в
* разомкнутой фазе он не препятствие, — и оригинал уносит Кида на все
* 11 px, а мы шагали на один. Отсюда «микрошаг вместо нормального
* короткого шага» перед челюстями (приёмка 2026-08-08). */
seqtbl_offset_char(SEQ_39_UNSAFE_STEP);
} }
} }