Raspberry pi 3 model b ретро консоль

Raspberry Pi в картридже от NES

Ностальгия

В детстве мы, кому сейчас за 25-35, любили играть в приставки. Тогда не было новомодного слова консоли, поэтому буду называть их так. Мое знакомство с приставками началось с Денди (клон NES). Super Mario Bros, Contra, Ducktales, Battletoads это лишь часть хитов того времени. Затем всем двором собирались поиграть у моего друга в Сегу (Sega Mega Drive), в такие хиты как Sonic, Ultimate Mortal Combat 3, Contra Hard Corps и другое. А уж когда вышла Play Station, надо сказать, она добралась к нам не сразу, то серия Resident Evil вызывала какой-то по истине пугающий восторг.

Смахнуть слезу ностальгии мне помогла эта картинка. Надо сказать, я не первый, кто придумал вставить Raspberry Pi в корпус от картриджа NES. Да, это не мое устройство. И этот картридж подходит для этих целей практически идеально, он маленький и красивый. А внутри много места. Судите сами.

Внутри Raspberry Pi Zero, USB хаб, и пара удлинителей. Все палки посажены на гов термоклей.

Сборка

Захотелось собрать нечто тоже самое или похожее. Был выбран такой же картридж от NES. Другие варианты либо совсем маленькие, либо выглядят не очень. В качестве пламенного сердца ретро-машины выступил Raspberry Pi 3B. Были закуплены на али, также, USB разъемы с удобными выводами для пайки. Вот это вот всё.

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

Также вам понадобится специальная отвертка nes screwdriver, если картридж закручивается на три шурупа. Есть также ранние варианты картриджей с пятью шурупами, они откручиваются обычной плоской отверткой. У меня как раз такой.

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

С Raspberry Pi были спаяны выступающие разъемы. Знатоки говорят, что можно обойтись и без паяльной станции, если сначала аккуратненько разобрать разъемы кусачками, а потом выпаять по одной ножке. Всё наклеено на термоклей. Между разъемами USB и малинкой проложил изолятор из неплавящегося пластика. Не забывайте соединять GND Raspberry Pi и корпус USB разъема (на картинке выше не показано). Иначе некоторые джойстики не будут работать.

На малинку был установлен последний Retropie. Поначалу стоял Recalbox, но я от него отказался, поскольку у него не поддерживается вибрация джойстиков на приставках Playstation 1. Но надо сказать, Recalbox чуть удобнее, в плане того, что работает из коробки и не надо ничего настраивать. В Retropie куча настроек, настраивать можно бесконечно. Этим он мне и понравился.
Вот что получилось. Подключаются любые джойстики с xinput.

Экран

Аппетит приходит во время еды. Как насчет встроить экранчик в картридж? Для игры или вывода изображения обложки игры. Был заказан такой экран. Это 800*480 3,5 дюймовый экран с параллельным интерфейсом DPI, который использует почти все GPIO Raspberry Pi. У меня он работает в режиме 120 Hz (но рендер все равно в 60 Hz), отклик мгновенный. Единственный минус — это 6 битная матрица. Всего 262 144 цвета. Хотя, в общем-то, это особо не заметно, судите сами.

Скриншот из игры Comix Zone (Кликабельно)

Все ножки с экрана и Raspberry Pi были спаяны. Экран был припаян двумя шлейфами с раздербаненного старенького кабеля IDE. Под экран установлены закладные в 5мм, он не касается нижней стенки картриджа. По периметру дисплея наклеена изолента, чтобы не было боковых засветов. Все приклеено на термоклей. На верхней крышке я прорезал окно и вклеил стекло толщиной 2мм.

Для того, чтобы запустить вывод изображения на этот экран, надо поправить конфиг /boot/config.txt. Рекомендую для обладателей Windows программу WinSCP, которая соединяясь с Raspberry Pi по SSH, дает представление файлов как в Total commander’e. Очень удобно. Особенно, если запустить ее в режиме shell sudo su —, которая дает доступ ко всем файлам.

К сожалению, когда включен DPI экран, вывод видео по HDMI не работает. Поэтому я создал в папке /boot/ два конфига, один config_hdmi.txt, второй config_dpi.txt. В конфиге config_hdmi.txt выставлено разрешение 1080p60Hz и убран overscan. config_dpi.txt содержит настройки DPI экрана.

Переключать конфиги будет наш автоскрипт который доступен по сети
\\192.168.x.xxx\configs\all\autostart.sh или в папке на устройстве /opt/retropie/configs/all/autostart.sh

