Переделка Денди: видеоусилитель, AV-mod, RF-модуль и звук


Этот пост является введением в мой проект «самодельной» консольной видеоприставки сделаной с нуля. Я вдохновлялся как ретро консолями так и современными образцами, но у меня получилась своя собственная архитектура. Мои друзья постоянно мне говорили, что я должен рассказать о своём проекте, а не делать всё исключительно «для себя», так что вот я публикую этот пост.

Внимание, это — перевод

Меня зовут Серхио Виейра (Sérgio Vieira) я выроc в Португалии в 80-е и 90-е годы, у меня давно ностальгия по ретро-геймингу, особенно по приставкам третьего и четвертого поколения.

Несколько лет назад я решил получше разобраться в электронике и попытаться сделать свою собственную приставку.

По профессии я программист и не имел никакого опыта как электронщик, если не считать (и не стоит этого считать) самостоятельных апгрейдов своего десткопа.

Хотя у меня и не было опыта, я сказал себе «почему бы и нет?», купил несколько книжек, несколько наборов электронщика и начал изучать исходя из своих ощущений о том, что именно стоит изучать.

Я хотел сделать приставку похожую на те которые вызывают у меня ностальгические чувства, я хотел что-то между NES и Super Nintendo, или может между Sega Master System и Mega Drive.

У этих приставок были CPU, оригинальный видео чип (тогда их ещё не называли GPU) и аудио чип, иногда встроеный, а иногда внешний.

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

Изначальный план был сделать приставку со следущими характеристиками:

  • Без эмуляции, игры и программы должны работать на настоящем железе, не обязательно том самом из тех времён, но достаточно быстром для задачи, и не более того.
  • С настоящим ретро CPU.
  • С аналоговым ТВ выходом.
  • Со звуком
  • С поддержкой двух контроллеров
  • Скроллинг бэков и анимация спрайтов
  • С возможностями для поддержки платформерных игр вроде Mario, ну и конечно всяких других игр.
  • С загрузкой игр и программ с SD карт.

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

Видео сигнал

Первое чем я занялся это генерация видео сигнала.

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

Это не перебор, и как раз достаточно мощное решение для графики того уровня который мне был интересен.

И так, я начал использовать микроконтроллер Atmega644 на чистоте 20 Мгц для генерации видеосигнала в формате PAL для телевизора. Мне пришлось бит-бангить протокол PAL, поскольку сам чип не умеет его.

Микроконтроллер выдаёт 8-битный цвет (RGB332, 3 бита красный, 3 бита зелёный и 2 синий) и пассивный ЦАП преобразует это всё в RGB. К счастью в Португалии почти все телевизоры оборудованы разъёмом SCART и они поддерживают RGB вход.

Дорожная карта при сборке Dendy своими руками

Схема, если кто всё-таки дочитал до этапа сборки) Чтобы открыть в полном расширении, на открывшейся картинке правой кнопкой — открыть в новой вкладке и уже левой кнопкой +.

Первым делом

Впаиваем 60-пиновый разъём и проверяем, как прозваниваются все его 60 контактов по дорожкам до тех мест, куда приходит каждый контакт. Почти половина ведёт к СPU, вторая половина — к PPU. Питание и выходы с генератора.

Вторым делом

Собираем схему питания. Разъём питания, диодный мост, стабилизатор с радиатором, конденсаторы до стабилизатора и после, кнопка включения и кнопка resset. Подаём питание и проверяем все последние ножки на всех микросхемах на наличие стабильного питания в +5 вольт. Последняя нога микросхемы +, минус находится на противоположной стороне в конце микросхемы.

Третьим делом

Собираем схему усилителя звука и вывода изображения. После сборки можно проверить работоспособность каскада касаниями к выходам левого и правого каналов с CPU, ножки 1 и 2. При касании к ним рукой должен появляться тихий шум на выходе усилителя звука. На вашем телевизоре, если вы подключили красный и белый выход ко входу аудио)

Касаниями к выходам с PPU ножка 21 на телевизоре при подключенном желтом кабеле к входу видео будет появляться мелкая рябь.

Четвёртым делом

Паяем все детали и каретки для микросхем на плату. Проверяем каждую припаянную деталь трижды: номинал, как припаяли, прозвонили её по месту.

Пятым делом

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

Вставляем картридж и включаем.

Долгие мучения с бубном и тщательная проверка пайки ведёт к запуску данного аппарата)

Жёлтым — каскад аудио и видео усилителей и выходов.

Красным — детали питания схемы.

Синим — генератор частоты — для смены частоты с PAL на NTSC меняется только кварц, PPU и CPU.

Напоследок опишу основные проблемы, которые почерпнул на форуме и с которыми сталкивался сам:

Основная проблема: картинка есть, игра идёт на экране артефакты — битый PPU, не починить никак, только замена на заранее стабильный для проверки.

Вторая причина

Питание есть, ничего не запускается вообще HELP.

Причин море)

