Files
Sprinter-SDCC/applications/PoP/CLAUDE.md
T
snark13 6673279cef PoP: скелет уровня 3, цвета стражей, окклюзия соперника; кэш соседних комнат
Скелет (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>
2026-08-07 22:11:03 +03:00

6.8 KiB
Raw Blame History

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) — ЕДИНСТВЕННЫЙ авторитетный источник того, как оригинальный движок это делает. Правило без исключений:

  1. Перед реализацией ЛЮБОЙ функции (движение, коллизия, окклюзия, падение, loose-полы, стражники, отрисовка, тайминги, любые числовые константы) — СНАЧАЛА найди и прочитай соответствующий код в SDLPoP/src/, и портируй по нему. Не пиши по памяти, не выводи логику «из общих соображений», не угадывай значения — это источник багов, которые потом ловятся в MAME часами.
  2. По любому вопросу «как в оригинале должно быть» (что окклюдит что, в каком порядке слои, когда меняется тайл, какая скорость/задержка, что делает такой-то кадр анимации) — ответ ищи в SDLPoP/src/, а не строй гипотезу. Если в SDLPoP не нашёл — это повод копать дальше в исходнике, а не додумывать.
  3. Расхождение нашей реализации с 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/.

Каноническая спецификация форматов .DATdocs/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 — квирки упаковки ассетов.