spiiin: (Default)
Felix The Cat - одна из немногих игр для NES, использующая сжатие данных описания уровня.

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

Уровень состоит из блоков 2x2 (с аттрибутами палитры и физики). Блоков используется 128.

Все подуровни описываются одним массивом, это необязательно в движке, но, видимо, так было удобнее разработчикам). Каждая вертикальная линия описывается отдельно, уровень описывается как массив указателей на линии, если линия полностью повторяет предыдущую, просто используется указатель на эту линию. Повторение линий активно используется, где-то 40-50% линий - повторы. Также в указателях на линии несколько бит используются для кодирования объектов.

Линии сжимаются с помощью алгоритма RLE, после чего из сжатых пар (количество повторов блока, номер блока для повтора) образуется словарь и повторы заменяются на слова из словаря. Обычные блоки имеют индексы от 0x00 до 0x7F, слова из словаря нумеруются от 0x80 и дальше, до 124 слов в словаре.

Последние 4 значения 0xFC-0xFF используются для задания второй формы сжатия. Она устроена интереснее и используется на уровнях с мозаичным фоном (например, узоры на стенах пирамид на уровнях 2-2 и 2-3).
В этом случае в начале линии может использоваться команда из двух байт (номер_базовой_линии, кол-во блоков из базовой линии). На уровне используется 4 базовые линии (их номера кодируются от 0xFC до 0xFF), которые описывают зацикленную мозаику. Первые несколько блоков берутся из этой линии, а затем нижняя часть дорисовывается обычным способом.
Пример таких начал линий на скриншоте:



На нём выделены рамками повторяющиеся базовые линии.

Эти три приёма (индексирование линий, RLE-словарь и базовые линии) позволяют сжимать уровни размером в 18 килобайт до 4-5 килобайт.

Tags:
spiiin: (Default)
http://spiiin.github.io/CadEditor/tutorial-powerblade2.html

Вторая статья по исследованию формата уровней игр и составление конфига для редактора уровней CadEditor, на примере Power Blade 2 [NES]. Работа с дампами памяти и начало работы с отладчиком.


Все статьи по редактору CadEditor .

Tags:
spiiin: (Default)
http://spiiin.github.io/CadEditor/tutorial-tmnt2.html

Написал более подробную статью про использование инструментов для поиска данных в NES-играх и добавление игр  в редактор уровней.
(на основе поста о формате блоков 4x4 + 1 байт атрибутов)

Tags:
spiiin: (totoro)
Обновил мажорную версию своего редактора CadEditor уровней для кучи NES и SMD игр.

За 3 года добавил:

- Поддержку новых режимов аттрибутов (бит палитры и свойств) – поддержка аттрибутов на уровне блоков (уже была, игры Capcom) , макроблоков (Tiny Toon Adventures / серия Ninja Gaiden), описание аттрибутов отдельным слоем поэкранно (Contra Spirits / Mickey Mania / Batman).
- Поддержку иерархий макроблоков любого уровня вложенности (рекорд: Rokin' Kats – 4 уровня иерархии).
- Систему плагинов для редактирования конкретных аспектов игр (примеры - плагин для редактирования глобальной карты или плагин для редактирования фонов в SMD-играх, доработанный редактор фреймов анимаций для Capcom-игр).
- Конфиги для отображения блоков и экранов для десятка сеговских игр (в основном использующих компрессор RNC, для которого есть пакер). Заметки по форматам уровней: Раз, Два, Три. (SMD Earthworm Jim 1-2, Alladin, Jungle Book, Mickey Mania, Pitfall etc)
- Написал универсальную утилиту для поиска блоков и аттрибутов известных форматов для NES игр. Она магическим способом обнаруживает не только известные форматы блоков, но также находит и те, на которые не была запрограммирована!
- С помощью этой утилиты открыл наиболее часто встречающийся способ кодирования блоков в NES играх – 16 байт на блок 4x4 и 1 байт на палитру. Добавил поддержку таких блоков в редактор и описал конфиги для двух десятков игр с таким форматом (серия TMNT, серия Battletoads, серия Adventure Island, серия Power Blade, Jackal, Contra Force, Jackie Chan Action Kung Fu etc.)
- Улучшил утилиту Autocorrupter, для создания скриншотов изменных данных об уровне и их последующего анализа. Утилита используется для упрощения генерации конфигов картинками и блоками для редактора.
- Немного улучшил код редактора и добавил возможность использовать его как библиотеку, управляя ею из скриптов на языке Python (с использовнием Jupyter Notebook). Скриптование своих же программ позволило перейти от реверса конкретных игр к реверсу всех игр на платформе вообще.
- Написал несколько обзорных заметок про ромхакинг и возможности редактора.
- Запустил кампанию на Patreon, собирающую по 3$ в месяц на пиво :)
- Суммарно в проекте около 30к строк кода, 500 конфигов уровней для 85 разных игр.

