Прошиваем эмулятор Retro-Go на Nintendo Game & Watch

3 апреля 2023

Game & Watch: Super Mario Bros — это портативная игровая консоль, выпущенная Nintendo в 2020-м году по случаю 35-и летия игр про Марио. Консоль напоминает игры Game & Watch из 80-х годов, но имеет цветной дисплей. Спустя год вышла аналогичная игровая консоль Game & Watch: The Legend of Zelda. Оба устройства имеют по три игры. Две из них — игры соответствующей серии (Марио / Зельда) под Famicom, и еще одна игра в стиле Game & Watch из 80-х. Вскоре энтузиасты научились прошивать больше трех игр. Этим мы сегодня и займемся.

Важно! Повторяйте описанные шаги на свой страх и риск. Автор данных строк, ровно как и разработчики соответствующего софта, не несут ответственности за ваш потенциально окирпиченный Game & Watch.

Закупаемся

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

Портативная игровая консоль Game & Watch: Super Mario Bros

Мне больше нравятся цвета этой версии. Устройство действительно напоминает геймпад от Famicom. Также, в Марио я хоть немного играл, в отличии от Зельды. Подставка была напечатана на 3D-принтере. Модель подставки доступна здесь.

Помимо самого G&W нам понадобится программатор STLink, а также виртуалка или ноутбук с Linux. Разработчики скриптов, которые мы будем использовать, рекомендуют Ubuntu или совместимые дистрибутивы. Поддержка MacOS не заявлена. Я использовал ноутбук с Ubuntu 22.04 LTS.

На Raspberry Pi версии ≤3 повторить описанные шаги не выйдет. Некоторые зависимости не удастся скомпилировать из-за ограниченного количества памяти.

Наконец, нам понадобится чип MX25U51245GZ4I00. Он доступен на AliExpress. Чип представляет собой 64 Мб SPI flash памяти. В моем устройстве всего лишь 1 Мб флеш-памяти (Зельда имеет 4 Мб), и много игр в нее не записать. Поэтому чип будем перепаивать.

Замена SPI flash памяти в Nintendo Game & Watch

На приведенной иллюстрации сверху показан оригинальный чип (даташит [PDF]), а снизу — тот, который будем впаивать на замену (даташит [PDF]). Они имеют разные корпуса, но совместимы по пинам. Первый чип может быть заменен на второй без модификации платы.

Ставим зависимости

На Linux-ноутбуке говорим:

mkdir game-and-watch
cd game-and-watch

Ставим зависимости:

sudo apt install p7zip-full python3-pip gcc-arm-none-eabi \
  binutils-arm-none-eabi stlink-tools libtool pkg-config \
  libusb-1.0-0-dev libhidapi-hidraw0 libftdi1 libftdi1-2

Еще нам понадобится пропатченная версия OpenOCD:

git clone git@github.com:openocd-org/openocd.git
mkdir openocd-git
cd openocd
wget "https://raw.githubusercontent.com/kbeckmann/ubuntu-openocd-"\
"git-builder/master/0001-Extend-bank1-and-enable-bank2-"\
"of-STM32H7B0VBTx.patch"
git am < 0001-Extend-bank1-and-enable-bank2-of-STM32H7B0VBTx.patch
./bootstrap
./configure --prefix=/home/eax/game-and-watch/openocd-git \
  --enable-stlink
make -j4
make install

Затем объявляем такую переменную окружения:

export OPENOCD="/home/eax/game-and-watch/openocd-git/bin/openocd"

С ее помощью скрипты найдут правильную версию OpenOCD. Рекомендую сразу добавить эту строчку в ~/.bashrc.

Бэкапимся

С обратной стороны устройства выкручиваем 4 самореза. Здесь понадобится трехгранная (Y-образная) отвертка. Внутри видим следующее:

Внутренности игровой консоли Nintendo Game & Watch

