Give the console colour and a cursor

COLOUR COSTS A NIBBLE AND NO HARDWARE. A glyph is drawn in palette indices 0 and 1, paper
and ink, and a cell's attribute nibble adds sixteen to both - so sixteen banks is already
sixteen ink and paper pairs, and all that was missing was a register saying which one the
console draws in. That is port 0x06, read as well as written like the rest.

The palette a machine wakes up with is arranged so that HIGHLIGHTING IS ONE BIT: banks 0 to
7 are colours on black, banks 8 to 15 are the same colours as paper with black ink. So
attribute XOR 8 turns any pair inside out. That is a convention rather than a rule of the
machine - the device only ever adds the nibble and looks the answer up - but it is the
convention that makes a highlighted line and a cursor free.

Bank 0 is still grey on black, so nothing that was written before this has changed colour.

THE CURSOR IS THE SAME BIT AGAIN. It is drawn by turning its cell inside out rather than by
putting a block over it, so the character underneath stays readable, which matters to
somebody editing a line. The device draws it rather than the window, because on a machine
with a screen a cursor is a hardware feature - one drawn by the presenter would not be in a
picture the machine saved.

It blinks on the machine's own clock, half a second each way, so the phase is a pure
function of the cycle count and a screen saved at a given cycle is the same screen every
time. A blink on the host's clock would have made every saved picture a matter of luck.

Off unless asked for, with bit 2 of the control port. That is right for a machine - a
program painting its own screen does not want something blinking in the middle of it - and
CosmOS asks for one at boot. It also asks again when it takes the console back from a
program that has stopped, because a program handing key mode back the way it was told to
writes zero, which turns the cursor off. The shell owns the prompt, so the shell is what
makes sure there is something blinking at it.

Nine more checks in Tests/video.sh, to 41: that the attribute colours the ink and not the
paper, that XOR 8 turns both, that it reads back, that a cursor appears where the registers
put it and only when asked for, and that it goes dark again half a million cycles later.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E2JrLzFvuFX9fgi1LDRjrW
This commit is contained in:
Anachronaut
2026-08-29 08:13:28 -04:00
co-authored by Claude Opus 5
parent 978aec4809
commit d6feddd1b6
7 changed files with 235 additions and 21 deletions
+26 -3
View File
@@ -269,8 +269,8 @@ Port 0x00 is the oldest thing on this machine and it has not changed: writing se
| Port | Register |
| --- | --- |
| 0x00 | Data. Writing sends a byte out, reading takes one in and waits for it. |
| 0x01 | Status. Bit 0 a byte is waiting, bit 1 input has ended, bit 2 the console is in key mode, bit 3 the console is set to interrupt. |
| 0x02 | Control. Bit 0 asks for key mode, bit 1 asks the console to interrupt when a byte arrives. Writing 0x00 asks for neither, which is how the console starts. |
| 0x01 | Status. Bit 0 a byte is waiting, bit 1 input has ended, bit 2 the console is in key mode, bit 3 the console is set to interrupt, bit 4 a cursor is being shown. |
| 0x02 | Control. Bit 0 asks for key mode, bit 1 asks the console to interrupt when a byte arrives, bit 2 asks for a cursor. Writing 0x00 asks for none of them, which is how the console starts. |
The control port's two bits are independent, and one write sets both. Everything the control port can ask for, the status port reports, so a program can put the console back the way it found it instead of assuming it knows.
@@ -577,7 +577,7 @@ And the rows that scrolled off are still in the map, which is where a terminal o
A console on a machine with a screen sends every byte to both, because a machine with a screen and a serial line is an ordinary machine and there is one console driving both.
At reset the font is expanded into tile memory and the palette is given two entries: 0 is paper and 1 is ink. That is all a machine needs to be able to say something before any program has run, and it is deliberately not more - a program that wants colour sets it, and sixteen guessed entries would be sixteen a program had to overwrite.
At reset the font is expanded into tile memory and the palette is given sixteen ink and paper pairs. See Colour below.
The font is in ASCII order, so a byte becomes a glyph by subtracting 32. Bytes below that have no glyph and are not drawn; three of them do something instead.
@@ -589,6 +589,24 @@ The font is in ASCII order, so a byte becomes a glyph by subtracting 32. Bytes b
Writing past the last column wraps to the next row, the same as a newline.
### Colour:
A glyph is drawn in palette indices 0 and 1 - paper and ink - and a cell's attribute nibble adds sixteen to both. **So sixteen banks is sixteen ink and paper pairs**, and a text attribute system costs one nibble and no hardware at all.
Which pair the console draws in is the Attribute register, 0x06. Everything written after it is drawn that way, until it changes.
The palette a machine wakes up with is arranged so that **highlighting is one bit**:
| Attribute | Paper | Ink |
| --- | --- | --- |
| 0 | Black | Grey |
| 1 to 7 | Black | Red, green, yellow, blue, magenta, cyan, white |
| 8 to 15 | The same seven and grey | Black |
So `attribute XOR 8` turns any pair inside out, which is what a highlighted line wants and how the cursor is drawn. Bank 0 is grey on black, which is what plain text has always been.
**That arrangement is a convention rather than a rule of the machine.** A program that wants different colours writes its own palette, and one that wants thirty-two of something rather than sixteen pairs can have that too - the device only ever adds the nibble and looks the answer up.
### Moving The Cursor:
Three more registers, because that is how this machine talks to everything else.
@@ -598,6 +616,11 @@ Three more registers, because that is how this machine talks to everything else.
| 0x03 | Cursor row. Read and write. |
| 0x04 | Cursor column. Read and write. |
| 0x05 | Command. Write 1 to clear the screen. |
| 0x06 | Attribute. Read and write. |
**A cursor is shown only when it is asked for**, with bit 2 of the Control port, and status bit 4 says whether one is being shown. Off is the right default for a machine: a program painting its own screen does not want something blinking in the middle of it, and a system that reads lines from a person turns it on.
It is drawn by turning its cell inside out rather than by putting a block over it, so the character underneath stays readable - which matters to somebody editing a line. And it blinks **on the machine's own clock**, half a second on and half a second off, so the picture at a given cycle count is the same picture every time and a saved screen is not a matter of luck.
Both counted from zero, and both **readable**, which is the thing worth having: a routine that wants to put the cursor back where it found it asks where that was.