Z88 Developers' Notes | ||
---|---|---|
Previous | Contents | Next |
7. Output and the screen driver
Output
Output to the screen can be achieved by treating the screen as a device
and using the file I/O system calls. However, there are four calls which
can be used to send output to what is called standard output, which although
it may be redefined by the CLI, see 'Standard I/O and the CLI', is usually
the screen device. The four calls are:
OS_Out write character to standard output
GN_Nln write newline to standard output (<CR><LF>)
GN_Sop write a string in local memory to standard output
GN_Soe as GN_Sop, but from an extended address
These calls are fairly friendly as far as register corruption is concerned.
OS_Out writes the character held in register A and forces Fc = 0 before
returning with no other register or flag changes. GN_Nln changes no registers
and returns Fc = 0 unless there is an error. GN_Sop and GN_Soe expect HL
(or BHL) to point to a null-terminated string, and on exit HL (or BHL)
will point to the null, with other registers remaining the same, unless
there is an error. Errors can occur if the standard output device has been
redirected to somewhere other than the screen. In the case of errors Fc
= 1 and register A will contain an error code. If you are not doing any
redirection yourself then these kind of error situations can be largely
ignored, since if the user is doing bizarre stream rebindings it is not
your responsibility what happens. Examples of these routines in use can
be seen in the "Input and the keyboard decoder" section.
In using the Z88 you may well have come across a "Page Wait" message
which appears on the left hand side of the screen in place of the application
name and list of topics. This message can be generated by an application
(it is not done automatically) when scrolling output is being sent to the
screen. The actual system call involved is OS_Sr with register A = SR_PWT.
This call produces the "Page Wait" message, waits for a key, restores the
application name and topic list and then returns to the application. Because
at the core of this routine there is a keyread, application writers must
be careful to check for pre-emption codes, especially RC_QUIT. Although
the writer may think about "Page Wait" as primarily an output function,
it has all the characteristics of an input function. However, it only returns
<BACKSPACE> (ASCII 8) and all relevant error codes like RC_QUIT and
RC_DRAW.
The screen driver
The Z88 incorporates a comprehensive screen driver, so that apart from
printing normal characters, the user may, by sending suitable control codes
to the screen:
Set fonts and select bold or flash effects for characters;
Switch the cursor on and off;
Simulate the effects of special keys (Caps lock, index etc.)
Define, select and scroll windows;
Select the horisontal and vertical print positions;
Set justification or alignment;
Set up user defined characters;
Make various strings of beeps
in fact, any graphic effects used by the built-in software with the single
exception of the map. This is accessed more directly through the system
calls, in particular OS_Map described in "Miscellaneous useful routines".
InterLogic have also supplied utilities to plot, draw lines and sprites
in the map area, which easily can be linked with application code using
the Z80 Module Assembler.
Direct Control Characters
The following standard control characters have a special effect:
The characters SOH ($01) is used as an escape character to prefix the special
character combinations. It may be followed either by a single special character,
or if more than one parameter is to follow, by a count byte which specifies
the number of following parameters - this may be in the form of a binary
number with the top bit set, ie. count plus 128, or an ASCII code for a
single decimal digit - clearly the latter is impossible for a count of
more than 9. Thus the following sequences are equivalent - both move the
cursor to character position (x,y):
1, '3', '@', 32+x, 32+y 1, 128+3, '@', 32+x, 32+y
NOTE: A character in single quotes is used in this section as a concise
notation for a character constant, so for instance 'A' is the ASCII code
for A, ie. $41 or 65 decimal. This translates into rather less elegant
ASC"A" when used in BBC BASIC or its assembler, so to send the former of
the above sequences to the screen from BBC BASIC one might do:
x=3: y=4 VDU 1,ASC"3", ASC"@", 32+x,32+y
Special Characters
The following screen driver codes generate special printable characters
when preceeded by SOH:
1, '2', '*', <char>
(where <char> is from 'A' to 'O') draws various character such as
arrows or box construction shapes (which are all boldable), with the following
logic:
Each of the bottom 4 bits of 'char' represents a direction:
For example, the corner generated: VDU 1, ASC"2", ASC"*", ASC"F"
makes a reasonable logical NOT sign.
User Defined Characters
Finally, the screen driver may create user defined characters by the
following combination which specifies the rows on a 6x8 matrix:
1, 138, '=', charcode, r0, r1, r2, r3, r4, r5, r6, r7
Note that the count of 10 is specified in numeric form with the top
bit set (138) as it will not fit in a single digit. If you use a smaller
count, the unspecified rows will be set to 0. This can be useful since
most system characters have a blank bottom row. The number 'charcode' is
the character code of the defined character and must be between 64 ('@')
and 127 (DEL) inclusive providing 64 user characters on an expanded machine.
On an unexpanded machine (ie. without 128K or more in slot 1) only 16 characters
can be defined without encroaching on the memory used for the PipeDream
map. Characters above the limit of 16, will have their definitions overwritten
by map information when PipeDream is used. If the map width is 64 pixels
or less then the full 64 user characters can be used.
r0 to r7 are the numeric representations of the top to bottom rows of
the character, with the top bit set. Bit 5 is on the left edge of the character
and bit 0 the right. The standard characters have their left-hand rows
blank, so if the user-defined characters are to sit alongside them, they
should follow this convention. The characters coexist with the normal characters
with the same code. Doing "VDU charcode" will print the system character,
whereas the sequence:
1, '2', '?', charcode
will print the user defined one. For instance:
10 VDU 1, 138, ASC"=", ASC"@", 155, 155, 128, 132, 132, 132, 145, 142,
128 20 VDU 1, ASC"2", ASC"?", ASC"@"
will draw a little smiling face to the screen.
Display Attributes
These combinations toggle various display modes of the current window
(applying to subsequently written characters):
With horizontal scrolling on, the row scrolls between the left and right margins when the cursor
tries to go outside of the window margins
else the cursor wraps from left column to right column or vice versa.
Horizontal scrolling disables vertical scrolling.
Rather than toggling these modes, they may be set or reset explicitly by
prefixing them with '+' (on) or '-' (off), and a count byte of two to indicate
that there are two parameters. For instance:
1, '2', '+', 'B'
sets bold on. When written in this form, modes may be combined in a
list, for example:
1, '5', '-', 'B', 'F', 'T', 'U'
resets the bold, flash, tiny, underline toggles. Finally SD_DTS ($7F)
deletes all toggle settings, ie. sets all toggles to off:
1, SD_DTS
Changing Display Attributes
The display modes are usually set at the time of writing text to the screen,
however it is possible to apply the various effects to text already present.
This approach is used in the menu system to highlight commands and by the
Filer to highlight files. The technique can only be used with the hardware
attributes ie. flash, grey, inverse and underline. The two commands, apply
and eor, work over the next <n> characters where <n> is the second
parameter and offset from 32:
1, '2', '+', 'R', 1, '3', '@', 32, 32, 1, '2', 'E', 52
Windows
Windows on the Z88 are referred to by a single ASCII numeric character.
Windows '1' to '6' are available for the user to redefine; '7' and '8'
are already used by the system - window '7' is the topic area, window '8'
is used by many of the system calls during error processing. Windows remember
their toggle settings, but if the window area is overwritten (by text from
an overlapping window, for example) then the window contents are lost.
The following sequences manipulate the windows. The # character is used
because it is vaguely reminiscent of a window:
Defining a Window
1, '7', '#', '<n>', 32+x, 32+y, 32+w, 32+d, t
The "type" of the window is defined by the parameter t:
This redefines window <n>, with the top left corner at (x,y) and
horizontal and vertical sizes of w and d respectively. The values of x
and y are offset from the top left corner of the application area ie. (10,0),
but can be made absolute (ie. offset from the top left corner of the screen)
by using 128+x, 128+y in the above sequence. E.g. for placing a window at top
left corner of the screen use relative coordinates 32-10,32-0, absolute
coordinates 128+0, 128+0 or mixed 128+0,32+0. It is very important that windows
do not go beyond the width of the screen. To avoid the OZ window, windows
should be no more than 94 6 pixel wide characters from the edge of the
application window, or 104 from the leftmost edge of the screen.
Application windows may be preserved by using the system call OS_Sr,
A=SR_SUS. This is a lazy method and consumes 2K of contigous memory - don't
use use it unless strictly necessary. Further, only the screen area starting
from (10,0) to the right edge (before the OZ window) are preserved. Windows
beyond that has to be redrawn explicitly. In any case, application windows
must be redrawn when your application is re-entered (otherwise your are
faced with a blank screen). If your application uses a window that overlaps
the system's topic window you must also re-draw your window after an executed
command, pressing <MENU> or the <HELP> key.
The OZ window contains special characters which control the LCD scanning
and if these are disturbed, the display will not work properly. If your
window overlaps the OZ area, these characters are almost certain to be
disturbed.
Selecting a Window
To direct output to a window use one of the three following sequences:
Deleting a Window
The following sequence clears a window including side bars and shelf brackets:
Window Scrolling
Grey Window
Bannered Window Example
The shelf brackets are used by the system to create banners at the top
of a window (see the Filer display for an example). This effect is achieved
by using inverted, tiny and underlined characters. We give here an example
in BBC BASIC. You can enter this program on the Z88 and see the effect
of a bannered window. It is worth modifying the program to gain a feel
for the way the various screen effects work and how they are accessed by
the screen driver:
10 VDU 1, ASC"7", ASC"#", ASC"1", 33, 32, 72, 40, 131
Note how the window is defined one character in from the edge of the
screen to allow space for the vertical bar. It is then redefined to exclude
the top line of the screen, thus the banner will be undisturbed by text
written to the window. The centralization is achieved by using the justification
codes, which are as follows:
Justification and Margins
Cursor Positioning
The cursor position, ie. the next print position, may be moved by the
following sequences - x and y are the column and row respectively, with
(0,0) being the top left of the current window:
Clear from Cursor
Unknown
Low Level Access
There are three calls which can be used to obtain information about
the current state of the screen and they are all accessed via OS_Nq which
takes a reason code in the BC register. A fuller description is given in
"Miscellaneous useful routines", but the reason codes of interest are:
ASCII name Value Z88 effect
NUL $00 Ignored (Possibly used by the system for control of screen restoring.)
SOH $01 Escape character for screen driver
BEL $07 Make a beep
BS $08 Move Cursor Left
HT $09 Move Cursor Right
LF $0A Move Cursor Down
VT $0B Move Cursor Up
FF $0C Clear screen (current window)
DEL $7F Draw black box, (currently, undefined codes do too)
Escape Sequences
Code Value Description Width Boldable
' ' $20 Exact symbol 1
'!' $21 Bell symbol 3
''' $27 Grave accent 1 yes
'*' $2A Square 1 yes
'+' $2B Diamond 1 yes
'-' $2D SHIFT symbol 3
'|' $7D Vertical unbroken bar 1 yes
SD_SPC $E0 SPACE symbol 3
SD_ENT $E1 ENTER symbol 3
SD_TAB $E2 TAB symbol 3
SD_DEL $E3 DEL symbol 3
SD_ESC $E4 ESC symbol 3
SD_MNU $E5 MENU symbol 3
SD_INX $E6 INDEX symbol 3
SD_HLP $E7 HELP symbol 3
SD_OLFT $F0 Outline arrow Left 2
SD_ORGT $F1 Outline arrow Right 2
SD_ODWN $F2 Outline arrow Down 2
SD_OUP $F3 Outline arrow Up 2
SD_BLFT $F4 Bullet arrow Left 1
SD_BRGT $F5 Bullet arrow Right 1
SD_BDWN $F6 Bullet arrow Down 1
SD_BUP $F7 Bullet arrow Up 1
SD_PLFT $F8 Pointer arrow Left 1 yes
SD_PRGT $F9 Pointer arrow Right 1 yes
SD_PDWN $FA Pointer arrow Down 1 yes
SD_PUP $FB Pointer arrow Up 1 yes
Box Characters
bit 0 decimal 1 Left
bit 1 decimal 2 Down
bit 2 decimal 4 Right
bit 3 decimal 8 Up
If one bit is set, a pointer arrow in the relevant direction is drawn.
If two bits are set, two sides of a square or a line will be drawn. If three bits
are set, a 'T' shape will be drawn. If all four bits are set, a cross will
be drawn.
Code Up Left Down Right Symbol
1, '2', '*', 'A' 0 0 0 1 Pointer arrow Right
1, '2', '*', 'B' 0 0 1 0 Pointer arrow Down
1, '2', '*', 'C' 0 0 1 1 Corner Down Right
1, '2', '*', 'D' 0 1 0 0 Pointer arrow Left
1, '2', '*', 'E' 0 1 0 1 Horizontal bar
1, '2', '*', 'F' 0 1 1 0 Corner Left Down
1, '2', '*', 'G' 0 1 1 1 T Down
1, '2', '*', 'H' 1 0 0 0 Pointer arrow Up
1, '2', '*', 'I' 1 0 0 1 Corner Up Right
1, '2', '*', 'J' 1 0 1 0 Vertical unbroken bar
1, '2', '*', 'K' 1 0 1 1 T Right
1, '2', '*', 'L' 1 1 0 0 Corner Up Left
1, '2', '*', 'M' 1 1 0 1 T Up
1, '2', '*', 'N' 1 1 1 0 T Left
1, '2', '*', 'O' 1 1 1 1 Cross
To draw a horizontally and vertically divided window:
C- -G- -F
| | |
| | |
K- -O- -N
| | |
| | |
I- -M- -L
1, 'B' Bold
1, 'C' Cursor visible
1, 'F' Flash
1, 'G' Grey
1, 'L' Caps Lock
1, 'R' Reverse video
1, 'S' Vertical scrolling
1, 'T' Tiny font
1, 'U' Underline
1, 'W' Horizontal scrolling
With vertical scrolling on, the window scrolls when the cursor tries to go outside of the window
else the cursor wraps from top row to bottom row or vice versa.
1, '2', 'A', 32+<n> Apply toggles
1, '2', 'E', 32+<n> EOR toggles
The following sequence inverts a 20 character bar at cursor position (0,0):
bit 0 sets left and right bars on
bit 1 sets shelf brackets on
bit 2 - 6 ignored
bit 7 must be set.
The type parameter is optional. Using a count byte of '6' will define the
window without bars or brackets.
The PipeDream map window actually has bit 5 and 6 set and not bit 7.
1, '2', 'H', '<n>' (Select and Hold)
1, '2', 'I', '<n>' (Select and Init)
1, '2', 'C', '<n>' (Select and Clear)
The 'H' version will maintain display modes, whereas the 'I' version
will reset them all (ie. cursor off, scrolling disabled). If this is the
first time the window has been selected (after being redefined) then the
'I' version will also clear the window. The 'C' version resets the display
modes and clears the window.
1, '2', 'D', '<n>' (Delete/Destroy)
1, SD_DWN ($FE) Scroll downwards
1, SD_UP ($FF) Scroll upwards
Scrolling downwards is the usual direction. These commands operate over
the current window, not the screen.
1, '2', 'G', '+' Grey window
1, '2', 'G', '-' Ungrey window
Please note that if you grey a window that has already been greyed then
ungreying doesn't work.
20 VDU 1, ASC"2", ASC"I", ASC"1"
30 VDU 1, ASC"4", ASC"+", ASC"T", ASC"U", ASC"R", 1, ASC"2", ASC"J",
ASC"C"
40 PRINT TAB(0,0);"CENTRAL BANNER"; TAB(0,0;
50 VDU 1, ASC"2", ASC"A", 72
60 VDU 1, ASC"7", ASC"#", ASC"1", 33, 33, 39, 129
70 VDU 1, ASC"2", ASC"I", ASC"1"
80 VDU 1, ASC"3", ASC"+", ASC"C", ASC"S"
1, '2', 'J', 'N' Normal
1, '2', 'J', 'C' Centre
1, '2', 'J', 'L' Left align
1, '2', 'J', 'R' Right align
1, 'L', 32+n Set left margin (n=leftmost character position)
1, 'R', 32+n Set right margin (n=rightmost character position)
The default is 'normal'. Note that there is no count byte for the left
and right margin commands. The non-normal justification modes only work
with directly output text, in particular the system input routine fails
spectacularly if it is used with these modes. It is also worth noting that
if you output more characters than will fit between the margins then horisontal
scrolling, and not wrapping, will occur.
1, '3', '@', 32+x, 32+y move to x,y
1, '2', 'X', 32+x horisontal tab
1, '2', 'Y', 32+y vertical tab
1, '2', 'C', 253 Clear from the cursor to the end of the line.
1, '2', 'C', 254 Clear from the cursor to the end of the window.
Multiple Output
1, '3', 'N', 32+n, m Output n copies of the code m
Multiple Bell
1, '4', '!', 32+r, 32+s, 32+m Beep sequence
A beep sequence is a series of beeps
(NOT a single beep), with mark m and space s (in 10ms ticks), and r cycles.
1, '2', '.', '[' Unknown (Possibly used by the system
1, '2', '.', ']' for control of screen restoring.)
NQ_WBOX return the size of a window
NQ_WCUR return the cursor location in a window and indicate whether enabled
NQ_RDS read characters from the screen starting at the cursor position
Previous | Contents | Next |
Memory Management | Output and the screen driver | File Input / Output |