Первое и главное: ПАЙКА. Проверяйте 10 раз все детали на работоспособность перед пайкой.

Второе: микросхемы. Очень часто купленные микры не совместимы с китайскими катриками на 400 игр. Не хватает скорости обработки. Проверяйте работоспособность на старых картриджах, которые ещё на капле. У них микры на 5 вольт и там скорость медленнее, чем на новый китайских многоигровках. В моём случае причина незапуска картриджа Кулбой была в микросхеме SN74HC139N. На каплях все катрики работали , а новый 400 в 1 не запускался, пока я её не поменял.

Правильная графическая подсистема

Поскольку микроконтроллер довольно мощный, а использовать его я решил исключительно для генерации видео сигнала (я назвал это VPU — Video Processing Unit), то я решил заодно организовать дабл-буфер.

У меня получилось что второй микроконтроллер (PPU, Picture Processing Unit, чип Atmega1284 тоже на 20 МГц) генерировал картинку в микросхему ОЗУ номер 1 (я назвал её VRAM1), а первый в это же время отправлял содержимое второй микросхемы (VRAM2) в телевизор.

После одного кадра, а два кадра в системе PAL это 1/25 секунды, VPU переключает VRAM-ы и они меняются местами, PPU генерирует картинку в VRAM2, а VPU дампит VRAM1 на ТВ вывод.

Видео плата получилась очень сложной поскольку мне пришлось использовать внешнее железо чтобы оба микроконтроллера могли пользоваться обоими модулями памяти и чтобы ускорить доступ к ОЗУ, ведь там тоже бит-бангинг, так что пришлось добавить чипы 74 серии как счётчики, line-селекторы, трансиверы и тд.

Прошивки для VPU и PPU тоже получились громоздкие поскольку пришлось писать много кода чтобы выжать максимум скорости из графики. Сначала всё было написано на ассемблере, потом часть была переписана на Си.

В результате PPU генерирует картинку 224×192 пикселей, которая потом отпраляется на ТВ через VPU. Может разрешение вам покажется низким, но вообще-то это почти столько, сколько консоли того времени имели на самом деле, обычно 256×224. Несколько меньшее разрешение зато позволило мне добавить больше фич которые система успевает просчитать за один кадр.

Как и в старину, PPU имеет свою жёсткую механику которой надо уметь пользоваться. Подложка (бэк) рендерится из символов 8×8 пикселей, так же называемых тайлами. Получается что размер бэкграунда 28х24 тайла.

Чтобы бэк мог скроллиться плавно, попиксельно, я сделал так что всего есть 4 виртуальных экрана, каждый по 28х24 тайла которые идут в памяти последовательно и обёрнуты вокруг друг друга, на картинке это понятнее.

Поверх бэкграунда, PPU может отрендерить 64 спрайта которые могут быть 8 или 16 пикселей по высоте или ширине, то есть 1, 2 или 4 тайла и ещё могут быть флипнуты горизонтально и/или вертикально.

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

Одна «продвинутая» фича в том, что бэк можно скролить не целиком, а каждую линию в отдельности, что позволяет всякие интересные эффекты вроде сплит скрина или почти-параллакса.

Ещё есть таблица аттрибутов, которая позволяет задавать каждому тайлу значение от 0 до 3, и потом можно всем тайлам с одним аттрибутом задать страницу тайлов или инкрементировать их символьное значение. Это удобно когда есть части бэка которые надо регулярно изменять и CPU не придётся обсчитывать каждый тайл в отдельности, ему достаточно только сказать что-то вроде: «все тайлы с аттрибутом 1 инкрементируйте числовое значение своего символа на 2», подобные вещи реализованые разными техниками можно наблюдать, например, в блочных тайлах в Mario где знак вопроса анимируется или в играх где есть водопад в котором все тайлы постоянно меняются создавая эффект падающей воды.

Что нужно для полноценной ретро консоли

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

— Собственно, сам ноутбук или ПК. Разумеется, рабочий, с древней Windows XP или уставшей «семерочкой». Мощность девайса роли практически не играет. Если на нем уживается Windows XP, работает хотя бы один USB-порт и есть выход на внешний монитор, кандидат к перевоплощению готов.

— USB-флешка. Объем тут прямо влияет на количество игр, которые вы сможете установить. Если нативные игрушки по Sega или Dendy занимают по 100 – 200 КБ, то с образами CD-дисков от Sony PlayStation первого поколения все немного серьезнее. Дистрибутивы занимают от 300 МБ до 700 – 800 МБ. Одним словом, чем больше памяти у флешки, тем лучше.

— Геймпад, а лучше два. Подойдет абсолютно любой контроллер с USB-портом: хоть от именитого за пару сотен рублей. Если хотите устроить настоящий батл, прикупите сразу парочку.

— Внешний монитор или телевизор + соответствующий кабель и переходник. Тут все строго индивидуально. Если есть HDMI – нужен соответствующий кабель, который подходит к вашем телевизору. DVI или VGA — неважно, главное, заставить картинку с ноутбука отображаться на экране телевизор.

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

