/* * Programme test pour illustrer l'affichage de ligne VGA dans le mode 360x480 * 256 couleurs. * * Compilé avec Borland C++ 4.02. * Testé par Jim Mischel 11/21/94 * * Doit être lié avec le Listing 32.1 avec une ligne de commande comme: * * bcc l10-2.c l10-1.asm * * Par Michael Abrash. 6/2/89. * */ #include /* contient geninterrupt */ #define TEXT_MODE 0x03 #define BIOS_VIDEO_INT 0x10 #define X_MAX 360 /* largeur de l'écran de travail */ #define Y_MAX 480 /* hauteur de l'écran de travail */ extern void Draw360x480Dot(); extern void Set360x480Mode(); /* * Affiche une ligne en octant 0 ou 3 ( |DeltaX| >= DeltaY ). * |DeltaX|+1 points sont affichés. */ void Octant0(X0, Y0, DeltaX, DeltaY, XDirection, Color) unsigned int X0, Y0; /* coordonnée du début de la ligne */ unsigned int DeltaX, DeltaY; /* longueur de la ligne */ int XDirection; /* 1 si la ligne est affichée de gauche à droite, -1 si la ligne est affichée de droite à gauche */ int Color; /* couleur dans laquelle afficher la ligne */ { int DeltaYx2; int DeltaYx2MinusDeltaXx2; int ErrorTerm; /* Configure le terme d'erreur initial et les valeurs utilisées à l'intérieur de la boucle d'affichage */ DeltaYx2 = DeltaY * 2; DeltaYx2MinusDeltaXx2 = DeltaYx2 - (int) ( DeltaX * 2 ); ErrorTerm = DeltaYx2 - (int) DeltaX; /* Affiche la ligne */ Draw360x480Dot(X0, Y0, Color); /* affiche le premier pixel */ while ( DeltaX-- ) { /* Vérifie s'il est temps d'avancer la coordonnée Y */ if ( ErrorTerm >= 0 ) { /* Avance la coordonnée Y & ajuste le terme d'erreur en arrière */ Y0++; ErrorTerm += DeltaYx2MinusDeltaXx2; } else { /* Ajoute au terme d'erreur */ ErrorTerm += DeltaYx2; } X0 += XDirection; /* avance la coordonnée X */ Draw360x480Dot(X0, Y0, Color); /* affiche un pixel */ } } /* * Affiche en octant 1 ou 2 ( |DeltaX| < DeltaY ). * |DeltaY|+1 points sont affichés. */ void Octant1(X0, Y0, DeltaX, DeltaY, XDirection, Color) unsigned int X0, Y0; /* coordonnées du début de la ligne */ unsigned int DeltaX, DeltaY; /* longueur de la ligne */ int XDirection; /* 1 si la ligne est affichée de gauche à droite, -1 si la ligne est affichée de droite à gauche */ int Color; /* couleur dans laquelle afficher la ligne */ { int DeltaXx2; int DeltaXx2MinusDeltaYx2; int ErrorTerm; /* Configure le terme d'erreur et les valeurs utilisées à l'intérieur de la boucle d'affichage */ DeltaXx2 = DeltaX * 2; DeltaXx2MinusDeltaYx2 = DeltaXx2 - (int) ( DeltaY * 2 ); ErrorTerm = DeltaXx2 - (int) DeltaY; Draw360x480Dot(X0, Y0, Color); /* affiche le premier pixel */ while ( DeltaY-- ) { /* Vérifie s'il est temps d'avancer la coordonnée X */ if ( ErrorTerm >= 0 ) { /* Avance la coordonnée X & ajuste le terme d'erreur en arrière */ X0 += XDirection; ErrorTerm += DeltaXx2MinusDeltaYx2; } else { /* Ajoute au terme d'erreur */ ErrorTerm += DeltaXx2; } Y0++; /* avance la coordonnée Y */ Draw360x480Dot(X0, Y0,Color); /* affiche un pixel */ } } /* * Affiche une ligne sur EGA ou VGA. */ void EVGALine(X0, Y0, X1, Y1, Color) int X0, Y0; /* coordonnée de l'une des extrémités de la ligne */ int X1, Y1; /* coordonnée de l'autre extrémité de la ligne */ unsigned char Color; /* couleur dans laquelle affiche la ligne */ { int DeltaX, DeltaY; int Temp; /* économise la moitié des cas de l'affichage de ligne en permutant Y0 et Y1 ainsi que X0 et X1, si Y0 est supérieur à Y1. Au final, DeltaY est toujours > 0, et seuls les octants 0-3doivent être traités. */ if ( Y0 > Y1 ) { Temp = Y0; Y0 = Y1; Y1 = Temp; Temp = X0; X0 = X1; X1 = Temp; } /* Traite comme quatre cas distincts, les quatre octants dans lesquels Y1 est supérieur à Y0 */ DeltaX = X1 - X0; /* calcule la longueur de la ligne dans chaque coordonnée */ DeltaY = Y1 - Y0; if ( DeltaX > 0 ) { if ( DeltaX > DeltaY ) { Octant0(X0, Y0, DeltaX, DeltaY, 1, Color); } else { Octant1(X0, Y0, DeltaX, DeltaY, 1, Color); } } else { DeltaX = -DeltaX; /* valeur absolue de DeltaX */ if ( DeltaX > DeltaY ) { Octant0(X0, Y0, DeltaX, DeltaY, -1, Color); } else { Octant1(X0, Y0, DeltaX, DeltaY, -1, Color); } } } /* * Routine pour afficher un rectangle remplit de lignes, de * longueur spécifiée et dans diverses couleurs, autour * du centre du rectangle spécifié. */ void VectorsUp(XCenter, YCenter, XLength, YLength) int XCenter, YCenter; /* centre du rectangle à remplir */ int XLength, YLength; /* distance du centre au bord du rectangle */ { int WorkingX, WorkingY, Color = 1; /* Lignes du centre en haut du rectangle */ WorkingX = XCenter - XLength; WorkingY = YCenter - YLength; for ( ; WorkingX < ( XCenter + XLength ); WorkingX++ ) EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color++); /* Lignes du centre à la droite du rectangle */ WorkingX = XCenter + XLength - 1; WorkingY = YCenter - YLength; for ( ; WorkingY < ( YCenter + YLength ); WorkingY++ ) EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color++); /* Lignes du centre au bas du rectangle */ WorkingX = XCenter + XLength - 1; WorkingY = YCenter + YLength - 1; for ( ; WorkingX >= ( XCenter - XLength ); WorkingX-- ) EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color++); /* Lignes du centre à la gauche du rectangle */ WorkingX = XCenter - XLength; WorkingY = YCenter + YLength - 1; for ( ; WorkingY >= ( YCenter - YLength ); WorkingY-- ) EVGALine(XCenter, YCenter, WorkingX, WorkingY, Color++); } /* * Programme pour afficher quatre rectangles plein de lignes. */ void main() { char temp; Set360x480Mode(); /* Affiche les quatre rectangles pleins de vecteurs */ VectorsUp(X_MAX / 4, Y_MAX / 4, X_MAX / 4, Y_MAX / 4, 1); VectorsUp(X_MAX * 3 / 4, Y_MAX / 4, X_MAX / 4, Y_MAX / 4, 2); VectorsUp(X_MAX / 4, Y_MAX * 3 / 4, X_MAX / 4, Y_MAX / 4, 3); VectorsUp(X_MAX * 3 / 4, Y_MAX * 3 / 4, X_MAX / 4, Y_MAX / 4, 4); /* Attend une touche clavier */ scanf("%c", &temp); /* Revient en mode texte */ _AX = TEXT_MODE; geninterrupt(BIOS_VIDEO_INT); }