Оптимизация логики: окно коллизии как в оригинале + деление таблицей
Замерено брейкпоинтами в MAME (уровень 1 комната 1, Кид стоит у факела). Калибровка, без которой цифры не сходятся: такт totalcycles != номинальный T-такт Z80, wait-state'ы ОЗУ Sprinter дают ~2,4x (get_tile 574 против 1422). 1. Окно перебора коллизии — как у оригинала (left_checked_col..right_checked_col, seg004:0047), было: все 14 колонок каждый кадр. Признак годности слота у нас дешевле оригинального: не массив номеров комнат с очисткой, а границы окна, которые move_coll_to_prev переносит в prev вместе с флагами; бамп считается по пересечению двух окон. check_chomped_flags тоже ограничен окном, иначе протухшие слоты дают фантомный перемол. 2. get_tile_div_mod — таблицами tile_div_tbl/tile_mod_tbl (seg006:702), было /14 и %14. SDCC разворачивал это в __divsint + __modsint, а __modsint внутри зовёт __divsint ещё раз: 5 400 тактов на вызов, 13 вызовов за кадр = 16 % кадрового периода на «в какой колонке точка». 3. get_row_collision_data: ряд разрешается один раз на весь перебор (было — get_tile на каждую колонку, 1 422 такта), грань идёт шагом TILE_SIZEX как в оригинале, wall_type таблицей вместо switch. Итог: check_collisions 60 888 -> 42 750, физика Кида 100 578 -> 67 518, синяя полоса ~60 % -> ~30 % кадрового периода. Профиль остатка и следующие цели (отрисовка Кида 47 %, process_trobs 21 %) — в TASKS_OPEN.md#draw-cost. tests-host: все 5 наборов прошли. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -55,7 +55,7 @@
|
||||
| 2 | [L3-CHOMP](#l3-chomp) | **СЛЕДУЮЩАЯ**: чомперы (5 шт) | прохождение ур. 3 |
|
||||
| — | [L3-SKEL](#l3-skel) | скелет ур. 3 — **сделан 2026-08-07**, ждёт финальной приёмки | — |
|
||||
| 3 | [L3-PASS](#l3-pass) | приёмка уровня 3 (обход комнат) | закрытие цели |
|
||||
| — | [DRAW-COST](#draw-cost) | шаг 1 сделан (пропуск неизменившегося персонажа): в покое 210 % -> **116 %**. ШАГ 2 — цена ОДНОЙ перерисовки: бегущий Кид даёт циан почти 100 % | плавность на ВСЕХ уровнях |
|
||||
| — | [DRAW-COST](#draw-cost) | шаг 1 (пропуск персонажа) и логика сделаны: синяя полоса 60 % -> 30 %. ОСТАЛОСЬ: отрисовка одного Кида = 47 % кадра, `process_trobs` = 21 % | плавность на ВСЕХ уровнях |
|
||||
| — | [L1-SPEED](#l1-speed) | игра на ~39 % быстрее оригинала | ощущение от ВСЕХ уровней; берётся в любой момент |
|
||||
| — | [TUNE-1](#tune-1) | параметры движка → cfg-файл (сейчас `pop_tune.h`) | отладка таймингов и моды; берётся по мере надобности |
|
||||
|
||||
@@ -358,6 +358,67 @@ W1/W2 (см. [BUG-GUARD-COLOR-1](bug_closed.md#bug-guard-color-1)).
|
||||
понадобится — держать не один прямоугольник, а 3-4 отдельных и мержить
|
||||
только при переполнении.
|
||||
|
||||
### Шаг 2 сделан частично: ЛОГИКА (синяя полоса) 2026-08-09
|
||||
|
||||
Пользователь: «на стоящем Киде с двумя факелами на логику уходит 60 %
|
||||
кадрового периода — недопустимо». Разобрано брейкпоинтами в MAME
|
||||
(`z80_profiling_method`), сцена: уровень 1 комната 1, Кид СТОИТ вплотную к
|
||||
левому факелу (то есть пропуск персонажа НЕ срабатывает — худший случай).
|
||||
|
||||
**Калибровка, которую надо знать заранее.** Один такт `totalcycles` в MAME
|
||||
— НЕ один номинальный T-такт Z80: у Sprinter на обращениях к ОЗУ есть
|
||||
wait-state'ы, и замеренная стоимость выходит **≈ 2,4× номинала**
|
||||
(`get_tile`: 574 номинальных против 1 422 замеренных). Считать бюджет по
|
||||
таблице T-тактов из справочника нельзя — только мерить. Кадр растра =
|
||||
430 000; главный цикл спейсится тремя `gfx_wait_vsync`, поэтому работа
|
||||
СВЫШЕ 430 000 стоит сразу целый лишний кадр.
|
||||
|
||||
**Что нашли и починили:**
|
||||
|
||||
| правка | что было | стало |
|
||||
|---|---|---|
|
||||
| окно перебора коллизии как в оригинале (было: все 14 колонок каждый кадр) | `check_collisions` 60 888 | 50 940 |
|
||||
| `get_tile_div_mod` — таблицей (`tile_div_tbl`/`tile_mod_tbl`), было `/14` и `%14` | 5 400 тактов на вызов, 13 вызовов за кадр ≈ 70 000 = **16 % кадра** | ~250 на вызов |
|
||||
| разрешение ряда вынесено из цикла колонок + грань шагом 14 + `wall_type` таблицей | `check_collisions` 58 026 | **42 750** |
|
||||
|
||||
Самое дорогое было НЕ там, где ожидалось: `/14` и `%14` SDCC разворачивает
|
||||
в `__divsint` + `__modsint`, а `__modsint` внутри зовёт `__divsint` ещё раз —
|
||||
два полноценных 16-битных деления на каждый вопрос «в какой колонке точка».
|
||||
Оригинал делит таблицей (seg006:702) — мы просто не портировали это место.
|
||||
|
||||
**Профиль работы за один логический кадр ПОСЛЕ правок (470 964 такта):**
|
||||
|
||||
| блок | тактов | % растрового кадра |
|
||||
|---|---|---|
|
||||
| see_kid + ctrl_tick + heal | 46 920 | 11 |
|
||||
| kid_tick (play_seq) | 6 468 | 1,5 |
|
||||
| физика Кида (`pop_phys_tick`) | 67 518 | 16 |
|
||||
| страж + боёвка | 10 350 | 2,4 |
|
||||
| `pop_loose_tick` | 27 438 | 6,4 |
|
||||
| **`pop_process_trobs`** | **92 346** | **21,5** |
|
||||
| `pop_redraw_needed` + шов | 6 474 | 1,5 |
|
||||
| skip + отрисовка соперника (пусто) | 11 178 | 2,6 |
|
||||
| **`pop_char_draw` + `pop_char_fore` Кида** | **201 336** | **47** |
|
||||
| борта | 732 | 0,2 |
|
||||
|
||||
Синяя полоса (ввод+heal+логика) была ~60 % → стала ~30 %. Внутри физики
|
||||
`check_collisions` — по-прежнему больше половины (42 750 из 67 518), и в ней
|
||||
15 разрешений тайла на кадр: три ряда × окно 4–5 колонок, как в оригинале.
|
||||
|
||||
**Что осталось — по убыванию (это и есть остаток шага 2):**
|
||||
|
||||
1. **Отрисовка одного Кида 201 336 тактов = 47 % кадра.** Ровно тот «циан»,
|
||||
который пользователь назвал следующей целью. План — ниже.
|
||||
2. **`pop_process_trobs` 92 346 на ДВА факела** (46 000 на факел). У
|
||||
оригинала `process_trobs` только двигает состояние, рисование —
|
||||
в `redraw_needed`; у нас `redraw_needed` стоит 6 474, значит блиты факелов
|
||||
сидят внутри process_trobs. Разобрать, где именно.
|
||||
3. **`pop_loose_tick` 27 438** при полном отсутствии падающих плит в комнате —
|
||||
похоже, безусловный проход по всем 30 тайлам.
|
||||
4. Работа за цикл 470 964 против 430 000 бюджета: **не хватает ~41 000**,
|
||||
чтобы уложиться в три растровых кадра вместо четырёх. Любая из правок
|
||||
выше даёт игре сразу +25 % скорости — граница проходит рядом.
|
||||
|
||||
### Шаг 2 (СЛЕДУЮЩИЙ, назначен пользователем): ДВИЖУЩИЙСЯ Кид
|
||||
|
||||
Пропуск закрывает только покой. Наблюдение пользователя 2026-08-08: как
|
||||
|
||||
Reference in New Issue
Block a user