CPU

Когда моя видеоплата заработала, я начал работать с CPU в качестве которого для моей приставки был выбран Zilog 80.

Одна из причин по который был выбран именно Z80, ну кроме того, что это классный ретро CPU, это его способность адресовать два 16 битных пространства, одно для памяти и второе для портов ввода-вывода, не менее легендарный 6502, например, так не может, он может только одно адресовать 16 битное пространство и в него приходится мапить как память так и различные внешние устройства, видео, аудио, джойстики, апаратный генератор случайных чисел и тд. Удобнее иметь два адресных пространства, одно полность отданное на 64 килобайта кода и данных в памяти и второе для доступа к внешним устройствам.

Сначала я подсоединил CPU к EEPROM в котором разместилась моя тестовая программка и ещё присоединил его через пространство ввода-вывода к микроконтроллеру который я установил чтобы можно было общаться с моим компом через RS232, и мониторить как работает CPU и всё остальное. Этот микроконтроллер Atmega324 работающий на 20 МГц я называю IO MCU — input/output microcontroller unit, он отвечает за контроль доступа к игровым контроллерам (джойстикам), SD карт ридеру, клавиатуре PS/2 и коммуникатору по RS232.

CPU подключается к микросхеме памяти на 128 килобайт, из которых только 56 килобайт доступны, это конечно бред, но я мог достать только микросхемы по 128 или 32 килобайта. Получилось, что память состоит из 8 килобайт ПЗУ и 56 килобайт ОЗУ.

После этого я обновил прошивку IO MCU с помощью этой библиотеки и у меня появилась поддержка SD карт ридера.

Теперь CPU мог ходить по директориям, смотреть что в них лежит, открывать и читать файлы. Всё это делается посредством записи и чтения в определённые адреса пространства ввода-вывода.

Настраиваем приставку

Разумеется, главное – научить Raspberry работать с подходящим геймпадом. Проводные модели практически всегда заводятся из коробки, из беспроводных у меня сразу же подключился Dualshock 3, остальные пришлось вручную настраивать из параметров системы.

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

Из ключевых настроек нужно сделать следующее:

1. Переключить интерфейс на русский язык. Main Menu (Enter на клавиатуре) – System settings – Language. Изначально для подтверждения действий используется клавиша “A”.

2. Подключиться к домашней Wi-Fi сети для удобной загрузки игр. Главное меню – Настройка сети активировать пункт Включить Wi-Fi, ввести имя домашней сети и пароль.

3. Настроить веб-интерфейс. После подключения к сети запоминаем IP-адрес и вбиваем его в браузере на компьютере.

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

Остальные параметры настраиваются уже по желанию.

Подключение CPU к PPU

Следущее, что я сделал это связь между CPU и PPU. Для этого я применил «простое решение» которое заключалось в приобретении двухпортового ОЗУ, это такая микросхема ОЗУ которую можно подключать сразу к двум разным шинам. Это позволяет избавиться он дополнительных микросхем вроде лайн-селекторов и, к тому-же, позволяет практически одновременный доступ к памяти с обоих чипов. Ещё PPU напрямую может обращаться к CPU на каждом кадре активируя свои немаскируемые прерывания. Получается, что CPU получает прерывание на каждом кадре, что полезно для разных задач по таймингу и для понимания когда пора заняться апдейтом графики.

Каждый кадр взаимодествия CPU, PPU и VPU происходит согласно следующей схеме:

  1. PPU копирует информацию из памяти PPU в внутреннюю память.
  2. PPU отправляет сигнал прерывания на CPU.
  3. Одновременно:
      CPU прыгает на функцию прерывания и начинает обновлять PPU память новым графическим состоянием. Программа должна вернуться из прерывания до следующего кадра.
  4. PPU рендерит картинку на основании информации ранее скопированой в одну из VRAM.
  5. VPU отправляет картинку из другой VRAM на ТВ выход.

Примерно тогда же я занялся поддержкой игровых контроллеров, сначала я хотел использовать контроллеры от Nintendo, но сокеты для них проприетарные и вообще их трудно найти, поэтому я остановился на 6-кнопочных контроллерах совместимых с Mega Drive/Genesis, у них стандартные сокеты DB-9 которые везде есть.

Добавляем динамическую графику

Всё было супер, у меня была своя игровая приставка, но мне этого было мало, потому-что приходилось в игре использовать графику прошитую в памяти PPU и нельзя было нарисовать тайлы для конкретной игры и изменить её можно было только перепрошив ПЗУ. Я стал думать как добавить ещё памяти, чтобы CPU в неё мог бы загружать символы для тайлов, а PPU потом мог оттуда это всё считывать и как это сделать попроще поскольку приставка и так уже получалась сложной и большой.

