Skip to content

PMD 85 hardware ​

The screen, colour, graphics and sound hardware of each machine that runs BASIC-G, and where machine-code and data blocks live in its memory.

Tesla PMD 85-2 ​

Screen modes ​

One mode, always. The video circuit reads a 16K frame buffer and paints 288×256 monochrome pixels; there is no text mode underneath it, and no way to change the resolution.

The geometry is not the one a 256×192 machine would lead you to expect. A scanline is 64 bytes apart from the next, of which only the first 48 reach the screen, and only the low six bits of each byte are pixels — 48 × 6 = 288. The 16 bytes the video circuit never fetches are ordinary RAM, and the firmware keeps its own variables in the tails of the first eight lines.

Text is the firmware's doing rather than the hardware's: it draws 48 characters across and 26 rows down, each glyph eight pixel rows tall on a nine-scanline pitch, and keeps a separate one-line dialogue line at the very foot of the screen. That line is where what you type appears, where DISP prints, and where error messages arrive; the 26 rows above it scroll independently of it.

Colour ​

None: the display is monochrome. The top two bits of each byte are that six-pixel cell's attribute, and they are two independent flags rather than a colour:

BitEffect
6The cell blinks between its pixels and black
7The cell is drawn at half brightness

PEN n writes the pair for the drawing statements and PRINT INK(n); for the text that follows it, so 0 is plain, 1 blinking, 2 dim and 3 both. A clear pixel bit is background whatever the attribute says.

The PMD 85-3 reuses the same two bits as an RGB colour select and loses the blink; that machine is not modelled here.

Graphics ​

Drawn rather than typed — which is the "G" in BASIC-G, and the sharpest break from the Microsoft BASICs it otherwise resembles. SCALE sets a coordinate window, MOVE and PLOT draw lines inside it, AXES draws a pair of axes with tick marks, LABEL plots text at the drawing scale, and FILL plots a byte as an enlarged bit pattern. BMOVE and BPLOT go under all of that and write bytes straight into the frame buffer, six pixels at a time, which is how a sprite is drawn.

There are no graphics characters at all. The character generator holds printable ASCII plus one solid cell, so a mosaic set of the kind a Sinclair or a Commodore has simply does not exist here — the escape codes page has the whole of it.

Sound ​

BEEP is the whole of BASIC-G's sound repertoire — no pitch, length or channel to give it, because the tone it sounds is not the interpreter's to choose. The speaker hangs off the low four bits of the motherboard's MHB8255A port C, and those bits are three different ways of driving it:

OUT 134,nEffect
1A steady tone of about 1 kHz
2A steady tone of about 4 kHz — the one BEEP sounds
4Connects the speaker straight to the bit
8The red indicator LED, not the speaker

The two tones are not generated by the program or by the firmware: they are taps off the counter that scans the screen, running whether or not anything is listening, and bits 0 and 1 only gate them through to the speaker. So they are the two pitches the machine has, and holding both gives a mix of the pair rather than a chord.

Bit 2 is the one to build a tune from. It is wired to the speaker directly, so flipping it in a loop sounds whatever pitch the loop runs at — but left standing at 1 it holds the cone at one end, which silences the machine and overrides the two tone bits with it. Bits can be combined (OUT 134,10 sounds the 4 kHz tone and lights the red LED), and port 246 is the same port under another number.

INP(134) reads the bits back, so a program can flip one without disturbing the others.

Joystick ​

The official stick is the 4004/482, and it plugs into the I/O board rather than the computer itself — connector K3 (GPIO0), or K4 (GPIO1) for a second player. BASIC-G has no keyword that reads it, so a program does the work itself with OUT and INP.

Its five switches arrive on the low five bits of port 76, active low: a released stick reads 255, and a pressed switch pulls its bit to zero.

BitValueSwitch
01Down
12Up
24Right
38Left
416Fire

The connector's data lines run through a bidirectional buffer, and it points away from the computer until told otherwise — so a program that reads port 76 without setting it up first sees 255 no matter what the stick is doing. Turn it inward once, before the game loop:

basic
10 OUT 79,146 : REM the interface's mode
20 OUT 78,17  : REM point both connectors' buffers inward
30 J=255-INP(76)
40 IF J AND 2 THEN PRINT "UP"

Port 77 is the second connector, read exactly the same way.

Choosing Controller for the on-screen pad and switching the gamepad to the machine's own joystick sends a real stick here. It is left on key presses by default, which is what the bundled games read — they take K0–K3 through INKEY, not the joystick port.

Memory ​

The whole of the machine's address space, region by region. Zoom in to open a band into the parts it groups, and select a region for its addresses and what sits there.

Two things about this layout are unusual enough to be worth stating outright.

BASIC-G is not firmware. The interpreter lives in a replaceable ROM module the CPU cannot address at all: the Monitor reads it a byte at a time through a parallel-interface chip and copies it down to address 0 before anything runs. So the whole interpreter is in writable RAM, and a stray POKE really can take it down — there is no read-only memory below '8000 and nothing in the hardware to say no.

String space is not at the top of memory. Most Microsoft BASICs put the string pool above the arrays and let the two grow towards each other. BASIC-G gives strings a region of their own above its workspace, which is why the program area has a hard ceiling: program text, variables and arrays share the run from '2401 up to the stack at '5DFF, and that is the 14846 bytes a program has to fit in.

The two pools are spent independently, and the RAM readout counts both while a program runs — 18686 bytes in all, the program area plus the 3840-byte string region from '6000 to '6EFF. That is what makes string churn visible: a program that builds and drops strings moves the figure, and the profiler's memory report can say which line the bytes went to.

A PMD 85 program can carry fixed-address machine code or data — memory blocks — that load into RAM alongside the BASIC program before it runs. A block may sit in the program area itself, from '2401 to '5DFF, or in the free RAM above the string pool, from '6F00 to '7EFF; new blocks default to '7000, which is where the machine's own ROM n statement copies a module block and calls it. Everything else in the bottom 32K belongs to something that is live while a program runs, so a block reaching it is rejected outright rather than warned about. The block editor accepts an address either way round, as 0x7000 or as 28672.

Blocks travel with the document through the project bundle and through share links. On Run the IDE refuses to start if a block would overlap the BASIC program. See the machine code guide and the cross-dialect Machine code & data blocks overview. Every mnemonic, directive and operand form the assembly editor accepts is in the Z80 assembly reference — the PMD 85's MHB8080A is a Tesla-made 8080A clone and every 8080 instruction is a Z80 instruction, so the assembler assembles genuine 8080 code correctly. The reverse is not true: a Z80-only instruction will run here but would not have run on the real machine.

Released under GNU GPL v3.0. Some ROM images are third-party copyrighted works, separate to this project, strictly for personal/educational purposes.