КОД НЕ МЕНЯЛСЯ. Построчный разбор наших реализаций против оригинала: 26 позиций за пять проходов, каждая с рангом вероятности (А..Д), с описанием «чем грозит» и сценарием проверки. Расхождения группируются в три узла, и это главный вывод аудита: 1. СМЕРТЬ ПРИ АКТИВНОЙ ФИЗИКЕ — здесь все находки ранга А. У нас смерть это флаг, а физика продолжает вести персонажа как живого: нет ветки «убит и сброшен с уступа» (оригинал выбирает её по тайлу позади), прижатие к полу в hurt_by_sword стало безусловным (в оригинале только для выжившего удара), в land лишний пересчёт колонки. Этим объясняется наблюдение пользователя: заколотый на краю Кид доезжает этажом ниже и садится в присед. 2. ГРАНИЦЫ МОДУЛЕЙ — pop_map не отдаёт наружу тайловые запросы от произвольного Char, wall_type и загрузку кадра. Три ветки упрощены НЕ по логике, а по доступности функций: отсутствующая ветка уступа, «стена впереди» сужена у стражей до одного тайла (оригинал считает преградой ещё ворота, верх двери, зеркало и чомпер), in_wall не перезагружает кадр. Чинить это заплатками неправильно — сначала расширять интерфейс pop_map. 3. МОМЕНТ ПОБОЧНЫХ ДЕЙСТВИЙ — делаем то же самое, но раньше или позже: сброс fall_x, побудка чомперов (у нас отложена до конца play_seq), звук удара, перезагрузка кадра. По отдельности мелочь, вместе — сдвиг состояния на кадр. Восемь позиций СВЕРЕНЫ И СОВПАДАЮТ (диспетчер control, все 15 опкодов seqtbl, control_with_sword, parry, swordfight, sword_strike, check_sword_hurt, check_hurting, bumped_fall, таблицы кадров) — их не нужно перепроверять. Дважды по ходу работы едва не записана ложная находка из-за чтения отфильтрованного вывода; отсюда правило: фиксировать расхождение только после чтения обеих реализаций целиком. Отдельно: второе наблюдение пользователя (падение частично в стене) — у SDLPoP есть ТРИ опциональных фикса ровно про это, то есть в ванили баг присутствует, и мы его намеренно повторяем. Но найдены два места, где мы можем быть хуже ванили (гард curr_row<=2 в do_fall и in_wall выше). Незакрытое перечислено в файле: тела autocontrol_*, check_grab, check_bumped_look_left, старшие биты байта клинка. Также отмечено, что ни одно найденное осознанное отличие не занесено в docs/impl_diff.md, хотя правило проекта этого требует. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011MsUsEFAQfsjjQpJ7RtKVY
SprPoP — Prince of Persia на Sprinter Sp2000
Порт оригинального Prince of Persia (1989) на компьютер Sprinter Sp2000: режим 320×256×256, дабл-буфер, звук через CBL, код разложен по одиннадцати 16-килобайтным банкам.
Приложение автономно — код, оригинальные данные, конверторы ресурсов и сборка лежат внутри этой папки. Наружу нужен только компилятор:
export SPRINTER_ROOT=/путь/к/C-Compiler # не нужен, если папка лежит внутри его дерева
make # build/sprpop.exe + ресурсы в build/
make hdd # + образ build/hdd/sprpop.chd
Чужих данных в репозитории нет — есть адреса, откуда их взять. Чтобы перегенерировать ресурсы (или получить эталон механики), сначала:
make fetch # SDLPoP + записи саундтрека DOS-версии в assets/orig/
Что где
src/ рукописный C: главный цикл sprpop.c + движок pop_*.c
gen/ генерируемые заголовки — руками не править
assets/orig/ оригинальные данные игры (вне репозитория, качает `make fetch`)
assets/packed/ то, что ложится на диск игры, в раскладке диска
tools/ конверторы ресурсов; все пути — в tools/paths.py
docs/ планы, доски задач и багов, справочники (начинать с docs/README.md)
tests/host/ модульные тесты движка под ucsim_z80
build/ выход: sprpop.exe, каталоги ресурсов, hdd/, промежуточные atl/
Цели сборки
| Команда | Что делает |
|---|---|
make |
собрать build/sprpop.exe и разложить ресурсы в build/ |
make hdd |
+ образ жёсткого диска build/hdd/sprpop.chd |
make mame-link |
однократно подставить образ в MAME (символьная ссылка на IMG/test_hdd.chd) |
make fetch |
скачать внешние исходные данные в assets/orig/: fetch-sdlpop, fetch-music, fetch-check, fetch-list |
make resources |
перегенерировать ресурсы из assets/orig/ |
make music-mp3 |
музыка из другого набора записей: music-flac (умолчание), music-mp3, music-ogg, music-mt32 |
make SND_SRC=msdos |
оцифровка эффектов из дистрибутива DOS вместо SDLPoP (нужен свой assets/orig/MSDOS/) |
make -C tests/host |
модульные тесты движка (секунды, без эмулятора) |
make test-tools |
тесты упаковщиков на хосте: форматы файлов, которые читает Z80 |
make clean |
снести build/ (ассеты не трогает) |
make distclean |
clean + снести упакованные ассеты assets/packed/ |
Отладочные ключи: make LEVEL=9 — стартовый уровень, make ROOM=15 POS=2 —
стартовая комната и тайл (row*10+col), make PROF=1 — профиль фаз кадра
полосами бордюра, make ALLOCS=100000 — плотная упаковка регистров для
замеров размера.
Сборка из чистого клона
Работает без assets/orig/: упакованные ресурсы (assets/packed/) и
генерируемые заголовки (gen/) лежат в репозитории. Исключение —
assets/packed/LEVELS/: файлы уровней ложатся на диск прямо из оригинала,
без конвертации, поэтому они, как и assets/orig/, вне репозитория. Что и
откуда положить — assets/orig/README.md.
assets/orig/ нужен только чтобы ресурсы перегенерировать (make resources) и как эталон механики: любая правка поведения сверяется с
assets/orig/SDLPoP/src/ до кодинга, см. CLAUDE.md. Заполняется он одной
командой make fetch — качается SDLPoP (ресурсы + исходники-эталон) и записи
саундтрека; адрес архива музыки скрипт берёт из самого SDLPoP.
Оригинальный дистрибутив DOS (assets/orig/MSDOS/) не нужен: и уровни, и
оцифровка звука берутся из SDLPoP. Он даёт ровно одно — более полный набор
эффектов (в SDLPoP пуст звук spiked, 48); у кого дистрибутив есть, включает
его явно: make SND_SRC=msdos. Подробности — assets/orig/README.md.
Происхождение
Выделен из applications/PoP/roomtest 2026-08-26; та папка заморожена и
служит архивом закрытых задач, багов и исполненных планов. Референсные
реализации (Apple II 6502, Princed Resources, mininim) остались в
applications/PoP/.