И я придумал следущее: только PPU будет иметь доступ к этой новой памяти, а CPU будет загружать туда данные через PPU и пока этот процесс загрузки происходит, эта память не может быть использована для отрисовки, но можно будет в это время рисовать из ПЗУ.

После конца загрузки CPU переключит внутреннюю ПЗУ память на эту новую память, которую я назвал Character RAM (CHR-RAM) и в этом режиме PPU начнет рисовать динамическую графику, это наверное не лучшее решение, но оно работает. В результате новая память была установлена 128 килобайт и может хранить 1024 символа 8х8 пикселей каждый для бэкаграунда и ещё столько-же символов для спрайтов.

Выбираем операционную систему, на которой будет работать приставка

После подбора компонентов следует определиться с операционной системой будущей консоли. На данный момент существует три хороших сборки, которые подходят для нашей задачи:

Lakka – сборка с красивым визуальным интерфейсом в стиле PlayStation. Проект развивается довольно неспешно, Lakka еще имеет множество глюков и недоработок. ‎ RecalBox – более продвинутое решение «все в одном». После установки образ уже будет содержать пару десятков классических игр для разных платформ. Кроме этого в образ интегрирован медиацентр KODI. В пару нажатий можно превратить игровую консоль в медиакомбайн для проигрывания видео со съемного накопителя, из интернета или сетевого хранилища. Есть возможность настроить IPTV.

RetroPie – еще один многофункциональный эмулятор старых игровых консолей. Изначально в образ не включены игры и нет медиаплеера вроде KODI, однако, присутствует возможность установить RetroPie поверх родной операционной системы для Raspberry – Raspbian. Это значит, что игровой сервис может работать на «‎малинке» одновременно с другими службами, например, с HomeBridge, связывающем умные гаджеты в доме.

Выбирать стоит между двумя последними вариантами. RecalBox – простой образ с играми из коробки и медиацентром KODI, а RetroPie для тех, кто хочет повозиться и установить систему поверх Raspbian.

И наконец звук

До звука руки дошли в последнюю очередь. Сперва я хотел звук наподобие того что есть в Uzebox, то есть чтобы микроконтроллер генерировал 4 канала ШИМ-звука.

Однако, оказалось, что я могу легко достать винтажные чипы и я заказал несколько микросхем FM синтеза YM3438, эти ребята полностью совместимы с YM2612 которые использовались в Mega Drive/Genesis. Установив их можно получить музыку качества Mega Drive и звуковые эффекты производимые микроконтроллером.

Я установил ещё один микроконтроллер и назвал его SPU (Sound Processor Unit), он управляет YM3438 и сам может генерировать звуки. CPU управляет им через двух-портовую память, в этот раз она всего 2 килобайта.

Как и в графическом блоке, звуковой блок имеет 128 килобайта памяти для хранения PCM сэмплов и звуковых патчей, CPU загружает данные в эту память обращаясь к SPU. Получилось, что CPU либо говорит SPU исполнять комманды из этой памяти или обновляет комманды для SPU каждый кадр.

CPU управляет четырьмя ШИМ каналами через четыре циркулярных буфера находящихся в памяти SPU. SPU проходит через эти буферы и исполняет комманды записаные в них. Ещё есть один такой-же буфер для микросхемы FM синтеза.

Итого, как и в графике взаимодействие между CPU и SPU идёт согласно схеме:

  1. SPU копирует данные из памяти SPU во внутреннюю память.
  2. SPU ждёт сигнала прерывания от PPU (это для синхронизации)
  3. Одновременно
      CPU обновляет буферы ШИМ каналов и буферы FM синтезатора.
  4. SPU исполняет комманды в буферах согласно данным во внутренней памяти.
  5. Одновременно со всем этим, SPU обновляет ШИМ звуки на частоте 16 килогерц.

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

На макетной плате сейчас (пока) остался только звук. Вот как всё выглядит на сегодняшний день:

Найти сбалансированную плату для монтажа Dendy своими руками.

Точнее сказать, найти граберы платы, сделанные профессионалами. Такие есть. Хочу выразить благодарность Хардварычу с форума emu-land.net и всем, кто участвовал в проекте по адаптации и настройке платы для Junior.

Так выглядит готовая плата. Заказывал я её у китайских друзей с АЛИ. Приехала она в течении 2 недель. Заказывал 10 штук, приехало 11. За что им и спасибо. По Москве сделать такую плату предлагали в 4 раза дороже. Она полностью подходит под стандартный корпус, имеет стереовыход аудио. Микросхемы выставлены оптимально для распайки и уменьшения длины дорожек.

Сами граберы для вытравливания, версия платы 01. Есть более новая, в ней отличается только расположение одного конденсатора. Считаю такую доработку не новой версией. Выкладывать её не буду. Собирал по версии 01, всё отлично, рабочая и отлично встаёт в стандартный корпус.

Архитектура