Также был написан скрипт switchscreen.sh, который надо положить в /home/pi/RetroPie/retropiemenu/. Этот скрипт переключает конфиги вручную и доступен из главного меню настроек Retropie. Надо после его запуска вытащить кабель HDMI, а то после перезагрузки всё переключится обратно автоматически. Не забудьте скрипту прописать

В autostart.sh видны следы кода, отключающие подсветку DPI экрана, когда включен HDMI. Этот скрипт я скопипастил в интернете, так что на нашем экране это не работает. Можно было бы заморочиться с транзисторами, чтобы отключать питание экрана, но зачем, если нам надо выводить картинку обложки в данный момент запущенной игры. Надо только разобраться, что такое DPI.

Parallel Display Interface (DPI)

DPI, как было сказано, это параллельный интерфейс для экранов. Информации по этому интерфейсу раз, два и обчелся. Ну а теперь еще и здесь будет, на русском.

Все попытки включить DPI консольными командами во время работы HDMI результатов не дали. Возможно делал что-то не то. Был принят к реализации план Б: выводить изображение на малый экран, дергая программно за ножки GPIO.

DPI характеризуется тем, что один пиксель передается дисплею за один такт сигнала clock. Поскольку у нас матрица 6-битная, то это 18 выводов для трех цветов, а также присутствуют выводы display enable (обозначает валидную дату), h_sync (устанавливает нулевой адрес горизонтальной строки в контроллере дисплея), v_sync (устанавливает нулевой адрес вертикальной строки в контроллере дисплея). Защелкивание данных происходит по заднему фронту сигнала clock. Это известно, если расшифровать строчку «dpi_output_format=0x6f015» из нашего config_dpi.txt согласно этой терминологии.

Последовательность битов приведена на рисунке выше. На каждую строчку, начинающуюся с VSYNC, приходится полный цикл тактов строчки HSYNC. Это на один кадр. Back и Front porch это так называемые отступы у дисплея, которые есть в памяти контроллера, но их нет на экране.

Теперь расшифруем строку «hdmi_timings=480 0 16 16 24 800 0 4 2 2 0 0 0 120 0 46080000 6» из нашего config_dpi.txt. Здесь ничего сложного нет, просто записываем параметры по порядку.

Какие GPIO ноги используются для передачи цветов, показано на этой картинке. У нас Mode 5. Внимание, это не ноги по порядку, а именно обозначения GPIO! Остальные сигналы Clock — GPIO 0, DE — GPIO 1, VSYNC — GPIO 2, HSYNC — GPIO 3.

Быстренько был установлен питон, необходимая GPIO библиотека и написан hello-скрипт хотя бы окрашивающий экран в синий цвет. А еще у меня был когнитивный диссонанс, когда Notepad++ на Windows не показывал отступы, там где они были в nano, при этом при переносе строк делал табуляцию, а не пробелы. Кстати, VSCode тем же самым грешит, как поправить, не нашел.

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

Принято решение переписать всё на С. Работает резвее, примерно несколько кадров в секунду. Экран рябит как на старых ЭЛТ мониторах или радарах. То что надо. Ретро! Код выложил на GitHub.

Доступ к GPIO осуществляется напрямую, через регистры SoC чипа BCM2837. Примеры кода брал здесь.

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

Чтобы запустить код, надо скопировать содержимое репозитория в папку /home/pi/lcd_screen/ (Кто знает как на C под nix написать путь относительно бинарника, а не рабочей папки? Поэтому пока только в эту папку) и выполнить следующие команды.

Либо скачать сразу бинарник из релизов. Чтобы запустить, надо набрать следующее. SUDO требуется для доступа к GPIO.

Где «path/file.bmp» — путь до файла изображения, работает только с BMP форматом, «usec_per_frame» — задержка между кадрами в микросекундах, чтобы напрасно не грузить процессор.

Автоматизируем запуск нашей программки lcd, чтобы она выводила нужную обложку, когда игра запущена. Конечно же, для загрузки обложек в Retropie используется встроенный scrapер.
Установим конвертер изображений. Он будет конвертить все форматы в bmp, поддерживаемый программой. Заодно и изменять размер, чтобы изображения были на весь экран.

В директории /opt/retropie/configs/all/ создадим два файла: runcommand-onstart.sh и runcommand-onend.sh. Эти скрипты Retropie автоматически выполняет при загрузке/завершении любой игры. Не забудьте прописать chmod +x каждому файлу.

