From e4e9836f2980f7b3c5448fe840a8b71df2ab8460 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Mon, 17 Aug 2026 17:47:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=BB=D0=B8=D0=BF=D1=88=D0=B8?= =?UTF-8?q?=D0=B9=20=D0=B1=D0=BB=D0=B5=D1=81=D0=BA=20=D0=BC=D0=B5=D1=87?= =?UTF-8?q?=D0=B0:=20trob=5Fdrawn=20=D0=BE=D0=B1=D0=BD=D1=83=D0=BB=D1=8F?= =?UTF-8?q?=D0=BB=D1=81=D1=8F,=20=D0=B0=20=D0=BA=D0=BE=D0=BC=D0=BD=D0=B0?= =?UTF-8?q?=D1=82=D0=B0=20=D1=80=D0=B8=D1=81=D0=BE=D0=B2=D0=B0=D0=BB=D0=B0?= =?UTF-8?q?=D1=81=D1=8C=20=D0=BF=D0=BE=20=D0=B6=D0=B8=D0=B2=D0=BE=D0=BC?= =?UTF-8?q?=D1=83=20modif?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Найдено пользователем (2026-08-17, уровень 1 комната 15): при входе в комнату блеск меча иногда горит несколько секунд вместо одиночной вспышки. Повторить не удавалось. Порядок в enter_room: 1) pop_trob_room_changed() обнуляет trob_drawn[] для ВСЕХ тайлов = «нарисовано без блеска»; 2) pop_trob_anim_room() задаёт мечу СЛУЧАЙНУЮ фазу счётчика 0..31 (start_anim_sword, seg007:087C); 3) pop_room_draw() рисует комнату по ЖИВОМУ modif. Если случайная фаза попала ровно на 1, комната рисуется С БЛЕСКОМ (draw_tile берёт кадр (modif==1)+10), а trob_drawn говорит «блеска нет». На следующем кадре animate_sword уводит счётчик с 1, признак снова 0 — и СОВПАДАЕТ со стоячим trob_drawn, поэтому перерисовка не помечается. Блеск остаётся запечённым в фон. Оба наблюдённых числа сходятся: вероятность ровно 1/32 на вход в комнату — отсюда «редко»; длительность animate_sword считает ВНИЗ и на нуле берёт новый период 0x28..0x67, то есть до 103 логических кадров ~ 6 секунд. Фикс: trob_drawn для меча инициализируется тем, что реально нарисует комната (mod == 1), а не нулём. Одно присваивание на вход в комнату — в кадре ноль. ПОДТВЕРЖДЕНО АРТЕФАКТОМ, а не рассуждением: временная сборка с подменой фазы на mod[i] = 1 давала баг на КАЖДОМ входе в комнату 15 (пользователь подтвердил), с фиксом — ни на одном. Временный форсаж снят. У КНОПКИ той же дыры нет, хотя механизм общий (оба используют trob_drawn): её признак — ДЛИТЕЛЬНОЕ состояние (нажата/нет), рассогласование само исправляется на первой же смене. У блеска признак — одиночная вспышка в ОДНОМ кадре из 40..103, и пропущенная смена стоит целого периода. Записано в комментарии, чтобы их не «унифицировали» обратно. 8 наборов tests-host зелёные. Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/pop_trob.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/applications/PoP/roomtest/pop_trob.c b/applications/PoP/roomtest/pop_trob.c index 2a322e0..0986d59 100644 --- a/applications/PoP/roomtest/pop_trob.c +++ b/applications/PoP/roomtest/pop_trob.c @@ -177,6 +177,27 @@ void pop_trob_anim_room(uint8_t room) __banked } else if (code == TILE_SWORD) { /* start_anim_sword (seg007:087C): случайная фаза счётчика блеска. */ mod[i] = (uint8_t)(trob_prandom(0xFF) & 0x1F); + /* trob_drawn обязан описывать то, что НАРИСУЕТ полная отрисовка + * комнаты, а она идёт ПОСЛЕ этой функции и берёт ЖИВОЙ modif. + * Обнулять его (как делает pop_trob_room_changed для всех тайлов) + * тут нельзя: если случайная фаза попала ровно на 1, комната + * рисуется С БЛЕСКОМ, а trob_drawn говорит «блеска нет» — и на + * следующем кадре счётчик уходит с 1, sig снова 0, СОВПАДАЕТ со + * стоячим trob_drawn, и перерисовка НЕ помечается. Блеск остаётся + * запечённым в фон до конца периода: animate_sword считает вниз и + * выдаёт новый период 0x28..0x67, то есть до 103 логических кадров + * ≈ 6 секунд. Вероятность ровно 1/32 на вход в комнату — отсюда + * «редко воспроизводится» (найдено пользователем 2026-08-17, + * уровень 1 комната 15). Проверено ПРИНУДИТЕЛЬНО: со временной + * подменой фазы на mod[i] = 1 баг ловится на КАЖДОМ входе в + * комнату, а с этой строкой не ловится ни на одном. + * + * У КНОПКИ той же дыры нет, хотя механизм общий: её признак — + * ДЛИТЕЛЬНОЕ состояние (нажата/нет), и рассогласование само + * исправляется на первой же смене. У блеска признак — одиночная + * вспышка в ОДНОМ кадре из 40..103, и пропущенная смена стоит + * целого периода. */ + trob_drawn[i] = (uint8_t)(mod[i] == 1); pop_add_trob(room, i, 1); } }