From a89b8b30c65520cb27137d764afdb351396f60f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9F=D0=B5=D1=82=D1=80=D0=BE=D0=B2?= Date: Mon, 3 Aug 2026 23:02:02 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20BUG-DRAWORDER-1=20=D0=B7=D0=B0=D0=BA?= =?UTF-8?q?=D1=80=D1=8B=D1=82;=20=D0=BE=D1=81=D1=82=D0=B0=D1=82=D0=BE?= =?UTF-8?q?=D0=BA=20=C2=AB=D0=BD=D0=BE=D0=B3=D0=B8=20=D0=BF=D0=BE=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=85=20=D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D1=8B=C2=BB?= =?UTF-8?q?=20=E2=80=94=20=D0=B2=20=D0=9D=D0=95=20=D0=91=D0=90=D0=93=D0=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Сверено в SDLPoP: Кид, стоящий колонкой правее лежащего трупа, и там рисуется поверх его головы. Значит порт верен, а артефакт врождённый: set_objtile_at_char приписывает персонажа РОВНО ОДНОМУ тайлу, ширина спрайта на выбор тайла не влияет, и всё, что стоит правее, перекрывает выступающую часть тела. Механизма «широкий объект в нескольких тайлах» в оригинале нет — сверено с draw_objtable_items_at_tile, sort_curr_objs и веткой tile_object_redraw == 0xFF (та про оверлеи пола). Закрытая запись перечисляет все четыре корня, которые пришлось снять по очереди: порядок по роли вместо тайла; своя регрессия с общим окном fore-клипа; колонка трупа из тайла вместо X; непортированная ветка actions_1_run_jump. Записано и то, как отличать остаток от этих багов, и цена «починки» остатка (тайл по центру габарита = отход от эталона). Co-Authored-By: Claude Opus 5 --- applications/PoP/roomtest/bug_closed.md | 79 +++++++++++++++++++++++++ applications/PoP/roomtest/bug_list.md | 42 ++----------- 2 files changed, 84 insertions(+), 37 deletions(-) diff --git a/applications/PoP/roomtest/bug_closed.md b/applications/PoP/roomtest/bug_closed.md index 7a798de..ac5da13 100644 --- a/applications/PoP/roomtest/bug_closed.md +++ b/applications/PoP/roomtest/bug_closed.md @@ -382,6 +382,29 @@ MAME по кромкам. которые БЫЛИ нашими багами и исправлены: вис/подтягивание на кромке плиты и падение вместе с плитой — там плита обязана быть поверх Кида. +- **Ноги стоящего Кида поверх головы лежащего трупа стража.** Комната 21: + страж убит, комната покинута и открыта заново (у трупа своя запомненная X), + Кид СТОИТ на одну колонку правее тела — его ноги рисуются поверх головы. + Проверено в SDLPoP (2026-08-03): там ровно то же. + + Корень — устройство движка, а не наш порт. `set_objtile_at_char` + (seg006:13F3) приписывает персонажа РОВНО ОДНОМУ тайлу, и ширина спрайта на + выбор тайла не влияет никак; дальше `redraw_needed_tiles` (seg008:1B06) + обходит тайлы рядами 2,1,0 и колонками 0..9, и кто позже — тот поверх. + Стоящий Кид укладывается примерно в колонку, поэтому у него это незаметно, а + лежащий труп занимает две-три колонки, но «принадлежит» левой. Всё, что + стоит правее, перекрывает выступающую часть тела. Механизма «широкий объект + участвует в нескольких тайлах» в оригинале нет — сверено с + `draw_objtable_items_at_tile`, `sort_curr_objs` и веткой + `tile_object_redraw == 0xFF` (последняя про оверлеи пола, не про персонажей). + + Отличать от того, что БЫЛО нашими багами в этом же месте и исправлено + (BUG-DRAWORDER-1): колонка трупа считалась из тайла вместо X, ветка + `actions_1_run_jump` не была портирована, окно fore-клипа затиралось стражем. + Если когда-нибудь захочется «починить» и это — минимальный вариант — брать + тайл по ЦЕНТРУ габарита, а не по левой границе; но это осознанный отход от + эталона, и в других позах порядок поменяется в обратную сторону. + - **Комнаты 13, 18, 24 недостижимы в обычной игре** — свойство ДАННЫХ уровня 1, не наш баг. Обход графа от стартовой комнаты (по `res2001.bin`, links @1952) показывает: у всех трёх ссылки наружу есть, а на них не ссылается никто @@ -623,3 +646,59 @@ dir_56_none`. То есть стражи — такая же часть дан **Проверено в MAME:** комната 21, страж жив (`alive = -1`, hp 3) → убит читом `K` (`alive = 0`, hp 0) → Кид убит стражем → респавн → возврат в комнату 21: страж снова `alive = -1`, hp 3. + + +## BUG-DRAWORDER-1. Кид рисовался поверх тела стража — **ЗАКРЫТ** + +**Симптом.** В оригинале Кид проходит ЗА телом убитого стража; у нас — перед ним. + +**Три разных корня, найденные по очереди.** Стоит того, чтобы перечислить: два +первых захода были неполны, и каждый следующий кадр от тестера вскрывал новый +слой. + +1. **Порядок задавался ролью, а не тайлом.** Мы безусловно рисовали + `pop_guard_draw()` → `kid_draw()`, то есть Кид был сверху всегда. В + оригинале никто не «поверх» по определению: оба персонажа попадают в midtable + при обработке СВОЕГО тайла (`set_objtile_at_char`, seg006:13F3), а тайлы + обходятся строго — `redraw_needed_tiles` (seg008:1B06) идёт рядами 2,1,0 и + внутри ряда колонками 0..9; кто позже, тот поверх. Совпали тайлы — решает + `sort_curr_objs` (seg008:203C): ниже по `obj_y` = позже. + Фикс: `guard_over_kid()` в `roomtest.c`. + +2. **Своя же регрессия: Кид полез поверх передних столбов.** Окно fore-клипа + (`pop_fore_set_clip`) одно на всех, и его ставит каждый, кто рисует + персонажа. Пока страж рисовался строго ДО Кида, к моменту + `pop_fore_over_kid` в окне оказывался Кид и всё сходилось само. Как только + порядок стал переменным, при «страж поверх» окно оставалось СТРАЖЬИМ, и + fore-проход Кида отсекался целиком. + Фикс: `kid_fore_clip_restore()` — окно восстанавливается явно, а не + «по счастливому порядку вызовов». + +3. **Колонка трупа была нулевой.** `leave_guard` сохраняет тайл как + `get_tilepos(0, row)`, то есть колонку 0 всегда, а `enter_guard` у нас брал + `curr_col` оттуда и следом перетирал X запомненным значением. В памяти это + было видно прямо: `col=0` при `x=95`. Оригинал (seg002:180) выводит колонку + ИЗ X: `Char.curr_col = get_tile_div_mod_m7(Char.x)`. У живого стража + незаметно (X там сама считается из колонки), у запомненного ТРУПА — ломало + порядок. Колонка нужна не только отрисовке: на неё смотрят коллизия и + `check_can_guard_see_kid`. + +4. **Ветка `actions_1_run_jump` оказалась не «упрощаемой».** Сначала я решил, + что её можно не портировать. Кадр в движении показал `ACT=1`: в беге + оригинал берёт тайл не из `curr_row`/`curr_col`, а из нижнего ряда и ЛЕВОЙ + колонки ГАБАРИТА (`char_bottom_row`/`char_col_left` из `set_char_collision`, + seg006:0723). При беге вправо левая колонка меньше `curr_col` примерно на + тайл — потому бегущий Кид и уходит за объекты справа. Отсюда «некоторые + кадры бега рисовали Кида поверх тела». Считается для ОБОИХ персонажей: + `enter_guard` ставит `action = 1` и стражу, односторонний учёт дал бы + перекос в другую сторону. Тонкость: `char_col_left` берётся по НЕ + утоньшённой границе — поправку THIN оригинал применяет только к `*_coll`. + +**Проверено в MAME:** после возврата в комнату у трупа `col=5` при `x=135` +(было `col=0`); Кид слева от тела — и стоя, и в кадре бега — рисуется за телом; +передние столбы снова перекрывают Кида. + +**Остаток, который НЕ баг.** Ноги стоящего Кида поверх головы трупа, когда он +стоит колонкой правее тела, — врождённое свойство движка (один спрайт = один +тайл при спрайте шире колонки). Сверено в SDLPoP: там так же. Подробности — в +разделе «НЕ БАГИ» выше. diff --git a/applications/PoP/roomtest/bug_list.md b/applications/PoP/roomtest/bug_list.md index f4aaa1b..0f01af5 100644 --- a/applications/PoP/roomtest/bug_list.md +++ b/applications/PoP/roomtest/bug_list.md @@ -17,14 +17,14 @@ BUG-DEATH-1 (смерть от меча), BUG-GATE-ANIM-1 (анимация во (см. ниже); из первой волны открытым остался косметический BUG-SEAM-DRAW-1. Ревизия **2026-08-03, вечер** (вторая волна с прогона): четыре наблюдения → -BUG-KBD-4 (фантомный отжим Shift) и BUG-RESPAWN-2 (стражи не оживают) — -**закрыты и проверены в MAME**; BUG-DRAWORDER-1 (Кид поверх тела стража) и -BUG-LOOSE-2 (осколки только от одной из двух плит) — **исправлены по SDLPoP, -но их сценарии автоматикой не воспроизведены** (см. таблицу ниже). +BUG-KBD-4 (фантомный отжим Shift), BUG-RESPAWN-2 (стражи не оживают) и +BUG-DRAWORDER-1 (Кид поверх тела стража) — **закрыты**; у последнего остался +артефакт «ноги поверх головы», сверенный с SDLPoP и записанный в «НЕ БАГИ». +BUG-LOOSE-2 (осколки только от одной из двух плит) — **исправлен по SDLPoP, но +гонка автоматикой не воспроизведена** (см. таблицу ниже). | ID | что | тип | статус | |----|-----|-----|--------| -| [BUG-DRAWORDER-1](#bug-draworder-1) | Кид рисуется поверх тела стража (в оригинале — за телом) | Minor | фикс есть, **сценарий не проверен** | | [BUG-LOOSE-2](#bug-loose-2) | осколки только от одной из двух падающих плит (комната 12) | Minor | фикс есть, **гонка не воспроизведена** | | [BUG-SEAM-DRAW-1](#bug-seam-draw-1) | у решётки на шве экран переключается, а Кид в шве НЕ рисуется | Minor | открыт | | [T-1](#t-1) | пики перерисовываются безусловно | оптимизация | открыт | @@ -64,7 +64,6 @@ BUG-LOOSE-2 (осколки только от одной из двух плит) | # | что проверить | ожидаемо | |---|---------------|----------| -| 13 | **[BUG-DRAWORDER-1]** убить стража там, где через тело можно пройти С ЛЕВОЙ стороны (не у самой кромки), и провести Кида сквозь тело | Кид проходит ЗА телом, когда его тайл в обходе РАНЬШЕ (левее по колонке или ниже по ряду), и поверх — когда позже | | 14 | **[BUG-LOOSE-2]** комната 12: разбежаться по плитам (0,1)/(0,2) и уйти в 15 ДО того, как долетит вторая; вернуться | осколки на ОБОИХ — (1,1) и (1,2) | | 15 | то же в комнате 7 (плиты 0,5/0,6 → 2,5/2,6) | не сломалось: по-прежнему двое осколков | | 16 | плита, улетевшая из комнаты вниз, при возврате | лишнего щебня не появилось | @@ -80,37 +79,6 @@ BUG-LOOSE-2 (осколки только от одной из двух плит) # Открытые баги уровня 1 - -## BUG-DRAWORDER-1. Кид рисуется поверх тела стража - -**Симптом.** В оригинале Кид проходит ЗА телом убитого стража; у нас — перед -ним. - -**Корень.** Мы рисовали безусловно `pop_guard_draw()` → `kid_draw()`, то есть -Кид всегда сверху. В оригинале «кто поверх» никем не назначается: и Кид, и -страж кладутся в midtable при обработке СВОЕГО тайла -(`set_objtile_at_char`, seg006:13F3), а тайлы обходятся строго — -`redraw_needed_tiles` (seg008:1B06) идёт рядами 2,1,0 и внутри ряда -колонками 0..9. Нарисованный позже оказывается сверху. Если тайлы совпали, -решает `sort_curr_objs` (seg008:203C): у обычных объектов (не тень, не плита) -ниже по `obj_y` — значит позже. - -**Фикс** (`roomtest.c`): `guard_over_kid()` считает ключ обхода -`(2 - row) * 10 + col` для обоих персонажей (с поправкой -`set_objtile_at_char` на лазание/полёт/вис — колонка левее), сравнивает, при -равенстве сравнивает `obj_y`, и порядок вызова `pop_guard_draw`/`kid_draw` -выбирается по результату. - -**Известное упрощение.** Ветку `actions_1_run_jump` (там оригинал берёт -нижний ряд и левую колонку ГАБАРИТА, а не `curr_row`/`curr_col`) не -воспроизводим: она требует полного футпринта, а влияет только когда -прыгающий Кид делит тайл со стражем — там порядок всё равно разводит `obj_y`. - -**Не проверено.** Сценарий не воспроизведён: в комнате 21 страж падает у -самой левой кромки (col 0), слева от тела встать нельзя, а «Кид поверх» при -Кид.col=1 > страж.col=0 — это как раз ПРАВИЛЬНЫЙ порядок и бага не -показывает. Нужен ручной прогон, п.13 таблицы выше. - ## BUG-LOOSE-2. Осколки только от одной из двух падающих плит