Je me demandais ce que j'allais faire pour ce cours ASM, et comme
je suis loin d'tre une brute de l'assembleur pur (la dernire
fois que j'ai fait un prog cent pour cent en ASM, c'etait de l'ASM
Z80!) je me suis dis qu'une initiation avec un exemple a l'appui
irait tres bien. Et comme c'est plus interressant de voir ce que
l'on fait, j'ai opt pour un 'fire on the screen', classique mais
toujours chouette ! Je vais donc vous expliquer un peu comment ca
marche ...  Le source devrait tre disponible quelques part ...



I] La mmoire en mode rel


La mmoire en mode rel se dcoupe en segments de 64Ko, les dix
premiers sont rservs  la RAM de la mmoire centrale dont la
taille est donc limite a 640Ko. A la suite de la RAM se trouve
un segment de mmoire A (10 en hexa) qui appartient  la carte
graphique et qui mmorise le contenu de l'cran. Les segments
suivants sont rservs soit pour une carte monochrome, soit pour
le BIOS. Chaque segment est lui-mme adress par un offset.
En rsum, nous avons 16bits pour le segment puis 16 bits pour
l'offset, soit 32 bits qui nous permettent d'adresser 1Mo!!!
Zarb'ca! 1Mo=2^20 octets!!! Mais ou sont passs les 12 autres !!!

Because avant le 8080, le registres d'adresse avait 16 bits (donc
65536 units soit 64Ko. A l'poque ils voulait pouvoir grer
16 fois plus de RAM, ils leur fallait un registre d'adresse de
20bits... mais voila,  l'poque c'tait pas vraiment vident ...
Alors, ils ont fait comme d'hab', ils ont trouv l'astuce qui tue!
Le 8088 ne dispose plus d'un registre d'adresse spcialis.
A chaque accs en mmoire, il compose l'adresse 20 bits en
combinant deux nombres 16bits.

Mais comment ils font ca les bougres !!!!!

En fait, c'est pas trs compliqu, le segment est dcal de 4 bits
sur la gauche, puis l'offset lui est additionn: ce qui nous fait
bien 20 bits en tout (16+4). Donc si on ajoute 1 au segment, cela
revient  ajouter 16  l'offset (avec le dcalage de 4: 1*2^4).

Donc pour adresser la mmoire il faut un Segment et un offset. Et
comme nous l'avons vu plus haut la video se situe en 0A000h.



II] Enclenchons dj un mode graphique sympa: le mode 13h


Tout d'abord nous allons enclencher le mode 13h (320x200x256) car
sa gestion est des plus simple, pour cela il suffit d'appeler la
fonction 0 ( dans AH ) de l'interruption 10h avec le numero du
mode dans AL:

   Ŀ
        Mov AX,0013h
        INT 10h
   

Oulala, komment il a fait a ??? Bon, c'est vrai que ces
registres peuvent paratre un peu chiant au premier abord mais
en fat, c'est des plus simple. Les registres de donnes sont
batis de la faon suivante: Deux registres 8 bits forment un
registre 16 bits, et 16 bits + 16 bits = 32 bits ...
Enfin presque ... prenons un exemple, a sera plus simple ...
Bon, AH et AL se rassemble en AX, ainsi si AH=12h et AL=34h et
bien AX=1234h ... jusque la tout va bien ...
Mais, les registres 32 bits ne se dcoupe pas en deux registres
16 bits mais en UN registre 16 bits ... Zarb'Ca!

                |            EAX            |
                |      ??     |      AX     |
                |  ??  |  ??  |  AH  |  AL  |

Vous pouvez bien entendu vous servir de la partie haute de EAX,
mais indirectement avec les dcalages par exemples (SHL et SHR)
Ainsi, pour mettre 1234h dans la partie haute de EAX:


    Ŀ
            OR  EAX,12340000h
      ou    MOV AX,1234h
            SHL EAX,16
    



III] Mais comment s'est-y-que ca marche ?


Bon, alors c'est bien beau d'enclencher un mode graphique mais
encore faut il savoir le grer. Mais vous allez voir comme c'est
simple: c'est un mode linaire c'est  dire que de l'adresse 0 a
319 se trouve les 320 pixels de la premire ligne, de 320  639
les 320 pixels de la deuxime ligne, etc...
Donc pour poser un point aux coordonnes (x,y), il suffit de le
poser  l'offset:
  offset=x+y*320 dans le segment vido:    [0A000h:x+y*320]

  Ŀ
    MOV AX,0A000h                ; On charge le Segment Video
    MOV ES,AX                    ; dans le Registre ES
  

Donc pour adresser, il suffit de charger le segment vido dans un
registre de Segment(ES par ex). Mais on ne peut pas le faire
directement, il faut charger le segment dans un registre de
donnes puis copier ce registre dans le registre de segment.
Il faut ensuite calculer l'offset, le charger dans un registre de
donnes (DI par ex) et poser un octet ayant pour valeur le numro
du stylo du pixel que l'on veut afficher.



IV] Dtes, on peut avoir des couleurs ?


