...
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 six 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:
...
...
- , write
...
- character
...
- to
...
- standard
...
- output
- OS_Nln, write newline to standard output (<CR><LF>), replace GN_Nln
- OS_Sout, write a string in local memory to standard output, replace GN_Sop
- OS_Bout, as OS_Sout, but from an extended address, replace GN_Soe
- OS_Pout, write an embedded string at (PC)
- OS_Hout, write a hexadecimal byte to standard output
These calls are fully compatible with GN_Sop, GN_Soe, GN_Nln. They are deprecated and maintained for compatibility. They perform a significantly slower rendering.
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.
...
- 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 horizontal and vertical print positions
- Set justification or alignment
- Set up user defined characters
- Make various strings of beeps
in 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". The Standard library 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 Mpm.
...
The following screen driver codes generate special printable characters when preceeded by SOH:
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
1, '2', '*', <char>
...
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.
For example, the corner generated:
VDU 1, ASC"2", ASC"*", ASC"F"
makes a reasonable logical NOT sign. Here's the complete VDU's:
...
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
...
corner generated:
VDU 1, ASC"2", ASC"*", ASC"F"
makes a reasonable logical NOT sign. Here's the complete VDU's:
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 |
0
Pointer arrow |
Left |
1, '2', '*', ' |
E' | 0 | 1 |
0 | 1 |
Horizontal |
bar |
1, '2', '*', ' |
F' | 0 | 1 |
0
1 | 0 |
Corner |
Left |
Down |
1, '2', '*', ' |
G' | 0 | 1 |
0
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 |
Cross
To draw a horizontally and vertically divided window:
...
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:
Gliffy | ||||
---|---|---|---|---|
|
User Defined Characters
Finally, the screen driver may create user defined characters by the following combination which specifies the rows on a 6x8 matrix:
...
Application windows may be preserved by using the system call OS_Sr, A=SR_SUS. This is a lazy method and consumes 2K of continuous 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.
...
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:
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 position1, '2', '*', 'J'