Оригинальная Snowboard Kids теперь декомпилирована на 100%: все функции1 получили C-реализации, которые при компиляции дают машинный код, идентичный оригинальной игре.

Проект был явно не одиночным. Отдельная благодарность inspectredc, Bl00D4NGEL и queueRAM за значительный вклад — никакой ИИ не смог бы их заменить.2 Также стоит поблагодарить iFuzzle, JamesBLewis и douglasjv, предоставивших свои токены для дела.

Полная декомпиляция должна оказаться полезной для сообщества Snowboard Kids. Спидраннеры давно фокусируются на первой части серии. Рабочий исходный код поможет прояснить внешне наблюдаемые явления — например, пути движения CPU-соперников и точные факторы, влияющие на скорость игрока. Полное понимание исходников также пригодится для статической рекомпиляции и более амбициозных модификаций в будущем.

Скорость, с которой был завершён проект, тоже заслуживает внимания. На декомпиляцию Snowboard Kids ушло всего 84 дня против 596 дней для Snowboard Kids 2 — примерно в семь раз быстрее.3

график еженедельного прогресса декомпиляции Snowboard Kids

Еженедельный прогресс декомпиляции Snowboard Kids.

Чем объясняется такая разница? Дело происходит в 2026 году, так что ответ хотя бы отчасти связан с ИИ. Но было бы серьёзным упрощением списывать всю разницу исключительно на LLM.

Что было по-другому

Очевидно, что старт был не с нуля. К этому моменту на аналогичном проекте уже было потрачено почти два года, и скорость работы выросла многократно по сравнению с началом пути. Это преимущество трудно измерить количественно, и оно отчасти компенсировалось новыми сложностями — например, работой с другим компилятором.

В целом примерно 4,8% коммитов с совпадением потребовали вмешательства экспертов.4 Благодарность этим людям уже прозвучала выше, но её стоит повторить: проект не состоялся бы без значительной помощи сообщества декомпиляции, особенно inspectredc, queueRAM и Bl00D4NGEL <3.

Сложность обычно возникала не в том, чтобы понять, что делает функция5, а в том, как эта логика была выражена на C и как получившийся код был скомпилирован. Snowboard Kids компилировалась с помощью IDO 5.3, а не GCC 2.7.2, который использовался для Snowboard Kids 2.

Большинство программистов знакомы с GCC — широко используемым open-source компилятором, который активно развивается и сегодня. IDO же был проприетарным компилятором от SGI, чья история тесно переплетена с историей Nintendo 64.6 Его исходный код никогда не публиковался, а оригинальная среда разработки была привязана к устаревшему оборудованию и ПО SGI. Чтобы использовать и по-настоящему понять его сегодня, сообществу декомпиляции пришлось реверс-инжинирить и декомпилировать части набора инструментов компилятора, а также статически рекомпилировать наборы IDO 5.3 и 7.1 для запуска на современном железе. Эта закрытая история делает IDO сложнее для анализа, чем открытый компилятор вроде GCC.

IDO разбивает оптимизацию и генерацию кода на несколько разных проходов, довольно агрессивно преобразуя код по пути.7 Крошечные изменения в C-коде могут затем распространиться через эти проходы и привести к совершенно другому распределению регистров.

Сообщество добилось больших успехов в понимании IDO и его особенностей, но это остаётся скорее искусством, чем наукой. Ни LLM, ни человек не особо хороши в воспроизведении его вывода. Обычный рабочий процесс — как для человека, так и для агентов — заключался в том, чтобы понять, что делает функция, а затем написать C-код, приближённо реализующий эту цель. Дальше небольшие правки с помощью permuter могли устранить оставшиеся различия. Но не во всех случаях можно перебором прийти к совпадению — особенно когда сама структура кода неверна. Поведение IDO делало этот процесс значительно менее предсказуемым.

Мотивированная человеческая команда с нужной экспертизой и интуицией может сравняться по темпу с декомпиляцией Snowboard Kids или даже превзойти его. Декомпиляция Pilotwings 64 была завершена всего за 74 дня.8 В Pilotwings 64 было на 16% меньше функций, чем в Snowboard Kids, но больше скомпилированного кода в целом, так что и это сравнение не совсем чистое.

скриншот Pilotwings 64

Pilotwings 64 — очаровательный авиасимулятор, стартовый тайтл Nintendo 64, который до сих пор остаётся культовой классикой.

Snowboard Kids также была меньше своего сиквела: 2145 функций против 2995 в Snowboard Kids 2. Количество функций — грубая мера сложности, но фактически декомпилировать нужно было меньше кода.

Где агенты действительно помогли

Об использовании агентов для декомпиляции функций уже рассказывалось ранее, и базовый процесс здесь был тот же самый, так что стоит остановиться на том, что изменилось. В отличие от предыдущего проекта, этот начался сразу с доступом к передовым моделям и работоспособной оснасткой для агентов.

Библиотечный код и другие простые случаи