Nous verrons le dtail du feu plus loin, passons maintenant au
changement de couleur. Pour que le feu rende bien, il faut que
les couleurs soient bien ranges en dgrad. Le changement de
couleur des stylos est trs simple, il faut envoyer sur le port
3C8h (grce  l'instruction OUT) le numro du stylo dont on veut
changer la couleur, puis d'envoyer sur le port 3C9h ( OUT ) les
composantes Rouge, Vert, Bleu de la couleur. Petit dtail, les
composantes varient de 0  63, nous disposons donc de
64*64*64=262144 couleurs diffrentes avec une simple carte VGA.
De plus, il n'est pas ncessaire de renclencher le numro du
stylo suivant, en envoyant trois nouvelles composantes R,V,B,
le controleur comprend qu'il s'agit des composantes de la couleur
du stylo suivant.

  Ŀ
    Mov DX,3C8h        ; adresse du controleur
    Mov AL,255         ; on va changer la col du stylo No255
    Out DX,AL          ; on selectionne le stylo
    Inc DX             ; DX = 3C9h
    Mov AL,45          ; Composante Rouge = 45
    Out DX,AL          ; on envoie au controleur
    Mov AL,18          ; Composante Vert = 18
    Out DX,AL          ; on envoie au controleur
    Mov AL,22          ; Composante Bleu = 22
    Out DX,AL          ; on envoie au controleur
 



V] La Synchronisation Vertival, bon sang mais c'est bien sur!


Pour que le feu (ca vient ...) soit fluide, nous allons nous
synchroniser sur le canon  lectrons: Si on met  jour le feu 
l'cran alors que le canon  lectrons est en train d'afficher
l'image d'avant, on va rencontrer la synchro, c'est  dire que
nous verrons le dbut de l'image d'avant et la fin de la nouvelle
image introduisant ainsi une fracture (social?) entre le haut et
le bas de l'cran. Pour viter cela, nous allons d'abord attendre
la fin de l'affichage puis le dbut de l'affichage pour tre
certain que l'image prcdente a t totalement affiche et
seulement alors nous afficherons la nouvelle image. Tout ce passe
sur le port 3DAh du CRTC. (lecture garce a l'intruction IN)

 Ŀ
      Mov DX,3DAh           ; On charge le numero du port
   VSync1:                  ; du CRTC
      In AL,DX              ; On lit sa valeur
      Test AL,8             ; Le bit No4 y est-il ?
      Jnz VSync1            ; Oui! On recommence ! 
   VSync2:                  ; Non! On continue...
      In AL,DX              ; On lit sa valeur
      Test AL,8             ; Le bit No4 y est-il ?
      Jz Vsync2             ; Non! On recommence! 
 

Donc pour notre feu (NTous: enfin!!!), nous allons travailler dans
un buffer et n'acceder  cette dernire que pour poser le pixel.
En effet, la mmoire vido n'est pas des plus rapides et comme
nous allons faire huit accs en lecture, cela risqurait de pdaler
mme sur une grosse bcane.



VI] Description de l'effet le plus compliqu de la Demoscne !!!


En fait, nous allons raliser un smooth, c'est  dire une moyenne
des points mais au lieu de reposer la moyenne au centre, nous
allons la reposer juste au dessus:
                                                       
2 0 2                                                2 2 2
3 1 3    ( 2+2 + 3+1+3 + 2+3+2 ) /8 = 2,25  => 2     3 1 3
2 3 2                                                2 3 2

Et ainsi de suite pour chaque point, or comme la palette est
intelligemment range, les couleurs sont de plus en plus sombres
plus leur numro diminue, cela donne un effet de dgrad vers le
noir en montant. Vous allez me dire 'Et c'est tout ?' ... et bien
nan! il faut encore gnrer le feu proprement dit! Pour cela, il
faut des points de niveau de couleur diffrent poss de facons
alatoire a l'cran et ainsi entretenir le feu. Et la, je dois
dire que pour gnrer des nombres alatoires (hum hum) qui rendent
bien  l'cran assez  rapidement n'a pas t une mince affaire,
mais heureusement j'ai eu beucoup de chance. Je suis en fat parti
d'une procedure diffuse par Jare/Iguana mais ca rendait trs mal
sur mon foutu feu! Alors, comme Mr Chance passait par l ...

Ŀ
     Xor CL,CL                 ; CL=0 => 256 itrations
  merdes:                      ; On va aff des cacas (caches)
     Mov DI,Rand               ; Je recup' la dernire valeur
     Add DI,1000100010001000b  ; La val que j'ADD n'est QUE belle
     Ror DI,3                  ; en binaire, puis je ROTE tout ca
     Mov AX,DI                 ; on sauvegarde la valeur dans AX
     And DI,511                ; et on ramne ca  une valeur
     Sub DI,512-320            ; comprise entre 0 et 1280 (320*4)
     Shl DI,2

     Add AX,1100000011000000b  ; Celle la aussi elle est jolie...
     RoR AX,3                  ; c'est pas jolie tout ca ???
     Mov Rand,AX               ; on sauve la dernire valeur
     or  al,00000111b          ; al toujours > 15
     mov ah,al                 ; on va poser 2 fois la meme col
     Mov [64000+BX+DI],ax      ; c'est fait ( ES:[BX+64000+DI])
     Dec CL                    ; BX=buf, 64000=> hors de l'cran
     Jnz merdes                ; DI=adresse alatoires (hum???)


Une fois qu'on a attendu le dbut de la synchro, que les couleurs
tires alatoirement sont poses alatoirement  l'cran, on peut
alors faire notre 'smooth montant' et tout recommencer ....
Et voila !


                                                ArrakS
                                          Ki en a un peu marre
                                           de la mise en page!
