Claude Fable 5 портировала игру 1993 года для Amiga на Godot: 72 758 строк ассемблера без документации
В 1993 году в Багдаде студент-инженер писал на Amiga 500 (512 КБ памяти, без жёсткого диска) игру «Babylonian Twins», целиком на ассемблере 68000, вручную рисуя каждый спрайт и просчитывая каждую строку развёртки. Художник, Муртада Салман, композитор, Махир аль-Салман. Страна жила под санкциями: не было интернета, не было литературы по разработке игр, только Amiga Hardware Reference Manual, по которому автор программировал железо напрямую, и электричество по несколько часов в сутки. От постоянной смены дискет и летней жары под 50°C дисковод выходил из строя трижды. Игра стала первой коммерческой игрой, сделанной в Ираке, но крах Commodore и санкции отпугнули издателей, и она легла на полку, пока в 2008 году её не нашёл Amiga-форум по роликам брата автора на YouTube. В 2010 году та же команда вручную переписала игру для iPhone на новом движке (около 34 000 строк C++), Apple и Google её отметили, а суммарно она набрала больше двух миллионов скачиваний.
Около года назад автор уже пробовал отдать более ранней модели необъяснённые данные карт уровней, та в итоге разобралась, но за несколько заходов и с массой подсказок. Когда вышла Claude Fable 5, модель, запущенная в агентном инструменте Claude Code с доступом к терминалу и файловой системе автора, он решил повторить эксперимент осознанно: расчёт был на то, что ассемблера 68000 в обучающих данных крайне мало, и если модель действительно рассуждает, а не вспоминает, это должно проявиться именно здесь. Он поставил три последовательных задачи, каждая следующая, только если сработала предыдущая: «безопасный» контрольный перенос уже знакомого движка 2010 года (34 000 строк C++) в Godot 4; «нечестный» перенос оригинальных 72 758 строк ассемблера 1993 года (26 файлов, без документации) прямо в Godot, на родной частоте Amiga 50 Гц; и «жадный» финал, встроить версию 1993 года вторым, отдельно запускаемым режимом внутрь современной игры. Сработали все три.
Перенос движка 2010 года занял один вечер: за 21 минуту с нуля получился играбельный персонаж, а затем, все 38 типов игровых объектов и полный игровой цикл. Ещё около трёх дней ушло на то, чтобы вернуть правильное ощущение прыжков и трамплина; каждую сборку вместе с автором тестировал его тринадцатилетний сын. Модель сама заметила и сохранила тонкости: коэффициент трения 0,85, который в оригинале применяется покадрово, работает по-разному на разной частоте обновления, поэтому порт движка 2010 года остался на 60 Гц, как и его исходный iOS-билд, а порт из ассемблера 1993 года, на «родных» 50 Гц, как сама Amiga. Вместо готового компонента Godot для физики (CharacterBody2D) модель построчно перенесла собственную 150-строчную процедуру коллизий автора, включая странную константу 0,49, которую тот сам подобрал на глаз пятнадцать лет назад и ни разу не «причесал».
Второй, «нечестный» перенос начался с того, что модель заставила современный ассемблер vasm (на Mac с процессором Apple Silicon) собрать исходники 1993 года так, чтобы результат побайтово совпал с уже выпущенными на дискетах бинарниками, это заняло пятнадцать минут от импорта файлов до первой удачной сборки. По пути пришлось преодолеть различия диалектов оригинального ассемблера ASM-One и современного vasm (модель написала отдельный слой, компенсирующий пять таких расхождений) и восстановить имена файлов, укороченные ещё при переносе на современный носитель в 2008 году. Была и собственная ошибка модели: разворачивая счётчик адреса назад, она один раз неверно истолковала резервирование 800 байт как их обнуление, из-за чего часть файла сместилась на 944 байта, ошибку нашли и исправили той же побайтовой сверкой. Ещё около 108 байт продолжали не совпадать в области переменных; по объяснению, которое дала сама модель (и которое автор прямо признаёт, что ни разу не проверял самостоятельно), дело в том, что дискеты 1993 года хранили не чистую сборку, а снимок памяти уже поработавшей программы.
От готовой побайтово точной сборки модель двигалась «от кода к формату»: разбирала процедуры, которые читают байты уровня, а не наоборот. Так она без единой подсказки, в отличие от прошлогодней попытки с другой моделью, с первого раза правильно разобрала карты всех пяти уровней, перерисовала их по извлечённым данным и сверила попиксельно с эталонными скриншотами, которые автор сделал в 2020 году; после того как нашлись два пропущенных эффекта видеопроцессора Amiga (градиент неба и смена цвета воды), все пять уровней совпали без единого лишнего пикселя. Так же по крупицам восстановили: назначение битов свойств в каждой ячейке карты (какое число означает твёрдую землю, лестницу, смертельную ловушку или дверь, нигде не записано, но два разных участка кода читают одно и то же слово по-разному, и по ним удалось восстановить всю раскладку); таблицы объектов на экране; причину, по которой в самих данных карты дверей нет вообще, их рисует отдельный код поверх карты в момент открытия, и наивный перенос одних тайлов оставляет на их месте дыры; и неоднозначность формата листов со спрайтами (удвоенный размер кадра мог означать либо кадр вдвое шире, либо два ряда для двух направлений), здесь модель не угадывала, а прямо спросила автора, и тот подтвердил: это его собственное решение 1993 года, два ряда по направлениям.
Третий шаг, встроить версию 1993 года как отдельный запускаемый режим внутрь современной игры, автор ожидал на неделю работы с риском, что фичу вообще вырежут; вместо этого её сделали за один вечер. Скачиваемая современная игра не содержит кода Amiga: графику, звук и данные один раз раскодировали в обычные PNG, WAV и JSON, а поведение переписали на GDScript, собственном языке сценариев Godot; настоящий оригинал доступен отдельно, бесплатным образом диска для эмулятора. Порт получился не без ошибок: страж во втором уровне бил игрока сквозь сплошную скалу с тринадцати тайлов сверху, порт сохранил только нижнюю границу проверки дистанции до игрока, потеряв верхнюю; нашлись и другие мелкие баги вроде повторного засчёта прыжка на трамплине из-за перепутанного порядка обновления. Отдельно разбирались с жалобой «трамплин подбрасывает слишком высоко», дело оказалось не в физике, а в том, что Godot и старый iOS-билд по-разному определяют, отпущена ли кнопка прыжка. Самой дорогой оказалась просьба автора добавить фичу, которой в оригинале не было, обмен местами близнецов на любом расстоянии: без старой проверки дистанции их неактивные «статуи» на карте начали портить тайлы друг друга, и только тогда выяснилось, что убранная проверка с самого начала защищала именно от такого наложения, а не от «слишком далеко»; фичу в итоге вырезали.
После сборки модель сама провела публикацию: скриншоты для пяти размеров экрана на одиннадцати языках, ролик, тексты магазинов, иконки шести форматов, в Apple App Store, Google Play и Steam (для Steam, у которого нет API и множество полей в формах, через управление браузером); автору остались только вход в аккаунт и нажатие кнопок «опубликовать» и «назначить цену». Модель же прочитала отзывы Google Play (официальный API отдаёт только последние семь дней, а у игры, пятнадцать лет истории отзывов, поэтому использовали неофициальный сборщик отзывов) и отобрала те, что описывают реальные баги; среди них оказался однозвёздочный отзыв про дверь, которая «открывается, но уровень не заканчивается», как выяснилось, подсказка о завершении уровня стояла всего в двух из восемнадцати уровней игры, и именно её не хватало на последнем бесплатном уровне, из-за чего игрок перед решением о покупке утыкался в открытую дверь и решал, что игра сломана. Сам автор пятнадцать лет не замечал этот баг, не заметили его и тестировщики, и два предыдущих переноса игры; исправление вышло версией 2.0.3.
Спустя тридцать три года оригинал 1993 года вышел бесплатно на itch.io, образ диска для FS-UAE, WinUAE или настоящего железа. Современная «Babylonian Twins: Definitive Edition» уже доступна на iOS и Android, в Steam есть бесплатное демо, а полный релиз на Windows, Mac и Linux с версией 1993 года внутри запланирован на эту осень. Сам этот текст тоже начинался как черновик, который по заметкам и репозиториям автора написала модель, а он редактировал его целую неделю.
Ключевые факты
- Игру «Babylonian Twins» для Amiga 500 автор писал в Багдаде в 1993 году под санкциями, 512 КБ памяти, чистый ассемблер 68000, без интернета и документации кроме мануала по железу Amiga; дисковод от жары и смены дискет выходил из строя трижды.
- Claude Fable 5 в Claude Code перенесла на Godot и старый движок 2010 года (34 000 строк C++, играбельный персонаж за 21 минуту), и оригинальные 72 758 строк ассемблера 1993 года (26 файлов), вторую версию пересобрали так, что бинарники совпали с оригиналом с точностью до байта, а затем встроили как отдельный режим внутрь первой всего за один вечер.
- Без единой подсказки модель восстановила недокументированные форматы игры, карты уровней, битовые свойства тайлов, таблицы объектов, отсутствие дверей в данных карты, и сверила результат попиксельно с эталонными скриншотами автора 2020 года: после починки двух пропущенных визуальных эффектов все пять уровней совпали без единого лишнего пикселя.
- После сборки в порте были найдены и исправлены баги (страж бил игрока сквозь скалу с тринадцати тайлов сверху из-за потерянной верхней границы проверки дистанции), а модель провела публикацию в трёх магазинах приложений, включая чтение отзывов Google Play, так нашёлся баг, из-за которого подсказка о завершении уровня стояла всего в двух из восемнадцати уровней.
- «Babylonian Twins: Definitive Edition» уже вышла на iOS и Android, полный релиз в Steam с версией 1993 года внутри запланирован на осень, а сам оригинальный образ диска 1993 года спустя 33 года стал бесплатным на itch.io.
Почему это важно
Это подробный, проверяемый на уровне кода и байтов рассказ о том, что ИИ-агент способен сделать с грудой недокументированного легаси-кода за несколько дней, а не абстрактный бенчмарк. Год назад более ранняя модель разбирала всего один формат данных этой же игры за несколько заходов и с массой подсказок автора; Claude Fable 5 в Claude Code без единой подсказки с первого раза правильно разобрала карты уровней, битовые свойства тайлов, таблицы объектов и отсутствие дверей в данных карты, весь набор форматов 33-летней давности, для которых нет ни документации, ни второй копии на сверку, кроме памяти самого автора. При этом модель не просто писала код: она сама построила себе полигон для проверки, флаги для скриптованного прохождения уровней, автоматическую сборку и компиляцию, побайтовое сравнение пересобранных бинарников с оригиналом, попиксельное сравнение отрендеренных уровней с эталонными скриншотами, и довела процесс до публикации в трёх магазинах приложений.
Кому это важно
Тем, кто держит недокументированный легаси-код, старые игры, встроенные системы, любой продукт, чьи форматы данных нигде не описаны и нужны только их собственному автору. Автор «Babylonian Twins» прямо говорит, что его уровневый загрузчик, 1 652 строки ассемблера без единого комментария, был причиной, по которой он годами не лез внутрь и пользовался только hex-редактором; здесь модель прочитала именно такой код и восстановила логику по тому, как её использует остальная программа. Важно это и разработчикам, которые оценивают агентные кодинговые инструменты не по демонстрационным задачам, а по тому, вытягивают ли они многодневный проект с реальными неизвестными до конца, включая последующую публикацию продукта в магазинах приложений. И отдельно, сообществу сохранения ретро-игр: результатом стал не только современный порт, но и бесплатный выход оригинального образа диска 1993 года.
Как это применить
Прежде чем доверять модели незнакомый легаси-код, стоит повторить структуру этого эксперимента: сначала контрольная задача на уже известном материале (здесь, перенос движка 2010 года, который автор сам написал), и только потом, неизвестное. Там, где есть образцовые данные для сверки (выпущенные бинарники, эталонные скриншоты), их стоит использовать как жёсткий критерий «сошлось / не сошлось», а не полагаться на то, что результат «выглядит правильно», именно так модель поймала два пропущенных визуальных эффекта, которые иначе прошли бы незамеченными. При переносе между разными частотами обновления стоит отдельно проверять покадровые константы вроде коэффициентов трения, то, что тихо ломает ощущение от игры, не ломая сборку. И стоит явно резервировать за собой решения, для которых нужен контекст, которого нет в самом коде (здесь, восстановление неоднозначного формата спрайтов через прямой вопрос автору), а также последний шаг необратимых действий вроде публикации.
Можно ли доверять
Источник, личный блог автора игры, известный по обсуждению на Hacker News; независимой проверки самого текста нет. Часть утверждений в принципе проверяема (код, репозитории, скриншоты и таймстемпы автор называет настоящими), а сама механика рассказа построена на объективных сверках, побайтовое совпадение пересобранных бинарников с уже выпущенными в 1993 году, попиксельное совпадение отрендеренных уровней с эталонными скриншотами 2020 года. Но у истории есть открытое слабое место, которое автор называет сам: объяснение оставшихся примерно 108 байт несовпадения (что дискеты 1993 года хранили не чистую сборку, а снимок памяти уже поработавшей программы), это версия самой модели, и автор прямо пишет, что никогда не проверял её самостоятельно. Сам этот пост тоже не написан автором с нуля: черновик по его заметкам и репозиториям подготовила модель, а он редактировал его неделю.
Риски и подводные камни
Работа модели не была безошибочной ни на уровне кода, ни на уровне дизайна. При пересборке ассемблера она один раз неверно интерпретировала разворот счётчика адреса как обнуление зарезервированного блока, из-за чего часть файла сместилась на 944 байта, ошибку поймали и исправили той же побайтовой сверкой. В самом порте на Godot нашлось несколько игровых багов: страж во втором уровне бил игрока сквозь сплошную скалу с тринадцати тайлов сверху, порт сохранил только нижнюю границу проверки дистанции до игрока, потеряв верхнюю; из-за перепутанного порядка обновления врагов и игрока дважды засчитывался прыжок на трамплине; а один составной ключ от двери был прочитан как единственный несуществующий, из-за чего не открывался выход из обучающего уровня. Отдельная, более тонкая жалоба, «трамплин подбрасывает слишком высоко», потребовала другой диагностики: модель смоделировала оригинальную физику и убедилась, что константы перенесены верно (расчёт давал 19,1 тайла высоты против 19,5 измеренных), а настоящая причина оказалась в том, что Godot и старый iOS-билд по-разному опрашивают кнопку прыжка. Самой дорогой стала ошибка в совсем новой фиче, которой в оригинале не было: без старой проверки расстояния между близнецами их «статуи» на карте начали портить тайлы друг друга, и только тогда выяснилось, что убранная проверка защищала не от «слишком далеко», а именно от такого наложения, фичу пришлось вырезать. Наконец, ничего в процессе не сравнивало картинку современного порта с оригиналом автоматически и не проверяло, «ощущается» ли игра правильно, это целиком осталось на глаз автора и его сына.
«Часть, в которой я меньше всего уверен, это те 108 байт: модель сказала мне, что файлы поставки, это снимок памяти, сохранённый после того, как программа уже поработала, и что код записывает эти переменные раньше, чем их читает. Я прочитал это, пошёл дальше и с тех пор ни разу не проверил сам.»
— автор «Babylonian Twins», в посте о переносе игры на Godot