Das VDI wird über ein einziges Unterprogramm aufgerufen, dem 5 Parameter übergeben werden; es handelt sich dabei um Adressen verschiedener Arrays, die zur Ein-/Ausgabe-Kommunikation benutzt werden. Um eine VDI-Funktion aufzurufen, muß der folgende Parameterblock mit den Adressen der unten beschriebenen Arrays bestückt werden:
typedef struct { int16_t *contrl; /* Zeiger auf contrl-Array */ int16_t *intin; /* Zeiger auf intin-Array */ int16_t *ptsin; /* Zeiger auf ptsin-Array */ int16_t *intout; /* Zeiger auf intout-Array */ int16_t *ptsout; /* Zeiger auf ptsout-Array */ } VDIPB;
Die Adresse dieses Parameterblocks muß dann im Register d1 vermerkt, und zusätzlich Register d0.w mit dem Wert 0x73 (115) gefüllt werden. Durch einen TRAP#2 Systemaufruf kann dann das VDI direkt aufgerufen werden. Für den Pure-Assembler könnte das z.B. so aussehen:
.EXPORT vdi ; Funktion exportieren .IMPORT contrl ; contrl-Feld importieren .IMPORT intin ; intin-Feld importieren .IMPORT ptsin ; ptsin-Feld importieren .IMPORT intout ; intout-Feld importieren .IMPORT ptsout ; ptsout-Feld importieren .DATA ; Beginn des Daten-Segments pblock: .DC.L contrl ; Adresse des contrl-Arrays .DC.L intin ; Adresse des intin-Arrays .DC.L ptsin ; Adresse des ptsin-Arrays .DC.L intout ; Adresse des intout-Arrays .DC.L ptsout ; Adresse des ptsout-Arrays .CODE ; Beginn des Code-Segments
vdi: MOVE.L #pblock,D1 ; Adresse des Parameterblocks MOVE.W #$73,D0 ; Opcode des VDI TRAP #2 ; GEM aufrufen RTS ; raus hier .END ; Ende des Moduls
Darüber, welche Register verändert werden dürfen, gibt es keine klaren Informationen. Tatsache ist jedoch, daß die entsprechenden Routinen im ROM alle Register retten.
Im Gegensatz zum GEMDOS kennt das VDI leider keinen dokumentierten Rückgabewert für 'unbekannte Funktionsnummer'. Daher muss man sich im Zweifelsfall wie folgt behelfen:
Viele Eigenschaften eines Treibers können bereits über die
Funktion vq_extnd ermittelt werden.
Ansonsten sollte man den entsprechenden VDI-Aufruf einfach
ausprobieren, und die Rückgabewerte analysieren. Viele Funktionen
liefern nämlich als Resultat den eingestellten Wert zurück. Darüber
hinaus kann man auch noch die Felder contrl[2] und contrl[4] (s.u.)
untersuchen, und kontrollieren, ob sie die korrekten Zahlen enthalten.
Nun zu den einzelnen Arrays. Über jedes Feld können bestimmte Ein- bzw. Ausgaben getätigt werden; es gilt:
int16_t contrl[12] | Über dieses Feld werden die Funktionsnummer, die Anzahl der
Eingaben, die Kennung der Workstation sowie funktionsabhängige
Parameter übergeben. Eingaben an das VDI werden dabei wie folgt
eingetragen:
Ausgaben des VDI werden über die folgenden Felder gemacht:
| ||||||||||||||||||
int16_t ptsin[1024] |
| ||||||||||||||||||
int16_t ptsout[256] | Diese beiden Felder werden benutzt, um Paare von Koordinaten
oder Maße in Pixeln (wie z.B. die Breite einer Linie, oder die Höhe
eines Zeichens) zu übergeben. Die Größe dieser Felder hängt von
der aufgerufenen Funktion ab.
| ||||||||||||||||||
int16_t intin[1024] |
| ||||||||||||||||||
int16_t intout[512] | Diese Felder werden benötigt, um Werte wie den Index eines
Zeichens oder einer Farbe zu übergeben. Die Größe dieser Felder
hängt von der aufgerufenen Funktion ab.
|
Bei der Übergabe von Strings an das VDI sind einige Besonderheiten zu beachten: Diese werden grundsätzlich über die Felder intin und intout übergeben, wobei pro Zeichen ein Wort benutzt wird. Das hat den Vorteil, daß auch andere Codierungen als ASCII genutzt, und mehr als 256 Zeichen eines Zeichensatzes verwendet werden können.
Die Bindings arbeiten i.d.R. mit normalen C-Strings, und wandeln sie für das VDI um. Dabei wird die Länge des Strings in contrl[3] bzw. contrl[4] vermerkt, wobei kein abschließendes Null-Byte oder -wort vorhanden ist. Um z.B. eine in intout liegende Zeichenkette in einen C-String zu verwandeln, müssen contrl[4] Elemente kopiert (dabei die oberen 8 Bit abschneiden !) und anschließend ein Null-Byte angehängt werden.
Achtung: Wenn das Betriebssystem Threads unterstützt, muss unbedingt darauf geachtet werden, eine Multithread-sichere Bibliothek zu verwenden.
Querverweis: C-String nach VDI-String VDI-String nach C-String AES-Bindings
VOID vdi_str_to_c( UWORD *src, UBYTE *des, int16_t len ) { while ( len > 0 ) { *des++ = (UBYTE)*src++; /* nur Low-Byte kopieren */ len--; } *des++ = 0; /* Ende des Strings */ }
int16_t c_str_to_vdi( UBYTE *src, UWORD *des ) { int16_t len; while (( *des++ = *src++ ) != 0 ) len++; return (len); /* Stringlänge ohne Null-Byte */ }