Откат bank-data для pop_trob: указатель на его статику уходил наружу

Симптом: через несколько комнат живого прохода перезагружался 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>
This commit is contained in:
2026-08-20 21:21:44 +03:00
parent 354582662c
commit 90255737c2
2 changed files with 46 additions and 13 deletions
+15 -8
View File
@@ -35,14 +35,21 @@ MEMORY ?= huge # small-раскладка + банки кода в W
# ВАЖНО: любое сравнение занятости банков имеет смысл только при ОДНОМ и том
# же ALLOCS — иначе сравниваются не правки, а уровни оптимизации.
ALLOCS ?= 3000
# Писучие данные ЭТИХ банковых модулей живут в их же странице, а не в
# резиденте W1/W2 — это 2549 Б, которые иначе съедала бы база. Список
# короткий не по лени: у остальных банковых модулей часть глобалов читают
# соседние банки и резидент (hitp_*, pop_upside, pop_loose_modif, pop_cd),
# и такие данные ОБЯЗАНЫ остаться замапленными всегда. Проверять новичка в
# списке — по объектным файлам: символ должен быть Def только в своём .rel и
# нигде не Ref (см. ../docs/resident_budget.md).
BANK_DATA := --bank-data=pop_room.c --bank-data=pop_trob.c
# Писучие данные ЭТОГО банкового модуля живут в его же странице, а не в
# резиденте W1/W2 (1620 Б базы). Список из одного файла — не лень, а
# результат проверки; ДВА условия, и второе стоило перезагрузки DSS:
#
# 1) ни один чужой модуль не ссылается на его глобалы (проверяется по
# .rel: символ Def только в своём объекте и нигде не Ref);
# 2) НИ ОДИН УКАЗАТЕЛЬ на его статику не уходит наружу. Def/Ref этого не
# видит. Так провалился pop_trob: pop_trob_modif() возвращает указатель
# на room_modif[24][30], и его разыменовывают банки 2/3/7 и резидент —
# то есть пишут по 0xC000+ в СВОЮ страницу, поверх чужого кода.
#
# У pop_room оба условия выполнены: _mobs не читает никто, bake_copy
# статическая, а atlas_load(&pop_env[i]) берёт адрес глобала из pop_tile.c
# (резидент), не своего. Подробности — ../docs/resident_budget.md.
BANK_DATA := --bank-data=pop_room.c
EXTRA_FLAGS ?= --gfx 256 -I $(CURDIR)/../poc/res/bg --max-allocs $(ALLOCS) --bank 2=pop_bg.c --bank 7=pop_room.c --bank 4=pop_cdraw.c --bank 4=pop_kdraw.c --bank 3=pop_map.c --bank 1=guards.c --bank 5=pop_ctrl.c --bank 6=pop_trob.c --bank 7=pop_redraw.c --bank 8=roomtest_cold.c --bank 8=pop_level_cold.c --bank 8=pop_kboot.c --bank 8=pop_guard_cold.c --bank 8=pop_shadow.c --bank 8=pop_sfx_cold.c $(BANK_DATA) $(PROF_FLAGS)
# Профилирование полосами бордюра (см. PROF() в roomtest.c) — ВКЛЮЧЕНО по