Files
Sprinter-SDCC/applications/PoP/roomtest/bug_list.md
T
Александр Петров d552cbaca9 docs: bug_list — только открытые баги; закрытые → bug_closed.md
Три Critical'а (BUG-1 провал на row 1 при боковом переходе, BUG-2 ping-pong
при возврате, BUG-3 окклюзия climb-up на кнопке) висели непроверенными с
2026-07-21.  Прогнал в MAME:

- BUG-1 не воспроизводится: room6 → кнопка (0,2) → открытая решётка →
  переход влево даёт room8, y=55, curr_row=0.  Заодно снят и сам диагноз
  записи — репроекция Y при БОКОВОМ переходе не нужна: goto_other_room
  (seg002.c:390) меняет только x, наш check_leave делает то же.
- BUG-2 не воспроизводится: шов room2↔room3, четыре пересечения с
  разворотом сразу после входа — комната меняется ровно раз на пересечение.
- BUG-3 закрыт фиксом tile_code_drawn от 2026-07-28 (это дубль уже
  записанного «спуск с кнопки»); оговорка про непереснятый подъём — в
  bug_closed.md.

bug_list.md теперь только открытое (BUG-CEIL-1/2/3, BUG-OCCL-1, T-1, T-2,
таблица обхода 24 комнат) + индекс с якорями.  bug_closed.md — закрытое
вместе с разбором корней (odd-pixel char_x, подстановка тайла кнопки, баг
кодогенератора SDCC), он и есть главная ценность архива.

TASKS.md: кросслинки на открытые баги в шапке, в L1-TRIAGE, L1-PASS и
«Отложено».  Указатели в CLAUDE.md/README/room_model_plan/layout_plan_v2
переведены на нужный из двух файлов.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 20:57:33 +03:00

14 KiB
Raw Blame History

roomtest — ОТКРЫТЫЕ баги и незакрытые оптимизации

Только то, что не закрыто. Всё закрытое (и, что важнее, разбор корней — odd-pixel арифметика char_x, подстановка тайла нажатой кнопки, баг кодогенератора SDCC) переехало в bug_closed.md: прежде чем заводить новый баг, грепни там по симптому.

Приоритеты работ — в TASKS.md, а не здесь. Правило проекта: механику сверять с ../SDLPoP/src/ ДО кодинга.

Ревизия списка: 2026-08-01 (задача L1-TRIAGE). BUG-1, BUG-2 и BUG-3 стояли как Critical с 2026-07-21 — все три прогнаны в MAME и закрыты, протокол в bug_closed.md. Critical'ов сейчас нет.

ID что тяжесть
BUG-CEIL-1 прыжок вверх: руки Kid поверх потолка Medium
BUG-CEIL-3 анимация ворот стирает потолок над ними Medium
BUG-OCCL-1 тень дальней колонны перекрывает Kid Medium
BUG-CEIL-2 loose-плита в потолке не трясётся Medium, отложен
T-1 пики перерисовываются безусловно оптимизация
T-2 Кид перерисовывается в покое оптимизация
обход 24 комнат таблица заполнена на 5 строк из 24 ревизия

BUG-CEIL-1. Прыжок вверх: руки Kid рисуются ПОВЕРХ потолка — Medium

Симптом (2026-07-22): при прыжке вверх (SEQ up, кадры 67..79) руки/голова Kid заходят в полосу кладки у потолка (row -1) и рисуются ПОВЕРХ неё — потолок должен окклюдить руки (как передняя грань).

Где: pop_bg.c — полоса потолка (draw_tile(-1)) сейчас только фон (запечена в pop_room_draw), не окклюдер поверх Kid. Нужен ceiling-overlay в pop_fore_over_kid (перерисовать срез полосы над Kid поверх спрайта), по аналогии с fore-тайлами. Инфраструктура g_clip_top/gfx_blit_part уже есть.

BUG-CEIL-3. Анимация ворот стирает потолок над ними — Medium

Симптом (2026-07-22): при опускании/поднятии решётки шва (анимация openness) полоса кладки у потолка НАД воротами пропадает (см. потолок над левым швом).

