Assembly Language Tips/Tricks

Page Index

Useful and interesting Z-80 assembly language routines for the TRS-80.

Detect Model I, III or 4 from the Hardware - George Phillips

George Phillips wrote this routine to tell which TRS-80 a program is running on by testing the hardware itself, not by looking at the ROM. A ROM check cannot reliably tell a Model 4 from a Model III, because in Model III mode the Model 4 runs a Model III compatible ROM.

Call GETMODEL and it returns the model number in Register A: 1 for a Model I, 3 for a Model III, or 4 for a Model 4. It changes Registers A, B and C and the flags. The routine is 30 bytes long and uses only a relative jump, so it can be assembled at any address or packed into a string for a USR call.

Call it with interrupts disabled: DI before the CALL, and EI after it if interrupts were on. George leaves that to the caller on purpose, so the routine never turns interrupts back on for a program that had them off.

; GETMODEL - return TRS-80 Model number in A (1, 3 or 4).
GETMODEL:
IN A,(0FFH)
; read the OUTMOD latches (the Port ECH settings) back through Port FFH
LD B,A
; save the original settings in B, to compare against and to restore later
LD C,60H
; C = 01100000 = mask for Bit 6 (CPU Fast, 4 MHz, Model 4 only) and Bit 5 (Video Waits / DISWAIT)
XOR C
; flip Bits 6 and 5 of the original settings; every other bit stays as it was
OUT (0ECH),A
; write to Port ECH: on a machine that has them, this toggles the CPU speed and the video wait states
IN A,(0FFH)
; read the latches again; a latch that exists now holds its flipped value
XOR C
; flip Bits 6 and 5 back: a latch that took the write returns to its original value
XOR B
; compare against the original: Bit 6 or 5 is now 0 if that latch exists, 1 if it ignored the write
LD C,0ECH
; C = Port ECH, since A is holding the result and cannot be used for the OUT
OUT (C),B
; restore the original CPU speed and video wait settings
RLCA
; rotate left: Bit 7 goes to Carry (not used) and Bit 6 moves up to Bit 7
RLCA
; rotate left again: the Bit 6 (CPU Fast) result is now in the Carry flag
JR NC,.ISM4
; Carry clear means the CPU Fast latch exists, so it must be a Model 4
RLCA
; rotate left again: the Bit 5 (Video Waits) result is now in the Carry flag
LD A,3
; assume a Model III (LD does not change the Carry flag)
RET NC
; Carry clear means the Video Waits latch exists, so return with A = 3 for a Model III
LD A,1
; neither latch answered, so it is a Model I
RET
; return with A = 1
.ISM4:
LD A,4
; Model 4
RET
; return with A = 4

© George Phillips 2026

How It Works

On the Model III and Model 4, bits 1-6 of the OUTMOD latches set through Port ECH read back through bits 1-6 of Port FFH. The routine uses two of those bits:

  • Bit 6 is the CPU clock speed (2 MHz or 4 MHz). Only the Model 4 has it.
  • Bit 5 is the video wait state control (DISWAIT). The Model III and the Model 4 both have it, and so does the Model 4P, which still latches and reads it back even though it does not use it.

The routine reads the current latch settings and saves them in Register B. It flips bits 6 and 5 with XOR C (C = 60H), writes the result to Port ECH, and reads the latches back. XOR C then XOR B compares what came back with what was written: a bit is 0 if the latch took the new value and 1 if it did not. The original settings go back out with OUT (C),B, since Register A is holding the result of the compare. Both OUT instructions also send whatever Port FFH returned in bits 0 and 7 (the cassette data bits) to Port ECH, but the hardware ignores those two bits of Port ECH.

Two RLCA instructions move bit 6 into the Carry flag. If it is clear, the speed latch is there and the machine is a Model 4. A third RLCA moves bit 5 into the Carry flag. If it is clear, the wait state latch is there and the machine is a Model III. If neither latch answered, it is a Model I, where Port ECH is not connected at all.

Caution: George notes that a Model III with a speed-up board that uses Port ECH bit 6, the same bit as the Model 4's CPU speed control (the Seatronics Super Speed-Up Board, for one), is bound to throw the routine off.

Emulators: the emulators generally return the Port ECH settings on a read of Port FFH, so GETMODEL works in them. George considered also using the Model I's own Port FFH readback (bit 6, the inverse of the 32/64 video mode bit), but it was not needed, and emulators get that bit wrong, so detection would have broken in some of them.