Сердцем устройства является микроконтроллер STM32H7B0VBT6. Рядом с ним находится SPI flash, который мы уже опознали. Остальные компоненты, вроде контроллера заряда аккумулятора и регуляторов напряжения, особого интереса не представляют. С обратной стороны платы ничего нет, кроме контактных площадок для кнопок.

Отстегиваем аккумулятор. Разъем вынимается вверх, а не в сторону. Теперь наша задача — припаяться к SWD пинам. Они выведены справа от микроконтроллера:

Распиновка SWD в игровой консоли Nintendo Game & Watch

У Зельды распиновка та же, только справа есть два дополнительных контакта. Отмеченные выводы подключаем к соответствующим пинам программатора. STLink подключаем к ноутбуку, сам G&W запитываем штатным образом, через разъем USB-C, от внешнего источника питания. Устройство должно быть включено и показывать время.

Выполняем команды:

git clone --recurse-submodules \
  git@github.com:ghidraninja/game-and-watch-backup.git
cd game-and-watch-backup
./1_sanity_check.sh stlink mario

Должны увидеть:

Running sanity checks...
Looks good!

Далее:

./2_backup_flash.sh stlink mario

В случае успеха увидим:

...
Validating checksum...
Looks good! Successfully backed up the (encrypted) SPI flash to ⏎
  backups/flash_backup_mario.bin!

Далее:

./3_backup_internal_flash.sh stlink mario

Следуем инструкциям. В конце должны получить:

...
Dumping internal flash...
Verifying internal flash backup...
Device backed up successfully

На этом шаге в каталоге backup/ должно быть три .bin файла. Это очень важные файлы. Они позволят раскирпичить устройство, если во время прошивки что-то пойдет не так. Сохраните их в надежном месте.

Теперь нужно зажать боковую кнопку на G&W и выполнить:

./4_unlock_device.sh stlink mario

Ожидаемый вывод:

...
Unlocking device... (Takes up to 30 seconds.)
Congratulations, your device has been unlocked. Just a few more steps!
- The Game & Watch will not yet be functional
- Disconnect power from the device for the changes to take full effect
- Power it again
- Run the 5_restore.sh script to restore the SPI and Internal Flash.

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

./5_restore.sh stlink mario

Скрипт должен вывести:

...
Restoring SPI flash...
Restoring internal flash...
Success, your device should be running the original firmware again!
(You should power-cycle the device now)

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

Перепаиваем SPI flash

Есть больше одного способа перепаять чип. Лично я воспользовался паяльным феном. Плату нужно излечь из пластикового корпуса и заклеить каптоном (термоскотчем) все, кроме самого чипа. Ставим температуру 300 градусов и среднюю силу обдува. Прогреваем чип, снимаем его пинцетом. Удаляем остатки припоя с помощью оплетки.

Чтобы впаять новый SPI flash, нужно залудить контактные площадки и нанести побольше флюса. После этого новый чип легко впаивается тем же феном. Отклеиваем каптон, отмываем плату изопропиловым спиртом, помещаем плату в корпус.

Далее говорим:

cd ..
git clone git@github.com:BrianPugh/game-and-watch-patch.git
cd game-and-watch-patch
pip3 install -r requirements.txt
make download_sdk
cp ../game-and-watch-backup/backups/flash_backup_mario.bin ./
cp ../game-and-watch-backup/backups/internal_flash_backup_mario.bin ./

Удерживая боковую кнопку на устройстве, выполняем команду:

make PATCH_PARAMS="--device=mario" LARGE_FLASH=1 \
  ADAPTER=stlink flash_patched

Здесь выводится много разного текста. Главное, чтобы в конце было:

...
Info : 4-byte address parameter table
Info : valid SFDP detected
Info : flash1 'sfdp' id = 0x3a25c2 size = 65536 KiB
Error: FSIZE in DCR(1) doesn't match actual capacity.
** Programming Started **
Warn : Adding extra erase range, 0x900d7000 .. 0x900dffff
** Programming Finished **