В стартовом скрипте сначала проверяется наличие DPI соединения, затем ищется изображение с форматами jpeg или png, поворачивается на нужный угол, изменяется его размер и конвертится в формат bmp, потом запускается моя программа с необходимыми параметрами.

Охлаждение

Raspberry Pi 3B мощнее, чем Zero, и ему необходимо хорошее охлаждение. Особенно в таком закрытом корпусе. С небольшим радиатором, видимым на фото, через полчаса игры на любом эмуляторе температура ядра достигала 80 градусов и начинался тротлинг.

Был заказан центробежный вентилятор 40*30*10 мм, но пока он не приехал, я просто попробовал выпилить из 3 мм алюминия небольшую пластину, размером 80*30 мм. К тому времени все пины GPIO я выпаял, поэтому они уже не мешались установке пластины. Дополнительно еще выпилил кусочек 20*10мм для контакта с чипом и сделал из пластин бутерброд. Это превзошло все мои ожидания, максимум 65 градусов на ядре.

Так это выглядит внутри.

В итоге что

Как это играется? Отлично! С криками, битьем геймпадов, взаимными упреками. Прямо как когда-то.

Никаких задержек и лагов замечено не было.

Экранчик, конечно, маловат, всего три с половиной дюйма. Разбаловали нас смартфоны с пятью дюймами, но играть можно. Текст читается, даже мелкий. Предпочитаю HDMI.

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

К сожалению, штатный звук Raspberry Pi оставляет желать лучшего. В качестве звуковой системы применена ШИМ модуляция с пассивной фильтрацией. Поэтому был закуплен USB ЦАП на PCM2704. Главным образом, из-за своих размеров.

Очень не хватает вывода звука при игре на маленьком LCD экранчике, поэтому куплен также микроусилитель 3W на NS8002 и подобран динамик от планшета на 8 Ом.

Всё это поместится под LCD экраном. Приедет, буду ставить.

Подпиливаем Retropie

Сборка окончена. Далее приведу некоторые менее интересные для развлекательного чтения особенности настроек Retropie.

Большинство приставок, которые способен эмулировать Raspberry Pi, выдает разрешение 320×240 пикселей. По сегодняшним меркам это очень мало. Все игры приобретают ярко выраженную пикселизацию на современных экранах.

Создатели Retroarch, который входит в состав Retropie, озаботились этим вопросом и добавили поддержку шейдеров. Например, мне очень нравится предустановленный xbr-lv1-noblend.glslp. Он, буквально, вытягивает детали из картинки. См. ниже.

Скриншот из игры Castlevania: Symphony of the Night, советую в нее сыграть

Чтобы установить шейдер, зайдите в меню Retropie -> Configuration editor. Выберите Configure basic libretro emulator options, после выберите Configure default options for all libretro emulators. Затем установите Video Shader Enable в «true» и Video Shader File на желаемый шейдер. Установите также Video Smoth в «false», поскольку он только смазывает картинку. Можно даже выбрать что-то типа scanline шейдера, который эмитирует работу CRT телевизоров. Но это на любителя.

Если у вас есть любой xinput геймпад (стандарт Micro$oft), он подойдет. Настраивается он при первом же запуске Retropie, либо через кнопку старт — Configure Input. Но и тут есть головная боль. Ушлые заокеанские ребята, чтобы не попадать на патентные судебные иски поменяли местами кнопки с A и B, X и Y.

Если у вас геймпад от xbox или аналогичный, то настраивать надо с перевернутыми кнопками, как на NES. Затем зайти в Retropie -> Retropie Setup, выбрать Configuration / tools, затем emulationstation, поставить в Swap A/B Buttons in ES «Swapped». Потом заново переконфигурируйте джойстик.

Также, мне не нравится, как разработчики Retropie распорядились кнопочным фондом. Где комбинация кнопок сделать скриншот? Зачем мне кнопка reset, если я на нее попадаю каждый раз? Где кнопки перемотки и ускорения времени?

Чтобы это исправить, нужно подредактировать файл с названием вашего джойстика в /opt/retropie/configs/all/retroarch-joypads/. Также он доступен по сети \\192.168.x.xxx\configs\all\retroarch-joypads\. После каждого обновления Retropie через апдейтер, нумерация привязки слетает, поэтому я не буду выкладывать весь конфиг. Напишу, что изменил лишь эти кнопки. Они выполняются при нажатии одновременно с Hotkey-м, обычно это кнопка с логотипом, посередине джойстика.

