Inside the Einstein: The MOS, a TatungBytes course: the MOS 1.2 start up screen on a rainbow sunburst
← Back to Modules
module
10

Putting Characters on the Screen

Introduction

Every character your programs have printed went through one routine, OUTC, at 0F1Ah. This section looks at the three doors into it, at the table that decides what a control code does, and at the 1,792 bytes that give each character its shape.

Three ways in

Call 158 is the one you know. Its table entry points at OUTC.

RST 10h is a one-byte shortcut to the same place. In the ROM, 0010h holds:

l0010h:
        jp OUTC                 ;0010

The MOS uses it to print single characters - the prompt, for one (S9). It saves a byte over RST 8 / DEFB 158 every time.

RST 18h prints a whole message, and the message is written in the code, straight after the RST:

PRMZ:
        ex (sp),hl              ;0018
l0019h:
        call PRMCHR             ;0019
        jr z,l0019h             ;001c
        ex (sp),hl              ;001e
        ret                     ;001f
...
PRMCHR:
        ld a,(hl)               ;0f3f
sub_0f40h:
        bit 7,a                 ;0f40
        res 7,a                 ;0f42
        rst 10h                 ;0f44
        inc hl                  ;0f45
        ret                     ;0f46

EX (SP),HL swaps HL with the return address - which is the address of the message. PRMCHR prints one character with RST 10h, but first tests bit 7: the last character of every message has bit 7 set. BIT 7,A sets the zero flag for every character except the last, so JR Z loops until the last one is printed. The final EX (SP),HL puts back a return address that now points past the message, so the program carries on after it.

The design saves bytes twice. No separate pointer to the message is needed, and no terminating zero: the end marker is a bit borrowed from the last character, which never needs bit 7 anyway. ERROR (S9) is written exactly like this.

Control codes: a second table

Characters below 20h are not printed; they do things. 13 returns to the start of the line, 10 moves down a line, 8 steps back. OUTC handles them with a table like FMTBL: VDUTBL, at 0A68h, 32 addresses - one for each code from 00h to 1Fh, in order.

VDUTBL:
        defw NODSP              ;0a68
        defw l09fbh             ;0a6a
        defw NODSP              ;0a6c
        defw NODSP              ;0a6e
        defw l08cfh             ;0a70
        defw NODSP              ;0a72
        defw l09a6h             ;0a74
        defw l0f71h             ;0a76
        defw l08e7h             ;0a78
        defw NODSP              ;0a7a
        defw l08d9h             ;0a7c
        defw l08e2h             ;0a7e
        defw l0930h             ;0a80
        defw CRET               ;0a82
        ...

Entry 0Dh is CRET, the carriage return. NODSP is a single RET: codes that do nothing all point at it, which is cheaper than testing for them.

The shapes of the letters

The Einstein's video chip draws each character from an 8 x 8 pattern of bits. Those patterns come from the ROM. PGTAB, at 116Dh, holds eight bytes for every character from 20h (space) to FFh - 224 characters, 1,792 bytes - and at start-up the MOS sends all of them to the video chip's memory.

Here is A, code 41h, at 116Dh + 8 x (41h - 20h) = 1275h:

        defb 000h,010h,028h,044h,07ch,044h,044h,000h    ;1275  ..(D|DD.

Write the bytes in binary, one under another, and the letter appears:

00h  ........
10h  ...#....
28h  ..#.#...
44h  .#...#..
7Ch  .#####..
44h  .#...#..
44h  .#...#..
00h  ........

Top row first; each 1 bit is a lit pixel, bit 7 on the left.

Above code 90 the shapes are not all the ASCII characters you might expect: the Einstein uses some of those codes for its own symbols. Its glyphs are whatever these 1,792 bytes say.

The code

Control codes are easiest to see by printing one between ordinary characters:

        ORG 256

        LD A,'A'
        RST 8
        DEFB 158
        LD A,'B'
        RST 8
        DEFB 158
        LD A,13         ; carriage return: VDUTBL entry 0Dh, CRET
        RST 8
        DEFB 158
        LD A,'C'
        RST 8
        DEFB 158
        RET

Build and run

Press Run.

What you should see

CAB
 A   BC   DE   HL   PC  SZ-H-PNC
43 3D41 08FF FB3E 0FA5 00101000

A and B were printed after the prompt; 13 went back to the start of the line, and C landed on top of the >. The register display shows A = 43h, the C.

Change one thing

In your copy of mos12.asm, change VDUTBL's entry for 0Dh from CRET to NODSP, rebuild the ROM (S5) and boot it. Before you look, predict two things: what the program above prints, and what the start-up screen looks like. The second is the more revealing - why does it change at all?

Summary

OUTC is reached by call 158, by RST 10h, and by RST 18h, which prints the text that follows it, ending at a byte with bit 7 set. Control codes 00h-1Fh are dispatched through VDUTBL, 32 addresses at 0A68h. Every character's shape is eight bytes in PGTAB, from 116Dh, copied to the video chip at start-up.

Next

S11 turns to the keyboard: how a key press becomes the character OUTC prints.

Get the Newsletter

New guides, disk images and community finds, roughly once a quarter. No spam, we promise, this isn't Tatung's marketing department.
Your subscription could not be saved. Please try again.
Your subscription has been successful.

Newsletter

Subscribe to our newsletter and stay updated.

This form is protected by reCAPTCHA, and the Google Privacy Policy and Terms of Service apply.