View Page Source

Back to Page
Revision 8 (current)
Edited by adelikat on 8/29/2023 12:23 AM
%%TOC%%

''"Искусство ТАС стало чем-то большим, нежели просто играть в игру. ТАСинг сделался игрой сам по себе, и мы идем еще дальше, создавая вещи, которые играют в эту игру за вас. Своего рода, метаигра. Ее лучшие игроки знают, как нарушить все правила, и это требует глубокого понимания как архитектуры, особенностей игры, так и инструментов для взаимодействия с ней."'' - [Forum/Posts/389519|ТРУЪ].

!! Предисловие

[http://ru.wikipedia.org/wiki/%D0%9E%D0%B1%D1%80%D0%B0%D1%82%D0%BD%D0%B0%D1%8F_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0|Обратная разработка] - исследование некоторого готового устройства или программы, а также документации на него с целью понять принцип его работы; например, чтобы обнаружить недокументированные возможности (в том числе программные закладки), сделать изменение, или воспроизвести устройство, программу или иной объект с аналогичными функциями, но без копирования как такового.

В старые ламповые времена, создание ТАС сводилось к экспериментам над игрой в попытках пройти ее неизвестным прежде способом. Это было довольно ново, и потому работало. Но приходили все новые люди, делались ТАСы по все новым играм, старые прохождения постоянно обгонялись, и сообщество в итоге развило новый стандарт ТАСинга, значительно превосходящий прежний. Это был естественный процесс, по двум основным причинам:
* Уровень оптимизации постоянно возрастал, обнаруживались и применялись новые трюки, улучшались старые.
* Развлечь зрителей становилось все сложнее, коль скоро за годы они повидали уже столько всего, что ТАСам всегда нужно было находить новые необычные идеи ради улучшение развлекательности.

Сегодня, чтобы сделать мувик, полностью отвечающий современным стандартам ТАС, стало необходимо применять к проходимой игре самые продвинутые методики. А именно - детально разбираться во внутренних механизмах игры и применять эти знания непосредственно при создании ТАС.

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

''Примечание: настоящее руководство изложено в контексте наиболее мощного в части обратной разработки эмулятора - FCEUX. Однако, опыт, полученный с его помощью, может быть эффективно применен в отношении любых других платформ/эмуляторов, для которых существуют аналогичные инструменты.''

!! Области памяти (RAM)

''Примечание: Используйте встроенный во FCEUX шестнадцатеричный редактор, чтобы обозревать память RAM в ходе игры. Команда меню "Debug -> Hex Editor". Также будет полезно сразу отрегулировать размер окна, чтобы единовременно отображалось 16 строк (1 страница памяти).''

В диапазоне адресов от $0000 до $00FF располагается нулевая страница (Zero Page). Игры размещают там временные переменные, которые очень часто меняются, или те, к которым необходим самый быстрый доступ; очень часто одни и те же адреса в пределах Zero Page отражают значения массы несвязанных между собой переменных из основной памяти. В связи с чем эти самые адреса, пусть даже если в них можно стабильно находить реальные данные, все равно не надежны. Необходимо искать реальные адреса, где на самом деле хранятся данные о состоянии RAM игры, и которые не заполняются посторонней информацией.

В диапазоне $0100 - $01FF располагается Стек, который также используется для данных временного характера.

Третья страница часто отводится под данные о спрайтах, что можно заметить, наблюдая, как там меняются значения.

А вот дальше уже идут настоящие данные об игровом процессе, из которых можно многое узнать. Существует ряд довольно типичных способов размещения этих данных. Не считая всяких особо хитрых счетчиков и прочего, практически каждая игра хранит состояние объектов в различного вида массивах.

!! Объекты

Термин говорит сам за себя. Реализованные в игре сущности, взаимодействующие друг с другом и окружением, принято называть объектами. Как правило, все они обладают неким общим набором атрибутов. Для их хранения можно организовать виртуальную таблицу, где сами объекты будут представлены рядами, а их атрибуты - столбцами. Если вы разберетесь в адресах, соответствующих атрибутам тех или иных объектов, то ---Матрица откроет вам свои тайны--- вы увидите систему.

Вышеназванная гипотетическая таблица не так уж далека от того, как объекты на самом деле размещаются в памяти. Начинаться сия структура может с массива идентификаторов объектов, располагающихся в свободных слотах. Потом - массив из идентификаторов спрайтов для них. А может - какой-нибудь номер состояния объекта, от которого зависит его поведение. И в дополнение ко всему - пространственные координаты, обычно из 2-3 переменных каждая. Типичный набор таков:
* X - младший байт
* X - старший байт
* X - субпиксельная позиция
* Y - младший байт
* Y - старший байт
* Y - субпиксельная позиция
Порой имеется и координата по оси Z. Также ситуация может различаться в зависимости от того, является ваш персонаж элементом общей карты объектов или обладает уникальными атрибутами, адресуемыми отдельно.

Какие-то игры отслеживают положение объектов по абсолютным координатам в рамках уровня. А какие-то - чисто в зависимости от положения игровой камеры. Координаты X и Y для камеры тоже могут занимать по паре байт и обычно хранятся отдельно от основного массива объектов. Это позволяет получить истинное положение объекта на экране путем вычитания их абсолютных координат из координат камеры. А некоторые игры просто хранят данные о положении на экране отдельно, но такие данные ненадежны.

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

Вам потребуется определить, что - ряды, а что - колонки. Некоторые игры представляют слоты в виде колонок, а атрибуты располагают рядами. А некоторые хранят атрибуты сразу за идентификатором, тем самым делая слоты рядами, а атрибуты строя в колонки. Бывает еще так, что игра форматирует таблицу на манер того, как показывает данные HEX-редактор, к примеру, резервируя 8 или 16 слотов под объекты, или давая каждому из них по 16 атрибутов. Такая таблица объектов легко различима на глаз.

Разобравшись с назначением некоторых частей таблицы, вам уже нет нужды искать все атрибуты вручную, достаточно наблюдать изменения в ячейках памяти и делать выводы об их реальном назначении, например:
* Младший байт для X координаты растет от 0 до 255 и снова сбрасывается в 0, увеличивая старший байт.
* Координата X для позиции на экране замирает, когда персонаж достигает точки, где экран начинает прокручиваться вслед за ним.
* Здоровье уменьшаются при получении объектом урона (хотя иногда наоборот - полученный урон аккумулируется в счетчике). 
* Скорость часто также показывает направление (принимая положительные или отрицательные значения) и меняется при ускорении.
* Субпиксельные позиции интенсивно меняются, когда скорость растет или уменьшается, замирают или колеблются между парой значений, когда скорость постоянна.
* Идентификатор объекта появляется в слоте вместе с вводом объекта в игру и не обнуляется, пока последний не исчезнет.
* Значения таймеров уменьшаются или увеличиваются на один до наступления определенного момента, и иногда можно увидеть, наступление каких событий отслеживается.

Какие-то игры реализуют боссов, как обычные объекты, а какие-то хранят их атрибуты отдельно от прочих. Вам потребуется найти их: здоровье, таймер неуязвимости, позиция, состояние/направление движения. Это позволит понять их действия и найти способ их контролировать, или, по меньшей мере, отслеживать.

!! Генераторы случайных чисел.

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

Для начала, следует определить для себя некий видимый атрибут, который изменяется, и вы хотите это контролировать. К примеру, конкретный кадр, в который противник предпримет атаку. Или тип этой атаки. Или место появления какого-то объекта. В общем, любой фактор, который выглядит случайным и меняется в зависимости от вашего поведения в игре.

После этого надо найти адрес, по которому хранится значение этого атрибута. В этом нам поможет инструмент RAM Search, который позволит найти адреса переменных, которые меняются в точности тогда же, когда и искомый видимый атрибут.

Затем ставится точка останова на событие Записи по найденному адресу. Запускается мувик, в котором меняется искомый атрибут. Важно знать, как часто происходит его запись. В большинстве случаев точка останова будет срабатывать лишь раз в некоторый промежуток времени (скажем, раз в несколько секунд). А записываемое значение равняется тому, что вы впоследствии видите в RAM. Номер кадра, на котором происходит запись следует куда-то записать, например, в текстовый файл, или сохранить состояние игры непосредственно перед ним.

После этого надо вывести в файл код, выполняющийся непосредственно перед срабатыванием точки останова. Во многих случаях лога лишь за один кадр, где это произошло, достаточно. Однако, если точка останова срабатывала много раз за кадр, обязательно убедитесь, что в лог попали они все. Хорошо может сказаться и привычка пройти несколько "шагов вглубь" (Step Into) вслед за последним срабатыванием, чтобы захватить весь вовлеченный в событие код. Читать его во время выполнения не так уж полезно. А вот чтение лога покажет вам, откуда взялось значение, записанное по наблюдаемому адресу. Обычно оно бывает:
* Скопировано как есть из ROM.
* Скопировано как есть с другого адреса в RAM.
* Результатом какого-то взаимодействия с другой или несколькими другими переменными.

В первом случае, вам потребуется найти условие, при котором игра выполняет переход на данную позицию в коде и пишет это значение. Если переход будет сделан в другое место, записанное значение тоже будет другим.

В двух других случаях, вам нужно будет найти, откуда берется результирующее значение. Если оно копируется напрямую с другого адреса, установите точку останова на запись туда, и ищите, откуда берется ''то'' значение (точка останова может активироваться не единожды, прежде чем там окажется конечное значение, в таком случае надо обращать внимание на последний раз, в который было установлено значение, попавшее по наблюдаемому вами адресу). Если имел место какой-то алгоритм с участием значений по сторонним адресам, вам потребуется отладить процедуру, выполняющуюся каждый раз и выдающую разный результат для различного набора исходных значений.

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

Иными словами, для поиска причин вы будете раз за разом отматывать время назад. И наконец, отладив и натрейсив достаточно, придете к четкому пониманию, как себя ведет искомый псевдослучайный атрибут. Можно будет даже написать аналогичный алгоритм на LUA, и с его помощью предсказывать будущие значения в зависимости от игровой ситуации. И, самое главное, у вас появится возможность влиять на псевдослучайные исходные факторы, определяющие искомый атрибут, тем самым эффективно контролируя его. А может наоборот, узнаете, что он нисколько не случаен, и им нельзя манипулировать без существенного проигрыша по скорости. Это головоломка, в конце концов, вам ее решать!

''Замечание: Некоторые эмуляторы поддерживают использование при отладке и трассировке информации об отладочных символах. Это ужасно полезная вещь, позволяющая заменить нужные вам адреса на понятные человеку слова. В результате, в коде будут фигурировать не безликие цифры, а осмысленные названия, отражающие назначение упоминаемых адресов.''

!! Ссылки

* http://www.6502.org/tutorials/6502opcodes.html
* http://wiki.nesdev.com/w/index.php/Nesdev_Wiki
* http://en.wikibooks.org/wiki/Super_NES_Programming
* http://forums.nesdev.com/viewtopic.php?t=5528
* http://www.romhacking.net/utilities/749/
* http://gendev.spritesmind.net/page-home.html
* http://problemkaputt.de/gbatek.htm
* http://gbadev.org/docs.php

* http://www.fceux.com/web/help/HexEditor.html
* http://www.fceux.com/web/help/fceux.html?Debugger.html
* http://www.fceux.com/web/help/fceux.html?TraceLogger.html
* http://www.fceux.com/web/help/NESRAMMappingFindingValues.html

!! Эмуляторы

|| Эмулятор || Платформа || Инструменты ||
| [http://www.fceux.com/|FCEUX] | NES/FDS | - Отладчик%%% - Трассировщик кода%%% - HEX-редактор%%% - Функции отладки LUA |
| [BizHawk] | Несколько | - Трассировщик кода%%% - HEX-редактор |
| [http://code.google.com/p/vba-rerecording/|VisualBoyAdvance] | GBx/GBA | - Дизассемблер%%% - Трассировщик кода%%% - HEX-редактор |
| [http://desmume.org/|DeSmuME] | NDS | - GDB Stub%%% - Дизассемблер%%% - HEX-редактор |
| [EmulatorResources/Lsnes|lsnes] | SNES | - Дизассемблер%%% - Трассировщик кода%%% - HEX-редактор%%% - Функции отладки LUA |
| [http://psxemulator.gazaxian.com/|pSX] | PSX | - Отладчик%%% - HEX-редактор |
| [http://problemkaputt.de/index.htm|nocash emulators] | Несколько | - Отладчик%%% - Трассировщик кода%%% - HEX-редактор%%% |
| [http://aamirm.hacking-cult.org/www/regen.html|Regen D] | Genesis/GG/SMS | - Отладчик%%% - HEX-редактор%%% |
| [http://code.google.com/p/gens-rerecording/downloads/list|Gens-rr] | Genesis/SegaCD/32X | - Трассировщик кода%%% |
| [http://elektropage.ru/publ/programmy_dlja_romkhakinga/ehmuljatory/gens_11_r57shell_mod/38-1-0-122|Gens-rr r57shell mod] | Genesis/SegaCD/32X | - Отладчики%%% - Трассировщик кода%%% - HEX-редактор%%% |

----

''[TODO]'': Add cases that contradict this guide..%%%
''[TODO]'': Expand this guide with details..%%%