Les modes graphiques de l'Amiga
Je vous propose de découvrir, ou de redécouvrir les différents modes graphiques de l'Amiga, des premières puces OCS à l'AGA et au delà, le RTG Picasso96. On ne va pas entrer dans les détails des registres, mais regarder comment on peut utiliser les routines de l'intuition.library et graphics.library.

OCS (Old Chip Set) et ECS (Enhanced Chip Set)
L'OCS est le nom donné après coup aux puces originales de l'Amiga 1000, 500 et 2000 avant 1990. L'ECS est apparu en 1990 avec l'Amiga 3000 et ces puces ont pu être adaptées au 500 et 2000 moyennant quelques adaptations: super Agnus (ligne 19 (existante) et 20 (fil à souder) pour l'adressage de 2Mo de chip) super Denise pour pouvoir adapter les signaux video, circuit Amber pour désentrelacer les signaux video.

La puce utilisée pour la génération des pixels, Denise (Display Encoder Chip...) utilise l'horloge de base 7M (7,16 MHz en PAL et 7,14MHz en NTSC). Par cycle, elle émet un pixel LoRes ou deux pixels Hires, 1/7,16MHz = 139,66ns soit environ 140ns et 1/7,14MHz = 140ns pile poil. (ns = nanosecondes) Le temps mis pour afficher un pixel s'exprime en nanosecondes.
Dans les circuits OCS il y a deux résolutions horizontales pour les pixels:
140 ns pour la base résolution (LoRes).
70 ns pour la haute résolution (HiRes).

Dans cette puce Denise, il y a 32 registres couleurs.
$dff180 COLOR00
$dff182 COLOR01
...
$dff1be COLOR31

En LoRes, on peut gérer 6 plans (bitplanes).
De 1 à 5 plans, on affichera 2 à 32 couleurs à choisir parmi 4096 couleurs.
Mais alors à quoi peut servir le 6ième plan vu que la puce n'a que 32 registres ?
Le mode EHB (Extra Half Bright) gère le 6ième plan en utilisant les intensités divisées par deux des 32 registres couleurs. Le mode HAM (Hold And Modify) permet d'afficher 4096 couleurs avec des contraintes de proximité.
00xxxx => registre COLOR00 à COLOR15.
01BBBB => les composantes rouges et vertes sont conservées, la composante bleue est sur 4 bits 0x0 à 0xf.
10RRRR => les composantes bleues et vertes sont conservées, la composante rouge est sur 4 bits 0x0 à 0xf.
11GGGG => les composantes bleues et rouges sont conservées, la composante verte est sur 4 bits 0x0 à 0xf.

en HiRes, on ne peut gérer que 4 plans (16 couleurs)
Dans les circuits ECS il y a une résolution supplémentaire: 35 ns pour le Super HiRes. Il y existe aussi plein d'autres résolutions, les fréquences horizontales et verticales sont entièrement programmables, au risque de faire exploser son écran multisynchrone...
en Super HiRes, on n'a accès qu'à 2 plans (4 couleurs à choisir parmi 64 couleurs...)

Les modes "Dynamic" (ou "Sliced"
Le processeur Copper (inclus dans la puce Agnus) dispose de 3 instructions MOVE, WAIT et SKIP. Un programme pour le Copper s'appelle une copperlist. Dans la plupart des cas, le système utilise ces copperlist en chargeant la palette dans les registres COLOR00 à COLOR31 une bonne fois pour toute en haut de l'écran visible. Mais on peut ruser en coupant le DMA audio, disque et sprite, on a assez de temps pour changer la valeur des registres à chaque ligne:
une ribambelle de MOVE COLORcc,$0rvb suivi d'un WAIT 0,n+1
d'où les modes "Sliced" ou "Dynamic".
Le Sliced HiRes (Dynamic HiRes), 16 couleurs par ligne.
Le Sliced EHB (Dynamic LoRes EHB), 64 couleurs par ligne.
Le Sliced HAM (Dynamic LoRes HAM), 16 couleurs + HAM par ligne.

Pour illustrer, voici des images MacroPaint en Dynamic Hires (Sliced Hires)
Ces images accompagnent Shazam, un utilitaire capable d’afficher ce genre d’images. (il y a même le code source en C pour les curieux: c’est une grosse copperlist)

astronaut.mp 237 couleurs

fb111.mp 104 couleurs

Digi-View est un module électronique permettant de digitaliser une trame video avec un logiciel qui offre la possibilité d'enregistrer 7bits par composante dans des fichiers IFF 21 bits. Un Amiga sans carte graphique ne peut pas afficher de telles images. Digi-View permet de convertir ces données en HAM, en EHB, et en Dynamic HiRes, directement ou en utilisant diverses techniques de dispersion de pixels.

Test de capture de la boite du logiciel, avec une caméra noir et blanc et les filtre rouge/vert/bleu de Digi-View.

fashion, une image en HAM, obtenue à partir d'un poster par le même procédé que la boite.

Un peu plus ardu, la conversion d'une image 24 bits en image 21 bits...

image 24 bits de référence.

image convertie en Dynamic Ham, 634 couleurs alors qu'en réalité il y en a plus de 57536.

image convertie en Dynamic HiRes, 185 couleurs alors qu'en réalité il y en a plus de 57536.

AGA
L'AGA (Advanced Graphics Architecture) est arrivé avec l'Amiga 4000 (septembre 1992) puis 1200 (décembre 1992). Il conserve les modes graphiques ECS et ajoute d'autres modes.
LoRes, HiRes et SuperHiRes de 1 à 8 plans, soit de 2 à 256 couleurs. Les registres couleurs sont toujours sur 16 bits
$dff180 COLOR00
$dff182 COLOR01
...
$dff1be COLOR31
La palette de 256 couleurs est décomposée en 8 palettes de 32 couleurs. Le registre BPLCON3 $dff106 permet de sélectionner la composante basse (bit 9 à 0) ou haute (bit 9 à 1). Pour écrire RrGgBb dans COLOR00, il faudra commencer par mettre le bit 9 de BPLCON3 à 0, écrire rgb dans COLOR00 puis mettre le bit 9 de BPLCON3 à 1 pour écrire RGB dans COLOR00.
Les copperlists deviennent énormes.

L'EHB est conservé.
Le HAM6 correspond au HAM OCS, avec 6 plans.
Le HAM8 utilise 8 plans.
00xxxxxx => couleur 0 à 63 dans la palette logique.
01BBBBBB => les composantes rouges et vertes sont conservées, la composante bleue est sur 6 bits 0x0 à 0x3f.
10RRRRRR => les composantes bleues et vertes sont conservées, la composante rouge est sur 6 bits 0x0 à 0x3f.
11GGGGGG => les composantes bleues et rouges sont conservées, la composante verte est sur 6 bits 0x0 à 0x3f.
262144 couleurs en théorie, sauf que l'on est en HiRes (et même SuperHiRes).

Picasso96
Vu la complexité de l'AGA, de nombreuses sociétés ont développé des cartes graphiques, reprennant des caractéristiques communes avec les PC et les Macintosh. Le RTG ReTargetable Graphics, permet d'ouvrir la bibliothèque graphique de l'Amiga à d'autres technologies. Fini les registres, les copperlist et les limitations, maintenant un pixel a 3 composantes sur 8bits, qu'importe le sens où comment il se situe en mémoire...

Mise en œuvre
Nous allons nous servir des bibliothèques intuition et graphics.
Ouvrir un écran avec le bon type avec OpenScreen() ou OpenScreenTags() => s
Ouvrir une fenêtre... mais c'est optionel... car on peut écrire directement dans l'écran... OpenWindow() ou OpenWindowTags() => w
Pour fermer une fenêtre CloseWindow(w), et pour fermer un écran CloseScreen(s)

Accès aux couleurs, par le ViewPort du Screen:
Pour changer les couleurs à partir de la fenêtre: vp = &w->WScreen->ViewPort ; à partir d'un écran: vp = &s->ViewPort ;

SetRGB4(vp, entry, R, G, B); /* Toutes les versions, 12 bits */
SetRGB32(vp, entry, R, G, B); /* V39 et plus, 32 bits par composantes (on voit large...) */
LoadRGB4 et LoadRGB32 chargent des palettes entières en un seul appel, bien plus rapidement que leurs équivalents en SetRGB4 et SetRGB32.

Accès aux plans, par le RastPort. Pour récupérer le RastPort
de la fenêtre : rp = w->RPort ;
de l'écran : rp = &s->RastPort ;

Les pinceaux A (primaire) et B (secondaire) permettent de peindre dans le RastPort
SetAPen(w->RPort, fg) ;
SetBPen(w->RPort, bg) ;

Les modes de rendu JAM1 0 (1 couleur pinceau primaire A), JAM2 1 (2 couleurs, pinceau A et pinceau B), COMPLEMENT 2 (ou exclusif avec les couleurs déjà présentes), INVERSVID 4 (video inverse avec les couleurs déjà présentes, sont sélectionnés par
SetDrMd(w->RPort, mode) ;
A partir de V39 (OS3.0) il existe une fonction qui effectue les 3 opérations en un seul appel
SetABPenDrMd(w->RPort, fg, bg, m) ;

Les primitives graphiques
Move déplace le pinceau, sans tracé, Draw relie le dernier point (w->RPort->cp_x, w->RPort->cp_y) au point précisé.
w->RPort->LinePtrn contient la texture de la ligne, par défaut 0xffff, prendre 0xaaaa pour faire un pointillé alterné entre pinceau A et pinceau B.
RectFill remplit le rectangle dont les coordonnées sont précisées.
Text Affiche le texte en précisant la longueur.
DrawEllipse dessine une ellipse.
Move(rp, x, y) ;
Draw(rp, x, y) ;

RectFill(rp, le, te, re, be) ;
Text(rp, text, len) ;
DrawEllipse(rp, x, y, rx, ry) ; /* V33 et plus */
Les primitives graphiques nécessitant d'allouer un RastPort temporaire (remplissage)
AreaEllipse(rp, x, y, rx, ry) ;
AreaMove(rp, x, y) ;
AreaDraw(rp, x, y) ;
AreaEnd(rp) ;
Flood(rp, mode, x, y) ;

Accès aux pixels
WritePixel(w->RPort, x, y) ;
WritePixelLine8(rp, xstart, ystart, width, pens, tempRP) ; /* V36 et plus */

Le WritePixelLine8 s'écrit naïvement comme suit sans devoir allouer un RastPort temporaire.
Il est évident que WritePixel est très lent, vu qu'il faut accéder à chaque plan.
LONG V33_WritePixelLine8
( struct RastPort *rp, ULONG xstart, ULONG ystart, ULONG width,
  UBYTE *array, struct RastPort *tempRP
)
{ 
  register ULONG i;
  
  for ( i=width; i; i-- )
  { 
    SetAPen(rp, *array++);
    WritePixel(rp, xstart++, ystart);
  }
  
  return (LONG)width;
} /* V33_WritePixelLine8 */
A quoi WritePixelLine8 peut-il bien servir ?
On peut s'en servir pour convertir des pixels RVB en HAM... ou en HAM8 ou pour recalculer une image avec les couleurs disponibles

Comment peut-on écrire des couleurs en 24 bits dans un écran Picasso96 ? Tout simplement en sacrifiant une entrée arbitrairement dans le viewport de l'écran, ou en verrouillant une couleur (avec ObtainPen/ReleasePen).
SetRGB32(&w->WScreen->ViewPort,
         249,
         0xffffffff,
         0xa2a2a2a2,
         0x87878787) ;

SetAPen(w->RPort, 249) ;

Permettra de peindre les droites/boites/textes à l'aide des primitives graphiques avec la couleur (255,162,135). Ce qui est valable pour le pinceau A l'est aussi pour le pinceau B, mais il faudra prendre une autre entrée, la 248 par exemple.

Conclusion
De 2 à 16,7 millions de couleurs, on peut beaucoup s'amuser avec un Amiga.