Character definitions; Boot message; VDU tables - 1216 bytes (7.4%)


§1. Character definitions.

font.png

 This is the start of the OS, located at $C000.

 The shape of each printable character (ASCII codes 32-126) is defined below. They are used
 to draw text in all non-teletext MODEs 0-6 (see .displayACharacter). Character 127 (DELETE)
 is not a printable character, but is given a definition here anyway as a solid block of set
 pixels. It's drawn in the background colour to erase the character at the graphics cursor.

 Characters already drawn can be read from the screen, to retrieve the ASCII code from the
 pattern of pixels on screen. The OS itself uses this when in cursor editing mode (the two
 cursor editing with READ and WRITE cursors, as seen in the BASIC line editor and user text
 input in general). See .osbyte135EntryPoint.

 Historical note: The BBC Micro was Acorn's first computer to contain a character set in
 ROM, unless you count the seven-segment LED settings for the hex digits 0 to F in the
 tiny Acorn System 1. The System 2 used teletext graphics akin to the BBC's Mode 7, and
 the Atom's rather smaller set of symbols (which lacked lower-case letters) were similarly
 generated directly in the video circuitry rather than being plotted from symbols in ROM.
* = $C000

.characterDefinitions = $c000
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........

    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %........
    !byte %...##...
    !byte %........

    !byte %.##.##..
    !byte %.##.##..
    !byte %.##.##..
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........

    !byte %..##.##.
    !byte %..##.##.
    !byte %.#######
    !byte %..##.##.
    !byte %.#######
    !byte %..##.##.
    !byte %..##.##.
    !byte %........

    !byte %....##..
    !byte %..######
    !byte %.##.#...
    !byte %..#####.
    !byte %....#.##
    !byte %.######.
    !byte %...##...
    !byte %........

    !byte %.##.....
    !byte %.##..##.
    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %.##..##.
    !byte %.....##.
    !byte %........

    !byte %..###...
    !byte %.##.##..
    !byte %.##.##..
    !byte %..###...
    !byte %.##.##.#
    !byte %.##..##.
    !byte %..###.##
    !byte %........

    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........

    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %..##....
    !byte %..##....
    !byte %...##...
    !byte %....##..
    !byte %........

    !byte %..##....
    !byte %...##...
    !byte %....##..
    !byte %....##..
    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %........

    !byte %........
    !byte %...##...
    !byte %.######.
    !byte %..####..
    !byte %.######.
    !byte %...##...
    !byte %........
    !byte %........

    !byte %........
    !byte %...##...
    !byte %...##...
    !byte %.######.
    !byte %...##...
    !byte %...##...
    !byte %........
    !byte %........

    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %...##...
    !byte %...##...
    !byte %..##....

    !byte %........
    !byte %........
    !byte %........
    !byte %.######.
    !byte %........
    !byte %........
    !byte %........
    !byte %........

    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %...##...
    !byte %...##...
    !byte %........

    !byte %........
    !byte %.....##.
    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %.##.....
    !byte %........
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.##.###.
    !byte %.######.
    !byte %.###.##.
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %...##...
    !byte %..###...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %.######.
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.....##.
    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %.######.
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.....##.
    !byte %...###..
    !byte %.....##.
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %....##..
    !byte %...###..
    !byte %..####..
    !byte %.##.##..
    !byte %.######.
    !byte %....##..
    !byte %....##..
    !byte %........

    !byte %.######.
    !byte %.##.....
    !byte %.#####..
    !byte %.....##.
    !byte %.....##.
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %...###..
    !byte %..##....
    !byte %.##.....
    !byte %.#####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %.######.
    !byte %.....##.
    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %..##....
    !byte %..##....
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %..#####.
    !byte %.....##.
    !byte %....##..
    !byte %..###...
    !byte %........

    !byte %........
    !byte %........
    !byte %...##...
    !byte %...##...
    !byte %........
    !byte %...##...
    !byte %...##...
    !byte %........

    !byte %........
    !byte %........
    !byte %...##...
    !byte %...##...
    !byte %........
    !byte %...##...
    !byte %...##...
    !byte %..##....

    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %.##.....
    !byte %..##....
    !byte %...##...
    !byte %....##..
    !byte %........

    !byte %........
    !byte %........
    !byte %.######.
    !byte %........
    !byte %.######.
    !byte %........
    !byte %........
    !byte %........

    !byte %..##....
    !byte %...##...
    !byte %....##..
    !byte %.....##.
    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %....##..
    !byte %...##...
    !byte %...##...
    !byte %........
    !byte %...##...
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.##.###.
    !byte %.##.#.#.
    !byte %.##.###.
    !byte %.##.....
    !byte %..####..
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.######.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %........

    !byte %.#####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.#####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.#####..
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %.####...
    !byte %.##.##..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##.##..
    !byte %.####...
    !byte %........

    !byte %.######.
    !byte %.##.....
    !byte %.##.....
    !byte %.#####..
    !byte %.##.....
    !byte %.##.....
    !byte %.######.
    !byte %........

    !byte %.######.
    !byte %.##.....
    !byte %.##.....
    !byte %.#####..
    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.##.....
    !byte %.##.###.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.######.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %........

    !byte %.######.
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %.######.
    !byte %........

    !byte %..#####.
    !byte %....##..
    !byte %....##..
    !byte %....##..
    !byte %....##..
    !byte %.##.##..
    !byte %..###...
    !byte %........

    !byte %.##..##.
    !byte %.##.##..
    !byte %.####...
    !byte %.###....
    !byte %.####...
    !byte %.##.##..
    !byte %.##..##.
    !byte %........

    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %.######.
    !byte %........

    !byte %.##...##
    !byte %.###.###
    !byte %.#######
    !byte %.##.#.##
    !byte %.##.#.##
    !byte %.##...##
    !byte %.##...##
    !byte %........

    !byte %.##..##.
    !byte %.##..##.
    !byte %.###.##.
    !byte %.######.
    !byte %.##.###.
    !byte %.##..##.
    !byte %.##..##.
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %.#####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.#####..
    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##.#.#.
    !byte %.##.##..
    !byte %..##.##.
    !byte %........

    !byte %.#####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.#####..
    !byte %.##.##..
    !byte %.##..##.
    !byte %.##..##.
    !byte %........

    !byte %..####..
    !byte %.##..##.
    !byte %.##.....
    !byte %..####..
    !byte %.....##.
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %.######.
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %........

    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %...##...
    !byte %........

    !byte %.##...##
    !byte %.##...##
    !byte %.##.#.##
    !byte %.##.#.##
    !byte %.#######
    !byte %.###.###
    !byte %.##...##
    !byte %........

    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %...##...
    !byte %..####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %........

    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %........

    !byte %.######.
    !byte %.....##.
    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %.##.....
    !byte %.######.
    !byte %........

    !byte %.#####..
    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %.#####..
    !byte %........

    !byte %........
    !byte %.##.....
    !byte %..##....
    !byte %...##...
    !byte %....##..
    !byte %.....##.
    !byte %........
    !byte %........

    !byte %..#####.
    !byte %.....##.
    !byte %.....##.
    !byte %.....##.
    !byte %.....##.
    !byte %.....##.
    !byte %..#####.
    !byte %........

    !byte %...##...
    !byte %..####..
    !byte %.##..##.
    !byte %.#....#.
    !byte %........
    !byte %........
    !byte %........
    !byte %........

    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %########

    !byte %...###..
    !byte %..##.##.
    !byte %..##....
    !byte %.#####..
    !byte %..##....
    !byte %..##....
    !byte %.######.
    !byte %........

    !byte %........
    !byte %........
    !byte %..####..
    !byte %.....##.
    !byte %..#####.
    !byte %.##..##.
    !byte %..#####.
    !byte %........

    !byte %.##.....
    !byte %.##.....
    !byte %.#####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.#####..
    !byte %........

    !byte %........
    !byte %........
    !byte %..####..
    !byte %.##..##.
    !byte %.##.....
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %.....##.
    !byte %.....##.
    !byte %..#####.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..#####.
    !byte %........

    !byte %........
    !byte %........
    !byte %..####..
    !byte %.##..##.
    !byte %.######.
    !byte %.##.....
    !byte %..####..
    !byte %........

    !byte %...###..
    !byte %..##....
    !byte %..##....
    !byte %.#####..
    !byte %..##....
    !byte %..##....
    !byte %..##....
    !byte %........

    !byte %........
    !byte %........
    !byte %..#####.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..#####.
    !byte %.....##.
    !byte %..####..

    !byte %.##.....
    !byte %.##.....
    !byte %.#####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %........

    !byte %...##...
    !byte %........
    !byte %..###...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %..####..
    !byte %........

    !byte %...##...
    !byte %........
    !byte %..###...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %.###....

    !byte %.##.....
    !byte %.##.....
    !byte %.##..##.
    !byte %.##.##..
    !byte %.####...
    !byte %.##.##..
    !byte %.##..##.
    !byte %........

    !byte %..###...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %..####..
    !byte %........

    !byte %........
    !byte %........
    !byte %..##.##.
    !byte %.#######
    !byte %.##.#.##
    !byte %.##.#.##
    !byte %.##...##
    !byte %........

    !byte %........
    !byte %........
    !byte %.#####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %........

    !byte %........
    !byte %........
    !byte %..####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %........

    !byte %........
    !byte %........
    !byte %.#####..
    !byte %.##..##.
    !byte %.##..##.
    !byte %.#####..
    !byte %.##.....
    !byte %.##.....

    !byte %........
    !byte %........
    !byte %..#####.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..#####.
    !byte %.....##.
    !byte %.....###

    !byte %........
    !byte %........
    !byte %.##.##..
    !byte %.###.##.
    !byte %.##.....
    !byte %.##.....
    !byte %.##.....
    !byte %........

    !byte %........
    !byte %........
    !byte %..#####.
    !byte %.##.....
    !byte %..####..
    !byte %.....##.
    !byte %.#####..
    !byte %........

    !byte %..##....
    !byte %..##....
    !byte %.#####..
    !byte %..##....
    !byte %..##....
    !byte %..##....
    !byte %...###..
    !byte %........

    !byte %........
    !byte %........
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..#####.
    !byte %........

    !byte %........
    !byte %........
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..####..
    !byte %...##...
    !byte %........

    !byte %........
    !byte %........
    !byte %.##...##
    !byte %.##.#.##
    !byte %.##.#.##
    !byte %.#######
    !byte %..##.##.
    !byte %........

    !byte %........
    !byte %........
    !byte %.##..##.
    !byte %..####..
    !byte %...##...
    !byte %..####..
    !byte %.##..##.
    !byte %........

    !byte %........
    !byte %........
    !byte %.##..##.
    !byte %.##..##.
    !byte %.##..##.
    !byte %..#####.
    !byte %.....##.
    !byte %..####..

    !byte %........
    !byte %........
    !byte %.######.
    !byte %....##..
    !byte %...##...
    !byte %..##....
    !byte %.######.
    !byte %........

    !byte %....##..
    !byte %...##...
    !byte %...##...
    !byte %.###....
    !byte %...##...
    !byte %...##...
    !byte %....##..
    !byte %........

    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %........
    !byte %...##...
    !byte %...##...
    !byte %...##...
    !byte %........

    !byte %..##....
    !byte %...##...
    !byte %...##...
    !byte %....###.
    !byte %...##...
    !byte %...##...
    !byte %..##....
    !byte %........

    !byte %..##...#
    !byte %.##.#.##
    !byte %.#...##.
    !byte %........
    !byte %........
    !byte %........
    !byte %........
    !byte %........

    !byte %########
    !byte %########
    !byte %########
    !byte %########
    !byte %########
    !byte %########
    !byte %########
    !byte %########

