Скелет (L3-SKEL, ассеты + механика): - pop_pack_guard.py получил параметр набора (GUARD/SKEL): атлас скелета poc/res/skel/g0..g3.atl (28 кадров), палитра — из его res750.pal (на ур. 3 curr_guard_color = 0, оригинал палитру не подменяет); - pop_guard_load выбирает набор по tbl_guard_type и перезагружается ПРИ СМЕНЕ УРОВНЯ (load_lev_spr, seg000:1092) — без этого скелет рисовался атласом стража и был невидим; - load_frame: charid_4_skeleton идёт по таблице стража (seg006:529), тень — только в кадрах 150..189. Пока ветка была одна (charid_2_guard), скелет получал image из таблицы Кида (180 при 28 спрайтах) и не рисовался; - check_skel (seg002:1042), ветка charid_4 в enter_guard, возрождение в комнате 3 при падении (seg002:252), autocontrol_skeleton; - leveldoor_open (seg007:456) — новый флаг, сбрасывается стартом уровня. Цвета стражей (BUG-GUARD-COLOR-1, закрыт): - все 7 палитр res10.bin -> pop_guard_pal.h, заливка 16 слотов по guards_color комнаты перед отрисовкой (set_chtab_palette, seg003:257). Проверено в MAME: ур. 2 комн. 11 = цвет 1, комн. 7 = цвет 3, полоса HP меняется вместе со стражем. Грабля: gfx_pal_load отдаёт указатель в BIOS, а тот читает только #4000-#BFFF — таблицу из банка копируем в стек. Кэш соседних комнат (BUG-SWORD-GHOST-1, закрыт): - pop_map кэширует fg соседей слева/справа ЦЕЛИКОМ и резолвит col -10..19. Было -2..11, дальше мнимая стена: луч видимости упирался в неё (страж после follow_guard в col 12), Кид прятал меч посреди боя и не мог достать обратно. +48 байт W2. Окклюзия соперника: - pop_fore_over_char получил проход other_overlay_tile (порядок midtable, seg008:1B06) и расширение перебора объединённым прямоугольником «персонаж + клинок + брызги» — падающий скелет больше не рисуется поверх кладки и верхней грани пола; - клип полем 192 строк (reset_obj_clip, seg006:0507) для спрайта, клинка (общий pop_sword_draw) и брызг — спрайт не залезает на полосу HP; - ROOMNAV после смерти Кида делает честный pop_start_level: телепорт «оживлял» мёртвого мимо старта уровня, оставляя живого скелета рядом с вернувшейся кучей костей. Ассеты чомпера (под L3-CHOMP): весь набор кадров в атласе явным списком (101-105 низ, 111-113 верх, 106-110 фронт, 114-123 кровь mono-силуэтом) — render_room анимированные тайлы пропускает, и в атласе не было ни одного. Число EMM-страниц не изменилось. Тесты: tests-host все 5 наборов зелёные, t_char вырос до 65 проверок (резолв колонок за краем комнаты, возрождение скелета); в testkit добавлен гард «код наехал на данные» (DATA_LOC). Доски: TASKS.md разнесён на TASKS_OPEN/TASKS_CLOSED, закрытые баги с разбором корней — в bug_closed.md; заведены DRAW-CHAR (отрисовка одна на всех Char, как физика после GUARD-PHYS) и L3-COLOR (зелёная кладка уровня 3: level_var_palettes = ресурс 20, есть в MSDOS/PRINCE.DAT). В roomtest.c временно оставлен автостоп на падении соперника (отладка падений скелета) — помечен ВРЕМЕННО. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
6.8 KiB
Prince of Persia → ZX Sprinter — правила подпроекта
Порт Prince of Persia (DOS/Apple II) на Sprinter Sp2000 поверх нашего
sprinter-cc / libc / libbgi. Действуют правила корневого
CLAUDE.md (сборка, libc, ABI, MAME-автотест); ниже — только специфика PoP.
Общение и комментарии — на русском.
Главное правило: SDLPoP — источник истины. Сначала читай, потом кодь
SDLPoP/src/ (github.com/NagyD/SDLPoP, GPLv3) — ЕДИНСТВЕННЫЙ авторитетный
источник того, как оригинальный движок это делает. Правило без исключений:
- Перед реализацией ЛЮБОЙ функции (движение, коллизия, окклюзия,
падение, loose-полы, стражники, отрисовка, тайминги, любые числовые
константы) — СНАЧАЛА найди и прочитай соответствующий код в
SDLPoP/src/, и портируй по нему. Не пиши по памяти, не выводи логику «из общих соображений», не угадывай значения — это источник багов, которые потом ловятся в MAME часами. - По любому вопросу «как в оригинале должно быть» (что окклюдит что,
в каком порядке слои, когда меняется тайл, какая скорость/задержка,
что делает такой-то кадр анимации) — ответ ищи в
SDLPoP/src/, а не строй гипотезу. Если в SDLPoP не нашёл — это повод копать дальше в исходнике, а не додумывать. - Расхождение нашей реализации с SDLPoP — по умолчанию баг у нас, пока не доказано обратное (наша платформа/ABI требует отличия — тогда явно зафиксировать почему в комментарии).
Карта сегментов: seg005 control-диспетчер, seg006 play_kid/коллизия/
seqtbl, seg007 mob/loose/падающие объекты, seg008 отрисовка тайлов/
слои/окклюзия, seg009 чтение ресурсов. Слои окклюзии у нас = слои SDLPoP.
См. memory pop_check_sdlpop_first.
Вторичные референсы (когда в SDLPoP непонятно/нужен другой ракурс):
Prince-of-Persia-Apple-II/— оригинальный 6502-исходник 1989 (Мехнер).PR/(github.com/NagyD/PR, GPLv2) — Princed Resources.mininim/— независимая реализация.
Все эти папки — справочник логики/структур/констант и источник ассетов, но НЕ код для копирования (лицензии несовместимы, наш ABI другой): читаем и переписываем под наш движок, а не вставляем куски.
Ассеты
Готовые распакованные VGA-256 ассеты (то, что нужно под 320×256×256) —
SDLPoP/data/ (res<id>.png/.pal/.bin). Брать оттуда, а НЕ писать свой
декодер DOS .DAT. Локальные .DAT — в MSDOS/.
Каноническая спецификация форматов .DAT — docs/POP-DAT-FormatSpecifications.pdf
(грепаемая копия — docs/POP-DAT-FormatSpecifications.txt): первоисточник
Princed для DAT v1.0 (контейнер/индекс/чек-сумма, кодеки RLE/LZG, палитры,
формат уровней, звук), на нём построены и SDLPoP, и Princed Resources. Наши
разборы (docs/MSDOS_RESOURCE_FORMAT.md / docs/APPLEII_RESOURCE_FORMAT.md /
docs/README.md) — практические заметки/сверки; при расхождении источник
истины — спецификация. Формат уровня почти идентичен в Apple II и DOS.
Упаковка ассетов под Sprinter (атласы .atl, палитра) — python-скрипты в
toolchain/ (render_room.py, pop_pack_bg.py, pop_pack_kid.py,
pop_extract_kid_data.py). Их дёргают Makefile'ы тестов.
Структура папки
docs/— планы и форматы; индекс с отметками актуальности —docs/README.md, начинать чтение оттуда. Ключевое:levels_plan.md(следующий этап),layout_plan_v2.md(раскладка кода по окнам/банкам + скорость отрисовки),PORT_PLAN.md(карта фаз со статусами).roomtest/— активная разработка: уровень 1 целиком (Kid, стражи, ловушки, ворота, loose-полы). СвойCLAUDE.md; текущие задачи —roomtest/TASKS_OPEN.md(закрытые с протоколами —roomtest/TASKS_CLOSED.md), открытые баги —roomtest/bug_list.md, закрытые с разбором корней —roomtest/bug_closed.md.poc/— ранний proof-of-concept (снег/атлас/kbd_raw); ассеты вpoc/res/.bgtest/,coltest/— отдельные проверки фона/коллизии.toolchain/— python-упаковщики ассетов + эталонные PNG (1.1-2.png).SDLPoP/,PR/,Prince-of-Persia-Apple-II/,mininim/,MSDOS/— референсы/оригинальные данные (см. выше).
Ключевые архитектурные решения (memory/)
pop_port_project— общий статус порта.pop_banking_architecture— будущее: big+BANK_W1, графику нельзя в W3, один файл = один банк = прямые вызовы, main резидентен.pop_background_strategy— фон = композиция тайлов в рантайме (вариант 3).pop_kid_plan/pop_hang_state/pop_fore_layer/pop_fall_debug_baseline— этапы Kid.kbd_raw_fifo_drain— held-state клавиатуры (единственный принципиальный пробел движка, закрыт<kbd_raw.h>): вычерпывать FIFO SIO циклом.png_strip_padding_tradeoff,pop_tile_atlas_palette_merge— квирки упаковки ассетов.