ИИ-агенты для реверс-инжиниринга


KORG DSN-12 на New Nintendo 3DS, Game Boy Color и KORG M01 на Nintendo 3DS, подключённые к шестиканальному аудиомикшеру

Проблема

KORG DS-10 – отличный виртуальный аналоговый синтезатор для Nintendo DS, но у этой игровой консоли 8-битный звуковой выход низкого качества. Позже KORG выпустили улучшенную версию синтезатора DSN-12 для новой игровой консоли Nintendo 3DS с 16-битным звуком. Но беда в том, что перенести сохранения из старой программы в новую невозможно.

Исследование

С другим синтезатором KORG M01 точно такая же история, но оказалось, что недавно один программист разобрался в формате файлов и написал конвертер. Я скачал исходники, сконвертировал несколько мелодий для M01, добавил несколько файлов формата DS-10 и DSN-12 и задумал направить ИИ на поиск общих паттернов. Оба синтезатора были написаны одними и теми же программистами, так что я исходил из гипотезы, что они применили схожие структуры данных.

Fable vs Sonnet

В самом начале я применил тяжёлую артиллерию – модель Claude Fable 5. На неё была возложена первая часть плана: по исходникам Mystievous сравнить форматы M01 и M01D, а затем разобраться в контейнерах DS-10 и DSN-12. Claude Code разложил сохранение DS-10 на слоты и хеши, научился распаковывать сжатые LZ11 мелодии DSN-12 и упаковывать их обратно, описал дерево полей и запрограммировал первую версию конвертера на Python. На этом месячный лимит закончился (за полчаса работы!), и мне пришлось переключиться на Claude Sonnet 5.

Гипотеза подтвердилась

Форматы файлов KORG DS нигде не описаны, поэтому вся работа – контролируемые эксперименты. Я готовил сохранения, отличающиеся изменением одного параметра, и скриншоты (DS-10 из эмулятора, DSN-12 с реального железа). Claude сравнивал файлы побайтно и пополнял описание формата. Как я и предполагал, между DS-10, M01 и DSN-12 оказалось много общего. Исходники конвертера M01 помогли быстро понять назначение многих байтов и дать им осмысленные названия.

Экран эффектов KORG DS-10: выбор и назначение эффектов Экран эффектов KORG DSN-12: параметры дилея, хоруса и реверберации
Параметры эффектов в DS-10 и DSN-12

Подбор контрольной суммы

В заголовке каждой мелодии DSN-12 лежит 32-битное слово контрольной суммы (CRC), и конвертер обязан считать её правильно. В M01 это просто арифметическая сумма байтов, но в DSN-12 изменение данных на единицу приводило к «случайному» (а не на единицу) изменению контрольной суммы, следовательно, алгоритм контрольной суммы сложней. Claude перепробовал больше десятка стандартных алгоритмов, но ни один не подошёл.

Сложность в том, что у CRC слишком много неизвестных: полином, начальное значение, финальный XOR, порядок битов и даже то, какие байты считаются. Одних только начальных значений и финальных XOR 2^64 сочетаний, больше восемнадцати квинтиллионов – брутфорсом не перебрать.

Тогда я сделал специальную тестовую пару файлов, в которой только один байт отличался на единицу (нота выше на полтона). У CRC есть красивое свойство: разность контрольных сумм двух файлов одной длины равна контрольной сумме разности самих файлов. Начальное значение и финальный XOR из этого уравнения выпадают, остаётся перебор полиномов. Claude написал скрипт для подбора и нашёл ровно один подходящий вариант: 0x04C11DB7 – тот же, что в Ethernet и ZIP (только без зеркалирования битов).

Остальные константы Claude нашёл решением системы линейных уравнений по двум мелодиям разной длины. Финальный XOR оказался банальным 0xFFFFFFFF (просто инверсия). Начальные значения определились как символы «mfsd» для каталога и «dxsd» для мелодий.

Микшер KORG DSN-12: шесть каналов с посылами на эффекты, фейдерами громкости, mute и solo Экран коммутации KORG DSN-12: источники модуляции соединены со входами виртуальными кабелями

ИИ ошибается

По какой-то причине Claude решил, что значения панорамы (лево-право) в микшере закодированы зеркально, вразрез со всеми остальными органами управления в программе. Это очень странно. К чести ИИ надо сказать, что он сам заметил странность и предупредил о ней. Проверка на реальном железе выявила ошибку – не нужно было ничего зеркалировать.

Также Claude хотел округлять и квантовать все переменные, чтобы получилось как на тестовых мелодиях. Пришлось убрать округление.

Кажется, всплыл баг, допущенный создателями синтезатора: при удалении из партитуры барабана программа стирала параметры ноты, но в другом месте оставался неочищенным бит, отвечающий за присутствие ноты. KORG DS-10 в этом случае игнорировал ноту, а KORG DSN-12 играл (с параметрами по умолчанию). Пришлось добавить в конвертер подчистку не полностью удалённых нот. Ошибка ИИ в том, что он не уловил связи между данными и не увидел противоречия в тестовом файле.

У синтезатора DSN-12 больше параметров для инструмента, и конвертер выставлял «лишним» параметрам значение 0, не задумываясь об их смысле. Хотя названия параметров были написаны в интерфейсе, и можно было бы догадаться, что при нулевых значениях звука не будет вообще. Пришлось объяснять, какие значения по умолчанию нужно выставлять.

Claude преувеличил число возможных звуковых каналов в DS-10 просто потому, что до конца файла оставалось свободное место и оно было точно кратно длине записи о канале. А на самом деле у всех файлов сохранений просто фиксированная длина 256 килобайт.

Пошаговый секвенсор KORG DSN-12: сетка из 16 шагов с нотами на пианоролле Экран клавиатуры KORG DSN-12 в режиме записи

Результат

Теперь мои старые 8-битные мелодии зазвучали в 16 бит! Конвертер выложен на GitHub (около 600 строк на Python, без зависимостей).

Основная работа была выполнена за день. Ещё день ушёл на доводку: выявление расхождений на реальном железе, прояснение формата, упущенные параметры, документация и публикация на GitHub. Плюс эта статья. Я много раз проводил реверс-инжиниринг в прошлом, и по собственному опыту могу сказать, что без ИИ такая работа заняла бы в 2–3 раза больше времени.

Репозиторий KORG-DS-10-to-DSN-12-converter на GitHub