§2. Screen initialisation on reset.

 [This is an oddity, since there's no real reason for this JMP instruction to be here. The
 only caller (see .skipSpeech) could have equally used 'JSR .initialiseVDUVariablesAndSetMODE'
 instead of 'JSR .initialiseScreenOnReset' saving three bytes and three cycles.]
.vduBaseAddress = $c300
.initialiseScreenOnReset = $c300
    JMP .initialiseVDUVariablesAndSetMODE               

§3. The boot message.

Boot.png

 Here a BBC Micro Model B has booted up, displaying the 32K version of its welcome message.
 The Acorn Disk Filing System, installed on this machine as a sideways ROM, also identifies
 itself, after which the MOS enters the language ROM, BBC BASIC. It's BASIC, not the MOS,
 which displays the ">" prompt and receives commands. The screen is in MODE 7, so the
 text uses Teletext characters rather than being rendered in the raster font above.

 The startup sound has random variation in the first tone(s) as the sound chip starts
 playing random data on reset until the audio is silenced (See .resetClearAllSounds), and
 the second tone is the familiar .charBELL sound from the boot message below.

 Teletext characters look smoother than the regular raster font, thanks to the hardware's
 diagonal smoothing algorithm, giving them an effective resolution of 10x18 pixels instead
 of 8x8 in other MODEs.
 See https://en.wikipedia.org/wiki/Pixel-art_scaling_algorithms#SAA5050_'diagonal_smoothing'.

 Historical note: All of Acorn's early computers booted up with brief identifications
 like this, then a skipped line, then a prompt. For the System 2, it was "Acorn Cos",
 referring to its "cassette operating system"; for the Atom, which had only upper case
 characters, the ident was "ACORN ATOM". What is perhaps most notable about the ident on
 the original BBC Micro is that it mentions the BBC, but not Acorn (unless additional
 ROMs such as the disc filing system are also plugged in). Subsequent models did
 not follow this pattern: the BBC Master ident is "Acorn MOS", and the B+ is "Acorn OS"
 plus a RAM size.

5050.png

.bootMessage = $c303
    !text .charRETURN, "BBC Computer ", 0

.bootMessageMemory16 = $c312
    !text "16K", .charBELL, 0

.bootMessageMemory32 = $c317
    !text "32K", .charBELL, 0

.bootMessageEnding = $c31c
    !text .charBACKSPACE, .charRETURN, .charRETURN      overlaps by one byte into the
                                                        following table for the zero
                                                        terminator

§4. Four colour conversion table.

 Used when drawing characters to the screen. The index into the table is a pattern of four
 bits (%0000-%1111) representing half of the eight bit text character row definition. The
 value of the array entry is the byte value required to write that pattern of white pixels
 on screen.
.fourColourMODEByteMaskTable = $c31f
    !byte $00, $11, $22, $33, $44, $55, $66, $77
    !byte $88, $99, $AA, $BB, $CC, $DD, $EE, $FF

§5. Sixteen colour conversion table.

 Used when drawing characters to the screen. The index into the table is a pattern of two
 bits (%00-%11) representing a quarter of the eight bit text character row definition. The
 value of the array entry is the byte value required to write that pattern of white pixels
 on screen.
.sixteenColourMODEByteMaskTable = $c32f
    !byte $00, $55, $AA, $FF

§6. Table of addresses (low byte) to handle VDU N.

 This table stores the low byte of the address of the routine to handle VDU n.
 It holds values for VDU 0-31 and 127.
.vduEntryPointTableLow = $c333
    !byte <.vdu0EntryPoint                              Does nothing
    !byte <.vdu1EntryPoint                              Send next character to printer only
    !byte <.vdu2EntryPoint                              Enable printer
    !byte <.vdu3EntryPoint                              Disable printer
    !byte <.vdu4EntryPoint                              Write text at text cursor
    !byte <.vdu5EntryPoint                              Write text at graphics cursor
    !byte <.vdu6EntryPoint                              Enable VDU drivers
    !byte <.vdu7EntryPoint                              Make a short beep
    !byte <.vdu8EntryPoint                              Move cursor left
    !byte <.vdu9EntryPoint                              Move cursor right
    !byte <.vdu10EntryPoint                             Move cursor down
    !byte <.vdu11EntryPoint                             Move cursor up
    !byte <.vdu12EntryPoint                             Clear text window
    !byte <.vdu13EntryPoint                             Move cursor to start of current line
    !byte <.vdu14EntryPoint                             Paged mode on
    !byte <.vdu15EntryPoint                             Paged mode off
    !byte <.vdu16EntryPoint                             Clear graphics window
    !byte <.vdu17EntryPoint                             Define text colour
    !byte <.vdu18EntryPoint                             Define graphics colour
    !byte <.vdu19EntryPoint                             Change palette colour
    !byte <.vdu20EntryPoint                             Restore default palette
    !byte <.vdu21EntryPoint                             Disable VDU drivers / delete line
    !byte <.vdu22EntryPoint                             Select screen MODE
    !byte <.vdu23EntryPoint                             Define character shape (etc)
    !byte <.vdu24EntryPoint                             Define graphics window
    !byte <.vdu25EntryPoint                             PLOT
    !byte <.vdu26EntryPoint                             Restore default windows
    !byte <.vdu27EntryPoint                             Does nothing
    !byte <.vdu28EntryPoint                             Define text window
    !byte <.vdu29EntryPoint                             Define graphics origin
    !byte <.vdu30EntryPoint                             Move text cursor to top left
    !byte <.vdu31EntryPoint                             Move text cursor to X,Y
.vduEntryPointTableDelete = $c353
    !byte <.vdu127EntryPoint                            Delete

§7. Table of addresses (high byte) to handle VDU N.

 The previous table holds the lower byte.
 This table holds values for VDU 0-31 and 127.

 If parameters are required then the top bit is clear, (16 - number of parameters) is stored
 in the lower 4 bits, and the remaining three of the top four bits holds the high byte of
 the offset from .vduBaseAddress. We only have three bits to store the offset's high byte,
 so the offset must be less than $800. For this reason, VDU calls with parameters are stored
 near the start of the ROM.

 The top bit set indicates that no parameters are required, so the entry just holds the high
 byte of the address directly.
.vduEntryPointTableHigh = $c354
    !byte >.vdu0EntryPoint                                      Does nothing
    !byte (>(.vdu1EntryPoint - .vduBaseAddress))*16 + (16 - 1)  Send next character to
                                                                printer only (1 parameter)
    !byte >.vdu2EntryPoint                                      Enable printer
    !byte >.vdu3EntryPoint                                      Disable printer
    !byte >.vdu4EntryPoint                                      Write text at text cursor
    !byte >.vdu5EntryPoint                                      Write text at graphics cursor
    !byte >.vdu6EntryPoint                                      Enable VDU drivers
    !byte >.vdu7EntryPoint                                      Make a short beep
    !byte >.vdu8EntryPoint                                      Move cursor left
    !byte >.vdu9EntryPoint                                      Move cursor right
    !byte >.vdu10EntryPoint                                     Move cursor down
    !byte >.vdu11EntryPoint                                     Move cursor up
    !byte >.vdu12EntryPoint                                     Clear text area
    !byte >.vdu13EntryPoint                                     Move cursor to start of
                                                                current line
    !byte >.vdu14EntryPoint                                     Paged mode on
    !byte >.vdu15EntryPoint                                     Paged mode off
    !byte >.vdu16EntryPoint                                     Clear graphics window
    !byte (>(.vdu17EntryPoint - .vduBaseAddress))*16 + (16 - 1) Define text colour
                                                                (1 parameter)
    !byte (>(.vdu18EntryPoint - .vduBaseAddress))*16 + (16 - 2) Define graphics colour
                                                                (2 parameters)
    !byte (>(.vdu19EntryPoint - .vduBaseAddress))*16 + (16 - 5) Define palette colour
                                                                (5 parameters)
    !byte >.vdu20EntryPoint                                     Restore default palette
    !byte >.vdu21EntryPoint                                     Disable VDU drivers /
                                                                delete current line
    !byte (>(.vdu22EntryPoint - .vduBaseAddress))*16 + (16 - 1) Select screen MODE
                                                                (1 parameter)
    !byte (>(.vdu23EntryPoint - .vduBaseAddress))*16 + (16 - 9) Define character shape (etc)
                                                                (9 parameters)
    !byte (>(.vdu24EntryPoint - .vduBaseAddress))*16 + (16 - 8) Define graphics window
                                                                (8 parameters)
    !byte (>(.vdu25EntryPoint - .vduBaseAddress))*16 + (16 - 5) PLOT (5 parameters)
    !byte >.vdu26EntryPoint                                     Restore default windows
    !byte >.vdu27EntryPoint                                     Does nothing
    !byte (>(.vdu28EntryPoint - .vduBaseAddress))*16 + (16 - 4) Define text window
                                                                (4 parameters)
    !byte (>(.vdu29EntryPoint - .vduBaseAddress))*16 + (16 - 4) Define graphics origin
                                                                (4 parameters)
    !byte >.vdu30EntryPoint                                     Move text cursor to top left
    !byte (>(.vdu31EntryPoint - .vduBaseAddress))*16 + (16 - 2) Move text cursor to X,Y
                                                                (2 parameters)
    !byte >.vdu127EntryPoint                                    Delete

§8. Multiplication tables.

 Used for calculating screen addresses
.multiplyBy640Table = $c375
    !be16 0 * 640
    !be16 1 * 640
    !be16 2 * 640
    !be16 3 * 640
    !be16 4 * 640
    !be16 5 * 640
    !be16 6 * 640
    !be16 7 * 640
    !be16 8 * 640
    !be16 9 * 640
    !be16 10 * 640
    !be16 11 * 640
    !be16 12 * 640
    !be16 13 * 640
    !be16 14 * 640
    !be16 15 * 640
    !be16 16 * 640
    !be16 17 * 640
    !be16 18 * 640
    !be16 19 * 640
    !be16 20 * 640
    !be16 21 * 640
    !be16 22 * 640
    !be16 23 * 640
    !be16 24 * 640
    !be16 25 * 640
    !be16 26 * 640
    !be16 27 * 640
    !be16 28 * 640
    !be16 29 * 640
    !be16 30 * 640
    !be16 31 * 640

.multiplyBy40Table = $c3b5
    !be16 0 * 40
    !be16 1 * 40
    !be16 2 * 40
    !be16 3 * 40
    !be16 4 * 40
    !be16 5 * 40
    !be16 6 * 40
    !be16 7 * 40
    !be16 8 * 40
    !be16 9 * 40
    !be16 10 * 40
    !be16 11 * 40
    !be16 12 * 40
    !be16 13 * 40
    !be16 14 * 40
    !be16 15 * 40
    !be16 16 * 40
    !be16 17 * 40
    !be16 18 * 40
    !be16 19 * 40
    !be16 20 * 40
    !be16 21 * 40
    !be16 22 * 40
    !be16 23 * 40
    !be16 24 * 40

§9. Screen MODE dimensions.

 The maximum text row and column number in each MODE.
.textWindowBottomRowTable                               Maximum text row number
    !byte 31                                            MODE 0 (32 rows)
    !byte 31                                            MODE 1 (32 rows)
    !byte 31                                            MODE 2 (32 rows)
    !byte 24                                            MODE 3 (25 rows)
    !byte 31                                            MODE 4 (32 rows)
    !byte 31                                            MODE 5 (32 rows)
    !byte 24                                            MODE 6 (25 rows)
    !byte 24                                            MODE 7 (25 rows)

.textWindowRightColumnTable                             Maximum text column number
    !byte 79                                            MODE 0 (80 columns)
    !byte 39                                            MODE 1 (40 columns)
    !byte 19                                            MODE 2 (20 columns)
    !byte 79                                            MODE 3 (80 columns)
    !byte 39                                            MODE 4 (40 columns)
    !byte 19                                            MODE 5 (20 columns)
    !byte 39                                            MODE 6 (40 columns)
    !byte 39                                            MODE 7 (40 columns)

§10. Video Control Register of the VideoULA.

 bit
   0 - Flash colour select (which of the flashing colours is displayed)
   1 - Teletext select
   2 - } These two bits determine the number of characters per row
   3 - } from this table:
       %00 = 10 characters per row
       %01 = 20 characters per row
       %10 = 40 characters per row
       %11 = 80 characters per row
   4 - CRTC clock rate select:
        %0 = low frequency clock for MODEs 4-7
        %1 = high frequency clock for MODEs 0-3
   5 - } These two bits determine the width of cursor in bytes
   6 - } from this table:
       %00 = 1 (MODEs 0,3,4,6)
       %01 = - undefined
       %10 = 2 (MODEs 1,5,7)
       %11 = 4 (MODE 2)
   7 - Master cursor width. If set, causes a larger cursor to be displayed
.videoULAVideoControlRegisterDefaultValuesPerMODE = $c3f7
    !byte %10011100                                     MODE 0
    !byte %11011000                                     MODE 1
    !byte %11110100                                     MODE 2
    !byte %10011100                                     MODE 3
    !byte %10001000                                     MODE 4
    !byte %11000100                                     MODE 5
    !byte %10001000                                     MODE 6
    !byte %01001011                                     MODE 7

.bytesPerCharacter = $c3ff
    !byte 8                                             MODE 0
    !byte 16                                            MODE 1
    !byte 32                                            MODE 2
    !byte 8                                             MODE 3
    !byte 8                                             MODE 4
    !byte 16                                            MODE 5
    !byte 8                                             MODE 6
    !byte 1                                             MODE 7

§11. Pixel tables.

 A 16 colour MODE (MODE 2) has two pixels per byte. The first table gives the byte
 values required to set each pixel in a byte to white (leaving the remainder black).
 The second table is the equivalent for four colour MODEs (four pixels per byte).
 The third table is the equivalent for two colour MODEs (eight pixels per byte, dual use
 with .fontMaskTable)
.sixteenColourMODEMaskTable = $c407
    !byte %10101010, %01010101                          2 pixels per byte (MODE 2)

.fourColourMODEMaskTable = $c409
    !byte %10001000, %01000100, %00100010, %00010001    4 pixels per byte (MODE 1 or 5)

.fontMaskTable                                          8 pixels per byte (MODE 0 or 4)
     This array is dual purpose - used both as the 8 pixels per byte MODE mask table and
     also to interrogate a particular bit in the vduFontByte.
     !byte $80, $40, $20, $10, $08, $04, $02
     The next byte overlaps (being the last byte in this table and the first byte in the
     next)

.numberOfColoursMinusOneInMODETable = $c414
    !byte 1                                             MODE 0
    !byte 3                                             MODE 1
    !byte 15                                            MODE 2
    !byte 1                                             MODE 3
    !byte 1                                             MODE 4
    !byte 3                                             MODE 5
    !byte 1                                             MODE 6
    !byte 0                                             MODE 7

§12. gcolPlotOptionsTable.

 This table is used when setting .vduGraphicsColourByteOR and .vduGraphicsColourByteEOR
 in .setGraphicsColourMaskXY. This table is used to help implement the GCOL Mode.

 GCOL Mode: 0=Normal, 1=OR, 2=AND, 3=EOR, 4=Invert

 See .setGraphicsColourMaskXY
.gcolPlotOptionsTable = $c41c
    !byte $FF                                           Underflow: The last byte of the
    !byte $00                                           previous table (zero) is accessed as
    !byte $00                                           part of the calculations.
    !byte $FF                                           
    !byte $FF                                           
    !byte $FF                                           
    !byte $FF                                           
    !byte $00                                           Overflow: The following byte in the
                                                        next table (zero) is accessed as
                                                        part of the calculations.

§13. Solid colour tables.

 The following tables hold the byte values required to write a full solid byte of COLOUR N
 on screen (N being the offset into the table). One table for the 2 colour MODEs, one for
 4 colour MODEs, and one for 16 colour MODEs.
 See .vdu18EntryPoint.
.twoColourMODEParameterTable = $c424
    !byte %00000000                                     
    !byte %11111111                                     

.fourColourMODEParameterTable = $c426
    !byte %00000000                                     
    !byte %00001111                                     
    !byte %11110000                                     
    !byte %11111111                                     

.sixteenColourMODEParameterTable = $c42a
    !byte %00000000                                     
    !byte %00000011                                     
    !byte %00001100                                     
    !byte %00001111                                     
    !byte %00110000                                     
    !byte %00110011                                     
    !byte %00111100                                     
    !byte %00111111                                     
    !byte %11000000                                     
    !byte %11000011                                     
    !byte %11001100                                     
    !byte %11001111                                     
    !byte %11110000                                     
    !byte %11110011                                     
    !byte %11111100                                     
    !byte %11111111                                     

.pixelsPerByteMinusOneInMODETable = $c43a
    !byte 7                                             MODE 0
    !byte 3                                             MODE 1
    !byte 1                                             MODE 2
    !byte 0                                             MODE 3
    !byte 7                                             MODE 4
    !byte 3                                             MODE 5
    Overflow: the first two bytes of the next table are accessed as the last two bytes of
    this table (zero for MODE 6 and 7 values).

    This table describes how much memory each MODE takes. Eight byte table (one byte for
    each MODE), overlapping with the next two tables.
.screenDisplayMemoryIndexTable = $c440
    !byte 0                                             MODE 0

    Sound pitch offsets table: Notes played on different sound channels are offset in pitch
    slightly from each other (perhaps to reduce phase shift effects when the same note is
    played on two or more different channels). This is four bytes long (in the middle of
    the previous table!).
.soundPitchOffsetByChannelTable                         Dual use:
                                                        screen memory   sound pitch offsets
                                                        -----------------------------------
    !byte 0                                             MODE 1          Channel 0
    !byte 0                                             MODE 2          Channel 1
    !byte 1                                             MODE 3          Channel 2
    !byte 2                                             MODE 4          Channel 3

    !byte 2                                             MODE 5
    !byte 3                                             MODE 6
                                                        Overflow: the first byte of the next
                                                        table is accessed for:
                                                        MODE 7 - next byte, value 4


Table of offsets into the VDU variables, used when line plotting
.vduGraphicsWindowBoundariesTable = $c447
    !byte .vduGraphicsWindowPixelsRightLow - .vduVariablesStart     } offsets into the VDU
    !byte .vduGraphicsWindowPixelsLeftLow - .vduVariablesStart      } variables of the
    !byte .vduGraphicsWindowPixelsTopLow - .vduVariablesStart       } graphics window edges
    !byte .vduGraphicsWindowPixelsBottomLow - .vduVariablesStart    }

§14. Hardware scroll tables.

 Stores which System VIA Register B registers to write, see .systemVIARegisterB
.systemVIAHardwareScrollTable1                          
Which System VIA register to write to set the hardware scrolling, for each MODE group.
    !byte 13                                            20k (MODE 0,1,2)
    !byte 5                                             16k (MODE 3)
    !byte 13                                            10k (MODE 4,5)
    !byte 5                                             8k  (MODE 6)
                                                        Overflows one byte into next table
                                                        1k  (MODE 7)

Which System VIA register to write to set the hardware scrolling, for each MODE group.
.systemVIAHardwareScrollTable2 = $c44f
    !byte 4                                             20k (MODE 0,1,2)
    !byte 4                                             16k (MODE 3)
    !byte 12                                            10k (MODE 4,5)
    !byte 12                                            8k  (MODE 6)
    !byte 4                                             1k  (MODE 7)

Low byte of the address to clear the screen in each MODE group
.clearScreenRoutineEntryPointLow = $c454
    !byte <.clearScreenRoutineEntryPointMODE012         MODE 0,1,2
    !byte <.clearScreenRoutineEntryPointMODE3           MODE 3
    !byte <.clearScreenRoutineEntryPointMODE45          MODE 4,5
    !byte <.clearScreenRoutineEntryPointMODE6           MODE 6
    !byte <.clearScreenRoutineEntryPointMODE7           MODE 7

screen size (high byte) for each MODE group
.screenMemorySizeInBytesHigh = $c459
    !byte $50                                           MODEs 0,1,2 ($5000 = 20k)
    !byte $40                                           MODE  3     ($4000 = 16k)
    !byte $28                                           MODEs 4,5   ($2800 = 10k)
    !byte $20                                           MODE  6     ($2000 = 8k)
    !byte $04                                           MODE  7     ($0400 = 1k)

screen start address (high byte) for each MODE group
.screenMemoryStartHigh = $c45e
    !byte $30                                           MODEs 0,1,2 ($3000)   %00110000
    !byte $40                                           MODE  3     ($4000)   %01000000
    !byte $58                                           MODEs 4,5   ($5800)   %01011000
    !byte $60                                           MODE  6     ($6000)   %01100000
    !byte $7C                                           MODE  7     ($7C00)   %01111100

number of bytes in each row
.bytesPerRowLow = $c463
    !byte <40                                           MODE 7          40 bytes per row
    !byte <320                                          MODE 4,5,6     320 bytes per row
    !byte <640                                          MODE 0,1,2,3   640 bytes per row

Which multiplication table to use (low byte of address, assumes the multiplication tables
are in the same page)
.multiplicationTabletoUseLow = $c466
    !byte <.multiplyBy40Table                           MODE 7
    !byte <.multiplyBy640Table                          MODE 4,5,6
    !byte <.multiplyBy640Table                          MODE 0,1,2,3

Offset to CRTC cursor end register in each MODE group
.crtcCursorEndRegisterTable = $c469
    !byte .crtcMODEs012CursorEndRegister - .crtcRegisters0to11ForMODEs012   MODEs 0,1,2
    !byte .crtcMODE3CursorEndRegister    - .crtcRegisters0to11ForMODEs012   MODE  3
    !byte .crtcMODE45CursorEndRegister   - .crtcRegisters0to11ForMODEs012   MODEs 4,5
    !byte .crtcMODE6CursorEndRegister    - .crtcRegisters0to11ForMODEs012   MODE  6
    !byte .crtcMODE7CursorEndRegister    - .crtcRegisters0to11ForMODEs012   MODE  7

default CRTC register values
.crtcRegisters0to11ForMODEs012 = $c46e
    !byte 127                                           R0 = Horizontal total register
    !byte 80                                            R1 = Horizontal displayed register
    !byte 98                                            R2 = Horizontal sync position
                                                        register
    !byte $28                                           R3 = The sync width register
    !byte 38                                            R4 = Vertical total register
    !byte 0                                             R5 = Vertical total adjust register
    !byte 32                                            R6 = Vertical displayed register
                                                        (number of visible character rows)
    !byte 34                                            R7 = Vertical sync position
    !byte %00000001                                     R8 = Interlace and delay register
    !byte 7                                             R9 = Scan lines per character
    !byte $67                                           R10 = Cursor start register
.crtcMODEs012CursorEndRegister = $c479
    !byte 8                                             R11 = The cursor end register

.crtcRegisters0to11ForMODE3 = $c47a
    !byte 127                                           R0 = Horizontal total register
    !byte 80                                            R1 = Horizontal displayed register
    !byte 98                                            R2 = Horizontal sync position
                                                        register
    !byte $28                                           R3 = The sync width register
    !byte $1E                                           R4 = Vertical total register
    !byte $02                                           R5 = Vertical total adjust register
    !byte $19                                           R6 = Vertical displayed register
                                                        (number of visible character rows)
    !byte $1B                                           R7 = Vertical sync position
    !byte $01                                           R8 = Interlace and delay register
    !byte $09                                           R9 = Scan lines per character
    !byte $67                                           R10 = Cursor start register
.crtcMODE3CursorEndRegister = $c485
    !byte $09                                           R11 = The cursor end register

.crtcRegisters0to11ForMODEs45 = $c486
    !byte $3F                                           R0 = Horizontal total register
    !byte $28                                           R1 = Horizontal displayed register
    !byte $31                                           R2 = Horizontal sync position
                                                        register
    !byte $24                                           R3 = The sync width register
    !byte $26                                           R4 = Vertical total register
    !byte $00                                           R5 = Vertical total adjust register
    !byte $20                                           R6 = Vertical displayed register
                                                        (number of visible character rows)
    !byte $22                                           R7 = Vertical sync position
    !byte $01                                           R8 = Interlace and delay register
    !byte $07                                           R9 = Scan lines per character
    !byte $67                                           R10 = Cursor start register
.crtcMODE45CursorEndRegister = $c491
    !byte $08                                           R11 = The cursor end register

.crtcRegisters0to11ForMODE6 = $c492
    !byte $3F                                           R0 = Horizontal total register
    !byte $28                                           R1 = Horizontal displayed register
    !byte $31                                           R2 = Horizontal sync position
                                                        register
    !byte $24                                           R3 = The sync width register
    !byte $1E                                           R4 = Vertical total register
    !byte $02                                           R5 = Vertical total adjust register
    !byte $19                                           R6 = Vertical displayed register
                                                        (number of visible character rows)
    !byte $1B                                           R7 = Vertical sync position
    !byte $01                                           R8 = Interlace and delay register
    !byte $09                                           R9 = Scan lines per character
    !byte $67                                           R10 = Cursor start register
.crtcMODE6CursorEndRegister = $c49d
    !byte $09                                           R11 = The cursor end register

.crtcRegisters0to11ForMODE7 = $c49e
    !byte $3F                                           R0 = Horizontal total register
    !byte $28                                           R1 = Horizontal displayed register
    !byte $33                                           R2 = Horizontal sync position
                                                        register
    !byte $24                                           R3 = The sync width register
    !byte $1E                                           R4 = Vertical total register
    !byte $02                                           R5 = Vertical total adjust register
    !byte $19                                           R6 = Vertical displayed register
                                                        (number of visible character rows)
    !byte $1B                                           R7 = Vertical sync position
    !byte $93                                           R8 = Interlace and delay register
    !byte $12                                           R9 = Scan lines per character
    !byte $72                                           R10 = Cursor start register
.crtcMODE7CursorEndRegister = $c4a9
    !byte $13                                           R11 = The cursor end register

§15. VDU Line Plotting.

.vduPlotLineRoutineAddresses = $c4aa
    !word .plotLineMoveToNextColumnRight                if X axis is dominant, move right
    !word .plotLineMoveToNextRowUp                      if Y axis is dominant, move up

.vduRoutineBranchVectorAddressesLow = $c4ae
    !byte <.plotLineDominantYAxisSameSign               
    !byte <.plotLineDominantYAxisDifferentSign          
    !byte <.plotLineDominantXAxisSameSign               
    !byte <.plotLineDominantXAxisDifferentSign          

.vduRoutineBranchVectorAddressesHigh = $c4b2
    !byte >.plotLineDominantYAxisSameSign               
    !byte >.plotLineDominantYAxisDifferentSign          
    !byte >.plotLineDominantXAxisSameSign               
    !byte >.plotLineDominantXAxisDifferentSign          

§16. Converting characters in Teletext.

teletext.png

 Writing printable characters (32-126) directly to the display memory in MODE 7
 gives different results in three cases to printing via OSWRCH. In particular:

 Value     Write to Screen     Write to screen
           Memory Directly       via OSWRCH
 ----------------------------------------------
   $23           £                   #
   $5F           #                   long dash
   $60           long dash           £
 ----------------------------------------------
.teletextCharacterConversionTable = $c4b6
    !byte $23                                           when writing a character in MODE 7,
                                                        replace each byte here with the next
                                                        in the table
    !byte $5F                                           when reading the character from the
                                                        screen, replace each byte with the
                                                        previous in the table
    !byte $60                                           
    !byte $23                                           

§17. Soft character table offsets.

 Converts the OSBYTE 20 parameter 1-6 (how much of the character set to 'explode', i.e.
 which range of character definitions can be redefined) into the offset into the
 .vduFontZoneAddressesHigh1 table, which stores the page addresses used to define characters
 in an 'exploded' soft character set.
 See .osbyte20EntryPoint
.softCharacterRamAllocationTable = $c4ba
    !byte $04                                           1 -> 4 = range of characters 128-159
    !byte $05                                           2 -> 5 = range of characters 160-191
    !byte $06                                           3 -> 6 = range of characters 192-223
    !byte $00                                           4 -> 0 = range of characters  32-63
    !byte $01                                           5 -> 1 = range of characters  64-95
    !byte $02                                           6 -> 2 = range of characters  96-127