Диаграмма иллюстрирует компоненты в каждом блоке и как они взаимодействуют друг с другом. Единственное, что не показано это сигнал от PPU к CPU на каждом кадре в виде прерывания и такой-же сигнал который идёт в SPU.

  • CPU: Zilog Z80 на 10 МГц
  • CPU-ROM: 8KB EEPROM, содержит код загрузчика
  • CPU-RAM: 128KB RAM (56KB доступных), код и данные для программ/игр
  • IO MCU: Atmega324, является интерфейсом между CPU и RS232, клавиатурой PS/2, джойстиками и файловой системой SD карт
  • PPU-RAM: 4 килобайта двухпортовой памяти, промежуточная память между CPU и PPU
  • CHR-RAM: 128KB RAM, хранит динамические тайлы для бэка (подложки) и спрайтов (в символах по 8×8 пикселей).
  • VRAM1, VRAM2: 128KB RAM (43008 реально доступно), используются для фреймбуфера в них пишет PPU и читает из них VPU.
  • PPU (Picture Processing Unit): Atmega1284, рисует кадр во фреймбуфер.
  • VPU (Video Processing Unit): Atmega324, читает фреймбуфер и генерирует RGB и PAL сигнал и синхронизацию.
  • SPU-RAM: 2KB двухпортовая RAM, служит интерфейсом между CPU и SPU.
  • SNDRAM: 128KB RAM, хранит ШИМ патчи, PCM сэмплы и блоки инструкций для FM синтезатора.
  • YM3438: YM3438, микросхема FM синтеза.
  • SPU (Sound Processing Unit): Atmega644, генерирует звуки на принципе широтно-импульсной-модуляции (ШИМ) и управляет YM3438.

Устанавливаем операционную систему на игровую приставку

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

Для начала рекомендую попробовать RecalBox. Здесь самый понятный и дружественный интерфейс, настройка предельно простая, большинство фишек включено из коробки, а в виде бонуса получаем медиацентр KODI, который запросто заменит бюджетную ТВ-приставку для просмотра фильмов с флешки, по сети или онлайн.

1. Скачиваем выбранный образ с сайта разработчика.

2. Скачиваем и устанавливаем приложение Etcher для записи образа на карту памяти.

3. Записываем образ на карту памяти.

4. После окончания записи устанавливаем карту памяти в Raspberry и подключаем её к телевизору.

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

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

Окончательные спецификации

CPU:

  • 8-bit CPU Zilog Z80 на частоте 10Mhz.
  • 8KB ROM для загрузчика.
  • 56KB RAM.

IO:

  • Чтение данных с FAT16/FAT32 SD карт ридера.
  • Чтение/запись в порт RS232.
  • 2 MegaDrive/Genesis-совместимых игровых контроллера.
  • Клавиатура PS2.

Видео:

  • Разрешение 224×192 пикселя.
  • 25 кадров в секунду (половина FPS от PAL).
  • 256 цветов (RGB332).
  • 2×2 виртуальная подложка (448×384 пикселей), с двунаправленым по-пиксельным скроллингом, на базе четырёх полноэкранных страниц.
  • 64 спрайта с шириной и высотой 8 или 16 пикселей с возможностью как вертикального так и горизонтального флипа.
  • Подложка и спрайты состоят из символов по 8х8 пикселей каждый.
  • Символьная видеопамять на 1024 символа для бэкграунда и 1024 для спрайтов.
  • 64 независимых горизонтальных скроллинга по задаваемым линиям
  • 8 независимых вертикальных скроллингов по задаваемым линиям
  • Оверлей на 224х48 пикселей с опциональной прозрачностью по цветовому ключу.
  • Таблица аттрибутов бэкграунда.
  • RGB и композитный PAL через разъём SCART.

Звук:

  • ШИМ на 8 бит и 4 канала, с встроенными вейвформами: квадрат, синус, пила, шум и тд.
  • Сэмплы на 8 бит, 8 КГц в одном из ШИМ каналов.
  • Микросхема FM синтеза YM3438 загружаемая инструкциями на частоте 50 герц.

Для приставки был написан загрузчик. Загрузчик помещается в CPU ПЗУ и может занимать до 8 килобайт. Он использует первые 256 байт ОЗУ. Загрузчик это первое, что исполняет CPU. Он нужен чтобы показать программы находящиеся на SD карте.

Эти программы находятся в файлах которые содержат скомпилированый код и могут также содержать графику и звук.

После выбора программы она загружается в память CPU, память CHR и память SPU. После чего программный код исполняется. Максимальный размер кода загружаемого в приставку 56 килобайт, кроме первых 256 байт и конечно надо учесть место для стека и данных. И этот загрузчик и другие программы написаные для этой приставки создавались одинаковым нижеописаным способом.

Неофициальные ретроконсоли

Прежде чем начать разговор о неофициальных устройствах, стоит сделать важную ремарку: большинство из них находятся в так называемой серой зоне. Сами по себе они не запрещены, но поставляемые в комплекте образы игр являются пиратским ПО. Cybersport.ru не поддерживает деятельность хакеров и «пиратов». Скачивая взломанные игры, вы лишаете разработчиков прибыли — покупайте лицензионные копии в официальных магазинах.

