The VDI is called via a single subprogram, which is passed five parameters; these are addresses of various arrays that are used for input/output communication. To call a VDI function, the following parameter block must be populated with the addresses of the arrays described below:
typedef struct { int16_t *contrl; /* Pointer to contrl array */ int16_t *intin; /* Pointer to intin array */ int16_t *ptsin; /* Pointer to ptsin array */ int16_t *intout; /* Pointer to intout array */ int16_t *ptsout; /* Pointer to ptsout array */ } VDIPB;
The address of this parameter block must then be stored in register d1, and additionally register d0.w must be filled with the value 0x73 (115). With a TRAP#2 system call the VDI can then be called directly. For the Pure-Assembler, for example, this could look like this:
.EXPORT vdi ; Export function .IMPORT contrl ; Import contrl field .IMPORT intin ; Import intin field .IMPORT ptsin ; Import ptsin field .IMPORT intout ; Import intout field .IMPORT ptsout ; Import ptsout field .DATA ; Start of the DATA segment pblock: .DC.L contrl ; Address of the contrl arrays .DC.L intin ; Address of the intin arrays .DC.L ptsin ; Address of the ptsin arrays .DC.L intout ; Address of the intout arrays .DC.L ptsout ; Address of the ptsout arrays .CODE ; Start of the CODE segment
vdi: MOVE.L #pblock,D1 ; Address of the parameter blocks MOVE.W #$73,D0 ; Opcode of the VDI TRAP #2 ; Call GEM RTS ; Exit here .END ; End of the module
There is no clear information available about which registers may be changed. In fact, however, the pertinent routines in ROM save all registers.
Unlike GEMDOS, the VDI unfortunately has no documented return value for 'unknown function number'. Hence, in doubtful cases, one has to help oneself as follows:
Many properties of a driver can already be obtained via the
function vq_extnd.
Otherwise one should simply try the relevant VDI call, and
then analyse the return values. This is because many functions return
the set value as a result. In addition one can examine the fields
contrl[2] and contrl[4] (see below) and check whether these hold the
correct numbers.
Now to the individual arrays. With each field, designated input and output actions can be carried out. The following apply:
int16_t contrl[12] | This field passes the function number, the number of entries,
the handle of the workstation as well as the function-dependent
parameters. Inputs to the VDI are entered as follows:
Outputs of the VDI are made via the following fields:
| ||||||||||||||||||
int16_t ptsin[1024] |
| ||||||||||||||||||
int16_t ptsout[256] | These two fields are used to pass pairs of coordinates or
dimensions in pixels (such as the width of a line, or the height of a
character, for instance). The size of these fields depends on the
function called.
| ||||||||||||||||||
int16_t intin[1024] |
| ||||||||||||||||||
int16_t intout[512] | These fields are required to pass values such as an index of a
character or of a colour. The size of these fields depends on the
function called.
|
When passing strings to the VDI, one should note some specialties: These are passed basically via the fields intin and intout, where one WORD per character is used. This has the advantage that other codings than ASCII can be used as well, and more than 256 characters of a font may be used.
As a rule the bindings work with normal C-strings, and convert them for the VDI. For this the length of the strings are stored in contrl[3] or contrl[4], and no terminating NULL-byte or WORD is present. To convert a character string lying in intout to a C-string, for instance, contrl[4] elements have to be copied (and the upper 8 bits cut off !) and then a NULL-byte appended.
Warning: If the operating system supports threads, then it is imperative that a multithread-proof library is used.
See also: C-string to VDI-string VDI-string to C-string AES bindings
VOID vdi_str_to_c( UWORD *src, UBYTE *des, int16_t len ) { while ( len > 0 ) { *des++ = (UBYTE)*src++; /* Only low byte */ len--; } *des++ = 0; /* End of string */ }
int16_t c_str_to_vdi( UBYTE *src, UWORD *des ) { int16_t len; while (( *des++ = *src++ ) != 0 ) len++; return (len); /* Length of the string without NULL byte */ }