From 89b603ae048da206c6f4849bd05b4a487a7d0ef6 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Mon, 17 Aug 2026 23:27:22 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=B2=D0=BE=D1=80=D1=86=D0=BE=D0=B2?= =?UTF-8?q?=D1=8B=D0=B9=20=D0=BF=D0=BE=D1=80=D1=82=D0=B0=D0=BB:=20=D0=9A?= =?UTF-8?q?=D0=B8=D0=B4=20=D1=81=D0=BA=D1=80=D1=8B=D0=B2=D0=B0=D0=BB=D1=81?= =?UTF-8?q?=D1=8F=20=D0=B7=D0=B0=20=D0=BA=D1=80=D0=BE=D0=BC=D0=BA=D0=BE?= =?UTF-8?q?=D0=B9=20=D1=80=D0=B0=D0=BD=D1=8C=D1=88=D0=B5=20=D0=B2=D1=80?= =?UTF-8?q?=D0=B5=D0=BC=D0=B5=D0=BD=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Уровень 4: в анимации ухода на следующий уровень контур Кида обрезался не правой гранью портала, а раньше — брался клип подземного проёма, а дворцовый шире. draw_leveldoor считал кромку как xh*8 + 48, без дворцовой поправки. В оригинале строкой ниже стоит (seg008:1429): if (custom->tbl_level_type[current_level]) leveldoor_right += 8; Значение читает clip_char как правую границу клипа персонажа — отсюда ранняя обрезка. Расхождение было осознанным и отложенным: в коде стоял комментарий «+8 у palace-уровней — на уровне 1 не применяется», дворцовых уровней тогда в порту не было. tbl_level_type[4] = 1, там и проявилось. pop_palace выставляет pop_bg_load из того же tbl_level_type, что читает оригинал, так что эквивалент дословный. Попутно найдено и НЕ починено (заведено отдельным багом LEVELDOOR-STARTROOM-WIPE): в той же функции оригинал в СТАРТОВОЙ комнате кладёт затирающий прямоугольник вместо лестницы, со своей дворцовой/ подземной разницей 48/39 и сдвигом 2 px, а мы рисуем марш 144 безусловно. Видно только при приподнятой створке входной двери, поэтому на обходах уровней 1-4 не попалось. Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/BUGS_CLOSED.md | 45 +++++++++++++++++++++ applications/PoP/roomtest/BUGS_OPEN.md | 51 ++++++++++++++++++++++++ applications/PoP/roomtest/pop_room.c | 12 +++++- 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/applications/PoP/roomtest/BUGS_CLOSED.md b/applications/PoP/roomtest/BUGS_CLOSED.md index 4f6e23c..f0748a4 100644 --- a/applications/PoP/roomtest/BUGS_CLOSED.md +++ b/applications/PoP/roomtest/BUGS_CLOSED.md @@ -2740,3 +2740,48 @@ if (Char.sword != SWORD_2_DRAWN) { `Kid`: `ldir` копирует байт кадра (0) раньше байта меча (12), поэтому по `Kid` ловушка слепа ровно в тот тик, когда меч теряется, и ложно срабатывает на каждом законном доставании. + +--- + + +## LEVELDOOR-PALACE-CLIP. Кид скрывался за кромкой дворцового портала раньше времени — ЗАКРЫТ 2026-08-17 + +**Наблюдение (пользователь, уровень 4, обход после оптимизации фаз).** +Порталы, через которые Кид входит на уровень и уходит на следующий, в +подземелье и во дворце РАЗНОЙ ширины — дворцовый шире. В анимации ухода с +уровня 4 на 5-й Кид убегает по лестнице, и его контур обрезается не правой +гранью портала, а раньше, «как будто он прячется проходом». Диагноз +пользователя сразу верный: взята ширина подземного портала. + +**Корень.** `draw_leveldoor` (`pop_room.c`, порт seg008:1D29) считал правую +кромку проёма без дворцовой поправки: + +```c +pop_leveldoor_right = xh * 8 + 48; +``` + +В оригинале строкой ниже стоит (seg008:1429): + +```c +leveldoor_right = (draw_xh<<3)+48; +if (custom->tbl_level_type[current_level]) leveldoor_right += 8; +``` + +Это значение читает `clip_char` (у нас `pop_map.c:2668`) как правую границу +клипа персонажа — отсюда ранняя обрезка. + +Расхождение было **осознанным и отложенным**: в коде стоял комментарий +«+8 у palace-уровней (tbl_level_type) — на уровне 1 не применяется». На +момент написания дворцовых уровней в порту не было, и условие не дописали. +`tbl_level_type[4] = 1` (`pop_level_cold.c:52`), то есть уровень 4 — +дворцовый, и на нём это наконец проявилось. + +**Фикс.** `if (pop_palace) pop_leveldoor_right += 8;` Флаг `pop_palace` +выставляет `pop_bg_load(set)` из того же `tbl_level_type`, который читает +оригинал, так что эквивалент дословный и рассинхронизироваться не может. + +**Найдено попутно, НЕ починено:** +[LEVELDOOR-STARTROOM-WIPE](BUGS_OPEN.md#leveldoor-startroom-wipe) — в той же +функции оригинал в СТАРТОВОЙ комнате кладёт затирающий прямоугольник вместо +лестницы (и там своя дворцовая/подземная разница 48/39 и сдвиг 2 px), а мы +рисуем марш 144 безусловно. Заведено отдельным багом. diff --git a/applications/PoP/roomtest/BUGS_OPEN.md b/applications/PoP/roomtest/BUGS_OPEN.md index 6d92740..6f585bd 100644 --- a/applications/PoP/roomtest/BUGS_OPEN.md +++ b/applications/PoP/roomtest/BUGS_OPEN.md @@ -812,3 +812,54 @@ seg008:1572). Правка: позвать `on_guard_killed()` в ветке «не скелет». Мешает только то, что функция сейчас `static` в `guards.c` (банк 1), а `pop_guard_fallout` живёт в резиденте. + +--- + + +## LEVELDOOR-STARTROOM-WIPE. В стартовой комнате за входной дверью рисуется лестница вместо черноты + +**Найдено разбором 2026-08-17** (попутно к фиксу +[LEVELDOOR-PALACE-CLIP](BUGS_CLOSED.md#leveldoor-palace-clip) — то же +`draw_leveldoor`). + +`draw_leveldoor` (seg008:1D29) в приподнятой створке различает две комнаты: + +```c +if (modifier_left) { + if (level.start_room != drawn_room) { + add_backtable(..., 144 /*level door stairs*/, ...); + } else { + short leveldoor_width = (tbl_level_type[current_level] == 0) ? 39 : 48; + sbyte x_low = (tbl_level_type[current_level] == 0) ? 2 : 0; + add_wipetable(0, 8*(draw_xh + 1) + x_low, ybottom - 4, 45, leveldoor_width, 0); + } +} +``` + +Смысл: за дверью, **через которую вошли на уровень**, лестницы нет — там +чернота, и оригинал её ЗАТИРАЕТ прямоугольником, а не рисует марш 144. +Ширина затирки дворцовая/подземная (48 против 39) и подземная сдвинута на +2 px вправо — то есть здесь ЕЩЁ одно расхождение подземелья и дворца, помимо +уже починенного `leveldoor_right += 8`. + +У нас (`pop_room.c`, `draw_leveldoor`) стоит безусловно: + +```c +if (modif) + pop_env_b(144, x, ybottom - 4); /* лестница (комната ≠ стартовой) */ +``` + +— условие названо в комментарии, но не реализовано. Различие стартовой +комнаты у нас есть только в логике входа (`pop_leveldoor_enter`, +`pop_map.c:1166`), не в отрисовке. + +**Когда видно:** только пока створка входной двери приподнята +(`modif != 0`) в стартовой комнате — то есть в анимации входа на уровень и +если дверь снова открыть. При закрытой двери `modif == 0`, и обе ветки +ничего не рисуют, поэтому баг и не попался на обходах уровней 1-4. + +**Что мешает сделать прямо:** у нас нет понятия wipetable — нужен чёрный +прямоугольник в проходе backtable, то есть либо прямой `gfx`-fill в +`draw_leveldoor`, либо запечка. Проверять на уровне 1 (подземелье, ширина +39, сдвиг 2) И на уровне 4 (дворец, 48, сдвиг 0) — иначе поймаем только +половину. diff --git a/applications/PoP/roomtest/pop_room.c b/applications/PoP/roomtest/pop_room.c index e7c6325..ab5d5e8 100644 --- a/applications/PoP/roomtest/pop_room.c +++ b/applications/PoP/roomtest/pop_room.c @@ -337,9 +337,17 @@ static void draw_leveldoor(uint8_t modif, int xh, int dmy) int y = ybottom - (int)modif; /* leveldoor_right (seg008:1D29): правая кромка проёма — от xh ТЕКУЩЕГО * тайла, то есть ПРАВОЙ половины двери (сюда мы попадаем из - * draw_tile_anim_right, разбирая левого соседа). +8 у palace-уровней - * (tbl_level_type) — на уровне 1 не применяется. */ + * draw_tile_anim_right, разбирая левого соседа). + * + * +8 у дворцовых уровней — дословно seg008:1429 + * (`if (tbl_level_type[current_level]) leveldoor_right += 8;`): проём + * во дворце шире, чем в подземелье. Без этой строки Кид в анимации + * ухода на следующий уровень скрывался за кромкой РАНЬШЕ, чем нужно, + * потому что клип брался по ширине подземного проёма (найдено на + * уровне 4, обход 2026-08-17). pop_palace ставит pop_bg_load из того + * же tbl_level_type, что читает оригинал. */ pop_leveldoor_right = xh * 8 + 48; + if (pop_palace) pop_leveldoor_right += 8; pop_env_b(99, x, ybottom); if (modif) pop_env_b(144, x, ybottom - 4); /* лестница (комната ≠ стартовой) */