TUTORIAL ASSEMBLEUR - chapitre 7
--------------------------------

Programmation graphique
-----------------------

Introduction
------------

Nous allons aborder un vaste sujet. En effet, il existe une infinit de possibilits 
pour crer des effets avec un ordinateur. J'essayerais d'tre simple et d'aller progressivement 
pour viter les confusions. Tout d'abord, nous verrons la mmoire vido, les diffrents
modes vidos du BIOS. Nous ne verrons pas spcialement les autres modes 
(svga, mode-X, fakemode, truecolor..), il existe assez de docs sur ces modes et je m'en tiens
 un cours d'introduction.

La mmoire vido
----------------

Il existe un emplacement en mmoire qui s'appelle la mmoire video (VRAM = video-ram). 
Ce bloc de 64ko (en mode rel) commence  partir de l'adresse 0a000h:0000. 
Pour pouvoir utiliser cette emplacement, il faut initialiser depuis un mode texte 
(ou un autre mode graphique), le mode video dsir. 

Nous utiliserons tout d'abord pour sa simplicit, le mode 013h de l'interruption 010h. Ce mode 
possde une rsolution de 320x200. Nous aurons donc 320 pixels en largeur et 200 en hauteur. 
Le nombre de couleurs est de 256, ce qui permet dj pas mal de chose. 

Dans ce mode, il suffit d'crire la couleur du pixel (un byte) dans la mmoire. 
La position du pixel dans la mmoire n'est pas calcule selon les coordonnes X,Y 
mais linairement. Normalement, dans un language comme le BASIC, on utilise l'instruction 
PSET (X,Y),couleur. En asm, on ne va pas utiliser 2 valeurs pour adresser directement
dans la mmoire mais un seul offset.

Il faut donc convertir ces coordonnes X,Y en adresse linaire et exploitable. 
Nous utilisons la formule :

[(Y*320)+X]=offset_du_pixel.

Pour mieux comprendre ce qui se passe, voici un schma de la VRAM :
           
          0                                319 (dernier pixel de la ligne)
ligne 0 : **********************************
ligne 1 : **********************************
         320                              640  


Les pixels sont disposs les un aprs les autres. Un pixel  la position (12,79) aura
comme offset :

(79*320)+12 = 25292

Nous voulons un pixel de couleur 14 (couleur jaune pour la palette standard du DOS), 
nous crirons  aprs avoir initialis le mode vido et les registres, le byte de valeur 14
 l'adresse 0a000h:025292d.

Un petit exemple directement compilable dans A86:

MOV AX,013h 		; nous utilisons le mode 013h => 320x200x256c
INT 10h 		; l'interruption 10h utilise pour tout ce qui concerne la vido
MOV AX,0A000h 		; on place 0A000h dans AX que l'on va 
MOV ES,AX 		; transfrer dans ES
MOV AL,14 		; pixel index 14 => jaune
MOV ES:[25292],AL 	; on ne peut pas crire directement MOV ES:[25292],14
RET 			; mme chose que MOV AX,04ch - INT 21h 
                        ; mais en plus court => fin programme

Vous aurez un beau pixel jaune sur l'cran =8)

Cependant, il reste un petit problme, nous sommes rests dans le mode 013h en revenant au DOS
et nous n'avons plus de mode texte. La solution consiste  placer avant le RET, les instructions
suivantes :

MOV AX,03h
INT 10h

Nous mettons d'abord 03h pour signaler que nous voulons le mode texte 03h (80x25) et INT 10h 
pour initialiser le mode. Vous n'aurez plus le temps de voir votre pixel. Il faut ajouter 
avant le retour en mode texte, ces instructions :

XOR AX,AX 		; toujours utiliser XOR pour mettre des registres  0
INT 16h 		; interruption du clavier

Vous aurez ainsi le temps de voir votre pixel et tant que vous ne touchez pas votre clavier, 
vous pourrez l'admirer, l'interruption 16h attend que vous appuyez sur une touche pour 
continuer et passer aux instructions qui suivent. Nous avons donc au final, le
petit programme suivant :

MOV AX,013h 		; nous utilisons le mode 013h => 320x200x256c
INT 10h 		; l'interruption 10h utilise pour tout ce qui concerne la vido
MOV AX,0A000h 		; on place 0A000h dans AX que l'on va 
MOV ES,AX 		; transfrer dans ES
MOV AL,14 		; pixel index 14 => jaune
MOV ES:[25292],AL 	; on ne peut pas crire directement MOV ES:[25292],14
XOR AX,AX 		; comme MOV AX,0 mais plus court
INT 16h 		; interruption du clavier - attente de l'appui d'une touche
MOV AX,03h 		; mode texte
INT 10h 		; on l'appelle
RET 			; retour au DOS

Effacer l'cran
---------------

Maintenant que nous avons quelques notions et que nous savons utiliser les boucles 
(si vous ne savez pas, retournez aux autres chapitres, c'est indispensable), nous allons 
effacer l'cran avec la couleur 0 qui est le noir tant que vous ne touchez pas  la palette. 
En ce qui concerne celle-ci, nous verrons dans une prochaine leon, comment la modifier.

Nous avons  effacer exactement 64000 bytes. Nous n'allons pas les effacer un  un mais 
directement deux par deux (16 bits) ou quatre par quatre en 32 bits. Il suffit de crer 
une boucle qui les effacera et regardera si nous sommes  la fin de l'cran.
Pour gagner la vitesse, nous utiliserons des words et des dwords au lieu des bytes. 

Voici un exemple :

MOV AX,013h 		; nous utilisons le mode 013h => 320x200x256c
INT 10h 		; l'interruption 10h utilise pour tout ce qui concerne la vido
MOV AX,0A000h 		; on place 0A000h dans AX que l'on va 
MOV ES,AX 		; transfrer dans ES
XOR DI,DI 		; premier pixel de l'cran
MOV AX,0 		; on met AX  0, AL et AH = 0 = noir

Debut: 		
MOV ES:[DI],AX 		; on place directement le word  l'emplacement de DI
ADD DI,2 		; on travaille avec des Words donc on augmente de deux et plus de un
CMP DI,64000 		; on regarde si on dpasse
JNAE Debut 		; (saute si pas suprieur), ds que nous avons DI>=64000, stop
MOV AX,03h 		; mode texte
INT 10h 		; on l'appelle
RET 			; retour au DOS

Nous avons vu dans le prcedent chapitre, que l'utilisation de STOSB permettait
de remplacer des MOV, nous allons diminuer la taille du programme:

MOV 	ax,013h
INT 	010h		; ca reste la meme chose
PUSH 	0a000h
POP  	es		; permet de diminuer la taille d'un byte, on utilise la pile
XOR 	di,di		
XOR	ax,ax		; met di  0 et ax=couleur  0 aussi

MOV     cx,32000	; nous allons effacer 32000 words = 64000 bytes
REP	STOSB		; MOV ES:[DI],ax  ADD DI,2  et ceci, 32000 fois.
MOV 	al,03h		; pas besoin d'initialiser AX  03, AH est dj  0
INT     010h		; on initialise que AL et on appelle l'interruption
RET

C'est de cette manire que l'on procde ds que l'on optimise du code pour la taille
(intros 4k..). Faites attention aux bugs lors des optimisations.

### Chapitre 7 - dake / c a l o d o x ###
### http://www.space.ch/scene/calodox ###
   
