There was one dev board left on the desk I hadn't done anything with: an M5Stack AtomS3R. A capable little thing, but in earlier tests I kept hitting its limits fast. So I picked the laziest possible starting question. Can I get DOOM running on it.

Other people had already done this. I wanted to do it myself anyway.

But just running the executable would be boring, so I started reading what the board actually has. Natively, without touching a single GPIO pin, the AtomS3R has a 128x128 screen, a motion sensor, WiFi, and one button, which is the screen itself. Screen, input, communication. That's a terminal.

So I stopped trying to run DOOM on the device and started trying to run DOOM somewhere else and hand the device a picture.

That one decision is the whole project, and it took me until halfway through to admit what it meant. If the device only draws whatever arrives and sends back a tilt and a button, then it doesn't know what DOOM is. It doesn't know what any game is. DOOM was never the point. It's a dumb terminal at arcade scale, and the thing on the other end can be anything. It ended up being 28 games to play and a demo reel of 41, because the eXoDOS collection has more than 7,000 DOS titles sitting on my disk and a terminal doesn't care which one you pick.

The rest of this is how a 0.85 inch screen that computes nothing ended up being the best DOS arcade cabinet I own.

The stack, for the record:

wherewhat
deviceAtomS3R, UIFlow2 MicroPython v1.27, one main.py, no custom firmware build
serverPython 3 with numpy and Pillow, plus OpenCV for the one video
DOOMdoomgeneric, C, compiled with zig cc on Windows because it installs without admin
DOSjs-dos emulators 8.4.2: DOSBox compiled to WebAssembly, running headless in Node
gameseXoDOS, 7,629 zip archives on disk

The code and the full technical notes are on GitHub: apn201/Micro_Arcade, with the long version of every decision and bug in NOTES.md. No game data in it, you bring your own.

For the demo the server runs on my own PC. The plan was a Raspberry Pi, and it still can be one, but the eXoDOS library lives on the PC and a headless DOSBox on the Pi is a fight I didn't need to pick to prove the idea. Device and server talk over WiFi UDP. Nothing about the device changes based on which machine is sending.

What it's actually for

None of this is a new idea, and none of it is complicated. VNC has done remote screens since the nineties, and thin clients are a whole industry. What changed is the price of the thing on the receiving end. The Atom costs about 15 dollars. Put the pipe in front of it and it gets as much memory and compute as the machine on the other end has, which is as much as you want.

This started as a retrocomputing entry, and I decided it should be an arcade cabinet. But the arcade cabinet is the demo. The reusable part isn't the games, it's the pipe: once the device is a draw-only terminal that renders rectangles from a server, the device stops mattering and the server can drive anything.

A cheap screen that owns nothing fits anywhere a PC or a tablet would be overkill, or would get broken or walk off. An art gallery. A shop window. An info point nobody is watching. If it breaks, it's a 15 dollar part. If it gets stolen, someone stole 15 dollars and no data. In a lot of places it could replace a PC or a tablet outright, because all that box was doing was showing something and taking a tap back.

The screen doesn't need to be this tiny either. The server sends rectangles at whatever size the client asks for. A bigger panel works the same way, and for something that changes once a minute it could be e-ink.

Three more directions I keep thinking about.

The real one is industrial, and it's my day job leaking into a toy. Old control PCs get virtualized and contained, because you cannot have a Win95 box running on a plant floor. But the operator still, sometimes, needs to see a corner of that screen at a panel somewhere. A full thin client is cost and overkill for a glance at one readout. A 15 dollar board that draws one rectangle of that virtualized machine's framebuffer over UDP - no OS, no moving parts, almost no attack surface - is a reasonable answer for the non-critical, non-Ex, "I just need to see that gauge over there" case. Not the primary HMI. Not safety-critical. Not hazardous areas. But there's a real, cost-sensitive middle ground where a draw-only terminal beats a real thin client, and this is the shape of it.

The fun one: the server already slices a frame into rectangles for a client that draws whatever arrives. Nothing says that client is one screen. Fifty of these tiles as a single surface - flat, or glued to a sphere - is the same protocol pointed at fifty terminals at once. I have no use case for it. It would look sick. That's reason enough.

The one I'm not doing: a keyboard. There are loose keys in a drawer and the GPIO pins are right there, and I keep being tempted. But adding real input hardware would make the thing work better and mean less. The whole premise was native peripherals only - a terminal made from a board that was never meant to be one. A keyboard turns it into a small computer with buttons, which is a different, more boring object. So the keys stay in the drawer.

It's going in my daughter's dollhouse when it's done. A fully working arcade cabinet, dollhouse scale, furniture that happens to run DOOM.