LE GEM EN GFA Basic

 

deuxieme PARTIE : Le vdi

Ouvrez votre "Atari Compendium" Page 465 ...

Oui je sais ça vous rappelle de mauvais souvenirs, mais là je vous assure qu'il est préférable d'avoir cette bible sous la main, ou n'importe quel équivalent, pour qu'on puisse causer VDI.

La couche VDI est composée de drivers permettant d'accéder, en toute abstraction avec le type de hardware, à différents périphériques dont votre écran, une imprimante ou même une tablette graphique.

Pour rappel du précédent tutoriel, tout ce qui vous sera expliqué ici sera ainsi parfaitement exécutable sur une vraie machine Atari ou sur une machine virtuelle (Aranym par exemple).

Ainsi VDI nous propose un grand nombre de routines graphiques nous permettant de faire du graphisme vectoriel sans avoir à ce soucier des spécificités matérielles de la machine.

Il s'agit de faire son marché dans le compendium, et d'utiliser les routines adaptées à vos besoins, c'est à peine plus compliqué que cela.


Exemple extrait du compendium :


v_arc()

VOID v_arc( handle, x, y, radius, startangle, endangle )

WORD handle, x, y, radius, startangle, endangle;

v_arc() outputs an arc to the specified workstation.

OPCODE 11

SUB-OPCODE 2

AVAILABILITY Supported by all drivers. This function composes one of the 10 VDI GDP’s

(Generalized Drawing Primitives). Although all current drivers support all

GDP’s, their availability is not guaranteed and may vary. To check for a particular

GDP refer to the table returned by v_opnvwk() or v_opnwk().


Cette fonction VDI permet comme indiqué de dessiner un arc de cercle à l'écran. Les anglophones auront toutefois noté la présence de la rubrique "Availability" dans la description.

C'est la première chose qu'il vous vaudra considérer, car seules certaines routines VDI fonctionnent sur toutes les déclinaisons du GEM, et ce sans ajout de composants externes comme SpeedoGDOS ou FontGDOS.

Il vous faudra donc guetter particulièrement les fonctions comme celle indiquée en exemple, arborant fièrement leur "Supported by all drivers".

Cette seule contrainte suffira à vous garantir qu'il n'y aura pas de soucis quand vous montrerez votre appli géniale à votre pote super équipé (que vous jalousez secrètement bien sûr), avec son Falcon à carte Centek 60 Mega Power Turbo bi-valve.

Et à ce jeu, il y a déjà de quoi s'amuser largement avec les routines les plus compatibles.


Vous vous souvenez du tuto sur l'AES avec ses "handles", les descripteurs des fenêtres ?

La première chose à faire avant de jouer avec VDI va être de créer de la même manière un descripteur désignant l'écran.

Il y a une fonction GFA pour cela, elle se nomme GRAF_HANDLE :

ghandle%=GRAF_HANDLE(char_w%,char_h%,box_w%,box_h%)


La valeur de retour, le handle donc, ne servira pas dans l’immédiat, mais les paramètres passés, et qui sont des paramètres en sortie, renvoient des valeurs intéressantes pour une utilisation ultérieure.

Notamment les deux premiers renvoient la taille en pixels de la police système.


Mais revenons au VDI, ce dernier avant toute chose a besoin d’une « Virtual workstation », considérons

Pour faire simple qu’il s’agit d’un écran virtuel pointant sur l’écran physique.

Là encore le GFA nous donne un coup de main avec la fonction V_OPNVWK :

vhandle%=V_OPNVWK(1,1,1,1,1,1,1,1,1,1,2)


Que de paramètres n’est ce pas ? Si le cœur vous en dit vous pouvez là encore compulser le compendium quant au choix des valeur à passer.

Ici je ne mentionnerai que la première valeur qui est l’identifiant du périphérique physique, le compendium nous indiquant que la valeur 1 est une valeur acceptable dans la plupart des cas pour désigner un écran.

La dernière est aussi intéressante, car elle fixe le système de coordonnées choisi.

