на каком языке писали игры для денди
Разработка игр под NES на C. Главы 1-3. От введения до Hello World
Впервые я задумался о том, как разрабатывают игры под приставки где-то через 20 минут после того, как в самый первый раз увидел Turbo Pascal. На глаза иногда попадался Subor с клавиатурой, и появилась мысль: «Наверное можно набрать какую-то программу, а потом в нее поиграть». Но интерес быстро затух, потому что абсолютно никакой информации по этой теме тогда не было доступно. Следующий раз эта же идея всплыла, когда увидел вполне играбельные эмуляторы старых консолей. Тогда стало ясно, что вбивать листинг в саму консоль и необязательно. Где-то очень потом появился Хабр с благожелательной аудиторией для таких вещей. В какой-то момент даже начал собирать разрозненную инфу чтобы написать мануал самому, и вот сегодня наткнулся на готовый учебник, который явно надо перевести.
Разработка под старые консоли документирована вдоль и поперек, но именно по NES 99% информации относятся к разработке на Ассемблере. Меня почему-то зарубило, что надо освоить именно работу с С.
следующая >>>
Всем привет.
Меня зовут Дуг. Я пишу игры для NES вот уже год, и решил начать этот блог. Я намерен написать туториал по разработке игр под NES, чтобы вдохновить других людей делать собственные игры.
Особенностью блога будет использование чистого С, так что другие программисты смогут начать писать быстро и не особо вникая в ассемблер для процессора 6502. Насколько мне известно, других туториалов такого формата по компилятору cc65 пока нет, кроме нескольких примеров игр на сайте Shiru.
Также помните, что я не профессионал ни в разработке, ни в ведении блога. Если возникнут вопросы по NES, скорее всего ответы найдутся в Вики.
Я постараюсь максимально упростить обучение, и использовать самые простые примеры. Также рекомендую начать с простейшей идеи игры. Читателю явно захочется сделать новую Зелду, но это не получится. Простейшая игра потребует 2-3 месяца на разработку, Зелда — 2-3 года. Такой проект скорее всего будет заброшен. Ориентируйтесь на Пакман, хотя бы первое время.
Память консоли
Начнем с памяти процессора.
Здесь более подробная информация.
Таблица имен, nametable, связывает тайлы фона и их позицию на экране.
Зеркалирование позволяет управлять горизонтальной или вертикальной прокруткой, но всему свое время.
Еще в PPU есть отдельная область памяти OAM, Object Attribute Memory, размером 256 байт. Доступ к ней реализован через регистры в адресном пространстве процессора, и она позволяет управлять отображением спрайтов.
Другой тип картриджа использует CHR-RAM вместо CHR-ROM. Это позволяет подгрузить часть графики в эту дополнительную оперативную память. Это сложная техника, и в этом туториале не рассматривается.
Теперь можно посмотреть на софт, используемый для разработки.
В этом туториале рассматривается только cc65. Это один из лучших компиляторов для 6502, процессора NES.
Во-вторых, надо создать графику. Я использую YY-CHR
Для предобработки графики нужен любой графический редактор: Photoshop или GIMP, по вкусу.
Код удобно писать в Notepad++. У него есть подсветка сишного синтаксиса и нумерация строк — это облегчает отладку.
А теперь эмулятор. Я использую FCEUX 90% времени, потому что в нем есть крутой дебаггер и инструменты для работы с памятью, просмотрщики спрайтов и все такое. Но он не самый точный в эмуляции. Игры надо будет тестировать где-то еще. Судя по отзывам, самые точные эмуляторы это Nintendulator, Nestopia, и puNES. Еще желательно подгрузить более точную палитру — лежит здесь.
Есть две версии FCEUX — SDL и Win32. Первая работает почти везде, вторая только в Windows. Так вот, отладчик есть только во второй. Так что в случае альтернативной ОС придется воспользоваться виртуалкой или Wine.
И наконец расстановщик тайлов. Мы можем сделать игру без него, но он точно поможет. Я рекомендую NES Screen Tool. Он отлично показывает ограничения консоли по цветам и отлично подходит для одноэкранных игр. Для игр с прокруткой лучше подойдет Tiled map editor.
Как же всем этим пользоваться?
Надо сжать изображение до адекватного размера, например 128 пикселей в ширину. Потом преобразовать в 4 цвета и подправить при необходимости огрехи. Теперь можно копипастить в YY-CHR.
В YY-CHR надо проверить, чтобы цвет был двухбитный.
Палитра сейчас не имеет значения, потому что она все равно задается в другом месте.
Как работает сс65
Все компиляторы для NES работают через консоль, без графического интерфейса. То есть пишем программу в Блокноте, а потом вызываем компилятор с нужными параметрами.
В приставке используется 8-битный процессор MOS 6502. Он не умеет просто обращаться к переменным больше 8 бит. Адресация 16-битная, из математики есть только сложение, вычитание и битовые сдвиги. Так что код придется писать с учетом этих факторов.
Оптимизация жизненно необходима, потому что у 8-битного процессора очень мало ресурсов, и в некоторых случаях надо следить за временем выполнения кода. А обычный код на С этим требованиям не соответствует.
Поддерживается импорт переменных из других файлов. cc65 умеет импортировать переменные и массивы из ассемблерных модулей командой
а если это символ из нулевой страницы памяти, то добавьте директиву
В дальнейшем курсе эти конструкции будут использоваться редко. Единственное исключение — импорт большого бинарного файла. В этом случае оптимально будет завернуть его в ассемблерный файл:
а потом импортировать в С как
Знак _ здесь критичен, потому что при компиляции в ассемблерный код cc65 добавляет _ перед каждым именем переменной. Нам надо этому соответствовать.
Можно вызывать функции, написанные на ассемблере, через __fastcall__. В этом случае аргументы передадутся в функцию через регистры, а не стек — экономит время. В некоторых случаях без ассемблерного кода не обойтись, например при инициализации приставки. В любом случае, чем меньше аргументов передается в функцию, тем лучше. Сравним две функции, причем переменные test и A глобальные:
Еще можно вставлять ассемблерный код прямо в сишный. Я так почти никогда не делаю, но наверное иногда это необходимо. Выглядит примерно так:
Кроме того, я заменил громоздкий код инициализации crt0.s на компактный reset.s, и подправил конфигурацию для всего этого. Эти файлы иногда будут меняться. nes.lib используется стандартный, из состава компилятора. Проект собирается с опцией –add-source, которая не удаляет промежуточные ассемблерные файлы — можно порассматривать сгенерированный код.
Удобней определить переменные в сишном коде, а потом импортировать в ассемблерный через
Но это вопрос вкуса, на мой взгляд, такой код наглядней.
Hello World
Эта программа будет просто печатать текст на экране. Надо помнить, что приставка вообще не знает про кодировку ASCII и работу с текстом в любом виде. Но зато есть возможность вывести картинки размером 8х8 поверх фона.
Так что делаем массив спрайтов-букв, чтобы адреса букв в нем соответсвовали их ASCII-кодам. Потом их можно будет дернуть из кода на С.
Код инициализации приставки пока берем как есть, после его выполнения происходит переход на main().
Нам надо сделать такие операции:
Выключение экрана нужно, потому что работа с видеопамятью вызывает мусор на экране. Надо или выключить экран, или ждать кадровый гасящий импульс (V-Blank). Детально этот вопрос мы рассмотрим в следующий раз.
Код инициализации заполняет память нулями, так что весь экран будет залит нулевым тайлом — в нашем случае, он пустой. А вся палитра заполнена серым цветом.
Дропбокс
Гитхаб
На Гитхабе чуть исправил Makefile, чтобы корректно работал под Windows.
Включение экрана через “PPUMASK = 0x1e” описано в Вики.
Как писались игры на Dendy
Всё ещё пишут игры для нэс? Дайте примеров годных новых игр плз, это же в тысячу раз лучше говна из плэймаркета
А если для сеги есть новые, то я совсем в экстазе буду
Так выглядит счастливая европейская семья
Это событие должны преподавать на уроках истории
Тут мы постим дегродные мемасы: Dank memes
Сервера Близзард как обычно
Слишком страшно
Целительница
Как убивает локдаун на примере малого бизнеса
Всем рыцарям малого бизнеса посвящается. Держитесь, ребят!
У каждого человека есть список обязательных ежемесячных затрат:
А в локдаун этих продаж нет.
На сегодня в Челябинске нет таких жестких ограничений, но прошлое лето ужасно сказалось на нас и продажи до сих пор не вернулись к показателям прошлых лет.
И так, у меня есть два маленьких магазинчика с товарами для рукоделия. Бизнес специфичный, на личную яхту и самолёт никогда не заработаю, но товар добрый и пушистый. Да и мегамонстров на рынке нет (кроме относительно близкого по группам товаров «Леонардо»).
Мои основные ежемесячные расходы:
— зарплата («нерабочие оплачиваемые дни»)
— аренда (для многих это стало непомерной ношей и гвоздем в гроб бизнеса)
— коммунальные платежи (батареи работают как всегда, мусор вывозят каждый день, квадратных метров меньше не стало)
— налоги (патент. деньги снимают на него заранее; не слышала чтобы кто-то забрал у государства обратно за неработающий магазин из-за ограничений)
— кредиты за товар (кто-то берет у банков, а я беру товары в рассрочку и ежемесячно выплачиваю поставщикам, независимо от продаж)
— реклама (у нас были напечатаны листовки с датами, пришлось их выбросить. А большие магазины заранее все согласовывает и печатают баннеры-раздатку..)
— прочие расходы (канцелярия, сезонное/праздничное обновление витрины-полочек и тд)
В общей сложности, для моего маленького бизнеса это около 400-600 тысяч ежемесячно. Затраты, от которых ты никуда не спрячешься и не убежишь. Для бизнесов покрупнее речь идёт о десятках-сотнях миллионов.
Так откуда взять эти деньги, если % продаж в локдаун около нуля?
И так, ты должен всем кучу денег. У тебя нет финансов на закуп новых коллекций к приближающемуся сезону/празднику. Часть товаров пойдёт в мусорку. В моем случае остались вся весенняя и садовая тематика на 200т.р (на самом деле больше, но не смогла выполнить прогноз продаж на эту сумму), не смогла закупиться своевременно и выбросила в общей сложности ещё примерно на 300т.р.
— убытки 500т.р. плюс хранение целый год
То есть у тебя уже минус миллион…
И оно так помогает.
Кстати, в инете есть чек-лист с 19 пунктами, которые проверяют в магазинах. В том числе сертификат, срок годности антисептика, аппарат для обеззараживания воздуха и запас масок в магазине. Об этом вам никто не расскажет, сами ищите.
От администрации района мы постоянно получаем письма: «устройте субботник», «покрасьте мусорку», «посадите цветочки и деревья». Так что могли бы и написать полный список и обязательств магазинов (которые меняются постоянно)… но зачем напрягаться?
Вот и вся помощь от государства.
И они весь негатив от этой ситуации сливают на продавцов.
Нервы у последних не выдерживают и они увольняются.
Вот только ты честный человек и несёшь ответственность за людей, которые тебе поверили. И ты стараешься найти выход.
Но что ты можешь сделать, если тебе говорят: «плати всем, но работать тебе нельзя»??
Без малого бизнеса в каждом доме останутся Пятёрочка, Красное-белье и Еаптека с пунктом выдачи Маркета. Все будут ходить в одинаковой одежде от Глория джинс и Спортмастера, есть «колбасу одинаковую докторскую» или только в Макдональдсе, и цены взлетят на все, ведь конкуренции по сути не будет.
В России вас и так мало осталось. Держитесь.
Игры для NES/Famicom/Денди глазами программиста
Это пост про ограничения старых видеоигр. Сам я под NES никогда не программировал, но с архитектурой поверхностно познакомился. Теперь я не могу играть в игры для NES, не задумываясь, как же они устроены. Иногда это на столько вызывает восхищение, что невольно забываешь про саму игру. «Чему же там восхищаться?», — скажете вы. Да просто укладываться во все ограничения NES, но при этом делать игру красивой, — это действительно целое искусство.
Сейчас я постараюсь рассказать об этом вам, максимально всё упростив.
На NES всё отображаемое на экране делится на спрайты и фон. Спрайты — это объекты, которые двигаются по экрану. Как правило, это непосредственно ваш герой и враги. Иногда это ещё какие-то предметы, но тут всё уже сильно зависит от игры. Фон — это собственно то, что находится позади. И у спрайтов, и у фона есть уйма ограничений.
Фон на NES делится на квадраты размером 8 на 8 пикселей, которые называются тайлами. Итого таких квадратов 30 в высоту и 32 в ширину. При этом фон может плавно двигаться горизонтально и/или вертикально.
Во многих играх, особенно старых, можно заметить, что игра состоит из таких повторяющихся квадратов. Вспомните Super Mario Bros., Bomberman или Battle City. Дело в том, что в память NES можно загрузить одновременно весьма ограниченное количество таких рисунков, поэтому приходилось использовать одни и те же повторно.
Помимо этого существенные ограничения накладывались на цвета. Всего NES может отображать около 53-55 цветов, учитывая повторяющиеся и похожие. По тем временам это было не так уж мало, но всё не так просто. Используются такие штуки, как палитры:
Это может быть не так просто понять с первого раза. Попробую объяснить на пальцах. Взгляните ещё раз на картинку выше. Каждый квадратик раскрашен не более, чем в четыре цвета. При этом они делятся на три типа: чёрно-бело-голубые, черно-зелёно-голубые, чёрно-коричневые. Возможно, что используется и четвёртый, но я не заметил.
Цвет помеченный звёздочкой постоянно меняется, так монетки и вопросики мерцают. Да, монетки — это часть фона. И именно поэтому облака и кусты — это один и тот же рисунок: тайл один, палитра выбрана разная. Сэкономили немного памяти, но ведь совсем незаметно с первого взгляда.
Как я уже говорил, фон может двигаться. Для этого обычно используется мирроринг, но в эти подробности я вдаваться не буду. При этом есть возможность разделить экран на две части и двигать их отдельно друг от друга, именно так обычно делается неподвижная строка с информацией о жизнях, здоровье, очках и прочем.
Спрайты
Если вы разобрались с ограничениями фона, со спрайтами всё будет легко. Суть в том, что это движущиеся на экране объекты размером 8×8 или 8×16 пикселей. Причём они все одновременно должны быть либо 8×8, либо 8×16, что накладывает несколько других ограничений. В лучшем случае (зависит от размера) всего их может быть аж 64, но на одной строке может отображаться не более восьми, даже если соответствующая область спрайта прозрачная, поэтому слишком много подвижных объектов не сделаешь. Правда, некоторые игры всё-таки делают, заставляя один из спрайтов исчезать на долю секунды, что приводит к неприятному мерцанию. Наверняка многие замечали такое. На цвета наложены примерно те же самые ограничения, что и для фона, но для спрайтов даются отдельные четыре палитры, один из цветов при этом считается за прозрачность. То есть получаем всего три цвета + фон…
Луиджи же — это просто Марио с другой палитрой. Обратите внимание — у Марио рукава, глаза, волосы и усы одного цвета. Именно поэтому у Луиджи глаза, волосы и усы стали зелёными.
Как же так получается?
А теперь взгляните на игры для NES, учитывая описанные выше ограничения. Как же так получается, что фон может быть только из 13 цветов, но многие игры запомнились очень красочными? Как же при таких маленьких спрайтах мы сражались с огромными боссами? Игры начинают выглядеть совсем иначе.
Например, Chip and Dale 2:
Всё весьма красочно и разноцветно, при этом разработчики вписываются во все ограничения.
Как только мы доходим до второй половины уровня, появляются новые цвета:
Просто в момент, когда мы переходим в другую локацию, и экран темнеет, в память загружается уже новые палитра и тайлы. Так создаётся впечатление, что игра гораздо более красочная, чем она есть на самом деле: эти самые 13 цветов достаточно часто меняются от уровня к уровню.
Выше я описал, что фон может делиться на две части, которые движутся отдельно. Именно так сделана начальная заставка, где летит дирижабль Толстопуза:
Колючая проволока внизу движется с одной скоростью, фон с другой, сам дирижабль — это спрайт, который движется с третьей скоростью. Так создаётся иллюзия объёма.
Бывают и совсем другие приёмы. Посмотрите внимательно знаменитую заставку Megaman 2:
Окна и выступы — это спрайты, а само здание представляет из себя фон из просто вертикальных линий, движение которых отследить невозможно:
На самом деле здание движется с той же скоростью, что и город на фоне, но это незаметно. При этом за счёт движения окон складывается впечатление, что здание движется всё-таки гораздо быстрее, а это соответственно создаёт ощущение того, что оно ближе.
Кстати, некоторые спросят, почему у самого Мегамена так много цветов? Да просто на самом деле он состоит из нескольких спрайтов: лица и тела, которые накладываются друг на друга:
А теперь подумайте — как же делались большие подвижные боссы, учитывая все ограничения на количество спрайтов? Ответ прост: такие боссы обычно на самом деле являются фоном. Именно поэтому при битве с ними фон зачастую либо чёрный, либо просто одноцветный. Вот пример из тех же Chip and Dale 2:
В первом случае такой фон двигается вертикально, во втором горизонтально. Думаю, что вы и сами вспомните очень много боссов на чёрном фоне.
В некоторых играх вроде Jurassic Park делают ещё хитрее:
Босс — это всё-таки фон, а вот кустики и камни на фоне — это спрайты. То есть всё шиворот навыворот! И да, спрайт может быть позади фона. Именно поэтому когда персонаж проходит через кусты, они иногда просвечивают сквозь него.
Кстати, у этой же игры в заставке надпись «Ocean» большая, движется в разные стороны с разной скоростью, а потом и вовсе отображается волнами:
Тут всё совсем хитро. Игра отслеживает момент, когда на экране телевизора дорисовывается сканлайн (горизонтальная линия), после чего сдвигает фон по горизонтали. Таким образом можно получить эффект вроде горизонтальных волн.
Продолжать можно очень долго. Любая достаточно серьёзная игра напичкана самыми разными такими «фокусами», которые выжимали из NES гораздо больше, чем было задумано изначально. Надо сказать, что многие из этих ограничений можно было снять, установив в картридж с игрой дополнительные чипы. И это весьма активно делали, в итоге картриджи могли весьма сильно отличаться с аппаратной точки зрения, но тогда нужно было не забывать и об итоговой цене производства, поэтому разработчики не очень сильно себя баловали.
Не стоит забывать и про ограниченные звуковые возможности, но это не так наглядно. Скажу лишь то, что для создания приятной музыки при помощи такого железа действительно нужно было обладать музыкальным талантом. Game Boy был уже немного более продвинутым в этом плане и в результате породил целый музыкальный жанр и свою культуру.
Надеюсь, что теперь и вы будете смотреть на игры иначе, задумываясь о том, как же разработчикам пришлось поломать себе голову.
upd: Огромное спасибо товарищу VEG за многие уточнения!
Как воплотить в жизнь мечту детства и запрограммировать что-нибудь для Dendy
Для меня Dendy всегда была чем-то большим, чем просто приставкой. Я не только играл в неё, но и значительное время провёл внутри неё с паяльником в руках для некоторых простых модификаций. По дороге куда-нибудь я часто размышлял о том, как же создаются эти игры и как это работает внутри. Наверняка, многие из вас когда-то задавались подобными вопросами, такова уж натура будущих IT-шников.
Прошли годы. С некоторой периодичностью погружался в эму-тему, изучая всё новое на тематических сайтах, но я не решался окунуться в изучение ассемблера 6502 и архитектуры NES. Внутренний конфликт рационального и иррационального. Я долго убеждал себя, что мне не нужно тратить на это время, но… сорвался. Глядя на то, какие интересные вещи делают энтузиасты эму-сцены, я взялся за свою давнюю идею со светлой мыслью: «Я тоже смогу!». Две недели пролетели незаметно, я еле смог остановить себя. И да, теперь я знаком с ассемблером без команд умножения, о чём раньше только слышал в песне о программистской молодости.
Очень вероятно, что сейчас вы вспомнили свой первый картридж для Dendy и меню с романтическим сюжетом и приятной музыкой. На таких картриджах никогда не было «серьёзных» игр, и не глядя на громкие надписи типа 9999-in-1, их обычно было что-то около пяти. Но это меню… Разве это не шедевр китайской мысли? 🙂 Мне с детства нравилась эта мелодия (Unchained Melody), а фоновые изображения сейчас навевают кучу ностальгических воспоминаний. Поэтому я взял IDA и дизассемблировал меню 300-in-1, вырезал всё лишнее, исправил ошибки, добавил фейдинг да немного приятных мелочей — и получилась демка Unchained Nostalgia (для запуска нужен эмулятор, например, Nestopia), есть запись на YouTube.
Хотите также окунуться в олдскульное программирование? Делюсь самым полезным и интересным, что я нашёл по теме.
Архитектура, программирование и отладка
Раньше для процессора 6502 писали только на ассемблере, выбор инструментов был маленьким, документации было немного и поведение железа было плохо изучено. Сегодня же таких проблем нет. В последние годы были даже разработаны библиотеки для C и полноценные игры на них, которые при этом быстро работают на скромном железе NES.
Современные разработки для NES
Если кто-то считает, что NES — мёртвая платформа, тот ошибается 🙂 Достаточно регулярно выпускаются новые игры и демки. Понятно, что это не массовый рынок, и здесь крутятся, в основном, энтузиасты, но тем не менее… Различных релизов выходит достаточно много, я поделюсь самым интересным и забавным из того, что нашёл сам.
Тематические сайты
Зачем всё это?
Если вы задаётесь этим вопросом, может быть это и не для вас. Но на самом деле это очень интересное и увлекательное занятие. Если у вас любимой приставкой была не Dendy, то может быть вам будет интереснее сделать что-то, например, для Sega Mega Drive. Вперёд! И обязательно расскажите о том, что у вас получилось.