Зачем всё это?
Если долго и упорно годами бить в одну точку, пространство раскрывается и показывает тайны скрытых неизведанных миров между строчек ассемблерного кода. Даже если эти миры существуют только для тебя и ещё нескольких сотен энтузиастов по всему миру.
Tags:
spiiin: (totoro)
Как в python собрать функцию, которая после вызова pickle.loads совершит любое действие.

Программирование с помощью виртуальной машины pickle:
http://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_WP.pdf

Сериализация функции:
https://www.cs.uic.edu/~s/musings/pickle/

Выполнение кода и открытие сокета с remote shell:
https://blog.nelhage.com/2011/03/exploiting-pickle/
Tags:
spiiin: (totoro)
https://www.root-me.org/en/Challenges/App-Script/

Отличные челленджи на поиск уязвимостей в скриптах на различных языках – достаточно сложные (решения минимум в 2-3 этапа), требуют знаний в нескольких областях одновременно, не все решения запалены в интернете. Обнаружил, что знаю Python достаточно, чтобы почти полностью самому в них разобраться. Прошёл все пять:

В принципе, и так известно, что не надо совать в eval и pickle.loads ничего, что пришло от пользователя, но после выполнения таких заданий понятно, что не надо так делать СОВСЕМ (даже максимально отфильтровав ввод), потому что даже с очень сильными ограничениями пользователя, он всё равно сможет запустить любой код, который ему захочется.
Tags:
spiiin: (2D)
После праздников взял в руки NesBlockFinder, и прошёлся им по играм, добавленным в CadEditor с помощью Autocorrupter'а. Схема простая – меняем в редакторе в тестовом РОМе один из блоков на первом экране на 0-й (по нему проще находить начало списка блоков), и запускаем поиск блоков в BlockFinder'е.

С помощью применения такого подхода обнаружилась целая группа игр, в основе описания уровней которых содержится одна и та же структура:


Она состоит из 16 байт, которые построчно кодируют номера 16-тайлов видеопамяти,  по ним строится блок размером 4x4 тайла (именно блок, а не макроблок, как в играх капком).

В дополнение к индексам тайлов с таким блоком связан 1 байт, в котором закодированы индексы палитры для каждой группы 2x2 блока (выделены на скриншоте разными цветами), по 2 бита на каждую группу из 4х блоков слева-направо сверху-вниз. Биты палитры применяются сразу к группе тайлов из-за аппаратных особенностей NES, именно так на ней хранится описание бекграунда. NesBlockFinder не ищет такие биты палитры, но во всех проверенных случаях это описание оказывалось либо сразу за массивом описания блока тайлами, либо сразу перед ним, так что обнаружить поинтер на эти биты очень просто.

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


Эта структура оказалась настолько универсальной, что она обнаружилась в следующих играх:
Power Blade 1-2 (разработчик Natsume)
Adventure Island 2-3 (Hudson soft)
Yo-Noid (Now production)
Jackie Chan Action Kung Fu (Now production)
Contra Force (Konami)
Batman Returns (Konami)
Super C (Konami)
Monster in My Pocket (Konami)
Bucky O'Hare (Konami)
Jackal (Konami)
Teenage Mutant Ninja Turtles 1-3 (Konami)
Alien 3 (Probe entertaiment)
Battletoads (Rare)
Battletoads & Double Dragon (Rare)
Darkman (Ocean software)


И, возможно, обнаружится ещё в паре десятков других игр для этой платформы. Такая универсальность объясняется тем, что её легко закодировать (легче, чем иерархическую систему из блоков и макроблоков).
Tags:
spiiin: (2D)

Скрипт для поиска секретов в Утиных Историях 2. Отмечает квадратиками все игровые объекты, за счёт чего получается найти все секретные места.
https://github.com/spiiin/CadEditor/blob/master/Stuff/nes_lua/duck_tales_2_show_objects.lua
Tags:
spiiin: (2D)
Тестировал свой редактор трасс для Battletoads, собрал гипер-туннель, который очень хотелось бы отправить поиграть разработчикам Боевых Жаб, чтобы они поняли, как игроки мучались в детстве, когда после первых двух простых уровней они попадали в третий и видели нечто такое:

После этого, конечно же, надо представить, что в гости зашёл друг поиграть на двоих, а уровень перезапускается, если ошибается хотя бы один.
Tags:
spiiin: (2D)
Изобрёл ещё один способ реверса формата уровней NES-игр.

Способ во многом лучше предыдущего (автокорраптера) и работает практически в любой игре:

- не надо ловить момент старта уровня, достаточно сделать дамп памяти PPU в любой момент.
- не надо использовать графику вообще, метод работает напрямую с данными от PPU консоли.
- намного меньше усилий со стороны пользователя.
- способ сочетается с предыдущим (можно использовать оба метода для достижения лучшего результата).
- работает быстрее - перебирает все возможные варианты размещения блоков в ROM за 15-20 секунд.
- универсальнее (сработал в 48 из 50 проверенных игр, будет время – прогоню более полные тесты).

Теория
Read more... )

Идея метода
Read more... )

Результаты находок разных типов
Read more... )
Возможные улучшения

Read more... )
Ссылки
Исходники
Скомпилированный бинарник
Tags:
spiiin: (2D)
Планшет Cube IWork 7 попал ко мне практически случайно.

Он показался очень необычным тем, что на нём стояла не какая-нибудь урезанная телефонно-планшетная, а полноценная десктопная Windows. Потенциально, это семидюймовый ноутбук с 4х-ядерным процессором и гигабайт RAМ, с возможностью подключать его к монитору-телевизору через HDMI и гонять на нём старые и не очень игрушки.

На практике же оказывается, что, без должной обработки напильником, это практически кирпич, на который нужно потратить много времени и энтузиазма, чтобы нормально им пользоваться.
Результаты потраченного времени... )
Tags:
spiiin: (2D)
Нашёл отличное шоу.
Tags:
spiiin: (2D)
После промотра фильма Jungle Book решил вернуться к ромхак-анализу игр этой серии.

Существует несколько различных портов Jungle Book для разных консолей, выпущенных одной и той же командой разработчиков.
Версии для PC и Sega практически идентичны, Snes версия обладает схожей графикой, но полностью другими уровнями, а NES и GameBoy – очень похожими по структуре уровнями, но отличаются по используемому физическому движку и графике.
Для примера карты уровней для NES и SMD версии (можно сравнить позиции деревьев).

Однако при всей схожести сеговская версия проходится легко и приятно, а NES-версия – хардкорный ад, как будто разработчики намерянно решили усложнить игру в разы. Смотрите сами:

Во-первых, физический движок на NES написан так, чтобы усложнить жизнь игроку – медленно летящие снаряды, вроде осколков ореха наносят урон не один раз, а 4-5, что отбирает почти всё здоровье, попасть на врага сверху очень сложно, нужно чётко знать область повреждения, чтобы не промахнуться по ней (в сега версии можно хоть ударить врага снизу, игра всё равно вытолкнет Маугли наверх и нанесёт урон врагу), вдобавок иногда Маугли просто промахивается мимо лианы, пролетая сквозь неё. Дальше – на наклонной поверхности или после бега в NES версии Маугли начинает не останавливается сразу, а пробуксовывает вперёд, что часто приводит к незапланированным падениям. Ещё он умеет прыгать двумя способами, с места и с разбега, в обеих версиях, но в сеге отличия заключаются только в анимации прыжка, на NES же уровни построенны так, что иногда требуется прыгнуть только конкретным типом прыжка, иначе не хватит длины или высоты полёта. Особенно это ощущается в уровне Falling Ruins, целиком состоящем из падающих под весом Маугли платформ.

Во-вторых, в версии на SMD кристалы, необходимые для окончания уровня, чаще всего лежат на видном месте и для прохождения нужно найти не все из них, а только (8/10/12 из 15 в зависимости от выбранной сложности), причём можно найти компас, который показывает, где лежит ближайший кристал. В NES, соотвественно, некоторые кристалы спрятаны в секретных нычках, которые ещё нужно найти, иногда даже совершив "прыжок веры" вслепую, причём какую бы сложность вы ни выбрали, придётся собирать все кристалы. Часто приходится отыскивать по всему уровню последний лучше всего спрятанный кристал в условиях, когда кончается время (для справедливости отмечу, что в GameBoy версии всё ещё сложнее, в ней кристалы часто спрятаны внутри врагов, и для их отыскания приходится устраивать уничтожение всех животных, встреченных на пути в поисках драгоценностей).