Семейство Android (от ₽2 000 и выше)


1/2

Один из самых распространенных девайсов на рынке представляет собой немного измененную версию Android Box с внешней оболочкой для игр. Чаще всего такие устройства поставляются с двумя дешевыми геймпадами в стиле DualShock 2 и ТВ-пультом. Большой плюс подобных устройств — «всеядность»: на Android выпущено немало эмуляторов, и Console X способны воспроизводить приложения с 60 различных устройств. Конечно, остается вопрос производительности: на более дешевых и слабых девайсах геймеры вряд ли смогут запустить игры с консолей продвинутее PS1, но в отдельных случаях (как, например, в случае Beelink GT-King, оснащенной 4 ГБ RAM) вполне можно рассчитывать на более-менее вменяемую игру даже в тайтлы с PSP или Dreamcast.

Семейство RetroPie (от ₽5 000 и выше)


1/2

На сегодняшний день на рынке присутствует немало девайсов, построенных на плате Raspberry Pi. Можно приобрести плату самостоятельно и собрать устройство с нуля: в интернете немало подсказок для всех этапов, от сборки и установки софта до создания кастомных корпусов. В числе поддерживаемых платформ — устройства в диапазоне от Atari 2600 до Sony PSP (а если использовать Pi 4 — вплоть до SEGA Dreamcast). При самостоятельной сборке выходит дешевле, но сложнее в эксплуатации. Впрочем, все инструкции находятся в свободном доступе, остается только подобрать ядра эмуляторов.

Мини-ПК (от ₽4 500 и выше)


1/2

В последнее время набирают популярность сборки на основе ПК: небольшие устройства не сильно превышают в размерах девайсы на Android, но при правильном подходе при сборке дешевле $100 можно получить довольно убедительную ретромашину. При установке особой системы можно добиться как высокой производительности, так и огромной библиотеки игр на любой вкус, как с аркад, так и с домашних консолей начала нулевых. В продаже можно найти в том числе и готовые устройства с предустановленными играми и эмуляторами. Слова здесь излишни: это привычный ПК, просто в небольшом корпусе, со всеми его плюсами и минусами. За более высокую стоимость можно купить вполне приличное устройство, воспроизводящее игры вплоть до PS2 и Wii.

Memory/IO Mapping

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

CPU обращается к оперативной и постоянной памяти загрузчика через адресное пространство памяти.

Адресное пространство памяти

А к PPU-RAM, SPU-RAM и IO MCU через адресное пространство ввода-вывода.

Адресное пространство ввода-вывода

Как видно из таблицы, внутри адресного пространства ввода-вывода выделены адреса для всех устройств, IO MCU, PPU и SPU.

Управление PPU

Из информации в таблице видно, что для управления PPU надо писать в память PPU которая доступна по адресам 1000h-1FFFh в адресном пространстве ввода-вывода.

Распределение адресного пространства PPU

PPU Status может принимать следущие значения:

  1. Режим вшитой графики
  2. Режим динамической графики (CHR-RAM)
  3. Режим записи в CHR память
  4. Запись завершена, ждём подтверждения режима от CPU

Вот, например, как можно работать со спрайтами: Приставка может рисовать 64 спрайта одновременно. Данные по ним доступны через CPU через адресное пространство ввода-вывода по адресам 1004h-1143h (320 байт), на каждый спрайт приходится 5 байт информации (5 * 64 = 320):

  1. Байт разных флагов, каждый бит этого байта флаг: Active, Flipped_X, Flipped_Y, PageBit0, PageBit1, AboveOverlay, Width16, Height16.
  2. Байт символа, номер символа из таблицы (определяемой флагами выше).
  3. Байт цветового ключа (то есть какой цвет — прозрачность)
  4. Байт координаты X
  5. Байт координаты Y

Итого, чтобы увидеть спрайт, надо установить флаг Active в 1, и задать координаты X и Y в пределах видимости, координаты 32/32 помещают спрайт в верхний левый угол экрана, меньшие значения спрячут его либо сделают частично видимым.

Потом мы можем установить код символа и цвет прозрачности.

Например, если нам нужно показать спрайт номер 10, то адрес будет 4145 (1004h + (5 x 9)), пишем значение 1 для активирования и координаты, например, x=100 и y=120, пишем по адресу 4148 значение 100 и по адресу 4149 значение 120.

Настройка геймпада (джойстика)

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

Чтоб настроить геймпад, откройте «Настройки», затем «Система». Подключите ваше устройство и перейдите в раздел «Ввод», после «Настройка подключенных контроллеров»:

Выберите тип вашего джойстика и настройте значения кнопок:

На этом всё. Как видите, всё просто до безобразия. А Вы думали, что ваш Smart TV способен быть игровой приставкой?

