Откат оптимизации резидента: перенос данных банка в его страницу ломает картинку

Возврат к состоянию после звуковых правок (c6828c0).  Отменяются 3545826 и
9025573 целиком: --bank-data=SRC в sprinter-cc, его включение в PoP и
docs/resident_budget.md.

Что выяснено и почему откат, а не доводка.  Перенос писучих данных
банкового модуля в его 16-КБ страницу даёт цветной мусор блоками и уводит
DSS.  У pop_trob причина найдена: pop_trob_modif() возвращает указатель на
room_modif[24][30], и его разыменовывают банки 2/3/7 и резидент — то есть
пишут по 0xC000+ в СВОЮ страницу, поверх чужого кода.  Def/Ref-анализ такое
не ловит: снаружи ссылки на символ нет, есть ссылка на функцию, отдающую
его адрес.

Но и один pop_room, у которого явной утечки указателя найти не удалось,
ломается так же — значит механизм понят не до конца.  Пока не понят,
включать нельзя.  Нулевая инициализация при этом ни при чём: mkexe -p 0
проверен по образу (прогон нулей 14304 Б, самый длинный прогон 0xFF — 14).

Место в резиденте искать другими путями: malloc (287 Б, требует раздельных
cbl_open для APP и SILENCE) и код pop_tile (5972 Б).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 21:26:23 +03:00
parent 90255737c2
commit 63e426cc0d
3 changed files with 3 additions and 155 deletions
+2 -27
View File
@@ -54,10 +54,6 @@
# no writable data belongs in W3 (code + rodata only). From a
# __banked context the resident W3 code is unreachable (but
# resident -> __banked via the W1 trampoline is fine).
# --bank-data=SRC писучие данные ТОЛЬКО этого банкового модуля — в его
# страницу (repeatable). Безопасно лишь если ни один
# другой модуль не ссылается на его глобалы: проверяется
# по .rel (Def/Ref). Включает mkexe -p 0 (zero-init).
# --mkexe FLAG extra mkexe flag (repeatable; e.g. --mkexe -p --mkexe 0)
# --max-allocs N SDCC --max-allocs-per-node (default: 100000 — smaller/
# faster code at the cost of compile time; pass a lower
@@ -115,8 +111,7 @@ MKEXE_EXTRA=()
BANK_SPECS=() # entries like "1=engine.c"
W3_SPECS=() # entries like "mod.c" — резидентные модули окна W3 (--w3)
USER_DEFS=() # -DFOO / -DFOO=bar — пробрасываются в sdcc как есть
BANK_LOCAL_DATA=0 # 1 (--bank-data): писучие данные ВСЕХ банков — в страницу банка
BANK_DATA_SRCS=() # --bank-data=src.c: только эти модули (выборочно)
BANK_LOCAL_DATA=0 # 1 (--bank-data): писучие данные банков — В СТРАНИЦУ банка
W3_RELS=() # заполняется при компиляции W3-модулей
W3_LD_FLAGS=() # -Wl-b_W3CODE=0xC000, если есть --w3
USER_SET_MEMORY="" # непусто, если --memory задан явно (для --w3 авто-small)
@@ -153,7 +148,6 @@ while [[ $# -gt 0 ]]; do
-D*) USER_DEFS+=("$1"); shift;;
--bank) BANK_SPECS+=("$2"); shift 2;;
--bank-data) BANK_LOCAL_DATA=1; shift;;
--bank-data=*) BANK_DATA_SRCS+=("${1#*=}"); shift;;
--mkexe) MKEXE_EXTRA+=("$2"); shift 2;;
--max-allocs) MAX_ALLOCS="$2"; shift 2;;
--gfx) GFX_MODE="$2"; shift 2;;
@@ -442,17 +436,8 @@ if [[ "$CRT0_TYPE" == "banked" ]]; then
# глобал банкового модуля лёг по 0x0001C000): это экономит
# W1/W2, но требует ручного контроля видимости, поэтому
# включается явно через --bank-data.
# Выборочный режим (--bank-data=src.c) точнее глобального: у
# большинства банковых модулей часть глобалов ЧИТАЮТ соседние
# банки и резидент, и такие данные обязаны остаться в W2.
# Проверять это надо по объектным файлам (кто Def, кто Ref), а
# не на глаз.
bank_data_flags=()
bank_data_want=$BANK_LOCAL_DATA
for bd in "${BANK_DATA_SRCS[@]}"; do
[[ "$(basename "$bd")" == "$(basename "$bank_src")" ]] && bank_data_want=1
done
[[ $bank_data_want -eq 1 ]] && bank_data_flags=(--dataseg "BANK${bank_n}")
[[ $BANK_LOCAL_DATA -eq 1 ]] && bank_data_flags=(--dataseg "BANK${bank_n}")
run "$SDCC" "${CC_FLAGS[@]}" \
--codeseg "BANK${bank_n}" --constseg "BANK${bank_n}" \
"${bank_data_flags[@]}" \
@@ -509,16 +494,6 @@ MK_PREFIX=()
[[ $VERBOSE -eq 1 ]] && MK_PREFIX+=(-v)
[[ $BANK_W1 -eq 1 ]] && MK_PREFIX+=(-B 0x4000)
[[ $W3_RESIDENT_HUGE -eq 1 ]] && MK_PREFIX+=(-W)
# Данные банка в его же странице обязаны стартовать НУЛЯМИ: crt0 зануляет
# только резидентный _DATA, до банковых страниц он не дотягивается. Даром
# это даёт паддинг образа нулём вместо дефолтного 0xFF — иначе вся банковая
# статика поднимется с 0xFF, а по правилам проекта её никто не инициализирует
# явно (crt0 зануляет _DATA, см. memory/sdcc_static_storage_gotcha).
if [[ $BANK_LOCAL_DATA -eq 1 || ${#BANK_DATA_SRCS[@]} -gt 0 ]]; then
mk_has_pad=0
for f in "${MKEXE_EXTRA[@]}"; do [[ "$f" == "-p" ]] && mk_has_pad=1; done
[[ $mk_has_pad -eq 0 ]] && MK_PREFIX+=(-p 0)
fi
MK_PREFIX+=("${MKEXE_EXTRA[@]}")
MK_PREFIX+=(-L "$LOAD_ADDR" -E "$ENTRY_ADDR" -S "$STACK_ADDR" -o "$OUT")
run "$MKEXE" "${MK_PREFIX[@]}" "$IHX"