CH32V003 Mini Game Console
Introduction
Hi! I present to you a little project I have been working on... honestly, for a few years (on and off). But it's finally finished! This Mini Game Console uses one of the cheapest MCUs available, the CH32V003 (chosen when the project began in mid-2023), paired with also one of the cheapest color LCD display featuring a mind-blowing 80x160 resolution.
Despite memory limitations, it runs games with full 16-bit color* graphics at 30 FPS (It can technically hit 60 FPS in all example games, but I designed them for 30, so I locked it there.) It supports either terminal grid and sprite graphics, has simple sound system and even option to save high score data.
It has simple "game engine" and each game can be kind of treated as independent program. There is API for buttons, sound and graphics, but it's all low-level anyways, so making games still require some knowledge how it all works overall.
Advanced game like Dino Run takes about ~2 kB in code alone. But for simple one like snake it's around 0.5 kB. With the example games and lto enabled there is about 1 kB of FLASH memory left, as well there are two free GPIOs. I didn't have idea what else to add despite e.g. flashlight functionality, but the project still can be expanded.
*Single sprite can have 3 colors + transparency, but every sprite can use different palette.
Specifications
- MCU: CH32V003F4P6 (16 kB FLASH, 2 kB RAM, 48 MHz RISC-V)
- Display: ST7735 80x160 IPS LCD (SPI)
- Audio: PWM Buzzer
- Input: 5 Buttons
- Current Games:
- Snake
- Pong
- Jump Bird
- Dino Run
- Other Features:
- High Score Saving
- Flashlight Mode
- Low Battery Detection
Showcase Video
Detailed Overview
Below I described the most important functionalities in more detail. It's also on GitHub: https://github.com/max7d3/CH32V003-MiniGameConsole
Graphics System (termGFX)
Obviously, there is no way to fit a full frame buffer for this LCD into the MCU's available RAM. To solve this, graphics rendering is based on 8x8 blocks, and the main mode of operation is simple terminal-like graphics.
Terminal Graphics
Instead of storing whole picture in the memory, MCU uses map of chars and their color on the grid. Each block contains 2 bytes of information: character, 4-bit background color, 4-bit foreground color. On 80x160 display there are 200 blocks, so whole "frame buffer" for terminal uses 400 bytes of memory.
However, the buffer cannot be send to the LCD in format like that. That's why next step is rendering each block into little 8x8 frame buffer and drawing it on the screen in the right position. Rendering function checks which character to draw and in which colors, then renders the bitmap in the output buffer. Next the buffer is send to the LCD.
That's the simple version. To achieve the higher frame rate there are further optimizations.
First, there is a map of 'dirty' blocks. An array of variables that act as bit fields, where '1' means change and '0' means lack of changes. All the exposed drawing functions write into that map. When the tGFX_Update is called to send the frame to LCD, the rendering function reads the map and skip all the blocks that didn't change. It also resets state of all the drawed blocks to '0'.
Second, the DMA of MCU is utilized to send data to LCD. And when data is being send to the LCD over SPI, the CPU switches output buffer and begin to render the next block. So we trade x2 RAM usage for almost x2 throughput increase.
Overall the terminal graphics in used configuration uses ~700 bytes of RAM. The usage can be further decreased by e.g. using only B/W colors. It can be also increased if we want more colors of text. But in this project I decided on compromise of 4-bit foreground/background colors of text.
This mode can be already used to make simple games. The Snake game implementation uses only this grid terminal graphics and custom characters. But for other games the 'free' graphics is needed, something that doesn't need...
Read more »
Maksym

ebenupton
Albert Gonzalez
Jim Shortz
Peter Noyes
I really like projects like this because they remind me how much you can squeeze out of tiny hardware if the code is clean and optimized. Building a mini console from scratch feels way more satisfying than just emulating something on a PC. When I get into that retro mood, I sometimes switch from coding experiments to checking out classic-style slot demos, and I actually found a full review here right in the middle of comparing different versions and payout mechanics. It’s not a casino itself, just a simple review platform with demo access, which makes it easy to explore things casually without signing up anywhere.