В-третьих, Балу. В мультфильме есть эпизод, в котором он обучает Маугли жизни в джунглях и поёт песню:

Уровень The River в игре про этот момент. В Sega версии Маугли доходит до Балу со стороны реки, рядом три камня, Балу бросает фрукты, их надо ловить, если упасть в речку, бонус закончится, и начнётся следующий уровень. В NES же Балу просто пытается утопить Маугли, и его нужно победить. Друг называется...

Чтобы хоть немного облегчить NES-версию, я написал Lua-скрипт для эмулятора FCEUX, который добавляет в игру компас, который, как и в Sega-версии показывает направление к ближайшему ещё не собранному кристалу.
https://gist.github.com/spiiin/14acca27ded1989f86622eaa3ad1b515
Так что можно перепройти игру, не путаясь в лабиринтах из лиан:
Tags:
spiiin: (2D)
Когда-то я для тестов автоматического корраптера игр я находил массивы с описаниями экранов уровней обеих игр серии Flintstones для NES.
С помощью цепочки логических рассуждений (и скриптов для их автоматизации) можно получить полное описание формата уровней.

Read more... )

Заметки по формату уровней
- Часто используются хитрости для уменьшения размера, причём для разных уровней - свои. Для уровня замка используется полбанка видеопамяти, которые дублируются во вторую половину видеопамяти,  Для некоторых подуровней одного уровня используется общая "раскладка", например, для ночных джунглей, т.е. они используют общие наборы блоков и макроблоков, а также координатную сетку для описания объектов).
- После разметки обнаруживается небольшое различие в экранах для европейской, американской и японской версии игры, для уровня 3 данные не влезли в первые два банка, поэтому он находится в последнем банке с данными, в котором хранятся и строки, из-за чего смещения отличаются.
- В Surprise at the Dinosaur Peak размер макроблока уменьшен до 4x2, при этом удалось достичь того, что уровни состоят из намного меньшего числа макроблоков, при таком размере их функциональность намного увеличена.
- В описании уровней нету данных о физике блоков, она хранится где-то среди других данных, возможно, рядом со списками объектов.

(полноразмерные скрины)
Tags:
spiiin: (2D)
Так как оживить IronPython для работы с Jupyter у меня не получилось (pyzmq собрать под него целый квест с кучей патчей, получилось только пересобрать своими силами IronClad и через него запустить IPython, чтобы выводить данные в Visio, как здесь), то вместо него научился пользоваться Python.NET, который позволяет загружать .NET-сборки в обычный Python и вызывать методы из них, что, собственно, мне  и требовалось.

На всём этом собрал примерчик, как загрузить готовый конфиг для CadEditor'а и отрендерить графику уровней Чёрного Плаща прямо в браузере:
http://nbviewer.jupyter.org/github/spiiin/CadEditor/blob/master/JupyterCadEditor/CadEditor-example-dwd.ipynb
spiiin: (2D)
Для съёмки пластилиновых роликов я использую абсолютно хипстерский метод – iphone на штативе, потому что он снимает лучше доступных под рукой фотоаппаратов, и блютуз селфи-кнопку для него, чтобы не трясти пальцем телефон, потому что часов у меня нет.

Для записи взял программу "Кукольная анимация", по возможностям весь софт примерно одинаковый, самое полезное их свойство в отличие от обычной камеры – возможность показывать совмещенный с текущим предыдущий кадр, что позволяет править случайные изменения в кадре (в камеру  или сцену периодически кто-то врезается :) ). Она в бесплатной версии не позволяет снимать кадры в самом высоком качестве и не позволяет экспортировать проект в виде картинок (что впрочем, при желании лечится– экспортируется проект в дропбокс и переименовывается в ZIP, в котором хранится xml и имена файлов, дальше файлы сортируются по дате создания и получаются картинки всех разрешений сразу). Так что покупать можно только ради 4k картинок.

Снял с помощью неё два ролика, а сегодня пытался снять третий и обнаружил, что программа перестала работать с селфи-кнопкой. Почитал описание кнопки и понял, что она изначально не должна была работать с программой совсем! Селфи брелок только эмулирует нажатие кнопки "-", что работает с обычной камерой, и программами, которые делают снимок по нажатию этой кнопки. Но в "Кукольной анимации" снимок делается только кнопкой "+", а не "-", а нажатие на "-" просто снижает громкость звука приложений. Вроде бы всё, несовместимость, но раньше то снимки брелком делались!

