home *** CD-ROM | disk | FTP | other *** search
/ PC Interdit / pc-interdit.iso / graph / gif.asm < prev    next >
Assembly Source File  |  1994-10-07  |  13KB  |  319 lines

  1. .286
  2.  
  3. clr=256                         ;code d'effacement de l'alphabet
  4. eof=257                         ;code de fin de fichier
  5. w equ word ptr
  6. b equ byte ptr
  7.  
  8. data segment public
  9.   extrn gifname:dataptr         ;Nom du fichier Gif, avec ".gif" + db 0
  10.   extrn vscreen:dword           ;pointe sur la mémoire de destination
  11.   extrn palette:dataptr         ;palette de destination
  12.   extrn vram_pos:word           ;position à l'intérieur de la mémoire d'écran
  13.   extrn rest:word               ;nbre de codes restant à copier
  14.   extrn numerr:word;            ;indicateur d'erreur
  15.  
  16.   handle     dw 0               ;handle DOS pour fichier Gif
  17.   buff       db 768 dup (0)     ;buffer des données lues      
  18.   buffInd     dw 0              ;pointeur à l'intérieur de ce buffer
  19.   abStack    db 1281 dup (0)    ;pile de décodage            
  20.   ab_prfx    dw 4096 dup (0)    ;alphabet, préfixe 
  21.   ab_suffx    dw 4096 dup (0)   ;alphabet, suffixe
  22.   free      dw 0                ;position libre dans l'alphabet
  23.   nbbit    dw 0                 ;nombre de bits dans un code
  24.   max        dw 0       ;nombre maximum d'entrées dans un alphabet à nbbit
  25.   stackp    dw 0                ;pointeur dans la pile de l'alphabet
  26.   restbits  dw 0                ;nombre de bits à lire      
  27.   restbyte  dw 0                ;nombre d'octets disponibles dans le buffer
  28.   casspecial dw 0               ;mémoire pour le cas spécial
  29.   act_code  dw 0                ;code traité 
  30.   old_code  dw 0                ;code précédent     
  31.   readbyt   dw 0                ;code en cours de lecture               
  32.   lbyte      dw 0               ;dernier code lu
  33. data ends
  34.  
  35. extrn p13_2_modex:far           ;utilisé en cas de dépassement du segment
  36.  
  37. code segment public
  38. assume cs:code,ds:data
  39.  
  40. public readgif
  41. GifRead proc pascal n:word
  42. ;lit n octets dans le fichier        
  43.   mov ax,03f00h                 ;fonction 3fh de l'interruption 21h   
  44.   mov bx,handle                 ;charge le handle
  45.   mov cx,n                      ; et le nombre d'octets à lire  
  46.   lea dx,buff                    ;pointe sur le buffer de destination
  47.   int 21h                       ;exécute l'interruption
  48.   ret
  49. gifread endp
  50.  
  51. GifOpen proc pascal
  52. ;ouvre le fichier Gif pour y accéder en lecture
  53.   mov ax,03d00h                 ;fonction 3dh: ouvrir
  54.   lea dx,gifname + 1  ;pointe sur le nom (saute l'octet qui mémorise la taille)
  55.   int 21h                       ;exécute l'interruption
  56.   mov handle,ax                 ;sauvegarde le handle
  57.   ret
  58. gifopen endp
  59.  
  60. GifClose proc pascal
  61. ;ferme le fichier Gif
  62.   mov ax,03e00h                 ;fonction 3eh: fermer   
  63.   mov bx,handle                 ;charge le handle
  64.   int 21h                       ;exécute l'interruption
  65.   ret
  66. gifclose endp
  67.  
  68. GifSeek proc pascal ofs:dword
  69. ;positionne le pointeur du fichier 
  70.   mov ax,04200h                 ;fonction 42h,
  71.   mov bx,w handle          ;sous-fonction 0: Seek relatif au début du fichier
  72.   mov cx,word ptr ofs + 2       ;charge l'offset
  73.   mov dx,word ptr ofs
  74.   int 21h                       ;exécute l'interruption
  75.   ret
  76. Endp
  77. ShiftPal proc pascal
  78. ;adapte la palette 24 bits au format VGA (18 bits)            
  79.   mov ax,ds             ;segment de données pour tables source et destination 
  80.   mov es,ax
  81.   mov si,offset buff            ;lecture dans le buffer de données
  82.   lea di,palette                ;écriture dans la palette de destination
  83.   mov cx,768d                   ;traite 786 octets
  84. @l1:
  85.   lodsb                         ;lit un octet
  86.   shr al,2                      ;le convertit
  87.   stosb                         ;et l'enregistre
  88.   loop @l1
  89.   ret
  90. Endp
  91. FillBuff proc pascal
  92. ;lit tout un bloc du fichier en Buf
  93.   call gifread pascal,1         ;lit un octet
  94.   mov al,b buff[0]               ;transfère la taille en al 
  95.   xor ah,ah
  96.   mov w restbyte,ax             ;et la mémorise en restbyte 
  97.   call gifread pascal, ax       ;lit les octets
  98.   ret
  99. Endp
  100.  
  101. GetPhysByte proc pascal
  102. ;lit un octet dans le buffer
  103.   push bx                       ;bx préservé pour l'appelant
  104.   cmp w restbyte,0              ;plus de données dans le buffer ?
  105.   ja @yadurab
  106.   pusha                         ;remplit à nouveau le buffer 
  107.   call fillbuff
  108.   popa
  109.   mov w buffInd,0               ;réinitialise le pointeur 
  110. @yadurab:                       ;il y a des données dans le buffer
  111.   mov bx,w buffInd              ;charge le pointeur
  112.   mov al,b buff[bx]             ;lit un octet
  113.   inc w buffInd                 ;déplace le pointeur 
  114.   pop bx                        ;c'est tout 
  115.   ret
  116. Endp
  117.  
  118. GetLogByte proc pascal
  119. ;lit un code dans le buffer en exploitant GetPhysByte
  120.   push si                       ;registre "si" préservé pour l'appelant
  121.   mov ax,w nbbit                ;lit la taille en bits du code
  122.   mov si,ax                     ;et la sauvegarde 
  123.   mov dx,w restbits             ;décale lbyte de 8-restbits vers la droite
  124.   mov cx,8
  125.   sub cx,dx                     ;calcule la différence
  126.   mov ax,w lByte
  127.   shr ax,cl                     ;et lance le décalage 
  128.   mov w act_code,ax             ;sauve le code 
  129.   sub si,dx                     ;restbits déjà lus -> soustraire
  130.  @nextbyte:
  131.   call getphysbyte              ;lit un nouvel octet
  132.   xor ah,ah
  133.   mov w lByte,ax                ;le met en lByte pour le prochain code
  134.   dec w restbyte                ;octet traité
  135.  
  136.   mov bx,1                      ;masque les bits restants dans l'octet
  137.   mov cx,si                     ;fixe le nombre de bits
  138.   shl bx,cl                     ;décale 1 du nombre de bits
  139.   dec bx                        ;et décrémente
  140.   and ax,bx                     ;masque le code 
  141.  
  142.   mov cx,dx                     ;effectue le décalage recherché
  143.   shl ax,cl                     ;de restbits vers la gauche 
  144.   add w act_code,ax             ;ajoute le résultat
  145.  
  146.   sbb dx,w nbbit                ;diminue le nombre restbits 
  147.   add dx,8                      ;de ce qui dépasse 8 bits
  148.   jns @positif
  149.   add dx,8
  150. @positif:
  151.   sub si,8                      ;jusqu'à 8 bits cherchés -> soustraire
  152.   jle @fini                     ;<= 0 -> tout est fini
  153.   add dx,w nbbit         ;sinon augmente restbits du nombre de bits manquants
  154.   sub dx,8
  155.   jmp @nextbyte                 ;et on continue
  156. @fini:
  157.   mov w restbits,dx   ;sauve le nombre de bits restants pour le prochain appel
  158.   mov ax,w act_code   ;et charge ax
  159.   pop si
  160.   ret
  161. Endp
  162.  
  163. ReadGif proc pascal
  164. ;lit en vscreen un fichier Gif appelé gifname,
  165. ;en cas de dépassement, stockage en mémoire d'écran
  166.   push ds                       ;sauvegarde ds
  167.   call GifOpen                  ;ouvre le fichier
  168.   jnc ok                        ;erreur ?
  169.   mov numerr,1                  ;la signaler et conclure
  170.   pop ds
  171.   ret
  172.  
  173. ok:
  174.   call gifseek pascal, 0,13d    ;saute les 13 premiers octets
  175.   push 768d                     ;lit les 768 octets de la palette
  176.   call gifread
  177.   call shiftpal                 ;et l'enregistre avec conversion
  178.   call gifread pascal,1         ;passe un octet
  179.  
  180. @extloop:                       ;laisse tomber les blocs d'extension
  181.   cmp w buff[0],21h              ;encore un bloc d'extension ? ?
  182.   jne @noext                    ;non, on continue
  183.     call gifread pascal,2       ;les deux premiers octets...
  184.     mov al,b buff[1]             ;...donnent la longueur du bloc...
  185.     inc al                      ;...si on ajoute 1 
  186.     xor ah,ah
  187.     call gifread pascal, ax     ;on passe par dessus
  188.   jmp @extloop
  189.  
  190. @noext:
  191.   call gifread pascal, 10d      ;lit le reste de l'IDB
  192.   test b buff[8],128             ;une palette locale  ?
  193.   je @noloc                     ;non on poursuit 
  194.     push 768                    ;lit la palette 
  195.     call gifread
  196.     call shiftpal               ;et la convertit
  197.  
  198. @noloc:
  199.   les di,dword ptr vscreen      ;charge l'adresse de destination
  200.  
  201.   mov w lbyte,0                 ;dernier code lu 0
  202.   mov w free,258                ;première entrée libre 258
  203.   mov w nbbit,9                 ;nb de bits d'un code = 9 
  204.   mov w max,511                 ;donc maximum d'entrées = 511
  205.   mov w stackp,0                ;pointeur sur début
  206.   mov w restbits,0              ;pas de bits restants
  207.   mov w restbyte,0              ;rien à chercher
  208. @mainloop:                      ;boucle pour chaque code
  209.   call getlogByte               ;lit un code
  210.   cmp ax,eof                    ;signature fin de fichier ?
  211.   jne @no_abandon
  212.   jmp @abandon                  ;oui, abandonne
  213. @no_abandon:
  214.   cmp ax,clr                    ;code clr  ?
  215.   jne @no_clear
  216.   jmp @clear                    ;oui efface l'alphabet
  217. @no_clear:
  218.   mov w readbyt,ax              ;sauve le code actuel
  219.   cmp ax,w free                 ;est-il déjà dans l'alphabet ? (<free)
  220.   jb @code_in_ab                ;oui, passe au traitement 
  221.   mov ax,w old_code             ;non, donc cas spécial, transmettre 
  222.   mov w act_code,ax             ;au traitement la dernière chaîne
  223.   mov bx,w stackp
  224.   mov cx,w casspecial    ;et accrocher le premier caractère (toujours concret)
  225.   mov w abstack[bx],cx          ;gère la pile
  226.   inc w stackp                  ;en conséquence
  227. @code_in_ab:                    ;code disponible dans l'alphabet :
  228.   cmp ax,clr                    ;< code clr ?
  229.   jb @concret                   ;oui, caractère concret
  230. @fillstack_loop:                ;sinon passe au décodage
  231.   mov bx,w act_code             ;le code est un pointeur dans l'alphabet
  232.   shl bx,1                      ;Word Array (!)
  233.   push bx
  234.   mov ax,w ab_suffx[bx]         ;cherche le suffixe, qui est concret
  235.   mov bx,w stackp               ;le place sur la pile
  236.   shl bx,1                      ;considérée comme Word Array
  237.   mov w abstack[bx],ax
  238.   inc w stackp
  239.   pop bx
  240.   mov ax,w ab_prfx[bx]          ;cherche le préfixe
  241.   mov w act_code,ax             ;le prend comme code courant
  242.   cmp ax,clr;> code clr 
  243.   ja @fillstack_loop            ;poursuit le décodage
  244. @concret:                       ;plus que des caractères concrets sur la pile
  245.   mov bx,w stackp               ;empile le dernier code
  246.   shl bx,1                      ;comme Word Array
  247.   mov w abstack[bx],ax
  248.   mov w casspecial,ax           ;en prend note aussi pour le cas spécial 
  249.   inc w stackp                  ;fait progresser le pointeur
  250.   mov bx,w stackp               ;prépare la lecture de la pile
  251.   dec bx                        ;décrémente le pointeur
  252.   shl bx,1                      ;sur Word Array 
  253. @readstack_loop:                ;traite la pile
  254.   mov ax,w abstack[bx]          ;prend un caractère
  255.   stosb                         ;et l'écrit dans la mémoire de  destination
  256.  
  257.   cmp di,0                      ;dépasse-t-on le segment ?
  258.   jne @noovl1
  259.   call p13_2_modex pascal,vram_pos,16384d
  260.   add vram_pos,16384d           ;exploite la mémoire d'écran
  261.   les di,dword ptr vscreen      ;nouvelle position en mémoire VGA
  262.  
  263. @noovl1:
  264.   dec bx                        ;pointeur de pile sur l'élément suivant
  265.   dec bx
  266.   jns @readstack_loop           ;fini ? non on poursuit
  267.   mov w stackp,0                ;réinitialise le pointeur de pile
  268.   mov bx,w free                 ;met à jour l'alphabet
  269.   shl bx,1                      ;à la position "free" 
  270.   mov ax,w old_code             ;écrit le dernier code dans préfixe
  271.   mov w ab_prfx[bx],ax
  272.   mov ax,w act_code             ;et le code courant dans suffixe
  273.   mov w ab_suffx[bx],ax
  274.   mov ax,w readbyt              ;le code  lu est le plus récent
  275.   mov w old_code,ax
  276.   inc w free           ;met à jour la dernière position libre dans l'alphabet 
  277.   mov ax,w free
  278.   cmp ax,w max                  ;déjà saturé ??
  279.   ja @no_mainloop
  280.   jmp @mainloop                 ;non, on continue
  281. @no_mainloop:
  282.   cmp b nbbit,12                ;nombre de bits déjà égal à 12 ?
  283.   jb @no_mainloop2
  284.   jmp @mainloop                 ;oui, alors on recommence simplement
  285. @no_mainloop2:
  286.   inc w nbbit                   ;sinon on l'augmente
  287.   mov cl,b nbbit                ;nouveau maximum d'entrées
  288.   mov ax,1                      ;1 décalé de nbbit vers la gauche
  289.   shl ax,cl
  290.   dec ax                        ;puis décrémenté
  291.   mov w max,ax                  ;enregistre le maximum 
  292.   jmp @mainloop                 ;revient à la boucle principale
  293. @clear:                         ;réinitialise l'alphabet:
  294.   mov w nbbit,9                 ;nbbit reprend la valeur de départ
  295.   mov w max,511                 ;le maximum d'entrées est 511
  296.   mov w free,258                ;première place libre = 258
  297.   call getlogbyte               ;lit le code suivant
  298.   mov w casspecial,ax           ;le note pour le cas spécial
  299.   mov w old_code,ax             ;et comme ancien code
  300.   stosb                         ;passe directement en mémoire car concret
  301.  
  302.   cmp di,0                      ;dépassement de segment ?
  303.   jne @noovl2
  304.   call p13_2_modex pascal,vram_pos,16384d
  305.   add vram_pos,16384d           ;stockage dans la mémoire d'écran
  306.   les di,dword ptr vscreen      ;avance le pointeur en mémoire VGA
  307.  
  308. @noovl2:
  309.   jmp @mainloop                 ;retour à la boucle principale
  310. @abandon:                       ;abandon par code Eof
  311.   call gifclose                 ;ferme le fichier
  312.   mov rest,di                   ;mémorise le nombre de codes restant à copier
  313.   pop ds                        ;et clôture
  314.   ret
  315. Endp
  316.  
  317. code ends
  318. end
  319.