2d Chapitre 7 - Modes VESA haute résolution
CHAPITRE 7 - Modes VESA haute résolution
Le BIOS VGA nous offrent seulement le mode 12h, soit 640x480x16, comme mode haute résolution. Le problème est qu'avec seulement 16 couleurs, les effets même les plus simples ne peuvent être réalisés. Le standard VESA permet d’exploiter les modes SVGA, mais la programmation sous mode réel ne nous permet pas de beaucoup en profiter. En effet, lorsqu’il nous faut un écran virtuel de 307Kb (comme c’est le cas en mode 640x480), la mémoire conventionnelle devient très vite une denrée rare.
Pour ceux qui serait intéressé à programmer dans ces modes, je vous recommende fortement un DOS extender pour travailler en mode protégé, ou encore un compilateur 32-bit mode protégé comme DJGPP. Les programmeurs Windows peuvent oublier ce chapitre car de toutes façon DirectX gère lui-même les modes VESA. Le chapitre traite de VESA 1.2, c'est à dire sans le linear frame buffer qui, par définition, requiert le mode protégé. Le VESA VBE 2.0 permet simplement de travailler avec une structure de mémoire linéaire (comme en mode 13h), ce qui n'est pas le cas pour la version 1.x, qui elle est fracturée en plusieurs "fenêtres". Veuillez noter que les algorithmes vues précédemment peuvent s'adapter au mode VESA sans grande modifications.
NOTIONS DE BASE
Le standard VESA a vu le jour en 1989 alors que le comité Video Electronics Standards Association s'est rencontré pour déterminer un standard pour les cartes SVGA, qui se construisaient en nombre de plus en plus considérables à l'époque. Le premier souci de ce comité était de déterminer les modes vidéos soutenus par ce futur standard. Ils se sont mit d'accord sur 9 modes :
Numéro du mode Résolution Couleurs Mémoire
100h 640x400 256 256k
101h 640x480 256 512k
102h 800x600 16 256k
103h 800x600 256 512k
104h 1024x768 16 512k
105h 1024x768 256 1meg
106h 1280x1024 16 1meg
107h 1280x1024 256 1.25meg
06Ah 800x600 16 256k
Ces modes furent complétés par l’ajout de modes permettant l’utilisation de couleurs 15, 16, 24 et 32-bits. Ces modes requiert une attention toute particulière pour ce qui est de l’affichage des pixels, donc nous y reviendrons en détails vers la fin du chapitre.
APPEL DES FONCTIONS DU BIOS VESA
Tout comme les fonctions du BIOS VGA, celles du BIOS VESA s'appelle par l'interruption 10h du BIOS. 6 sous-fonctions implementées dans la fonction 4Fh peuvent être appelées par cette fonction. Avant l'appel de la fonction, il faut charger le numéro de fonction 4Fh dans AH et le numéro de fonction, entre 0 et 5, dans AL. Voici les diverses fonctions que nous aurons besoins pour travailler confortablement avec les modes VESA. REGPACK est utilisé comme structure pour nos registres.
Liste des fonctions du BIOS VESA (4Fh)
- 00h Déterminer les performances de la carte Super VGA
- 01h Déterminer les données-clés d'un mode déterminé
- 02h Définir le mode VESA
- 03h Lire le mode vidéo actuel
- 04h Sauvegarder/Restaurer le statut de la carte Super VGA
- 05h Définir/Demander la fenêtre d'accès à la RAM vidéo
Les registres AH et AL sont ceux dans lesquels on obtient le résultat de l'appel de fonction. Ces fonctions sont nécessaires pour mettre sur pied notre espace de travail en mode hautes résolutions. Voici la description des fonctions et leurs effets.
00h Déterminer les performances de la carte Super VGA
Dans le meilleur des mondes, toutes les cartes Super VGA seraient standardisés. Comme nous le savons tous, il existe toujours des exceptions. Le premier travail effectué avec les fonctions doit donc consister à appeler la fonction 00h pour obtenir les caractéristiques de la carte vidéo. En plus des numéros de fonctions que l'on doit mettre dans AH/AL, 00h attend un pointeur FAR sur un buffer de 256 octets dans ES:DI. Dans ce même buffer, 00h retourne les informations sur la carte:
Structure du bloc de données de la sous-fonction 00h
Offset Contenu Type
00h Signature VESA ("VESA") 4 Bytes
04h Version VESA, numéro de version principal 1 Byte
05h Version VESA, numéro de version secondaire 1 Byte
06h Pointeur FAR sur chaîne ASCII avec le nom du fabricant 1 DWord
0Ah Flag (inutilisé dans v.1) 1 DWord
0Eh Pointeur FAR sur les numéros des modes vidéos soutenus 1 DWord
Par l'intermédiaire du dernier pointeur de la table, la carte vidéo fournit la liste des modes qu'elle soutient. On peut donc déterminer si le mode vidéo désiré est disponible.
typedef struct vesa // Information sur le pilote VESA
{
unsigned char signature[4];
unsigned char version1;
unsigned char version2;
char far *oem;
long capabilities;
unsigned far *videomodes;
short memoire;
char reserves[236];
};
void lireVesaInfo()
{
Regs.r_ax = 0x4F00;
Regs.r_es = FP_SEG(vesaInfo);
Regs.r_di = FP_OFF(vesaInfo);
intr (0x10, &Regs);
}
Quelques notes sur le code source : on utilise ici la structure REGS pour adresser les registres, plutôt que d’avoir recours à l’assembleur, même si cela s’y prêterais bien. Le cours sur l’assembleur contient plus de détails sur la version assembleur de ces fonctions.
01h Déterminer les données-clés d'un mode déterminé
Une fois la disponibilité du mode assuré, il nous faut toutes les informations nécessaire sur ledit mode afin de pouvoir travailler avec ce dernier. La fonction 01h nous permet d'obtenir toutes ces informations. En plus du numéro de la fonction en AH/AL, il faudra lui passer le numéro de mode souhaité. Encore une fois, la fonction retourne ces informations dans un buffer, encore cette fois de 256 octets.
Structure du bloc de données de la sous-fonction 01h
Offset Contenu Type
00h Flag de mode 1 Word
02h Flag pour la première fenêtre d'accès 1 Byte
03h Flag pour la deuxième fenêtre d'accès 1 Byte
04h Granularité en Ko pour décaler les deux fenêtre d'acces 1 Word
06h Taille des deux fenêtre d'accès en Ko 1 Word
08h Adresse de segment de la première fenêtre d'accès 1 Word
0Ah Adresse de segment de la deuxième fenêtre d'accès 1 Word
0Ch Pointeur FAR sur routine de définition de la zone visible 1 DWord
10h Octets utilisés par chaque ligne de points dans la RAM vidéo 1 Word
12h Résolution X 1 Word
14h Résolution Y 1 Word
16h Largeur de la matrice 1 Byte
17h Hauteur de la matrice 1 Byte
18h Nombre de plans de bits 1 Byte
19h Nombre de bits par pixel 1 Byte
1Ah Nombre de blocs mémoire 1 Byte
1Bh Modèle de mémoire 1 Byte
1Ch Taille des blocs de mémoire en Ko 1 Byte
225 225 Octets réservés pour la version 2.0 225 Byte
typedef struct mode // Informations sur un mode VESA
{
unsigned short AttributsMode;
unsigned char AttributsFenetreA;
unsigned char AttributsFenetreB;
unsigned short GranulariteFenetre;
unsigned short TailleFenetre;
unsigned short SegmentFenetreA;
unsigned short SegmentFenetreB;
void far *PtrFunctionFenetre;
unsigned short OctetsParLigne;
unsigned short ResolutionX;
unsigned short ResolutionY;
unsigned char TailleCarX;
unsigned char TailleCarY;
unsigned char NombreDePlans;
unsigned char BitsParPixel;
unsigned char NbrBanques;
unsigned char ModeleMemoire;
unsigned char TailleBanque;
unsigned char NombrePages;
unsigned char Reserves[225];
};
L'information la plus importante qui nous est retourné est l'adresse de segment de la fenêtre d'accès sur la RAM vidéo. On se sert de cette donnée pour déclarer un pointeur sur cette adresse, comme nous l'avons toujours fait en mode 320x200. Nous obtenons également le nombre de bits par pixel, la résolution horizontale et verticale et la « granularité » existant entre les fenêtres d’accès (le décalage qui existe entre chacune)
void lireInfoMode(unsigned short Mode)
{
Regs.r_ax = 0x4F01;
Regs.r_cx = Mode;
Regs.r_es = FP_SEG(modeInfo);
Regs.r_di = FP_OFF(modeInfo);
intr (0x10, &Regs);
}
02h Définir le mode VESA
Une fois qu'on a invoqué la liste des modes vidéos soutenus à l'aide de la fonction 00h, demandé les informations sur ce mode avec la 01h, on peut maintenant activer ce mode vidéo avec la fonction 02h. Il faut charger dans BX le mode vidéo souhaité avant d'appeler l’interruption 10h.
void initVESAmode(unsigned short Mode)
{
Regs.r_ax = 0x4F02;
Regs.r_bx = Mode;
intr (0x10, &Regs);
lireInfoMode(Mode);
int i = modeInfo->TailleFenetre/modeInfo->GranulariteFenetre;
switch(i)
{
case 1: decalage=0; break;
case 2: decalage=1; break;
case 4: decalage=2; break;
case 8: decalage=3; break;
case 16: decalage=4; break;
case 32: decalage=5; break;
case 64: decalage=6; break;
}
for (int fenetre=0; fenetre<15; fenetre++)
Banques[fenetre] = (fenetre*modeInfo->TailleFenetre)/modeInfo- GranulariteFenetre;
unsigned short Segment = modeInfo->SegmentFenetreA;
ecran = (char *) MK_FP(Segment, 0x000);
}
Une fois le mode initialisé, il faut déterminer le décalage qui existe entre chacune des fenêtres. En effet, il arrive qu’une fenêtre ne débute pas exactement après la précédente. La fonction qui nous permet de changer de banque mémoire doit connaître ce décalage. Ensuite, nous pouvons initialiser le pointeur sur le premier segment vidéo (généralement 0xA000), et précalculer les adresses des banques mémoires en fonction de la taille des fenêtres et de leurs granularité.
05h Définir/Demander la fenêtre d'accès à la RAM vidéo
Il nous était facile avant de travailler avec un mode vidéo qui nécessite moins de 64k de mémoire. On pouvait accéder à la totalité de la RAM vidéo à travers le segment de mémoire de 64k qui commence à A000. Mais les choses se compliquent quand il nous faut plus de 64k, comme c'est le cas pour presque tous les modes SVGA. La solution à ce problème se trouve dans les fenêtres d'accès, qui permettent au programme d'adresser 64k de mémoire, en utilisant le segment A000.
Pour sélectionner la fenêtre, en plus du traditionnel numéro de fonction dans BH, le numéro de la fenêtre doit être fourni dans BL (0 ou 1). La deuxième fenêtre ne peut être déplacé seulement si elle est présente sur la carte vidéo (comme le signale 01h). L'autre paramètre, qui doit être mit dans le registre DX, est ce qu'on appelle la granularité de la fenêtre d' accès. Il indique le début de la zone adressable dans la RAM vidéo. La granularité représente une puissance de deux de 1 Ko (1,2,4,8,etc). La taille d'une page correspond à la granularité, donc avec une granularité de 1ko, le segment A000 peut contenir 64 pages consécutives. Le numéro de la première page est déterminé par un registre électronique nommé Page Select.
void changerBanque(unsigned short Banque)
{
BanqueCur = Banque;
Regs.r_ax = 0x4F05;
Regs.r_bx = decalage;
Regs.r_dx = Banques[Banque];
intr (0x10, &Regs);
}
MODES COULEURS 15,16 et 24 Bits
Comme vous le savez, le comité VESA a mit sur pied un éventail assez important de modes graphiques qui travaillent en "hi-color", c'est à dire avec 32K, 64K ou 16.8 millions de couleurs. Ces modes d'affichages permettent de réaliser les effets les plus spectaculaires, et la plupart des jeux d'aujourd'hui fonctionnent en modes 16-bit. Pour bien comprendre comment fonctionne les modes hi-color, regardons tout d’abord le fonctionnement de base d’un putpixel VESA en mode 256 couleurs.
void putpixel (long X, long Y, unsigned char Color)
{
unsigned long offset;
unsigned short Banque;
offset = (Y*modeInfo->ResolutionX) + X;
Banque = offset >> 16;
if (BanqueCur != Banque) changerBanque(Banque);
ecran[offset] = Color;
}
On calcule l’offset par la formule (y*RÉSOLUTION_X)+x, et on vérifie ensuite dans quelle banque de mémoire se situe l’offset du pixel. Si on doit changer de banque, on appel changeBanque, la fonction 05h, et on affiche ensuite le pixel sur l’écran à l’offset spécifié.
L'utilisation ces modes hi-color ne demande pas beaucoup de modifications au code de base que nous avons construit auparavant. Le seul hic, c'est que nous n'envoyons plus simplement un seul octet pour afficher un pixel. En effet, un nous faudra maintenant 2 ou 3 octets pour envoyer toute l'information nécessaire pour afficher un pixel. Voici un tableau qui résume l'information nécessaire pour l'affichage:
BPP Données Organisation
8 Palette 256 couleurs dans une palette
15 5.5.5.1 RGBA Red Green Blue et 1 bit pour Alpha
16 5.6.5 RGB Red Green Blue mais Green a 1 bit+
24 8.8.8 RGB Red Green Blue
32 8.8.8.8 RGBA Red Green Blue Alpha
Le "Alpha" peut être utilisé selon votre humeur (il est inutilisé par le CRT) mais souvent on s'en sert souvent pour la transparence en mode 16-bit. Vous pouvez maintenant dire adieu à la palette 256 couleurs, car vous n'en aurez plus besoin pour les modes hautes couleurs. En mode 13h, si on voulait écrire un pixel blanc, on utilisait n'importe quel entrée de palette qui correspondait à blanc (rgb==63,63,63). Maintenant nous envoyons directement ces informations sur l'écran:
En mode 24-bit:
col: RGB RGB RGB ......... RGB
octet: 012 345 678 ......... 957,958,959
pixel: 0 1 2 ......... 319
Donc, afin d'écrire un pixel blanc sur l'écran au pixel 0, il faut envoyer 3 octets correspondant aux valeurs de rouge, de vert et de bleu (RGB):
(char *)(ecran)[0]=255;
(char *)(ecran)[1]=255;
(char *)(ecran)[2]=255;
Maintenant, les choses se compliquent un peu pour travailler en mode 15-bit/16-bit. Il faut shifter les bits pour convertir de 24 bpp à 15/16 bpp. Je vous épargne les détails de cette formule, mais vous pouvez facilement la trouver en faisant les opérations logiques sur les bits. Voici la formule:
// 16-bit
pixel = (int)(red & 0xF8) <<8 | (int)(green & 0xFC) << 3| (int)(blue & 0xF8) >> 3;
//15-bit
pixel = (int)(red & 0xF8) << 7| (int)(green & 0xF8) << 2| (int)(blue & 0xF8) >> 3;
CONCLUSION
Dans le code source, j’ai inclus une fonction qui charge des PCX 256 couleurs de hautes résolutions. Cependant, elle ne fait que « dumper » le contenu du fichier sur l’écran directement. Également, il y a une fonction putpixel pour modes hi-color qui illustre la qualité d’un effet de transparence au fur et à mesure que le nombre de couleurs augmente.
En résumé :
- Utilisation des fonctions 0x4F du BIOS SVGA
- Concept de fenêtrage et de banques mémoires de 64k en mode réel
- Mode couleurs 15,16 et 24-bit
2dchap7.cpp
//----------------------------------------------------------------------//
// FICHIER : 2DCHAP7.CPP //
// AUTEUR : Shaun Dore //
// DESCRIPTION : Modes VESA hautes resolutions //
// DATE DE MODIFICATION : 19-04-98 //
// COMPILATEUR : Borland Turbo C++ Real Mode 16-bit compiler //
// NOTES : Compiler avec modele memoire Compact //
//----------------------------------------------------------------------//
#define PAUSE asm {XOR AX,AX; INT 0x16}
#define TEXT asm {MOV AX,0x03; INT 0x10}
//----------------------------------------------------------------------//
// Fichier includes //
//----------------------------------------------------------------------//
#include <mem.h>
#include <dos.h>
#include <stdio.h>
//----------------------------------------------------------------------//
// Structures de donnees //
//----------------------------------------------------------------------//
typedef struct vesa // Information sur le pilote VESA
{
unsigned char signature[4];
unsigned char version1;
unsigned char version2;
char far *oem;
long capabilities;
unsigned far *videomodes;
short memoire;
char reserves[236];
};
typedef struct mode // Informations sur un mode VESA
{
unsigned short AttributsMode;
unsigned char AttributsFenetreA;
unsigned char AttributsFenetreB;
unsigned short GranulariteFenetre;
unsigned short TailleFenetre;
unsigned short SegmentFenetreA;
unsigned short SegmentFenetreB;
void far *PtrFunctionFenetre;
unsigned short OctetsParLigne;
unsigned short ResolutionX;
unsigned short ResolutionY;
unsigned char TailleCarX;
unsigned char TailleCarY;
unsigned char NombreDePlans;
unsigned char BitsParPixel;
unsigned char NbrBanques;
unsigned char ModeleMemoire;
unsigned char TailleBanque;
unsigned char NombrePages;
unsigned char Reserves[225];
};
//----------------------------------------------------------------------//
// Variables globales //
//----------------------------------------------------------------------//
char *ecran; // Ptr sur segment initial de memoire video
char BanqueCur; // Indicateur de la banque memoire courante
char decalage; // Decalage entre les fenetres
vesa *vesaInfo = (vesa *)256; // Informations sur le pilote VESA
mode *modeInfo = (mode *)256; // Information sur un mode VESA
struct REGPACK Regs; // Registres du processeur
unsigned short Banques[15]; // Adresse des banques memoires
unsigned int nomode = 0x101; // No du mode video
//----------------------------------------------------------------------//
// Fonction 0x00 - Lire les information sur le pilote VESA de la carte //
//----------------------------------------------------------------------//
void lireVesaInfo()
{
Regs.r_ax = 0x4F00;
Regs.r_es = FP_SEG(vesaInfo);
Regs.r_di = FP_OFF(vesaInfo);
intr (0x10, &Regs);
}
//----------------------------------------------------------------------//
// Fonction 01h - Determiner les donnes-cles d'un mode VESA //
//----------------------------------------------------------------------//
void lireInfoMode(unsigned short Mode)
{
Regs.r_ax = 0x4F01;
Regs.r_cx = Mode;
Regs.r_es = FP_SEG(modeInfo);
Regs.r_di = FP_OFF(modeInfo);
intr (0x10, &Regs);
}
//----------------------------------------------------------------------//
// Fonction 02h - Initialise un mode graphique VESA //
//----------------------------------------------------------------------//
void initVESAmode(unsigned short Mode)
{
Regs.r_ax = 0x4F02;
Regs.r_bx = Mode;
intr (0x10, &Regs);
lireInfoMode(Mode);
int i = modeInfo->TailleFenetre/modeInfo->GranulariteFenetre;
switch(i)
{
case 1: decalage=0; break;
case 2: decalage=1; break;
case 4: decalage=2; break;
case 8: decalage=3; break;
case 16: decalage=4; break;
case 32: decalage=5; break;
case 64: decalage=6; break;
}
for (int fenetre=0; fenetre<15; fenetre++)
Banques[fenetre] = (fenetre * modeInfo->TailleFenetre/modeInfo->GranulariteFenetre);
unsigned short Segment = modeInfo->SegmentFenetreA;
ecran = (char *) MK_FP(Segment, 0x000);
}
//----------------------------------------------------------------------//
// Fonction 05h - Fonction pour changer de banque memoire //
//----------------------------------------------------------------------//
void changerBanque(unsigned short Banque)
{
BanqueCur = Banque;
Regs.r_ax = 0x4F05;
Regs.r_bx = decalage;
Regs.r_dx = Banques[Banque];
intr (0x10, &Regs);
}
//----------------------------------------------------------------------//
// Putpixel en modes VESA 256 couleurs //
//----------------------------------------------------------------------//
void putpixel (long X, long Y, unsigned char Color)
{
unsigned long offset;
unsigned short Banque;
offset = (Y*modeInfo->ResolutionX) + X;
Banque = offset >> 16;
if (BanqueCur != Banque) changerBanque(Banque);
ecran[offset] = Color;
}
//----------------------------------------------------------------------//
// Putpixel en modes VESA hicolor //
//----------------------------------------------------------------------//
void putpixelH(int x, int y, int red, int green, int blue)
{
unsigned long int offset;
unsigned short Banque;
int data;
switch(nomode)
{
case 0x10D: // Couleurs 15-bit
case 0x110:
case 0x113:
case 0x116:
case 0x119:
data = (red & 0xF8) << 7 | (green & 0xF8) << 2 | (blue & 0xF8) >> 3;
offset = (long)y * modeInfo->OctetsParLigne + 2 * x;
Banque = offset >> 16;
if (BanqueCur != Banque) changerBanque(Banque);
ecran[offset++] = data & 0xFF;
ecran[offset] = data >> 8;
break;
case 0x10E: // Couleurs 16-bit
case 0x111:
case 0x114:
case 0x117:
case 0x11A:
data = (red & 0xF8) << 8 | (green & 0xFC) << 3 | (blue & 0xF8) >> 3;
offset = (long)y * modeInfo->OctetsParLigne + 2 * x;
Banque = offset >> 16;
if (BanqueCur != Banque) changerBanque(Banque);
ecran[offset++] = data & 0xFF;
ecran[offset] = data >> 8;
break;
case 0x10F: // Couleurs 24-bit
case 0x112:
case 0x115:
case 0x118:
case 0x11B:
offset = (long)y * modeInfo->OctetsParLigne + 3 * x;
Banque = offset >> 16;
if (BanqueCur != Banque) changerBanque(Banque);
ecran[offset++] = blue;
Banque = offset >> 16;
if (BanqueCur != Banque) changerBanque(Banque);
ecran[offset++] = green;
Banque = offset >> 16;
if (BanqueCur != Banque) changerBanque(Banque);
ecran[offset] = red;
}
}
//----------------------------------------------------------------------//
// setpal - Modifie la palette //
//----------------------------------------------------------------------//
void setpal(unsigned char coul,unsigned char r,unsigned char g,unsigned char b)
{
outp (0x03C8,coul);
outp (0x03C9,r);
outp (0x03C9,g);
outp (0x03C9,b);
}
//----------------------------------------------------------------------//
// loadpcx - Charge en memoire un fichier .PCX //
//----------------------------------------------------------------------//
int loadpcx(char *nomfich)
{
unsigned char data, nb_octets, palette[768];
unsigned long index = 0;
unsigned int indexrle,x,y;
unsigned short Bank = 0;
FILE *fichpcx;
if (!(fichpcx = fopen(nomfich, "rb"))) return 0;
fseek(fichpcx, -768, SEEK_END);
fread(&palette, 768, 1, fichpcx);
for (int coul=0;coul<=255;coul++)
setpal(coul,palette[coul*3]>>2,palette[coul*3+1]>>2,palette[coul*3+2]>>2);
fseek(fichpcx, 128, SEEK_SET);
do
{
fread(&data, 1, 1, fichpcx);
if ((data & 0xC0) == 0xC0)
{
nb_octets = (data & 0x3F);
fread(&data,1,1,fichpcx);
for (indexrle=0;indexrle<nb_octets;indexrle++)
{
Bank = index >> 16;
if (BanqueCur != Bank) changerBanque(Bank);
ecran[index++] = data;
}
}
else
{
Bank = index >> 16;
if (BanqueCur != Bank) changerBanque(Bank);
ecran[index++] = data;
}
} while(index < 307200L);
fclose(fichpcx);
return 1;
}
//----------------------------------------------------------------------//
// Fonction principale //
//----------------------------------------------------------------------//
void main()
{
TEXT
lireVesaInfo();
printf("* INFORMATIONS VESA *\n---------------------\n");
printf("Version VESA : %i.%i\n",vesaInfo->version2,vesaInfo->version1);
printf("Manufacturier: %s\n",vesaInfo->oem);
printf("Memoire: %i Meg\n",vesaInfo->memoire >> 4);
PAUSE
// LoadPCX en 640x480x8 bit
initVESAmode(nomode);
if(!(loadpcx("ad.pcx")))
{
TEXT
printf("ERREUR: Incapable de charger ad.pcx");
return;
}
PAUSE
// 640x480x15-bit
nomode = 0x110;
initVESAmode(nomode);
for (int y=0;y<480;y++)
for (int x=0;x<640;x++)
putpixelH(x,y,0,x%100,x&y);
PAUSE
// 640x480x16-bit
nomode = 0x111;
initVESAmode(nomode);
for (y=0;y<480;y++)
for (x=0;x<640;x++)
putpixelH(x,y,0,x%100,x&y);
PAUSE
// 640x480x24-bit
nomode = 0x112;
initVESAmode(nomode);
for (y=0;y<480;y++)
for (x=0;x<640;x++)
putpixelH(x,y,0,x%100,x&y);
PAUSE
TEXT
printf("\n* INFORMATIONS DU MODE *\n------------------------\n");
printf("Granularite : %iK\n",modeInfo->GranulariteFenetre);
printf("TailleFenetre : %iK\n",modeInfo->TailleFenetre);
printf("Segment Fenetre: 0x%x\n",modeInfo->SegmentFenetreA);
printf("Octets par ligne: %i\n",modeInfo->OctetsParLigne);
printf("Resolution X: %i\n",modeInfo->ResolutionX);
printf("Resolution Y: %i\n",modeInfo->ResolutionY);
printf("Bits par pixel %i\n",modeInfo->BitsParPixel);
printf("\nShaun Dore\ndores@videotron.ca\n http://pages.infinit.net/shaun ");
}