Где: pop_bg.c pop_room_redraw_seam_leftpop_button_redraw/ pop_spike_redraw — общий класс): чёрный bar по col0 row0 стирает потолочную полосу (row-1), а redraw рисует только сам гейт, не восстанавливая полосу. Нужно: при перерисовке шва/тайла у потолка перерисовать и срез потолочной полосы (draw_tile(-1,col) с g_clip_top) над затронутыми колонками.

BUG-OCCL-1. Тень дальней колонны перекрывает Kid в (0,4)-(0,5) — Medium

Симптом (2026-07-22): Kid, стоя/прыгая у (0,4)-(0,5), частично перекрыт тёмной штриховкой — это ТЕНЬ/боковая грань ДАЛЬНЕЙ колонны (сзади по глубине), которая НЕ должна окклюдить персонажа. Over-occlusion fore-слоя.

Где: pop_bg.c pop_fore_over_kid/fore_tile — рисует fore футпринт-тайлов без учёта глубины (какая грань РЕАЛЬНО перед Kid). Порт seg003 redraw_at_char окклюдит только передние грани; дальняя колонна (за Kid) не должна. Сверить с SDLPoP redraw_at_char (какие тайлы/грани идут в fore vs back по y-сортировке).

BUG-CEIL-2. Тряска/разбитие loose-плиты в потолке (row -1) не работает — Medium, ОТЛОЖЕН

Симптом (2026-07-22): loose-плита в ряду 2 верхнего соседа (room5 (2,5) → потолок room6 над (0,5)) при прыжках Kid на (0,5) НЕ трясётся и не разбивается.

Где: верхний сосед не «живой» — above_fg берётся из статики уровня, loose-состояние соседней комнаты не тянем (per-room loose/modif не персистятся). check_press/knock работают только по текущей комнате. Нужно: (а) пробой loose сверху через границу комнаты, (б) персистентное loose-состояние соседа + его отрисовка в полосе. Пока полоса рисует loose статически (кадр покоя).

Почему отложен: требует персистентного per-room modifier соседей — это фаза P0 из ../docs/gates_spikes_plan.md, а не точечный фикс. См. «Отложено осознанно» в TASKS.md.


Оптимизация отрисовки (записано 2026-07-29)

Не баги — план работ. Оба пункта про одно: у оригинала пометка тайла к перерисовке стоит копейки (бит в таблице, которая всё равно чистится каждый кадр), а у нас каждая такая пометка превращается в реальный heal (копию из ОЗУ-копии акселератора) плюс блиты. Поэтому буквальный порт «перерисовываем безусловно» корректен, но дорог.

T-1. Пики: перерисовывать по причине, а не безусловно

Сейчас: pop_process_trobs зовёт pop_spike_redraw каждый кадр для каждой живой пики в комнате (порт redraw_21h, который animate_spike вызывает вне всяких if). Это корректно, но лишнее для пик, до которых Киду дела нет.

Надо: перерисовывать тайл пики, только если

  1. сменился её видимый кадр (шаг выдвижения/уборки), ЛИБО
  2. её кто-то стёр — а стереть у нас может только heal, то есть тайл попал в прямоугольник kid_heal этого кадра.

Это и есть модель оригинала, просто выраженная флагами: redraw_at_char (seg003:0576) каждый кадр помечает set_redraw_fore тайлы персонажа, причём объединение текущего и предыдущего прямоугольника (MIN(char_top_row, prev_char_top_row) и т.д.), а animate_spike помечает свой тайл. Итог = {тайл сменил кадр} ∪ {тайлы Кида}.

Как: слой Кида и так считает cL..cR/rT..rB в pop_fore_over_kid — пусть публикует их (плюс предыдущие, как в оригинале), а цикл trob'ов сравнивает tilepos с диапазоном целочисленно. Никаких пересечений прямоугольников (см. память manual_hints_over_auto_detect).

Приоритет: отдаётся почти бесплатно ПОСЛЕ T-2, отдельно не окупается.

T-2. Idle-skip: не перерисовывать Кида, когда ничего не происходит

Сейчас: kid_healkid_drawpop_fore_over_kid идут каждый кадр, даже когда Kid стоит и в его тайлах ничего не меняется. Это ровно поведение оригинала (draw_game_frame, seg000:917 — draw_moving() + draw_tables() безусловно), но у него это дёшево, а у нас нет.

