Проект: CadEditor  Публичный пост
4 августа 2021  2028
ОХУЕННО
CadEditor
https://github.com/spiiin/CadEditor

Расскажите о себе и сути проекта?

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

Как появилась идея? Что вдохновило?

Мне было дико интересно разобраться, как это происходит, и ради этого я сидел часами, вооружившись справочником по ассемблеру 6502, листочком и ручкой за эмулятором. Я не особо понимал режимов адресации памяти, принципов работы мапперов, переключающих банки памяти, особенностей работы видеопроцессора и вообще устройства приставки. Главный инструмент исследования - изменить несколько байт в памяти шестнадцатеричным редактором, и изучить, что произойдет. На тот момент, когда я начинал этим заниматься, не было удобных эмуляторов с продвинутыми функциями отладки и плагинов по ida pro для интерактивной декомпиляции (ну, или кто-то только писал их и мне было о них неизвестно), но и того, что было, хватало, что посмотреть, во что декомпилируется набор из чисел, составленных по таблице опкодов.

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

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

Однажды меня все таки осенило, и пазл по составлению уровня из кусочков сошелся.

Какой технологический стек вы использовали?

Потом скрипты выросли в программу отображения данных. Я взял C#, просто чтобы попрактиковаться в нем, и потому что устал от C++ на работе, собрал форму с канвасом, на котором рисовался уровень, и закинул в тему на форуме emu-land, на котором тусовались ромхакеры - энтузиасты, увлекающиеся модификацией старых игр.
Там меня упросили превратить отображатель данных в полноценный редактор, а потом добавить туда еще несколько игр.

Изучая уровни диснеевских capcom-игр, я заметил, что они похожи друг на друга, но все же отличается по формату данных. Возможно, разработчики пробовали разные методы, исследуя их плюсы и минусы.

Я задумался на тем, как описывать сам формат данных об уровнях так, чтобы не делать редактор для каждой отдельной игры. Сложность также была в том, что некоторые игры различались по формату между собой, а также содержали некоторые уровни, отличающиеся по описанию от других (возможно, это финальные оптимизации, в попытках запихнуть игру на картридж или результаты ошибок разработчиков). Некоторые данные могли достраиваться кодом или использовать какие-либо особенности работы железа NES.

На этом этапе стало понятно, что редактор должен быть a) data-driven (сами данные описывают, как именно их рендерить) б) поддерживать хаки из кода игр, чтобы корректно отображать все уровни.

Поэтому я внедрил в редактор CSScript - библиотеку, которая могла компилировать и выполнять код на C# из текстовых файлов во время работы приложения.

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

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

Также я начал «втягивать» в свой редактор другие редакторы игр, потому что моя система конфигов позволяла быстро добавлять новые игры, формат которых был уже исследован кем-то.

Одновременно с этим я сделал сайт, на котором выложил несколько статей по форматам уровне(а также описал общую статью про возможные устройства форматов уровней на хабр, и провел там же «сеанс разбора на заказ» для игры jackal).

С накоплением знаний оказалось, что задействовать дизассемблер чаще всего не нужно, можно в автоматическом режиме пролистать всю память игры, и по содержимому экрана (или памяти знакогенератора, что тоже самое) понять, изменился ли игровой экран. Я немного отточил этот способ, модифицировав сам эмулятор fceux, так что теперь мог разобрать 5-6 игр за один день. В какой-то момент моим скриптом начали пользоваться другие пользователи, за счет чего удалось собрать данные для ~100 игр для nes.

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

Одновременно с этим изучением форматов я работал над фидбеками по редактору, несколько групп ромхакеров начали работать над хаками игр Chip & dale, Darkwing Duck, Duck Tales. Они просили дорабатывать и исправлять конфиги для первых исследованных игр.

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

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

Например, автор одного из ромхаков «Черного Плаща», работал около двух месяцев по 10 часов в день. Я понял, что нами движет что-то общее, детское желание прикоснуться к культуре диснеевских мультиков, которые мы все (кому ща за тридцатку :) ) смотрели по телевизору. И теперь можно было отправить любимых персонажей в еще одно, последнее, и созданное самостоятельно приключение.

