Table of Contents
- Introduction
- 1. What’s Needed?
- 2. Linux Machine Preparation
- 3. Install Debugger/Programmer Software (OpenOCD special build)
- 4. Install Flash Backup and Restore tools
- 5. Perform Flash Backup and Restore
- 6. Swapping out the Flash Memory for Higher Capacity
- 7. Open Source Games Emulator: Retro-Go
- 8. Writing your own code
- 9. Problems?
- Summary
Introduction
This blog post discusses upgrading a pocket electronic game toy, so that last year’s toys don’t go to waste! There is no video to this project, so it’s not part of the competition, but maybe it gives some ideas for Xmas anyway!
The upgrade capability allows one to create either custom software for the device, or you can run open-source games emulators (with games that you own). The photo below shows custom code that implements a simple tree-drawing formula.
Note: It goes without saying, that you should not violate laws with regards to game binary files (known as Game ROMs) usage; long story short, in virtually every country, unless you’ve purchased the games in the past, you shouldn’t be installing and running that content; furthermore, there’s a chance some countries may still not allow users to transfer games from one system to another in this manner). There are open source games for emulators too; often they will require very old processor assemblers and compilers to be installed to build the binary file however, so you may wish to go native for custom apps.
In any case, there’s nothing wrong with running your own custom code and therefore saving ordinarily non-upgradeable devices from being thrown in the trash after kids might be bored of them.
I think it is a good idea to enable electronic game toys to run additional content, because it saves it from e-waste once the child is bored of the game that was supplied. It’s also great for experimenting and learning how to create games.
This blog post documents the steps I took, but there are no code files or scripts here; I didn’t create any of the code or scripts (apart from the open-source custom app that is available in a zip file below), they are available online hosted by others. There are a lot of steps, but they are simple, and I’ve placed them in an order that hopefully makes sense.
The particular products in the photo above are just going to be called green and red games in this blog post, because we don’t need to use any trademarks or copyrighted content. A few scripts (that are hosted on other people’s sites) require you to type the game name, but I won’t mention that here since we are keeping things clean.
Only photographs that I have taken myself will be used in this blog post, so that the product manufacturer does not own the copyright to them.
No special soldering or desoldering tools are required, but if you wish to expand the memory on the device, then that requires a soldering iron with a fine point.
1. What’s Needed?
Five main things are needed:
(a) You’ll need the game itself (either the red or green variants)
(b) a computer running Linux
(c) a tri-wing screwdriver so you can open the game (it is just 4 screws)
(d) a Debugger/Programmer device that can read and write to the ARM microcontroller, in order to access the microcontroller’s internal Flash memory as well as the separate Flash memory chip attached to the microcontroller
(e) a new, larger capacity Flash memory chip, so you can swap out the old smaller capacity one.
For item (b) I used an Intel PC (a Raspberry Pi could be used too, but that will not be covered in this blog post). For the programmer, I used a ST-Link V2 device. Other programmers (known as SWD programmers) could be used, or the GPIO pins on the Raspberry Pi could be used (ideally with some additional circuitry so that the logic levels are correct), but I have not tried those options. The programmer needs to support low voltage (approximately 1.9V) logic levels, which the ST-Link V2 does support.
The photo below shows everything required, all connected up. It will be explained in detail further below. There’s not a lot to it.
For the optional memory chip upgrade, there are several options. Since there is a worldwide chip shortage, sometimes the desired ones may not be available. There is a list of ‘Stock and Custom Firmware compatible’ chips here.
Certain tools and consumables are helpful:
(a) ESD wrist strap
(b) Chip Quik or alternative low-melt solder for removing the memory chip
(c) Desoldering braid for cleaning up pads
(d) Isopropyl alcohol (IPA) for cleaning
(e) Solder paste for soldering the new memory chip
(f) Syringe of flux paste for any further rework (I used MG Chemicals 8341-10ML )
(g) Hard-bristle ESD-safe brush (Vermason 238110 is excellent)
For item (b), there are special Chip Quik kits (Farnell 1850214), or (a bit more general-purpose) you could use a syringe of Sn42Bi58 solder paste.
The photo here shows the Sn42Bi58 low-melt solder paste (you could use low-melt solder wire, but I just had the paste) and the flux that I used. The paste is 3 years expired : ) but worked fine for this purpose.
2. Linux Machine Preparation
Install Ubuntu (I used Ubuntu 22) on a PC, and then type the following as a root user (either by prepending sudo to each command, or type sudo su followed by passwd to assign a root user password, and then you can type su whenever you wish to become the root user):
apt update
apt upgrade
apt install libnewlib-arm-none-eabi build-essential
apt install git
apt install python3-pip
As normal user (i.e. don’t prepend sudo to the command, or type exit if you’d previously become the root user using su), append the following to the ~/.bashrc file:
export PATH="$HOME/.local/bin:$PATH"
export ADAPTER=stlink
Close and re-open a shell, for the file modifications to take effect.
Download gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 from the ARM website and type the following to install it; there is probably a better way, but this works for now:
su
tar xjf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2 -C /usr/share
cd /usr/share/gcc-arm-none-eabi-10.3-2021.10
ln -s /usr/share/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gcc /usr/bin/arm-none-eabi-gcc
ln -s /usr/share/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-g++ /usr/bin/arm-none-eabi-g++
ln -s /usr/share/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-gdb /usr/bin/arm-none-eabi-gdb
ln -s /usr/share/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-size /usr/bin/arm-none-eabi-size
ln -s /usr/share/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-objcopy /usr/bin/arm-none-eabi-objcopy
apt install libncurses-dev
ln -s /usr/lib/x86_64-linux-gnu/libncurses.so.6 /usr/lib/x86_64-linux-gnu/libncurses.so.5
ln -s /usr/lib/x86_64-linux-gnu/libtinfo.so.6 /usr/lib/x86_64-linux-gnu/libtinfo.so.5
3. Install Debugger/Programmer Software (OpenOCD special build)
In a temporary folder as a normal user, type:
wget https://nightly.link/kbeckmann/ubuntu-openocd-git-builder/workflows/docker/master/openocd-git.deb.zip
unzip openocd-git.deb.zip
As root user:
dpkg -i openocd-git_*_amd64.deb
apt --fix-broken install
apt-get -y -f install
As normal user, append the following to the ~/.bashrc file:
export OPENOCD="/opt/openocd-git/bin/openocd"
Close and re-open a shell, so that the .bashrc contents are read.
4. Install Flash Backup and Restore tools
As root user:
apt-get install binutils-arm-none-eabi python3 libhidapi-hidraw0 libftdi1 libftdi1-2
As a normal user:
mkdir -p ~/development/gamewatch
cd ~/development/gamewatch
git clone https://github.com/ghidraninja/game-and-watch-backup.git
cd game-and-watch-backup
5. Perform Flash Backup and Restore
The firmware on the microcontroller is inaccessible usually, because the microcontroller is locked. The aim of this section is to remove the lock on the microcontroller, and to make a copy of all the storage in the game device, and re-upload the firmware onto the unlocked microcontroller, to be sure that nothing is broken. By the end of this section, the microcontroller will be able to run any code you desire, and you will have a backup of the contents of the device.
Open the game (a tri-wing screwdriver is needed), and disconnect the battery. The plug on the battery needs to be gently levered up vertically off the board. A flat insulated spatula of some sort could be helpful to do this.
The photo here shows the red game opened up (the battery is still connected in this photo):
Next, taking ESD precautions, connect up the ST-Link V2 as shown in the diagram below. The triangles point to pin 1 for reference. Four wires are used. If you’re using a different programmer, then note that approximately 1.9V logic levels are used.
You could directly solder wires, but it is a bit neater to use a connector. I used a 1.27 mm pitch right-angle pin header.
Connect the ST-Link USB cable to the Linux PC, and the red power LED on the ST-Link will come on. Use a USB power supply (such as a mobile phone charger), and press the power button on the game so that you can see activity on the LCD screen.
Next, type (replace the text <<game_name>> with the name of the game device, it’s a one-word fairly obvious identifier that distinguishes the red and green games; if you can’t guess it, google it):
./1_sanity_check.sh stlink <<game_name>>
If you are using a Raspberry Pi, then the text stlink would have been replaced with rpi. If you were using a J-Link debugger then use the text jlink. The output should be:
Running sanity checks...
Looks good!
Make sure the game is on the time screen, and then type:
./2_backup_flash.sh stlink <<game_name>>
Press return when prompted. The display will go off, and for about a minute the ST-Link LED flashes red and green. You’ll see the following:
Make sure your game is turned on and in the time screen. Press return when ready!
Attempting to dump flash using adapter stlink.
Running OpenOCD... (This can take up to a few minutes.)
Validating ITCM dump...
Extracting checksummed part...
dd if=backups/flash_backup_<<game_name>>.bin of=backups/flash_backup_checksummed_<<game_name>>.bin bs=16 skip=8192 count=197962
Validating checksum...
Looks good! Successfully backed up the (encrypted) SPI flash to backups/flash_backup_<<game_name>>.bin!
In the backups sub-folder, there are now two files. The smaller file (1300 bytes for me) is itcm_backup_<<game_name>>.bin and the larger file (4194304 bytes) is flash_backup_<<game_name>>.bin. Your file sizes may be slightly different.
Next, type:
./3_backup_internal_flash.sh stlink <<game_name>>
Press y when prompted:
Validating ITCM dump...
This step will overwrite the contents of the SPI flash chip that we backed up in step 2.
It will be restored in step 5. Continue? (y/N)
After a minute or so, you’ll see some output:
Generating encrypted flash image from backed up data...
Programming payload to SPI flash...
Flash successfully programmed. Now do the following procedure:
- Disconnect power from the device
- Power it again
- Press and hold the power button on the device
- The LCD should show a blue screen
- If it's not blue, you can try pressing the Time button on the device
- Press return (while still holding the power button)!
Now you need two hands. First, unplug the USB cable to the game. Then, re-plug the USB cable. Then, with one hand, press and hold the power button on the right side of the game. Wait until you see the screen turn blue, but keep the power button pressed. While holding it pressed, hit return on your Linux box. Keep the button pressed until you see the following (it will take a few seconds):
Dumping internal flash...
Verifying internal flash backup...
Device backed up successfully
Now the backups sub-folder contains a third file, called internal_flash_backup_<<game_name>>.bin (mine was of size 131072 bytes).
Type the following:
./4_unlock_device.sh stlink <<game_name>>
Press y when prompted. The screen will change from blue to black. You’ll see the following output, and it will take about 10 seconds to complete:
Unlocking your device will erase its internal flash. Even though your backup
is validated, this still can go wrong. Are you sure? (y/N)
Validating internal flash backup before proceeding...
Unlocking device... (Takes up to 30 seconds.)
Congratulations, your device has been unlocked.
Please power-cycle it for the changes to take full effect.
Disconnect and reconnect the power. Next, type the following:
./5_restore.sh stlink <<game_name>>
The following text will appear (it will take about a minute to complete):
Ok, restoring original firmware! (We will not lock the device, so you won't have to repeat this procedure!)
Restoring SPI flash...
Restoring internal flash...
Success, your device should be running the original firmware again!
(You should power-cycle the device now)
Now the USB cable power to the game can be disconnected, and the ST-Link cable can also be disconnected. The microcontroller is now unlocked.
The game will function as normal by plugging in the USB cable, or plugging in the battery again, but keep the battery disconnected for now so that any further steps can be done.
6. Swapping out the Flash Memory for Higher Capacity
The Flash memory chip ideally needs removing, because it doesn’t contain a lot of storage space for many games. The photo below shows the default memory chip installed in the green game.
To remove the chip, with the battery still disconnected, apply some low-melt solder to all the pins on the chip, and by heating up pins on both sides one row at a time with a soldering iron, it should be possible to get enough heat into the solder that it remains melted long enough that the chip can be lifted off (with no force) with tweezers. Note that there are extremely tiny passive components close to the memory chip, and you shouldn’t accidentally touch them with the soldering iron. Some of the parts are so tiny it may be almost impossible for the user to fix them if things go wrong. If you think there is a risk of touching them, then cover them up with Kapton tape! The red game for instance, has two resistors very close to the memory chip, and if one of them gets removed or damaged, then the battery level indicator will be incorrect, because the two resistors form a potential divider, supplying the battery voltage level to the analog-to-digital converter (ADC) inside the ST microcontroller:
The pads are cleaned up with desoldering braid, and then cleaned with isopropyl alcohol and a brush and/or cleaning wipe. The photo below shows what the board (in the green game) should now look like, with as much of the low-melt solder now removed as possible, and the board cleaned.
Here is a photo of the pads where the memory chip was desoldered in the red game:
Apply normal solder paste to the pads, place the new memory chip on top (use the triangle marker on the PCB to orient the memory chip correctly), and then heat each pin/pad area with a soldering iron with a bit of solder on the tip. Apply flux later if necessary and re-heat any pins if you think they need a touch-up. You could also use thin solder wire instead of the solder paste, but you will need flux too, since thin solder wire may have too little flux.
After the new chip has been soldered on, clean off the flux. Be careful not to let any liquid flux or IPA fall into the LCD area (I held the board inverted to prevent that), in case it causes a mess further into the game device that cannot easily be cleaned up.
7. Open Source Games Emulator: Retro-Go
The Retro-Go game emulator is actually a suite of multiple emulators for different machines. The emulator suite plus any game ROM files and cover artwork are all together built into an image to install onto the game device. If you don't wish to use the emulator, then skip to the next section titled Writing your own Code.
If you wish to use Retro-Go, obtain the source code by typing the following on the Linux PC:
cd ~/development/gamewatch
git clone --recurse-submodules https://github.com/sylverb/game-and-watch-retro-go
cd game-and-watch-retro-go
python3 -m pip install -r requirements.txt
As root user type (this step may not be necessary, but there is no harm in typing it):
python3 -m pip install -r requirements.txt
Game Binaries and Cover Art
The game emulator requires game binaries (known as ROM files), and, ideally, a graphical image file to use as cover art in a menu. If you already possess the game, then it might be legal to search for the binaries online and download them, but I’m no expert. You’d need to check the legality in your country.
Place the files and image files (they can be of .jpg or .png suffix. GIF files will not work) into the subfolders under ~/ development/roms
Note that gbc virtual console games are placed into the gb folder along with any gb games as desired.
The image files will automatically get resized to 128x96, so as long as the image ratio is approximately 4:3 then the cover art will look fine (it doesn’t have to be precise, you can just eyeball this unless you want precisely identical sized cover art for each game).
Buiding the Image
Now that the Retro-Go source is on the Linux PC as well as the ROM files and cover art, you can build it all into the binary files to be installed onto the game device.
Type the following:
cd ~/development/gamewatch/game-and-watch-retro-go
make clean
make romdef
The make romdef command will result in a set of .json files in the roms subfolder. Here is an example snippet:
"My Game 1": {
"enable_save": "0",
"name": "My Game 1",
"publish": "1"
},
"My Game 2": {
"enable_save": "0",
"name": "My Game 2",
"publish": "1"
},
"My Game 3": {
"enable_save": "0",
"name": "My Game 3",
"publish": "1"
},
"_cover_height": 96,
"_cover_width": 128
}
If required, you can modify the .json file content.
Next, type the following line. The EXTFLASH_SIZE_MB parameter needs to match the installed memory chip. For instance, for a 512 Mbit memory chip, the parameter would be set to 512 divided by 8, which is 64:
make COVERFLOW=1 JPG_QUALITY=90 COMPRESS=lzma GNW_TARGET=<<game_name>> EXTFLASH_SIZE_MB=64
It may take several minutes, or longer, to complete. After about five minutes, it had completed for me, and the final output was:
External flash usage
Capacity: 64708608 Bytes ( 61.711 MB)
Usage: 13114618 Bytes ( 12.507 MB)
Free: 51593990 Bytes ( 49.204 MB)
[ BIN ] gw_retro_go_extflash.bin
[ BIN ] gw_retro_go_intflash.bin
[ BIN ] gw_retro_go_intflash2.bin
The binary files are in the build subfolder. The file sizes will vary greatly, dependent mainly on the game ROMs that were included. In my case, the file sizes were:
13114618 Nov 24 00:25 gw_retro_go_extflash.bin
219660 Nov 24 00:25 gw_retro_go_intflash.bin
0 Nov 24 00:25 gw_retro_go_intflash2.bin
Installing the Image
With the battery still disconnected, connect the programmer to the game device, and attach the USB power to the game too. Hold the power button depressed and enter the same command as described above, but this time with the text flash inserted in it, as shown:
make flash COVERFLOW=1 JPG_QUALITY=90 COMPRESS=lzma GNW_TARGET=<<game_name>> EXTFLASH_SIZE_MB=64
Keep the power button depressed, and then the image will begin transferring. You can release the button once the progress is being displayed on the LCD.
The process may take a while, and the image will be programmed in chunks.
I saw the following output on completion:
Programming of chunk 16 / 16 succeeded.
Programming of the external flash succeeded.
make[1]: Leaving directory '/home/shabaz/development/gamewatch/game-and-watch-retro-go'
make[1]: Entering directory '/home/shabaz/development/gamewatch/game-and-watch-retro-go'
# Reset the DBGMCU configuration register (DBGMCU_CR)
Open On-Chip Debugger 0.12.0-rc2+dev-00019-g9d925776b-dirty (2022-11-22-02:40)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
none separate
Info : clock speed 1800 kHz
Info : STLINK V2J29S7 (API v2) VID:PID 0483:3748
Info : Target voltage: 1.840105
Info : [stm32h7x.cpu0] Cortex-M7 r1p1 processor detected
Info : [stm32h7x.cpu0] target has 8 breakpoints, 4 watchpoints
Info : starting gdb server for stm32h7x.cpu0 on 3333
Info : Listening on port 3333 for gdb connections
[stm32h7x.cpu0] halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0x08018e68 msp: 0x20020000
If all went well, the LCD should now be displaying a game menu! Everything is complete, and you can power off the game, remove the USB power, unplug the programmer connection, and then re-plug the battery and close it all back up.
Now you/your kids can enjoy playing the games.
Selecting a Game
Use the up/down/left and right parts of the directional pad to select games or virtual consoles, and button A will select a game, and button B will allow you to go back.
When you press A, a pop-up menu will appear. Move down to New game and press A again.
Setting Emulator Options
Press the Pause/Set button for the options such as volume setting, move up and down, and press the left/right buttons to adjust each setting. Press B to exit.
Playing Games
The buttons have different meanings depending on the particular virtual game console. With more complex consoles, to start the game and select things in the game, you may have to use the Game button at the top of the device, and the three buttons nearest the thumb area (A, B, and Select) are used for gameplay. For simpler consoles, just A and B are used for gameplay.
Since there are differences between virtual game consoles, you may have to experiment to see which button does what.
8. Writing your own code
Once the microcontroller is unlocked, you can upload custom code to it. This could be useful for writing your own games or using the device for a completely different purpose.
For this task, I used a Windows PC instead of a Linux machine, simply because I had the development environment, STM32CubeIDE, already on the Windows PC. You could use the Linux or Mac versions if desired. STM32CubeIDE can be downloaded here.
See the attached zip file at the bottom of this blog post, which contains a complete project for STM32CubeIDE. This project was created by building on the base project code here.
To use it, open it and then select Project->Clean from STM32CubeIDE, and then select Project->Build Project. If all goes well, the project will build, and there will be a gw_proj1.bin file in the Debug subfolder in the project directory.
To install and run the project, connect the STLink V2 to the PC and to the game device, ensure there is power to the game (either from USB, or from the battery). Next, click on Run->Run and if a configurations window appears, select the defaults. The firmware will install onto the microcontroller and will execute. The demo code will draw an image to the LCD screen, as shown in the photo at the top of the blog post. So far I have only implemented a basic text function, line drawing, and pixel plotting capabilities.
The schematic for the red game has been approximately deduced by others and is available on the Internet via Google. The green game schematic will be fairly similar, but I have not seen it. There are some unused GPIO pins if you wish to connect the game to external hardware, but it is likely that most of them will need fine wires to be directly soldered onto the microcontroller pins to make use of them.
9. Problems?
If they are technical related (and not game ROM related, since I know nothing about that) stick them in the comments below, and I'll do my best to help, but I'm just learning too. However for a lot more information, there's an excellent Discord channel that would be worth connecting to, it is dedicated to this game device. I found it very helpful. There are also lots of good YouTube videos. I happened to find this Retro Tech Corner video useful.
There's not much that can really go wrong, it needs a bit of care to remove and replace the memory chip (optional), but the pads are spaced a generous 1.27mm apart and provided you have a reasonable soldering iron, and flux, and solder paste, then it is straightforward. The memory chip should be purchased from a reputable source otherwise there's a risk of getting a fake. Also, at least some basic ESD-safe practices should be done (wear the wrist strap, make sure the soldering iron is grounded [i.e. don't use a USB soldering iron unless you know what you're doing], and don't wear a furry Santa outfit : ) while soldering.
Summary
This blog post discusses how to access the microcontroller within a pocket game machine, and transfer an open source suite of game emulators to it. Finally, the blog post discusses how to write your own open source application and how to install it on the device.
Thanks for reading!