Было интересно посмотреть, как агенты справятся на ранних стадиях проекта. Одна область, где они преуспели, — сопоставление кода стандартных библиотек. Теоретически это самый очевидный кусок практически любой декомпиляции для Nintendo 64: такой код не уникален для конкретной игры, и его версии доступны в открытом доступе. Snowboard Kids содержит более сотни исходных сегментов из библиотеки Nintendo libultra, а также функции из аудиобиблиотеки libmus. Инструменты вроде N64Sym способны находить вероятные библиотечные функции прямо в ROM.

Этот проход прошёл довольно успешно. Основной трудностью было убедить агентов опираться на существующий исходный код библиотек, а не декомпилировать те же функции заново с нуля. Это потребовало более настойчивых промптов. После обнаружения вероятной библиотечной функции агентам предписывалось использовать соответствующий исходник как отправную точку и перебрать правдоподобные версии SDK, опции компилятора и пути условной компиляции, прежде чем пробовать собственную реализацию.

Ещё одной оптимизацией стало поручить агенту написать скрипт, который запускал m2c против каждой несовпадающей функции и автоматически интегрировал точные совпадения, вместо того чтобы полагаться на попытки агентов разбирать эти функции по одной.9 Скрипт нашёл совпадение лишь для 17 из 1830 функций — крайне низкий показатель успеха в 0,93%, но всё найденное таким способом обходилось дешевле, чем расход токенов агентов.

Инструментарий и навыки работы с IDO

IDO странный, но часто странный по повторяющимся причинам. Успешное совпадение одной функции могло выявить особенность компилятора, применимую ко многим другим. Codex стал лучше переносить уроки между задачами благодаря таким функциям, как локальная память. Чтобы сделать эти уроки доступными за пределами одного агента, агентам предписывалось фиксировать наблюдаемое поведение IDO в файле DECOMPILATION_LEARNINGS.md. Обнаружив обобщаемую особенность компилятора, агент мог записать туда доказательства для последующих попыток. Так возник полезный цикл обратной связи: агенты помогали документировать IDO, а получившаяся документация делала следующих агентов лучше в сопоставлении кода IDO.

Но самым полезным ресурсом оказался N64 Decomp Workbench — набор инструментов и документации для отладки несовпадений на поздних стадиях декомпиляции MIPS-кода. Он умеет классифицировать несовпадения, учитывать релокации, воспроизводить отдельные проходы компилятора и помогать отличить структурную проблему от проблемы распределения регистров. Воспроизведение проходов требует соответствующих бинарников компилятора и настройки под конкретный проект, но после настройки этот инструмент раскрывает информацию, недоступную из простого diff'а ассемблера. Обычный diff говорит лишь, что две функции отличаются. Workbench же может дать агентам куда более точное представление о том, почему функции отличаются и какое изменение может это исправить.

Worktree и синхронизация

Для этого проекта оснастка декомпиляции запускалась параллельно на четырёх Git worktree. Каждый worktree давал агенту независимую копию репозитория, что позволяло пробовать несколько функций одновременно.

Одним небольшим, но полезным улучшением стало назначение явного дедлайна для каждой задачи с передачей этого дедлайна агенту. Во время проекта Snowboard Kids 2 агенты часто испытывали трудности с эффективным использованием permuter, поскольку тот работал до нахождения 100% совпадения или ручной остановки. Явный дедлайн позволил агентам устанавливать разумные тайм-ауты и балансировать время на перебор с другими способами решения задачи. По ощущениям, это также помогло агентам определять, сколько времени стоит потратить на сложную функцию, прежде чем отступить. Затем допустимое время можно было увеличивать по мере того, как простые функции заканчивались, а оставшаяся работа усложнялась.

Ещё одна проблема, существовавшая ещё в Snowboard Kids 2, но ставшая заметнее с добавлением worktree — синхронизация. Как обсуждалось в предыдущей заметке, каждому агенту давалась функция для декомпиляции вместе с набором похожих уже сопоставленных функций. Они служили полезными опорными точками для воспроизведения конкретных паттернов инструкций IDO. Работа делилась между worktree с помощью опции --shard в Nigel, которая использует базовое хеширование для распределения кандидатов между заданным числом воркеров.

Это позволило выполнять больше работы параллельно без дублирования, но породило новую проблему по мере расхождения worktree. Например, один worktree мог успешно декомпилировать функцию, на 99% похожую на функцию, которую пытался разобрать другой агент, — но новый эталон оставался невидимым для другого агента до слияния изменений. Периодическое слияние всего в основную ветку и ресинхронизация worktree решали проблему, но синхронизация всех четырёх могла занимать больше часа. Постоянная синхронизация впустую тратила время, а слишком долгое ожидание увеличивало расхождение.

Чтобы снизить критичность синхронизации, поиск похожих функций был обновлён так, чтобы проверять каждый worktree. Только что сопоставленная функция могла сразу же стать эталоном для другого агента, не дожидаясь попадания в основную ветку. Оснастка выдавала сообщения вроде следующего.

1✓ Candidate ["func_80094A94", "func_80094FF4 (../sbk-c)",
2  "func_80094808", "func_8009491C (../sbk-a)",
3  "func_8009469C (../sbk-c)", "func_80093144"] was fixed!