Эти приключения до сих пор периодически обнаруживаются и освещаются на каких-нибудь популярных ресурсах.

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

Например - редактор трасс для Battletoads и пример созданной трассы.

Или редактор анимаций и титульных экранов для Capcom игр.

Интересно, что с инструментами ромхакеры задействовали возможности игровых движков, неиспользуемые в оригинальных играх. Например, один из уровней хака «Чипа и Дейла» (цирк) использовал возможность создавать двери, ведущие в различные части уровня, таким образом игрок мог сам выбирать, в какую часть уровня он пойдет.

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

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

Я пробовал выкладывать редактор на других ресурсах - romhacking.net (подключив иностранных пользователей), Patreon (в попытках собирать пожертвования), Itch.io (себя показать) и Steemit (тоже для пожертвований через сообщество финансирования open-source кода utopian-io).

Где-то в этот период редактором заинтересовались ромхакеры других платформ. DrMefistO (с которым мы впоследствии стали приятелями) добавил изначальную поддержку Sega графики (сначала в виде форка редактора для игры Thunder Force 3, затем я портировал код построения графики обратно в CadEditor) и написал декомпрессоры нескольких игр, которыми можно было достать данные из игровых архивов и работать с ними в редакторе, а австралиец с ником Darthatron помог мне разобраться с форматом данных для Final Fantasy Tactics Advanced (одной из моих любимых игр) для game boy advance, и я также добавил карты из этой игры в редактор.

Сам я для тестов сделал плагин для Game Boy графики.

Какие планы на будущее?

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

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

Связанные посты
8 комментариев 👇
Kirill Penkin Руководитель группы ГИС инженеров 6 августа 2021

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

  Развернуть 1 комментарий

Потрясающая история! Сколько тысяч часов ты потратил на этот проект? Кто оплатил их?)

  Развернуть 1 комментарий

@KiEwsD6gHcJanH5P, да сложно сосчитать. Это скорее деятельность вместо просмотра сериалов или прохождения игр по вечерам. Не скажу даже, что я всё свободное время за этим проводил, на другие увлечения тоже оставалось. Можно на удивление много времени найти откуда-то, когда всерьёз увлекаешься.

По поводу оплаты - тут скорее hacker value, важно не сколько тебе платят, а сколько ты можешь отдать. Эмуляторщики изначально занимаются в первую очередь сохранением для истории части культуры, которая в противном случае будет уничтожена временем. Мне достаточно знания того, что и мой небольшой вклад есть в это дело, я не потерял что-то, занимаясь этим.

Для себя я решил, что странно, что моя профессиональная деятельность не особо полезна для решения МОЕЙ сложной проблемы, у которой нет готового решения (из-за этого и трудоёмкость). Часто программистам лень что-то делать для себя, сложнее каких-то относительно простых скриптов и no-code средств, особенно если это нельзя монетизировать. Странно не использовать свои навыки хоть раз для того, чтобы сделать что-то, что хочешь именно ты, а не кто-то другой.

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

Пользы сейчас мне от этого в итоге никакой, современное железо абсолютно другое, ну разве что в резюме упомянуть, что у меня "небольшой" пет-проектик имеется.

  Развернуть 1 комментарий

Чудесное путешествие и чудесная история. Спасибо :)

  Развернуть 1 комментарий
Сергей Драган Java-консультант, тимлид 6 августа 2021

Я залип на твой блог с ссылок в начале поста. Количество и сложность труда очень впечатляет и восхищает. Ты охеренный.

  Развернуть 1 комментарий

Есть какой то совет, как сделать большой пет проект и не бросить посередине? )

  Развернуть 1 комментарий

@T6NR0co8aI5BzODE, ага, нужно, чтобы в твоих глазах этот недоделанный проект имел какую-то ценность, которая потеряется, если ты его бросишь)

  Развернуть 1 комментарий

@spiiin, спасиб, хороший совет

  Развернуть 1 комментарий

😎

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

Что вообще здесь происходит?


Войти  или  Вступить в Клуб