Здесь кнопка скриншотов назначена вместо reset. Fast forvard и rewind (перемотка назад) настроены на кнопки крестовины: вперед и назад. Кнопки крестовины вверх и вниз изменяют слот сохранения.

Rewind надо включить в конфиге /opt/retropie/configs/all/retroarch.cfg. Только не включайте Rewind на эмуляторе psx, всё начинает дико тормозить. Перемотка назад, по-умолчанию, отключена в конфиге psx.

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

Xboxdrv

Но и это еще не всё. В Retropie Setup в менеджере пакетов можно поставить различные порты, например Openttd, Doom или вообще DOS эмулятор Dosbox. Но управлять в них джойстиком не получится. Только клавиатурой и мышкой. Чтобы это исправить, нужно поставить в менеджере пакетов драйвер xboxdrv, который умеет эмулировать нажатия клавиатуры. Просто поставить из исходников, автозапуск делать не нужно, он не подходит под все джойстики.

Скрипт запуска напишем сами под наш геймпад. Добавим в /opt/retropie/configs/all/runcommand-onstart.sh следующие строки в конец файла.

Здесь $1 — наша целевая система, при которой запускается xboxdrv. Можно добавлять по аналогии. Строки —evdev-absmap —evdev-keymap отвечают за привязку осей и кнопок к вашему джойстику. Скрипт выше дан для контроллера Xbox One S. Чтобы узнать какая ось и кнопка соответствуют номеру или названию вашего джойстика, нужно в консоли набрать команду evtest. Заодно можно посмотреть какой event соответствует нашему джойстику. У меня это /dev/input/event0 который стоит в параметре —evdev.

Параметры —ui-axismap эмулируют оси мыши, а —ui-buttonmap кнопки клавиатуры. В данном примере курки — это кнопки мыши, левый стик — мышь, правый стик — курсорные клавиши. Старт, селект — enter и esc, соответственно. На остальные кнопки привязаны цифры клавиатуры. Задействовать крестовину под кнопки клавиатуры, к сожалению, не удалось. Почему-то на джойстике Xbox One S отказывается работать.

С таким конфигом отлично играются стратегии, наподобие Theme Hospital, OpenTTD и пр. Чуть хуже играется в шутеры, но вы можете создать аналогичные скрипты запуска под шутеры в этом же файле, меняя там параметр $1.

Чтобы обеспечить нормальную работу джойстика в emulationstation, нужно завершить xboxdrv после выхода из игры. Для этого в конец файла /opt/retropie/configs/all/runcommand-onend.sh добавляем следующее.

Однажды, я запустил обновление Retropie и при распаковке ядра отвалился встроенный Wi-Fi. Устройство загружалось, но не реагировало ни на какие кнопки, в том числе на подключенной клавиатуре. SSH нет, так как нет Wi-Fi, на клавиатуру не реагирует, а SD карточку не достать…

Заметил, что клавиатура работает при загрузке. Понажимал много раз ctrl+c и, о, консоль! Но как теперь восстановить Wi-Fi? Интерфейс wlan0 отсутствовал от слова совсем. Запуск апдейтера не помог, поскольку он подтягивает файлы с интернета.

Первым делом в /opt/retropie/configs/all/autostart.sh закомментировал запуск emulationstation и перезагрузился. После перезапуска загружается консоль, клавиатура работает. Дальнейшее гугление, как вернуть wlan дало вот это. Команда переконфигурирует все установленные пакеты. Помогло.

При загрузке приставки мне не хочется смотреть на лог загрузки Linux. Он портит весь дух приставок девяностых.

Чтобы убрать лог загрузки Linux, нужно привести файл /boot/cmdline.txt к такому виду. Всё в одну строку.

Кратко, конфиг убирает лого, выводит сообщения в другую консоль, убирает мигающий курсор.
Затем убираем весь текст в motd.

Убираем автологин текст.

Нужно в этом файле изменить строку

Более подробно про это написано здесь.

Также, при загрузке системы можно вывести свое фото — splashscreen. Можно и несколько, они будут сменять друг друга со временем. Нужно положить свои картинки в папку в сети \\192.168.x.xxx\splashscreens, и выбрать их в меню Retropie -> SPLASH SCREEN -> Append Splashscreen to list.

Мне, например, безумно нравится вот эта картинка.

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

Что еще можно сделать

Улучшать можно бесконечно. Приведу еще пару ссылок, что можно сделать. Пишите еще интересные штуки, которые можно добавить. Спасибо за внимание.

Источник

Adblock
detector