MEM-BANK2 шаг 3: холодная половина слоя фона в банк 7 (90.4% -> 35.8%)
pop_bg.c разрезан по ЧАСТОТЕ вызова, а не по размеру:
pop_bg.c (банк 2) горячее fore-проход, оверлеи, кладка, клип
pop_room.c (банк 7) холодное draw_tile, точечные перерисовки, mob,
загрузка атласов
Стык — три тонкие __banked-обёртки (wall_pattern, wall_pattern_reset,
draw_gate_back): тела остаются непомеченными, поэтому горячий fore-проход,
зовущий wall_pattern до девяти раз за кадр, платит ноль, а трамплин
достаётся только холодному пути — ~40 вызовов на вход в комнату, 26 000
тактов = 0.06 кадра РАЗОВО. Общее состояние (pop_loose_modif, pop_ceil_modif,
obj_row/obj_col) писучее, лежит в _DATA/W2 и видно обеим половинам.
Заодно удалена мёртвая potion_bubble (169 Б).
Грабля: n_banks объявляет само приложение (roomtest.c), а не sprinter-cc.
Восьмой банк без правки константы линкуется молча, _bank_pages[7] остаётся
0xFF, и программа встаёт намертво до первого кадра. Диагноз снят дампом
_bank_pages из MAME.
Замер (ALLOCS=3000): BANK2 11 942 -> 5 872, BANK7 6 035; _CODE и куча не
тронуты (22 556 / 4 301).
Проверено: tests-host зелёные; построчная сверка pop_bg.c+pop_room.c против
дорефакторного pop_bg.c — ни одной строки логики не пропало; 8 комнат в MAME
до/после совпали попиксельно по активному экрану (различия только в фазе
анимации факелов и кадре Кида); живой прогон с переходами комнат, боем и
воротами сверен контрольным запуском HEAD-бинаря.
DRAW-COST поднят в приоритете: замер пользователя (ур.1 комната 3, страж
убит, Кид стоит) — синяя 80%, зелёная 20%, циан 110%, итого ~210 %
кадрового периода В ПОКОЕ.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -322,6 +322,123 @@ BANK4 pop_cdraw 4 625 5 905 +1 280 (сюда переехала отрис
|
||||
|
||||
|
||||
<a id="clip-1"></a>
|
||||
### <a id="mem-bank2"></a>MEM-BANK2. Разгрузка банка 2 — **ЗАКРЫТА 2026-08-08**
|
||||
|
||||
Банк 2 (`pop_bg.c`) упирался в потолок: 90.8 % ещё до чомперов. Разбор по
|
||||
символам показал, что он держит ДВЕ разные вещи — горячий fore-проход (каждый
|
||||
кадр) и холодную отрисовку тайлов (вход в комнату, точечные перерисовки), —
|
||||
а общие «листья» (`blit_b`, `tile_code`, `tile_table`, `wall_pattern`) нужны
|
||||
обеим.
|
||||
|
||||
**Ключевое ограничение платформы** (записано в memory
|
||||
`sdcc_banked_call_rules`): писучие данные банка лежат в `_DATA`/W2 и видны
|
||||
всем, а `const`-таблицы — в СТРАНИЦЕ банка, и из другого банка их не
|
||||
прочитать вовсе. Плюс трамплин выбирается ОБЪЯВЛЕНИЕМ: пометить лист
|
||||
`__banked` — значит заставить платить и горячих вызывающих (654 такта на
|
||||
круг).
|
||||
|
||||
**Шаг 1 — общие листья в РЕЗИДЕНТ** (`pop_tile.c` + внутренний `pop_tile.h`).
|
||||
W1 замаплен всегда, поэтому и горячая половина, и будущая холодная зовут их
|
||||
прямым `call` и читают таблицы напрямую — без дублей и без трамплинов.
|
||||
Уехали: `blit_b`, `env_b/wall_b/fore_b/pot_b`, `tile_code/tile_mod/
|
||||
tile_code_drawn/wall_modifier`, `heal_off`, `get_loose_frame`,
|
||||
`potion_flask`, `pop_fore_set_clip`, `pop_room_set_below/above` + таблицы
|
||||
`tile_table`, `COL_XH`, `WALL_FRAM_*`, `SPIKES_FRAM_LEFT`,
|
||||
`LOOSE_FRAM_LEFT/BOTTOM`. Заодно три функции перестали быть `__banked` —
|
||||
минус трамплин на кадр.
|
||||
|
||||
**Шаг 2 — дедуп внутри банка.** `wall_pattern` (808 → 394) и `wall_rnd`
|
||||
(786 → 654): четыре ветки по виду стены (SWS/SWW/WWS/WWW) отличались ТОЛЬКО
|
||||
набором кусков и числами в одной и той же серии `prandom` — сведены к
|
||||
таблицам `WP_PARTS` и `WR_RULE`. Порядок вызовов `prandom` сохранён
|
||||
дословно (иначе разъедется раскладка кладки).
|
||||
|
||||
**Грабля, пойманная замером:** после выноса `tile_table` из `static const` в
|
||||
глобальную SDCC перестала сворачивать `tile_table[10].fore_x/fore_y` в
|
||||
константы и стала читать их в рантайме — `potion_flask` раздулся 115 → 265 Б.
|
||||
Лечится макросами, которыми инициализируется та же запись таблицы (одно место
|
||||
правки, дублирования данных нет): 265 → 230.
|
||||
|
||||
**Замер (ALLOCS=3000):**
|
||||
|
||||
```
|
||||
было после ш.1 после ш.2
|
||||
BANK2 14 815 12 460 11 942 (90.4 % -> 72.9 %, свободно 4442 Б)
|
||||
_CODE 20 064 22 591 22 556 (куча 6793 -> 4301 Б)
|
||||
```
|
||||
|
||||
С релизным `ALLOCS=100000` банк 2 будет ещё примерно на 500-600 Б меньше
|
||||
(замер до разгрузки: 14 815 -> 14 176).
|
||||
|
||||
**Проверено:** `tests-host` зелёные; в MAME комната 1 уровня 1 после дедупа
|
||||
совпала с дорефакторным снимком **попиксельно (0 различий из 227 520)**,
|
||||
комната 3 (сплошная кладка, все четыре вида стены и марки) — та же раскладка
|
||||
кирпича.
|
||||
|
||||
**Шаг 3 — ХОЛОДНАЯ половина в банк 7** (`pop_room.c` + внутренний
|
||||
`_pop_bg.h`). Граница проведена по частоте вызова, а не по размеру:
|
||||
|
||||
```
|
||||
pop_bg.c (банк 2) ГОРЯЧЕЕ fore-проход, оверлеи, кладка, клип каждый кадр
|
||||
pop_room.c (банк 7) ХОЛОДНОЕ draw_tile, точечные перерисовки, mob, раз на комнату
|
||||
загрузка атласов / на событие
|
||||
```
|
||||
|
||||
Обратных зависимостей нет вовсе: холодная половина зовёт горячую ровно в
|
||||
трёх местах (`wall_pattern`, `wall_pattern_reset`, `draw_gate_back`) — и
|
||||
через ТОНКИЕ `__banked`-обёртки, а не пометкой самих тел. Тела остаются
|
||||
непомеченными, поэтому fore-проход, который зовёт `wall_pattern` до девяти
|
||||
раз за кадр, платит ноль. Общее состояние (`pop_loose_modif`,
|
||||
`pop_ceil_modif`, `obj_row/obj_col`) — писучее, лежит в `_DATA`/W2 и видно
|
||||
обеим половинам; `obj_row/obj_col` для этого перестали быть `static`.
|
||||
|
||||
**Цена трамплинов:** полная отрисовка комнаты — ~40 вызовов через границу
|
||||
(по два `wall_pattern` на стенной тайл), 26 000 тактов = 0.06 кадра РАЗОВО
|
||||
на вход в комнату. Анимация пик/ворот — 2-4 вызова на кадр, ~1 %. Ровно
|
||||
тот порядок, который был признан приемлемым при постановке задачи.
|
||||
|
||||
Заодно удалена мёртвая `potion_bubble` (169 Б): её работу давно делают
|
||||
`pop_potion_flask` (резидент) и `pop_potion_draw`, вызывающих не осталось.
|
||||
|
||||
**ГРАБЛЯ, стоившая прогона: `n_banks` объявляет САМО ПРИЛОЖЕНИЕ**
|
||||
(`roomtest.c`), а не `sprinter-cc`. Восьмой банк без правки этой константы
|
||||
собирается и линкуется без единого предупреждения, `_bank_pages[7]`
|
||||
остаётся 0xFF, и трамплин уводит в мусор: exe грузится, но программа встаёт
|
||||
намертво ещё до первого кадра — на экране остаётся приглашение DSS.
|
||||
Диагноз снят дампом `_bank_pages` из MAME (`FF EC ED EE EF F0 F1 FF` —
|
||||
семь страниц вместо восьми), а не гаданием. Предупреждение об этом в
|
||||
шапке `roomtest.c` было — и всё равно не сработало, потому что число банков
|
||||
живёт в двух местах.
|
||||
|
||||
**Замер (ALLOCS=3000):**
|
||||
|
||||
```
|
||||
было ш.1 ш.2 ш.3
|
||||
BANK2 14 815 12 460 11 942 5 872 (90.4 % -> 35.8 %)
|
||||
BANK7 — — — 6 035 (36.8 %)
|
||||
_CODE 20 064 22 591 22 556 22 556 (куча 4301 Б — не тронута)
|
||||
```
|
||||
|
||||
**Проверено (шаг 3):**
|
||||
- `tests-host` зелёные;
|
||||
- построчная сверка `pop_bg.c` + `pop_room.c` против дорефакторного
|
||||
`pop_bg.c`: НИ ОДНОЙ строки логики не пропало и не изменилось —
|
||||
расхождения только шапки, включения, три обёртки и удалённый мёртвый код;
|
||||
- в MAME **8 комнат** (стартовая + 7 по `ROOMNAV`) сняты до и после и сверены
|
||||
попиксельно по активному экрану 320×256: различия ТОЛЬКО в фазе анимации
|
||||
(пламя факелов, кадр Кида), статическая кладка совпадает пиксель в пиксель;
|
||||
- живой прогон: переход между комнатами, бой со стражем, решётка ворот,
|
||||
окклюзия Кида ближней колонной — как на дорефакторном билде (сверено
|
||||
контрольным запуском HEAD-бинаря с тем же вводом).
|
||||
|
||||
**Что осталось в запасе, если места снова не хватит** (не делаем, пока нет
|
||||
причины): вынести из РЕЗИДЕНТА холодные части — инициализацию в `main` +
|
||||
`enter_room_side`/`pop_start_level` (~1.7 КБ), загрузчик атласов Кида
|
||||
(~1.2 КБ), `pop_room_load`/`pop_level_load` (~1.4 КБ). Итого ~4-4.5 КБ
|
||||
резидента, то есть куча 4301 -> ~8.6 КБ. Целиком `pop_level.c` в банк
|
||||
нельзя: его `pop_level_tile` зовётся из банка на КАЖДЫЙ тайл — только
|
||||
расщепление модуля.
|
||||
|
||||
### CLIP-1. Аудит блитов: где клип не нужен — **СДЕЛАНО 2026-08-01**
|
||||
|
||||
> **Итог.** Heal Кида и стража переведены на выбор ядра по тому же тесту,
|
||||
|
||||
Reference in New Issue
Block a user