Если у Вас остались какие-то вопросы, пишите в комментарии и вместе мы всё решим.

В закладки

Пожалуй, у многих есть старый ноутбук или морально устаревший компьютер. Такой агрегат и выбросить жалко, и денег на площадке частных объявлений с него не выручишь.

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

Используем ассемблер

Один из способов программирования для приставки это ассемблер.

Вот пример как показать один спрайт и анимировать его чтобы он двигался и отталкивался от краёв экрана.

ORG 2100h PPU_SPRITES: EQU $1004 SPRITE_CHR: EQU 72 SPRITE_COLORKEY: EQU $1F SPRITE_INIT_POS_X: EQU 140 SPRITE_INIT_POS_Y: EQU 124 jp main DS $2166-$ nmi: ; обработчик немаскируемого прерывания (NMI) ld bc, PPU_SPRITES + 3 ld a, (sprite_dir) and a, 1 jr z, subX in a, (c) ; увеличить X inc a out (c), a cp 248 jr nz, updateY ld a, (sprite_dir) xor a, 1 ld (sprite_dir), a jp updateY subX: in a, (c) ; уменьшить X dec a out (c), a cp 32 jr nz, updateY ld a, (sprite_dir) xor a, 1 ld (sprite_dir), a updateY: inc bc ld a, (sprite_dir) and a, 2 jr z, subY in a, (c) ; увеличить Y inc a out (c), a cp 216 jr nz, moveEnd ld a, (sprite_dir) xor a, 2 ld (sprite_dir), a jp moveEnd subY: in a, (c) ; уменьшить Y dec a out (c), a cp 32 jr nz, moveEnd ld a, (sprite_dir) xor a, 2 ld (sprite_dir), a moveEnd: ret main: ld bc, PPU_SPRITES ld a, 1 out (c), a ; активировать спрайт 0 inc bc ld a, SPRITE_CHR out (c), a ; задать символ спрайту 0 inc bc ld a, SPRITE_COLORKEY out (c), a ; установить цветовой ключ спрайту 0 inc bc ld a, SPRITE_INIT_POS_X out (c), a ; установить координату Х спрайту 0 inc bc ld a, SPRITE_INIT_POS_Y out (c), a ; установить координату Y спрайту 0 mainLoop: jp mainLoop sprite_dir: DB 0

Использование языка Си

Можно также использовать язык Си, для этого нам понадобится компилятор SDCC и некоторые дополнительные утилиты.

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

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

#include #define SPRITE_CHR 72 #define SPRITE_COLORKEY 0x1F #define SPRITE_INIT_POS_X 140 #define SPRITE_INIT_POS_Y 124 struct s_sprite sprite = { 1, SPRITE_CHR, SPRITE_COLORKEY, SPRITE_INIT_POS_X, SPRITE_INIT_POS_Y }; uint8_t sprite_dir = 0; void nmi() { if (sprite_dir & 1) { sprite.x++; if (sprite.x == 248) { sprite_dir ^= 1; } } else { sprite.x—; if (sprite.x == 32) { sprite_dir ^= 1; } } if (sprite_dir & 2) { sprite.y++; if (sprite.y == 216) { sprite_dir ^= 2; } } else { sprite.y—; if (sprite.x == 32) { sprite_dir ^= 2; } } set_sprite(0, sprite); } void main() { while(1) { } }

8-битная игровая приставка своими руками ?

Итак, представляем Вашему вниманию UZEBOX!

Это homebrew-консоль, которую можно изготовить дома.

Базируется она всего на 2х чипах — ATMega 644 и кодер NTSC-сигнала AD725 (опционально, есть версия с ЧБ изображением, но без этого кодера)

Текущие фичи с сайта разработчков консоли (без перевода, чтобы не играть в испорченный телефон):

  • Low parts count and cost: The system is made of only two chips and discrete components.
  • Interrupt driven kernel: No cycle counting required, sound mixing and video generation are all made in the background.
  • 256 simultaneous colors: Accomplished by using a R-2R resistor ladder DAC.
  • 4 channels sound engine: The sound subsystem is composed of 3 wavetable channels and 1 noise or PCM channel.
  • MIDI In: With a music sequencer, allows the creation of music directly on the console.
  • Retro controllers: The joypad inputs uses standard NES/SNES controllers interface.
  • SNES Mouse Support
  • SD/MicroSD card interface
  • Expandable: I/O lines and peripherals are still available, like the UART and SPI port for one to experiment.
  • Emulator: A fully, cycle-perfect, emulator was developed and greatly eases development.
  • Gameloader (beta): Load and flash games stored on SD cards!
  • API: Develop games using an API that provides multiple video modes, sound driver and more.
  • Open Source: The software and hardware design are totally free and licensed under the GPL.