Отмечу, что у меня получилось не с первого раза. Если теперь обесточить устройство и снова его включить, мы должны увидеть часы. Таким образом, был получен тот же G&W, что и раньше, только с 64 Мб флеша.

Прошиваем Retro-Go

Retro-Go — это открытый (GPL 2.0) эмулятор ретро-игр для устройств на основе ESP32. Существует порт под G&W, которым мы и воспользуемся. Точнее говоря, мы воспользуемся форком с более симпатичным интерфейсом, чем в апстриме.

Говорим:

cd ..
git clone git@github.com:olderzeus/game-and-watch-retro-go.git
cd game-and-watch-retro-go
git submodule update --init --recursive

В каталог roms/ нужно положить ROM’ы с играми. В roms/nes/ идут ROM’ы для NES (a.k.a. Famicom), в roms/md/ — для Sega Mega Drive (a.k.a. Genesis), и так далее. Хороший сборник с играми для NES называется GoodNES, а для Sega Genesis — GoodGen. Заинтересованным читателям предлагается найти их самостоятельно, в качестве упражнения. Другие платформы на данный момент меня не сильно интересуют, быть может, кроме ZX Spectrum. Однако в Retro-Go он не поддерживается, ровно как и Commodore 64. Вероятно, потому что это ПЭВМ с клавиатурой, а не игровые консоли с геймпадом.

Если вы хотите, чтобы у игры была обложка, рядом с ROM’ом нужно положить файл PNG с разрешением 160x160 пикселей и 8-и битным RGB цветом. Файл должен иметь то же имя, что и ROM, с точностью до расширения. Например:

-rw-r--r--  1 eax eax 2097152 Mar 26 17:15 'Sonic and Knuckles.md'
-rw-r--r--  1 eax eax   33212 Mar 26 17:44 'Sonic and Knuckles.png'

Обложки к играм есть на Википедии. Для их редактирования подходит Gimp.

Когда ROM’ы и обложки готовы, говорим:

make clean

# Команда `make clean` не удаляет закэшированные .img/.lzma файлы,
# поэтому удаляем их самостоятельно:
find ./roms/ -type f -name "*.img" -delete -print
find ./roms/ -type f -name "*.lzma" -delete -print

make romdef

Будет выведен список игр и найденных обложек. Если он выглядит похожим на правду, собираем Retro-Go:

make -j4 COVERFLOW=1 GNW_TARGET=mario EXTFLASH_SIZE_MB=63 \
  EXTFLASH_OFFSET=1048576 INTFLASH_BANK=2 flash

Сборка займет некотороые время и завершится с ошибкой, потому что команде не удастся прошить устройство. Теперь зажимаем боковую кнопку на G&W и повторяем последнюю команду. Должны увидеть, что G&W прошивается:

Прошивка новых игр на Nintendo Game & Watch

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

Когда процесс завершится, выдергиваем и снова подаем питание. Должны увидеть дэфолтную прошивку с Марио. Если теперь одновременно нажать кнопки «game» и «влево», мы должны попасть в эмулятор с новыми играми.

Заключение

Если вы планируете часто загружать новые игры, то SWD можно вывести на разъем USB-C. Данный разъем используется только для питания устройства. Поэтому мы можем спокойно воспользоваться пинами D+ и D- (номера 6 и 7 из 12-и пинов разъема). Данная модификация наглядно показана в этом видео. В своем экземпляре я так и сделал. Иметь для этого микроскоп, как советует автор видео, желательно, но по моему опыту не обязательно.

Таким образом, мы получили действительно классную портативную игровую консоль. И что с ней теперь делать? Можно просто играть в любимые игры. А можно портировать перечисленные скрипты на MacOS, законтрибьютить в Retro-Go, или даже попробовать писать игры для Famicom. Как обычно, все ограничено лишь вашей фантазией.

Метки: , , , , .


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