MEM-BANK5: pop_ctrl.c → банк 5; чит [/] подгонки Кида по X
Три правки едут вместе намеренно: n_banks и --bank обязаны меняться атомарно, иначе промежуточный коммит — зависание (см. ниже). MEM-BANK5. CODE и DATA делят одно 32-КБ пространство W1+W2, поэтому килобайт кода, уехавший в банк, — это килобайт, доступный данным. Кандидат выбран не по размеру, а по частоте вызова: диспетчер управления дёргается раз в кадр на персонажа и горячих банк→банк переходов не создаёт (в отличие от pop_level, чей pop_level_tile зовётся из банка 2 на КАЖДЫЙ тайл). _CODE 26 780 -> 24 662 Б (−2 118) куча 180 -> 2 298 Б банк 5 2 211 / 16 384 (13.5 %) Шина control_* (8 глобалов) переехала в pop_state.c. Сегодня она уцелела бы и в pop_ctrl.c — банки собираются без --bank-data, их писучие данные остаются в общем _DATA, — но это флаг сборки, а не свойство кода, а шину трогают уже три банка: 5 пишет с клавиатуры, 1 подаёт синтетический ввод ИИ (autocontrol_*, seg002), 3 читает через pop_ctrl_shift_held. Заодно pop_ctrl.c наконец включает собственный заголовок — раньше объявления жили прямо в нём. ГРАБЛИ, на которые наступили (стоили дольше самой задачи): n_banks в roomtest.c захардкожен, и его надо править вместе с числом --bank. С n_banks=4 и пятым банком crt0 выделил четыре страницы, _bank_pages[5] остался нулём, и первый же вызов pop_ctrl_init() через трамплин отобразил в W3 страницу 0 и прыгнул на 0xC874 в мусор — исполнение забрело в дисковый код DSS и осталось крутить чтение секторов. Симптом: загрузка ресурсов проходит целиком (open=45 — все атласы), комната и Кид успевают нарисоваться из enter_room, а HP и номер комнаты уже нет, и kid_tick не вызывается ни разу. Ровно предупреждение из шапки runtime/bank.s. Сверку n_banks с реальным максимальным индексом банка записал в docs/TODO.md (Auto-banking) — это должно быть ошибкой сборки. DBG-CHEATS: [ (0x54) и ] (0x5B) двигают Кида на пиксель (seg000:1828), по фронту нажатия, под pop_cheats. Нужны потому, что мост MAME теряет нажатия при быстрой отправке и подогнать Кида в позу скриптом нельзя — на это упёрлись BUG-LOOSE-2 и BUG-GATE-PASS-1. ROOMNAV больше не зовёт pop_trob_reset: reset обнуляет room_seen, то есть чит ОТМАТЫВАЛ МИР (открытые/закрытые ворота, нажатые кнопки). Навигация обязана только телепортировать. Проверено в MAME: старт уровня 1 рисуется полностью (комната, Кид, HP, номер), бег вправо и падение на второй ряд отрабатывают, ] даёт x+1 и [ даёт x−1 по одному нажатию, Shift+→ — осторожный шаг (x 131 -> 142, колонка 4 -> 5) и при удержании 90 кадров не срывается в бег (x 142 -> 151), то есть pop_ctrl_shift_held работает через границу банк 3 -> банк 5. Наборы под ucsim: geom 39, grab 53, phys 1723 — все зелёные. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -61,6 +61,35 @@
|
||||
|
||||
## Auto-banking (memory/banking_roadmap.md)
|
||||
|
||||
- [ ] **Сверять `n_banks` с реальным числом банков — ошибкой сборки.**
|
||||
Сейчас число банков задаётся ДВАЖДЫ и вручную: флагами `--bank N=…`
|
||||
у `sprinter-cc` и константой `const uint8_t n_banks = N;` в
|
||||
приложении (её читает `crt0_banked` при старте, чтобы выделить
|
||||
EMM-страницы и загрузить в них образы банков). Рассогласование не
|
||||
даёт ни ошибки компиляции, ни ошибки линковки — только зависание в
|
||||
рантайме: `_bank_pages[N]` остаётся нулём, трамплин отображает в
|
||||
окно страницу 0 и прыгает по 0xC000 в мусор (предупреждение об этом
|
||||
уже есть в шапке `runtime/bank.s`).
|
||||
**Найдено 2026-08-05** на PoP/roomtest: добавили пятый банк
|
||||
(`--bank 5=pop_ctrl.c`), забыли `n_banks` — игра доходила до конца
|
||||
загрузки ресурсов и вставала намертво в дисковом коде DSS. Диагноз
|
||||
занял заметно больше, чем сама правка: симптом (зависание в чужом
|
||||
коде) никак не указывает на причину.
|
||||
Сверять надо не количество, а **максимальный индекс** банка: `--bank`
|
||||
нумеруются с 1 и в принципе могут идти с дырами, а `crt0_banked`
|
||||
заполняет `_bank_pages[1..n_banks]` подряд.
|
||||
Варианты, от простого к правильному:
|
||||
1. **Проверка после линковки** — вытащить значение `_n_banks` из
|
||||
`.ihx`/`.map` (это `const` в `_CODE`, адрес известен из карты) и
|
||||
сравнить с `max(N)` по флагам; не совпало — `sprinter-cc` падает
|
||||
с внятным сообщением. Ничего не ломает в существующих
|
||||
приложениях, ставится сразу.
|
||||
2. **Генерировать самим `sprinter-cc`** — он уже так делает, когда
|
||||
банков нет (`const unsigned char n_banks = 0;`). Правильнее по
|
||||
сути (единственный источник истины), но требует убрать константу
|
||||
из всех банковых приложений, иначе дубль символа: `tests/banked`,
|
||||
`banktest`, `banklocl`, `bankedbg`, `applications/PoP/roomtest`.
|
||||
|
||||
Phase 1 — file-level bin-packing (`toolchain/auto_bank.py`) — когда
|
||||
проект перерастёт ~30 KB кода: парсинг размеров из .rel/.map,
|
||||
first-fit-decreasing, уважение `#pragma codeseg BANKn`, перелинковка,
|
||||
|
||||
Reference in New Issue
Block a user