The RunCPM prompt with DIR, ASM, DDT and MBASIC.
The console runs original CP/M 2.2 software, including Microsoft BASIC-80, through a port of RunCPM to bare metal. The Z80 decoder supplies the register file, a 64 KB virtual address space, and the zero page vectors at 0x0000 for warm boot and 0x0005 for the BDOS entry.
Standard RunCPM expects a hosted POSIX filesystem to expose its virtual drives. There is none here, so the disk is packed ahead of time: a script scans a directory, converts filenames into 11-byte CP/M form with 8.3 space padding, and writes the disk blob that goes into the asset container. The BDOS translation layer traps the calls and routes them:
- Console output, functions 1, 2, 6 and 9, goes to the hardware UART and to a four-line by sixteen-character virtual terminal rendered into the 64x32 framebuffer with a 4x6 bitmap font, which is what makes the phosphor-green screen in the capture above possible on a monochrome display.
- File access, functions 14, 15, 16, 20 and 21, reads the in-memory RAM disk arena. Writes update it in place, so file changes persist for the session.
- AUTOEXEC.TXT is synthesized into the RAM disk at boot so the internal CCP can auto-launch a title such as MBASIC STARTRK without a human typing at the prompt.
One bug is worth recording in full, because its symptom was a hang rather than an error.
Files larger than 16 KB are split across CP/M extents. The record offset was being computed from the record field alone, so at record 128 the address wrapped back to the start of the file and the read looped forever. The correct linear offset uses both fields:
offset = ((fcb->ex * 128) + fcb->cr) * 128
MBASIC.COM is 24 KB, so this hit on the first program that mattered. A naive implementation does not crash; it spins, which costs an afternoon before the penny drops.
ESC during blocking console input needed its own path for the same reason the launcher did. The character input loop polls the hardware key register every 22 ms and unwinds to the launcher on keycode 27, so a CP/M program that blocks on input can still be exited with one key, and the console does not have to be rebooted to escape a text adventure.
Speed: at 50 MHz with SDRAM access latencies, the Z80 interpreter runs at roughly a 2 to 4 MHz equivalent, which is the range of the machines that ran this software originally. Star Trek, Hamurabi and Lunar Lander are period-appropriate at that speed rather than merely tolerable.
![]() Star Trek (1971) |
![]() Hamurabi (1968) |
![]() Hunt the Wumpus |
Porting this was the most retrocomputing part of the project so far: original 8080-era binaries, unmodified, running on a RISC-V core I designed, with the disk image packed at build time and the console rendered into a 64x32 framebuffer.
M_Jagadeesh97


Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.