Спецификации: CPU: ATmega644 microcontroller Total RAM: 4K Program Memory: 64K Speed: 28.61818Mhz (Overclocked) Colors: 256 simultaneous colors arranged in a 3:3:2 color space (Red:3 bits, Green:3 bits, Blue: 2 bits) Resolution: Up to 240×224 pixels (tiles-only and tiles-and-sprites modes) Sprites: Up to 32 simultaneous sprites on screen at any time Video output: NTSC Composite and S-Video Sound: 4 channels wavetable, 8-bit mono, mixed at

15Khz and output via PWM Inputs: Two NES/SNES compatible joypad inputs Options: MIDI-in interface and s-video output

Для тех, кто не дружит с электроникой, с сайта разработчиков можно скачать эмулятор (для Windows, требуется SDL.dll) и попробовать консоль без риска попортить детали.

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

А теперь будут слайды. Кликабельные.

Динамическая графика

(В оригинале Custom graphics. прим. пер.)

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

Цель у меня была такая, чтобы вся необходимая графика в бинарной форме сразу грузилась в оперативную память CHR, причём делать это умеет код в загрузчике из ПЗУ. Для этого я сделал несколько картинок правильного размера с разными полезными символами:

Поскольку память динамической графики состоит из 4-х страниц по 256 символов 8х8 пикселей каждый и 4-х страниц таких же символов для спрайтов, я перевёл картинки в PNG формат, удалил повторяющиеся одинаковые:

И потом использовал самописную тулзу чтобы перевести это всё в бинарный формат RGB332 с блоками 8х8.

В результате имеем файлы с символами, где все символы идут последовательно один за другим и каждый занимает по 64 байта.

В чем оптимизация, брат

  1. Уменьшили персонажей: маленькие спрайты — меньше памяти.
  2. Оптимизировали графику: вместо больших повторяющихся картинок — много маленьких повторяющихся картинок.
  3. Оптимизировали архитектуру уровней: сделали их симметричными, но сдвинули ряды по кругу влево-вправо, чтобы добавить разнообразия.
  4. Для дополнительного разнообразия ввели новые цветовые палитры.
  5. Более сложные уровни не хранили в памяти целиком. Для них хранились лишь дополнительные ловушки и враги. А на фоне лежали те же старые уровни.
  6. И всё это на чистом Ассемблере.

Звук

Волновые RAW сэмплы переведены в 8-битный 8-килогерцовые PCM сэмплы.

Патчи для звуковых эффектов на ШИМ и музыки пишутся особыми инструкциями.

Что касается микросхемы FM синтеза Yamaha YM3438, то я нашел программку называемую DefleMask которая выдаёт музыку синхронизируемую по PAL и предназначеную для YM2612 микросхемы из Genesis, которая совместима с YM3438.

DefleMask экспортирует музыку в формате VGM и я её конвертирую ещё одной самописной утилитой в свой собственный двоичный формат.

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

Эмулятор

Я написал эмулятор своей приставки на С++ с применением wxWidgets, чтобы проще было девелопить для неё.

CPU эмулируется библиотекой libz80.

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

По графике, я могу заглянуть в видео память, в таблицы символов и в саму CHR память.

Вот пример программы запущеной на эмуляторе со включёнными средствами отладки.

Эти видео снимались камерой смартфона направленой на экран ЭЛТ телевизора, прошу прощения за неидеальное качество картинки.

Интерпретатор БЭЙСИКа программируемый с PS/2 клавиатуры, после первой программы, я показываю как писать напрямую в память PPU через адресное пространство ввода-вывода активируя и двигая спрайт:

Демка графики, в этом видео программно скачут 64 спрайта 16х16, на фоне бэкграунда с динамическим скроллингом и оверлеем который двигается под и над спрайтами:

Звуковая демка показывает возможности YM3438 и ШИМ звук, звуковые данные этой демки и FM музыка и ШИМ звуки вместе занимают почти все доступные 128 килобайт звуковой памяти.

Тетрис, для графики использваны почти только возможности бэкграунда, музыка на YM3438, звуковые эффекты на ШИМ патчах.

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

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

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

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

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

Логика игры

Чтобы в игру было интереснее играть дольше пяти минут, разработчики поставили такие требования:

  1. Это будет платформер — игра, где главному герою нужно бегать и прыгать по платформам, залезать наверх и скакать через препятствия.
  2. Герой сможет ловко двигаться и стрелять по врагам.
  3. Чтобы можно было играть компанией, делают мультиплеер на четырёх человек.

Так как у нас ограничения по памяти, всю игру пишут на Ассемблере — это язык, который работает напрямую с процессором. С одной стороны, код Ассемблера исполняется очень быстро; с другой — в нём работа идёт тупо с перекладыванием данных из одной ячейки процессора в другую. Это примерно как готовить суши, работая с индивидуальными рисинками.

Память распределили так:

  • 8 килобайт на графику,
  • 32 килобайта на сам код игры и хранение данных.
Рейтинг
( 2 оценки, среднее 4.5 из 5 )
Понравилась статья? Поделиться с друзьями:
Для любых предложений по сайту: [email protected]