
(Fig. 1: The STM32F429I-Discovery showing the title screen of The Secret of Monkey Island, with a USB stick and the audio output on a breadboard)
In 2019, I used the STM32F429I-Discovery board to run rePalm, a port of Palm OS. The board has a Cortex-M4 with 168 MHz, 8 MB SDRAM and a 2.4 inch touch display – far more power than the PCs that Monkey Island was made for in 1990. So why not play Monkey Island on it?
The result: The Secret of Monkey Island runs completely on the board. Intro, all rooms, menus, saving and AdLib music through the DAC. It is controlled via the touch screen, and the game data comes from a USB stick.
Video
(Video: From the loader via the intro to the first rooms, played with a stylus)
You need your own copy of the game
The game itself is not part of this project. Graphics, texts and music belong to Lucasfilm Games / Disney. What this project provides is the engine and the adaptation to the board – the game data comes from your own copy, just like with ScummVM on a PC.
I use the German VGA floppy version from my shelf:

(Fig. 2: The box of the German VGA version of The Secret of Monkey Island)
And yes, the rest of the series is there too:

(Fig. 3: All Monkey Island games in their original boxes)
Hardware
| Board | STM32F429I-Discovery (MB1075) |
| CPU | STM32F429ZI, Cortex-M4F, 168 MHz |
| Memory | 2 MB flash, 192 KB SRAM + 64 KB CCM, 8 MB SDRAM |
| Display | 2.4 inch, 240x320, ILI9341 on the LTDC |
| Touch | resistive, STMPE811 |
| USB | Mini-USB (ST-LINK) for power, flashing and debugging; Micro-USB (USB USER, OTG) for the USB stick |
Apart from the board, you only need a USB stick with an OTG adapter, one capacitor, two resistors, a headphone jack and a pair of active speakers.
Audio output
The sound comes from DAC channel 2 on pin PA5. The 100 Ohm resistor limits the level, otherwise the active speakers are overdriven. The capacitor blocks the DC voltage of the DAC (about 1.45 V at rest), and the 10 kOhm resistor keeps the output at ground level, so there is no crackling when plugging it in:
PA5 --- 100 Ohm --- (+) 10 uF (-) --+----------+---- jack tip (left)
| +---- jack ring (right)
10 kOhm
|
GND --------------------------------+--------------- jack sleeve
The DAC output is designed for loads of 5 kOhm and more, so active speakers are the right choice. Headphones work too, but they are quite quiet.
USB stick
The stick has to be formatted as FAT32. These files go into the root directory:
000.LFL, 901.LFL to 904.LFL |
Game files from your own copy (VGA floppy version) |
DISK01.LEC to DISK04.LEC |
Game files from your own copy (VGA floppy version) |
MONKEY.BIN |
The game program, built from this project |
The ._* files that macOS creates on FAT sticks do no harm, they are ignored.
Saved games end up on the stick in /SAVES.
Controls
Hold the board in landscape orientation, with the ST-LINK connector on the left.

(Fig. 4: The board in landscape orientation – ST-LINK connector on the left, blue USER button and black RESET button in the middle)
| Tap | Left click at this position (verbs, items, walking) |
| Drag | The mouse pointer follows the finger |
| Blue USER button, short | Escape: skip a cutscene |
| Blue USER button, long (0.8 s) | ScummVM menu: save, load, options |
| Black RESET button | Restart, the game is loaded from the stick again |
A stylus works best on the resistive display. With a finger, the verbs are quite small:

(Fig. 5: Playing with a stylus on the touch screen)
How it works
Under the hood runs the SCUMM engine of ScummVM, the same one that runs Monkey Island on modern PCs. The work was in adapting it to a microcontroller without an operating system. A few points were more interesting than expected:
The program runs from the SDRAM
ScummVM with the SCUMM engine is about 2.7 MB – more than the 2 MB flash of the chip. That is why the flash only contains a small loader (29 KB). It initializes the clock, SDRAM, USB and the file system, loads MONKEY.BIN from the stick into the SDRAM and jumps into it.
On the display, the loader shows what it is doing: blue means it is waiting for the USB stick, a green bar means it is loading, red means an error.
There is a catch: on a Cortex-M4, the address range of the SDRAM is marked as "device memory" by default, and code cannot be executed from there. One region of the MPU (memory protection unit) turns the 8 MB into normal, executable memory.
Time-critical code in the internal RAM
The SDRAM is only 16 bits wide and has no cache. For most of the game this does not matter, but the AdLib emulation has to calculate every single audio sample. That is why the OPL emulation, the mixer and the sample rate converter are copied into the fast internal SRAM at start-up.
With 11,025 Hz mono, the sound emulation needs about 35% of the CPU. At 22,050 Hz it was around 70% – too much.
FreeRTOS against crackling sound
The first version ran without an operating system. The sound then crackled on every room change, because ScummVM holds a lock for up to 400 ms while loading a room, and the audio mixer had to wait for it.
The solution was FreeRTOS: ScummVM runs as one task, the mixer as a second task with higher priority, woken up by the DMA interrupt of the audio output. The locks are FreeRTOS mutexes with priority inheritance. Since then, room changes are silent – no crackling.
Rotated picture
The game has 320x200 pixels with 256 colours, the display is 240x320 in portrait mode. The picture is rotated by 90 degrees and copied into an 8-bit layer of the display controller (LTDC), the VGA palette of the game goes into its colour table. ScummVM's menus are drawn into a second layer on top.
Source code
The source code is on GitHub: github.com/User7142/monkey-island-stm32
Because ScummVM is licensed under the GPL v3, this port is licensed under the GPL v3 as well. The repository contains no game data – you need your own copy of the game.
Building needs the Arm GNU Toolchain, stlink and OpenOCD:
git clone --recurse-submodules https://github.com/User7142/monkey-island-stm32.git cd monkey-island-stm32/firmware make # builds ScummVM (takes a while the first time), the loader and MONKEY.BIN make flash # writes the loader to the flash cp -X build/MONKEY.BIN /Volumes/<stick>/
Limits
- The board has no battery-backed clock, so all saved games carry the same date.
- Music only via AdLib. A real Roland MT-32 could be connected via a MIDI output on a UART – the Cortex-M4 is far too slow to emulate one.