Перебрал в памяти все варианты изменений на телефоне. До этого по вечерам я рубился на телефоне в "Civization Revolution 2", открывая все достижения (часто сложные требуют очень нестандартного стиля игры, удовольствие от прохождения получается как от решения шахматных задачек). Недавно дооткрывал все, и перестал играть. После этого программа и перестала работать. Мистика!

Немного поковырялся вокруг этого и нашёл причину такого странного поведения. В ios 8.4 (да и 9, скорее всего), если нажимать кнопку "-" в приложении, то снижается громкость звука во всех приложениях, его можно снизить до 0, если же сделать это на главном экране, снижается громкость звука звонка, и его можно довести только до 1 (на 0 не сбрасывается, потому что есть отдельный рычажок "заглушить звук", вроде логично).
Но "Цивилка" ведёт себя не как другие приложения, в ней обработчик кнопки "-" программно снижает звук одновременно и приложения и звонка! И через такой интерфейс звук звонка всё-таки доводится до 0, что идее должно быть невозможно.

Дальше веселее, после того, как программно звук звонка выставлен в 0, поведение при нажатии на кнопки в приложениях меняется на другое (если изменение звука звонка заблокировано аппаратно рыжачком, то кнопки программно перестают обрабатываться вообще, логика меняется только если выставить звук звонка в 0 программно, что невозможно без "Цивилизации", другими приложениями такого эффекта добиться не удалось).
Теперь если в приложении попытаться повысить громкость звонка, то программно пошлётся команда "повысить громкость на 1", и тут где-то в недрах операционной системы срабатывает логика "Если звук до этого стоял на 0, значит он был выключен аппаратно, а кто-то решил его увеличить. Но раз аппаратно он выключен, то его нельзя включать!!!". Что делать в такой ситуации? Кто-то из программистов в "Apple" решил, что в такой ситуации сразу же за командой "Повысить звук на 1", стоит послать команду "Понизить звук на 1", чтобы он снова стал равен нулю. В этом месте догадливый читатель должен понять, что происходит в приложении.

Физически нажали на кнопку на кнопку "+", а виртуально нажалась  ещё и кнопка "-". Которая и сделала снимок. Поведение явно бажное (сообщения приходят сразу два одновременно и иногда успевает даже отрисоваться гуи операционной системы, в котором видна быстро появляющаяся и исчезающая одинокая палочка звука), но благодаря нему программа работает там, где не должна \^_^/

И скоро будет третье пластилиновое видео ;)

Возможно, я слегка ошибся при описании этой схемы, отладчиком я туда не лез, но опыт ломателя подсказывает, что скорее всего процесс происходит именно так, при желании можно проверить это с другими программами.
Tags:
spiiin: (2D)
http://www.kegel.com/mangle.html
Помогает разобраться в том, почему предварительно скомпилированная библиотека не линкуется к другому коду.
Tags:
spiiin: (2D)

CaH4e3 (последний босс всех отечественных nes-ромхакеров) выложил видео процесса дизассемблирования «Чёрного Плаща» с нуля, с комментированием процесса. Эх, где он пару лет назад был...
Дизасмов игр такого размера в интернетах всего пара десятков, многие делаются годами (я за дизасмом ЧП недели две-три каждый вечер просидел, и то только формат карт и объектов исследовал для редактора, а не всю игру), а тут за несколько часов реверс движка и его оптимизация с освобождением места под три новых уровня — скрипты рулят.

В ходе просмотра ловил себя на мысли, что до сих пор визуально помню некоторые массивы данных и что именно в них хранится.
Tags:
spiiin: (2D)
Систематизировал немного свои заметки про устройство уровней в NES-играх:
http://habrahabr.ru/post/259171/ — Устройство уровней в NES-играх (про систему блоков и макроблоков)
http://habrahabr.ru/post/259483/ — Исследование формата карты уровней NES-игры «Jackal» (пример поиска данных об уровнях конкретной игры)
http://habrahabr.ru/post/259761/ — Устройство игрового движка для NES на примере игр «Capcom» (обзорно про всё)

Ради второй статьи улучшил скрипт автокоррапта образов игр (потребовалось немного модифицировать эмулятор Fceux, но теперь он и официально поддерживает фичи, нужные для коррапта) и прогнал через него ещё десяток игр, благодаря чему получил карты лабиринтов от Alien 3 (всегда забывал, как они проходятся):
Tags:

Profile

spiiin: (Default)
spiiin

September 2017

S M T W T F S
     1 2
34 567 89
101112131415 16
17181920212223
24252627282930

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Sep. 24th, 2017 05:44 pm
Powered by Dreamwidth Studios