Files
z80_monitor/README.md
T

5.0 KiB

Z80 UART monitor

This project provides a resident BIOS, an interactive monitor, and ROM-resident applications for a Z80 system with a UART/CTC card at I/O base 20.

At reset, a small ROM bootstrap copies only the BIOS and monitor into the top 16 KiB of RAM at C000. The BIOS initializes interrupt mode 2 and the UART, then starts the monitor. Applications remain in ROM and execute in place while calling the stable BIOS jump table in high RAM. Tiny BASIC is the first such application, linked at ROM address 1000.

Connect a terminal at 2400 baud, 8 data bits, no parity, 1 stop bit. Commands are case-insensitive and all numeric arguments are hexadecimal; an optional 0x prefix is accepted.

Command Action
D 8000 Dump 40 bytes starting at address 8000
D 8000 20 Dump 20 bytes starting at address 8000
W 8000 3E 41 D3 25 C9 Write bytes starting at address 8000
I 20 Read I/O port 20
O 20 57 Write 57 to I/O port 20
G 8000 Execute code at address 8000
G 1000 Start the ROM-resident Z80 Tiny BASIC interpreter
B or BASIC Shortcut for G 1000
HELP Show the command summary

G transfers control with a return address on the stack, so code ending in RET returns to the monitor. Code that changes the stack pointer, interrupt mode, or UART/CTC setup must restore it before returning.

Build the ROM and programmer-format images with:

make

The outputs are:

  • build/metal/monitor.bin: complete 32 KiB ROM image
  • build/metal/monitor.prog.bin: compact image ending at the last occupied byte
  • build/tinybasic/tinybasic.bin: standalone relocated Tiny BASIC payload

The current compact image is 6,157 bytes. Its ROM layout is:

  • 0000-007F: reset/copy bootstrap
  • 0080-0F9D: packed BIOS+monitor image copied to RAM at C000-CF1D
  • 0F9E-0FFF: unused space reserved for the resident image to grow
  • 1000-180C: Tiny BASIC, executed directly from ROM
  • 180D-7FFF: unused space available for additional ROM content

The resident image starts at C000, its IM 2 vector table is at C040, and linked code starts at C080. The bootstrap obtains the resident copy length from a linker symbol, so it tracks BIOS and monitor changes automatically.

The resulting RAM layout is:

  • 8000-AFFF: Tiny BASIC workspace and BASIC program text
  • B000-B077: Tiny BASIC variables and input buffer
  • B078-BFFF: Tiny BASIC stack space
  • C000-CF1D: resident BIOS, vectors, services, and monitor
  • CF1E-EFFF: free space for resident-image growth
  • F000-FFFF: BIOS globals, UART buffers, and monitor stack

The BIOS and monitor continue to work if low ROM is disabled. ROM-resident applications naturally require ROM to remain mapped while they execute.

BIOS interface

Assembly applications include include/bios.inc and call these fixed entries:

Address Service Interface
C050 BIOS_PUTC Write character in A
C053 BIOS_TRY_GETC Return character in A, or zero
C056 BIOS_GETC Wait for and return a character in A
C059 BIOS_IO_OUT Write L to port A
C05C BIOS_IO_IN Read port A, returning the value in A
C05F BIOS_DELAY_MS Delay approximately HL milliseconds
C062 BIOS_MONITOR Warm-start the monitor; does not return

The service wrappers preserve working registers except for documented return values. The monitor uses the corresponding C API declared in bios.h.

Project organization:

  • boot.asm: ROM bootstrap, high vectors, BIOS jump table, and assembly glue
  • bios.c / bios.h: UART, buffers, interrupts, and resident BIOS API
  • monitor.c: command interpreter implemented on the BIOS API
  • apps/tinybasic.asm: first ROM-resident application
  • apps/README.md: ROM application memory and integration contract
  • include/bios.inc: stable assembly interface for ROM applications

Tiny BASIC

Tiny BASIC is built from apps/tinybasic.asm. The port replaces fixed low-page RST calls with relocatable calls and uses a marker-based command table so it can be linked at a nonzero ROM address.

Tiny BASIC is linked at and runs directly from ROM address 1000. Start it from the monitor with:

B

BASIC and G 1000 are equivalent alternatives.

Tiny BASIC calls the BIOS at C050 for output and C053 for non-blocking input. Tiny BASIC keeps interrupts enabled so it can share the BIOS-configured interrupt-driven UART.

Line editing accepts either BS (08) or DEL (7F) for backspace and emits BS SPACE BS so ANSI-style terminals erase the character visually. Ctrl-U clears the complete input line.

During execution, Ctrl-O toggles output suppression without stopping the BASIC program. Press Ctrl-O again to resume output. Ctrl-C stops execution and returns to the Tiny BASIC prompt.

Tiny BASIC resets the stack pointer when it starts, so it does not currently return through the monitor's G call. Reset the machine to return to the monitor. The first currently unused ROM byte is 180D; 1900 is a convenient aligned starting point for another ROM payload.