September 2023
In 2021 I attended Tandy Assembly, a small conference in Ohio for TRS-80 enthusiasts, and spoke to a few people who were still writing games for the late-70s 8-bit machines. Everyone else at the conference found a way to contribute to the community, by showing their machines or engineering new hardware and software, and I decided to write an IDE for these game programmers.
TRS-80 games are all written in assembly language, so this IDE only needed to handle that. This is both easier (assembly is easy and fast to parse and assemble) and harder (assembly doesn’t give the IDE much information to go on). Conveniently, I’d already written a suite of TypeScript libraries to assemble and emulate Z80 assembly language.
The great thing about retrocomputing is that modern technology is ridiculously overpowered for just about any project you want to tackle. So I thought: What are some absurd things this IDE could have that couldn’t have been done at the time, nor could be done today for modern languages?
How about: With every keystroke in the IDE’s code editor, we assemble the whole program, reset a virtual TRS-80 to a known state, install the program, and run it? Could I do this at interactive rates, even for large programs?
I decided to make it web-based. There are many modern tools for TRS-80s, some with user interfaces, but most are Windows-only, and I wanted the IDE to be usable on all platforms, and without an installation step. Modern JavaScript runtimes are fast enough that assembling a large program and launching it takes 40ms, easily doable for every keystroke.
For the code editor I used the outstanding CodeMirror widget. Version 6 has been rewritten to be heavily functional, which takes some getting used to, especially the interaction between the editor and external data, such as an emulator. In the end there was little I wasn’t able to get it to do, and the author, Marijn Haverbeke, was responsive and helpful on the forums; highly recommended.
The IDE supports auto-complete of instructions (including full-text search of the instruction descriptions), pop-up detailed information about each instruction, real-time display of bytecode and instruction timing, a debugger, exporting various formats (CMD, CAS, and WAV), infinite undo/redo, jumping between symbol declarations and usages, and inline display of errors.
The screen resolution of the black-and-white TRS-80 machines is very low, 128 by 48, and in fact isn’t even a graphics mode: graphics characters are used in text mode:
The entire screen takes up just 1024 bytes. When you wanted a splash screen or game maze, instead of drawing it with code, it was often easiest and most compact to embed the 1024 bytes right into the code, like this:
SPROW1 DC 9,128 DB 151,131,131,148,128,156,140,140,144,128 DB 176,176,176,144 DC 41,128 SPROW2 DC 9,128 DB 157,140,166,128,128,181,176,152,129,128 DB 149,128,128,128,128,152,131,137,144,128 DB 148,128,160,132,128,176,176,144 DC 27,128 SPROW3 DC 9,128 DB 181,176,176,133,128,149,128,130,148,128 DB 151,131,128,128,128,157,140,140,149,128 DB 181,176,134,128,128,149,128,130 DB 148,128,152,131,137,144,128,148,128,128 DB 148,128,176,128,128,144 DC 11,128 SPROW4 DC 14,128 DB 129,128,128,130,128,141,140,140,132,128 DB 149,128,128,149,128,149,128,169,128,128 DB 149,128,128,149,128,149,128,128,149,128 DB 149,128,128,149,128,149,165,128,149 DC 13,128 SPROW5 DC 27,128 DB 129,128,128,129,128,141,140,134,128,128 DB 137,176,152,129,128,165,168,160,133,128 DB 149,138,144,149 DC 13,128 SPROW6 DC 43,128 DB 131,129,128,128,133,128,137,133 DC 13,128
That’s the splash screen from Peter Cetinski’s game Breakdown, which you can play instantly in your browser if you want to see the screen displayed by the above code.
The process of making these is tedious: You first draw your screen by hand on a template that Radio Shack sold in notebooks:
That one’s mine from the early 80’s. You then go through each of the 1024 characters, look up its code, and enter it into your program. The walking guy on the left maps to:
.byte 0x80,0xAF,0x9F .byte 0x88,0xBF,0xBF,0x8C,0x84 .byte 0xB8,0x87,0xA2,0x9D
(There are several standards for Z80 assembler directives,
which is why Pete’s code uses DB
(define byte) and
mine uses .byte
. They’re both accepted by my assembler.)
To make this easier to do, I embedded a drawing program into the IDE. You can draw any screen and it’ll generate the code, marked up with comments so that the editor knows how to bring it back into the paint program:
It’s fun to disassemble famous programs and bring their screens into the paint program. Scarfman, for example, has three mazes: the one used for the game, and two demo mazes (with and without ghosts). I don’t know how to see those demo mazes when running the program. You can also modify the maze and, when you save it, the game immediately re-runs with it, trapping the ghosts and making the game a bit easier to play:
When single-stepping through the code, it’s useful to know the values of various variables. Instead of having a separate view of memory, I display the values right in the code:
To try the IDE myself, I wrote a demo version of the famous Castle Wolfenstein 3D algorithm:
You can play it in the browser. Use WASD to navigate and the left and right arrow keys to turn.
I gave a talk about the IDE at Tandy Assembly 2022:
One nice thing about making a tool that literally no one needs is that you don’t get any bug reports! There are a few demo programs you can load if you want to mess with it. Try it in your browser now!
The source code is available on GitHub.
(Cover image credit: Midjourney, “Abstract painting representing z80 assembly language, bright colors.”)