Порт tbl_envir_ki[tbl_level_type[level]] (seg000:1108): оригинал под один и
тот же набор id грузит РАЗНЫЙ .DAT — VDUNGEON или VPALACE.
Упаковщик (toolchain/pop_pack_bg.py):
- аргумент набора: `pop_pack_bg.py dungeon|palace`. Каскад каталогов —
сначала свой набор, потом чужой фолбэком (в распакованном data/ res230/
231/348 есть только в VDUNGEON, два десятка — только в VPALACE).
- ОБА набора пакуются по одному объединению id, поэтому раскладка
id -> (страница, idx) общая и заголовок один: коду достаточно подменить
имена файлов.
- PALACE_ENV_IDS: 78/80/82 (doortop_fram_bot), 81/83 (doortop_fram_top),
84 (полоска стены), 145 (stripe_id) — их рисует только палас, render_room
про них не знает.
- ENV_SHIFT 5 -> 4: с паласными кусками страница 2 переваливала за 16 КБ
(16 996). Цена — 10 страниц EMM на набор вместо 5, при 215 свободных.
- *tile.pal: 32 записи (env 0x50..0x5F + wall 0x60..0x6F) на набор. Полная
kid.pal не трогается — Кид, страж, меч и зелья в других слотах.
Движок:
- pop_level_type() (tbl_level_type, SDLPoP data.h:840): дворцовые уровни
4, 5, 6, 10, 11, 14. Живёт в pop_level.c, потому что по типу расходятся
не только атласы, но и ветки отрисовки seg008, кладка стены и модификатор
пустой клетки от упавшей плиты (remove_loose, seg007:0EB8).
- pop_bg_load(set): no-op при том же наборе, при смене выгружает старый
(иначе текут 12 EMM-страниц) и правит 32 записи палитры в ОБЕ страницы
дабл-буфера. Зовётся на старте и на границе уровня, не в кадре.
- Путь к атласу склеивается на месте (bg_path): двадцать строк-имён в банке
— лишние полкилобайта.
Проверено в MAME: уровень 1 (подземелье) рисуется как прежде; уровень 4
(-DFIRST_LEVEL=4) — дворцовые арки, окна, пол, решётчатая дверь уровня,
Кид не перекрашен. Стены пока чёрные: паласный wall_pattern — шаг C.
tests-host: 5/5.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Три фикса, найденные разбором в MAME.
1. Просвечивание Кида сквозь торец кнопки (подъём/спуск у кромки).
draw_tile_bottom (seg008:570) рисует нижнюю грань блиттером
blitters_0_no_transp: пиксель индекса 0 заливается ЧЁРНЫМ, а не
пропускается. У граней кнопок (env 96/149) и нижних кадров loose (73/74)
последняя строка целиком нулевая — наш упаковщик переводил 0 в 0xFF для
ВСЕХ спрайтов, и она становилась дырой, сквозь которую был виден Kid за
тайлом (на запечённом фоне не видно — там и так чёрное).
pop_pack_bg.py: NO_TRANSP_ENV_IDS пакуется с сохранением индекса 0 как
ЦВЕТА (0x50 = чёрный в палитре env). Ноль тактов в рантайме.
2. Разворот в проёме опущенной решётки выкидывал Кида на другую её сторону.
check_bumped проверял столкновение УРОВНЕМ («край зашёл за грань»), поэтому
разворот на месте внутри тайла-стены менял, какую грань мы меряем, и это
читалось как новое столкновение → Kid.x = char_dx_forward(d) швырял его
сквозь решётку. Оригинал (check_collisions + get_row_collision_data,
seg004:0004) считает флаги перекрытия от ГАБАРИТА персонажа, БЕЗ
направления, и зовёт bumped() только на переходе 0 -> 1 (вправо смотрит на
0x0F, влево на 0xF0). Порт этого edge-триггера: флаги от габарита + память
прошлого кадра по колонке, сброс при смене комнаты (в оригинале это
несовпадение prev_coll_room/curr_row_coll_room). Проверено: теперь
разворот даёт уход в комнату 8 (leave_room, взгляд влево, char_x_left<=54)
— то есть туда, где Kid физически и стоит.
3. Снимок шва расширен до ДВУХ колонок с каждой стороны (lcol_fg[6]/
rcol_fg[6]: col9+col8 и col0+col1). Kid, стоящий В шве (curr_col=-1),
смотрит вперёд на колонку -2, где раньше была мнимая стена (get_tile ->
TILE_WALL). Оригинал резолвит любую колонку через find_room_of_tile
(seg006:005D).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Порт Prince of Persia (applications/PoP/roomtest): развитие уровня,
объекты (loose-полы/обломки), переходы между комнатами, фон-упаковка;
планы (room_model/size_optimization), bug_list, pop_trob.
Арт third_party/16x16-RPG-characters.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Проваливающиеся полы в roomtest (порт SDLPoP seg007/seg008), проверено в MAME:
- Падающий кусок (mob): правый край env-42 (w=26, доходит до mob_x+57)
теперь полностью покрыт heal-коридором (MOB_W 56->64) — убран тёмный
хвост-тень на полу 2,7 ПОСЛЕ падения.
- Окклюзия правого куска во ВРЕМЯ падения: после отрисовки плиты
перерисовывается сосед-пол draw_tile(row,col+1) в том же кадре — край
прячется за полом 2,7 (порт redraw_at_cur_mob: set_redraw_full+1).
- Тряска от сотрясения (knock): seqtbl-команды KNOCK_DOWN/UP в play_seq ->
флаг knock -> do_knock(ряд) трясёт loose ряда из покоя (modif=0x80).
KNOCK_DOWN в land-seq (приземление) и runcyc (footstep).
- Фикс «бесконечной тряски» (дабл-буфер): при завершении тряски (0x84->0)
перерисовать покойный кадр плиты на ОБЕИХ страницах (loose_rest, 2 кадра) —
иначе на одной странице застревает дрожащий кадр правой грани (живёт в
тайлах col и col+1) -> мерцание через флип.
Инфраструктура/документация:
- app.mk: цель `make hdd` (упаковка в D: для MCP-моста MAME).
- docs: POP-DAT-FormatSpecifications.pdf/.txt как каноническая спецификация
форматов ресурсов; ссылки в README/MSDOS_RESOURCE_FORMAT.
- README.md/CLAUDE.md для applications/PoP и roomtest (правило «SDLPoP —
источник истины», порядок слоёв, режим отладки freeze 1/2).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>