Ускорение холостого хода: указательный обход вместо arr[i] в горячих циклах
Замер зелёного блока (комната 23 уровня 13, MAME, такты эмулятора) показал, что 86% его стоимости в ПОКОЕ — это pop_loose_tick, который не делает ничего. Причина — кодоген SDCC, подтверждена чтением .asm. С `int pos` и записью pop_loose_modif[pos] компилятор держал счётчик в IX-фрейме, каждую итерацию заново складывал 16-битный адрес элемента, клал его в локал и тут же вычитывал обратно парами `pop bc / pop hl / push hl / push bc`. 40 холостых итераций (30 тайлов + 10 потолков) стоили 27 936 тактов. То же в pop_loose_mob_tick: запись mobs[i] заставляла умножать i на sizeof(mob_t)=15 заново под КАЖДОЕ поле (.active/.clean/.x/.y), 14 пустых слотов — 35 790. Правка — обход указателем, счётчик uint8_t, пустые слоты отсеиваются в вызывающем цикле (а не гардом внутри mob_tick_one, до которого надо ещё дойти). Холостая итерация стала `ld a,(de) / or a,a / jp Z` — три инструкции вместо дюжины с обращениями к памяти. Результат (такты MAME, холостой кадр): циклы по тайлам 27 936 -> 9 852 (2,8x) pop_loose_mob_tick 35 790 -> 7 416 (4,8x) pop_loose_tick 70 866 -> 24 384 (2,9x) ЗЕЛЁНЫЙ БЛОК 82 242 -> 35 760 (2,3x) Банки ужались: BANK3 -90 Б, BANK7 -74 Б. Все 8 наборов tests-host проходят; комната 23 в MAME рисуется корректно. Плюс ВРЕМЕННАЯ оснастка замера (маркеры m9..m16, pop_dbg_kind) — она же показала, что пик зелёного блока сидит НЕ в тряске плит, а в запекании тайлов; разбор продолжается, оснастку снять перед закрытием темы. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -256,6 +256,32 @@ MEM-BANK2, MEM-BANK5, CLIP-1, KBD-1, DBG-CHEATS.
|
||||
Осознанное расхождение: мигания Кида спрайтами тени во время вспышки нет —
|
||||
запись в [`../docs/impl_diff.md`](../docs/impl_diff.md).
|
||||
|
||||
<a id="loose-shake-runs"></a>
|
||||
### LOOSE-SHAKE-RUNS. Дрожание плит: пометки по сменам кадра, а не по кадрам
|
||||
|
||||
**Идея пользователя 2026-08-13, на этап полиша.**
|
||||
|
||||
`pop_loose_tick` на КАЖДОМ кадре отсчёта ставит `pop_set_redraw(pos,
|
||||
POP_RD_LOOSE, 1)` — полную перерисовку тайла, десять раз за отсчёт. А
|
||||
кадр дрожания меняется не каждую фазу: таблицы
|
||||
(`POP_LOOSE_FRAM_BOTTOM` = 43,73,43,74,74,43,43,43,74,74,74) дают
|
||||
|
||||
фаза 1 2 3 4 5 6 7 8 9 10
|
||||
кадр 73 43 74 74 43 43 43 74 74 74
|
||||
^^^^^ ^^^^^^^^ ^^^^^^^^
|
||||
парами и тройками одно и то же
|
||||
|
||||
С фазы 5 кадры идут ТРОЙКАМИ. Значит вместо шести пометок с `pages = 1`
|
||||
хватит двух — на фазах 5 и 8 — но с `pages = 2` (обе страницы дабл-буфера,
|
||||
иначе на второй застынет старый спрайт и пойдёт мерцание через кадр).
|
||||
|
||||
**Выигрыш ~20 % работы зелёного блока и ТОЛЬКО на дрожащих плитах.**
|
||||
Наивный вариант «ставить лишь на смене кадра» выигрыша НЕ даёт: пять смен
|
||||
по две страницы — те же десять перерисовок (проверено арифметикой
|
||||
2026-08-13, до правки).
|
||||
|
||||
Вопрос к этапу полиша: стоит ли неочевидный код такого узкого выигрыша.
|
||||
|
||||
<a id="bg-once"></a>
|
||||
### BG-ONCE. Задний фон рисуется ОДИН раз; вместо чёрных баров — heal
|
||||
|
||||
|
||||
Reference in New Issue
Block a user