I rediscovered this little board in my stash, and went down a rabbit hole of getting it working and testing its limits.
This is a Lichee Pi Nano from Sipeed, already discontinued a while ago, using a rather underpowered Allwinner F1C100s CPU and a mere 32 MB of DRAM. Nevertheless, it can run Linux, and someone made a Docker image and build script for using Buildroot to make a bootable SD card image that can run on this little board.
- My fork of this repository fixes up some minor issues, and allows the build to run in Windows, which was broken in the original repo.
The board allows you to connect a 40-pin TFT screen, to serve as a framebuffer. The display can be 800×480 by default, or a smaller 480×272 with a slight modification to the device-tree file.
Since the display becomes a standard framebuffer (/dev/fb0), we can write directly to it:
- To blank the screen:
cat /dev/zero > /dev/fb0 - To disable the cursor that shows up:
echo -e "\e[?25l" > /dev/tty1 - And then, we can write anything else we like:

The above can be done by taking a standard Windows bitmap image (.bmp), and removing the BMP header at the beginning of the file, so that only the actual image bits remain. (The bitmap must be 32-bit ARGB, uncompressed, and of course must match the dimensions of the display.)
Then, just send the file to the framebuffer: cat image.bmp > /dev/fb0
While playing around with Buildroot and looking at all the configuration options it provides, I noticed that it offers several games to be included in the built image, so I tried OpenTyrian:

OpenTyrian works perfectly, and is totally playable, with the Lichee Pi Nano serving as a host USB device with a keyboard plugged in. To get it working, we must set a couple of environment variables used by SDL, which is the standard graphics library used by this game (and many other apps) that can operate directly on top of a framebuffer:
export SDL_VIDEODRIVER=fbcon
export SDL_FBDEV=/dev/fb0
export SDL_NOMOUSE=1
export SDL_AUDIODRIVER=dummy
I then proceeded to try to compile some emulators to see how well they perform on this board. In my repo, you can find branches that correspond to a Nintendo emulator, and Dosbox-staging. Refer to the commits in those branches to see how to set up those builds in the context of a Buildroot environment with Docker.
Unfortunately neither of the emulators were actually “playable”, but they built and ran successfully, in both cases using SDL2, which uses the directfb driver to talk to the framebuffer, instead of the older fbcon. The only change to the environment variables becomes: export SDL_VIDEODRIVER=directfb
Additional configuration for DirectFB must be placed in /etc/directfbrc:
system=fbdev
device=/dev/fb0
hardware
vt-switch
vsync-none
no-cursor
Here is the Nintendo emulator running:

And here is DosBox-Staging running:

At first, DosBox crashed the board because it ran out of memory. No problem — let’s create some swap space, to make it be able to limp along. First, use fdisk to create a new partition on the SD card: fdisk /dev/mmcblk0
Tell fdisk to create a new primary partition, with a starting sector beyond the existing partitions (in my case 294912), and ending sector somewhere far out (in my case 4718592), which is about 2 GB. After writing the new partition table, you might need to reboot the device. After rebooting, enable the swap space: swapon /dev/mmcblk0p3 (or whatever is the device name of the new partition). After doing this, it should work!
And in fact, for a turn-based game like Civilization, the performance is actually almost acceptable to be playable:
