The Agon's picture is generated by its ESP32, the VDP. VIOS gives you two ways to put things on the screen:
- The GUI display server on the ESP32: windows, surfaces, menus, widgets,
sprites and animation, driven from Forth with the
UI-words. This is what you normally use, and it is described in The GUI. - Raw VDP access: a small set of words that send VDU commands straight to the VDP and read back characters and pixels, as BBC BASIC does on a stock Agon. They are useful for experiments, for full-screen graphics in other screen modes, and for talking to VDP features VIOS has no wrapper for.
This chapter covers the raw layer and how it coexists with the GUI.
The VIOS display mode
At power-on the ESP32 selects mode 0: 640x480 pixels, 16 colours, 60 Hz
and starts the GUI compositor in it, before the eZ80 has even loaded VIOS.
The GUI and the console (both the Console window and the full-screen text
console) are drawn only in this mode. VDP-INFO asks the VDP
what it is doing:
VDP-INFO
vdp width 640 height 480 colours 16 mode 0 console-dropped 0
console-dropped counts console input bytes the eZ80 had to discard
because its input buffers were full; it should stay 0.
Raw VDU output
VDU sends one byte to the VDP; VTYPE sends a
string of bytes. These are the same VDU byte streams documented for the
Agon VDP and BBC BASIC: printable bytes are drawn as text at the VDP's text
cursor, and control codes start commands (for example VDU 17,n sets a
colour, VDU 25,... plots, VDU 23,... reaches system and graphics
functions).
: VDU2 ( u -- ) DUP 255 AND VDU 8 RSHIFT VDU ; \ send u as a 16-bit little-endian value
CREATE BELL 1 C, 7 C,
BELL COUNT VTYPE
Unlike TYPE, VDU and VTYPE bypass the console: the bytes are not part
of the console text, are not echoed to USB, and the console view does not
know about them.
The convenience words wrap the common commands:
| Word | Effect | VDU sequence |
|---|---|---|
CLS |
( -- ) clear the text area |
12 |
COLOUR |
( n -- ) text colour: n < 128 foreground, 128+n background |
17, n |
MODE |
( n -- ) change screen mode and check it |
22, n |
PLOT |
( mode x y -- ) graphics operation |
25, mode, x; y; |
CHAR@ |
( x y -- c ) character at text column x, row y |
23, 0, &83, x; y; |
PIXEL@ |
( x y -- rgb index ) pixel colour at graphics point x, y |
23, 0, &84, x; y; |
VDP-INFO |
( -- ) print the mode |
23, 0, &86 |
BEEP |
( freq ms -- status ) a note on audio channel 0 |
23, 0, &85, ... |
CHAR@, PIXEL@, VDP-INFO, MODE and BEEP wait for the VDP's reply
and fail with a timeout error (for example VDP pixel timeout) after about
one second without one.
Colours
In mode 0 the 16 palette entries are, by default:
| Index | Colour | Index | Colour |
|---|---|---|---|
| 0 | black | 8 | dark grey |
| 1 | red | 9 | bright red |
| 2 | green | 10 | bright green |
| 3 | yellow | 11 | bright yellow |
| 4 | blue | 12 | bright blue |
| 5 | magenta | 13 | bright magenta |
| 6 | cyan | 14 | bright cyan |
| 7 | light grey | 15 | white |
n COLOUR sets the text foreground; 128 n + COLOUR sets the text
background. Graphics colours are set with VDU 18,mode,colour (GCOL):
: GCOL ( colour -- ) 18 VDU 0 VDU VDU ;
10 COLOUR 128 COLOUR
12 GCOL
PIXEL@ returns the pixel's colour as a packed RGB cell (red + green256 +
blue65536, 8 bits each) and its palette index:
0 0 PIXEL@ . .
Plotting
PLOT sends VDU 25,mode,x;y;. Coordinates are 16-bit. By
default the VDP uses BBC BASIC logical coordinates: the screen is 1280 by
1024 units whatever the mode, with (0,0) at the bottom left. VDU 23,0,&C0,0
switches to plain pixel coordinates with (0,0) at the top left, and
VDU 23,0,&C0,1 back. PIXEL@ uses the same coordinate system as PLOT;
CHAR@ uses text columns and rows.
Common plot codes (all with absolute coordinates):
| Mode | Operation |
|---|---|
| 4 | move to x, y |
| 5 | draw a line to x, y in the graphics foreground colour |
| 69 | plot a single point |
| 85 | filled triangle using the last two points and x, y |
| 101 | filled rectangle from the last point to x, y |
| 149 | circle outline through x, y around the last point |
| 157 | filled circle |
: MOVE-TO ( x y -- ) 4 -ROT PLOT ;
: LINE-TO ( x y -- ) 5 -ROT PLOT ;
: RECT ( x0 y0 x1 y1 -- ) 2SWAP MOVE-TO 101 -ROT PLOT ;
: TRIANGLE ( -- ) 100 100 MOVE-TO 400 100 LINE-TO 250 400 LINE-TO 100 100 LINE-TO ;
TRIANGLE
600 600 900 800 RECT
Reading the screen back
x y CHAR@ returns the character code shown at text column x, row y, or 0
if the VDP does not recognise the glyph. The VDP matches glyphs against the
current text colours, so set the colours the text was drawn with first
(on the full-screen console, 3 COLOUR 128 COLOUR); otherwise even correct
text reads back as 0.
0 0 CHAR@ .
Screen modes
MODE changes the VDP's screen mode and then asks the VDP which
mode it is in; if the VDP refused the change, MODE fails with
VDP mode rejected (the VDP then stays in, or restores, its previous mode).
The modes of the VDP firmware VIOS ships:
| Mode | Resolution | Colours | Notes |
|---|---|---|---|
| 0 | 640x480 | 16 | the VIOS display mode (GUI and console) |
| 1 | 640x480 | 4 | |
| 2 | 640x480 | 2 | |
| 3 | 640x240 | 64 | |
| 4 | 640x240 | 16 | |
| 5 | 640x240 | 4 | |
| 6 | 640x240 | 2 | |
| 7 | 640x480 | 16 | teletext |
| 8 | 320x240 | 64 | |
| 9 | 320x240 | 16 | |
| 10 | 320x240 | 4 | |
| 11 | 320x240 | 2 | |
| 12 | 320x200 | 64 | |
| 13 | 320x200 | 16 | |
| 14 | 320x200 | 4 | |
| 15 | 320x200 | 2 | |
| 16 | 800x600 | 4 | |
| 17 | 800x600 | 2 | |
| 18 | 1024x768 | 2 | |
| 129-134, 136-143 | as mode n-128 | double-buffered variants |
A mode change clears the screen and resets the palette, text and graphics colours, viewports and cursor.
13 MODE
4 0 0 PLOT 157 640 512 PLOT
Leaving mode 0 suspends the GUI and the console view. The GUI
compositor and the console renderer only draw in mode 0, so in any other
mode the screen shows only what you draw with VDU commands. VIOS keeps
running normally: the console still works over USB and the keyboard still
types into the REPL, but you will not see your typing on the screen. Type
0 MODE (blind, if necessary) to return; the GUI notices the new
framebuffer and repaints everything, console included.
Raw drawing and the GUI
In mode 0 the GUI compositor owns the screen. It redraws any part of the
screen where something changed: a window moved, text arrived in the
Console window, a widget updated. Whatever you plot with raw VDU commands
underneath it stays only until the compositor next repaints that area. Raw
drawing is fine for quick experiments; for anything that should stay on the
screen alongside windows, draw into a GUI surface or use sprites with the
UI- words (see The GUI). For a full-screen raw graphics
program, switch to another mode, draw, and return with 0 MODE when you
are done.
The DISPLAY-WRITE binding
DISPLAY-WRITE ( addr u -- ) is a deferred word bound
to VTYPE at boot. Programs that send raw display bytes through
DISPLAY-WRITE instead of VTYPE can later be pointed elsewhere (a log,
a test buffer, another renderer) with IS, without recompiling. The
console never goes through it, so rebinding it cannot hide the console.
VARIABLE DISPLAY-BYTES
: COUNT-DISPLAY ( addr u -- ) DUP DISPLAY-BYTES +! VTYPE ;
' COUNT-DISPLAY IS DISPLAY-WRITE
S" Hi" DISPLAY-WRITE DISPLAY-BYTES ?
' VTYPE IS DISPLAY-WRITE
A beep
BEEP plays a note on VDP audio channel 0 at a fixed volume and
returns the VDP's status byte (non-zero when the note was accepted). Both
the frequency in Hz and the duration in milliseconds must fit in 16 bits.
For music, envelopes and the VIOS audio engine, see Audio.
440 250 BEEP DROP