Perfboard handheld console with custom VM and games

Oct 29, 2026 Last reply: 17 hours ago 3 Replies
Jump to replies (3)

The toughest problem in this build is display speed. SPI writes are too slow for a handheld that plays games, and the maker has already worked out the answer: a parallel 8080-16P connection, planned but not yet wired up. Getting there has meant some serious low-level work on the software side, and that is where the project really shines.



The prototype itself is refreshingly honest. It lives on a perfboard with an ESP32 S3, a 3.5 inch 320x480 SPI display, and tactile pushbuttons, with a four-button directional pad on the left and two action buttons on the right. The maker is a student on a tight budget, so most parts are cheap modules from friends; the screen was the only purchase. A red status LED sits on the ESP32 board.



The software is the standout. Instead of leaning on LVGL, the maker built a custom rendering system on esp-idf with minimal libraries. A separate compiler turns game code into binaries, and a small virtual machine inside the ESP32 interprets them, pulling assets, metadata and instructions from an SD card into RAM. A hardware abstraction layer with permanently assigned function IDs keeps binaries working across builds. Both cores are used, screen handling split from input and game logic, and screen writes got faster through dirty rectangles, sram partitioning and a partial framebuffer. It boots, navigates a menu of seven options, and runs Tetris with chiptune audio, the score climbing to 307 in the demo.



Open items remain: DMA transfers to the display have not worked yet, the VM can only load what partitioned RAM allows so chunking is planned, and plenty of 64-bit data types still need cleaning up. It is an unfinished project shared for feedback, and a promising one.


The permanent unique IDs for HAL functions look like the smartest decision here. If binaries have to match function calls across builds, locking those IDs down early saves endless recompiles later. It trades some rigidity, since the ID table presumably cannot be shuffled freely, but for a hobby console that seems a very fair price for stable game files.

How does the maker assign those permanent IDs to each HAL function in practice? Is it a hand-maintained list, or generated somehow during the build? And with a full framebuffer costing around 300kb of RAM, I would love to know how the partial framebuffer and sram partitioning split the remaining memory between game data and rendering.

One concrete idea: once the DMA issue is sorted, releasing the VM loader as a reusable library could be worthwhile. Other people are clearly building similar things on ESP32 hardware, and a small package that reads game binaries from SD and calls the HAL would let the maker's design live beyond this one console. Cleaning up the 64-bit types first would probably help anyone porting it too.

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required