From 05bcd8197e9a1db473d3fd455fa8ec078ffc03cb Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Thu, 3 Sep 2026 11:04:27 +0300 Subject: [PATCH] =?UTF-8?q?check=5Fbank=5Fcalls:=20=D0=BB=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20=D0=B0=D0=B4=D1=80=D0=B5=D1=81=20=D0=9F?= =?UTF-8?q?=D0=9E=D0=9B=D0=AF=20=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=82=D1=83?= =?UTF-8?q?=D1=80=D1=8B=20=D0=B2=20=D0=B0=D1=80=D0=B3=D1=83=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B0=D1=85=20=D0=B1=D0=B0=D0=BD=D0=BA=D0=BE=D0=B2?= =?UTF-8?q?=D0=BE=D0=B3=D0=BE=20=D0=B2=D1=8B=D0=B7=D0=BE=D0=B2=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Проверка 2 искала форму «адрес метки своего банка положен в аргументы вызова в чужой банк», но регулярка принимала только `ld hl,#_метка` и `#_метка+6`. Адрес поля структуры SDCC пишет в скобках: ld bc, #(_mstream + 6) push bc ... call ___sdcc_bcall_ehl Из-за этого целый класс ошибок собирался «чисто». Поймано вживую 2026-09-03 в порту Loom: mask.c (банк 5, --bank-data 5) отдавал res_copy (банк 11) адрес поля своей структуры — поток маски читался в чужую страницу, маска выходила «всё заполнено», тайлов в комнате стало 30 вместо 17. Фон при этом оставался побайтово верным, потому что его путь идёт из резидентного кода, так что попиксельная сверка экрана молчала. Класс проверки не меняется: адрес метки ДАННЫХ своего банка, положенный в стек как аргумент вызова в ЧУЖОЙ банк, неверен всегда — это по-прежнему доказательный случай, а не эвристика. Проверено в трёх режимах: с ошибкой срабатывает, на исправленном коде молчит, и на всех банковых сборках самого тулчейна (banktest, w3probe, banked, bankedbg, banklocl, w3bankgfx, roomtest, сборка SprPoP) ложных срабатываний нет. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Qxu9rwsmyDyYPxG198nzSR --- toolchain/check_bank_calls.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/toolchain/check_bank_calls.py b/toolchain/check_bank_calls.py index cd296a2..006b7dd 100755 --- a/toolchain/check_bank_calls.py +++ b/toolchain/check_bank_calls.py @@ -72,9 +72,15 @@ BANK_ASM_RE = re.compile(r'^bank(\d+)_') IGNORE = {'___sdcc_bcall_ehl', '___sdcc_bcall'} # `ld hl,#_метка` / `ld de,#___str_3` — материализация адреса. +# +# Скобочную форму принимаем обязательно: адрес ПОЛЯ структуры SDCC пишет как +# `ld bc, #(_mstream + 6)`, и без неё проверка молча пропускала целый класс. +# Поймано вживую 2026-09-03 в порту Loom: `mask.c` (банк 5, --bank-data 5) +# отдавал `res_copy` (банк 11) адрес поля своей структуры — маска читалась как +# «всё заполнено», а сборка при этом была «чистой». LOADADDR_RE = re.compile( - r'^\s*ld\s+(hl|de|bc|iy|ix)\s*,\s*#(_{1,3}[A-Za-z_0-9]+)' - r'(?:\s*[+-]\s*\w+)?\s*(?:;.*)?$', re.IGNORECASE) + r'^\s*ld\s+(hl|de|bc|iy|ix)\s*,\s*#\(?\s*(_{1,3}[A-Za-z_0-9]+)' + r'(?:\s*[+-]\s*[\w()+\- ]+?)?\s*\)?\s*(?:;.*)?$', re.IGNORECASE) PUSH_RE = re.compile(r'^\s*push\s+(hl|de|bc|iy|ix)\s*(?:;.*)?$', re.IGNORECASE) # `ld e,#b_foo` перед трамплином называет банк цели.