В старые времена GML был интерпретируемым языком, и код хранился в исполняемом файле в открытом виде. А возможно даже и с комментариями, по крайней мере скорость выполнения кода зависела от их наличия и количества. Так что декомпиляторов для GM8 было достаточно. С выходом GM:S (или 8.1) хорошие времена закончились – теперь YoYoGames встроили в исполняемый файл виртуальную машину собственного изобретения и GML компилируется в байт-код для неё. При этом формат байт-кода и файла периодически заботливо меняют.
Насколько мне известно, на данный момент для GM:S не существует инструментов для декомпиляции. Есть конечно распаковщики ресурсов (типа
Altar.NET), но они не производят никакого анализа и уж точно не генерируют код на GML. Таким образом, мой проект предназначен для того, чтобы закрыть эту нишу.
Итак, я сотворил прототип декомпилятора на С++.
Все желающие могут скачать его с репозитория и оценить, как он не работает. Для удобства я также подготовил архив с тестовым проектом, на котором декомпилятор точно не падает. Репозиторий временно не актуален, т.к. TortoiseHg не хочет создавать ветки на нём. Последний билд скачать бесплатно, без смсПринцип работыВ основе лежит алгоритм структурного анализа. Программа разбивается на базовые блоки – участки кода, которые не содержат инструкций перехода. Из них потом строится граф потока управления (flowgraph), где узлы – это собственно базовые блоки (ББ), а дуги – переходы между ними.

flow1.png (5.34 Кб. 214x300 - просмотрено 445 раз.)
Рис. 1. Граф потока управления.
Далее алгоритм просматривает поочередно все узлы, и если данный узел является точкой входа в один из шаблонов, то весь этот участок заменяется на абстрактный узел. Процесс заканчивается, когда на очередном проходе не удалось найти ни одного совпадения.
(При этом, если граф сводимый, то в нем останется только одна вершина).

templates.png (13.23 Кб. 752x278 - просмотрено 418 раз.)
Рис. 2. Шаблоны конструкций.

flowgraph_conv.png (39.78 Кб. 884x280 - просмотрено 467 раз.)
Рис. 3. Пример свертки.
Последний оставшийся узел содержит в себе дерево управления, оно же (в данной реализации) синтаксическое дерево. И на основе его уже генерируется код на GML.

ctrl_tree.png (11.68 Кб. 450x359 - просмотрено 451 раз.)
Рис. 4. Дерево управления.
История версий1.0.0- Решена проблема с break/continue в циклах. Кроме нескольких исключительных ситуаций – задачу сломать анализатор оставим читателям в качестве упражнения
- Решена проблема с префиксными/постфиксными инкрементами
- Добавлена поддержка операторов switch, repeat, with
- Добавлены параметры командной строки для управления декомпилятором
- Улучшено форматирование при генерации кода
0.1.0Основные проблемы- Невозможно создать шаблон для циклов, содержащих break и continue. Так что для их распознавания нужен другой метод.
- Отсутствие какого-либо анализа потока данных не позволяет нормально обрабатывать инструкцию dup, так как в этом случае на стеке оказывается две версии одной переменной, и все ломается.
Текущие возможностиСейчас декомпилятор может восстанавливать следующие конструкции:
- if, if-else
- while, for,
repeat-until do-until (for превращается в эквивалентный while) - Арифметические выражения любой сложности, с операторами разного приоритета и вложенными скобками. Иногда код после декомпиляции выглядит лучше исходного
- Аналогично, логические выражения (отдельный пункт, т.к. они представлены совершенно другим образом)
- Вызовы функций (в смысле скриптов) с любым количеством аргументов.
- +=, -=, *=, /=, …
- Массивы, в том числе двумерные.
- Обращение к полям объектов.
Все перечисленное может иметь любую сложность и глубину вложенности:
a.b.c[d.e || true, f.g.h && s[t, u && v]] = s || x && --lol; Работа над проектом будет продолжаться
, пока GMS2 не выйдет из беты. Так что даже есть шансы, что он будет закончен.