Симптом: через несколько комнат живого прохода перезагружался DSS.
pop_trob_modif() возвращает указатель на room_modif[24][30], а зовут её из
банков 2, 3, 7 и резидента. После переноса массив лежит по 0xC000+ в
странице банка 6, но разыменовывает указатель ЧУЖОЙ код — когда замаплена
его собственная страница. Значит чтение и запись идут поверх кода соседнего
банка.
Анализ Def/Ref такое не ловит: снаружи нет ссылки на символ, есть ссылка на
функцию, которая отдаёт его адрес. Условий для кандидата два, и второе
проверяется только чтением кода — ни один указатель на статику не должен
уходить наружу.
pop_room оба условия проходит (_mobs не читает никто; bake_copy статическая;
atlas_load(&pop_env[i]) берёт адрес глобала из резидентного pop_tile.c).
Остаётся −1620 Б: данные в W2 6774 -> 5157, свободно 129 -> 1746 Б.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
sprinter-cc: новый повторяемый --bank-data=SRC — писучие данные ОДНОГО
банкового модуля в его же страницу. Прежний --bank-data был всё-или-ничего
и потому неприменим: у большинства банковых модулей часть глобалов читают
соседние банки и резидент (hitp_*, pop_upside, pop_loose_modif, pop_cd), и
такие данные обязаны остаться замапленными всегда.
Кандидаты отобраны по объектным файлам, а не на глаз: символ должен быть
Def только в своём .rel и нигде не Ref. Прошли ровно двое — pop_room
(_mobs не читает никто) и pop_trob (экспортируемых данных нет вовсе).
При любом --bank-data sprinter-cc сам добавляет mkexe -p 0: crt0 зануляет
только резидентный _DATA, а mkexe по умолчанию бьёт пустоты 0xFF — иначе
вся банковая статика поднялась бы мусором.
Итог: данные в W2 6774 -> 4228, свободно до стека 129 -> 2675 Б.
BANK7 87 %, BANK6 31 %. Проверено в MAME: уровень 1, комнаты 1-2, фон,
факелы, решётки, проваливающиеся полы, переход между комнатами.
Метод замера и оставшиеся кандидаты — docs/resident_budget.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>