Nous pouvons choisir entre une origine placée en haut à gauche de l’écran, ou bien en bas à gauche. La valeur 2 indique en l’occurrence le choix naturel de l’origine en haut à gauche.


Bien, maintenant que nous avons notre descripteur de virtual workstation, nous sommes prêts à dessiner.

Et je ne sais pas pour vous, mais cette fenêtre toute creuse me dérange un peu, alors commençons par lui donner un fond.

Pour cela, il va simplement falloir dessiner un rectangle en passant comme coordonnées celles de notre fenêtre, en tenant compte de la barre de titre et des autres éléments la composant.

Et cela que je dois vous faire du mal : le VDI se fiche pas mal de votre fenêtre, si vous lui demandez il écrira n’importe où à l’écran !

Cela suppose donc qu’à terme nous aurons à gérer nous même le « clipping » (autrement dit l’affichage dans une zone d’écran délimitée par les bords de notre fenêtre) ainsi que le rafraîchissement de la fenêtre.

Mais qu’à cela ne tienne, dessinons donc un rectangle blanc, pour cela nous allons utiliser la primitive VDI vr_recfl :



vr_recfl()

VOID vr_recfl( handle, pxy )

WORD handle;

WORD *pxy;

vr_recfl() outputs a filled rectangle.

OPCODE 114

AVAILABILITY Supported by all drivers.

PARAMETERS handle specifies a valid workstation handle. pxy points to an array of 4 WORDs

which give a VDI format rectangle of the object to draw.

BINDING contrl[0] = 114;

contrl[1] = 2;

contrl[3] = 0;

contrl[6] = handle;

ptsin[0] = pxy[0];

ptsin[1] = pxy[1];

ptsin[2] = pxy[2];

ptsin[3] = pxy[3];

vdi();

COMMENTS vr_recfl(), as opposed to v_bar(), never draws an outline regardless of the

settings of vsf_perimeter().

SEE ALSO v_bar()


Comme vous le voyez, dans le paragraphe « BINDING », on indique en fait les valeurs à initialiser lors de l’appel de la fonction (syntaxe C).

L’adresse « contrl » pointe sur le registre de contrôle de VDI, pour chaque appel il faut spécifier dans ce registre la façon dont nous allons utiliser la fonction.

Ainsi, contrl[x] permet d’écrire une donnée à l’adresse contrl+x, avec ci-dessous l’utilisation des différentes zones du registre :

contrl[x] Contents

0         Opcode de la fonction VDI

1         Nombre de vertices en entrée passés dans ptsin

2         Nombre de vertices en sortie passés dans ptsout

3         Nombre de paramètre en entrée passés dans intin

4         Nombre de valeurs en sortie récupérées dans intout

5         Sub-opcode de la fonction

6         Descripteur de la « Workstation »

7–11     Usage réservé


Un petite précision concernant ce tableau, notamment pour ceux n’ayant pas fait de programmation Open GL (entre autres), un « vertex » (pluriel « vertices ») désigne un point à l’écran désigné par ses coordonnées.


Si l’on reprend le « Binding » de la fonction vr_recfl mentionnée ci-dessus :


contrl[0] = 114;; Opcode 11

contrl[1] = 2;; 2 vertices en entrée (coin supérieur gauche et coin inférieur droit)

contrl[3] = 0;; pas de paramètres dans intin

contrl[6] = handle;; descripteur de la « workstation »

ptsin[0] = pxy[0];; coordonnée en x du coin supérieur gauche

ptsin[1] = pxy[1];; coordonnée en y du coin supérieur gauche

ptsin[2] = pxy[2];; coordonnée en x du coin inférieur droit

ptsin[3] = pxy[3];; coordonnée en y du coin inférieur droit



Une chose importante : Les registres « contrl », « ptsin », « ptsout », « intin », et « intout », utilisent des valeurs de 16 bits.

Pour écrire 2 octets (16 bits) à une adresse x en GFA, nous possédons la fonction INT :

INT{x} = <valeur sur 16 bits>


L’adresse du registre de contrôle est également disponible par le mot clé « CONTRL ».

