Про мифы касательно ГМО здесь уже писали. В дополнение к этому я хотел бы поделиться отличной аналогией с разбором реальных примеров из области реверс-инжиниринга и модификации машинного кода, что будет понятно и близко именно программистам.
«Мутации» машинного кода
В качестве примера возьмём приставку NES (известную у нас как Dendy), в которой используется процессор 6502. Система команд у него очень проста — опкод представлен всегда одним байтом, и каждый из 256 хоть что-то, да делает. Никаких «защит» от дурака не предусмотрено, и почти любой случайный набор байт будет выполняться без сопротивления со стороны процессора. Таким образом, мы можем взять ROM какой-нибудь игры, исправить в нём случайные биты (будем называть это «мутациями») — и после запуска наблюдать забавные глюки в разных неожиданных местах, но при этом в целом игра скорее всего будет работоспособной. Похоже, что на YouTube имеется целый жанр подобного видео. Полученный таким образом машинный код наверняка не очень корректен, но в большинстве случаев процессор сможет его выполнить и что-то сделать.
Как оказалось, такую методику используют не только для веселья (а играть в знакомые игры с неожиданными глюками весьма забавно), но и для полученя вполне себе конкретных модификаций: делают большое количество «мутантов» и ищут тот, в котором проявился нужный эффект. Точь-в-точь как в современных методах селекции, когда зародыши организмов подвергаются воздействию мутагенов (что приводит к случайным изменениям в генетическом коде), а потом из того что смогло вырасти отбираются те, у которых есть нужный признак. Полученные таким образом организмы получают в довесок массу других нежелательных мутаций. Избавляются от них путем постепенного скрещивания c нормальным видом, добиваясь получения более-менее вменяемого организма с нужным признаком и минимумом других мутаций, которые оказались заметны. То же самое можно сделать и с машинным кодом.
«Генная инженерия» на машинном коде
В качестве прямой аналогии здесь напрашивается реверс-инжиниринг. Мы изучаем машинный (двоичный) код, разбираемся как он работает (целиком или только некоторые его части), после чего вносим именно те изменения, которые наверняка приведут нас к целевому эффекту.
У программистов существует огромное количество инструментов для анализа машинного кода (всевозможные дизассемблеры, отладчики и тому подобное). Не глядя на то, что сам по себе машинный код не предназначен для чтения человеком, он был придуман людьми и задокументирован, так что создание инструментов для преобразования его в более понятный вид (ассемблерный листинг) не было проблемой. Также практически любая исследуемая программа скорее всего тоже была написана человеком, поэтому то что делает её код обычно выглядит логичным и понятным.
Понятное дело, что генетикам гораздо сложнее. Нет никакой официальной документации, которая могла бы пролить свет на все возникающие вопросы. Генетический код был «написан» волей случая и отобран по принципу «смогло ли оно выжить, приспособиться и дать потомство», поэтому наверняка он далёк от логичного и оптимального, скорее даже любая придуманная нами обфускация программного кода покажется просто детским лепетом. Тем не менее это не значит, что генетический код невозможно изучать и пробовать его изменять.
Предыстория
Для меня Dendy всегда была чем-то большим, чем просто приставкой. Я не только играл в неё, но и значительное время провёл внутри неё с паяльником в руках для некоторых простых модификаций. По дороге куда-нибудь я часто размышлял о том, как же создаются эти игры и как это работает внутри. Наверняка, многие из вас тоже когда-то задавались подобными вопросами, такова уж натура будущих IT-шников.
Прошли годы. С некоторой периодичностью погружался в эму-тему, изучая всё новое на тематических сайтах, но я не решался окунуться в изучение ассемблера 6502 и архитектуры NES. Внутренний конфликт рационального и иррационального. Я долго убеждал себя, что мне не нужно тратить на это время, но… сорвался. Глядя на то, какие интересные вещи делают энтузиасты эму-сцены, я взялся за свою давнюю идею со светлой мыслью: «Я тоже смогу!».
Наверняка многие из вас помнят картриджи типа «9999-in-1», которые были примечательны красивым меню с романтическим сюжетом у моря, летающими чайками и приятной музыкой (Unchained Melody). Я дизассемблировал это меню и сделал на его основе трибьют-демку Unchained Nostalgia.
Основная идея — никакого списка игр, а слайды переключаются под музыку. В освободившемся небе я нарисовал осмысленные облака и звёзды; реализовал автоматическое переключение слайдов синхронно с музыкой и возможность ручного переключения; добавил автокоррекцию скорости воспроизведения и высоты звука для систем, отличных от Dendy (ведь это меню делалось именно для китайских фамиклонов, а они отличались от оригинальных NES, из-за чего оригинальное меню работает слишком быстро на NES NTSC, а на NES PAL получается слишком низкий звук); не устоял и перед соблазном добавления целого ряда любопытных пасхалок. То есть используемый подход ничем не ограничивает фантазию и позволяет в принципе вносить любые изменения за какое-то конечное время.
Однако, похожие идеи приходят в голову разным людям
Уже после релиза своей демки я обнаружил, что кто-то тоже пробовал реализовать эту же идею. Автор указал, что он использовал «corruptor», который обычно используется для создания испорченных версий игр с различными глюками.
Если бы мне раньше кто-то сказал, что подобный «случайный» метод реально используется для модификации машинного кода с нужными эффектами — я бы наверняка не поверил. Ведь для этого нужно уйма времени и удача. Хотя с другой стороны нет необходимости изучать и понимать машинный код. Поскольку у меня в руках уже был «живой» пример подобного хака, ничего не оставалось, кроме как исследовать его работу.
Слайды переключаются автоматически, примерно каждые 2 секунды (что слишком быстро). Ручного управления нет. При смене слайда экран почему-то мерцает дважды. Главное, что оно работает! Но каким образом?
Следы хирургического вмешательства
В картридже программный код и тайлы для графики хранятся раздельно. Код — в PRG ROM, тайлы — в CHR ROM. Второй может быть легко изменён с использованием стандартных инструментов, по этой причине для Dendy существует огромное количество графических хаков известных игр, где код оставлен абсолютно без изменений.
Сравним CHR ROM оригинального меню и исследуемого хака:
На лицо следы прямого «хирургического» вмешательства. По какой-то причине были вырезаны тайлы цифр, точки и маленькой чайки. Попробуем вернуть оригинальный CHR ROM и посмотрим, что именно было скрыто таким образом.
Теперь стало немного понятнее. В программном коде был сломан ввод, из-за чего менюшка думает, что кнопка «вниз» всегда нажата. Также был сломан вывод названий игр. Видимо, сломать вывод номеров игр и маленькой чайки (это курсор, указывающий на выбранную игру) не получилось, поэтому их пришлось прятать вырезанием соответствующих тайлов в CHR ROM.
… и немного магии!
Копаем глубже. При помощи дизассемблера посмотрим, что именно делают исправленные в PRG ROM байты.
Код оригинала | Код хака |
---|---|
NMI: |
NMI: |
Код оригинала | Код хака |
---|---|
LDA #0 |
LDA #0 |
Код оригинала | Код хака |
---|---|
ASL A |
ASL A |
Выводы
Вы смогли прочувствовать, как всё «лихо закручено» в модификациях, созданных подобным «случайным» образом? Одна поломка подпирает другую поломку, и оно как-то в целом даёт результат, близкий к нужному. При этом появляются просто невероятные зависимости между случайными и на первый взгляд никак не связанными участками кода, и при малейших дальнейших модификациях (даже самих по себе корректных) всё может рухнуть. Полноценный реверс-инжиниринг гораздо надёжнее. То же самое можно сказать и о генной инженерии, в сравнении с традиционной селекцией.
Ссылки на файлы
- unchained_nostalgia.zip — демка Unchained Nostalgia, созданная методами реверс-инжиниринга.
- guyver_hack.zip — исследуемый хак, созданный «случайным» образом, и его исходный ROM.
Поделиться с друзьями
VEG
Если вы хотите поразвлекаться, создавая случайные глюки в ваших любимых играх для Dendy, могу предложить вам небольшую программу на C#, которая предназначена именно для этого. Программа учитывает особенности формата iNES и вносит случайные изменения только в программный код.
Для использования нужно запускать в консоли команды вида:
mutator in.nes out.nes keyword 100
, где keyword используется как randseed (то есть для одного и того же слова будет один и тот же набор случайных мутаций), а число задаёт количество мутаций (конкретно сколько байт будет испорчено).pehat
Поделюсь балалайками (которые, в свою очередь, узнал от Mrrl). Ежели у Вас селекция, то у нас — ампутация. При нахождении в ассемблерном коде подпрограммы непонятного назначения можно заNOPить ее вызов и посмотреть, что отвалилось. Иногда это убивает работоспособность всей программы, иногда вызывает забавные глюки, но после удачного применения такой хитрости становится проще понять назначение подпрограммы.
VEG
Всё же «ампутация», на мой взгляд, больше подходит к отрезанию каких-то внешних вещей, не относящихся непосредственно к коду. В статье выше упоминается удаление некоторых тайлов в CHR ROM для того, чтобы сделать нарисованные ими элементы невидимыми.
Не понял, почему вы говорите, что у меня селекция. Я сам занимался именно реверс-инжинирингом оригинальной менюшки, и в статье об этом сказано. Поскольку кода было немного (всего 16 килобайт), получилось разобраться в её работе на 100%, и на её основе сделать демку.pehat
Не совсем ясно выразился. «У Вас» — это относилось к описанному у Вас в статье методу другого товарища, который занимался селекцией.
Neftedollar
Как же теперь легко будет матери объяснить пользу ГМО. Спасибо.
ValdikSS
Заходил несколько дней назад к вам на сайт, увидел обновление к Unchained Nostalgia, думаю, наверняка скоро и интересная статья появится, и вот она!
Есть какие-то предположения, сколько потребовалось проб и ошибок для создания такого хака? Это все, полагаю, вручную проверялось?
VEG
Сколько именно времени ушло на создание хака — не знаю. Но его автор выкладывает и другие подобные хаки. Например, вот пачка странных хаков игры Battle City. На мой вопрос автор этого хака ответил лаконично:
Потом в процессе разговора он уточнил суть используемого им метода: Видимо, «случайные» правки всё же как-то были приправлены интуицией. Как видно, использованная программа позволяет задавать некоторые правила для «мутаций»:Я сам в детстве (15 лет назад) просто исправляя в HEX-редакторе байты, которые мне просто «не нравились», умудрился снять требование регистрации в одной из вариаций игры «О, счастливчик!» (я писал свой вариант этой игры, и взламывал «конкурента», который тоже был написан школьником). Просто очень сильно повезло. Плюс много терпения и сотни перезапусков с разными исправлениями :)