Это помогало процессу оставаться эффективным по мере исчезновения простых функций. Синхронизация по-прежнему требовалась для консолидации и отправки изменений, но больше не была нужна, чтобы агенты учились друг у друга.

Выбор моделей

Были опробованы GPT-5.5 и 5.6, Claude 4.5 и Fable, а также GLM 5.2 — совершенно ненаучным образом. Модели тестировались на меняющемся наборе сложных функций, иногда уже после того, как другая модель добилась частичного прогресса. В целом Codex продолжал превосходить Claude, как и к концу предыдущего проекта. Sol xhigh оказался особенно эффективным, как только стал доступен.

GLM 5.2 от z.ai сильно разочаровал. Раньше эта модель нравилась — она была эффективна, пусть и не совсем на уровне передовых моделей, а щедрые лимиты использования компенсировали разрыв. Этот компромисс стал куда менее привлекательным, когда лимиты стали жёстче, а задержки остались ужасными. Циклы обратной связи были настолько долгими, что работу для этой модели прекратили, а подписку в итоге отменили.

Что дальше

Ближайший приоритет — лучше задокументировать игру. 100% совпадение означает наличие C-кода для каждой функции, но не означает понимания того, что каждая функция делает. Остаются сгенерированные имена для замены, неизвестные поля структур для идентификации, неуклюжие совпадения для чистки и большие объёмы данных для описания.

Также ведётся работа над рекомпиляцией Snowboard Kids. К счастью, первая игра разделяет многие особенности, уже устранённые патчами в Snowboard Kids 2: Recompiled.

ранний скриншот Snowboard Kids: Recompiled

Рассматривается перенос уровней и другого контента из первой игры в движок второй, хотя пока неясно, сколько работы это потребует.

Помимо этого, есть интерес к декомпиляции Snowboard Kids Plus для PlayStation — эксклюзивного для Японии расширенного издания первой игры с дополнительными уровнями и персонажами.

Если вы дочитали до этого места, вас, вероятно, интересует декомпиляция и Snowboard Kids. Загляните в проект декомпиляции Snowboard Kids. Там ещё немало работы по чистке и документации, и вклад со стороны всегда приветствуется.

  1. Почти. Небольшое количество написанного вручную ассемблерного кода из системных библиотек остаётся, поскольку ассемблер был оригинальным исходным кодом, а не временной заглушкой декомпиляции. ↩︎

  2. В лучшем случае проект, вероятно, застрял бы на отметке 89–90% без их экспертизы по IDO. ↩︎

  3. Для Snowboard Kids 2 отсчёт вёлся от первого коммита 28 сентября 2024 года до последней сопоставленной функции 17 мая 2026 года — 596 дней. Цифра в 84 дня для Snowboard Kids — это подсчёт на уровне проекта; сам публичный репозиторий охватывает период от первого коммита 28 мая 2026 года до последней сопоставленной функции 19 августа 2026 года — чуть больше 83 дней. ↩︎

  4. На основе ручного анализа истории Git было выявлено примерно 41 совпадение с помощью экспертов, что составляет около 4,8% коммитов, классифицированных как работа по сопоставлению функций. Эта ретроспективная классификация приблизительна, поскольку коммиты могут содержать несколько функций, помощь часто встраивалась в собственные коммиты, а цифра не измеряет человеко-часы. Здесь автор себя «экспертом» не считает. ↩︎

  5. Одним заметным исключением стала validateControllerPakSave, которая, судя по всему, использовалась для отладки сохранений на Controller Pak. Большая часть её отладочной и проверочной логики была исключена из финальной сборки. ↩︎

  6. Nintendo рассказывала о заимствовании архитектуры Silicon Graphics для Nintendo 64. Оригинальная система разработки была во многом ориентирована на SGI. Документация Nintendo по разработке описывает подключение платы эмулятора к рабочей станции SGI Indy, а IDO был одним из поддерживаемых компиляторов. Таким образом связь распространялась от базовой архитектуры консоли до машин и инструментов, использовавшихся для разработки её игр. ↩︎

  7. IDO использовал многоэтапный конвейер компиляции. Документация к uopt гласит, что подходящие циклы по умолчанию разворачивались в четыре раза. Совпадение: четыре — это также число гонщиков в игре. Циклы с четырьмя итерациями, соответственно, становятся кандидатами на полное разворачивание, и встречаются они часто 🫠. ↩︎

  8. Отсчёт от добавления отслеживания прогресса 26 января 2026 года до финальных сопоставленных функций 10 апреля 2026 года дал почти ровно 74 дня декомпиляции. В Pilotwings 64 было 1791 функция против 2145 у Snowboard Kids, но примерно 838 КБ кода против 732 КБ у Snowboard Kids. ↩︎

  9. Использование одноразового скрипта такого рода — идея не особо новая. Скорее всего, она была позаимствована откуда-то, возможно, из m2c_all.sh для Diddy Kong Racing. ↩︎