Custom firmware for the newer Nintendo Game and Watch consoles.
This repo contains custom code as well as a patching utility to add additional functionality to the stock Game and Watch firmware. In short, this project allows you to run the firmware your game and watch came with along side retro-go.
LEFT
+ GAME
) to launch retro-go from internal flash bank 2.make help
to see all configuration options.PATCH_PARAMS="--device=mario"
)--smb1=path-to-patched-smb1-rom.nes
--smb1-graphics=path-to-patch.ips
ips/
and have the patcher automatically discover them via the flag --smb1-graphics-glob
PATCH_PARAMS="--device=zelda"
)--no-beep
This repo uses the gnwmanager cli tool. See it's instructions on how to install.
Install game-and-watch-patch python dependencies (>=python3.6 required) via:
pip3 install -r requirements.txt
Place your internal_flash_backup_${DEVICE}.bin
and flash_backup_${DEVICE}.bin
in the root of this
repo. To extract these from your gnw system, see the gnwmanager unlock tutorial.
For example, if we are patching the mario
game and watch, we need the files
internal_flash_backup_mario.bin
and flash_backup_mario.bin
in the root
directory of this project.
See the appropriate section below for your device model.
For additional configuration options, run make help
.
Since most people are going to be using this with retro-go, want the minimum amount of external storage used, and don't care about the sleeping images or the mario song easter egg, here are the recommend commands. Note that this uses an undocumented 128KB of internal Bank 1 and requires a patched version of openocd installed.
# in this repo
make clean
make PATCH_PARAMS="--device=mario --internal-only" flash
# in the retro-go repo
make clean
make -j8 INTFLASH_BANK=2 flash
This assumes you have upgraded the external flash to something larger than 4MB. See the zelda document for using retro-go with the stock 4MB flash chip.
# in this repo
make clean
make PATCH_PARAMS="--device=zelda" flash
# in the retro-go repo
make clean
# In this example, I'm assuming you have a 64MB flash chip (60 = 64 - 4)
make -j8 EXTFLASH_SIZE_MB=60 EXTFLASH_OFFSET=4194304 INTFLASH_BANK=2 flash
Steps to flash from a docker container (running on Linux, e.g. Archlinux or Ubuntu):
# Go into the docker directory of this repo.
cd docker/
# Pull the pre-built docker image.
docker pull brianpugh/game-and-watch-patch:latest
# When done, use the image to create a container with the attached docker-compose.yaml file.
# You have to edit the compose file and set the path to the directory with your firmware backup (volumes section of the file).
docker compose up -d
# This will create and run a container game-and-watch-patch.
# The firmware backup files will be mounted into /tmp/firmware of the container.
# Now, go inside the container copy the backup files and proceed as described above in the Usage section.
docker exec -it game-and-watch-patch /bin/bash
If you run into permission issues, ensure that your user is in the docker group.
keystone-engine
on rpi3If you are unable to install keystone-engine
on a raspberry pi 3, try:
raspi-config
git clone https://github.com/keystone-engine/keystone
cd keystone/bindings/python/
python3 -m pip install .
Main stages to developing a feature:
Core/Inc/stock_firmware.h
.Core/Src/main.c
. There's a good chance your custom function will call the function in (2). You will also probably have to add -Wl,--undefined=my_custom_function
to LDFLAGS
in the Makefile so that it doesn't get optimized out as unreachable code.patches/patches.py
.This is my first time ever developing patches for a closed source binary. I documented my journey in hopes that it helps other people. If you have any recommendations, tips, tricks, or anything like that, please leave a github issue and I'll update the documentation!
Thanks to the community that made this possible! This repo was built with the help of others. Repos referenced during the development of this project:
I would also like to thank the stacksmashing discord for all the help (special shoutout to @cyanic)!