Надо: пропускать heal+draw Кида, когда кадр/поза/координаты не менялись и в его тайлах нет активной анимации.

Осторожно (дабл-буфер): пропускать можно не раньше второго подряд неизменного кадра — иначе одна из двух страниц останется со старым содержимым. Условие «обе страницы уже получили это состояние».

Связь с T-1: после T-2 пики отпадают сами — раз Кида не перерисовываем, heal'а нет, стирать пики нечем, редрой не нужен.

Связь с KBD-1: это ещё и минус DI-окна в самых спокойных кадрах — ровно там, где тапают Shift+стрелку (см. остаток KBD-1 в TASKS.md).


Обход всех 24 комнат уровня 1 — поиск багов отрисовки

Инструмент: #define ROOMNAV в roomtest.c+/- (цифровой блок либо =/- основного ряда) переключают комнату по номеру (1..24, с обёрткой), Kid ставится на первый пол, pop_trob_reset() возвращает пики/ворота в исходное. Номер комнаты — полосками в верхнем борте: слева десятки, справа единицы (|| |||| = 24). Убирается закомментированием одной строки.

Комнаты 13, 18, 24 недостижимы в обычной игре — это свойство данных уровня, разбор в bug_closed.md («НЕ БАГИ»). Приоритет багов в них низкий.

Таблица заполнена на 5 строк из 24 — доделать в рамках L1-TRIAGE (TASKS.md).

комната статус что не так
1 пофикшено падающая плита (2,6): правая грань видна через пол (2,7) и перекрывает его переднюю грань — mob_render брал ряд соседа из m->row (счётчик, уже ушедший на ряд вперёд), а не из координаты
2
3
4
5 пофикшено прыжок в решётку: Kid оставался стоять на 6 px ВЫШЕ пола и без приземления-приседания — от bumped() (seg004) был портирован только хвост (seq_47), не хватало bumped_floor (прижатие Y к полу + seq_46_hardbump на кадрах прыжка 24/25/40..42/102..106) и bumped_fall
6
7
8
9 сделано дверь уровня (1,3)-(1,4) рисовалась чёрным проёмом: не был портирован draw_leveldoor (seg008:1D29) — створка (слайсы 33 + верх 34), лестница за ней (99/144) и анимация подъёма по кнопке (animate_leveldoor, seg007:05F1, modif 0→43). Спрайты 33/34/99/144 добавлены в атлас явным набором (render_room.py дверь не рисует)
10
11
12 пофикшено вис/подтягивание на кромке loose-плиты: плита рисовалась ПОД Кидом. Не хватало двух кусков draw_tile: (а) draw_loose кладёт нижнюю грань плиты И в foretable (поверх персонажа), (б) draw_tile_base подставляет верх плиты из loose_fram_left, а в нашем midtable-оверлее стоял голый base_id (у loose он 0). Голова Кида поверх падающей на него плиты — см. «НЕ БАГИ» в bug_closed.md
13 недостижима в игре
14
15 сделано меч (2,2) не рисовался: тайл 22 в draw_tile_anim не был портирован. Добавлены отрисовка предмета (chtab_1 id 10/11 на draw_main_y3), подъём по Shift (check_get_item/get_item/do_pickup: присед → seq_91 pickupsword → меч исчезает с пола) и статус pop_have_sword
16
17
18 недостижима в игре
19
20
21
22
23
24 недостижима в игре

Заметки (отладка)

  • Тестовые клавиши осторожного шага: J = шаг влево, L = шаг вправо (эмуляция Shift+стрелка), см. pop_ctrl.c KBD_DBG_STEP*. Первый шаг в сторону = разворот (как в оригинале safe_step), движение со второго.
  • Читы (pop_cheat.h): K — убить стража, I — бессмертие (toggle), S — выдать меч.
  • Респавн после смерти — по (или авто через RESPAWN_DELAY); ставит Kid в START_ROOM.
  • START_ROOM=1 / COL 3 / ROW 0 — жёстко зашитый тестовый старт; перевести на pop_level_start_* (задача L1-START в TASKS.md).