Enfin la fonction « VDISYS » permet d’appeler la fonction VDI.


On peut donc écrire la fonction GFA vr_recfl  suivante :


PROCEDURE vr_recfl(x%,y%,w%,h%)

  INT{ADD(CONTRL,2)}=2

  INT{ADD(CONTRL,6)}=0

  INT{ADD(CONTRL,12)}=vhandle%

  '

  INT{ADD(PTSIN,0)}=x%

  INT{ADD(PTSIN,2)}=y%

  INT{ADD(PTSIN,4)}=x%+w%-1

  INT{ADD(PTSIN,6)}=y%+h%-1

  VDISYS 114

RETURN




Pour illustrer l’appel de cette fonction, je vous propose de rassembler tout ce que nous avons appris depuis le début avec ce simple programme :


' Tutoriel AES/VDI en GFA Basic

' Jérome Savidan 2010

'

' initialisation de l'AES

' quelle est la taille du bureau ?

ret%=WIND_GET(0,4,bureaux%,bureauy%,bureauw%,bureauh%)

@test_erreur

' j'veux dire : la taille utile, sans le menu et les machins ?

ret%=WIND_CALC(1,&H2F,bureaux%,bureauy%,bureauw%,bureauh%,workx%,worky%,workw%,workh%)

@test_erreur

' création d'une fenetre de taille max

handle%=WIND_CREATE(&H2F,workx%,worky%,workw%,workh%)

titre$="Fenetre toute simple"

' initialisation du titre

ret%=WIND_SET(handle%,2,CARD(SWAP(VARPTR(titre$))),CARD(VARPTR(titre$)),0,0)

@test_erreur

' ouverture de la fenetre presque au max de sa capacite

ret%=WIND_OPEN(handle%,workx%+0,worky%+0,workw%-20,workh%-20)

@test_erreur

' recup de sa taille actuelle

ret%=WIND_GET(handle%,4,wworkx%,wworky%,wworkw%,wworkh%)

@test_erreur

'

' initialisation VDI

ghandle%=GRAF_HANDLE(char_w%,char_h%,box_w%,box_h%)

vhandle%=V_OPNVWK(1,1,1,1,1,1,1,1,1,1,2)

' avant de dessiner il faut cacher la souris

ret%=GRAF_MOUSE(256,VARPTR(mouse%))

@vsf_color(0)

@vr_recfl(wworkx%,wworky%,wworkw%,wworkh%)

' on rÇ-affiche la souris

ret%=GRAF_MOUSE(257,VARPTR(mouse%))

' boucle principale de gestion d'evenements AES

DO

  a%=EVNT_MESAG(0)

LOOP UNTIL MENU(1)=22

a%=WIND_CLOSE(handle%)

a%=WIND_DELETE(handle%)

'

' procedures et fonctions

'

PROCEDURE vsf_color(color%)

  INT{ADD(CONTRL,2)}=0

  INT{ADD(CONTRL,6)}=1

  INT{ADD(CONTRL,12)}=vhandle%

  INT{ADD(INTIN,0)}=color%

  VDISYS 25

RETURN

'

PROCEDURE vr_recfl(x%,y%,w%,h%)

  INT{ADD(CONTRL,2)}=2

  INT{ADD(CONTRL,6)}=0

  INT{ADD(CONTRL,12)}=vhandle%

  '

  INT{ADD(PTSIN,0)}=x%

  INT{ADD(PTSIN,2)}=y%

  INT{ADD(PTSIN,4)}=x%+w%-1

  INT{ADD(PTSIN,6)}=y%+h%-1

  VDISYS 114

RETURN

'

PROCEDURE test_erreur

  IF ret%=0

    ALERT 4,"Erreur d'initialisation graphique",0,"Ok",but%

  ENDIF

RETURN




Si vous vous dites qu’au final nous n’avons pas utilisé les valeurs retournées par la fonction GRAF_HANDLE, vous avez parfaitement raison !

Mais il faut bien en garder pour un prochain tuto, non ? ;)


Alors amusez vous bien et à la prochaine …