P5: гейты холостого хода в pop_loose_tick — минус 33 840 тактов на кадре
Замер 11/15 показал, что loose-механика берёт 28 872 такта в комнате, где не анимируется ни одна плита и не летит ни один кусок. Раскладка зондами m9..m12: два цикла по тайлам 9 852, обход 14 слотов mob 12 090, поиск куска над головой Кида 5 868 (там ещё и банковый трамплин). Два гейта: loose_any (статик pop_map.c) — «идёт ли анимация плит». Ставят пять мест записи ненулевой фазы: make_loose_fall, ветка потолка в check_press, do_knock для обоих рядов и восстановление фазы из room_modif при входе в комнату. Снимает его сам цикл, по факту прохода, в котором не осталось ни одной живой фазы. pop_mob_busy (резидент pop_state.c) — «занят ли слот падающего куска» (active или дочистка clean). Ставит mob_alloc, снимает обход по факту пустой таблицы. В резиденте, а не в pop_room.c, потому что читает его pop_map из банка 3, а писучие статики банкового модуля наружу не видны. Гейт отвечает не на «есть ли в комнате плиты», а на «идёт ли анимация»: у лежащей плиты-потолка фаза нулевая, и крутить нечего (вопрос пользователя). Асимметрия намеренная — ложная единица стоит одного холостого прохода, ложный ноль стоит застывшей навсегда плиты, поэтому взвод стоит рядом с КАЖДОЙ записью, а снятие только по факту пустого прохода. Стало: 132 / 996 / 546, вся функция 28 872 -> 2 760. На кадре работа 801 768 -> 767 928. Ожидание по реестру было -28 000. Покрытие: новый phys_loose_gate_survives_room_change на пятое место взвода (фаза восстановлена входом в комнату) — единственное, которое не прогонял ни один тест, и дающее самый тихий отказ. Мутационная проверка: со снятым взводом тест падает (фаза 3 вместо 4). Заодно отладочный старт сразу в целевую комнату: make ROOM=15 POS=2 (дефолт), roomtest стартует в 11/15 с Кидом в (0,2). kid_init ставит x = x_bump[col] + TILE_SIZEX, а это левая граница СЛЕДУЮЩЕЙ колонки — с неё физика относила Кида в тайл чомпера, и он погибал на старте (найдено пользователем). Сдвиг внутрь на 2: колонку определяет весовая точка кадра, поэтому число снято замером, а не выведено геометрией. План работ между сессиями — docs/perf_registry.md §4: очередь позиций со статусами, текущий бюджет сцены, рецепт её воспроизведения и метод замера. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -101,6 +101,20 @@ void pop_start_level(void) __banked
|
||||
* и разворачивается seq_5 */
|
||||
}
|
||||
|
||||
#ifdef DBG_START_ROOM
|
||||
/* ОТЛАДОЧНЫЙ СТАРТ: сразу в целевую комнату оптимизации, минуя проход
|
||||
* уровня. Задаётся сборкой (make ROOM=15 POS=2), по умолчанию — сцена
|
||||
* 11/15 из docs/perf_l11_room15.md: Кид в (0,2), справа чомпер под
|
||||
* факелом, дальше второй факел и страж.
|
||||
*
|
||||
* Ставится ПОСЛЕ чекпойнта намеренно: отладочная позиция должна
|
||||
* перебивать и его тоже, иначе рестарт уровня уводил бы Кида из
|
||||
* измеряемой комнаты. Направление и позу входа не трогаем — они из
|
||||
* данных уровня, как у обычного старта. */
|
||||
start_room = DBG_START_ROOM;
|
||||
pos = DBG_START_POS;
|
||||
#endif
|
||||
|
||||
/* Рестарт уровня = load_level() заново (play_level, seg003:57): в
|
||||
* исходное возвращаются И модификаторы (пики/ворота), И сами тайлы —
|
||||
* разбитые плиты целы, выпитые зелья на месте (BUG-RESPAWN-1), и
|
||||
@@ -146,6 +160,24 @@ void pop_start_level(void) __banked
|
||||
|
||||
enter_room(start_room);
|
||||
kid_init(seq, (int8_t)(pos % 10), (int8_t)(pos / 10), dir);
|
||||
#ifdef DBG_START_ROOM
|
||||
/* ...и поправить x: kid_init ставит `x_bump[col] + TILE_SIZEX`, а это
|
||||
* ЛЕВАЯ ГРАНИЦА СЛЕДУЮЩЕЙ колонки (порт set_start_pos — в данных уровня
|
||||
* стартовые позиции подобраны под такую договорённость). Отладочный
|
||||
* старт называет тайл, В КОТОРОМ Кид должен оказаться, поэтому сдвигаем
|
||||
* его внутрь названного: с границы физика относит Кида к колонке правее,
|
||||
* и в 11/15 он стартовал прямо в челюстях (найдено пользователем
|
||||
* 2026-08-19).
|
||||
*
|
||||
* Отступ ровно 2, а не «половина тайла»: колонку определяет не сам x, а
|
||||
* ВЕСОВАЯ ТОЧКА кадра (determine_col -> dx_weight: dx позы минус
|
||||
* weight-биты, с учётом направления), поэтому геометрически ровной
|
||||
* середины тут нет. Число снято замером живой сцены: x = 98 при позе
|
||||
* стойки даёт curr_col = 2, x = 94 — уже 1. */
|
||||
Kid.x = (uint8_t)(pop_x_bump[(pos % 10) + FIRST_ONSCREEN_COLUMN] +
|
||||
TILE_SIZEX - 2);
|
||||
Kid.curr_col = (int8_t)(pos % 10);
|
||||
#endif
|
||||
/* Спецсобытие «вход падением» (set_start_pos, seg003:0196): на 7-м
|
||||
* уровне Кид ставится в комнату 17, а экран тут же переводится на
|
||||
* комнату ПОД ней (`goto_other_room(3)`: y −= 189, ряд пересчитать) —
|
||||
|
||||
Reference in New Issue
Block a user