Suivez-nous sur X

|
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
ALL
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
0,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z
|
|
A propos d'Obligement
|
|
David Brunet
|
|
|
|
Programmation : C - Ouverture d'un écran avec graphics.library
(Article écrit par Pascal Amiable et extrait d'Amiga News Tech - mars 1991)
|
|
En tant qu'ordinateur multitâche, l'Amiga possède une gestion d'écran assez particulière, mais ô combien
efficace. Qui n'a jamais été amusé ou surpris, la première fois, de faire défiler l'écran du Workbench du
bout de sa souris.
Cette série d'articles a pour but de vous faire mieux connaître deux des bibliothèques de l'Amiga, à savoir
Graphics et Intuition.
La graphics.library contient toutes les fonctions de gestion des objets graphiques de base (écrans, sprites, BOB)
ainsi que les primitives de dessin (points, droites, cercles, remplissage...). L'intuition.library, quant
à elle, est une plate-forme permettant le développement d'interfaces conviviales à base de menus,
gadgets variés et autres fenêtres.
Cette étude sera formée d'une partie théorique et d'une série d'exemples, pour la plupart en langage C.
Une connaissance du C (ou de tout autre langage structuré) sera donc très utile, ainsi parfois que
des rudiments d'assembleur. Enfin, un certain nombre de termes anglo-saxons difficilement traduisibles
en français seront utilisés tout au long de cet article. En cas d'incompréhension, reportez-vous au
lexique de fin.
Les concepts de base
Lorsque l'on crée une zone de visualisation, il faut prendre en compte deux éléments essentiels,
qui sont le "playfield" (champ de jeu) et les "sprites". Le champ de jeu représente la partie statique de
la zone de visualisation, alors que les sprites peuvent se déplacer et interférer entre eux ou avec
le champ de jeu. Nous étudierons les sprites en détails dans un prochain article.
Pour projeter son affichage, l'Amiga utilise une technique de balayage vidéo connue sous le nom de
"Raster Display". Cette image est formée d'un certain nombre de lignes horizontales, créées par le
faisceau électronique du moniteur. En mode normal, c'est-à-dire non entrelacé, il est possible
d'afficher 256 lignes horizontales (200 en mode NTSC). En mode entrelacé, on peut afficher 512 lignes
(400 en NTSC). Comment est-ce possible ? C'est assez simple : pour afficher 512 lignes, l'Amiga
commence par afficher en 1/60e de seconde une première série de 256 lignes représentant les lignes
paires de l'image à afficher, puis il affiche les 256 lignes impaires après avoir décalé la position
verticale de départ d'une demie épaisseur de ligne. Il existe toutefois un inconvénient à ce mode :
pour tracer une image en mode entrelacé, l'Amiga met deux fois plus de temps, soit 1/30e de seconde.
Or ce délai est trop long pour obtenir un affichage de qualité visuelle standard, ce qui explique
le scintillement, si disgracieux, du mode entrelacé.
Chaque ligne visualisée est composée d'un certain nombre de points. Deux modes de précision horizontale
sont également proposés. En basse résolution, chaque ligne compte 320 points, alors qu'en haute résolution,
il est possible d'avoir 640 points par ligne. L'affichage en haute résolution ne permet plus que
d'obtenir 16 couleurs à l'écran alors que nous en avions 32 en basse résolution. A noter la présence
des modes EHB et HAM qui permettent respectivement d'obtenir 64 et 4096 couleurs simultanément à
l'écran avec toutefois quelques contraintes, mais nous y reviendrons plus tard.
Pour dessiner à l'écran, il est nécessaire d'écrire dans une portion de mémoire, portion qui représente
la zone de visualisation qui va être affichée sur le moniteur. Cette zone de mémoire est organisée sous
forme de plans de bits. Un plan de bits représente une zone virtuelle de traçage, permettant d'afficher une
seule couleur (mise à zéro ou à un de chaque bit de la zone). L'affichage avec plusieurs couleurs est
possible en superposant plusieurs plans de bits. On obtient alors 2^N couleurs, où N représente le nombre
de plans de bits. Cette gestion des couleurs par superposition de plans de bits est réalisée grâce à un circuit
spécialisé portant le doux nom de Denise. Un maximum de 6 plans de bits superposés est autorisé, soit dans
l'absolu 2^6 couleurs (64). Cet assemblage de plans de bits s'appelle une bitmap (Cf Fig 1).
Structures et fonctions d'affichage
L'Amiga produit une zone d'affichage à partir d'une série d'instructions organisée sous la forme
d'une structure C et baptisée "View". Cette zone d'affichage peut être décomposée en plusieurs parties
distinctes, séparées par au minimum une ligne horizontale (une ligne de "raster") : ce sont les
"ViewPorts", qui forment donc des zones rectangulaires (Cf. Fig 2). Le ViewPort correspond au
CustomScreen d'Intuition, que nous étudierons plus tard.
Pour définir un ViewPort, il faut dans un premier temps initialiser quelques paramètres : sa taille
(hauteur et largeur), sa profondeur (le nombre de plans de bits utilisés) qui indique le nombre de couleurs,
son mode de visualisation (basse ou haute résolution, entrelacement...), l'adresse de la zone de mémoire
utilisée pour l'affichage, et enfin sa position par rapport au coin haut et gauche de l'écran.
La hauteur est associée au champ DHeight de la structure ViewPort. Elle représente le nombre de lignes
verticales du ViewPort.
La largeur, elle, est contenue dans le champ DWidth. Elle représente le nombre de pixels (points) par lignes
du ViewPort. Il est possible de définir pour chaque ViewPort des largeurs différentes.
Le nombre de plans de bits utilisés pour la mémoire d'affichage, conditionne le nombre de couleurs affichables
dans le ViewPort sous la forme déjà citée nombre_couleurs = 2^nombre_plans_de_bits. A noter le cas
particulier du mode HAM qui autorise avec une profondeur de 6 plans de bits, l'affichage de 4096 couleurs,
avec toutefois des contraintes de proximité. La profondeur est codée dans le champ utilisé Depth.
A chaque ViewPort est associée une palette de couleurs. Cette palette est spécifiée dans une structure
baptisée ColorMap et rattachée au ViewPort par son adresse. Nous verrons cela un peu plus loin.
Il existe neuf modes possibles de visualisation, le mode par défaut étant la basse résolution. Pour
choisir un autre mode, il faut remplir le champ Modes avec les valeurs adéquates, suivant la liste ci-dessous :
- Basse résolution (Null) : dans ce mode, une ligne normale overscan (alias suraffichage).
- Haute résolution (Hires) : la résolution horizontale passe ici à 640 pixels, ou 704 en suraffichage.
- Entrelacé (Lace) : l'affichage s'effectue en mode entrelacé, soit 512 lignes par écran au lieu de 256.
Attention ! Lorsque vous spécifiez le mode Lace dans le ViewPort, vous devez impérativement le spécifier
également dans le champ View.Modes.
- Hold & Modify (HAM) : mode spécial permettant l'affichage de 4096 couleurs simultanées à l'écran.
- Double playfield (DualPF) : le ViewPort est traité comme possédant deux zones d'affichage superposées
et indépendantes.
- Avec Sprites (Sprites) : cette valeur est obligatoire pour indiquer à l'Amiga que l'on va utiliser
des sprites matériels.
- Playfield 2 avant 1 (PFBA) : cette valeur est liée au mode DualPF et permet de positionner le
champ de jeu 2 devant le premier.
- ViewPort caché (VP Hide) : indique que le ViewPort est caché et par là même, que son contenu
n'est pas visualisé à l'écran.
- Mode 64 couleurs (Extra_HalfBrite) : dans ce mode, 64 couleurs sont affichées, les 32 dernières
étant dérivées des 32 premières.
Pour obtenir, par exemple, un écran en haute résolution entrelacée, on mettra Hires+Lace dans le champ Modes.
Comme le ViewPort est de taille égale ou inférieure à la zone de visualisation, il est nécessaire d'indiquer
sa position à l'écran. Cette position est définie par les distances DxOffset et DyOffset entre le coin
supérieur gauche de l'écran et le coin supérieur gauche du ViewPort (Cf. Fig 3). DxOffset doit être
compris entre -16 et +352 (-32 et +704 en Hires), DyOffset entre -16 et +256 (-32 et +512 en mode Lace)
sachant que (0,0) positionne le ViewPort strictement dans le coin haut et gauche de l'écran.
DxOffset et DyOffset sont deux champs de la structure ViewPort.
La zone de mémoire réservée pour l'affichage peut être plus grande que l'écran de visualisation, et ce,
jusqu'à la taille limite de 1024x1024 points. C'est justement pour cela qu'il faut spécifier la position
du ViewPort dans cette zone d'affichage, suivant le même principe que ci-dessus et à l'aide des champs
RxOffset et RyOffset (Cf. Fig 4). Ces deux valeurs sont stockées dans les champs de la structure RasInfo
portant le même nom. Cette structure contient également un pointeur sur la Bitmap d'affichage (structure
BitMap).
Nous en savons maintenant assez pour créer notre propre écran. L'exemple ci-joint va nous permettre de
passer en douceur de la théorie à la pratique, en créant un simple ViewPort d'une taille de 320x200
avec une bitmap de même taille. Il démontre également la manière de placer ce ViewPort par rapport
à la structure View.
/*
Programmation : C - Ouverture d'un écran avec graphics.library
Article écrit par Pascal Amiable et extrait d'Amiga News Tech - mars 1991
http://obligement.free.fr/articles/c_ecrans_graphics.php
Adapté à vbcc par Tygre, 2020/09/06
*/
/* ----------------------------------------------------------------- */
/* Ouverture d'un écran sous graphics... */
/* Auteur Pascal AMIABLE (c) 1991 */
/* ----------------------------------------------------------------- */
#include <exec/exec.h>
#include <exec/types.h>
#include <graphics/gfx.h>
#include <graphics/rastport.h>
#include <graphics/copper.h>
#include <graphics/view.h>
#include <graphics/gels.h>
#include <graphics/regions.h>
#include <graphics/clip.h>
#include <graphics/text.h>
#include <graphics/gfxbase.h>
#include <hardware/dmabits.h>
#include <hardware/custom.h>
#include <hardware/blit.h>
#define PLAN 2 /* Nombre de Bitplane associé à l'écran */
#define COLOR 4 /* Nombre de couleurs disponibles */
#define HORIZONT 640 /* Largeur de l'écran en pixels */
#define VERT 512 /* Hauteur de l'écran en pixels */
#define MODE_V LACE /* Mode de visualisation du View (entrelacé) */
#define MODE_VP HIRES+LACE /* Mode de visualisation ViewPort */
/* Haute résolution et entrelacé */
int i;
struct View view; /* View associé à l'écran */
struct ViewPort viewport; /* ViewPort associé à View */
struct RasInfo rasinfo; /* Structure RasInfo liée au ViewPort */
struct BitMap bitmap; /* BitMap lié au ViewPort */
struct RastPort rastport; /* Le RastPort avec lequel on dessine */
struct GfxBase *GfxBase; /* Pointeur sur la graphics.library */
struct View *ecran_sauvegarde; /* Pointeur sur une structure View afin de sauvegarder l'écran courant */
UWORD colortable[COLOR] = { 0x000, 0xf00, 0x0f0, 0x00f };
/* Table des couleurs, couleur 0 = NOIR, couleur 1 = ROUGE, couleur 2 = VERT, couleur 3 = BLEU */
char *bouton_gauche = (char *)0xbfe001;
/* Port A du CIA dont le bit correspond au bouton gauche de la souris */
void init(), ouvreecran(), libere();
/* ----------------------------------------------------------------- */
/* Programme principal */
/* ----------------------------------------------------------------- */
int main()
{
init();
ouvreecran();
Move(&rastport, 100, 100);
Draw(&rastport, 200, 200);
while(!((*bouton_gauche & 0x40) - 64)); /* Tant que le bouton gauche de la souris n'est pas enfoncé */
LoadView(ecran_sauvegarde); /* Restauration du View sauvegardé */
libere();
}
/* ----------------------------------------------------------------- */
/* init() Ouvre la bibliothèque et sauvegarde l'ancien écran */
/* ----------------------------------------------------------------- */
void init()
{
if ((GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0)) == NULL)
exit(1); /* La bibliothèque graphics ne veut pas s'ouvrir */
ecran_sauvegarde = GfxBase->ActiView; /* Sauvegarde du View actif */
}
/* ----------------------------------------------------------------- */
/* ouvreecran() Initialise et ouvre un écran */
/* ----------------------------------------------------------------- */
void ouvreecran()
{
InitView(&view); /* Initialisation de la structure View */
InitVPort(&viewport); /* Initialisation de la structure ViewPort */
view.ViewPort = &viewport; /* On lie le ViewPort au View */
view.Modes = MODE_V; /* On indique le mode visualisation du View */
InitBitMap(&bitmap, PLAN, HORIZONT, VERT); /* On initialise la bitmap */
rasinfo.BitMap = &bitmap; /* Liaison de la BitMap avec le RasInfo */
rasinfo.RxOffset = 0;
rasinfo.RyOffset = 0;
rasinfo.Next = NULL; /* Pas d'autres structures */
viewport.DxOffset = 0; /* On remplit la structure ViewPort */
viewport.DyOffset = 0; /* cf. l'article ci-dessus */
viewport.DWidth = HORIZONT;
viewport.DHeight = VERT;
viewport.RasInfo = &rasinfo;
viewport.Modes = MODE_VP;
viewport.Next = NULL; /* Pas d'autre ViewPort */
viewport.ColorMap = (struct ColorMap *)GetColorMap(COLOR);
/* Initialisation de la ColorMap du ViewPort */
LoadRGB4(&viewport, colortable, COLOR);
/* Chargement des couleurs dans la ColorMap */
for(i = 0; i < PLAN; i++) /* Allocation des bitplanes */
{
if((bitmap.Planes[i] = (PLANEPTR)AllocRaster(HORIZONT, VERT)) == NULL)
exit(2);
BltClear((UBYTE *)bitmap.Planes[i], RASSIZE(HORIZONT, VERT), 0);
/* Éffacement de bitplanes au Blitter */
}
InitRastPort(&rastport); /* Initialisation du RastPort */
rastport.BitMap = &bitmap; /* On lie le RastPort à la bitmap dans laquelle on dessine */
MakeVPort(&view, &viewport); /* On crée la zone de visualisation */
MrgCop(&view); /* et la CopperList associée */
LoadView(&view); /* et on affiche l'écran sur le moniteur */
}
/* ----------------------------------------------------------------- */
/* libere() Libère la mémoire utilisée */
/* ----------------------------------------------------------------- */
void libere()
{
for(i = 0; i < PLAN; i++) /* On libère la mémoire des bitplanes */
FreeRaster(bitmap.Planes[i], HORIZONT, VERT);
FreeColorMap(viewport.ColorMap); /* On libère la mémoire de la ColorMap */
FreeVPortCopLists(&viewport); /* Libération de la CopperList */
CloseLibrary((struct Library *)GfxBase); /* Fermeture de la bibliothèque graphics */
}
|
Mise à jour de septembre 2020 : une archive contenant le listing adapté à vbcc, et avec les
exécutables compilés par SAS C et vbcc, a été réalisée par Yann-Gaël Guéhéneuc et est disponible sur
obligement.free.fr/files/antscreenwithgraphicslibrary.lha.
Le mois prochain, nous verrons la génération de champs de jeu avec Intuition, ce qui nous permettra
d'étudier les différences entre les deux méthodes.
Petit lexique
- Bitmap : assemblage de plans de bits, permettant de créer un écran pour le traçage en multi-couleurs.
- bitsplane : littéralement, plan de bits. Il s'agit d'une zone de mémoire organisée sous forme rectangulaire,
permettant de représenter un écran de traçage virtuel.
- BOB : alors que le sprite est indépendant du champ de jeu, le BOB en fait partie intégrante.
Ce qui signifie que l'on doit gérer son interaction avec le champ de jeu. C'est le principe des brosses
dans un logiciel de dessin.
- Copper : processeur spécialisé de l'Amiga. Synchronisé sur le spot vidéo, il a été conçu
pour gérer la partie affichage de l'Amiga grâce à son jeu d'instructions propres.
- Library : en français bibliothèque. Ce terme est utilisé pour désigner les bibliothèques de fonctions du système
d'exploitation de l'Amiga, qu'elles soient en ROM ou sur disquette (exemple : graphics.library).
- Sprite : lutin en français. Il représente un objet graphique indépendant du champ de jeu qui peut se
déplacer en superposition de celui-ci sans en modifier le contenu (idéal pour représenter, par exemple, un petit
vaisseau se déplaçant sur un fond).
|